关于函数的Perl6网站说
强制类型可以帮助您在例程中拥有特定类型,但可以接受更广泛的输入。调用例程时,参数将自动转换为较窄的类型。
sub double(Int(Cool) $x) {
2 * $x
}
say double '21'; # 42
say double Any; # Type check failed in binding $x; expected 'Cool' but got 'Any'
这里Int是参数将被强制的目标类型,Cool是例程接受作为输入的类型。
但潜艇的意义何在?$x
不就是一个Int
?为什么要限制调用者为参数实现Cool
?
这个例子让我倍感困惑,因为Int
已经很酷了。所以我做了一个示例,其中类型不共享层次结构:
class Foo { method foomethod { say 'foomethod' } }
class Bar {}
class Quux is Foo {
# class Quux { # compile error
method Bar { Bar.new }
}
sub foo(Bar(Foo) $c) {
say $c.WHAT; # (Bar)
# $c.foomethod # fails if uncommented: Method 'foomethod' not found for invocant of class 'Bar'
}
foo(Quux.new)
在这里,
foo
的调用者被限制提供一个可以转换为Bar
的Foo
,但是foo
甚至不能在$c
上调用Foo
的方法因为它的类型是Bar
。那么,为什么foo
首先会关心待强制类型是Foo
呢?
有人能解释一下吗?链接到适当的留档和规范的一部分也是值得赞赏的。我在那里找不到任何有用的东西。
我是不是漏了什么?我不是Perl 6的专家,但它的语法似乎允许一个人独立地指定什么输入类型是允许的,以及输入将如何呈现给函数。
限制允许的输入是有用的,因为这意味着当使用无意义的参数调用函数时,代码将导致错误,而不是静默(无用)类型转换。
我认为这两种类型不处于等级关系的例子没有意义。
它所做的是接受一个Cool的子类型的值,并尝试将其转换为Int。在这一点上,它是一个Int,无论它以前是什么。
所以呢
sub double ( Int(Cool) $n ) { $n * 2 }
实际上可以被认为是(我认为这就是它在Rakudo实际实现的方式)
# Int is a subtype of Cool otherwise it would be Any or Mu
proto sub double ( Cool $n ) {*}
# this has the interior parts that you write
multi sub double ( Int $n ) { $n * 2 }
# this is what the compiler writes for you
multi sub double ( Cool $n ) {
# calls the other multi since it is now an Int
samewith Int($n);
}
因此,它接受Int、Str、Rat、FatRat、Num、Array、Hash等中的任意一个,并在调用
say double ' 5 '; # 25
say double 2.5; # 4
say double [0,0,0]; # 6
say double { a => 0, b => 0 }; # 4
您可以将其限制为Cool而不是Any,因为所有Cool值本质上都需要提供对Int的强制。
(
:(Int(任何) $ )
可以缩短为仅仅:(Int() $ )
)
您可能这样做的原因是您需要它在sub中是一个
Int
,因为您正在调用其他代码,这些代码使用不同的类型执行不同的操作。
sub example ( Int(Cool) $n ) returns Int {
other-multi( $n ) * $n;
}
multi sub other-multi ( Int $ ) { 10 }
multi sub other-multi ( Any $ ) { 1 }
say example 5; # 50
say example 4.5; # 40
在这种特殊情况下,您可以将其作为其中一个来编写
sub example ( Cool $n ) returns Int {
other-multi( Int($n) ) * Int($n);
}
sub example ( Cool $n ) returns Int {
my $temp = Int($n);
other-multi( $temp ) * $temp;
}
sub example ( Cool $n is copy ) returns Int {
$n = Int($n);
other-multi( $n ) * $n;
}
没有一个比用签名来强迫你的更清楚。
通常,对于这样一个简单的函数,您可以使用其中的一个,它可能会做您想要的事情。
my &double = * * 2; # WhateverCode
my &double = * × 2; # ditto
my &double = { $_ * 2 }; # bare block
my &double = { $^n * 2 }; # block with positional placeholder
my &double = -> $n { $n * 2 }; # pointy block
my &double = sub ( $n ) { $n * 2 } # anon sub
my &double = anon sub double ( $n ) { $n * 2 } # anon sub with name
my &double = &infix:<*>.assuming(*,2); # curried
my &double = &infix:<*>.assuming(2);
sub double ( $n ) { $n * 2 } # same as :( Any $n )
更新今天回顾了这个答案,我得出结论,我完全误解了@musiKk的意思。这在@darch的问题和@musiKk的回答中表现得最为明显:
@达奇:或者你的问题是为什么人们更喜欢Int(酷)而不是Int(任何)?如果是这样的话,那就是要问的问题。
@这正是我的问题
回顾许多其他答案,我发现没有一个像我现在认为的那样解决了这个问题。
当然,我可能错了,所以我决定保持原来的问题不变,特别是保持标题不变,保持这个答案不变,而是写一个新的答案,解决@darch的重新表述。
我们可以宣布:
sub double (Int $x) { ... } # Accept only Int. (No coercion.)
那么这就行了:
double(42);
但是不幸的是,输入42
来回应这个:
double(prompt('')); # `prompt` returns the string the user types
导致double
调用失败,绑定$x时类型检查失败;应为Int,但得到Str(“42”)
,因为42
,虽然看起来像一个数字,但从技术上讲,它是一个类型为Str
的字符串,我们不要求强制。
我们可以在sub的签名中引入任意值的一揽子强制:
sub double (Int(Any) $x) { ... } # Take Any value. Coerce to an Int.
或:
sub double (Int() $x) { ... } # Same -- `Int()` coerces from Any.
现在,如果在双精度提示下键入42
(提示(“”))
123abc,强制将在运行时失败,并显示一条漂亮的错误消息:
Cannot convert string to number: trailing characters after number in '123⏏abc'
任何值的一揽子强制的一个问题是代码如下:
class City { ... } # City has no Int coercion
my City $city;
double($city);
运行时失败,消息为:“未找到类“City”发票的方法“Int”。
我们可以在无强制和任何价值的全面强制之间选择一个平衡点。
最好的强制类通常是Cool
类,因为Cool值可以很好地强制其他基本类型,或者生成一个很好的错误消息:
# Accept argument of type Cool or a subclass and coerce to Int:
sub double (Int(Cool) $x) { ... }
根据这一定义,如下:
double(42);
double(prompt(''));
尽可能完美地工作,并且:
double($city);
“绑定$x时类型检查失败;预期很酷,但得到了City(City)”,对于程序员来说,这在诊断上比“类'City'的发票找不到方法'Int'要好一点。
为什么Foo会关心被胁迫的类型首先是Foo?
希望现在很明显,将强制从type限制为Foo
的唯一原因是,这是一种期望成功强制为Bar
值的类型(或者,可能会因为友好消息而失败)。
有人能解释一下吗?链接到适当的留档和规范的一部分也是值得赞赏的。我在那里找不到任何有用的东西。
您最初引用的文档几乎就是最终用户文档的全部内容。希望现在一切都有意义,你们都准备好了。如果没有请评论,我们将从那里开始。
问题内容: 当每个人都可以使用jarsigner签名时,像Java的jars一样对代码进行签名有什么意义?它如何提供安全性? 问题答案: 签名JAR文件的重点是验证它是否已被篡改。对jar文件进行签名后,您可以验证该文件未被其他人修改。这样可以确保文件源自最初签名的人。如果有人修改了文件,则签名验证过程将失败。您可以查看本文,以获取有关如何使用公钥加密执行数字签名的更多详细信息。
我想知道为什么不使用这个明显简洁的表达呢?
我一直在做一些欧拉项目练习,以提高我的C语言知识。 我编写了以下函数: 这将在17毫秒内计算。 但是,如果我改变路线 自 计算在2毫秒内完成。我是否遗漏了< code>pow(int,int)的一些明显的实现细节,导致第一个表达式的计算速度如此之慢?
ENOENT中的是什么意思? 错误不应该是: 没有这样的文件或目录 只是被命名? 有什么故事或原因吗?
在中,是什么意思? 只是用命名吗? 有什么故事或原因吗?
问题内容: 我是Go的新手,在浏览其他一些线程时遇到了以下代码行: 含义是什么?它是否指定将在if条件中分配某些内容(因为err似乎正在发生这种情况)?我在Wiki上找不到这种语法的示例,并且我很好奇它的用途。 问题答案: 因为返回两个值,所以如果需要它们中的任何一个,都必须在某个地方接收这些值。该是一个占位符,基本的意思是“我不关心这个特殊的返回值。” 在这里,我们只关心检查错误,而无需对实际的