ProgrammingBackend Developer

How do the list operations map and grep work in Perl? What are their differences and how to avoid unexpected side effects when using them?

Pass interviews with Hintsage AI assistant

Answer

map and grep are powerful Perl functions for working with arrays:

  • map applies an expression to each element of the list and returns a new list with the results.
  • grep returns the elements of the list for which the expression returns a true value (filtering).

Example usage:

my @nums = (1, 2, 3, 4, 5, 6); my @squared = map { $_ * $_ } @nums; # (1, 4, 9, 16, 25, 36) my @even = grep { $_ % 2 == 0 } @nums; # (2, 4, 6)

Important

  • Scope: Within the blocks of map and grep, the variable $_ by default contains the current element. Modifying $_ will change the element of the original array if the array is passed by reference or if $_ is explicitly used (e.g., through aliasing with foreach).
  • Return values: map always returns a list, grep returns a subset of the original list.

Trick question

Question: What does the following code do and why?

my @nums = (1..5); my @result = map { $_++ } @nums; print "@nums ";

Answer: This code will not change the original array @nums. The operator $_++ increments the value of the variable inside the block but does not save these changes to the original array, since map returns the modified value but the original array remains unaffected (unless aliasing is used through foreach).

Example:

my @nums = (1..5); my @result = map { $_++ } @nums; # @result will be (1,2,3,4,5), @nums remains unchanged print "@nums "; # Prints: 1 2 3 4 5

Examples of real mistakes due to ignorance of the nuances of the topic


Story In one project, a developer expected that after map { $_++ } @array, the array @array itself would be modified. As a result, the program continued to work with the old values, leading to incorrect calculations during data aggregation.


Story In a reporting system, when filtering an array using grep, inside the block, an assignment command $result = $_ was accidentally used, causing all elements to be overwritten in the same variable, losing the data source. This complicated debugging and led to losses in reporting.


Story In an integration script, nested maps were used and it was forgotten that the inner context also operates with the shared variable $_, causing unpredictable behavior when modifying elements, as the inner map overwrote values in the resulting array.