7

首先让我说我明白我在标题中所问的是可疑的做法(如此所述),但我缺乏理解涉及所涉及的语法。

当我第一次尝试将标量绑定到无符号符号时,我这样做了:

my \a = $(3);

认为这$(...)会将 Int 3 打包为标量(如文档中所建议的那样),然后将其绑定到符号 a。但这似乎不起作用:找不到标量(a.VAR.WHAT返回(Int),而不是(标量))。

在上面引用的帖子中,raiph 提到可以使用不同的语法执行所需的绑定:

my \a = $ = 3;

哪个有效。鉴于结果,我怀疑该陈述可以等效地表达,尽管不太简洁,如:my \a = (my $ = 3),然后我可以理解。

这留下了一个问题:为什么尝试$(...)不起作用,它做了什么?

4

2 回答 2

6

什么$(…)是将值转换为item.
(标量变量 ( $a) 中的值也被标记为项目)

say flat (1,2,      (3,4)  );
# (1 2 3 4)

say flat (1,2,    $((3,4)) );
# (1 2 (3 4))

say flat (1,2, item((3,4)) );
# (1 2 (3 4))

基本上它是为了防止值变平。它存在的原因是 Perl 6 不像大多数其他语言那样扁平化列表,有时您需要对扁平化进行更多控制。


以下唯一一种做你想做的事

my \a = $ = 3;

一个bare$是一个匿名state变量。

my \a = (state $) = 3;

当您多次运行同一段代码时,问题就会出现。

sub foo ( $init ) {
  my \a = $ = $init; # my \a = (state $) = $init;

  (^10).map: {
    sleep 0.1;
    ++a
  }
}

.say for await (start foo(0)), (start foo(42));
# (43 44 45 46 47 48 49 50 51 52)
# (53 54 55 56 57 58 59 60 61 62)

# If foo(42) beat out foo(0) instead it would result in:
# (1 2 3 4 5 6 7 8 9 10)
# (11 12 13 14 15 16 17 18 19 20)

请注意,变量在调用之间共享。
第一个 Promise 在sleep调用时停止,然后第二个在第一个运行之前设置状态变量++a

如果您改用my $它,它现在可以正常工作。

sub foo ( $init ) {
  my \a = my $ = $init;

  (^10).map: {
    sleep 0.1;
    ++a
  }
}

.say for await (start foo(0)), (start foo(42));
# (1 2 3 4 5 6 7 8 9 10)
# (43 44 45 46 47 48 49 50 51 52)

问题是无符号的“<em>变量”并不是真正的变量(它们不会变化),它们更类似于词法范围(非)常量。

constant \foo = (1..10).pick; # only pick one value and never change it

say foo;
for ^5 {
  my \foo = (1..10).pick;     # pick a new one each time through

  say foo;
}

基本上,它们的全部意义在于尽可能接近您分配给它的值。(静态单分配)

# these work basically the same
-> \a        {…}
-> \a is raw {…}
-> $a is raw {…}

# as do these
my \a  = $i;
my \a := $i;
my $a := $i;

请注意,上面我写了以下内容:

my \a = (state $) = 3;

通常在状态变量的声明中,赋值只会在代码第一次运行时发生。Bare $没有这样的声明,所以我必须通过将声明放在括号中来防止这种行为。

# bare $
for (5 ... 1) {
  my \a =        $  = $_; # set each time through the loop

  say a *= 2; # 15 12 9 6 3
}

# state in parens
for (5 ... 1) {
  my \a = (state $) = $_; # set each time through the loop

  say a *= 2; # 15 12 9 6 3
}

# normal state declaration
for (5 ... 1) {
  my \a =  state $  = $_; # set it only on the first time through the loop

  say a *= 2; # 15 45 135 405 1215
}
于 2018-06-24T17:19:35.713 回答
2

Sigilless 变量实际上并不是变量,它们更像是一个别名,也就是说,它们不是容器,而是绑定到它们在右侧获得的值。

my \a = $(3); 
say a.WHAT; # OUTPUT: «(Int)␤»
say a.VAR.WHAT; # OUTPUT: «(Int)␤»

在这里,通过执行 $(3) 您实际上将标量上下文中已经存在的内容放入标量上下文中:

my \a = 3; say a.WHAT; say a.VAR.WHAT; # OUTPUT: «(Int)␤(Int)␤»

但是,您问题中的第二种形式会有所不同。您正在绑定到一个匿名变量,它是一个容器:

my \a = $ = 3; 
say a.WHAT;    # OUTPUT: «(Int)␤»
say a.VAR.WHAT;# OUTPUT: «(Scalar)␤»

在第一种情况下,a是 3 的别名(或$(3),相同);第二个a是 的别名$,它是一个容器,其值为3。最后一种情况等价于:

 my $anon = 3; say $anon.WHAT; say $anon.VAR.WHAT; # OUTPUT: «(Int)␤(Scalar)␤»

(如果您对如何改进文档有一些建议,我很乐意跟进)

于 2018-06-24T10:29:46.893 回答