在Lisp中,+函数实际上有多少输入?

问题描述:

我对Lisp比较陌生,我想知道是否真的有一个“+”函数的上限。在Lisp中,+函数实际上有多少输入?

(我猜这适用于所有其他的算术功能“ - ”,“/”等)

是的,有一个上限,但确切的上限取决于实现。你保证能够通过至少50次,但这一切都取决于。如果你需要总结一个列表,你最好用(reduce #'+ list),这应该会给你一个比任何其他方法更好的可伸缩性。

Common Lisp HyperSpec有更多信息。

当涉及到值范围有两个不同的情况下,浮动和整数。浮游物本身受其尺寸的限制,并且从单浮游物变为双浮游物的实施方式会让我大吃一惊。使用整数和有理数,CL可以在fixnums和bignum之间无缝转换,因此限制是可用于实现的可用地址空间的函数。我怀疑对于复数(复杂整数和有理因素 - >如果需要的话去bignum;复杂浮点数 - >超出范围,或返回Inf或NaN)也是如此。

+0

这就是规格说明的内容,但是您是否知道实际执行限制的任何实现? – Marcin 2012-04-02 10:10:22

+2

@Marcin好吧,SBCL保证您在10^18区域内有一个CALL-ARGUMENTS-LIMIT,我期望传递更多的参数,那根本行不通。我没有任何其他的实现,但我确实记得使用APPLY而不是REDUCE时遇到问题的人阅读与“在数百个元素中”一样短的列表。 – Vatine 2012-04-02 10:14:43

+1

@Vatine我刚刚意识到我的标题和问题描述相互矛盾的意思。因为我认为你正在回答“+”函数的数值限制,你是否介意函数可能具有_inputs_的限制?对困惑感到抱歉! – Soyuz 2012-04-02 10:17:00

答案很简单,没有,虽然使用递归而不是尾递归一个贫穷的实施将有一个堆栈限制。

根据您的实现+可能会使用递归或直接函数调用来实现。

我不太了解Common Lisp,知道它指定了什么要求,但是大多数实现(如果它们使用递归)将使用尾递归并避免任何栈限制。

函数调用将能够作为列表访问参数,因此对可以处理的参数数量没有限制。

编辑:因为有人实际上给了一个Common Lisp引用,它显然应该是一个更好的答案,但我会认为当提供足够的参数时,任何好的实现都会自动应用(reduce #'+ arg-list)的等效。

+0

常见的Lisp通常不是尾递归。我有一种感觉,我已经读到,他们不允许进行尾部呼叫优化是有原因的(尽管我可能会想到这一点)。 – Marcin 2012-04-02 09:51:47

+1

此外,没有理由为什么实现会使用递归,因为'reduce'和'loop'的可用性。 – Marcin 2012-04-02 09:56:29

+2

@Marcin如果你调整你的优化变量(主要是“速度”高和“调试”低,但请参阅你的实现手册的具体细节),他们被允许进行尾部调用优化,大部分都是。 – Vatine 2012-04-02 09:57:43

Common Lisp已被定义为可以在各种硬件和软件系统上有效实现。例如Motorola 68000/20/30/40,各种Intel x86处理器,基于Lisp Machine堆栈的处理器,DEC VAX,RISC处理器,Cray等超级计算机等处理器。在80年代,有许多处理器系列竞争,包括为执行Lisp代码而开发的处理器。今天,我们仍然有几个处理器系列(x86,x86-64,ARM,SPARC,POWER,PowerPC ......)。

它也可以编译为C,Scheme或其他编程语言。它也可以编译为像CMUCL,CLISP或JVM/Java虚拟机的虚拟机(Java虚拟机似乎有254个参数的限制)。

例如,Common Lisp编译器可能会将Lisp代码编译为直接C代码。因此,尽可能多地重用C编译器的函数是很好的。特别是从C调用Lisp更容易。

C/C++有上限值,也:

Maximum number of parameters in function declaration

以上给出像127(C)数字和256的C++。所以对于Lisp to C编译器来说,这可能是限制。否则,Lisp代码不会使用C函数调用。

第一个这样的编译器KCL(京都Common Lisp的,后来这个实施演变成GCL/GNU通用Lisp和ECL /可嵌入的Common Lisp)具有LispWorks/Mac OS X上的一个64的CALL-ARGUMENTS-LIMIT

甲64位实施例如CALL-ARGUMENTS-LIMIT的值为2047。

CALL-ARGUMENTS-LIMIT应不小于50 Common Lisp中,列表处理

因此并调用参数是不相关的。如果你想处理列表,你必须使用列表处理工具(LIST,MAPCAR,APPEND,REDUCE,...)。 Common Lisp提供了一种使用参数&REST作为列表访问参数的机制。但通常应该避免这样做,因为它可能会导致函数调用开销,因为参数列表需要一致。

Clojure中提供一个Lisp在这里可以实际上具有参数的函数的无限数量的一个例子,通过使用延迟序列:

; infinite lazy sequence of natural numbers 
(def naturals (iterate inc 1)) 

(take 10 naturals) 
=> (1 2 3 4 5 6 7 8 9 10) 

; add up all the natural numbers 
(apply + naturals) 
=> ...... [doesn't terminate] 

不是特别有用,当然.....

+0

这个例子并没有说服我。 APPLY被两个参数调用。用无穷参数调用这个+是不明确的。可能APPLY忙BEFORE +被无限参数调用。以@jwinandy为例,显示Clojure以8192个参数“挂起”,我怀疑这里会发生同样的情况...... – 2015-01-07 08:15:59

这取决于实施。 “我建议LISP用户花5分钟时间来测试他们的平台”。

对于Clojure的

(defn find-max-n [n] 
    (try 
    (eval (concat (list +) (take n (repeat 1)))) 
    (println "more than" n) 
    ; return n if something goes wrong 
    (catch Exception e n)) 
    (recur (* n 2))) 


(find-max-n 1) 

它不会终止,它挂在8192给我的设置。

more than 1 
more than 2 
more than 4 
more than 8 
more than 16 
more than 32 
more than 64 
more than 128 
more than 256 
more than 512 
more than 1024 
more than 2048 
more than 4096 
more than 8192