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.