Project

General

Profile

Actions

Feature #6641

open

Hash.auto constructor

Added by trans (Thomas Sawyer) about 10 years ago. Updated over 4 years ago.

Status:
Open
Priority:
Normal
Target version:
-
[ruby-core:45822]

Description

=begin
It is not uncommon to need a Hash following the pattern:

Hash.new{ |h,k| h[k]={} }

Another common example:

Hash.new{ |h,k| h[k]=[] }

This is common enough that it would very nice if we could have a more concise form, e.g.

Hash.auto{ {} }

Or for the second example:

Hash.auto{ [] }

Pure Ruby implementation is pretty simple:

def Hash.auto
Hash.new{ |h,k| h[k] = yield }
end

I think it would be nice to have in Core.

This is secondary, but it just occurred to me. Could there even be a literal notation for the above? Something like:

{}([])

?
=end

Updated by Eregon (Benoit Daloze) about 10 years ago

trans (Thomas Sawyer) wrote:

It is not uncommon to need a Hash following the pattern:

Hash.new{ |h,k| h[k]=[] }

This is common enough that it would very nice if we could have a more concise form, e.g.

Hash.auto{ [] }

I agree, this is a pattern I see quite often and the Hash.new { |h,k| h[k] = ... } form is not the most natural or expressive in my opinion.
But at the same time, this is clearly a specialization of Hash.new with a block, which loses some flexibility (you can not use the key for example). I'm curious what others think of it.

Updated by rosenfeld (Rodrigo Rosenfeld Rosas) about 10 years ago

Maybe something like Hash.with_default{[]}. "with_default" could be both a class and an instance method so that you could have something like {a: 1, b: 2}.with_default(0).merge... It would always return the hash itself...

Groovy has something like this (not quite the same behavior). In Groovy you can define default values as [:].withDefault{0}. You can optionally use the block argument as the key.

So I guess it would be great if Ruby with_default supported all those syntax below:

Hash.with_default(0)
Hash.with_default{Time.now}
Hash.with_default{|k| k.to_sym}
{}.with_default(0)
{}.with_default{Time.now}
{}.with_default{|k| k.to_sym}

Updated by jwille (Jens Wille) about 10 years ago

Eregon (Benoit Daloze) [2012-06-25 12:33]:

But at the same time, this is clearly a specialization of
Hash.new with a block, which loses some flexibility (you can not
use the key for example).
why not? you can yield the key to the block.

I'm curious what others think of it.
i like it and i use it occasionally:

http://blackwinter.github.com/ruby-nuggets/Nuggets/Hash/NestMixin.html
https://github.com/blackwinter/ruby-nuggets/blob/master/lib/nuggets/hash/nest_mixin.rb
https://github.com/blackwinter/ruby-nuggets/blob/master/spec/nuggets/hash/nest_spec.rb

Updated by nobu (Nobuyoshi Nakada) about 10 years ago

-1.
I don't like the destructive default proc, which sets new keys automatically.

Updated by kosaki (Motohiro KOSAKI) about 10 years ago

Hash.with_default(0)
Hash.with_default{Time.now}
Hash.with_default{|k| k.to_sym}
{}.with_default(0)
{}.with_default{Time.now}
{}.with_default{|k| k.to_sym}

I like with_default than auto. It describe the behavior more preciously.
auto is too vague to me.

Updated by yhara (Yutaka HARA) almost 10 years ago

  • Target version changed from 2.0.0 to 2.6

Updated by phluid61 (Matthew Kerwin) over 9 years ago

I agree with nobu-shi, if I were to encounter Hash::with_default &block I would assume it was the equivalent of:

Hash.new{ |h,k| yield }

rather than:

Hash.new{ |h,k| h[k] = yield }

Perhaps there could be ::with_default and ::with_default!

Updated by ko1 (Koichi Sasada) over 9 years ago

  • Assignee set to matz (Yukihiro Matsumoto)
Actions #9

Updated by naruse (Yui NARUSE) over 4 years ago

  • Target version deleted (2.6)
Actions

Also available in: Atom PDF