(Идентификатор) термины против констант против процедур с нулевой подписью - PullRequest
4 голосов
/ 22 марта 2019

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

sub term:<þor> { "Is mighty" }
sub Þor { "Is mighty" }

say þor, Þor;

Но вы уже можете определять подпрограммы с нулевой подписью. Однако вы можете увидеть ошибку, когда напишите:

say Þor ~ Þor;

Что даст many positionals passed; expected 0 arguments but got 1, в отличие от термина. Это кажется, однако, немного надуманным, и вы можете сэкономить, просто добавив () в конце.

Другой возможный вариант использования - это , игнорирующий правила обычных идентификаторов

sub term:<✔> { True }
say ✔; # True

Есть ли другие варианты использования, которые я пропустил?

Ответы [ 3 ]

5 голосов
/ 22 марта 2019

Включение подпрограмм с нулевым аргументом, так как термины лишают возможности пост-объявления подпрограмм, так как для поиска подпрограммы после анализа ее использования потребуется повторный разбор более раннего кода (что в языке perl 6 отказывается делать, "однопроходный анализ "и все такое), если подпрограмма не принимает аргументов.

4 голосов
/ 22 марта 2019

Термины полезны в сочетании с троичным оператором:

$ perl6 -e 'sub a() { "foo" }; say 42 ?? a !! 666'
===SORRY!=== Error while compiling -e
Your !! was gobbled by the expression in the middle; please parenthesize

$ perl6 -e 'sub term:<a> { "foo" }; say 42 ?? a !! 666'
foo
3 голосов
/ 22 марта 2019

Константы в основном термины.Поэтому, конечно, они сгруппированы вместе.

constant foo = 12;

say foo;

constant term:<bar> = 36;

say bar;

Есть небольшая разница, потому что term:<…> работает путем изменения синтаксического анализатора.Таким образом, он имеет приоритет.

constant fubar = 38;
constant term:<fubar> = 45;

say fubar; # 45

Выше будет напечатано 45 независимо от того, какое определение constant будет первым.

Поскольку term:<…> имеет приоритет, единственный способ получитьдругое значение - использовать ::<fubar> для прямого доступа к таблице символов.

say ::<fubar>; # 38
say ::<term:<fubar>>; # 45

Существует два основных варианта использования для term:<…>.

Один - получитьПодпрограмма должна быть проанализирована аналогично константе или переменной без знака.

sub fubar () { 'fubar'.comb.roll }

# say( fubar( prefix:<~>( 4 ) ) );
say fubar ~ 4; # ERROR
sub term:<fubar> () { 'fubar'.comb.roll }

# say( infix:<~>( fubar, 4 ) );
say fubar ~ 4;

Другой вариант - иметь переменную константы или сигиллы, отличную от обычного идентификатора.

my \✔ = True; # ERROR: Malformed my
my \term:<✔> = True;

say ✔;

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

sub term:<✔> () { True }

Perl 5 позволяет подпрограммам иметь пустой прототип (отличный от сигнатуры), который изменит способ его анализа.Основная цель прототипов в Perl 5 - изменить способ анализа кода.

use v5;

sub fubar () { ord [split('','fubar')]->[rand 5] }

# say( fubar() + 4 );
say fubar + 4; # infix +
use v5;

sub fubar { ord [split('','fubar')]->[rand 5] }

# say( fubar( +4 ) );
say fubar + 4; # prefix +

Perl 6 не использует сигнатуры, как в Perl 5 используются прототипы.Основной способ изменить способ анализа кода в Perl 6 - использовать пространство имен.

use v6;

sub fubar ( $_ ) { .comb.roll }
sub term:<fubar> () { 'fubar'.comb.roll }

say fubar( 'zoo' ); # `z` or `o` (`o` is twice as likely)
say fubar; # `f` or `u` or `b` or `a` or `r`


sub prefix:<✔> ( $_ ) { "checked $_" }

say ✔ 'under the bed'; # checked under the bed

Обратите внимание, что в Perl 5 на самом деле нет констант, это просто подпрограммы с пустым прототипом.*

use v5;

sub foo () { 12 } # ditto

(Это стало менее верно после 5.16)


Насколько я знаю, все другие виды использования прототипов были заменены проектными решениями в Perl 6.

use v5;
sub foo (&$) { $_[0]->($_[1]) }

say foo { 100 + $_[0] } 5; # 105;

Этот блок рассматривается как лямбда sub из-за прототипа подпрограммы foo.

use v6;
# sub foo ( &f, $v ) { f $v }
sub foo { @_[0].( @_[1] ) }

say foo { 100 + @_[0] }, 5; # 105

В Perl 6 блок рассматривается как лямбда, если ожидается термин,Поэтому нет необходимости изменять синтаксический анализатор с помощью функции, подобной прототипу.


Вы просите вернуть только одно использование прототипов, даже если уже есть функция, которая покрывает это использование.case.

Это будет особый случай.Часть концепции разработки Perl 6 заключается в ограничении числа особых случаев.
В других версиях Perl было множество особых случаев, и не всегда легко запомнить их все.

Не поймите меня неправильно;специальные случаи в Perl 5 полезны, но Perl 6 по большей части сделал их общими случаями.

...