这是 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
Run Code Online (Sandbox Code Playgroud)
我可以看到它[]表示一个数组文字,{}一个哈希文字。
我还可以看到它的(Any)行为类似于 nil - 在上面显示的布尔上下文中返回 false。
我觉得(Any)有趣。文档告诉我这Any只是 Raku 中的神类之一。但是()周围的括号Any告诉我什么?
Eli*_*sen 11
当您使用 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
Run Code Online (Sandbox Code Playgroud)
除了 lizmat 的出色回答之外,解释这里发生的事情可能也很重要。
当您说 时my $foo,您实际上是在说my Any $foo。1 而当您说 时my @foo,您隐含地说了一些更接近于my Any @foowhich 相同的内容my Array[Any] $foo(但在位置容器中)。这使您可以将任何内容放入数组中,因为它的类型是Any.
当您访问一个未定义的对象时,它会返回一个未定义的值——但该值仍然是类型化的。碰巧的是,默认情况下,类型是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)'
Run Code Online (Sandbox Code Playgroud)
正如 lizmat 在她的回答中指出的那样,(Type)是方法的默认表示,.gist由.say用于未定义的值。2
它们不返回的原因Nil是因为根据定义,每个调用它的方法都会Nil返回Nil(除了一些例外,比如Bool它返回的地方False)——它有点像 Objective-C 的nil. 但是一个未定义的类型对象仍然有用途:例如,你仍然可以调用它的方法,只要它们不访问属性。有时这可能是一个非常有用的属性,它实际上使您能够执行以下操作:
my Foo $foo .= new;
Run Code Online (Sandbox Code Playgroud)
哪个是语法糖
my Foo $foo;
$foo = $foo.new;
Run Code Online (Sandbox Code Playgroud)
$foo是一个未定义的类型对象,所以我们实际上仍然调用Foo.new.
有一个非常简单的答案。
Any是一个类。具体来说,它是每个其他类的默认基类。
在 Raku 中,您可以像传递实例一样传递类。
my $a = 1;
my $b = $a.WHAT;
say $b;
# (Int)
Run Code Online (Sandbox Code Playgroud)
问题是,如果您尝试将类用作实例,则会发生不好的事情。
say $b + 4;
# ERROR: … must be an object instance of type 'Int', not a type object of type 'Int'.
Run Code Online (Sandbox Code Playgroud)
当您使用 REPL 时,它会自动调用.gist并打印结果。
.gist 是为了让人类能够理解价值是什么。
那么为什么要在类名周围添加括号呢?
对我来说,这样做是为了告诉你它不是一个Str或其他一些实例。
say 'Str'; # say calls .gist
# Str
say 'abc'.WHAT;
# (Str)
say 'abc'.WHAT.^name;
# Str
say 'abc'.^name;
# Str
Run Code Online (Sandbox Code Playgroud)
除了其中之一之外,所有的都是Str类的实例。
(猜猜是哪一个。)
基本上,括号告诉您尝试将其用作实例是错误的。