-
Notifications
You must be signed in to change notification settings - Fork 17
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support adding to named tuples? #65
Comments
You could do: julia> nt = (x = 1, y = 2)
(x = 1, y = 2)
julia> (;nt..., z= 3)
(x = 1, y = 2, z = 3) |
When we implemented
|
tl;dr: There is a way to do add/delete for map-like objects using lenses. Whether or not this is a good approach is hard to decide (for me).
I remember I said a similar thing when we discussed it before. But I just realized that Haskell's lens library actually supports it. The idea is to define a lens that returns a using Setfield
import Setfield: get, set
struct MaybeKeyLens{T} <: Lens
key::T
end
# get(obj, lens) :: Maybe{T}
get(obj, lens::MaybeKeyLens) =
haskey(obj, lens.key) ? Some(obj[lens.key]) : nothing
# set(obj, lens, ::Maybe{T})
set(obj, lens::MaybeKeyLens, ::Nothing) = delete(obj, lens.key)
set(obj, lens::MaybeKeyLens, val::Some) = setkey(obj, lens.key, something(val)) where For function delete(obj::Dict, key)
clone = copy(obj)
pop!(clone, key, nothing)
return clone
end
function setkey(obj::Dict, key, val)
clone = copy(obj)
clone[key] = val
return clone
end For using Setfield: PropertyLens
delete(obj::NamedTuple{names}, key) where names =
NamedTuple{Tuple(n for n in names if n !== key)}(obj)
setkey(obj::NamedTuple{names}, key, val) where names =
if key in names
set(obj, PropertyLens{key}(), val)
else
NamedTuple{(names..., key)}(obj..., val)
end Type stable versionYou obviously needs a generated function :) @generated _remove(::Val{xs}, ::Val{x}) where {xs, x} =
:($(Tuple(y for y in xs if y != x)))
delete(obj::NamedTuple{names}, key) where names =
NamedTuple{_remove(Val(names), Val(key))}(obj) Examples: julia> get((a=1, b=2), MaybeKeyLens(:a))
Some(1)
julia> get((a=1, b=2), MaybeKeyLens(:c))
julia> set((a=1, b=2), MaybeKeyLens(:a), Some(100))
(a = 100, b = 2)
julia> set((a=1, b=2), MaybeKeyLens(:a), nothing)
(b = 2,) If we go to this route, I think this point
is more or less irrelevant as we wouldn't be touching the normal But the third point
is still true. On one hand,
|
Thanks for the thorough analysis! I think from a purely mathematical perspective your suggestion is very natural. Using Also I think there are some differences between julia and Haskell that make this lens more attractive in the latter:
|
Yeah, it makes sense. I really like that Setfield is very minimalistic but yet super powerful and also extensible. Adding this feature could ruin it. I agree that "wait for a practical example" for this lens is the right approach. (I'm supposing that the original request for "adding a field to a NamedTuple" is not a big enough motivation as there is a native syntax and
It's a bit tangential and maybe nit-picky, but I think support for the higher-kinded types has a bigger impact here. Run-time type assertion is not so crazy and maybe we would have static type checker in the future (at least JavaScript and Python pulled it off). But inability to express something like |
Yes. In the initial version of
Probably yes. I think the problems start at a less sophisticated level already. In Julia a function does not have a precise domain and range. E.g. we only have |
Ah yes, |
Would it make sense for this package to support adding to named tuples? E.g.
To me at least it'd be useful functionality that I don't think exists elsewhere.
The text was updated successfully, but these errors were encountered: