Function if可以是一个适当的函数,而不是一个特殊的形式
我终于开始学习函数式语言(emacs lisp),它明确区分了函数和特殊形式,例如流控制 特殊形式不同于函数的根本/理论原因是什么?如果,是否有任何语言提供功能性的Function if可以是一个适当的函数,而不是一个特殊的形式,function,lisp,functional-programming,special-form,Function,Lisp,Functional Programming,Special Form,我终于开始学习函数式语言(emacs lisp),它明确区分了函数和特殊形式,例如流控制 特殊形式不同于函数的根本/理论原因是什么?如果,是否有任何语言提供功能性的 感谢对于渴望求值,需要进行区分,具有惰性求值的语言(即Haskell)if等可以是函数 急切求值:在调用函数之前对函数的参数求值,并且只将结果传递给函数 惰性求值:当且仅当函数的参数被访问时才对其求值。如果函数是普通函数,则在调用if函数之前,将对其参数then表单和else表单进行求值,因为这是一条规则:求值所有参数以生成值,然后
感谢对于渴望求值,需要进行区分,具有惰性求值的语言(即Haskell)if等可以是函数
急切求值:在调用函数之前对函数的参数求值,并且只将结果传递给函数
惰性求值:当且仅当函数的参数被访问时才对其求值。如果函数是普通函数,则在调用if
函数之前,将对其参数then表单和else表单进行求值,因为这是一条规则:求值所有参数以生成值,然后将该值序列作为参数提供给列表中第一个符号指定的函数
相反,使用if
时,您要做的是精确计算then表单和else表单中的一个,而不是同时计算这两个表单。为了抑制对其中一个的求值,您需要一个宏或一个宏。简短回答:否
Long(er)答案:(if…)要求您控制参数的求值顺序。作为一种渴望的语言,Lisp无法在函数中实现这一点
解决方法:在宏中执行此操作:
(defmacro _if (cnd true false)
(let ( (gcond (gensym))
(gresp (gensym)))
`(let ( (,gcond ,cnd) ;`#quotes
(,gresp nil))
(and ,gcond (setf ,gresp (multiple-value-list ,true)))
(and (not ,gcond) (setf ,gresp (multiple-value-list ,false)))
(values-list ,gresp))))
例如:
[dsm@localhost:~]$ clisp -q
[1]> (defmacro _if (cnd true false)
(let ( (gcond (gensym))
(gresp (gensym)))
`(let ( (,gcond ,cnd) ;`#quotes
(,gresp nil))
(and ,gcond (setf ,gresp (multiple-value-list ,true)))
(and (not ,gcond) (setf ,gresp (multiple-value-list ,false)))
(values-list ,gresp))))
_IF
[2]> (_if (= 1 1) (+ 2 3) "bar")
5
[3]> (_if (= 1 2) (+ 2 3) "bar")
"bar"
[4]>
完整性:例如,该语言中没有特殊形式,if
是一个原始函数,而Pico受Scheme的启发,默认情况下具有急切的求值
在这个计划中,你可以写
(define (true t f)
(t))
(define (false t f)
(f))
(define (function_if c t e)
(c t e))
然后
(function_if true (lambda () 'true) (lambda () 'false))
==> true
在Pico中实现这一点的原因是,您可以定义函数参数,这些参数接受“自动”延迟的函数参数。这意味着您不必自己在lambdas内部进行包装。因此,Pico具有急切的求值功能,但在需要时具有惰性求值功能,从而绕过了对特殊表单的需求
因此,在带有函数参数的Scheme语法中,可以将布尔编码为:
(define (true (t) (f))
(t))
(define (false (t) (f))
(f))
然后,如果函数变为:
(define (function_if c (t) (e))
(c (t) (e)))
及
作为另一个示例,函数和
的定义是(define(和p(q))(p(q)false))
类似地,您可以定义或,不,而,用于。。。作为函数,使用上述布尔编码。在Emacs Lisp和Common Lisp等语言中,特殊形式是内置的语言构造。它们具有正常函数调用的不同求值规则。对于普通函数调用,将计算所有参数。因此,您不能将IF作为普通函数编写—条件决定要计算哪个子句。此外,通常您无法编写自己的特殊表单-在通用Lisp中,没有用于定义特殊表单的语言构造(虽然个别实现必须以某种方式实现了现有的表达式。这导致了宏。使用宏,您可以编写将一个表达式转换为另一个表达式的语法转换。要能够将IF作为宏编写,您需要有另一个条件形式,可用于转换的代码。Lisp提供了condi假设COND是这样一个基本构造,那么您可以将IF扩展为COND的用法
MY-IF作为公共Lisp中的宏:
(defmacro my-if (condition true-clause false-clause)
`(cond (,condition ,true-clause)
(t ,false-clause)))
所以
扩展到
(cond ((foo-p) 'one)
(t 'two))
在Scala中,可以使用按名称调用参数对if
进行建模,并进行正确的副作用评估
def If[A](cond : Boolean, truePart : => A, falsePart : => A) = if (cond) truePart else falsePart
这些特性也可以用来对很多函数建模。IF可以是函数式语言中的一个函数,具有名称调用语义(惰性计算),如Lambda演算或Algol。事实上,我认为,这是两者之间关系的核心,是计算的等效基础。然而,在有副作用的语言中(如变量赋值)它没有多大用处,因为事情发生的时候很重要。这是一个相关的问题:顺便说一句——虽然emacs lisp很有趣,因为你可以用它来操作emacs,但它随着语言的发展已经过时了。你可能想玩一些更现代的东西,比如scheme。@troelskn:你应该把elisp称为“蹩脚”而不是“旧”.GNU Emacs Lisp(1985:)比Scheme(1975:)年轻约10年。我认为在答案中发布工作代码会有所帮助。不仅代码的语法被破坏,逻辑也被破坏。逻辑没有缺陷。(和…)和(或…)已经懒惰。语法被破坏了。为什么(_ift nil 3)返回3?为什么((让((cond nil))返回3(\u if cond t nil))返回t?对我来说,您的或/和逻辑似乎根本不起作用。(\u if t nil'false)返回false而不是NIL。一个基本的IF不起作用,我会说是no-IF。好吧,我在Scala中从未做过任何事情,所以我不知道任何细节。不过,我希望必须指定参数是否是惰性计算的——或者按名称调用是否有其他语义?如果是,如果可以在纯引用旁边提供链接,我会非常感谢。我认为基本属性是纯功能性的:在纯功能性语言中,或者在只使用纯函数(返回值但没有副作用的函数)的代码中,if
可以是函数。Haskell的惰性求值对于它的功能性是必要的。嗯,我总是将纯函数与“纯函数式”且“不可能有副作用”(除了I/O部分…)。我从来没有想到纯函数式语言需要惰性评估。好吧,这只是我编程地图上的另一个空白……不知何故,我开始考虑放弃所有这些问题。
(cond ((foo-p) 'one)
(t 'two))
def If[A](cond : Boolean, truePart : => A, falsePart : => A) = if (cond) truePart else falsePart