2

When I try those code below:

function f(x)
    Meta.parse("x -> x " * x) |> eval
end

function g(x)
    findall(Base.invokelatest(f,x),[1,2,3]) |> println
end

g("<3")

Julia throws "The applicable method may be too new" error.

If I tried these code below:

function f(x)
    Meta.parse("x -> x " * x) |> eval
end

findall(f("<3"),[1,2,3]) |> println

Julia could give me corrected result: [1, 2]

How can I modify the first codes to use an String to generate function in other function, Thx!

Test in Julia 1.6.7

kaji331
  • 61
  • 4
  • Instead evaling strings (which is frowned upon), you can pass anonymous functions instead: `findall(<(3), [1,2,3])`. This is a better approach in general. – DNF Jan 09 '23 at 13:01
  • Fully agreed. However, for some reason recently many users on SO ask about parsing strings in Julia (as @DNF noted - this should be done normally). – Bogumił Kamiński Jan 09 '23 at 13:41

2 Answers2

3

Do

function g(x)
    h = f(x)
    findall(x -> Base.invokelatest(h, x) ,[1,2,3]) |> println
end

g("<3")

The difference in your code is that when you write:

Base.invokelatest(f, x)

you invoke f, but f is not redefined. What you want to do is invokelatest the function that is returned by f instead.

Bogumił Kamiński
  • 66,844
  • 3
  • 80
  • 107
  • Thanks very much for helping me understand the 'Base.invokelatest' – kaji331 Jan 11 '23 at 01:32
  • There's another point confused me. In my f(x), I parsed "x -> x". Why I have to add "x ->" befor "Base.invokelatest..." ? – kaji331 Jan 11 '23 at 02:07
  • Because `findall` takes a predicate as a first argument. In my solution I pass an anonymous function that can be compiled (i.e. is not dynamically defined) to `findall`. The dynamically defined function is only invoked in its body. This way compiler has a known function to dispatch to in `findall`. – Bogumił Kamiński Jan 11 '23 at 06:53
1

Use a macro instead of function:

macro f(expr)
    Meta.parse("x -> x " * expr)
end

Now you can just do:

julia> filter(@f("<3"), [1,2,3])
2-element Vector{Int64}:
 1
 2
Przemyslaw Szufel
  • 40,002
  • 3
  • 32
  • 62