Сабвуферы perl6 действительно лексически ограничены или имеют дополнительные возможности? - PullRequest
7 голосов
/ 26 июня 2019

Если у меня есть блок, подобный следующему:

{
   say $myVar;
   my $myVar=1;
}

Я получаю ожидаемую ошибку:

Variable '$myVar' is not declared 

Однако аналогичным образом с sub

{
    test();
    my sub test() {
        say "Hello";
    }
}

Это работает без ошибок и печатает:

Hello

И $myVar, и test не видны вне ограждающих блоков, поэтому в этом смысле они оба имеют лексическую область видимости.

У объявления sub должно быть «поднято» верхняя часть блока, поскольку test определено и может использоваться до его позиции в коде. Однако я не могу найти ссылку, чтобы подтвердить это.

Что вызвало этот вопрос, так это поиск лексической области действия my subs в perl, что приводит к ошибке «неопределенная подпрограмма» в версии perl во втором случае выше. В моем понимании лексического охвата это то, что я ожидал.

Я использую это без раздумий ... напиши какой-нибудь тестовый код, позже оберну его в sub, объявленный внизу моего файла, и вызову подпрограмму из ранее в файле. Все работает!

Это приводит к вопросу: действительно ли в этом смысле sub perl6 имеют лексическую область?

Ответы [ 2 ]

7 голосов
/ 26 июня 2019

Когда Perl6 сталкивается с вызовом функции, он записывает это, но не проверяет, есть ли функция.

Таким образом, следующее скомпилируется, но фактически не будет работать. (Функция недоступна там, где она вызывается.)

foo 1;
my &foo = &say;

Далее компилятор делает то же самое, но оптимизатор понимает, что он не может даже найти ссылку на функцию где-либо. (Таким образом, оптимизатор вызывает сбой во время компиляции.)

bar 1;

Причина этой разницы с другими переменными состоит в том, что часто у вас может быть одна функция, которая полагается на другую, или вы хотите поместить функции после остальной части кода.
Кроме того, код функции обычно известен во время компиляции, тогда как значение переменной неизвестно до тех пор, пока она не будет назначена. (Назначение происходит во время выполнения.)

В основном, люди склонны использовать переменные и функции, поэтому они работают немного по-другому.

Нет необходимости требовать, чтобы они были объявлены перед использованием, поэтому ограничение было снято.


В Perl5 функции изменяют синтаксический анализатор на основе своего прототипа, поэтому компилятору необходимо увидеть объявление, прежде чем их использовать, чтобы он знал, как их нужно анализировать.

use v5.10;

sub foo ();
sub bar;

say foo + 1; # foo() + 1 # foo is compiled as a term/constant
say bar + 1; # bar( +1 )

sub foo () { 2 }
sub bar { $_[0] + 2 }

В Perl6 все функции компилируются так, как будто они принимают список, поэтому нет необходимости требовать, чтобы они были предварительно объявлены.

use v6;

# these two lines don't really change anything.
sub foo () {...}
sub bar ($) {...}


say foo + 1; # foo( +1 ) # optimization failure (too many arguments)
say bar + 1; # bar( +1 )

sub foo () { 2 }
sub bar ( $a ) { $a + 2 }
5 голосов
/ 26 июня 2019

Из подпрограммы Апокалипсис :

Perl 6 также позволяет вам отложить объявление подпрограммы на более поздний срок в файле, но только если задержанное объявление объявляет, что подпрограмма должна быть проанализирована в соответствии с тем, как будет обрабатываться оператор списка. По сути, предполагается, что любое нераспознанное «голое слово» является предварительным оператором списка, который должен быть объявлен в конце текущего модуля компиляции.

...