Maxim Fedotov
Maxim Fedotov

Reputation: 1357

Correct semantic usage of map

I am trying to understand what is a semantically right way to use map. As map can behave the same way as each, you could modify the array any way you like. But I've been told by my colleague that after map is applied, array should have the same order and the same size.

For example, that would mean using the map to return an updated array won't be the right way to use map:

array = [1,2,3,4]
array.map{|num| num unless num == 2 || num == 4}.compact

I've been using map and other Enumerator methods for ages and never thought about this too much. Would appreciate advice from experienced Ruby Developers.

Upvotes: 2

Views: 88

Answers (2)

the Tin Man
the Tin Man

Reputation: 160551

Meditate on this:

array = [1,2,3,4]

array.map{|num| num unless num == 2 || num == 4} # => [1, nil, 3, nil]
    .compact # => [1, 3]

The intermediate value is an array of the same size, however it contains undesirable values, forcing the use of compact. The fallout of this is CPU time is wasted generating the nil values, then deleting them. In addition, memory is being wasted generating another array that is the same size when it shouldn't be. Imagine the CPU and memory cost in a loop that is processing thousands of elements in an array.

Instead, using the right tool cleans up the code and avoids wasting CPU or memory:

array.reject { |num| num == 2 || num == 4 } # => [1, 3]

I've been using map and other Enumerator methods for ages and never thought about this too much.

I'd recommend thinking about it. It's the little things like this that can make or break code or a system, and everything we do when programming needs to be done deliberately, avoiding all negative side-effects we can foresee.

Upvotes: 4

Sagar Pandya
Sagar Pandya

Reputation: 9497

In Computer Science, map according to Wikipedia:

In many programming languages, map is the name of a higher-order function that applies a given function to each element of a list, returning a list of results in the same order

This statement implies the returned value of map should be of the same length (because we're applying the function to each element). And the returned-elements are to be in the same order. So when you use map, this is what the reader expects.

How not to use map

arr.map {|i| arr.pop } #=> [3, 2]

This clearly betrays the intention of map since we have a different number of elements returned and they are not even in the original order of application. So don't use map like this. See "How to use ruby's value_at to get subhashes in a hash" and subsequent comments for further clarification and thanks to @meager for originally pointing this out to me.

Upvotes: 4

Related Questions