-
-
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
Hash#put and Hash#replace #8660
Comments
@straight-shoota Mind if I take a stab at this (if the feature is finalized) and is there any ETA on this feature. |
I'd wait for some more approval, maybe there'll be suggestions to change the proposed API. |
I'm fine with this change. |
I am not convinced
But the current semantics of
That sounds to me more like an explicit replacement (if there is something to replace, do it). Finally, the use case in the OC seems more like a vivification (Ref: #4376 (comment)) Or it can be coded in a way that there is no double mention of the key per initialize & append:
|
Yeah, maybe the names are not ideal. But the current semantics for Agreed, the example for what currently works could also be written more efficiently, I've added your suggestion to the OC. |
I don't understand this snippet in the original comment: # with #put:
hash.put(key, value) { |array| array << value } That doesn't compile in my head, I think |
@asterite Ooops, sry I forgot the brackets, it's supposed to be The documentation for def put(key : K, value : V)
return_value = fetch(key) { yield }
self[key] = value
return_value
end I think my main issue with the method is the mixture of concerns does not fit with the name. |
I'd like something like the below, but obviously only looking up the entry once, to be the building block for def lookup(key : K, & : V?, Bool -> V | Hash::Delete)
if exists?(key)
new_value = yield self[key], true
else
new_value = yield nil, false
end
if new_value.is_a? Delete
delete(key)
else
self[key] = new_value
end
end This method is basically a sanitized, public, interface to performing an arbitrary option on the Everything else can be composed efficiently on top of this primitive: def [](key)
lookup(key) do |value|
return value
end
end
def []=(key, value)
lookup(key) { value }
end
def exists?(key)
lookup(key) do |val, present|
return present
end
end
def delete(key)
lookup(key) { Hash.delete }
end
def put(key, value)
lookup(key) do |old_value, present|
if present
return_value = old_value
else
return_value = yield
end
value
end
return_value
end This would allow |
I can agree to put's semantics being a bit odd. But either it has to go completly or keep its alias for |
|
As a recent user of the language, I was looking for a method that behaves similar to |
We agree that the initial suggestions form the OP are not good: the semantics of I still think we're missing some additional behaviour for specific insertion conditions. As a very generic example, |
|
I think |
#8116 added
Hash#put
which sets the value, returns either the previous value (if exists) or the block result (invoked with the key).This behaviour seems counter-intuitive as expressed in #8116 (comment) f.
I'm proposing:
#put
to#replace
keeping the same semantics.#replace
without a block which returnsnil
if the value doesn't exit.#put
method which sets the value only if it does not exits.Maybe there could also be an overload to
#put
which accepts a block. The block would be called when the value exists and receive the value. This would be an efficient method for the use case when a value needs to be either added or the existing value updated. For example when a hash collects multiple values per key in an array:The text was updated successfully, but these errors were encountered: