Home     |     .Net Programming    |     cSharp Home    |     Sql Server Home    |     Javascript / Client Side Development     |     Ajax Programming

Ruby on Rails Development     |     Perl Programming     |     C Programming Language     |     C++ Programming     |     IT Jobs

Python Programming Language     |     Laptop Suggestions?    |     TCL Scripting     |     Fortran Programming     |     Scheme Programming Language


 
 
Cervo Technologies
The Right Source to Outsource

MS Dynamics CRM 3.0

Scheme Programming Language

newby macro question


Hello,

I'm learning macro by implementing simple list comprehension based on
Philip Wadler's transformation rules(the unoptimized ones for
simplicity). . The problem is, my program always returns the properly
converted s-expression instead of executing it. Below is my code. When
I tested it, I always got S-expression back. For example, if my test
case is (list-of x (x <- '(1 2 3 4)) (> x 2)), then I will get back
(map (lambda (x) (list-of x (> x 2))) '(1 2 3 4)), instead of the
result of *executing* the returned expression. I guess this is because
Scheme interprets that the quasiquoted expressions are returned result
instead of part of the transformation. Therefore, I also tried
removing quasiquotes, and simply using normal evaluation. However, by
doing that I couldn't get it work. Any suggestions? Thanks a bunch!

(define (generator? expr)
  (eq? (cadr expr) '<-))

(define (gen-var expr)
  (car expr))

(define (gen-list expr)
  (caddr expr))

(define-syntax list-of
  (syntax-rules ()
    ((_ e . rules)
     (if (null? 'rules) e
         (let ((rule (car 'rules))
               (remaining (cdr 'rules)))
           (cond
             ((not (generator? rule)) `(if ,rule (list-of
e ,@remaining)))
             (else
              (let ((var (gen-var rule))
                    (data (gen-list rule)))
                `(map (lambda (,var) (list-of
e  ,@remaining)) ,data)))))))))

The transformation rules I used are:
(a) TE[[E | v<- L: Q]] = map (lambda (v). TE[[E | Q]]) TE[L]
(b) TE[[E|B; Q]] = if TE[B] TE[[E|Q]] NIL
(c) TE[ [e |]] = Cons TE[E] NIL

Hi

> I'm learning macro by implementing simple list comprehension based on
> Philip Wadler's transformation rules(the unoptimized ones for
> simplicity).

You should mention the source where you got those rules from:
http://research.microsoft.com/~simonpj/papers/slpj-book-1987/index.htm

> The problem is, my program always returns the properly
> converted s-expression instead of executing it. Below is my code. When
> I tested it, I always got S-expression back. For example, if my test
> case is (list-of x (x <- '(1 2 3 4)) (> x 2)), then I will get back
> (map (lambda (x) (list-of x (> x 2))) '(1 2 3 4)), instead of the
> result of *executing* the returned expression. I guess this is because
> Scheme interprets that the quasiquoted expressions are returned result
> instead of part of the transformation.

Syntax-rules is not a computational macro-system, but rewrite rule
based (basically it does the thing you try to do, but automatic).

So with your macro:

(list-of e . rules)

is expanded into

(if (null? 'rules) e
    (let ((rule (car 'rules))
          (remaining (cdr 'rules)))
      (cond
        [...])))

which is then run and computes the s-expression. If you want an
computational macro system you should search for one of '(syntax-case
explicit-renaming-macros syntactic-closures define-macro). Mote that
these are not in the current scheme standard (but syntax-case might be
in the next). Common Lisps defmacro also falls into the class of
computational macro systems.

> Therefore, I also tried
> removing quasiquotes, and simply using normal evaluation. However, by
> doing that I couldn't get it work. Any suggestions? Thanks a bunch!

All the quoting and unquoting is allready done by syntax-rules in an
automated fashion, so you dont have to :)

You should also note that wadler does not use map but flat-map, which
is NOT the same as schemes map.

=== SPOILER ===

i have posted a version of list-of implemented with syntax-rules at:
http://paste.lisp.org/display/42060

(define-syntax list-of
  (syntax-rules (in is)
    ((_ 'aux expr base) (cons expr base))
    ((_ 'aux expr base (x in xs) clauses ...)
      (let loop ((z xs))
        (if (null? z)
            base
            (let ((x (car z)))
              (list-of 'aux expr (loop (cdr z)) clauses ...)))))
    ((_ 'aux expr base (x is y) clauses ...)
      (let ((x y))
        (list-of 'aux expr base clauses ...)))
    ((_ 'aux expr base pred? clauses ...)
      (if pred?
          (list-of 'aux expr base clauses ...)
          base))
    ((_ expr clauses ...)
      (list-of 'aux expr '() clauses ...))))

(list-of (+ y 6) (x in '(1 2 3 4 5)) (odd? x) (y is (* x x))) => (7 15
31)

On May 31, 5:54 am, Phil Bewig <pbe@gmail.com> wrote:

This will fail in odd ways:

(list-of (add1 y) (x in '(1 2 3 4 5)) (odd? x) (y is (* x x)))
. reference to undefined identifier: x

> I'm learning macro by implementing simple list comprehension based on
> Philip Wadler's transformation rules(the unoptimized ones for
> simplicity). . The problem is, my program always returns the properly
> converted s-expression instead of executing it. Below is my code. When
> I tested it, I always got S-expression back. For example, if my test
> case is (list-of x (x <- '(1 2 3 4)) (> x 2)), then I will get back
> (map (lambda (x) (list-of x (> x 2))) '(1 2 3 4)), instead of the
> result of *executing* the returned expression. I guess this is because
> Scheme interprets that the quasiquoted expressions are returned result
> instead of part of the transformation. Therefore, I also tried
> removing quasiquotes, and simply using normal evaluation. However, by
> doing that I couldn't get it work. Any suggestions? Thanks a bunch!

As the others write syntax-rules can't do arbitrary computations.
Despair not - syntax-case can. Here is a syntax-case version
written by turning

   '  into  #'
   `  into  #`
   ,@ into #,@

and then inserting syntax->list everywhere you car, cdr, null?
and friends to examine the syntax.

The snippet is *not* in good style, but it shows how to
use syntax-case in the "define-macro" style.

(begin-for-syntax
   (define (generator? expr)
     (eq? (cadr (syntax-object->datum expr)) '<-))

   (define (gen-var expr)
     (car (syntax->list expr)))

   (define (gen-list expr)
     (caddr (syntax->list expr))))

(define-syntax (list-of stx)
   (syntax-case stx ()
     ((_ e . rules)
      (let ([rules (syntax->list #'rules)])
        (if (null? rules)
            #'e
            (let ((rule      (car rules))
                  (remaining (cdr rules)))
            (cond
              ((not (generator? rule))
               #`(if #,rule (list-of e #,@remaining)))
              (else
               (let ((var  (gen-var rule))
                     (data (gen-list rule)))
                 #`(map (lambda (#,var)
                          (list-of e  #,@remaining)) #,data))))))))))

Welcome to DrScheme, version 370.2-svn29may2007 [3m].
Language: Pretty Big (includes MrEd and Advanced Student); memory limit:
900 megabytes.
 > (list-of x
          (x <- '(1 2 3 4))
          (> x 2))

(#<void> #<void> 3 4)

--
Jens Axel Sgaard

On May 31, 4:49 pm, Joe Marshall <eval.ap@gmail.com> wrote:

Maybe someday I will reach macro nirvana.  But not today.  This one
works.  Thanks, Joe.

(define-syntax list-of
  (syntax-rules (in is)
    ((_ "aux" expr base) (cons expr base))
    ((_ "aux" expr base (x in xs) clauses ...)
      (let loop ((z xs))
        (if (null? z)
            base
            (let ((x (car z)))
              (list-of "aux" expr (loop (cdr z)) clauses ...)))))
    ((_ "aux" expr base (x is y) clauses ...)
      (let ((x y))
        (list-of "aux" expr base clauses ...)))
    ((_ "aux" expr base pred? clauses ...)
      (if pred?
          (list-of "aux" expr base clauses ...)
          base))
    ((_ expr clauses ...)
      (list-of "aux" expr '() clauses ...))))

Add to del.icio.us | Digg this | Stumble it | Powered by Megasolutions Inc