首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Emacs Lisp中的递归函数在评估自身时存在void变量错误

Emacs Lisp中的递归函数在评估自身时存在void变量错误
EN

Stack Overflow用户
提问于 2012-11-04 05:37:41
回答 2查看 472关注 0票数 0

我正在尝试定义一个递归函数balanced,它接受一个字符串,并且仅当字符串中的括号是对称的时才返回true。

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

代码语言:javascript
复制
  ;; 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交互模式,所以我使用Ctrl-J来计算上面的defun语句。

然后,当我尝试评估它时:

代码语言:javascript
复制
  (balanced "(balanced nil nil)")

我得到了一个void-variable错误:

代码语言:javascript
复制
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()

这个函数似乎不能识别它自己,我做错了什么?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-11-04 11:47:07

当您执行函数(balanced ...)时,它所做的是:

  1. ,它首先定义了两个全局变量,

  1. ,它定义了另外五个函数,

  1. ,它访问变量is-balanced.

步骤3.在(defun is-balanced (list stack) ... ))))结束后立即发生。

代码语言:javascript
复制
(defun balanced (expr)
    ...

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

但是您还没有定义这样的变量。您已经定义了一个同名的函数,但是您不能像访问Emacs Lisp中的变量一样访问函数对象。另请参见here。因为没有名为is-balanced的变量,所以会得到一条错误消息。

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

票数 3
EN

Stack Overflow用户

发布于 2012-11-04 07:42:20

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

不正确:

代码语言:javascript
复制
    (is-balanced (cdr list) (cdr stack))

对,是这样

代码语言:javascript
复制
    (t (is-balanced (cdr list) (cdr stack)))

之所以需要这样做,是因为最后一个表达式应该是else的情况。

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13213762

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档