I’m creating a macro that expands to a lambda expression, something like this: (lambda (x y) lambda-body ...)
Inside the lambda-body
s will appear some x
or y
identifiers. Sometimes they refer to the args or maybe not. How can I know if x
or y
are bound to the args of the lambda?
Examples?
Do the args of the lambda appear as input to the macro, or are they introduced by the macro? As soegaard2 says, a couple of examples would help.
yep, they do
(my-macro (x y)
(something ... x y))
In this case x and y are bound to the args from my-macro, but it could be: (my-macro (x y)
(something ... (lambda (x) (f x))))
That x is not bound to the x from my-macro.
I would like to know if that identifiers are bound or not from the arg of my-macro
#lang racket
(require (for-syntax syntax/parse))
(define-syntax (foo stx)
(syntax-parse stx
[(_foo x y . body)
(syntax
(let ([x 10] [y 11])
. body))]))
(foo a b (+ a b)) ; => 21
((foo a b (λ (a b) (+ a b))) 1 2) ; => 3
((foo a b (λ (a c) (+ a b))) 1 2) ; => 12
> I would like to know if that identifiers are bound or not from the arg of my-macro I’m confused. Is this a programming question or a language question?
In particular, do you mean you want to programmatically find if an identifier is bound to an arg from your macro? Or you mean you want to learn the scoping rule in presence of macro?
For latter, see @soegaard2’s answer.
For former, how do you mark for an identifier that you want to query for the information?
I mean the first
Well, all this is also a bit confising to me. xD
OK, then how do you mark for an identifier that you want to query? The body of your macro could have million identifiers. Which one are you interested in?
I think im going to write a better example, wait a second
The procedure quotient/remainder
produces two values. For the first time I’m wondering how I could use in a for/fold
, say. Is it possible? This doesn’t work: (for/fold ([(quo r) (quotient/remainder 50 2)] ... )
quo)
; for/fold: expected an identifier to bind
; at: (quo r)
; in: (for/fold (((quo r) (quotient/remainder 50 2)) ... ) quo)
Suppose I use the macro my-macro
: (my-macro (arg1 arg2)
(aux-macro ... arg1 ... arg2 ...)
(aux-macro (lambda (arg1) arg1)))
The macro uses the identifier aux-macro that have to be treated in different manner depending if it has inside an arg1 or arg2 id. The first aux-macro have to be transformed into a number (for example) because it uses arg1 and arg2, but the second one have to be transformed to a procedure because it has no bounded identifiers to the args from my-macro. (Sorry about my english :D)
I think I missunderstamding something xD
for/fold
has the accumulator part and the iterator part.
Where do you want to use quotient/remainder
?
So what will happen if I have
(my-macro (arg)
(aux-macro arg (lambda (arg) arg)))
?
That’s in the first case
And what about:
(my-macro (arg1)
(my-macro (arg2)
(aux-macro arg1)))
?
Is that aux-macro
querying for the outer my-macro
or inner my-macro
?
But anyway, I think I just need to use another name for the lambda args and search for the identifiers.
This looks like an XY problem (see https://en.wikipedia.org/wiki/XY_problem). Can you tell what you actually want to do?
Hmm, I couldn’t do that
Hm, actually I’m not totally sure as I still don’t know what I really want to write. In English, what I need is to keep dividing an integer (say, 50) by 2 until some predicate is satisfied. If the integer to be divided happens to be odd (eventually) then I also need to bail out with a result. [In the 50-case, I’d bail out after a single iteration.] I guess I should write it without a for/fold so I can at least tell you precisely the procedure I need.
I don’t think for/fold
is an appropriate thing to use here
for
forms are for iterating over sequences
I see. I have an open-ended iteration here, right? A do-until-type, say.
Here, there’s no sequence to iterate over. I mean, you can technically iterate infinitely with (in-naturals)
and then use #:break
, but I would consider that a bad style.
Well, the macro has to transform to a lambda expression and the aux macro have inside some procedures. If the procs doesn’t use the args then they have to be executed only once. In the case they do, they are stored and have to be executed each time the lambda expression (the first I’ve mentioned) is executed.
Right. You can use let
-loop, for instance.
Got ya. I’ll write a recursive procedure… Yeah, sounds good. Thanks for your expertise on this!
(let loop ([n 50])
(define-values (q r) (quotient/remainder n 2))
(cond
[(= r 0) (loop q)]
[else n]))
Nice! Thank you so much for the example!
(define var 5)
(define foo (my-macro (a b)
(aux-macro (set! var (add1 var)))
(aux-macro (set! var (+ var a b)))
(aux-macro (set! var (add1 var)))))
var ; => 7
(foo 3 4) ; => 14
That could be an aproximation
Calling the macro only are executed first and third aux-macro
. Then, using foo only is executed the second aux-macro
.
Oh, It totally could be
It looks like you want stuff in aux-macro
to be evaluated right away if they don’t contain arguments of my-macro
?
Is that the case? If so, what should happen with:
(define foo
(my-macro (a)
(let ([b a])
(aux-macro (println b)))))
?
That demostrates my idea is very bad
xD