Domanda

Nel capitolo 9 della Schemer Little, l'autore presenta le seguenti due funzioni

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

e propone che vengono valutati con il seguente esecuzione:

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

Come vorresti scrivere le funzioni P e Q in Common Lisp?

(ho tradotto l'Y-Combinator me stesso - ma sto trovando questo uno stimolante)

- Funzioni di supporto -

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

(Disclaimer - Questa non è una questione Homework - è per la mia comprensione e l'apprendimento)

È stato utile?

Soluzione

Ho pensato:

  • Nella definizione P, con "(Q (str (primi $ str)))" si intende:. "(Q str (primi $ str))", come Q è una funzione a due argomenti
  • Crea è un assistente che fa crea qualcosa su cui prima e la seconda $ $ di lavoro:

Con questo in mente, la traduzione diretta del regime in Common Lisp dà:

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

La cui ultima riga riporta:

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

che è una serie ben nota, quindi immagino che la traduzione è successo: -)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top