当前位置: 首页 > 知识库问答 >
问题:

为什么将Perl 6命名参数约束为确定值会使其成为必需值?

明星剑
2023-03-14

考虑这些子例程,它们都采用一个命名参数。命名参数应该是可选的,我还没有看到任何东西说有例外。

没有类型约束就没有问题;命名参数不是必需的。使用可以接受类型对象的类型约束(无注释、:U、和)没有问题。

Parameter '$quux' of routine 'quux' must be an object instance of type 'Int', 
not a type object of type 'Int'.  Did you forget a '.new'?
  in sub quux at /Users/brian/Desktop/type.p6 line 16
  in block <unit> at /Users/brian/Desktop/type.p6 line 37

对于需要定义值(用:D注释)的类型约束,命名参数不再是可选的。也就是说,对于任何其他定义,我都不必提供值。对于:D,我必须提供一个值。我不想省略:d,因为我想要的值必须被定义。

从签名文档中:

通常,类型约束只检查传递的值是否为正确的类型。

但是,我没有传递任何值。我认为这些限制只对一项任务重要。因为我没有显式地提供要赋值的值,所以我希望不会有赋值,也不会有问题。拉库多2017年的情况并非如此。10。这让我以各种令人讨厌的方式来解决这个问题。这与我的问题有关,Perl 6块的参数是一个还是没有?我试图区分零参数和一参数情况。

我可以通过分配默认值来解决这个问题,但是在某些情况下,没有有意义的默认值。例如,一个Bool很容易,但是什么明确的Int适合呢?不管它是什么,都将是一些神奇的价值,会使代码复杂化和分散注意力。我已经用Perl 6有一个无限的Int做了这个,但是我逃脱了,因为Inf在这种情况下作为一个有效的值工作。

sub foo ( :$foo ) {
    put $foo.defined ?? 'foo defined' !! 'foo not defined';
    }

sub bar ( Int :$bar ) {
    put $bar.defined ?? 'bar defined' !! 'bar not defined';
    }

sub baz ( Int:U :$baz ) {
    put $baz.defined ?? 'baz defined' !! 'baz not defined';
    }

sub quux ( Int:D :$quux ) {
    put $quux.defined ?? 'quux defined' !! 'quux not defined';
    }

sub quack ( Int:_ :$quack ) {
    put $quack.defined ?? 'quack defined' !! 'quack not defined';
    }

foo();
foo( foo => 2 );

bar();
bar( bar => 2 );

baz();
baz( baz => Int );

quack();
quack( quack => 2 );

quux( quux => 2 );
quux();

共有3个答案

冉德元
2023-03-14

我通过检查类型Any或智能匹配来解决这一问题:

sub f ( :$f where { $^a.^name eq 'Any' or $^a ~~ Int:D } ) {
    put $f.defined ?? "f defined ($f)" !! 'f not defined';
    }

f( f => 5 );
f();

回答我最初的问题:所有参数都是必需的。这仅仅是他们如何获得价值的问题。它可以通过参数、显式默认值或隐式默认值(基于其类型约束)实现。

丁理
2023-03-14

FWIW,可选位置参数存在类似问题:

sub a(Int:D $number?) { ... }
a; # Parameter '$number' of routine 'a' must be an object instance of type 'Int', not a type object of type 'Int'.  Did you forget a '.new'

如果将类型对象指定为默认值,则会出现相同的问题:

sub a(Int:D $number = Int) { ... };
a; #  # Parameter '$number' of routine 'a' must be an object instance of type 'Int', not a type object of type 'Int'.  Did you forget a '.new'

恐怕这只是的结果:当应用于参数时,D约束:您必须指定一个定义的默认值,以便它在没有任何参数的情况下可以调用。

当然,另一种方法可以是使用多子和必需的命名参数:

multi sub a() { say "no foo named" }
multi sub a(Int:D :$foo!) { say "foo is an Int:D" }

希望这能有所帮助

东门新立
2023-03-14

所有参数总是有一些值,即使它们是可选的。我澄清了您在379678和b794a7中引用的文档。

可选参数具有作为显式或隐式类型约束的类型对象的默认值(对于例程,隐式约束为Any,对于块,隐式约束为Mu)。

sub (Int $a?, Num :$b) { say "\$a is ", $a; say "\$b is ", $b }()
# OUTPUT:
# $a is (Int)
# $b is (Num)

在上面,默认值传递参数上的类型约束。如果使用:U类型smileys,情况也是如此。

但是,当您使用: D类型笑脸时,默认缺省值不再匹配类型约束。如果不检查,您将失去指定: D约束的好处。例如,由于默认的默认类型对象会在这个例程的主体中引起爆炸,因此期望参数是确定的值。

sub (Int:D $a?, Num:D :$b) { say $a/$b }()

并回答指定:D是否应自动生成所需参数的名义问题。我对这个想法持-1观点,因为它引入了一种特殊情况,用户必须学会只保存一个输入字符(根据需要标记param的)。这样做也会产生一个不太有用的错误,它讨论的是算术或必需的参数,而不是实际的问题:默认的参数没有通过对参数的类型检查。

 类似资料:
  • 问题内容: 命名函数的返回参数有什么好处? 问题答案: 命名它们有一些好处: 它用作文档。 它们会自动声明并初始化为零值。 如果您有多个返回站点,则更改函数的返回值并不需要全部更改,因为它只会显示“ return”。 还有缺点,主要是很容易通过声明相同名称的变量来意外地遮盖它们。 有效的Go中有一个关于命名结果参数的部分: 可以给Go函数的返回或结果“参数”指定名称,并将其用作常规变量,就像传入参

  • 问题内容: 我们使用“从Java开始”方法来使用Metro 1.5堆栈创建JAX-WS 2.0 Web服务。当我们将诸如SoapUI的标准工具指向我们的一个Web服务时,它表明WebMethods的参数是可选的。生成的xsd显示minOccurs = 0。 我需要一种方法来使“从Java出发”方法中需要WebMethod参数(也许在xsd中为minOccurs = 1)。我认为这有一个Java注释

  • 问题内容: 为了运行ssh守护程序服务,必须在/etc/pam.d/sshd中将entry设置为可选,如Ubuntu 13.10 的官方示例中所述。 此项对于Ubuntu的早期版本是否可选?它甚至在Ubuntu 13.10之前存在吗? 什么是设置到的意思是,无论如何? 我的ssh配置在这方面的安全性要差得多吗? 问题答案: 用于在用户通过SSH,X或类似方式登录时设置进程的审核属性。然后,审核框架

  • 问题内容: 创建接口方法时,我们不能像在 java中 那样做: 相反,我注意到我们还需要给参数名称lile: 同样,接口实现者不需要具有与接口方法中相同的参数名称。 我在这里发现了有关c#的类似问题。他们提到了 命名参数的一种情况,但是我没有在Java中找到任何其他相关原因。 问题答案: 从技术角度来看,这是没有必要的。 我一直将其作为语法规范化和文档帮助。 这样有: 没有理由区分类和接口方法的语

  • 不是内置函数或关键字,但是如果函数名为,为什么我不能调用它呢? 调试控制台中没有错误消息,如果我将其重命名为all2,该函数就会工作。 这是代码:在chrome和IE10中测试

  • 问题内容: 就在今天,我需要一种在不同对象之间传递函数的方法。我很快了解到您不能直接在Java中做到这一点,但是您可以传递一个wht实例,该实例显然被称为“匿名内部类”,如下所示: 定义类: 使其成为一个实例: 并称之为: 很简单。但是我不明白的是为什么它被称为“匿名”。我不只是给它起名字MyCallback吗?命名的东西不能匿名,对吗?请避免对这个术语感到困惑。 问题答案: 不,您说的是MyCa