繁体   English   中英

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

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

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

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

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

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

put function 与say function 几乎相同,但它在表达式上调用了.Str function。 这会产生一个警告,因为您不能真正对 object 类型进行字符串化。 观察差异:

$ 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

有关详细信息,请参阅类和对象类型系统类型对象

除了 lizmat 的出色答案之外,解释这里发生的事情可能与此相关。

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

当您访问一个未定义的 object 时,它会返回一个未定义的值——但该值仍然是输入的。 只是碰巧默认情况下,类型是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

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

  my Foo $foo .= new;

哪个是语法糖

  my Foo $foo;
  $foo = $foo.new;

$foo是一个未定义的类型 object,所以我们实际上仍然调用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 的一个实例。
(猜猜是哪一个。)


基本上,括号会告诉您尝试将其用作实例是错误的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM