我故意避免使用术语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还是在代码中进行设置。
答案 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 $bar
和my $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。