Hi,
I am _trying_ to grok syntax-case. Getting pretty desperate. Anyway,
as an exercise, I thought I'd make an extensible piping construct. The
idea is that if a symbol in a list is marked as a pipe, then all
positions in the list before that symbol become the tail of the piping
expression.
Suppose i marked "if", and "print" as pipes.
(pipe-app list 1 2 if (test))
;;==
(if test (list 1 2))
(pipe-app foo a b c if (test1) if (test2) print)
;;==
(print (if (test2) (if (test1) (foo a b c))))
So it's a simple-minded transform that doesn't need to know about the
meaning of the symbols marked as pipes. But the piping symbols should
prevent capturing:
(let ((if 1)
(print 2))
(pipe-app list 1 if 2 print))
;;==
(let ((if 1)
(print 2))
(list 1 if 2 print))
My implementation works up to this point, but I don't know what to do
if I want local pipes. Something like:
(let ((if print))
(let-pipe (if)
(pipe-app list a b c if)))
;;==
(print (list a b c))
There should be a trick, but I don't see it.
(Another side question. In a botched effort to introduce local pipes,
I used "expand" in the transformer. What does that do? Does it do
expansion in the transforming environment of the transforming
environment (therefore the syntax object produced is useless in run-
time)?
Anyway, I got the error "identifier out of context", which is the one
that I get if the output of the transformer has an identifier that
refers to a binding in the transformer environment.
(define-syntax (foo x)
(syntax-case x ()
((_ e) (expand (syntax e)))))
Apparently works. What is it doing?
)
I am using plt-scheme.
Howard
-----------------------------------------------------
(define-syntax pipe-app
(lambda (x)
(syntax-case x ()
((_ e ...)
(not (null? (syntax->list (syntax (e ...)))))
(let loop ((exps (reverse (syntax->list (syntax (e ...)))))
(acc ()))
(if (null? exps)
#`#,acc
(if (and (is-pipe? (car exps))
(not (null? (cdr exps))))
;; not tail-recursive. Can use continuation
;; passing style instead.
(let ((result (loop (cdr exps) ())))
#`(#,(car exps) #,@acc #,result))
(loop (cdr exps) (cons (car exps) acc))))))
)))
(begin-for-syntax
(define pipes ())
(define (active-pipes) pipes)
(define (define-pipe-symbol identifier)
(set! pipes (cons identifier pipes)))
(define (is-pipe? identifier)
(and (identifier? identifier)
(let loop ((pipes pipes))
(and (not (null? pipes))
(if (free-identifier=? (car pipes) identifier)
#t
(loop (cdr pipes)))))))
(define-pipe-symbol (syntax if))
(define-pipe-symbol (syntax print))
)
Ooops. Should've posted to comp.lang.scheme.
I am soooo sorry :(
On Jun 13, 11:37 am, howard yeh <······@gmail.com> wrote:
> Hi,
>
> I am _trying_ to grok syntax-case. Getting pretty desperate. Anyway,
> as an exercise, I thought I'd make an extensible piping construct. The
> idea is that if a symbol in a list is marked as a pipe, then all
> positions in the list before that symbol become the tail of the piping
> expression.
>
> Suppose i marked "if", and "print" as pipes.
>
> (pipe-app list 1 2 if (test))
> ;;==
> (if test (list 1 2))
>
> (pipe-app foo a b c if (test1) if (test2) print)
> ;;==
> (print (if (test2) (if (test1) (foo a b c))))
>
> So it's a simple-minded transform that doesn't need to know about the
> meaning of the symbols marked as pipes. But the piping symbols should
> prevent capturing:
>
> (let ((if 1)
> (print 2))
> (pipe-app list 1 if 2 print))
> ;;==
> (let ((if 1)
> (print 2))
> (list 1 if 2 print))
>
> My implementation works up to this point, but I don't know what to do
> if I want local pipes. Something like:
>
> (let ((if print))
> (let-pipe (if)
> (pipe-app list a b c if)))
> ;;==
> (print (list a b c))
>
> There should be a trick, but I don't see it.
>
> (Another side question. In a botched effort to introduce local pipes,
> I used "expand" in the transformer. What does that do? Does it do
> expansion in the transforming environment of the transforming
> environment (therefore the syntax object produced is useless in run-
> time)?
>
> Anyway, I got the error "identifier out of context", which is the one
> that I get if the output of the transformer has an identifier that
> refers to a binding in the transformer environment.
>
> (define-syntax (foo x)
> (syntax-case x ()
> ((_ e) (expand (syntax e)))))
>
> Apparently works. What is it doing?
> )
>
> I am using plt-scheme.
>
> Howard
> -----------------------------------------------------
> (define-syntax pipe-app
> (lambda (x)
> (syntax-case x ()
> ((_ e ...)
> (not (null? (syntax->list (syntax (e ...)))))
> (let loop ((exps (reverse (syntax->list (syntax (e ...)))))
> (acc ()))
> (if (null? exps)
> #`#,acc
> (if (and (is-pipe? (car exps))
> (not (null? (cdr exps))))
> ;; not tail-recursive. Can use continuation
> ;; passing style instead.
> (let ((result (loop (cdr exps) ())))
> #`(#,(car exps) #,@acc #,result))
> (loop (cdr exps) (cons (car exps) acc))))))
> )))
>
> (begin-for-syntax
> (define pipes ())
> (define (active-pipes) pipes)
> (define (define-pipe-symbol identifier)
> (set! pipes (cons identifier pipes)))
> (define (is-pipe? identifier)
> (and (identifier? identifier)
> (let loop ((pipes pipes))
> (and (not (null? pipes))
> (if (free-identifier=? (car pipes) identifier)
> #t
> (loop (cdr pipes)))))))
> (define-pipe-symbol (syntax if))
> (define-pipe-symbol (syntax print))
>
> )