user1762229
user1762229

Reputation: 71

understanding ruby syntax inside do end block

I recently started learning ruby and was doing some research involving arrays when I saw this line of code:

array.map!{ |i| i.is_a?(Integer) ? (i + number) : i }

I'm trying to conceptualize and get a better understanding of what every part of this line means. Can someone explain how I would write this out using do end instead of {} and what the "?" after (Integer) and the ":" after (i + number) mean in words? Thanks a lot!

Upvotes: 0

Views: 53

Answers (2)

lurker
lurker

Reputation: 58244

array.map! { |i| i.is_a?(Integer) ? (i + number) : i }

The .map! is a method for an Array type in Ruby. It says to map each element of the array per the given block argument. A block argument in Ruby accepts its own arguments (delimited with |...|) so you can pass in the value of the array element in question. In this case, |i| is giving a block variable, i, representing the value of the current element of array being evaluated.

The result will be an array that has the same number of elements, but each element will be the result of this mapping from each corresponding element in the original array, array. The explanation point (!) means to replace the array elements with the results rather than return a new array with the result. You could also do, array.map {... which would yield the same results, but not alter array; the results would be a new array.

The block is delimited by {} and can be expressed with do and end on separate lines:

array.map! do |i|
  i.is_a?(Integer) ? (i + number) : i
end

There is no difference in behavior between using {} and do-end.

?: is the ternary if-then-else, just like in C. So exp1 ? exp2 : exp3 says, if exp1 is truthy, then do exp2 otherwise do exp3. The above, then, is equivalent to:

array.map! do |i|
  if i.is_a?(Integer) then
     i + number
  else
     i
  end
end

In either case, the value of the if-then-else expression is the value of the last statement executed in the branch that was taken. That is the result, then, returned for the execution of the block for the given element, i. So the result of this entire mapping is to replace each element that is of class Integer in the array with its index plus whatever number is (hopefully, also a variable of numeric class). If the element is not an Integer, then it's replaces with just its index.

Upvotes: 1

TDJoe
TDJoe

Reputation: 1398

{} is exactly the same as do/end, and ? and : work like an if/else block, so the code could also be written as

array.map! do |i|
  if i.is_a?(Integer)
    i + number
  else
    i
  end
end

Upvotes: 1

Related Questions