I thought an issue existed for something like this already, but I couldn't find it...apologies if it's a duplicate.
julia> signature = :(f(x))
:(f(x))
# works fine without body
julia> quote
function $signature
end
end
quote
#= REPL[3]:2 =#
function f(x) end
end
# adding a body causes a syntax error
julia> quote
function $signature
1
end
end
ERROR: syntax: expected "end" in definition of function "($ signature)"
Luckily, there's an easy workaround:
julia> quote
$signature = begin
return 1
end
end
quote
#= REPL[4]:2 =#
f(x) = begin
#= REPL[4]:3 =#
return 1
end
en
julia> versioninfo()
Julia Version 0.7.0-DEV.2826
Commit 66b2090 (2017-12-11 19:50 UTC)
Platform Info:
OS: macOS (x86_64-apple-darwin16.7.0)
CPU: Intel(R) Core(TM) i5-4288U CPU @ 2.60GHz
WORD_SIZE: 64
BLAS: libopenblas (USE64BITINT DYNAMIC_ARCH NO_AFFINITY Haswell)
LAPACK: libopenblas64_
LIBM: libopenlibm
LLVM: libLLVM-3.9.1 (ORCJIT, haswell)
Environment:
Even with interpolation, you need to write well-formed code for the parser, with $ used as a placeholder _value_. (if you eval the first, you'll notice that it still fails, since the interpolated value must be a function name).
This came up again on discourse and I think it should still be an issue. The workaround given by @jrevels does in fact work on Julia 1.2 and later (I haven't tried older versions):
julia> foosig = :( foo(x) )
:(foo(x))
julia> ( $foosig = 2*x ) )
foo (generic function with 1 method)
juila> foo(3)
6
I also fail to see what is wrong with the construction :( function $foosig 2*x end). If you dump a function ... end expression, the first element of args is a :call expression, which is exactly what foosig is.
I don't really see why this can't work. After all the AST for f(x) is a proper subtree of the AST for function f(x) end:
julia> Meta.@dump function f(x) end
Expr
head: Symbol function
args: Array{Any}((2,))
1: Expr
head: Symbol call
args: Array{Any}((2,))
1: Symbol f
2: Symbol x
2: Expr
head: Symbol block
args: Array{Any}((1,))
1: LineNumberNode
line: Int64 1
file: Symbol REPL[11]
So why is it not possible for function $(:(f(x))) end to splice the one AST into the other?
In this case:
function $sig
expr
end
if sig ends up being a symbol then we shouldn't have parsed expr in the first place. We can give an error later, but strictly speaking the parser doesn't know which form it's supposed to parse. If there's no expr then it's fully ambiguous, and we have to arbitrarily pick something.