0

我正在尝试定义一个递归函数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)")

我收到一个无效变量错误:

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()

该功能似乎无法识别自己,我做错了什么?

4

2 回答 2

3

当你执行你的函数(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,您会收到一条错误消息。

(也就是说,对于您的代码的其余部分有很多需要批评的地方。对于初学者,请注意,通过将defuns 包含在s 中,您每次调用defuns 时都在重新定义您的is-*函数。那肯定不是您的想要。类似地,您可能希望将 defvar 移到函数体之外,因为它们定义了全局变量。或者您的意思是要改用?如果您真的想要全局值,那么可能更合适。)(balanced ...)(let ...)(defconst...)

于 2012-11-04T03:47:07.047 回答
-1

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

不正确:

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

正确的

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

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

于 2012-11-03T23:42:20.093 回答