开发者

Translating the Q and P function from The Little Schemer into Common Lisp?

In Chapter 9 of the Little Schemer, the Author presents the following two functions

(define Q 
  (lambda (str n) 
    (cond 
      ((zero? (remainder (first$ str ) n)) 
        (Q (second$ str ) n)) 
      (t (build (first$ str ) 
        (lambda ( ) 
          (Q (second$ str ) n))))))) 

(define P
  (lambda (str)
    (build (first$ str)(lambda () (P (Q str (first$ str)))))))

and proposes that they are evaluated with the following execution:

(frontier (P (second$ (second$ int)))  10)

How would you write the P and Q functions in Common Lisp?

(I have translated the Y-Combinator myself - but I'm finding this one challenging)

--Helper Functions--

(define frontier
  (lambda (str n)
    (cond
      ((zero? n) (quote ()))
        (t (cons (f开发者_开发知识库irst$ str) (frontier (second$ str) (sub1 n)))))))

(define str-maker
  (lambda (next n)
    (build n (lambda () (str-maker next (next n))))))

(define int (str-maker add1 0))

(define second$
  (lambda (str)
    ((second str))))

(define first$ first)

(define build
  (lambda (a1 a2)
    (cond
      (t (cons a1
        (cons a2 (quote ())))))))))

(define first
  (lambda (p)
    (cond
       (t (car p)))))

(define second
  (lambda (p)
    (cond
      (t (car (cdr p))))))

(define add1 
  (lambda (n)
    (+ 1 n)))

(define remainder 
  (lambda  (n m)
    (cond
      (t (- n (* m (/ n m ))))))

(Disclaimer - This Is Not A Homework Question - it is for my understanding and learning)


I assumed:

  • In P definition, with "(Q (str (first$ str)))" you meant: "(Q str (first$ str))", as Q is a two-argument function.
  • build is a helper which does creates something on which first$ and second$ work: list

With this in mind, the direct translation of Scheme into Common Lisp gives:

(defun first$ (list) (first list))
(defun second$ (list) (funcall (second list)))
(defun build (a b) (list a b))

(defun frontier (str n)
  (if (zerop N)
    ()
    (cons (first$ str) (frontier (second$ str) (1- n)))))

(defun str-maker (next n)
  (list n (lambda () (str-maker next (funcall next n)))))

(setq int-maker (str-maker #'1+ 0))

(defun Q (str n)
  (if (zerop (rem (first$ str) n))
    (Q (second$ str) n)
    (list (first$ str) (lambda () (Q (second$ str) n)))))

(defun P (str)
  (list (first$ str) (lambda () (P (Q str (first$ str))))))

(frontier (P (second$ (second$ int-maker))) 10)

Whose last line returns:

(2 3 5 7 11 13 17 19 23 29)

which is a well known series, so I assume the translation is successful :-)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜