0

Take a good look at the snippet below:

a = [1,2,3]
n = 2
puts a.find { |i| i == n }
=> 2

a = [1,2,3]
n = [2]
puts a.find { |i| i == n.shift }
=> nil

Tip: you can see a running version here http://repl.it/OL3

Now explain it. Why the second #find returns nil ?

7
  • to avoid the problem use path.dup.shift Commented Jan 27, 2014 at 13:33
  • @majioa That's completely nuts. Just use path[-1] or path.last. Commented Jan 27, 2014 at 13:36
  • @tadman probably asker wish to use #shift Commented Jan 27, 2014 at 13:37
  • The snippet is out of context. In the context shift does make sense. Commented Jan 27, 2014 at 13:37
  • Use f.elements.find {|e| e['name'] == path[0]} Commented Jan 27, 2014 at 13:50

2 Answers 2

4

Because Array#shift removes the element from the array.

So, the first time the block executes, it is comparing e['name'] == "pets" but on the next iteration, it is comparing e['name'] == nil. Unless e['name'] is "pets" on the first iteration, the .find will return nil.

Sign up to request clarification or add additional context in comments.

7 Comments

I think the snippet isn't obvious enough, but that is not the case. You see, I assign a new value to path both times right before i execute #find. First I set it to a string 'pets' then I set it to an array with a string ['pets']. You can even note the lines irb is mentioning: 86 is where I set path, 87 is where I call #find.
Always be aware of methods that do in-place modification of the object they're called on. Many are identified with ! but there are some like shift that pre-date that convention.
You both are not paying attention. I DO know that shift mutates the variable. But that is NOT the case.
@ArthurCorenzan .find executes the code in the block once for every element in f.elements. So, if there are 3 elements, your block gets called 3 times. Hence, .shift gets called on the array 3 times. The first time reduces the array to [].
Maybe you need to amend your question with a more generic example because I'm in complete agreement with @CharlesCaldwell here.
|
0

@Charles Caldwell explained correctly, why you did get that result. Now just use Array#first method as below which is safe :

a.find { |i| i == n.first }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.