这是 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 @foo
which 相同的内容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
类的实例。
(猜猜是哪一个。)
基本上,括号告诉您尝试将其用作实例是错误的。
归档时间: |
|
查看次数: |
360 次 |
最近记录: |