Perl 5’s list-flattening and reference-taking design choices

Eevee:

Perl has the strange property that its data structures try very hard to spill their contents all over the place. Despite having dedicated syntax for arrays – @foo is an array variable, distinct from the single scalar variable $foo – it’s actually impossible to nest arrays.

my @foo = (1, 2, 3, 4);
my @bar = (@foo, @foo);
# @bar is now a flat list of eight items: 1, 2, 3, 4, 1, 2, 3, 4

The idea, I guess, is that an array is not one thing. It’s not a container, which happens to hold multiple things; it is multiple things. Anywhere that expects a single value, such as an array element, cannot contain an array, because an array fundamentally is not a single value.

And so we have “references”, which are a form of indirection, but also have the nice property that they’re single values.

This is a common thing for people to find weird about Perl. Really though it’s just a different default.

Perl’s reference-taking operator is simply dual with the splat operator in Ruby and recent Javascript.

So, in Javascript, you can (as of some years ago) say this:

var x = [1, 2, 3, 4];
var y = [x, x];       // y => [[1, 2, 3, 4], [1, 2, 3, 4]]
var z = [...x, ...x]; // z => [1, 2, 3, 4, 1, 2, 3, 4]

That’s exactly like Perl, only the other way around. In Perl, splatting happens to containers by default when they’re mentioned in a list, and you have to use an operator to prevent it:

my @x = (1, 2, 3, 4);
my @y = (\@x, \@x); // @y => ([1, 2, 3, 4], [1, 2, 3, 4])
my @z = (@x, @x);   // @z => (1, 2, 3, 4, 1, 2, 3, 4)

Note how if you always work with scalars containing references, rather than arrays, then the Perl form of this code becomes exactly equivalent to the Javascript:

my $x = [1, 2, 3, 4];
my $y = [$x, $x];   // $y => [[1, 2, 3, 4], [1, 2, 3, 4]]
my $z = [@$x, @$x]; // $z => [1, 2, 3, 4, 1, 2, 3, 4]

So the big difference is that Perl has lists as a first-class concept; within them it flattens containers, but it supplies you with an operator to prevent that. Other languages only have lists as a syntactic feature, limited to certain contexts such as list construction or argument passing; some of them supply an operator that allows you to flatten containers in such contexts, but many don’t.

That’s all.

Leave a comment

About Aristotle

user-pic Waxing philosophical