确定是否设置了 Raku 中的变量

use*_*601 12 raku

我有意避免使用该术语,defined因为变量很可能具有已定义的值,但该.defined方法将返回 false(例如,Failures)。

有什么方法可以确定变量是否已为其设置了值?

my $foo;
say $foo; # (Any), its type object, no value assigned
my Str $bar;
say $bar; # (Str), its type object, no value assigned
my $abc = Str;
say $abc; # (Str), the type object we assigned to $abc
Run Code Online (Sandbox Code Playgroud)

我们如何区分$bar(未设置值,输入为Str)和$abc(值设置为Str)?

鉴于$bar.WHICH == $abc.WHICH, but $bar.VAR.WHICH !== $abc.VAR.WHICH, 和类似的方法.defined将为每个返回 false ,是否有任何快速简便的方法来确定存在一个设置值?

我认为它可以根据默认值进行检查,但是没有办法区分由于未设置和在代码中设置的值。

Bra*_*ert 6

变量总是被设置为某种值。

如果您不将其设置为值,则会为您选择一个值。
具体来说,它将被设置为默认值。
(如果您不选择默认值,它将被设置为类型对象。)

my $abc;

say $abc.VAR.default.raku;
# Any
Run Code Online (Sandbox Code Playgroud)
my Int $def = 42;

say $def.VAR.default.raku;
# Int
Run Code Online (Sandbox Code Playgroud)
my $ghi is default(42) = 2;

say $ghi.VAR.default.raku;
# 42
Run Code Online (Sandbox Code Playgroud)

你所要求的并不是 Raku 真正支持的。

不过,您可能可以伪造一些接近的东西。
(每个实例Mu.new都是唯一的。)

sub is-not-set ( Mu $_ is raw ) {
  $_.self =:= $_.VAR.default
}

my $abc is default(Mu.new);
my $def is default(Mu.new) = Any;
my $ghi is default(Mu.new) = Mu.new;

say is-not-set $abc; # True
say is-not-set $def; # False
say is-not-set $ghi; # False
Run Code Online (Sandbox Code Playgroud)

问题是分配Nil也会将其设置为默认值。

$def = Nil;
say is-not-set $def; # True
Run Code Online (Sandbox Code Playgroud)

就像查找默认值并分配它一样。

$ghi = $ghi.VAR.default;
say is-not-set $ghi; # True
Run Code Online (Sandbox Code Playgroud)

我不认为你应该担心这些事情。

如果您真的需要在第一次分配给变量时发生某些事情,您可以执行以下操作:

my $abc := Proxy.new(
  # this FETCH only needs to return the default
  # as this Proxy gets replaced upon the first assignment
  FETCH => -> $ { Any },

  STORE => -> $, $value {
    # replace the Proxy with a new Scalar
    $abc := do { my $abc = $value };

    say 'first assignment just happened'
  },
);

say $abc;
# Any

$abc = 1;
# first assignment just happened

say $abc;
# 1

$abc = 2;

say $abc;
# 2
Run Code Online (Sandbox Code Playgroud)

do块就在那里,以便$abc.VAR.name返回$abc.
否则你可以只写$abc := my $ = $value.

  • 好吧,“总是设置为某个值”可能是 /sf/ask/4327274941/ 中的 OP 中的一些混乱之处具体来说,就是 had,并做出 jnthn 的推理,解释为什么 `(Type:U)` 不能很好地填充 gist 方法。我想知道是否有办法在文档中解决这个问题以明确这一点 (2认同)

wam*_*mba 5

我认为这两个值是相同的,但容器具有不同的类型约束

尝试

my Str $foo;
my  $bar = Str;

use Test;

cmp-ok $bar, &[===], $foo, 'The values are identical';
isa-ok $bar, Str;
isa-ok $foo, Str;
isa-ok $bar.VAR.of, Mu;
nok $bar.VAR.of.isa(Str), 'The container $bar is not of Str' ;
isa-ok $foo.VAR.of, Str;

done-testing();
Run Code Online (Sandbox Code Playgroud)
ok 1 - The values are identical
ok 2 - The object is-a 'Str'
ok 3 - The object is-a 'Str'
ok 4 - The object is-a 'Mu'
ok 5 - The container $bar is not of Str
ok 6 - The object is-a 'Str'
1..6
Run Code Online (Sandbox Code Playgroud)


Tyi*_*yil 2

my Str $barmy $bar = Str产生相同的结果,两者都是 Str 类型,但没有确定的值。Str是类型对象,而不是值。

.definedTrue如果您给出$bar一个确定的值,例如"Str"(请注意裸字周围的引号),则会返回。

  • “结果是一样的”:但事实并非如此。`我的Str $bar; $bar = 3` 错误,因为 `$bar` 被输入为 `Str`,但是 `my $bar = Str; $bar = 3` 不会,因为未输入 `$bar` (3认同)