Function if可以是一个适当的函数,而不是一个特殊的形式

Function if可以是一个适当的函数,而不是一个特殊的形式,function,lisp,functional-programming,special-form,Function,Lisp,Functional Programming,Special Form,我终于开始学习函数式语言(emacs lisp),它明确区分了函数和特殊形式,例如流控制 特殊形式不同于函数的根本/理论原因是什么?如果,是否有任何语言提供功能性的 感谢对于渴望求值,需要进行区分,具有惰性求值的语言(即Haskell)if等可以是函数 急切求值:在调用函数之前对函数的参数求值,并且只将结果传递给函数 惰性求值:当且仅当函数的参数被访问时才对其求值。如果函数是普通函数,则在调用if函数之前,将对其参数then表单和else表单进行求值,因为这是一条规则:求值所有参数以生成值,然后

我终于开始学习函数式语言(emacs lisp),它明确区分了函数和特殊形式,例如流控制

特殊形式不同于函数的根本/理论原因是什么?如果,是否有任何语言提供功能性的


感谢

对于渴望求值,需要进行区分,具有惰性求值的语言(即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