JuliaGizmos / Observables.jl

observable refs
Other
105 stars 32 forks source link

0.4: map function doesn't support union types #76

Open twavv opened 3 years ago

twavv commented 3 years ago

https://github.com/JuliaGizmos/Observables.jl/blob/0f94e69cabddd87fcf057fb95ed5dc64be9661de/src/Observables.jl#L477

For context, I have code that returns different things based on the state of observable:

app = Canvas()
hbox(app, map(app) do img_matrix
        if img_matrix === nothing
            return html"<b>Draw something!</b>"
        end
        heatmap_digit(img_matrix; size=(300, 300))
    end
)

This causes issues™:

MethodError: Cannot `convert` an object of type Plots.Plot{Plots.GRBackend} to an object of type HTML{String}
Closest candidates are:
  convert(::Type{T}, ::T) where T at essentials.jl:171
  HTML{String}(::Any) where T at docs/utils.jl:23

I think it's the line referenced above that creates an Observable{T} where T is the type of the return value of the mapper function the first time it's executed.

CC @rajraomichigan

timholy commented 3 years ago

You can create an observable like this: Observable{Union{TypeA, TypeB}}(args...). Does that fix it?

twavv commented 3 years ago

I think it does, but definitely a far less convenient syntax and definitely a gotcha that you can't just "use map".

Is there any way to infer the return type of a function and use that? (Instead of just the type of the functions return value from the initial evaluation)

timholy commented 3 years ago

definitely a far less convenient syntax

You can also use Observable{Any} instead of Observable. 5 more characters.

Is there any way to infer the return type of a function and use that?

Yes, that's possible too. Of course, it gives you something too wide if your code breaks inferrability, but Observable{Any} is not the worst thing that can happen to someone. Historically we tried to use inference only to handle the empty-container problem, so this would be a violation, but there are several in Base already. Want to put together a PR?

twavv commented 3 years ago

I can do a PR. I don't know how I'd go about it. Is there a de facto way of determining the return type of a function nowadays?

And by convenient syntax, I mean the map syntax. Correct me if I'm wrong but what you're suggesting would require creating a new observable and map!-ing into it.

timholy commented 3 years ago

Check out MappedArrays which seems to have wholeheartedly embraced your proposed strategy. (Just the simple stuff, don't worry about the fancy anonymous-function printing.)