bran.van.der.meer
2022-2-9 08:04:43

Question. Is it possible to create a syntax object via a literal that contains multiple consecutive expressions of syntax? E.g. could I write this macro without the added (begin) form? (define-syntax-rule (require/provide path) (begin (require path) (provide (all-from-out path)))) As soon as I move to define-syntax with syntax-parse, I don’t know how to write the syntax literal anymore, since it is multiple expressions: (define-syntax (require/provide stx) (syntax-parse stx [(_ path) #'#((require path) (provide (all-from-out path)))]))


bran.van.der.meer
2022-2-9 08:05:34

is the #'# construct the correct way to wrap multiple lines of syntax into a single syntax object?


bran.van.der.meer
2022-2-9 08:05:41

it seems to work, but i dont understand it :confused:


sorawee
2022-2-9 08:06:30

There’s no #'# operator.


sorawee
2022-2-9 08:06:57

I think you simply want:

(define-syntax (require/provide stx) (syntax-parse stx [(_ path) #'(begin (require path) (provide (all-from-out path)))]))


sorawee
2022-2-9 08:08:07

This is not directly related to syntax-parse btw. If you use syntax-case or produce a syntax object directly, you would need to write #' too.


sorawee
2022-2-9 08:08:30

define-syntax-rule is a shorthand that simplifies this step by removing the need to write #'.


bran.van.der.meer
2022-2-9 08:09:15

yeah i understand that part, my question is about syntax objects: > Is it possible to create a syntax object that contains multiple lines of syntax? (without the use of (begin))


bran.van.der.meer
2022-2-9 08:09:38

because syntax objects seem to be able to hold multiple lines


sorawee
2022-2-9 08:10:20

Sorry, I’m a bit confused. Why don’t you want to use begin?


bran.van.der.meer
2022-2-9 08:11:10

oh don’t get me wrong, i have nothing against begin, I’m just trying to understand syntax objects


bran.van.der.meer
2022-2-9 08:11:42

e.g. if I run syntax-e I can get a syntax object back which contains multiple lines of code


bran.van.der.meer
2022-2-9 08:12:05

so i don’t understand why i wouldn’t be able to create such an object manually


sorawee
2022-2-9 08:12:12

Ah, yes, but the macro expander will not treat that as many lines of code


sorawee
2022-2-9 08:12:20

It will treat that as a single line of code in parentheses (or #(...), or whatever you use to group them)


sorawee
2022-2-9 08:13:10

For #(...), that creates a vector.


sorawee
2022-2-9 08:13:28

For (...), that results in either a macro invocation or function application.


sorawee
2022-2-9 08:13:58

So using begin is essentially the only possibility of “grouping” multiple lines together


bran.van.der.meer
2022-2-9 08:14:31

hm, ok, interesting


bran.van.der.meer
2022-2-9 08:15:13

so what does actually get created when I use this kind of code? #'#((require path) (provide (all-from-out path)))


sorawee
2022-2-9 08:15:17

I would not use the term “line” btw. Let’s say “expressions” or something like that instead


bran.van.der.meer
2022-2-9 08:15:21

is that a syntax object with a vector inside?


sorawee
2022-2-9 08:15:24

That creates a vector.


sorawee
2022-2-9 08:15:27

Yes


bran.van.der.meer
2022-2-9 08:15:37

ah, makes sense


sorawee
2022-2-9 08:16:05

#lang racket (require (for-syntax syntax/parse)) (define-syntax (require/provide stx) (syntax-parse stx [(_ path) #'#((require path) (provide (all-from-out path)))])) (require/provide 123)


sorawee
2022-2-9 08:16:13

results in:

'#((require 123) (provide (all-from-out 123)))


sorawee
2022-2-9 08:16:46

which is a vector containing two lists: the list with require as the first element and the list with provide as the first element.


bran.van.der.meer
2022-2-9 08:17:05

ok, i understand it now :+1::skin-tone–2:


bran.van.der.meer
2022-2-9 08:18:01

and if i were to dig deeper in macro expansion, i would find that even things like function bodies secretly use begin as the only to way to contain multiple expressions in a syntax object?


sorawee
2022-2-9 08:20:18

So, actually, let me correct one thing.


sorawee
2022-2-9 08:21:18

It’s OK to use (), or even #() as a way to group stuff during the macro expansion. But the final expansion should not use () or #() for grouping


sorawee
2022-2-9 08:21:31

For example:


sorawee
2022-2-9 08:23:48

#lang racket (require (for-syntax syntax/parse)) (define-syntax (reverse/helper stx) (syntax-parse stx [(_ () (acc ...)) #'(acc ...)] [(_ (hd tl ...) (acc ...)) #'(reverse/helper (tl ...) (hd acc ...))])) (define-syntax-rule (reverse xs ...) (reverse/helper (xs ...) ())) (reverse 3 5 -)


sorawee
2022-2-9 08:24:09

This is a silly macro that transforms (reverse 3 5 -) to (- 5 3).


sorawee
2022-2-9 08:25:38

Here, I use (......) as a way to group multiple expressions together in the intermediate steps in the expansion. But the final result doesn’t use (.....) for grouping. It just produce one single term.


sorawee
2022-2-9 08:28:07

That is, the expansion roughly looks like this


sorawee
2022-2-9 08:28:45

(reverse 3 5 -) => (reverse/helper (3 5 -) ()) => (reverse/helper (5 -) (3)) => (reverse/helper (-) (5 3)) => (reverse/helper () (- 5 3)) => (- 5 3)


bran.van.der.meer
2022-2-9 08:29:34

yeah and to “aid” the wrapping of multiple expressions in a single form you have a recursive call now


bran.van.der.meer
2022-2-9 08:29:53

but begin would also be able to handle that case


bran.van.der.meer
2022-2-9 08:30:00

ok


bran.van.der.meer
2022-2-9 08:30:04

thanks a lot :slightly_smiling_face:


bran.van.der.meer
2022-2-9 08:30:08

insightful things


soegaard2
2022-2-9 08:51:15

@bran.van.der.meer FWIW I mention the technique of wrapping begin around definitions and expressions in the first example. https://soegaard.github.io/mythical-macros/


sorawee
2022-2-9 09:47:04

@soegaard2 FYI: in the recent Racket versions, the term “tamper status” is removed from the doc. The concept is simplified so that an object is either tainted or not tainted. You might want to update the tutorial.

Also, the title is named “titel”, which is probably a typo.


sorawee
2022-2-9 09:48:41

Also: wrong closing single quote


soegaard2
2022-2-9 09:51:13

@sorawee Thanks for the tips. I’ll remove “tamper status”.


soegaard2
2022-2-9 09:52:01

I have no clue why the closing quote is the wrong way around. I must have a bug somewhere.


sorawee
2022-2-9 09:55:41

Another thing: after you introduce syntax-parse, you might want to teach the #:with feature, which allows users express with-syntax / with-syntax* flatly.


sorawee
2022-2-9 09:55:58

the recipe can even switch to use #:with.


soegaard2
2022-2-9 09:59:34

The idea was to introduce with-syntax as a primitive (it’s useful to know about it for syntax-case macros). The intention was then to introduce #:with later on - but that section has yet to be written. When it materializes, I’ll add a note in the with-syntax section that #:with can be used.


soegaard2
2022-2-9 10:00:54

Fun fact - the use of single quotation marks in different countries (it’s a mess).


greg
2022-2-9 15:23:19

Yikes, that should be a new chapter in the “Falsehoods Programmers Believe About ___” series.


greg
2022-2-9 15:24:31

Where previous installments are “Names”, “Addresses”, etc.