Рекурсивный 'compose' в общем lisp (перевод со схемы) - PullRequest
1 голос
/ 26 апреля 2019

Я изучаю Common Lisp. Схема еще не знаю.

У меня нет проблем со следующим compose в Common Lisp

(defun compose (&rest fns)  
  (destructuring-bind (fn1 . rest) (reverse fns)
    #'(lambda (&rest args)                       
       (reduce #'(lambda (v f) (funcall f v))    
               rest                              
               :initial-value (apply fn1 args)))))

(интересно глубокое сходство между составлением и уменьшением :))

Затем, читая вокруг, я нашел пример из compose в Схеме, но сделал рекурсивно, вот так:

(define (compose . fs)
  (if (null? fs) (lambda (x) x)
      (lambda (x) ((car fs) ((apply compose (cdr fs)) x)))))

Моя попытка перевести вышеприведенное в Common Lisp (скорее в темноте):

(defun compose-r (&rest fs)
  (if (null fs)
      #'(lambda (x) x)                   ; base case
      #'(lambda (x) (funcall (car fs)    ; first given fn, applied to...
                     (compose-r (cdr fs) x)))))

Интересно, что вышеперечисленное производит:

COMPOSE-R
[179]> (mapcar (compose-r #'list #'abs #'round #'sqrt) '(4 9 16 25 130))
((#<FUNCTION :LAMBDA (X) (FUNCALL (CAR FS) (COMPOSE-R (CDR FS) X))>)
 (#<FUNCTION :LAMBDA (X) (FUNCALL (CAR FS) (COMPOSE-R (CDR FS) X))>)
 (#<FUNCTION :LAMBDA (X) (FUNCALL (CAR FS) (COMPOSE-R (CDR FS) X))>)
 (#<FUNCTION :LAMBDA (X) (FUNCALL (CAR FS) (COMPOSE-R (CDR FS) X))>)
 (#<FUNCTION :LAMBDA (X) (FUNCALL (CAR FS) (COMPOSE-R (CDR FS) X))>))
[180]> 

Итак, что-то работает, но я пропустил вызов функции.

Было бы здорово, если бы кто-то мог использовать этот пример, чтобы указать на некоторые ключевые различия между Common Lisp и Scheme, а также наметить ключевые вещи, которые нужно знать при переводе.

Я уже заметил, что в схеме представляется возможным оценить выражение в нулевой позиции выражения, тогда как Common Lisp жалуется, что «должно быть лямбда-выражением».

Заранее спасибо.

1 Ответ

5 голосов
/ 26 апреля 2019
(define (compose . fs)
  (if (null? fs)
      (lambda (x) x)
      (lambda (x)
        ((car fs)
         ((apply compose (cdr fs)) x)))))

is

(defun compose (&rest fs)
  (if (null fs)
      (lambda (x) x)
      (lambda (x)
        (funcall (car fs)
                 (funcall (apply #'compose (cdr fs)) x)))))

Тогда:

CL-USER 53 > (mapcar (compose #'list #'abs #'round #'sqrt) '(4 9 16 25 130))
((2) (3) (4) (5) (11))

Основные отличия в Common Lisp:

  • вызов объектов функций с FUNCALL
  • получить функциональный объект с помощью #'some-fun или (function some-fun)
...