I’m a happy user of both Chain.jl and Accessors.jl, but I find myself missing a few things from Clojure. I’m not sure if they exist, and I just don’t know about them, or if these are actual missing capabilities.
I think one motivating example is how easy it is in Clojure to extract a value from a nested data structure and pass it to a function. For example, you might have:
(some-> data
:foo
:bar
baz)
This is a bit like unpacking a Dict
in Julia and passing it to a function, like data[:foo][:bar] |> baz
, but there are some extra niceties that arise from how extensively and consistently Clojure uses nil
. First, the :foo
keyword works like a function in Clojure and is similar to x -> get(x, :foo, nothing)
in Julia. Second, some->
will short circuit and return nil
as soon an intermediate value is nil
. So, if we had a @chain_some
macro, if might expand to something like:
if isnothing(data)
nothing
else
foo_ = data[:foo]
if isnothing(foo_)
nothing
else
bar_ = foo_[:bar]
if isnothing(bar_)
nothing
else
baz(bar_)
end
end
end
So, combining those, I guess I wish I could write something like:
@chain_some data begin
get(_, :foo, nothing)
get(_, :bar, nothing)
baz
end
This has all been focused on Dict
, but in reality I have a mix of Dict
s, NamedTuple
s, and struct
s. My get
calls above would work for Dict
s and NamedTuple
s, but not for struct
s. This seems like something that Accessors.jl could provide a generalized solution to, and I see @maybe
in AccessorsExtra.jl, but that doesn’t seem to be quite what I want. I think I’m looking for something like @maybe
that could do @maybe_nested data.foo[:bar]
, and if any intermediate value is nothing
, it short circuits and evaluates to nothing
.
So, putting it all together again, perhaps something like:
@chain_some data begin
@maybe_nested _.foo[:bar]
baz
end
If you’ve made it this far, thanks for sticking with me. If you have suggestions for where this might already exist in the package ecosystem, or perhaps an alternative way of doing this, I’d love to hear about it! Thanks!