pproger
pproger

Reputation: 347

Translate Scheme to CL

I know Scheme a bit (read SICP long ago), wrote this program:

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

example - http://ideone.com/LuG45W

But i need this in CL, without using any macro. Can you help me with implementation? Thanks.

Upvotes: 2

Views: 622

Answers (4)

Will Ness
Will Ness

Reputation: 71070

One does not have to have tail-recursion guarantee in a language with 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)))))

Testing:

[19]> (prl 3 4)
321
4321
54321
654321
NIL
[20]> (prl 1 4)
1
21
321
4321
NIL

Upvotes: 0

Rainer Joswig
Rainer Joswig

Reputation: 139241

Scheme to Common Lisp.

  • SCHEME:DEFINE on the top-level is CL:DEFUN.
  • SCHEME:DEFINE as a local definition is CL:FLET or CL:LABELS.
  • CL is by default and by standard not tail call optimizing. That means best use a) a TCO supporting implementation and direct the compiler to do so or b) use loops where necessary/possible. Note also that most interpreters will not do TCO in Common Lisp, even though the compiler might support it.

So the code will be:

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

Upvotes: 4

Óscar López
Óscar López

Reputation: 235984

The translation from Scheme to CL in this case is pretty straightforward:

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

For example:

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

321
4321
54321
654321

1
21
321
4321

Upvotes: 2

danlei
danlei

Reputation: 14291

As Rainer correctly points out, Óscar's solution is not quite correct, since defun defines a new function in the global environment. This should be a correct translation:

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

But note that, unlike Scheme, the CL standard does not guarantee tail-call optimization. You'll have to check your implementation's documentation for that.

Upvotes: 3

Related Questions