But some of the elements in @$arr could be undefined, and of those that were defined, some could have the string 'NA' or undef returned by the value method. I wanted all these cases to show up as undef in the LHS, so I wrote something like this:

Spot the bug? It's in the second return statement of val. Without an argument, it causes val to return undef in scalar context, but return the empty list in list context. As it happens, map evaluates its first argument in list context. Bottom line: even though, in every iteration, the size of @$arr was the same, the size of @row would sometimes be smaller.

Well, map and grep are usually seen as functions, but there's no denying that both map and grep are looping constructs.

But ultimely, what is the difference between an operator, a function or a syntax construct from a programmers aspect of view (other than using it to answer "where do I find this in the manual")? Would you code differently if map or grep were reclassified as a syntax or looping construct, or foreach as a function?

When I first learned about map in Perl, I assumed it behaved the same way as map in other languages I was using at the time - Haskell and ML. In these languages, the mapped function takes one argument and returns one value. This is equivalent to Perl's map using scalar context, which it perfectly well could have done. This was (presumably) an intentional design decision on Larry's part. Had it been the other way, we could guarantee that map would always return a list of exactly the same length as its argument list, and issues like the one you describe wouldn't arise. On the other hand, we wouldn't have the flexibility to return longer or shorter lists if appropriate. So it's a tradeoff.

The bug is still there, but it's clearer now that you're working in list context. At that point, you can fix it either by returning an explicit undef from val() (the bad way) or modifying your map body to be val( $_ ) || undef (the good way).

My criteria for good software:

Does it work?

Can someone else come in, make a change, and be reasonably certain no bugs were introduced?