guile-user
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

and-let* is not composable?


From: Panicz Maciej Godek
Subject: and-let* is not composable?
Date: Mon, 9 Sep 2013 19:35:16 +0200

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

[Prev in Thread] Current Thread [Next in Thread]