Hash#shift using default values
source link: https://medium.com/@farsi_mehdi/hash-shift-using-default-value-b0d7cb62ffa2
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
How the way you define your hash default value can generate side effects in your program?
Feb 24 ·3min read
The 3 main ways to declare a default value to a Hash
are:
- by using the
Hash.new('default value')
method - by using the
Hash#default=
method - by using the
Hash.new { |h, k| h[k] = 'default value' }
Each of these 3 methods produces a different behavior using the Hash#shift
method.
Hash#shift
The hash#shift
method removes and returns a pair key/value of a hash
Here, we can see that the initial hash
contains a pair foo: :bar
.
After the call to hash.shift
, the hash
is empty and the pair [:foo, :bar]
is returned and stored in the pair
variable.
Then if we call the hash.shift
method on an empty hash nil
is returned.
Now that we’re more familiar with the Hash#shift
method, let’s see how it behaves when the hash
defines a default value.
Hash#default=
Here, we define an empty hash
. Then we set the 'val'
default value for this hash
.
Finally, when we call the hash.shift
method we notice that our default value is returned as the hash
is empty.
Hash.new(default_value)
Here we define an empty hash
using the Hash.new
with an argument as default value.
When we call the hash.shift
method, we notice the exact same behavior as a hash
that sets default value using the Hash#default=
method.
Hash.new {}
Here we define an empty hash
using the Hash.new
with a block that defines the default value.
Then we call the hash.shift
method that returns the hash
default value.
But a second call to hash.shift
returns a pair with nil
as key and our default value as value.
Weird..
Not at all. Let’s detail what happens here in the following section.
blocks and Hash#shift
Let’s add few lines to our previous example to understand what’s happens step-by-step
Here, we display the content of our hash
after a call to hash.shift
and we notice that it contains a nil => 'val'
pair.
Then we call hash.shift
for the second time and logically this pair is returned.
So, why this pair is inserted in our hash
after the first call to hash.shift
?
The answer is simple: because the block passed to Hash.new
is executed each time that you code tries to access the default value of our hash
.
Indeed, the call to hash.shift
forces our hash to execute the block passed to Hash.new
as its return value is used as default value of hash
— when hash
is empty.
But the subtlety here is that k
in the |h, k|
block arguments is nil
.
So, the block is processed as following:
hash[nil] = ‘val’ hash#[]= 'val'
This is why the first call to hash.shift
return 'val'
and sets the pair { nil => 'val' }
in our hash
.
So a second call to hash.shift
logically returns [nil, 'val']
and not the default value as the hash
is not empty at this stage.
Conclusion
When using Hash#shift
or any methods that interact with the default value of the hash, be aware if you use a block as default value of the hash.
Indeed, any assignations within this block can generate side effects that can roughly alter the behavior of your app.
Voilà
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK