-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Merge named tuples #2634
Merge named tuples #2634
Conversation
Thanks @soveran for his smart implementation
This is useful for default options. You merge a named tuple with the default values for some options with the user provided values for some of them. I would prefer a By the way, this implementation does not work in cases where the two tuples have the same key (those are the ones where commutativity is broken) {a: 1, b: 2} + {b: 3, c: 4} # compile error. expected: {a: 1, b: 3, c: 4} I don't know how to implement this. |
identity(**self, **other) | ||
end | ||
|
||
private def identity(**options) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just calling NamedTuple.new
instead should work as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jhass I forgot that NamedTuple.new
works like that. I'm fixing it
I'm not sure about the default values usecase, normally you would def foo(*, a = 1, b = 2)
end |
693ecd2
to
232bf1c
Compare
@lbguilherme the main intention was to compose
As @jhass mention, you probably want to use the following snippet for default values def foo(*, a = 1, b = 2)
end
I prefer the
I know and that is expected. You can't define The reason that I was looking for a method like this is that I'm writing an ORM where the attributes are stored as a Here is an example of the code using this cool feature and why I want it. def save
@attributes = {name: "emancu", profession: "programmer"}
id = DB.persist @attributes
@attributes = {id: id} + @attributes
end |
But that creates a union of named tuples, which you won't be able to splat later. I think hashes are more suitable for this use case. |
Note that I'm not against merging named tuples, and I think it can even be done if keys repeat, I'm just not sure named tuples should be used in places where a Hash is more useful. |
@asterite You are right, maybe that is not the best code example. |
Here's an implementation that preserves the values on the other merged named tuple. Code: struct NamedTuple
def self.new(**options)
options
end
def merge(other : NamedTuple)
merge_implementation(other)
end
private def merge_implementation(other : U)
{% begin %}
NamedTuple.new(
{% for key in (T.keys + U.keys).uniq %}
{% if U.keys.includes?(key) %}
{{key}}: other[:{{key}}],
{% else %}
{{key}}: self[:{{key}}],
{% end %}
{% end %}
)
{% end %}
end
end
a = {x: 1, y: 2}
b = {z: 3}
c = a.merge(b)
p c
p typeof(c)
d = {x: 10}
e = a.merge(d)
p e
p typeof(e) |
@asterite do I need to update this PR with your suggested code or you are going to add it manually ? |
@emancu We still need to define what semantics we want for the method, if we decide to include it. What happens with duplicated keys? If we look at Hash, it keeps the last key, so for me NamedTuple should do the same. If you want to combine tuples maybe we can have |
#triage |
I guess we can close this PR now that #4688 was merged. |
@emancu Indeed. Gracias! :-) |
I don't think this should be closed just because #4688 was merged, see #4727 (issue comment) and #4688 (issue comment). |
Looks like #4727 and #4688 have been closed now FWIW. Thanks for doing this guys, I was about to request the same thing. See also https://groups.google.com/d/msg/crystal-lang/YnoO8GMovKQ/2ZWF3_IfDAAJ |
I think it is useful and also completes the interface with a method defined in the tuples specification.