Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Lisp “if”如何计算它的所有参数?_Lisp - Fatal编程技术网

Lisp “if”如何计算它的所有参数?

Lisp “if”如何计算它的所有参数?,lisp,Lisp,我正在努力深入地学习和理解Lisp编程语言。函数+按应用程序顺序计算其参数: (+ 1 (+ 1 2)) 将对(+1 2)进行求值,然后对(+1 3)进行求值,但if功能的工作方式不同: (if (> 1 2) (not-defined 1 2) 1) 由于未计算表单(未定义1 2),因此程序不会中断 相同的语法如何导致不同的参数计算?if函数是如何定义的,这样它的参数就不会被计算的?这些参数不会像函数那样被计算,因为if是一个特殊的运算符。特殊运算符可以以任意方式进行计算,这就是为什

我正在努力深入地学习和理解Lisp编程语言。函数
+
按应用程序顺序计算其参数:

(+ 1 (+ 1 2))
将对
(+1 2)
进行求值,然后对
(+1 3)
进行求值,但
if
功能的工作方式不同:

(if (> 1 2) (not-defined 1 2) 1)
由于未计算表单
(未定义1 2)
,因此程序不会中断


相同的语法如何导致不同的参数计算?
if
函数是如何定义的,这样它的参数就不会被计算的?

这些参数不会像函数那样被计算,因为
if
是一个特殊的运算符。特殊运算符可以以任意方式进行计算,这就是为什么它们被称为特殊运算符

考虑例如

(if (not (= x 0))
    (/ y x))

如果总是计算除法,则可能会有一个明显不是故意的零除法错误。

如果不是函数,则它是一种特殊形式。如果您想自己实现类似的功能,可以通过定义宏而不是函数来实现


这个答案适用于普通的Lisp,但对于大多数其他Lisp可能都是一样的(尽管在一些
if
中可能是宏而不是特殊形式)。

这样做没有任何意义。示例:
(if(ask-user-should-i-quit)(quit)(continue))
。即使用户不想退出,也应该退出吗

如果
不是Lisp中的函数。它是一个特殊的内置操作符。Lisp是几个内置的特殊操作符。请参阅:。这些不是函数。

是函数,不是普通函数

这意味着在调用与
第一个
元素关联的函数之前,对中的
rest
元素求值的正常规则是不适用的(因为它类似于)

在编译器和/或解释器中实现这一点的方式是查看复合形式,并根据以下内容决定如何处理它:

  • 如果它是一个特殊的操作者,它做它特殊的事情
  • 如果是a,则其宏函数得到整个形式
  • 否则,它将被视为一个函数-即使没有定义函数
请注意,某些特殊窗体可以定义为扩展到其他特殊窗体的宏,但某些特殊窗体实际上必须存在

例如,可以根据以下方面定义
if

反之亦然(更复杂-实际上,
cond
是一个宏,通常扩展为一系列
if
s)

请注意,系统提供的宏和特殊运算符之间的区别在技术上清晰明了(请参见和),但在意识形态上却模糊不清

一个实现可以自由实现一个公共Lisp特殊操作符 作为一个宏。实现可以自由实现任何宏运算符 作为特殊运算符,但仅当 还提供了宏


Lisp语法是规则的,比其他语言更规则,但它仍然不是完全规则的:例如在

(let ((x 0))
   x)
let
不是函数名,
((x 0))
是一种不错的形式,其中在第一个位置使用了非lambda形式的列表

有相当多的“特殊情况”(当然仍然比其他语言少得多),其中没有遵循每个列表作为函数调用的一般规则,
if
就是其中之一。Common Lisp有很多“特殊形式”(因为绝对最小不是重点),但您可以使用scheme方言中的五种形式来摆脱它:
if
progn
quote
lambda
set(如果需要宏,则为六个)

虽然Lisp的语法并不完全一致,但是代码的底层表示法(仅列表和原子)是相当一致的,表示法的一致性和简单性是元编程(宏)的便利之处

“Lisp没有语法”是一个有一定道理的语句,但它也是“Lisp有两个语法”的语句:一个语法是使用
读取器
将字符流转换为s表达式,另一个语法是使用编译器/计算器将s表达式转换为可执行代码

Lisp没有语法也是事实,因为这两个级别都不是固定的。与其他编程语言不同,您可以自定义第一步(使用读卡器宏)和第二步(使用宏)。

很好地回答了这个问题,但我认为有几个更一般的方面值得一提。正如这个答案和其他人所指出的,
if
,作为一个特殊的操作符被内置到语言中,因为它实际上是一种原语。最重要的是,
如果
不是一个函数

这就是说,
if
的功能可以通过使用函数和普通函数调用来实现,其中所有参数都是经过计算的。因此,条件语句可以在中实现,族中的语言在某种程度上是基于条件语句的,但它没有条件运算符

在lambda演算中,可以将true和false定义为两个参数的函数。参数被假定为函数,true调用其第一个参数,false调用第二个参数。(这是一个微小的变化,只返回其第一个或第二个参数。)

(这显然与Common Lisp中的布尔值不同,
nil
为false,其他任何值均为true。)但这样做的好处是,我们可以使用布尔值调用两个函数中的一个,具体取决于布尔值是true还是false。考虑常见的LISP形式:

(if some-condition
  then-part
  else-part)
如果我们使用上面定义的布尔值,那么计算
某些条件将产生
true
true = λ[x y].(x) false = λ[x y].(y)
(if some-condition
  then-part
  else-part)
(lambda () then-part)
(lambda () else-part)
(defconstant true
  (lambda (x y)
    (declare (ignore y))
    (funcall x)))

(defconstant false
  (lambda (x y)
    (declare (ignore x))
    (funcall y)))

(defmacro new-if (test then &optional else)
  `(funcall ,test
            (lambda () ,then)
            (lambda () ,else)))
(new-if (member 'a '(1 2 3))
  (print "it's a member")
  (print "it's not a member"))))
(FUNCALL (MEMBER 'A '(1 2 3))                     ; assuming MEMBER were rewritten 
         (LAMBDA () (PRINT "it's a member"))      ; to return `true` or `false`
         (LAMBDA () (PRINT "it's not a member")))