在Racket中,有两个名为add1
和sub1
的通用编号程序,分别相当于(curry + 1)
和(curryr - 1)
。
这些程序是否适合风格使用,或者它们是否具有某种优化效益?这些程序背后的历史是什么?
答案 0 :(得分:3)
历史?
我们需要及时回到1986年,当时讨论了修订后的计划修订报告。
丹·弗里德曼写道:在描述算术时,我会发现符号“1+”和“-1+” 有害。函数+用符号“+”表示 混淆那些试图理解原始递归的人 +的定义。纯粹出于教学原因,我希望看到 “add1”和“sub1”是可选的。我知道macscheme& PC-Scheme有 包括他们。我不喜欢同一个构造的多个名字, 但我们在报告中已经有一些例子。
在此处查看更多信息:
https://groups.csail.mit.edu/mac/ftpdir/scheme-mail/HTML/rrrs-1986/msg00246.html https://groups.csail.mit.edu/mac/ftpdir/scheme-mail/HTML/rrrs-1986/msg00251.html
事实证明,add1
这个名称没有进入最低标准,但有些(非最小)实现包括它(例如Chez Scheme)。
根据实践方案[1],Chez Scheme,Racket和Chicken Scheme的实施包括add1
作为标准。我相信还有其他实现:
[1] http://practical-scheme.net/wiliki/schemexref.cgi?add1
至于它的用途:它更方便(也更容易阅读)
(map add1 xs)
大于
(map (lambda (x) (+ x 1)) xs)
这些天的表现应该没有差别(但不要采取 我的话 - 做一个基准)。曾几何时,一个简单的编译器可能会 为第一个表达式生成更好的代码。一个体面的编译器应该产生 两个表达式的输出相同。
答案 1 :(得分:2)
根据Racket Docs 语法suger :
递增(加1)和递减(减1)在编程中有点常见。使用它们的名称旨在使阅读代码的人更容易一目了然地看到这两个操作中的哪一个。
效果:使用原生' +'是表现明智的最佳方式。 ' 通用算术运算'(+, - ,<,> etc ...)由JIT编译器内联 {{3} }:
内联fixnum和flonum算术运算是JIT编译器最重要的优点之一。例如,当+应用于两个参数时,生成的机器代码会测试两个参数是否为fixnums,如果是,则使用机器的指令添加数字(并检查溢出)。
性能差异非常小,很难从racket docs检测到:
JIT编译器在应用函数时递增地工作,但JIT编译器在编译过程时仅限制使用运行时信息,因为给定模块体或lambda抽象的代码只编译一次。 JIT的编译粒度是一个单独的过程体,不包括任何词法嵌套过程的主体。 JIT编译的开销通常很小,很难检测到。
为全局环境添加定义的一些缺点:内存使用,命名空间冲突,增加GE维护。
向全球环境添加定义的一些优点:可读性,易于维护,可重复使用的代码。