Reputation: 145
I am a newbie of Ruby and I don't quite understand the following code.
n = [1,2,3]
n.map!.select{|x| x+=1}
puts n.inspect
will give me
[nil, nil, nil]
I know that n.map! will give me an enumerator but I don't get it why calling select on it will make n becomes nil. I know that map! will modify the original object, I just don't understand how that's achieved.
Update:
I tried n.map!.select {|x| true}
, n is still [nil, nil, nil]
I appreciate your help! Thanks!
Upvotes: 1
Views: 81
Reputation: 4573
In the comments, it says:
It's to do with the in-place modification of map!
that's true. Let me make it clearer here:
In the definition of Array#map!
, it says:
map! {|item| block } → ary click to toggle source map! → Enumerator
Invokes the given block once for each element of self, replacing the element with the value returned by the block
So:
[58] pry(main)> a = [1,2,3]
=> [1, 2, 3]
[60] pry(main)> e = a.map!
=> #<Enumerator: ...>
[61] pry(main)> e.each {|n| n + 1}
=> [2, 3, 4]
[62] pry(main)> a
=> [2, 3, 4]
However:
[71] pry(main)> a = [1,2,3]
=> [1, 2, 3]
[72] pry(main)> e = a.map!
=> #<Enumerator: ...>
[73] pry(main)> e.next
=> 1
[74] pry(main)> a
=> [1, 2, 3]
[75] pry(main)> e.peek
=> 2
[76] pry(main)> a
=> [nil, 2, 3]
I think this due to Enumerator#each
call takes a block, and that would be the return value from example 1; but when Enumerator#next
is called (same goes to Enumerator.to_a
), it cannot evaluate the block, therefore, returning nil
.
Upvotes: 0
Reputation: 1681
It's because the select
method is used for selection. It returns the element that satisfies the condition you placed in your block. In your case, you didn't put any condition so it returned nil
e.g. You want to do something like this:
n = [1,2,3]
n.select { |num| num < 3 }
#=> This should return
#=> [1,2]
Upvotes: 4