Perl is pretty nice about default values:
: jmglov@laurana; perl -e '@foo; printf "%d\n", $foo[123]' 0 : jmglov@laurana; perl -e '%foo; printf "%d\n", $foo{bar}' 0
Ruby can do the same, at least for hashes:
>> foo = Hash.new(0) => {} >> foo[:bar] => 0
But the same seemingly does not work for arrays:
>> foo = Array.new(0) => [] >> foo[123] => nil >> foo[124] = 0 => 0 >> foo[456] = 0 => 0 >> foo[455,456] => [nil, 0]
Is it possible to supply a default value for arrays, so when they are auto-extended, they're filled with 0 instead of nil?
Of course I can work around this, but at a cost to expressiveness:
>> foo[457,458] = 890, 321 => [890, 321] >> foo[456] += 789 NoMethodError: You have a nil object when you didn't expect it! You might have expected an instance of Array. The error occurred while evaluating nil.+ >> foo.inject(0) {|sum, i| sum += (i || 0) } => 1211 >> foo.inject(:+) NoMethodError: You have a nil object when you didn't expect it! You might have expected an instance of Array. The error occurred while evaluating nil.+
Update 1: One of my colleagues pointed out that I can use #compact
to solve the #inject
issue, and #to_i
to solve the standard element-at-index issue:
>> foo.include? nil => true >> foo.compact.inject(:+) => 1211 >> foo[456,457] => [0, 890, 321] >> foo[455..457] => [nil, 0, 890] >> foo[455..457].map(&:to_i) => [0, 0, 890]
Update 2: Thanks to Andrew Grimm for a solution to the +=
issue:
>> foo = [] => [] >> def foo.[](i) >> fetch(i) {0} >> end => nil >> foo[4] => 0 >> foo => [] >> foo[4] += 123 => 123 >> foo => [nil, nil, nil, nil, 123]
Update 3: this is starting to look like whack-a-mole!
>> foo => [nil, nil, nil, nil, 123] >> foo[-2..-1] TypeError: can't convert Range into Integer
But we can deal with that:
>> def foo.[](index) >> if index.is_a? Range >> index.map {|i| self[i] } >> else ?> fetch(index) { 0 } # default to 0 if no element at index; will not cause auto-extension of array >> end >> end => nil >> foo => [nil, nil, nil, nil, 123] >> foo[-2..-1] => [nil, 123]
I now have to admit (sheepishly) that I'll subclass Array
to avoid cluttering my code:
class MyClass class ArrayWithDefault < Array def [](index) if index.is_a? Range index.map {|i| self[i] } else fetch(index) { 0 } # default to 0 if no element at index; will not cause auto-extension of array end end end end
Thanks for all the creative solutions. TIMTOWTDI indeed!
Using default values in initialization of array For double or float , the default value is 0.0 , and the default value is null for string. Type[] arr = new Type[capacity]; For example, the following code creates a primitive integer array of size 5 . The array will be auto-initialized with a default value of 0 .
You can create an array by separating values by commas and enclosing your list with square brackets. In Ruby, arrays always keep their order unless you do something to change the order. They are zero-based, so the array index starts at 0.
Not auto extended, but initialized to the specified length with a default value:
>> Array.new(123, 0) => [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With