将Q和P函数从The Little Schemer翻译成Common Lisp?

时间:2009-11-11 10:06:00

标签: scheme lisp common-lisp the-little-schemer

在Little Schemer的第9章中,作者提出了以下两个函数

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

并建议通过以下执行评估它们:

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

您如何在Common Lisp中编写P和Q函数?

(我自己翻译了Y-Combinator - 但我发现这个有挑战性)

- 助手功能 -

(define frontier
  (lambda (str n)
    (cond
      ((zero? n) (quote ()))
        (t (cons (first$ 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 ))))))

(免责声明 - 这不是一个家庭作业问题 - 这是我的理解和学习)

1 个答案:

答案 0 :(得分:6)

我假设:

  • 在P定义中,用“(Q(str(first $ str)))”你的意思是:“(Q str(first $ str))”,因为Q是一个双参数函数。
  • build 是一个帮助程序,可以创建第一个$和第二个$ work的内容: list

考虑到这一点,将Scheme直接翻译成Common Lisp给出了:

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

最后一行返回:

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

这是一个众所周知的系列,所以我认为翻译是成功的: - )