curry

Das Macro curry erzeugt aus einem Ausdruck mit Platzhaltern eine Funktion. Als Platzhalter wird der Unterstrich (_) verwendet. Die Platzhalter werden zu den Parametern der Funktion. Der Ausdruck wird zum Rumpf der Funktion.

Das Macro verwendet select-if, map-with und gensym, um aus einer Liste die Unterstriche zu extrahieren und dafür Symbole zu erzeugen. Diese Symbole werden als Parameter der erzeugten Funktion verwendet. Die mittels cond, null?, equal?, first, rest, cons und reverse implementierte Hilfsfunktion replace-underscores setzt die erzeugten Symbole anstelle der Unterstriche ein. Schließlich konstruiert das Macro mit list einen lambda Ausdruck, der die Funktion erzeugt, sobald er ausgewertet wird.

(setq curry
  (letrec
    ((make-parameter (lambda (underscore) (gensym)))
     (underscore? (lambda (x) (equal? x (quote _))))
     (replace-underscores
       (lambda (arguments parameters result)
         (cond
           ((null? arguments)
             (reverse result))
           ((underscore? (first arguments))
             (replace-underscores
               (rest arguments)
               (rest parameters)
               (cons (first parameters) result)))
           (t
             (replace-underscores
               (rest arguments)
               parameters
               (cons (first arguments) result)))))))
    (mlambda args
      (let
        ((parameters
          (map-with
            make-parameter
            (select-if
              underscore?
              (first args)))))
        (list
          lambda
          parameters
          (replace-underscores
            (first args)
            parameters
            nil))))))


Das Macro curry kann wie folgt verwendet werden:

> ((curry (+ 1 2 _ _)) 3 4)
10

> (map-with (curry (_ 2 3)) (list + - *))
(5 -1 6)