Hi,
some time ago I posted to comp.lang.scheme with the
following proposal of "define-curried" macro:

(define-macro (define-curried signature . body)
  (match signature
    ((name args ...)
     `(define-syntax ,name
        (syntax-rules ()
          ((_ ,@args)
           (begin ,@body))
          ,@(let loop ((args* args))
              (match args*
                (() '())
                ((first ... last)
                 (cons `((_ ,@first #;...)
                         (lambda(,last)(,name ,@args*)))
                       (loop first #;...))))))))))

The idea was to expand, e.g. (define-curried (f a b c d) (list a b c d))
to:

(define-syntax f
  (syntax-rules ()
    ((_ a b c d)
     (begin (list a b c d)))
    ((_ a b c)
     (lambda(d)
       (f a b c d)))
    ((_ a b)
     (lambda(c)
       (f a b c)))
    ((_ a)
     (lambda(b)
       (f a b)))
    ((_)
     (lambda(a)
       (f a)))))

I asked whether it would be possible to write that code using syntax-rules
only, but I received no answer, not even a reprimend. I used that code to
implement a quite convinient macro (actually that urge was my inspiration):

(define-curried (matches? pattern x)
  (match x
    (pattern #t)
    (else #f)))

so that I could write

(filter (matches? (two elements)) some-list)

Recently, I tried to write a nicer interface to string-match, that would
allow me to extract parenthesized subexpressions easily. My first guess was
this:

(define-curried (string-matches pattern string)
  ;;CAUTION: buggy version
  (and-let* ((match-struct (string-match pattern string))
                (count (match:count match-struct)))
     (map (lambda(n)(match:substring match-struct n))
        (iota (1- count) 1))))

and although it worked with a complete list of arguments,
(string-matches "([a-z])" "a")
==> ("a")
it failed to curry properly
((string-matches "([a-z])") "a")
==> some strange error

It turned out, that the "string" symbol doesn't get tied
with the lambda argument:

(expand (string-matches "([a-z])"))
==>
(lambda (string-12552)
  (let ((match-struct-12557 (string-match "([a-z])" string)))
;; the reason of our tears and despair is right here^^^
    (if match-struct-12557
        (let ((count-12561 (match:count match-struct-12557)))
          (if count-12561
              (map (lambda (n-12564)
                     (match:substring match-struct-12557 n-12564))
                   (iota (#{1-}# count-12561) 1))
              #f))
        #f)))

This forced me to write another definition of string-matches
that doesn't use the and-let* macro and works as expected:

(define-curried (string-matches pattern s)
  (let ((match-struct (string-match pattern s)))
    (if match-struct
(let ((count (match:count match-struct)))
          (map (lambda(n)(match:substring match-struct n))
               (iota (1- count) 1)))
        #f)))

Nevertheless I am a little worried that either my macro,
or and-let* is not composable. Perhaps there's some wise
man here who knows what's going on.

Best regards,
M.

Reply via email to