I like perls scoping


TL;DR: I think it's chill that perl has both lexical and dynamic scoping.

for my $thing (@things) {
    local $ThingFinder::LogLevel = 9;

    print "I have $thing";
    if (my $thing = $thing->get_more_specific_things()) { 
        print "I have found this thing: $thing";
    }
}

Lexical variables!

Variables who are only declared / visible within their scope.

my $item = Thing->new();               # <- declare a lexical variable
                                       #    and shove an object in there
                                       #
for my $thing ($item->fetch_things) {  # <- $thing only exists within the loop
                                       #
    my $item = $thing>get_item();      # <- this $item masks the $item above
    $item->do_stuff();                 # <- do_stuff can't see either $item
                                       #    (though the inner one will be "self" in the call)
                                       #
}                                      # <- inner $item is DESTROYed here.

Lexicals are the power house of the closure:

sub thing_maker {
    my $thing = shift;                  # <- $thing will live past the end of the
                                        #    call to thing_maker
    return sub {                        # <- return a code-ref
        "I made this thing: $thing"     # <- This reference here keeps $thing alive.
    }
}

my $code = thing_maker("very good thing here");
print $code->()                         # "I made this thing: very good thing here"

Globals or Package variables!

These are the kind of variables you get if you don't use strict 'vars'.

#!perl
$half = $ARGV[1] / 2;            # <- $half isn't declared with my/our/state
                                 #    so it's ours 
print "Half of that is $half\n"  # "Half of that is 5"  (or whatever)

These are kind of pesky because the stuff you assign to them is only DESTROYed when the variable is assigned over or the interpreter shuts down.

You can see them from outside the package

You have a variable in a package:

package ThingFinder;
our $LogLevel = 4;
1

... and you can see the values in it:

use ThingFinder;

sub show_loglevel {
   say "It's $ThingFinder::LogLevel"; # It's 4
}

... sadly anyone can write to it too:

# Set the value for everyone forever:
$ThingFinder::LogLevel = 'just any old garbage'; 

These variables are super helpful for configuration when your package exports functions.

You can override the value for those called inside a block with local

$ThingFinder::LogLevel = 4;             # <- Set the value for everyone forever
ThingFinder->show_loglevel()            # "It's 4"

{
    local $ThingFinder::LogLevel = 9;   # <- Set the value until the end of the scope
    ThingFinder->show_loglevel()        # "It's 9"
}

local works on other stuff, like the symbol table, or just regular old hashes, which is also chill.

That's it.

I just think that's neat.

[(a,4),(b,3),(c,2),(a,1)]


Re: "an interview question":

Write a function that takes 'aaaabbbcca' and returns [('a', 4), ('b', 3), ('c', 2), ('a', 1)]

I'm not sure why an interviewer would hate someone enough to ask a question like this, but this seems like a fair response:

% echo aaaabbbcca | perl -nlE '
    s/((.)\2*)/push @things,sprintf "(%s,%s)", $2,length $1 /ge;
    $"=","; say "[@things]"
'
[(a,4),(b,3),(c,2),(a,1)]

I mean, it'd be easier if perl had tuples, but that's what you get for answering a python question in perl when nobody asked you to

Standard perl-golf disclaimer

Please don't do this kind of thing in a production code base

Perfection


“Perfection is achieved, not when there is nothing more to add, but when there are no TODO comments left to take away.”