hectometrocuadrado
2021-4-8 10:16:04

I’m creating a macro that expands to a lambda expression, something like this: (lambda (x y) lambda-body ...) Inside the lambda-bodys 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?


soegaard2
2021-4-8 11:34:37

Examples?


laurent.orseau
2021-4-8 13:06:36

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.


hectometrocuadrado
2021-4-8 13:42:17

yep, they do


hectometrocuadrado
2021-4-8 13:45:43

(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.


hectometrocuadrado
2021-4-8 13:46:30

I would like to know if that identifiers are bound or not from the arg of my-macro


soegaard2
2021-4-8 13:50:42

#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


sorawee
2021-4-8 13:55:34

> 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?


sorawee
2021-4-8 13:56:27

For latter, see @soegaard2’s answer.

For former, how do you mark for an identifier that you want to query for the information?


hectometrocuadrado
2021-4-8 13:56:44

I mean the first


hectometrocuadrado
2021-4-8 13:57:33

Well, all this is also a bit confising to me. xD


sorawee
2021-4-8 13:57:45

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?


hectometrocuadrado
2021-4-8 13:59:13

I think im going to write a better example, wait a second


anything
2021-4-8 14:05:53

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)


hectometrocuadrado
2021-4-8 14:06:55

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)


hectometrocuadrado
2021-4-8 14:10:09

I think I missunderstamding something xD


sorawee
2021-4-8 14:10:33

for/fold has the accumulator part and the iterator part.


sorawee
2021-4-8 14:10:43

Where do you want to use quotient/remainder?


sorawee
2021-4-8 14:11:42

So what will happen if I have

(my-macro (arg) (aux-macro arg (lambda (arg) arg))) ?


hectometrocuadrado
2021-4-8 14:12:48

That’s in the first case


sorawee
2021-4-8 14:13:27

And what about:

(my-macro (arg1) (my-macro (arg2) (aux-macro arg1))) ?


sorawee
2021-4-8 14:13:46

Is that aux-macro querying for the outer my-macro or inner my-macro?


hectometrocuadrado
2021-4-8 14:13:51

But anyway, I think I just need to use another name for the lambda args and search for the identifiers.


sorawee
2021-4-8 14:15:22

This looks like an XY problem (see https://en.wikipedia.org/wiki/XY_problem). Can you tell what you actually want to do?


hectometrocuadrado
2021-4-8 14:16:00

Hmm, I couldn’t do that


anything
2021-4-8 14:17:00

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.


sorawee
2021-4-8 14:18:08

I don’t think for/fold is an appropriate thing to use here


sorawee
2021-4-8 14:18:21

for forms are for iterating over sequences


anything
2021-4-8 14:18:38

I see. I have an open-ended iteration here, right? A do-until-type, say.


sorawee
2021-4-8 14:19:06

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.


hectometrocuadrado
2021-4-8 14:19:19

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.


sorawee
2021-4-8 14:19:24

Right. You can use let-loop, for instance.


anything
2021-4-8 14:19:44

Got ya. I’ll write a recursive procedure… Yeah, sounds good. Thanks for your expertise on this!


sorawee
2021-4-8 14:22:50

(let loop ([n 50]) (define-values (q r) (quotient/remainder n 2)) (cond [(= r 0) (loop q)] [else n]))


anything
2021-4-8 14:26:24

Nice! Thank you so much for the example!


hectometrocuadrado
2021-4-8 14:27:20

(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


hectometrocuadrado
2021-4-8 14:27:36

That could be an aproximation


hectometrocuadrado
2021-4-8 14:29:15

Calling the macro only are executed first and third aux-macro . Then, using foo only is executed the second aux-macro .


hectometrocuadrado
2021-4-8 14:31:01

Oh, It totally could be


sorawee
2021-4-8 14:46:00

It looks like you want stuff in aux-macro to be evaluated right away if they don’t contain arguments of my-macro?


sorawee
2021-4-8 14:46:28

Is that the case? If so, what should happen with:

(define foo (my-macro (a) (let ([b a]) (aux-macro (println b))))) ?


hectometrocuadrado
2021-4-8 14:52:47

That demostrates my idea is very bad


hectometrocuadrado
2021-4-8 14:52:49

xD