2

我对Scheme有点了解(很久以前读过SICP),写了这个程序:

(define (prl k m)
  (define (print-line n)
    (cond ((> n 0) (display n)
                   (print-line (- n 1)))
          (else (newline))))
  (print-line k)
  (cond ((> m 1) (prl (+ k 1) (- m 1)))))

示例 - http://ideone.com/LuG45W

但我在 CL 中需要这个,而不使用任何宏。你能帮我实现吗?谢谢。

4

4 回答 4

4

Common Lisp 的方案。

  • SCHEME:DEFINE顶层是CL:DEFUN.
  • SCHEME:DEFINE作为本地定义是CL:FLETor CL:LABELS
  • CL 是默认和标准的,不是尾调用优化。这意味着最好使用 a) 支持 TCO 的实现并指导编译器这样做,或者 b) 在必要/可能的情况下使用循环。另请注意,大多数解释器不会在 Common Lisp 中执行 TCO,即使编译器可能支持它。

所以代码将是:

(defun prl (k m)
  (flet ((print-line (n)
           (loop for i downfrom n downto 1 do (write i))
           (terpri)))
    (loop for i from k
          repeat m
          do (print-line i))))
于 2013-05-26T17:21:51.913 回答
3

正如 Rainer 正确指出的那样,Óscar 的解决方案并不完全正确,因为在全局环境defun中定义了一个新函数。这应该是正确的翻译:

(defun prl (k m)
  (labels ((print-line (n)
             (cond ((> n 0)
                    (princ n)
                    (print-line (1- n)))
                   (t (terpri)))))
    (print-line k))
  (when (> m 1)
    (prl (1+ k) (1- m))))

但请注意,与 Scheme 不同,CL 标准不保证尾调用优化。您必须为此检查您的实施文档。

于 2013-05-26T17:17:09.467 回答
2

在这种情况下,从 Scheme 到 CL 的翻译非常简单:

(defun prl (k m)
  (labels ((print-line (n)
             (cond ((> n 0)
                    (princ n)
                    (print-line (- n 1)))
                   (t (terpri)))))
    (print-line k)
    (cond ((> m 1)
           (prl (+ k 1) (- m 1))))))

例如:_

(prl 3 4)
(terpri)
(prl 1 4)

321
4321
54321
654321

1
21
321
4321
于 2013-05-26T16:26:22.547 回答
0

不必带有 GOTO 的语言中保证尾递归:

(defun prl (k m)                   ; (define (prl k m)
  (prog (n)
    PRL
      (setf n k)                   ;   (print-line k)
    PRINT-LINE                     ;   (define (print-line n)
      (cond ((> n 0) (princ n)     ;     (cond ((> n 0) (display n)
               (decf n)            ;              (print-line (- n 1)))
               (go PRINT-LINE))
            (t (terpri)))          ;           (else (newline))))
      (cond                        ;   (cond 
        ((> m 1)                   ;    ((> m 1) 
         (incf k)                  ;     (prl (+ k 1) (- m 1)))))
         (decf m) (go PRL)))))

测试:

[19]> (prl 3 4)
321
4321
54321
654321
NIL
[20]> (prl 1 4)
1
21
321
4321
NIL
于 2013-05-26T23:29:42.817 回答