程序应该重新格式化字符串,如下所示。
示例:(game-print‘(这是一个句子。那这个呢?可能。))
这是一个句子。那这个呢?可能吧。
但是有些地方不对劲( Lisp嵌套超过了‘`max lisp-eval-don),我不知道为什么。这段代码实际上来自于第97页的“lisp的土地”一书。原始代码是用普通的lisp编写的。我想用elisp重写它。two text中的最后两个参数表示队长和文字。
(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编写的原始代码。
(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))发布于 2012-06-14 11:30:54
在调整文本中递归时,您确实达到了‘max-lisp-eval- when’的限制。我看不出代码的方式有什么问题(我没有检查它是否在做你想要做的事情)。
您可以配置/提高'max-lisp-eval-depth‘限制。该变量的文档指出,只要您确信不会遇到堆栈空间耗尽的情况,就可以引发它。在我的机器上,这个限制被保守地设置为541。将其提高到600可以使上面的函数定义在您作为示例给出的输入上工作。
发布于 2012-06-14 13:07:09
在这两种情况下,都有非终端递归,因此使用O(length(lst))堆栈空间。显然,系统可能会限制您可以使用的堆栈空间,而在emacs中确实达到了这个限制。(现在在emacs中,您可以通过更改max-lisp-eval-lisp来增加限制,但这并不能解决根本问题)。
解决方案是使用迭代而不是递归。
但首先,在emacs中编写:
(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编写单个函数:
(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))然后:
(game-print '(not only does this sentence have a "comma," it also mentions the "iPad."))在emacs中:
prints: Not only does this sentence have a comma, it also mentions the iPad.
returns: t在Common Lisp中:
prints: Not only does this sentence have a comma, it also mentions the iPad.
returns: nil现在,一般来说,使用列表来处理字符串没有什么意义,emacs lisp和Common Lisp都有强大的原语来直接处理序列和字符串。
发布于 2012-06-14 12:27:10
请注意,elisp (遗憾的是)没有针对尾递归进行优化,因此这是编写此函数的一种非常低效的方法。
https://stackoverflow.com/questions/11026040
复制相似问题