Вопрос

В главе 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)

Как бы вы написали функции P и Q на Common Lisp?

(Я сам перевел 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 ))))))

(Отказ от ответственности - Это не вопрос домашнего задания - это для моего понимания и обучения)

Это было полезно?

Решение

Я предположил , что:

  • В определении P, с помощью "(Q (str (first$ str)))" вы имели в виду:"(Q str (first$ str))", поскольку Q - это функция с двумя аргументами.
  • строить является помощником, который создает что-то, над чем работают first $ и second $: Список

Имея это в виду, прямой перевод 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)

это хорошо известная серия, так что я предполагаю, что перевод удался :-)

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top