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

时间:2020-05-19 06:55:50

标签: raku

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

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

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

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

鉴于$bar.WHICH == $abc.WHICH,但$bar.VAR.WHICH !== $abc.VAR.WHICH以及类似.defined的方法将各自返回false,是否有任何快速简便的方法来确定是否存在设定值?

我认为可以将其与默认值进行比较,但是没有办法区分是通过unset还是在代码中进行设置。

5 个答案:

答案 0 :(得分:6)

变量始终设置为某种值。

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

my $abc;

say $abc.VAR.default.raku;
# Any
my Int $def = 42;

say $def.VAR.default.raku;
# Int
my $ghi is default(42) = 2;

say $ghi.VAR.default.raku;
# 42

您要的不是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

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

$def = Nil;
say is-not-set $def; # True

将查找默认值并进行分配。

$ghi = $ghi.VAR.default;
say is-not-set $ghi; # True

我认为您不应该担心此类事情。

如果您确实确实需要在首次分配变量时发生某些事情,则可以执行以下操作:

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

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

答案 1 :(得分:5)

我认为这两个值是相同的,但是容器具有不同的type constraints

尝试

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();
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

答案 2 :(得分:4)

是一般性问题还是实施问题?如果是后者,也许(ab)使用角色是一种选择?

role isUnset {}; 
my Str $a = Str but isUnset; 
say $a ~~ isUnset; 

# meanwile
$a = 'set'; 
# ...
$a = Str;

# and then
say $a ~~ isUnset; # Now False

答案 3 :(得分:2)

my Str $barmy $bar = Str的结果相同,它们均为Str类型,但没有确定的值。 Str是类型对象,而不是值。

如果您给.defined一个确定的值,例如True(请注意裸字周围的引号),

$bar将返回"Str"

答案 4 :(得分:0)

您可以尝试为变量分配默认值,而不是保持未定义状态:

 my Str $bar is default("");

$bar仅在分配了该值类型后才为Str;如果通过分配Nil删除了它的值,它将再次默认为空字符串。实际上,变量的默认值是其类型对象,因此:

my Str $foo;
my $bar = Str;
say $foo eqv $bar
实际上,

将返回True。