Function definition Expr that prints incorrectly but evals correctly

@MilesCranmer and I have a discussion over whether MacroTools.longdef is correct or not. For reference, longdef is meant to take a short-form function definition and turn it into long-form

julia> MacroTools.longdef(:(f(x) = 10))
:(function f(x)
      #= REPL[50]:1 =#
      10
  end)

But consider:

julia> long_form = longdef(:((a::Int; b=2) -> a + b))
:(function a::Int, #= REPL[44]:1 =#, b = 2
      #= REPL[44]:1 =#
      a + b
  end)

julia> eval(long_form)(1; b=28)   # long_form looks weird, but works out OK!
29

julia> dump(long_form)
Expr
  head: Symbol function
  args: Array{Any}((2,))
    1: Expr
      head: Symbol block
      args: Array{Any}((3,))
        1: Expr
          head: Symbol ::
          args: Array{Any}((2,))
            1: Symbol a
            2: Symbol Int
        2: LineNumberNode
          line: Int64 1
          file: Symbol REPL[44]
        3: Expr
          head: Symbol =
          args: Array{Any}((2,))
            1: Symbol b
            2: Int64 2
    2: Expr
      head: Symbol block
      args: Array{Any}((2,))
        1: LineNumberNode
          line: Int64 1
          file: Symbol REPL[44]
        2: Expr
          head: Symbol call
          args: Array{Any}((3,))
            1: Symbol +
            2: Symbol a
            3: Symbol b

long_form is correct as far as eval is concerned, but its printed representation is off. Should we take it as

  • long_form is purposefully accepted by eval, pretty-printing is just broken for this particular Expr
  • OR: “long_form isn’t meant to be valid julia code, eval accepts it accidentally.”
1 Like

The pretty printing seems broken to me, there is no reason it should insert a , after the inline comment block/LineNumberNode, thereby treating a comment as an argument. My guess is that the printing is a bit too naive here and doesn’t check whether the element in the list is actually an argument expression or not.

Of course, you could also just as well remove the LineNumberNode in your expansion.

1 Like