天道酬勤,学无止境

为什么将 Perl 6 命名参数限制为一个确定的值使其成为必需值?(Why does constraining a Perl 6 named parameter to a definite value make it a required value?)

问题

考虑这些都采用单个命名参数的子例程。 命名参数应该是可选的,我没有看到任何可以说有例外的内容。

没有类型限制就没有问题; 命名参数不是必需的。 使用可以接受类型对象(无注释、 :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因为必须定义我想要的值。

从签名文档:

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

但是,我没有传递任何价值。 我认为这些约束只对作业有影响。 由于我没有明确提供要分配的值,因此我预计不会有任何分配也没有问题。 Rakudo 2017.10 并非如此。 这使我以各种令人讨厌的方式解决此问题。 这与我的问题有关 Perl 6 块是一个参数还是一个参数? 我试图区分零个和一个参数的情况。

我可以通过分配默认值来解决这个问题,但在某些情况下,没有有意义的默认值。 例如,一个Bool很容易,但是什么明确的Int适合呢? 无论它是什么,都会有一些神奇的价值,会使代码复杂化和分散注意力。 我已经用 Perl 6 has an Infinite 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();
回答1

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

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

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

上面,默认默认值通过参数的类型约束。 如果您使用:U:_类型的笑脸,情况也是如此。

但是,当您使用:D类型笑脸时,默认默认值不再匹配类型约束。 如果未选中,您将失去指定:D约束的好处。 例如,由于默认的默认类型对象会导致此例程的主体发生爆炸,从而期望参数为确定值。

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

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

回答2

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和必需的命名参数:

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

希望这可以帮助

回答3

我通过检查我真正想要的类型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();

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

回答4

这个答案:

  • 说明这种情况适用于所有参数和变量。

  • 解释为什么限制到一个确定的值会让 Raku/Rakudo 抱怨。

  • 为将可选参数与定值约束相结合提供了可靠的解决方案。

这种情况适用于所有:D约束参数和变量

为什么将 Raku 命名参数限制为一个确定值使其成为必需值?

这不仅仅是命名参数。 你的例子是:

sub quux ( Int:D :$quux ) {}
quux # "Parameter '$quux' ... must be an object instance ..."

但是对于可选的位置也是如此:

sub quux ( Int:D $quux? ) {}
quux # "Parameter '$quux' ... must be an object instance ..."

Raku 也需要一个:D变量的值:

my Int   $foo;   # Won't complain if you constrain to a plain Int
my Int:U $foo;   # Int:U is fine too
my Int:_ $foo;   # Still fine
my Int:D $foo; # "... type Int:D requires an initializer"

为什么限制到一个确定的值会让 Raku/Rakudo 抱怨

首先,除了 NativeCall,Raku/Rakudo 是内存安全的。 因此,虽然用户可以假装或认为没有分配/绑定到变量或参数的值,但实际上,如果用户代码可以访问它,则必须始终存在一个值。 所以每个变量/参数都必须有一个隐式的默认初始值,如果它没有明确的初始值,它将被初始化。


只要你不要求它施展魔法,Raku 就会悄悄地处理内存安全。 如果根本不指定类型,则默认初始值为Mu类型对象。 如果您指定IntInt:UInt:_等类型,则它是Int类型对象。 但是,如果您指定Int:D而不指定默认初始值,它就会放弃,因为它以与您相同的方式看待事物:

我可以通过分配一个默认值来解决这个问题,但是......什么明确的Int适合? 无论它是什么,都会有一些神奇的价值,会使代码复杂化和分散注意力。

Raku 认为如果没有您的帮助,这个问题将无法解决。 它认为选择某个任意确定的值,在一般情况下,无论选择什么启发式方法,都会导致很多错误。 所以它拒绝悄悄地处理这个问题。


在参数情况下,它会抛出一个可恢复的异常:

sub quux ( Int:D :$quux? ) { say 42 } # Does NOT display 42
quux;
CATCH { .resume }
say 99; # 99

Rakudo 拒绝将quux调用绑定到quux sub 并抛出异常。 这足以维持内存安全。 如果你选择继续,那么就由你决定吧。

在可变情况下,Rakudo 无法保持内存安全(假设它拒绝选择任意确定的值)并立即退出程序而不抛出异常:

my Int:D $quux; # "Error while compiling ... requires an initializer"
CATCH { .resume }
say 99; # Does NOT display 99

潜在的词汇歧义可能会导致人们对这种行为感到惊讶。 参数可以称为“可选”。 这意味着与该参数对应的参数是可选的,而不是参数本身或分配/绑定到该参数的值是可选的。

将可选参数与定值约束相结合的稳健解决方案

你可以:

  • 将默认值设置为用户不会传递的某个值;

  • 应用约束要么是该值,或者您希望应用其他一些约束。

布莱恩的解决方案是朝着这个方向迈出的一步。 这是相同解决方案的更清晰版本:

subset OptionalInt where Any:U | Int:D;

sub f ( OptionalInt :$f ) { say $f }

f( f => 5 );   # 5
f();           # (Any)
f( f => Any);  # (Any)
f( f => 'a' ); # expected OptionalInt but got Str ("a")

虽然是一个改进(更容易阅读代码、更快、更好的错误消息),但上述解决方案仍然存在一个弱点,即使用Any参数意外调用 sub f代码会表现得好像它没有传递参数一样。

为了消除这个弱点:

class NoArgPassed {}

subset OptionalInt where NoArgPassed | Int:D;

sub f ( OptionalInt :$f = NoArgPassed ) { say $f }

f( f => 5 );   # 5
f();           # (NoArgPassed)
f( f => Any);  # expected OptionalInt but got Any (Any)
f( f => 'a' ); # expected OptionalInt but got Str ("a")

受限制的 HTML

  • 允许的HTML标签:<a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • 自动断行和分段。
  • 网页和电子邮件地址自动转换为链接。

相关推荐
  • Dart中的命名参数和位置参数有什么区别?(What is the difference between named and positional parameters in Dart?)
    问题 Dart支持命名的可选参数和位置的可选参数。 两者之间有什么区别? 另外,如何判断是否实际指定了可选参数? 回答1 Dart有两种类型的可选参数: named和positional 。 在讨论差异之前,让我首先讨论相似之处。 Dart的可选参数是可选的,因为调用者在调用函数时不需要为参数指定值。 可选参数只能在任何必需参数之后声明。 可选参数可以具有默认值,当调用方未指定值时使用该默认值。 位置可选参数 [ ]包裹的参数是位置可选参数。 这是一个例子: getHttpUrl(String server, String path, [int port=80]) { // ... } 在上面的代码中, port是可选的,默认值为80 。 您可以调用带有或不带有第三​​个参数的getHttpUrl 。 getHttpUrl('example.com', '/index.html', 8080); // port == 8080 getHttpUrl('example.com', '/index.html'); // port == 80 您可以为一个函数指定多个位置参数: getHttpUrl(String server, String path, [int port=80, int numRetries=3]) { // ... } 可选参数是位置性的
  • 非静态成员作为非静态成员函数的默认参数(Nonstatic member as a default argument of a nonstatic member function)
    问题 struct X { X():mem(42){} void f(int param = mem) //ERROR { //do something } private: int mem; }; 任何人都可以给我一个为什么这在C ++中是非法的原因! 就是说,我知道这是一个错误,我知道错误的含义,我只是不明白为什么这是非法的! 回答1 您的代码(简体): struct X { int mem; void f(int param = mem); //ERROR }; 您要使用非静态成员数据作为成员函数参数的默认值。 想到的第一个问题是:默认值mem属于哪个特定的类实例? X x1 = {100}; //mem = 100 X x2 = {200}; //mem = 200 x1.f(); //param is 100 or 200? or something else? 您的答案可能是100因为在具有mem = 100的对象x1上调用了f() 。 如果是这样,则要求实现将f()实现为: void f(X* this, int param = this->mem); 反过来,这要求在初始化其他参数之前首先初始化第一个参数。 但是C ++标准没有指定函数参数的任何初始化顺序。 因此,这是不允许的。 出于同样的原因,C ++标准甚至不允许这样做: int f(int a, int b
  • 什么是rvalue,lvalue,xvalue,glvalue和prvalue?(What are rvalues, lvalues, xvalues, glvalues, and prvalues?)
    问题 在C ++ 03中,表达式是rvalue或lvalue 。 在C ++ 11中,表达式可以是: 右值左值值总值 prvalue 两个类别已变成五个类别。 这些新的表达类别是什么? 这些新类别与现有的右值和左值类别有何关系? C ++ 0x中的右值和左值类别是否与C ++ 03中的右值和左值类别相同? 为什么需要这些新类别? WG21众神只是在试图使我们仅仅是凡人吗? 回答1 我想这份文件可能只是一个简短的介绍:n3055 整个屠杀始于移动语义。 一旦我们有了可以移动且不能复制的表达式,突然容易掌握的规则就要求在可以移动的表达式之间以及在哪个方向上进行区分。 根据我对草案的猜测,r / l值的区别保持不变,只是在移动事物变得混乱的情况下。 他们需要吗? 如果我们希望放弃这些新功能,可能不会。 但是要允许更好的优化,我们可能应该接受它们。 引用n3055: 左值(之所以称为历史值,是因为左值可能出现在赋值表达式的左侧)表示函数或对象。 [示例:如果E是指针类型的表达式,那么*E是一个左值表达式,它引用E指向的对象或函数。 又例如,调用返回类型为左值引用的函数的结果为左值。] xvalue (“ eXpiring”值)也指对象,通常在其生命周期即将结束时(例如,可以移动其资源)。 xvalue是某些包含rvalue引用的表达式的结果。 [示例
  • 您最不喜欢自己的语言的五件事是什么? [关闭](What are five things you hate about your favorite language? [closed])
    问题 关闭。 这个问题是题外话。 它当前不接受答案。 十年前关闭。 已锁定。 该问题及其答案被锁定,因为该问题是题外话,但具有历史意义。 它目前不接受新的答案或互动。 最近在Stack Overflow上出现了一堆Perl讨厌的东西,所以我想把我的“您最讨厌的五种语言讨厌”问题带给Stack Overflow。 用您最喜欢的语言,告诉我您讨厌的五件事。 这些可能只是让您烦恼,承认设计缺陷,发现性能问题或任何其他类别的事情。 您只需要讨厌它,它就必须是您最喜欢的语言。 不要将其与另一种语言进行比较,也不要谈论您已经讨厌的语言。 不要以您喜欢的语言谈论您喜欢的事情。 我只是想听听您讨厌但可以容忍的事情,以便您可以使用所有其他内容,而且我想听听有关您希望其他人使用的语言的信息。 每当有人试图将自己喜欢的语言强加给我时,有时还是作为面试问题,我都会问这个问题。 如果某人找不到最讨厌的五样东西,那么他对它的倡导或使用它的巨额资金将不甚了解。 他没有在足够不同的情况下充分利用它。 他主张将其作为一种文化或宗教,这意味着如果我不选择他最喜欢的技术,那我就错了。 我不太在乎您使用哪种语言。 不想使用特定的语言? 那不要您经过尽职调查才能做出明智的选择,但仍然不使用它? 美好的。 有时候正确的答案是“您拥有一支强大的编程团队,拥有良好的实践和在Bar方面的丰富经验。改用Foo是愚蠢的。”
  • 过程编程和函数式编程之间有什么区别? [关闭](What is the difference between procedural programming and functional programming? [closed])
    问题 关门了。 这个问题是基于意见的。 它当前不接受答案。 想要改善这个问题吗? 更新问题,以便可以通过编辑此帖子以事实和引用的形式回答。 2年前关闭。 改善这个问题 我已经阅读了有关程序化编程和函数式编程的Wikipedia文章,但是我仍然有些困惑。 有人可以将其归结为核心吗? 回答1 函数式语言(理想情况下)允许您编写数学函数,即采用n个参数并返回值的函数。 如果执行程序,则根据需要对该功能进行逻辑评估。 1个 另一方面,过程语言执行一系列顺序步骤。 (有一种将顺序逻辑转换为功能逻辑的方法,称为连续传递样式。) 结果,一个纯功能的程序对于输入总是产生相同的值,并且评估的顺序没有明确定义。 这意味着很难用纯函数语言来建模诸如用户输入或随机值之类的不确定值。 1正如此答案中的所有其他内容一样,这是一个概括。 该属性在需要计算结果时而不是在调用结果的位置按顺序进行计算时被称为“惰性”。 并不是所有的函数语言实际上都是普遍懒惰的,懒惰也不限于函数式编程。 而是,这里给出的描述提供了一个“思想框架”,以考虑不同的编程风格,这些风格不是截然不同的类别,而是相反的想法。 回答2 基本上这两种风格,就像阴和阳。 一个是有组织的,而另一个则是混乱的。 在某些情况下,函数式编程是显而易见的选择,而在其他情况下,过程式编程是更好的选择。
  • 什么时候应该使用&调用Perl子例程?(When should I use the & to call a Perl subroutine?)
    问题 我听说人们不应该使用&来调用Perl子,即: function($a,$b,...); # opposed to &function($a,$b,...); 我知道其中一个参数列表是可选的,但是在某些情况下使用&合适,在某些情况下您绝对不应该使用它呢? 当省略&时,性能如何在这里发挥作用? 回答1 IMO,唯一有理由使用&是在获取或调用coderef时,例如: sub foo() { print "hi\n"; } my $x = \&foo; &$x(); 主要的时间,你可以使用它,你绝对不应该在大多数情况下,调用一个已具雏形,指定任何非默认调用行为子时。 我的意思是,某些原型允许重新解释参数列表,例如将@array和%hash规范转换为引用。 因此,潜艇将期望发生这些重新解释,并且除非您进行任何必要的长度以手工模仿它们,否则潜艇将获得与预期的输入完全不同的输入。 我认为主要是人们试图告诉您您仍在以Perl 4风格进行编写,而我们现在有了一个更干净,更好的东西,称为Perl 5。 至于性能,有各种方法Perl的优化子调用它&失败,与主要有常量内联的一个。 在&情况下,还有一种情况会带来性能上的好处:如果要转发使用foo(@_)的子调用。 使用&foo比foo(@_)无限快。 除非您通过分析明确确定需要微优化,否则我不建议您这样做。 回答2 我经常滥用&
  • 面向对象的Perl构造函数语法和命名参数(Object-Oriented Perl constructor syntax and named parameters)
    问题 我对Perl构造函数中发生的事情有些困惑。 我发现了这两个例子perldoc perlbot。 package Foo; #In Perl, the constructor is just a subroutine called new. sub new { #I don't get what this line does at all, but I always see it. Do I need it? my $type = shift; #I'm turning the array of inputs into a hash, called parameters. my %params = @_; #I'm making a new hash called $self to store my instance variables? my $self = {}; #I'm adding two values to the instance variables called "High" and "Low". #But I'm not sure how $params{'High'} has any meaning, since it was an #array, and I turned it into a hash. $self->{'High'} = $params{
  • 自定义类型传递给函数作为参数(Custom type passed to function as a parameter)
    问题 当我定义一个自定义类型时,基础类型的类型似乎对我是否可以按原样将其传递给函数还是需要对其进行转换有所不同。 问题是:为什么RuneFunc和StringMap有效,而Integer不起作用? https://play.golang.org/p/buKNkrg5y- package main type RuneFunc func(rune) rune type Integer int type StringMap map[string]string func main() { //m := make(StringMap) //mf(m) var i Integer = 5 nf(i) //var f func(rune) rune //ff(f) } func mf(i map[string]string) { } func ff(i func(rune)rune) { } func nf(i int) { } 在这里,当我使用Integer运行名为nf函数时,尽管int是基础类型,但它会抱怨。 但是,当我致电mf或ff他们成功运行。 回答1 Integer和int int和您的新类型Integer是2种不同的不同类型。 如果需要使用Integer则必须传递Integer类型的值。 如果您具有Integer值,则可以使用简单的类型转换使其成为int类型的值
  • Perl的哪些功能使其成为功能性编程语言?(Which features of Perl make it a functional programming language?)
    问题 受到一点启发:https://stackoverflow.com/questions/30977789/why-is-c-not-a-functional-programming-language 我发现:高阶Perl 这让我怀疑Perl是一种功能编程语言的说法。 现在,我意识到函数式编程是一种技术(非常类似于面向对象)。 但是,我找到了构成函数式编程语言的清单: 头等舱功能高阶函数词汇闭包模式匹配单项作业懒惰评估垃圾收集类型推断尾叫优化清单理解单调效应 现在,其中一些我已经非常熟悉: 例如,垃圾收集是Perl参考计数并在不再需要时释放内存。 词汇闭包甚至是常见问题解答的一部分:什么是闭包? -此处可能有更好的文章:http://www.perl.com/pub/2002/05/29/closure.html 但是我开始对其中的一些变得有点模糊-例如列表理解-我认为这是指map / grep ( List::Util and reduce ?) 我有人可以帮我填补这里的空白吗? Perl可以轻松完成上述哪一项操作(并且有一个简单的示例),并且有一些示例可以使它掉下来? 回答1 相关的有用的事情: Perl僧侣热衷于函数式编程 高阶Perl C2.com功能编程定义 头等舱功能 在计算机科学中,如果编程语言将函数视为一流的公民,那么它就具有一流的功能。 具体来说
  • 什么是 lambda,什么是示例实现?(What is a lambda and what is an example implementation?)
    问题 我对编程相当陌生,虽然阅读了大量的 lambda 概念,但这个概念不断出现,但我很难弄清楚它究竟是什么以及如何实现它会让我的编程生活变得更好。 首先,什么是 lambda,其次是如何实现的? 感谢所有发帖的人。 正如评论中所提到的,这是一个重复的,但是这里有很多很棒的答案,我想为社区保留它们,所以我将它变成了社区帖子。 这是另一个问题的链接: 什么是 lambda(函数)? 回答1 Lambda 很难捕捉,但是一旦你想象了它们,你就无法理解为什么之前没有得到它。 Lamdba 是匿名函数 Lambda 是普通函数,唯一的区别是你不给它们命名。 要理解这一点,您首先必须知道,当您创建一个函数时,代码存储在内存中只有计算机知道的地址。 所以当你做这样的事情时: function Foo () { /* your code here */ } 您真正要做的是将名称“Foo”绑定到内存中代码的地址。 现在,还有另一种访问地址的方法:引用(和指针,但让我们跳过这个讨厌的家伙) 好吧,一个 lambda 函数是一个没有名字的函数,所以它只能通过它的引用来访问。 你如何使用它们? 创建 lambda 函数时,您通常只打算使用它一次。 分步过程通常是: 创建函数获取参考将引用传递到将要使用的地方 最后,引用丢失,函数自动销毁。 典型的用例是回调函数。 您在一行中声明、创建和传递函数
  • 括号中的代码块在 JavaScript/jQuery 中是什么意思? [复制](What does a block of code in parentheses mean in JavaScript/jQuery? [duplicate])
    问题 这个问题在这里已经有了答案: 10 年前关闭。 可能的重复: 什么 (function($) {})(jQuery); 意思? 我已经看到很多具有以下语法的 jQuery 代码,但我并不真正理解它的含义。 它出现在这个答案和这个关于代码组织问题的答案中。 两者都谈论命名空间,所以我猜这就是它的作用。 var foo = (function () { var someVar; function someFunc() { return true; } })(); 这是为了命名空间,它是如何工作的? 有时在最后一组括号中有一个名称(命名空间?),有时没有。 两者有什么区别? 回答1 包装函数的()将匿名函数声明转换为函数表达式,然后可以立即使用表达式后面的()调用该表达式。 在这种情况下,外部()确实不是必需的,因为var foo =会将其转换为表达式。 此外, foo的值将是undefined因为函数调用不返回任何内容。 它可用于创建新的变量作用域,因为函数是在 javascript 中实现这一目标的唯一方法。 (Javascript 没有块作用域。) 所以someVar变量不能被外部作用域访问。 有时可能需要以受控方式访问它。 为此,您可以在该范围之外传递一个引用someVar 。 然后在函数调用退出后,它的执行上下文将保持不变
  • python不接受关键字参数(python not accept keyword arguments)
    问题 我试图使我的代码不接受关键字参数,就像某些bulitins也不接受关键字参数一样,但是,我无法这样做。 根据我有限的理解,这是我的想法:- def somefunc(a,b): print a,b somefunc(10,20) 输出: 10 20 现在,当我运行以下命令时(我知道这不是函数定义中的关键字参数,但是,看一下函数调用,它的语法似乎与调用接受关键字参数的函数时的语法相同) : somefunc(b=10,a=20) 输出: 20 10 我有2个问题: 查看函数调用somefunc(b=10,a=20)而不是函数定义,这似乎是对仅接受常规参数的函数的调用,或者是接受关键字参数的函数。 口译员如何区分两者? 是否可以将我们的任何函数转换为某种形式,以使其不像许多内置函数那样接受关键字参数? 为什么我要这样做呢? 我只是在检查是否可以执行此操作,以便在深入了解python时不会错过任何内容。 我不知道python是否允许。 回答1 广告1)如果正确命名,如somefunct(name=value, ...)那样被调用,Python会自动对其进行验证。 我不需要记住确切的标准参数顺序,也不必每月都在每次使用时查看文档,以验证它是否“神经质”,如果我记得一个带有很好的参数描述性名称的函数,并且将测试它们是否被接受通过Python。 相反,只能通过文档来验证所用参数的正确顺序
  • 斐波那契功能是如何记忆的?(How is this fibonacci-function memoized?)
    问题 斐波那契功能是通过什么机制记忆的? fib = (map fib' [0..] !!) where fib' 1 = 1 fib' 2 = 1 fib' n = fib (n-2) + fib (n-1) 与此相关的是,为什么没有这个版本呢? fib n = (map fib' [0..] !! n) where fib' 1 = 1 fib' 2 = 1 fib' n = fib (n-2) + fib (n-1) 回答1 Haskell中的评估机制是必要的:当需要一个值时,将对其进行计算,并准备好以防再次请求该值。 如果我们定义一些列表xs=[0..] ,然后要求它的第100个元素xs!!99 ,则列表中的第100个插槽将被“清除”,现在保留数字99 ,为下一次访问做好了准备。 这就是“遍历列表”的窍门。 在正常的双递归Fibonacci定义中, fib n = fib (n-1) + fib (n-2) ,该函数本身从顶部被调用两次,从而导致指数爆炸。 但是有了这个技巧,我们为中期结果列出了一个清单,然后“遍历清单”: fib n = (xs!!(n-1)) + (xs!!(n-2)) where xs = 0:1:map fib [2..] 诀窍是使该列表被创建,并使该列表在对fib调用之间不消失(通过垃圾回收)。 实现此目的的最简单方法是命名该列表。 “如果您命名
  • 在C ++中对布尔值使用按位运算符(Using bitwise operators for Booleans in C++)
    问题 是否有任何理由不对C ++中的“布尔”值使用按位运算符&,|和^? 有时我遇到两种情况之一,即我希望两个条件之一完全为真(XOR),因此我只是将^运算符放入条件表达式中。 有时我还希望评估条件的所有部分,无论结果是否正确(而不是短路),因此我使用&和|。 有时我还需要累积布尔值,并且&=和| =可能非常有用。 在执行此操作时,我有些挑剔,但是代码仍然比其他代码有意义且更简洁。 有没有理由不将这些用于bool? 是否有任何现代编译器为此带来不好的结果? 回答1 || 和&&是布尔运算符,并且保证内置运算符返回true或false 。 没有其他的。 | , &和^是按位运算符。 当您操作的数字的域仅是1和0时,它们是完全相同的,但是在布尔值不是严格地为1和0的情况下(例如C语言),您可能会遇到一些问题你不想要。 例如: BOOL two = 2; BOOL one = 1; BOOL and = two & one; //and = 0 BOOL cand = two && one; //cand = 1 但是,在C ++中,保证bool类型只能是true或false (它们分别隐式地转换为1和0 ),因此从这种立场开始不必担心,但事实是人们不习惯在代码中看到这样的事情是不这样做的一个很好的理由。 只需说b = b && x并完成它。 回答2 两个主要原因。 简而言之,请仔细考虑
  • POST多个参数[关闭](POST multiple parameters [closed])
    问题 关闭。 这个问题需要调试细节。 它目前不接受答案。 想改善这个问题吗? 更新问题,使其成为 Stack Overflow 的主题。 6年前关闭。 改进这个问题 我正在将 GET 更改为 POST。 目前我有 .jsp?id=a,b,c,d。 将其更改为帖子时,我仍然使用 id 参数 a,b,c,d 。 这对我不起作用。 我可以将逗号分隔的列表提交给 post 参数吗? 回答1 我错了还是大多数答案都离题了? 要准确回答您的问题,是的,您可以将逗号分隔的列表提交给 POST 参数。 老实说,我只是快速尝试了一个 PHP 脚本,但我不明白为什么 Java 的行为会有所不同。 POST 请求的一点是,您对语法的限制要少得多(无需转义 = & 等)。 因此,如果您更详细地解释什么“不起作用”,也许我们可以为您提供更多帮助。 回答2 您可以像选择表单输入一样执行此操作: url?param=value1&param=value2&param=value3 根据您的语言和库,您应该能够获得 param 的值数组。 例如,对于 asp.net mvc,我这样做是为了获取一个字符串数组: string[] values = Request.Form.GetValues("param"); 回答3 菲恩是对的。 用 url?param=value1&param=value2&param
  • 如何最好地确定参数是否未发送到JavaScript函数(How best to determine if an argument is not sent to the JavaScript function)
    问题 现在,我已经看到了两种确定参数是否已传递给JavaScript函数的方法。 我想知道一种方法是否比另一种更好,或者一种方法不好用? function Test(argument1, argument2) { if (Test.arguments.length == 1) argument2 = 'blah'; alert(argument2); } Test('test'); 或者 function Test(argument1, argument2) { argument2 = argument2 || 'blah'; alert(argument2); } Test('test'); 据我所知,它们都可以产生相同的结果,但是我在生产中只使用了第一个。 汤姆提到的另一种选择: function Test(argument1, argument2) { if(argument2 === null) { argument2 = 'blah'; } alert(argument2); } 根据Juan的评论,最好将Tom的建议更改为: function Test(argument1, argument2) { if(argument2 === undefined) { argument2 = 'blah'; } alert(argument2); } 回答1
  • 偏差在神经网络中的作用是什么? [关闭](What is the role of the bias in neural networks? [closed])
    问题 关闭。 此问题不符合堆栈溢出准则。 它当前不接受答案。 想改善这个问题吗? 更新问题,使它成为Stack Overflow的主题。 6个月前关闭。 改善这个问题 我知道梯度下降和反向传播算法。 我没有得到的是:什么时候使用偏见很重要,以及如何使用它? 例如,在映射AND函数时,当我使用2个输入和1个输出时,它不能给出正确的权重,但是,当我使用3个输入(其中1个是偏差)时,它给出正确的权重。 回答1 我认为偏见几乎总是有帮助的。 实际上,偏差值使您可以将激活功能向左或向右移动,这对于成功学习至关重要。 看一个简单的例子可能会有所帮助。 考虑以下无偏差的1输入1输出网络: 通过将输入(x)乘以权重(w 0 )并将结果传递给某种激活函数(例如S型函数)来计算网络的输出。 这是该网络针对w 0的各种值计算的函数: 改变权重w 0本质上改变了S形的“陡度”。 这很有用,但是如果您希望网络在x为2时输出0,该怎么办? 仅仅改变S型曲线的陡度是不能起作用的-您希望能够将整个曲线向右移动。 这正是偏见允许您执行的操作。 如果我们向该网络添加偏见,如下所示: ...然后网络的输出变为sig(w 0 * x + w 1 * 1.0)。 这是w 1的各种值的网络输出的样子: w 1的权重为-5时,曲线向右移动,这使我们拥有一个在x为2时输出0的网络。 回答2 只是加上我的两分钱。
  • 我和Perl中的local和有什么不一样?(What is the difference between my and local in Perl?)
    问题 我看到我试图调试的脚本都使用了它们,文献还不清楚。 有人可以为我揭开神秘面纱吗? 回答1 动态范围。 这是一个整洁的概念。 许多人不使用它,也不了解它。 基本上将my视为创建变量并将其锚定到{},即AKA范围的一个块中。 my $foo if (true); # $foo lives and dies within the if statement. 因此, my变量就是您习惯的变量。 而通过动态作用域,可以在任何地方声明$ var并在任何地方使用。 因此,使用local您基本上会暂停使用该全局变量,并使用“局部值”来使用它。 因此, local为一个临时变量创建了一个临时作用域。 $var = 4; print $var, "\n"; &hello; print $var, "\n"; # subroutines sub hello { local $var = 10; print $var, "\n"; &gogo; # calling subroutine gogo print $var, "\n"; } sub gogo { $var ++; } 这应该打印: 4 10 11 4 回答2 简短的答案是, my在词法范围内将变量标记为私有,而在动态范围内将local标记为私有。 更容易理解my ,因为这通常会创建一个局部变量。 创建了一个新变量
  • 如何在gcc中实现变量参数?(How are variable arguments implemented in gcc?)
    问题 int max(int n, ...) 我正在使用cdecl调用约定,在该约定中,被调用方返回后,调用方将清理变量。 我想知道宏va_end , va_start和va_arg工作? 调用方是否将参数数组的地址作为max的第二个参数传递? 回答1 如果您看一下C语言在堆栈上存储参数的方式,那么宏的工作方式应该变得清楚: Higher memory address Last parameter Penultimate parameter .... Second parameter Lower memory address First parameter StackPointer -> Return address (请注意,根据硬件的不同,堆栈指针可能向下一行,而较高和较低的位置可能会互换) 即使没有...参数类型,参数也总是像这样存储1 。 va_start宏仅设置指向第一个函数参数的指针,例如: void func (int a, ...) { // va_start char *p = (char *) &a + sizeof a; } 这使p指向第二个参数。 va_arg宏可以执行以下操作: void func (int a, ...) { // va_start char *p = (char *) &a + sizeof a; // va_arg int i1 =
  • Perl子例程参数(Perl subroutine arguments)
    问题 我最近在阅读有关Perl的文章,对Perl如何处理传递给子例程的参数有些困惑。 在Python,Java或PHP之类的语言中,函数定义采用以下形式(以伪代码表示): function myFunc(arg1, arg2) { // Do something with arg1 and arg2 here } 但是在Perl中,它只是: sub mySub { # @_ holds all arguments passed } 据我了解,这是唯一的方法。 如果我想限制调用方仅传递2个参数怎么办? 这不是Perl不允许的,而是其他语言(例如Python,C等)的可变数参数吗? 那在某个时候难道不是一个问题吗? 使用其他语言的所有默认参数编号检查如何? 在Perl中是否必须明确地做到这一点? 例如sub a_sub { if (@_ == 2) { # Continue function } else { return false } } 回答1 您要警惕Perl环境,因为它与您以前遇到的语言完全不同。 相信强类型和函数原型的人在这里会有所不同,但是我相信这样的限制很少有用。 C是否真的使您经常将错误数量的参数传递给函数有用? 在现代Perl中,最常见的做法是将@_的内容复制到词汇标量变量列表中,因此您经常会看到以 sub mysub { my ($p1, $p2) = @_;