Re: Unquote syntax
Hi, [...] > I expect the following to be equal, and they are. > > (cons 'sym func) > > (quasiquote (sym . (unquote func))) `(sym . ,func) > > Guile writes them both as > > (sym . #) > > But, the following is also equivalent, which is a surprise to me. > > (quasiquote (sym unquote func)) > `(sym unquote func) > > Is this a valid use of unquote? It has to be. Because a list consists of car+cdr pairs, the notations (a . (b . (c . ( and (a b c) are equivalent and thus indistinguishable to the scheme reader: (equal? (with-input-from-string "(a . (b . (c . (" read) (with-input-from-string "(a b c)" read)) ; ===> #t > I get that (cons 'a (list 'b 'c)) == (list 'a 'b 'c), but, I'm not sure > if unquote should be valid in that sort of construction. The only alternative is that you wouldn't be able to write `(a . ,b), because -- since `x is transformed by reader to (quasiquote x), and ,x -- to (unquote x), the reader sees this as: (quasiquote (a . ,b)) == (quasiquote (a . (unquote b))) == (quasiquote (a unquote b)) But I think that from the perspective of the implementation of the "quasiquote" macro this is still consistent. Let's consider a simplified version of the macro -- call it semiquote -- that doesn't allow nesting of semiquotes, supports only lists, and doesn't support unquote-splicing: (define-syntax semiquote (syntax-rules (unquote) ((_ (unquote form)) form) ((_ (head . tail)) (cons (semiquote head) (semiquote tail))) ((_ atom) 'atom))) As you can see, the second case invokes semiquote on the tail of the list. So if it happens to be (unquote form), it will be considered the first case in the next iteration. Note however, that if you write (a b unquote c d), the unquote won't be interpreted, because there's only a rule for (_ (unquote form)), and not for (_ (unquote form . rest)). Having said that, I'd suggest reconsidering the idea (which might be a little OT), that if a function call is an improper list, like (+ a b . c), then it could be interpreted by the evaluator as (apply + a b c) (now it just raises a syntax error). Best regards, M.
Re: Unquote syntax
Mike Gran writes: > (quasiquote (sym unquote func)) > `(sym unquote func) > > Is this a valid use of unquote? > > I get that (cons 'a (list 'b 'c)) == (list 'a 'b 'c), but, I'm not sure > if unquote should be valid in that sort of construction. As has already been pointed out, since ,foo is literally the same as (unquote foo), (a . (unquote foo)) = (a unquote foo) has to be literally the same as (a . ,foo). This is actually a source of one of my favourite Scheme implementation bugs (favourite since it is common, subtle, but harmless) Try a few scheme implementations and see how many error on `#(1 2 3 unquote foo) because of implementing vector quasiquotation under the hood as list quasiquotation. -- Ian Price -- shift-reset.com "Programming is like pinball. The reward for doing it well is the opportunity to do it again" - from "The Wizardy Compiled"
Way to control the order of macro expansion
Hi, is there any way to control the order of macro expansion? Let's consider a particular problem. I'm trying to write a macro to control the visibility of certain definitions. I wrote it once, using define-macro, but it seemed to loose some relevant information, so I decided to rewrite it using define-syntax macros. The idea is that the code (publish (define (f x) (+ a x)) (define (g y) (* a y)) where (define a 5)) should expand to (begin (define f (and (defined? 'f) f)) (define g (and (defined? 'g) g)) (let () (define a 5) (set! f (let () (define (f x) (+ a x)) f)) (set! g (let () (define (g x) (* a y)) g The first thing that needs to be done is to split the definitions between the public (before "where") and private ones. It can be done by introducing a helper macro that will be called by our publish macro: (define-syntax-rule (publish definitions ...) (publisher (definitions ...) ())) (define-syntax publisher (syntax-rules (where) ((_ (where private ...) (public ...)) (private+public (private ...) (public ...))) ((_ (new defs ...) (approved ...)) (publisher (defs ...) (approved ... new) It works fine, but a simple question arises: how to make publisher visible only within the scope of publish macro? (I have tried many combinations, and all of them failed, although I don't know why) Now, we need the definition for the private+public syntax, that will do the actual conversion. I believe it should look more or less like this: (define-syntax-rule (private+public (private ...) ((df iface body ...) ...)) (letrec-syntax ((name (syntax-rules () ((_ (head . tail)) (name head)) ((_ atom) atom (begin (define (name iface) (and (defined? '(name iface)) iface)) ... (let () private ... (set! (name iface) (let () (df iface body ...) (name iface))) ... Unfortunately, there are some problems with that definition, the most annoying being the fact that it doesn't work ;] There are three problems, namely -- that quote, define and set! are special forms themselves, and as such they prevent the "name" local syntax to expand. (This can be observed easily, because when the names "define" and "set!" and the ' operator are replaced with some unbound identifiers, the macro expands just as I want it to). It seems that the expander works in the order from the outermost to the innermost level, and from left to right. Is there any way to force the expander to evaluate some innermost forms first? regards, M.