Lift and @Lift generically

I have some routines that I used for calculations and simulation. Occasionally I want to use those same routines in a Makie GUI using observable Nodes and lift/@lift.

In the past I have two versions of the plotting function, one that plot’s without observables and one that uses @lifts, etc. for the calculations so that sliders and things work correctly. When I try to do the plot function generically and feed in none Observables variables to the observable plotting function and call a lift functions, it usually barks errors. Why doesn’t lift know just to pass through if there are no observables in the call? Then I can just have one plotting function that is observable aware but still work with non-observables.

What am I doing wrong?

julia> lift(x->(x+1),4)
ERROR: MethodError: no method matching lift(::var"#15#16", ::Int64)
Closest candidates are:
  lift(::Any, ::Observables.AbstractObservable, ::Any...; kw...) at C:\Users\user\.julia\packages\Makie\gQOQF\src\interaction\nodes.jl:9
  lift(::Any, ::Type{T}, ::Observables.AbstractObservable, ::Any...) where T at C:\Users\user\.julia\packages\Makie\gQOQF\src\interaction\nodes.jl:20
Stacktrace:
 [1] top-level scope
   @ REPL[102]:1

julia> lift(x->(x+1),Node(4))
Observable{Int64} with 0 listeners. Value:
5
1 Like

Also, why can’t the typical operators be overloaded so I don’t even need lift?

julia> h=Node(4.0)
Observable{Float64} with 0 listeners. Value:
4.0

julia> h+5
ERROR: MethodError: no method matching +(::Observable{Float64}, ::Int64)

Could you share a minimal working example? (something that can be copy and pasted and works?)
What kind of routines are you trying to reuse? Could you do that one of your functions receives a non-observable thing, wraps it in a node and then continues on to the rest?

You would keep only the “observables” version of most of your functions and sounds like they would work also for the static plots, no?

I ended up making some helper functions.
One of my processing functions wraps the named tuple as an observable if called with “lift” or “@lift”, then that gets passed to the plotting function. So I need a helper function to get the named tuple components out. Then I also make a “mylift” function which only calls lift on an observable.

function getNode(sym,s)

    if isa(s,Observable)

        lift(a->getindex(a,sym),s)

    else

        getindex(s,sym)

    end

end

function mylift(f,ob, rest...)

    if isa(s,Observable)

        lift(f,ob, rest...)

    else

        # mylift becomes pass-through if not an observable

        f(ob, rest...)

    end

end