Two Questions about Hash Defaults

I have a couple of questions about hashes. The first is fairly simple: is there a way to set a default so that when the value for a key is changed, the object it points to is default.dup instead of default? So that if I do something like this:

lists = Hash.new([])
lists[:a].push 1
lists[:b].push 2
# Then doing the following
p lists[:a]
# Gets me
=> [1]
# Instead of
=> [1, 2]

And 'lists' is '{:a => [1], :b => [2]}' instead of '{}' with a default of '[1, 2]'.

I know why it happens this way, but is it possible to get it to behave differently? So that instead of
  lists[key] = [] if lists[key].nil? # Assuming default is nil
  lists[key].push value
or
  lists[key] = lists[key].dup.push value # default is []
I can write simply
  lists[key].push value # default is []

The second question is about setting defaults from one hash based on another. This question is more along the lines of 'Does this code violate Ruby sensibilities?'

class Hash
  def add_defaults(default_hash)
    raise TypeError unless default_hash.kind_of? Hash
    default_hash.each { |k,v|
      self[k] = v unless self.has_key? k
    }
    self
  end
end

def some_function(str, options=Hash.new(nil))
  # Set the defaults
  defaults = {
    :preserve_breaks => true,
    :indent => 0,
    :columns => 79,
  }
  options.add_defaults defaults
end

some_function("asdf", { :preserve_breaks => false })

Hi,

I have a couple of questions about hashes. The first is fairly simple:
is there a way to set a default so that when the value for a key is
changed, the object it points to is default.dup instead of default?

list = Hash.new{}

The second question is about setting defaults from one hash based on
another. This question is more along the lines of 'Does this code
violate Ruby sensibilities?'

defaults = {
  :preserve_breaks => true,
  :indent => 0,
  :columns => 79,
}
list = Hash.new{|h,k|defaults[k]}

···

In message "Re: Two Questions about Hash Defaults" on Sat, 2 Apr 2005 10:28:12 +0900, Pete Elmore <pete@petta-tech.com> writes:

Con fecha 2/4/2005, "Pete Elmore" <pete@petta-tech.com> escribió:

I have a couple of questions about hashes. The first is fairly simple:
is there a way to set a default so that when the value for a key is
changed, the object it points to is default.dup instead of default? So
that if I do something like this:

lists = Hash.new()
lists[:a].push 1
lists[:b].push 2
# Then doing the following
p lists[:a]
# Gets me
=> [1]
# Instead of
=> [1, 2]

And 'lists' is '{:a => [1], :b => [2]}' instead of '{}' with a default
of '[1, 2]'.

I know why it happens this way, but is it possible to get it to behave
differently? So that instead of
lists[key] = if lists[key].nil? # Assuming default is nil
lists[key].push value
or
lists[key] = lists[key].dup.push value # default is
I can write simply
lists[key].push value # default is

The second question is about setting defaults from one hash based on
another. This question is more along the lines of 'Does this code
violate Ruby sensibilities?'

class Hash
def add_defaults(default_hash)
  raise TypeError unless default_hash.kind_of? Hash
  default_hash.each { |k,v|
    self[k] = v unless self.has_key? k
  }
  self
end
end

def some_function(str, options=Hash.new(nil))
# Set the defaults
defaults = {
  :preserve_breaks => true,
  :indent => 0,
  :columns => 79,
}
options.add_defaults defaults
end

some_function("asdf", { :preserve_breaks => false })

Looks like matz already provided you with a good answer,
but here's a different take since I am not sure if you
are indeed referring to default values as the language
defines them or 'just' default values for your application
logic:

def some_function(str, options = {})
  defaults = {:preserve => true, :indent => 0, :columns =>79}
  options = defaults.merge options
end

"Pete Elmore" <pete@petta-tech.com> schrieb im Newsbeitrag news:424DCDEA.5020603@petta-tech.com...

I have a couple of questions about hashes. The first is fairly simple: is there a way to set a default so that when the value for a key is changed, the object it points to is default.dup instead of default? So that if I do something like this:

lists = Hash.new()

You want this:

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

lists[:a].push 1
lists[:b].push 2
# Then doing the following
p lists[:a]
# Gets me
=> [1]
# Instead of
=> [1, 2]

And 'lists' is '{:a => [1], :b => [2]}' instead of '{}' with a default of '[1, 2]'.

I know why it happens this way, but is it possible to get it to behave differently? So that instead of
lists[key] = if lists[key].nil? # Assuming default is nil
lists[key].push value
or
lists[key] = lists[key].dup.push value # default is
I can write simply
lists[key].push value # default is

The second question is about setting defaults from one hash based on another. This question is more along the lines of 'Does this code violate Ruby sensibilities?'

class Hash
def add_defaults(default_hash)
raise TypeError unless default_hash.kind_of? Hash
default_hash.each { |k,v|
self[k] = v unless self.has_key? k
}
self
end

def some_function(str, options=Hash.new(nil))
# Set the defaults
defaults = {
:preserve_breaks => true,
:indent => 0,
:columns => 79,
}

options.add_defaults defaults

This should do:
options = defaults.update options

end

some_function("asdf", { :preserve_breaks => false })

Kind regards

    robert

Yukihiro Matsumoto wrote:

Hi,

Wow, Matz himself! :slight_smile:

list = Hash.new{}
defaults = {
  :preserve_breaks => true,
  :indent => 0,
  :columns => 79,
}
list = Hash.new{|h,k|defaults[k]}

This is interesting; thanks for the response!