Conversation
base/expr.jl
Outdated
| macroexpand(x::ANY) = ccall(:jl_macroexpand, Any, (Any,), x) | ||
|
|
||
| """ | ||
| @macroexpand |
There was a problem hiding this comment.
missing indent, and would have to be added to rst if this gets merged before #18588
There was a problem hiding this comment.
where do I have to add it to rst?
test/expr.jl
Outdated
| @test (@macroexpand @doc "" f() = @x) == Expr(:error, UndefVarError(Symbol("@x"))) | ||
| @test (@macroexpand @seven_dollar $bar) == 7 | ||
| x = 2 | ||
| @test (@macroexpand @seven_dollar 1+$x) == :(1 + 2) |
There was a problem hiding this comment.
Is this actually the correct behaviour? Shouldn't it throw an error?
There was a problem hiding this comment.
You are right!
macro macroexpand(code)
code_expanded = macroexpand(code)
Expr(:quote, code_expanded)
end
code_expanded looks good the problem is the eval call on Expr(:quote, code_expanded) which does $ interpolation.
There was a problem hiding this comment.
So would the solution be to search and quote the dollars expressions in code_expanded?
There was a problem hiding this comment.
I'm honestly not sure. This stuff always makes my head hurt.
There was a problem hiding this comment.
I think correct behaviour would be not to throw an error but return something like
1 + $(Expr(:$, :x))
There was a problem hiding this comment.
Yeah my head hurts, too.
There was a problem hiding this comment.
Maybe it would be better to print the result, rather than return it, i.e. do:
macro macroprint(code)
print(macroexpand(code))
end
After all, that's probably what you want in 99% of cases.
There was a problem hiding this comment.
👎 to print it.
macro macroexpand(code)
QuoteNode(macroexpand(code))
endThere was a problem hiding this comment.
Is eval(QuoteNode(ex)) == ex for all expressions ex?
|
LGTM |
test/expr.jl
Outdated
| @@ -0,0 +1,18 @@ | |||
|
|
|||
There was a problem hiding this comment.
Why is this in a new file? This can probably go to parse or replutil or reflection.
| """ | ||
| @macroexpand | ||
|
|
||
| Return equivalent expression with all macros removed (expanded). |
There was a problem hiding this comment.
It should be documented that the expansion happens in the module where the @macroexpand macro is expanded (i.e. the same module if the expression is used directly) and not the current module when the returned code runs (which is the module if you call macroexpand) The difference is demonstrated below
julia> module M
macro macroexpand(code)
QuoteNode(macroexpand(code))
end
macro m()
1
end
function f()
(@macroexpand(@m), macroexpand(:(@m)))
end
end
M
julia> macro m()
2
end
@m (macro with 1 method)
julia> M.f()
(1,2)This makes no difference when used in the REPL and as I said the current @macroexpand might be slightly better but this should still be documented.
There was a problem hiding this comment.
Can you give a usecase this would actually make a difference? And why is @macroexpand potentially better for interactive use?
There was a problem hiding this comment.
Can you give a usecase this would actually make a difference?
That's exactly what the code above is showing.
And why is
@macroexpandpotentially better for interactive use?
I said
This makes no difference when used in the REPL
|
LGTM other than the comments above. |
|
commit messages could also be a bit more descriptive |
|
The PR title and the first commit message looks OK (more detail is fine but it's not bad). I assume the fix up commits will be squashed when merged. |
|
So this needs a squash and then can be merged? Is that correct, @yuyichao? |
|
Also #18660 (review) |
base/expr.jl
Outdated
| julia> M.f() | ||
| (1,2) | ||
| ``` | ||
| With @macroexpand the expression expands where @macroexpand appears in the code (module M). |
There was a problem hiding this comment.
@macroexpand, macroexpand and M should be quoted. Otherwise 👍
yuyichao
left a comment
There was a problem hiding this comment.
LGTM. Will merge later after the CI finishes. Thx for the contribution.
|
Cool! |
| With macroexpand the expressions expands in the current module where the code was finally called. | ||
| Note that when calling macroexpand or @macroexpand directly from the REPL, both of these contexts coincide, hence there is no difference. | ||
| With `@macroexpand` the expression expands where `@macroexpand` appears in the code (module `M`). | ||
| With `macroexpand` the expressions expands in the current module where the code was finally called (REPL). |
There was a problem hiding this comment.
this isn't the repl if the function is run in a script, is it?
There was a problem hiding this comment.
Let me explain it differently. If you call macroexpand, the expansion takes place at runtime. If you call @macroexpand the expansion takes place at compile time (when @macroexpand is expanded to be more precise.). So the context of @macroexpand is where it appears in the code, while the context of macroexpand is the current environment. So if you run M.f() from a script, the answer will be
(1, whatever @m() currently means in your script)
Does this answer the question?
There was a problem hiding this comment.
That makes sense. I'm referring to the "where the code was finally called (REPL)." here. I don't see why "(REPL)" is accurate.
There was a problem hiding this comment.
But in the example it is the REPL?
There was a problem hiding this comment.
You're making a general statement here "with macroexpand the expression expands` ... followed by a very not-general parenthetical that doesn't serve much purpose
There was a problem hiding this comment.
The julia> in the example implies that it runs in the REPL, doesn't it? And the "(module M)" in the sentence before also makes sense only in context of the example. So I'd say either leave as is or rephrase as "(module M in the example)" and "(REPL in the example)" (which I could well do in #18784).
There was a problem hiding this comment.
@martinholters I am happy with either formulation, so rephrase it as you see fit.
There was a problem hiding this comment.
a few words saying "in the example" sounds like a good clarification, thanks
Fix #18240