繁体   English   中英

Emacs中的递归函数Lisp在评估自身时具有void-variable错误

[英]Recursive function in Emacs Lisp has void-variable error upon evaluating itself

我试图定义一个递归函数balanced ,需要一个字符串,返回true只有在字符串中的括号是平衡的。

我写的elisp代码是基于我为Odersky为Coursera课程编写的一些Scala代码,它是一个音译。

  ;; check if expr (list of chars of some expression) is balanced
  (defun balanced (expr)
    (defvar lparen (string-to-char "("))
    (defvar rparen (string-to-char ")"))

    (defun is-open (c) (eq lparen c))
    (defun is-close (c) (eq rparen c))
    (defun is-empty (ls) (eq ls nil))
    (defun is-matching (l r) (and (is-open l) (is-close r)))

    (defun is-balanced (list stack)
      (cond ((is-empty list) (is-empty stack))

      ((is-open (car list))
       (is-balanced (cdr list) ;; 'push' open-paren onto stack
        (cons (car list) stack)))

      ((is-close (car list))

       (if (is-empty stack) nil
         (and 
          (is-balanced (cdr list) (cdr stack))
          (is-matching (car stack) (car list)))))

      (is-balanced (cdr list) (cdr stack))))
  is-balanced

我在lisp-interaction-mode中,所以我使用Ctrl-J来评估上面的defun语句。

然后,当我试图评估这个:

  (balanced "(balanced nil nil)")

我得到一个void-variable错误:

Debugger entered--Lisp error: (void-variable is-balanced)
    balanced("(balanced nil nil)")
    (progn (balanced "(balanced nil nil)"))
    eval((progn (balanced "(balanced nil nil)")) t)
    eval-last-sexp-1(t)
    eval-last-sexp(t)
    eval-print-last-sexp()
    call-interactively(eval-print-last-sexp nil nil)
    recursive-edit()
    debug(error (void-variable is-balanced))
    balanced("(balanced nil nil)")
    (progn (balanced "(balanced nil nil)"))
    eval((progn (balanced "(balanced nil nil)")) t)
    eval-last-sexp-1(t)
    eval-last-sexp(t)
    eval-print-last-sexp()
    call-interactively(eval-print-last-sexp nil nil)
    recursive-edit()

这个功能似乎没有认识到自己,我做错了什么?

当你执行你的功能(balanced ...) ,它的作用是:

  1. 它首先定义了两个全局变量
  2. 它定义了其他五个功能
  3. 它访问变量is-balanced

第3步发生在(defun is-balanced (list stack) ... ))))

(defun balanced (expr)
    ...

    (defun is-balanced (list stack)
      ...
      (is-balanced (cdr list) (cdr stack))))
  is-balanced ;; <= here!

但是你还没有定义这样的变量。 您已经定义了一个相同名称的函数 ,但是您无法访问函数对象,就好像它们是Emacs Lisp中的变量一样。 另见这里 由于没有名为is-balanced变量, is-balanced会收到错误消息。

(也就是说,对你的其余代码有很多批评。对于初学者来说,要注意通过defun s defun s,你每次调用都会重新定义你的is-*函数(balanced ...) 。这肯定不是你想要的。同样,你可能想要将defvar移动到函数体之外,因为它们定义全局变量。或者你的意思是使用(let ...)代替?如果你真的想要全球价值,然后(defconst...)可能更合适。)

问题是cond表达式的最后一个元素没有包含在(t ... )

不正确:

    (is-balanced (cdr list) (cdr stack))

正确

    (t (is-balanced (cdr list) (cdr stack)))

这需要的原因是最后一个表达式应该是else情况。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM