Julia: Interpolation of signature into `function...end` Expr causes syntax error if there is a function body

Created on 14 Dec 2017  Â·  4Comments  Â·  Source: JuliaLang/julia

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:

All 4 comments

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.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

musm picture musm  Â·  3Comments

StefanKarpinski picture StefanKarpinski  Â·  3Comments

omus picture omus  Â·  3Comments

sbromberger picture sbromberger  Â·  3Comments

ararslan picture ararslan  Â·  3Comments