Defining function from string with parse and eval failure in v0.6 master


#1

Hello,

The following seems like a bug, but maybe there is something I am missing about eval and parse that is causing the failure.
I define anonymous function and pass it as a parameter to another function. The code works when the anonymous function is defined directly as lambda, but fails when it is defined with parse and eval.

Contest of my file “test_func.jl”

function foo1()
    return (x,y)->(x==y)
end

function foo2()
   return eval(parse("(x,y) -> (x==y)"))
end

function foo3(f, x,y)    
    f(x,y)
end

# this works with function defined directly as lambda in foo1
f1=foo1()
foo3(f1,1,2)
foo3(foo1(),1,2)


# this works with foo2 returning a function defined with parse and eval
f2=foo2()
foo3(f2,1,2)

# this fails with the parse and eval defined function passed directly as parameter to another function
foo3(foo2(),1,2)

This is with master from build today.

               _
   _       _ _(_)_     |  A fresh approach to technical computing
  (_)     | (_) (_)    |  Documentation: http://docs.julialang.org
   _ _   _| |_  __ _   |  Type "?help" for help.
  | | | | | | |/ _` |  |
  | | |_| | | | (_| |  |  Version 0.6.0-pre.beta.180 (2017-04-16 23:46 UTC)
 _/ |\__'_|_|_|\__'_|  |  Commit 934e0e3 (0 days old master)
|__/                   |  x86_64-linux-gnu

julia> include("test_func.jl")
ERROR: LoadError: MethodError: no method matching (::##5#6)(::Int64, ::Int64)
The applicable method may be too new: running in world age 21669, while current world is 21670.
Closest candidates are:
  #5(::Any, ::Any) at none:1 (method too new to be called from this world context.)

#2

You’re experiencing https://docs.julialang.org/en/latest/manual/methods.html#Redefining-Methods-1 which is a breaking change in Julia v0.6. This change was made to avoid a long-standing issue in Julia in which newly-defined functions sometimes wouldn’t take effect: https://github.com/julialang/julia/issues/265 Julia v0.6 is stricter (which is annoying in your particular case) but also more correct (which is better in all cases).

It might be worth considering whether you really need to be defining a function with eval(). There may be an alternative that doesn’t require jumping through these hoops.


#3

On the other hand, I admit I was very surprised to see that

f2=foo2()
foo3(f2,1,2)

works, but

foo3(foo2(),1,2)

does not, even when the code is put inside a script or module.


#4

Ah, I see, the distinction between those two shows up only at global scope. Putting the calls to foo2() and foo3 inside a function results in

f2=foo2()
foo3(f2,1,2)

also failling, as expected.


#5

Thanks, got it to work with the double eval after reading the manual.

This came up with experimenting with runtime defined functions from strings.