(标识符)项vs.常量vs.空签名例程

时间:2019-03-22 08:26:37

标签: perl6

标识符术语在文档alongside constants中定义,具有几乎相同的用例,尽管术语在运行时计算其值,而常量在编译时获取。潜在地,这可能会使术语使用全局变量,但这是遥不可及的,因此我想这不是它们的用例。 OTOH,它们可能只是带有null签名的简单例程:

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

say þor, Þor;

但是您已经可以使用空签名定义例程。但是,您可以编写以下错误:

say Þor ~ Þor;

produce a many positionals passed; expected 0 arguments but got 1与术语不同。但是,这似乎有些牵强,您可以通过在末尾添加()来节省麻烦。

另一个可能的用例是defying the rules of normal identifiers

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

我还有其他用例吗?

3 个答案:

答案 0 :(得分:5)

将零参数subs用作术语将打破后声明subs的可能性,因为在解析了subs的用法后找到sub会要求重新解析早期的代码(perl 6语言拒绝这样做,“一次解析”以及所有内容)(如果该子对象不带任何参数。

答案 1 :(得分:4)

术语与三元运算符结合使用非常有用:

match(as.Date("2019-01-02"), as.Date(timestamp))

答案 2 :(得分:3)

常量基本上是术语。因此,它们当然会组合在一起。

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;

另一种方法是使用常量或无sigi变量,而不是普通标识符。

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;

use constant foo => 12;
use v5;

sub foo () { 12 } # ditto

(在5.16之后,这种情况变得不那么真实了)


据我所知,原型的所有其他用途已被Perl6中的设计决定所取代。

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

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

由于sub子例程的原型,该块被视为foo lambda。

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

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

在Perl 6中,如果期望一个术语,则将其视为lambda。因此,无需使用原型之类的功能来更改解析器。


即使您已经拥有涵盖该用例的功能,您仍要求将原型的一种用途重新带回。

这样做将是特例。 Perl 6的部分设计思想是限制特殊情况的数量。
其他版本的Perl具有多种特殊情况,要记住所有特殊情况并不总是那么容易。

别误会我的意思; Perl 5中的特殊情况很有用,但是Perl 6在大多数情况下使它们成为一般情况。