首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >调整文本: Lisp嵌套超过``max lisp-eval-depth

调整文本: Lisp嵌套超过``max lisp-eval-depth
EN

Stack Overflow用户
提问于 2012-06-14 10:54:41
回答 5查看 524关注 0票数 1

程序应该重新格式化字符串,如下所示。

示例:(game-print‘(这是一个句子。那这个呢?可能。))

这是一个句子。那这个呢?可能吧。

但是有些地方不对劲( Lisp嵌套超过了‘`max lisp-eval-don),我不知道为什么。这段代码实际上来自于第97页的“lisp的土地”一书。原始代码是用普通的lisp编写的。我想用elisp重写它。two text中的最后两个参数表示队长和文字。

代码语言:javascript
复制
(defun tweak-text (lst caps lit)
  (when lst
    (let ((item (car lst))
          (rest (cdr lst)))
      (cond ((eql item ?\ ) (cons item (tweak-text rest caps lit)))
            ((member item '(?\! ?\? ?\.)) (cons item (tweak-text rest t lit)))
            ((eql item ?\") (tweak-text rest caps (not lit)))
            (lit (cons item (tweak-text rest nil lit)))
            (caps (cons (upcase item) (tweak-text rest nil lit)))
            (t (cons (downcase item) (tweak-text rest nil nil)))))))

(defun game-print (lst)
  (print (coerce (tweak-text (coerce (prin1-to-string lst) 'list) t nil) 'string)))

(game-print '(not only does this sentence have a "comma," it also mentions the "iPad."))

用通用lisp编写的原始代码。

代码语言:javascript
复制
(defun tweak-text (lst caps lit)
  (when lst
    (let ((item (car lst))
          (rest (cdr lst)))
      (cond ((eql item #\space) (cons item (tweak-text rest caps lit)))
            ((member item '(#\! #\? #\.)) (cons item (tweak-text rest t lit)))
            ((eql item #\") (tweak-text rest caps (not lit)))
            (lit (cons item (tweak-text rest nil lit)))
            (caps (cons (char-upcase item) (tweak-text rest nil lit)))
            (t (cons (char-downcase item) (tweak-text rest nil nil)))))))

(defun game-print (lst)
    (princ (coerce (tweak-text (coerce (string-trim "() " (prin1-to-string lst)) 'list) t nil) 'string))
    (fresh-line))
EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2012-06-14 11:30:54

在调整文本中递归时,您确实达到了‘max-lisp-eval- when’的限制。我看不出代码的方式有什么问题(我没有检查它是否在做你想要做的事情)。

您可以配置/提高'max-lisp-eval-depth‘限制。该变量的文档指出,只要您确信不会遇到堆栈空间耗尽的情况,就可以引发它。在我的机器上,这个限制被保守地设置为541。将其提高到600可以使上面的函数定义在您作为示例给出的输入上工作。

票数 1
EN

Stack Overflow用户

发布于 2012-06-14 13:07:09

在这两种情况下,都有非终端递归,因此使用O(length(lst))堆栈空间。显然,系统可能会限制您可以使用的堆栈空间,而在emacs中确实达到了这个限制。(现在在emacs中,您可以通过更改max-lisp-eval-lisp来增加限制,但这并不能解决根本问题)。

解决方案是使用迭代而不是递归。

但首先,在emacs中编写:

代码语言:javascript
复制
(defun character (x)
  "common-lisp: return the character designated by X."
  (etypecase x
    (integer x)
    (string (aref x 0))
    (symbol (aref (symbol-name x) 0))))

(defun string-trim (character-bag string-designator)
  "common-lisp: returns a substring of string, with all characters in \
character-bag stripped off the beginning and end."
  (unless (sequencep character-bag)
    (signal 'type-error  "expected a sequence for `character-bag'."))
  (let* ((string (string* string-designator))
         (margin (format "[%s]*" (regexp-quote
                                  (if (stringp character-bag)
                                      character-bag
                                      (map 'string 'identity character-bag)))))
         (trimer (format "\\`%s\\(\\(.\\|\n\\)*?\\)%s\\'" margin margin)))
    (replace-regexp-in-string  trimer "\\1" string)))

(require 'cl)

因此您可以为CL和elisp编写单个函数:

代码语言:javascript
复制
(defun tweak-text (list caps lit)
  (let ((result '()))
    (dolist (item list (nreverse result))
      (cond ((find item " !?.")          (push item result))
            ((eql item (character "\"")) (setf lit (not lit)))
            (lit                         (push item result)
                                         (setf caps nil))
            (caps                        (push (char-upcase item) result)
                                         (setf caps nil))
            (t                           (push (char-downcase item) result)
                                         (setf caps nil
                                               lit nil))))))

(defun game-print (list)
  (princ (coerce (tweak-text (coerce (string-trim "() " (prin1-to-string list)) 'list)
                             t nil)
                 'string))
  (terpri))

然后:

代码语言:javascript
复制
(game-print '(not only does this sentence have a "comma," it also mentions the "iPad."))

在emacs中:

代码语言:javascript
复制
prints:   Not only does this sentence have a comma, it also mentions the iPad.
returns:  t

在Common Lisp中:

代码语言:javascript
复制
prints:   Not only does this sentence have a comma, it also mentions the iPad.
returns:  nil

现在,一般来说,使用列表来处理字符串没有什么意义,emacs lisp和Common Lisp都有强大的原语来直接处理序列和字符串。

票数 4
EN

Stack Overflow用户

发布于 2012-06-14 12:27:10

请注意,elisp (遗憾的是)没有针对尾递归进行优化,因此这是编写此函数的一种非常低效的方法。

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

https://stackoverflow.com/questions/11026040

复制
相关文章

相似问题

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