将标量绑定到无符号变量 (Perl 6)
Binding a scalar to a sigilless variable (Perl 6)
首先让我说我明白我在标题中问的是可疑的做法(如所解释的),但我对所涉及的语法缺乏理解。
当我第一次尝试将标量绑定到无符号符号时,我这样做了:
my \a = $(3);
认为 $(...)
会将 Int 3 打包在标量中(正如 documentation 中似乎建议的那样),然后将其绑定到符号 a。但这似乎不起作用:找不到标量(a.VAR.WHAT
returns(Int),而不是(标量))。
在 above-referenced post 中,raiph 提到可以使用不同的语法执行所需的绑定:
my \a = $ = 3;
有效。鉴于结果,我怀疑该陈述可以等效地表述为:my \a = (my $ = 3)
,但我可以理解。
这就留下了一个问题:为什么 $(...)
的尝试不起作用,它做了什么?
Sigilless variables are not actually variables, they are more of an alias, that is, they are not containers 但绑定到他们在右侧获得的值。
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)»
(如果您对如何改进文档有任何建议,我很乐意跟进)
$(…)
所做的是将值转换为 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;
裸 $
是匿名 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
调用处停止,然后第二个 Promise 在第一个 运行s ++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)
事实是无符号“变量”并不是真正的变量(它们不会变化),它们更类似于词法范围的(非)常量。
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;
}
基本上它们的全部要点是尽可能接近指代您分配给它的值。 (Static Single Assignment)
# 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
}
首先让我说我明白我在标题中问的是可疑的做法(如
当我第一次尝试将标量绑定到无符号符号时,我这样做了:
my \a = $(3);
认为 $(...)
会将 Int 3 打包在标量中(正如 documentation 中似乎建议的那样),然后将其绑定到符号 a。但这似乎不起作用:找不到标量(a.VAR.WHAT
returns(Int),而不是(标量))。
在 above-referenced post 中,raiph 提到可以使用不同的语法执行所需的绑定:
my \a = $ = 3;
有效。鉴于结果,我怀疑该陈述可以等效地表述为:my \a = (my $ = 3)
,但我可以理解。
这就留下了一个问题:为什么 $(...)
的尝试不起作用,它做了什么?
Sigilless variables are not actually variables, they are more of an alias, that is, they are not containers 但绑定到他们在右侧获得的值。
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)»
(如果您对如何改进文档有任何建议,我很乐意跟进)
$(…)
所做的是将值转换为 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;
裸 $
是匿名 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
调用处停止,然后第二个 Promise 在第一个 运行s ++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)
事实是无符号“变量”并不是真正的变量(它们不会变化),它们更类似于词法范围的(非)常量。
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;
}
基本上它们的全部要点是尽可能接近指代您分配给它的值。 (Static Single Assignment)
# 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
}