Hacker News new | ask | show | jobs
by wschroed 4163 days ago
If you are interested (feel free to ignore if not)... Here are some examples for understanding list context and some of the things it can do for you. One funny way to think about it is that in Perl, you store array, array ref, hash, and hash ref structures, and you do not store lists. Lists are a way to express in code, distinct from the actual storage.

    my $arr1 = [1, (), 2, (3, 4, (5, 6)), 7];   # $arr1 is [1, 2, 3, 4, 5, 6, 7]
    my $arr2 = [1, [], 2, [3, 4, [5, 6]], 7];   # $arr2 is [1, [], 2, [3, 4, [5, 6]], 7]

Perl's fat arrow => is the same thing as a comma, except that the thing on the left of it may be a bare word under "use strict". In other words, it has little special meaning and helps you to construct a list of things.

    my $arr3 = [1 => 2 => 3, 4 => 5];  # $arr3 is [1, 2, 3, 4, 5]

For readability, when we construct hashmaps, we use the fat arrow so that you can more easily distinguish key from value.

    my $hash1 = {x => 1, y => 2};  # $hash1->{x} is 1

But you don't have to use the fat arrow:

    my $hash2 = {'x', 1, 'y', 2};  # same as $hash1

An array used in an expression like this is considered to be in list context:

    my @pairs = ('x', 1, 'y', 2);
    my $hash3 = {@pairs};  # same as hash1

Since we can boil about anything down to expression in list context, we have a lot of concise flexibility on constructing arrays and hashes and a variety of ways to express the same concept. Here is a fun use case: Build a hashmap where the keys are the numbers from 1 to 100, and the values are all the string "foo". Other languages perform an elegant dance with infinite cycles and zippers. In Perl, knowing the list context magic, this is a possible solution that shows that "map" may not return the same number of elements as the input list/array:

    my %answer = map { $_ => "foo" } (1..100);

Let's join together two arrays with the letter 'x' between them:

    my @result = (@array1, 'x', @array2);

Take an array reference, and return a reference to its elements cycled once (this specific problem is awkward in Perl and easier in other languages with nice array operators):

    my $doubled = [@$ref, @$ref];

Construct a hashmap where some of the keys are completely optional. This is also an alternative expression for the "many optional parameters to object creation" problem, which most languages let you resolve by allowing you to instantiate the object with defaults and then alter the defaults with accessors in "if" clauses afterwards. In this example, if $self->y is false, then there will not be a "y" key.

    my %params = (
        x => $self->x,
        $self->y ? (y => $self->y) : (),
        z => $self->z,
    );
    MyClass->new(%params);  # this actually converts the hashmap into list context!

Tip of the iceberg. Note that I am not defending, just demonstrating. I am on the fence on if I prefer the Ruby explicit style over Perl's style. For one, in Ruby, the fat arrow actually means that you are now constructing a hashmap. In Perl, since it is just a comma, I can exploit it to mean new things, depending on my context.

    use Moose;
    has age => (isa => 'Int', required => 1);

    use Test::More;
    subtest 'Math is still valid' => sub {
        is(1, 1 => "1 is still equal to itself");
        is(2, 2 => "2 is still equal to itself");
    };