Lexical Variables in Perl 6

Original author: carl
  • Transfer
One of the problems of programming is the struggle with the increasing complexity of programs as their volume grows. Historically, it is solved by isolating certain parts of programs whose interaction with each other is limited. This approach operates at all levels of programming - “separation of concepts”, “do one thing and do it well”, BCNF, monads, procedures, classes, roles, modules. All of them encourage the limitation of parts of the program so as not to play against combinatorics. The simplest example of logical separation is a lexical variable.

{
    my $var;
    # $var доступна тут
}
# $var а тут недоступна


What is interesting about this?

From the very beginning, Perl did this wrong. By default, the scope of variables in Perl 5 is a module variable, something like a global variable. If you define something inside the block, it will be visible from the outside.

$ perl -v
This is perl 5, version 12, subversion 1 (v5.12.1)
$ perl -E '{ $var = 42 }; say $var'
42
$ perl -wE '{ my $var= 42 }; say $var'
Name "main::var" used only once: possible typo at -e line 1.
Use of uninitialized value $var in say at -e line 1.


In Perl 6, lexical variables work by default.

$ perl6 -e '{ $var = 42 }; say $var'    # необходима инициализация через 'my'
===SORRY!===
Symbol '$var' not predeclared in 
$ perl6 -e '{ my $var = 42 }; say $var' # не будет работать – не видна снаружи
===SORRY!===
Symbol '$var' not predeclared in 


Well, maybe it helps to catch a typo ... But the main advantage of this is that you will work with honest scope of variables. And this will allow you to manage the complexity of the programs.

Of course, Perl 5 did not force you to program “correctly” and did not impose the use of strict and warnings. Perl 5 promised to provide backward compatibility, while Perl 1 was clearly not intended for writing complex programs. Global variables in small scripts make sense.

Perl 6 is trying to help you get started small and add structured support as programs grow. In the case of variables, this means that in scripts and modules the variables are lexical by default, but in single-line files called by –e, global variables remain.

If you thought that everything about lexical variables is not so. There are unexpected bonuses in this approach. Consider the function:

sub counter($start_value) {
    my $count = $start_value;
    return { $count++ };
}


The code block is returned. Each time counter is called, we get a piece of code that can be called up a number of times.

Here's what happens if we create two different pieces of this code and play with them:

my $c1 = counter(5);
say $c1();           # 5
say $c1();           # 6
my $c2 = counter(42);
say $c2();           # 42
say $c1();           # 7
say $c2();           # 43


See? $ c1 and $ c2 work independently. Each state is saved in the form of the variable $ count. For us, it may look like one variable, but for two different counter instances, these are two different value storage areas - because, each time we re-enter the block, we open a new scope. Such a block is called a closure.

If it seemed to you that closures are similar to lightweight objects - congratulations, that is exactly so. Their essence of access restriction is the same as that of encapsulation and hiding information in the TOE. All this is necessary to limit the field of activity, so that certain parts of the program can do as little as possible.

Also popular now: