【问题标题】:Getting elisp to return a function as return value让elisp返回一个函数作为返回值
【发布时间】:2013-07-28 22:06:13
【问题描述】:

我正在尝试在 elisp 中创建一个返回另一个函数的函数。我看了一个类似问题的答案(how to return function in elisp),但不明白答案(我今天才刚刚开始学习 elisp,所以请原谅我的无知)。我认为一个更简单的例子会有所帮助。首先,考虑一个测试一个数是否能被 5 整除的函数:

(defun divisible-by-5 (x) 
  ;; tests whether a number is divsible by 5. 
  (setq remainder (% x 5))
  (if (= remainder 0) 1 0)
)

这很好用:

(divisible-by-5 25)
1

现在假设我想创建一个可以创建更多此类测试函数的函数——类似于:

(defun divisible-by-z (z)
  (lambda (z) 
  (setq remainder (% x z))
  (if (= remainder 0) 1 0))
 )

工作。例如,

(defun divisible-by-3 (divisible-by-z 3))
(divisible-by-3 4)

返回错误。我认为即使看到一个关于如何实现这种模式的 elisp 惯用示例也会有所帮助。

【问题讨论】:

    标签: elisp


    【解决方案1】:

    首先,确保您启用了lexical-binding。最简单的方法是评估当前缓冲区中的(setq lexical-binding t)。有关该主题的更多信息可以找到here

    您对divisible-by-z 的定义基本上是正确的,只是您的输入有误(将两个参数都命名为z;lambda 的参数应该是x)。此外,使用let 引入remainder 的绑定会更惯用 - setq 通常保留用于更改已经存在的绑定。结果如下:

    (defun divisible-by-z (z)
      (lambda (x)
        (let ((remainder (% x z)))
          (if (= remainder 0) 1 0))))
    

    您不能以您尝试过的方式使用defun 创建divisible-by-3 - 它期望新函数的参数列表位于您调用divisible-by-z 的位置。

    你可以创建一个全局的动态绑定

    (defvar divisible-by-3 (divisible-by-z 3))
    

    或本地的词法绑定

    (let ((divisible-by-3 (divisible-by-z 3)))
      ...)
    

    无论哪种方式,您都需要使用funcall 来调用该函数

    (funcall divisible-by-3 9) ; => 1
    

    当然,您也可以完全简单地跳过给它自己的名字

    (funcall (divisible-by-z 3) 10) ; => 0
    

    funcall 是必要的,因为 Emacs Lisp(基本上)是 Lisp-2,这意味着它可以将函数和值附加到给定符号。因此,当您将函数视为值(从函数返回一个或将一个作为参数传递给函数)时,您基本上必须告诉它查看该值“单元格”而不是通常的函数单元格。如果你搜索“Lisp-1 vs Lisp-2”,你会发现比你想知道的更多。

    【讨论】:

      【解决方案2】:

      一个可能的解决方案:

      (defun divisible-by-3 (x)
        (funcall (divisible-by-z 3) x))
      

      【讨论】:

        【解决方案3】:

        另一种(可能更简单)的方法是包含x 作为要传递给函数的变量:

        (defun divisible-by-z (x z) "
        Check if x is divisible by z.
        If so, return 0.
        If not, return the remainder."
           (if (% x z) (% x z) 0))
        

        因此:

        (divisible-by-z 5 2) --> 1
        (divisible-by-z 4 2) --> 0
        

        【讨论】:

          猜你喜欢
          • 2013-05-09
          • 2010-10-14
          • 1970-01-01
          • 2010-09-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-01-03
          相关资源
          最近更新 更多