Raku 中的 (Any) 是什么意思 - 特别是 ()?

What is the meaning of (Any) in Raku - specifically the ()?

这是 Raku 的实验:

> my $x
(Any)
> my $y=1
1
> my @a=[1, 2]
[1 2]
> my %h=a=>'b'
{a => b}
> say "nil" unless $x
nil

我可以看到 [] 表示数组文字,{} 表示哈希文字。

我还可以看到 (Any) 的行为类似于 nil - 在上面显示的布尔上下文中返回 false。

我觉得 (Any) 很有趣。文档告诉我 Any 只是 Raku 中的一位神 类。但是 Any 周围的括号 () 告诉我什么?

当您使用 REPL 时,表达式的结果使用 say 显示。 say 函数调用表达式上的 .gist 函数。

Any 是类型对象。类型对象有一个 .gist 方法,可以在它们两边加上括号。

put函数与say函数几乎相同,只是它在表达式上调用了.Str函数。这会产生警告,因为您无法真正将类型对象字符串化。观察差异:

$ raku -e 'say Any'
(Any)

# raku -e 'put Any'
Use of uninitialized value of type Any in string context.
Methods .^name, .raku, .gist, or .say can be used to stringify it to something meaningful.
  in block <unit> at -e line 1

有关详细信息,请参阅 Classes and Objects, Type System, Type Objects

除了 lizmat 的出色回答之外,解释这里发生的事情可能也很重要。

当你说 my $foo 时,你实际上是在说 my Any $foo1 而当你说 my @foo 时,你实际上是在说 my Any $foo。说一些更接近 my Any @foo 的东西,它与 my Array[Any] $foo 相同(但在位置容器中)。这使您可以将任何内容放入数组中,因为它的类型是 Any

当您访问一个未定义的对象时,它 return 是一个未定义的值 — 但该值仍然是类型化的。恰好默认情况下,类型是Any。然而,我们可以改变一些事情,它可能会变得更清楚:

my Str $foo;
say $foo;    # a Str that's undefined, so '(Str)';
my $bar;     # implicitly typed Any
say $bar;    # an Any that's undefined, so '(Any)';

my Int @foo = 0, 1, 2;
say @foo[0];   # an Int defined as 0, so '0'
say @foo[1];   # an Int defined as 1, so '1'
say @foo[3];   # an Int that's undefined, so '(Int)'

正如 lizmat 在她的回答中指出的那样,(Type).gist 方法的默认表示,.say 将其用于未定义的值。 2

他们不 return Nil 的原因是因为根据定义,Nil returns Nil 对于调用它的每个方法(除了少数例外,例如 Bool,其中 return 是 False)——它有点像 Objective-C 的 nil。但是未定义的类型对象仍然有用途:例如,只要它们不访问属性,您仍然可以调用它的方法。有时这可能非常有用 属性,它实际上使您能够执行以下操作:

  my Foo $foo .= new;

这是

的语法糖
  my Foo $foo;
  $foo = $foo.new;

$foo是一个未定义的类型对象,所以我们实际上还是调用了Foo.new.


  1. 正如 raiph 在评论中正确指出的那样,我应该注意到这并不是 确切地 正在发生的事情,但从最终用户的角度来看,已经足够接近了没那么复杂。
  2. 人们总是可以覆盖它,我已经为我的一些 类 做到了,这些名字可疑地接近或相同于添加明确前缀的内置函数,这样我就不会混淆它们.

答案很简单。

Any 是一个 class。具体来说,它是每个其他 class.

的默认基数 class

在 Raku 中,您可以像传递实例一样传递 class。

my $a = 1;
my $b = $a.WHAT;

say $b;
# (Int)

问题是,如果您尝试将 class 当作一个实例来使用,就会发生不好的事情。

say $b + 4;
# ERROR: … must be an object instance of type 'Int', not a type object of type 'Int'.

当您使用 REPL 时,它会自动调用 .gist 并打印结果。

.gist 是为了让人类能够理解值是什么。

那么为什么要在 class 的名称周围添加括号?

我觉得这样做是为了告诉您它不是 Str 或其他实例。

say 'Str'; # say calls .gist
# Str

say 'abc'.WHAT;
# (Str)

say 'abc'.WHAT.^name;
# Str

say 'abc'.^name;
# Str

除其中之一外,所有这些都是 Str class.
的实例 (猜猜是哪一个。)


基本上 parens 告诉您尝试将其用作实例是错误的。