ruby-core@ruby-lang.org archive (unofficial mirror)
 help / color / mirror / Atom feed
* [ruby-core:119632] [Ruby master Feature#20818] Allow passing a block to Hash#store (to update current value)
@ 2024-10-28 13:54 furunkel (Julian Aron Prenner) via ruby-core
  2024-11-07 10:25 ` [ruby-core:119799] " mame (Yusuke Endoh) via ruby-core
  2024-12-12 16:51 ` [ruby-core:120219] " AMomchilov (Alexander Momchilov) via ruby-core
  0 siblings, 2 replies; 3+ messages in thread
From: furunkel (Julian Aron Prenner) via ruby-core @ 2024-10-28 13:54 UTC (permalink / raw)
  To: ruby-core; +Cc: furunkel (Julian Aron Prenner)

Issue #20818 has been reported by furunkel (Julian Aron Prenner).

----------------------------------------
Feature #20818: Allow passing a block to Hash#store (to update current value)
https://bugs.ruby-lang.org/issues/20818

* Author: furunkel (Julian Aron Prenner)
* Status: Open
----------------------------------------
I would like to propose a block form for `Hash#store`. In addition to passing a value, it should also be allowed to pass a block.
If passed a block instead of a value, the block is called with the current value or, if unset, the hash's default value; the block's return value will be the value that is stored.
This is similar to e.g., `computeIfPresent`/`computeIfAbsent` in Java (I think).

I can think of several situations where this would be useful, in particular for caches and counters.
For instance:
```ruby
counts = {}
elements.each do |element|
  counts.store(element){ (_1 || 0) + element.weight}
end
```

or even more elegant with a default value:
```ruby
counts = {}
counts.default = 0
elements.each do |element|
  counts.store(element){ _1 + element.weight}
end
```

Moreover, using the block form we should be able to do operations such as  `h[k] ||= x`, `h[k] -= x`, `h[k] += x`, or more generally `h[k] = f(h[k])`, with a single "hashing round-trip".
 If I'm not mistaken, currently these involve two separate calls to `#[]` and `#[]=` (with two calls to `#hash`?).

Finally, this makes `#store` a proper dual of `#fetch` which, similarly, can be passed a block.

I have an experimental implementation of this (GitHub PR) at: https://github.com/ruby/ruby/pull/11956
 



-- 
https://bugs.ruby-lang.org/
 ______________________________________________
 ruby-core mailing list -- ruby-core@ml.ruby-lang.org
 To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
 ruby-core info -- https://ml.ruby-lang.org/mailman3/lists/ruby-core.ml.ruby-lang.org/

^ permalink raw reply	[flat|nested] 3+ messages in thread

* [ruby-core:119799] [Ruby master Feature#20818] Allow passing a block to Hash#store (to update current value)
  2024-10-28 13:54 [ruby-core:119632] [Ruby master Feature#20818] Allow passing a block to Hash#store (to update current value) furunkel (Julian Aron Prenner) via ruby-core
@ 2024-11-07 10:25 ` mame (Yusuke Endoh) via ruby-core
  2024-12-12 16:51 ` [ruby-core:120219] " AMomchilov (Alexander Momchilov) via ruby-core
  1 sibling, 0 replies; 3+ messages in thread
From: mame (Yusuke Endoh) via ruby-core @ 2024-11-07 10:25 UTC (permalink / raw)
  To: ruby-core; +Cc: mame (Yusuke Endoh)

Issue #20818 has been updated by mame (Yusuke Endoh).


Discussed at the dev meeting. @matz said "I don't like the style so much, but if the patch is safe and actually improves performance, I'm willing to consider it. I'd like you to show the benchmark."

I am not sure if it is safe to execute arbitrary Ruby code in the RHASH_UPDATE_ITER callback. For example, what will happen if we update the hash itself inside the block of Hash#store, like `h.store(:key){ h[:another_key] = 1 }`? Does the patch prohibit this? If it is allowed, we need to care the possibility that rehash may occur.

----------------------------------------
Feature #20818: Allow passing a block to Hash#store (to update current value)
https://bugs.ruby-lang.org/issues/20818#change-110484

* Author: furunkel (Julian Aron Prenner)
* Status: Open
----------------------------------------
I would like to propose a block form for `Hash#store`. In addition to passing a value, it should also be allowed to pass a block.
If passed a block instead of a value, the block is called with the current value or, if unset, the hash's default value; the block's return value will be the value that is stored.
This is similar to e.g., `computeIfPresent`/`computeIfAbsent` in Java (I think).

I can think of several situations where this would be useful, in particular for caches and counters.
For instance:
```ruby
counts = {}
elements.each do |element|
  counts.store(element){ (_1 || 0) + element.weight}
end
```

or even more elegant with a default value:
```ruby
counts = {}
counts.default = 0
elements.each do |element|
  counts.store(element){ _1 + element.weight}
end
```

Moreover, using the block form we should be able to do operations such as  `h[k] ||= x`, `h[k] -= x`, `h[k] += x`, or more generally `h[k] = f(h[k])`, with a single "hashing round-trip".
 If I'm not mistaken, currently these involve two separate calls to `#[]` and `#[]=` (with two calls to `#hash`?).

Finally, this makes `#store` a proper dual of `#fetch` which, similarly, can be passed a block.

I have an experimental implementation of this (GitHub PR) at: https://github.com/ruby/ruby/pull/11956
 



-- 
https://bugs.ruby-lang.org/
 ______________________________________________
 ruby-core mailing list -- ruby-core@ml.ruby-lang.org
 To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
 ruby-core info -- https://ml.ruby-lang.org/mailman3/lists/ruby-core.ml.ruby-lang.org/

^ permalink raw reply	[flat|nested] 3+ messages in thread

* [ruby-core:120219] [Ruby master Feature#20818] Allow passing a block to Hash#store (to update current value)
  2024-10-28 13:54 [ruby-core:119632] [Ruby master Feature#20818] Allow passing a block to Hash#store (to update current value) furunkel (Julian Aron Prenner) via ruby-core
  2024-11-07 10:25 ` [ruby-core:119799] " mame (Yusuke Endoh) via ruby-core
@ 2024-12-12 16:51 ` AMomchilov (Alexander Momchilov) via ruby-core
  1 sibling, 0 replies; 3+ messages in thread
From: AMomchilov (Alexander Momchilov) via ruby-core @ 2024-12-12 16:51 UTC (permalink / raw)
  To: ruby-core; +Cc: AMomchilov (Alexander Momchilov)

Issue #20818 has been updated by AMomchilov (Alexander Momchilov).


This is related to my `Hash#exchange_value` proposal, so I'll link that here. https://bugs.ruby-lang.org/issues/20300

I guess the difference is whether you already know the replacement you want to use instead, or if you'd like to compute it lazily when the key is already set.

----------------------------------------
Feature #20818: Allow passing a block to Hash#store (to update current value)
https://bugs.ruby-lang.org/issues/20818#change-110983

* Author: furunkel (Julian Aron Prenner)
* Status: Open
----------------------------------------
I would like to propose a block form for `Hash#store`. In addition to passing a value, it should also be allowed to pass a block.
If passed a block instead of a value, the block is called with the current value or, if unset, the hash's default value; the block's return value will be the value that is stored.
This is similar to e.g., `computeIfPresent`/`computeIfAbsent` in Java (I think).

I can think of several situations where this would be useful, in particular for caches and counters.
For instance:
```ruby
counts = {}
elements.each do |element|
  counts.store(element){ (_1 || 0) + element.weight}
end
```

or even more elegant with a default value:
```ruby
counts = {}
counts.default = 0
elements.each do |element|
  counts.store(element){ _1 + element.weight}
end
```

Moreover, using the block form we should be able to do operations such as  `h[k] ||= x`, `h[k] -= x`, `h[k] += x`, or more generally `h[k] = f(h[k])`, with a single "hashing round-trip".
 If I'm not mistaken, currently these involve two separate calls to `#[]` and `#[]=` (with two calls to `#hash`?).

Finally, this makes `#store` a proper dual of `#fetch` which, similarly, can be passed a block.

I have an experimental implementation of this (GitHub PR) at: https://github.com/ruby/ruby/pull/11956
 



-- 
https://bugs.ruby-lang.org/
 ______________________________________________
 ruby-core mailing list -- ruby-core@ml.ruby-lang.org
 To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
 ruby-core info -- https://ml.ruby-lang.org/mailman3/lists/ruby-core.ml.ruby-lang.org/

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2024-12-12 16:52 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-10-28 13:54 [ruby-core:119632] [Ruby master Feature#20818] Allow passing a block to Hash#store (to update current value) furunkel (Julian Aron Prenner) via ruby-core
2024-11-07 10:25 ` [ruby-core:119799] " mame (Yusuke Endoh) via ruby-core
2024-12-12 16:51 ` [ruby-core:120219] " AMomchilov (Alexander Momchilov) via ruby-core

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).