anything
2021-2-26 14:40:08

@soegaard2 FWIW, here’s my lengthy experience working on the tutorial: https://pastebin.com/raw/65CgwMp2


jjlammi
2021-2-26 16:52:42

@jjlammi has joined the channel


soegaard2
2021-2-26 17:34:18

@anything Thanks! This is great feedback - and has given me some food for thought.


soegaard2
2021-2-26 17:34:57

There were a few questions, so here are some thoughts:


soegaard2
2021-2-26 17:37:16

In the experiment in section 5.1, you add a new form and calls read-syntax twice. That does indeed give you two syntax objects. You observe correctly, that there is no binding information.

The reader only reads the syntax objects (and stores the source location information). Later, the expander analyses the objects and adds binding information. So, in your example the expander haven’t run yet.


soegaard2
2021-2-26 17:39:15

The section with “third, fourth and fifth lines” could be improved. I’ll see if I can add line numbers. If not, maybe I should repeat the lines?


soegaard2
2021-2-26 17:40:12

You are now, the second suggesting some examples earlier. I need to think about how that would change the flow.


soegaard2
2021-2-26 17:40:45

Your comment, that with-syntax is like let is spot on.


soegaard2
2021-2-26 17:41:02

Normal variables are bound with let.


soegaard2
2021-2-26 17:41:13

Pattern variables are bound with with-syntax.


soegaard2
2021-2-26 17:42:26

It’s rare in Racket other types of variables, so I agree it feels a bit odd.


soegaard2
2021-2-26 17:42:49

They are used to make the templates easier to use.


soegaard2
2021-2-26 17:46:39

If we want to write a template like (syntax (let ((x 1)) (+ x 1)). Here there are three identifiers: let, x and +. If these were normal variables, then we need some way to say “insert the name x” or “insert the value of x”. With standard list syntax, we would use `(let ((,x 1)) (+ ,x 1)) to say that we want literal let and +, but the value of x (which could contain some other name).


soegaard2
2021-2-26 17:48:09

The solution here is to mark every “pattern variable” in the template with a comma.


soegaard2
2021-2-26 17:49:00

If a pattern variable is used multiple times, it needs to be marked every, single time. Forgetting one leads to an error.


soegaard2
2021-2-26 17:49:44

On the other hand, with with-syntax we can “bind x as a pattern variable” once, and then use x multiple times in a template.


soegaard2
2021-2-26 17:50:07

Then the form (syntax ...) will automatically treat every instance of x the same way.


soegaard2
2021-2-26 17:51:13

As a plus, if you want to test a subexpression of a template, you can simple copy-paste it to the repl and try it. With the other method, one has to remove all the commas.


soegaard2
2021-2-26 17:54:33

Your observation that begin is needed when a template needs to produce multiple definitions are correct. There is similar begin in the silly example in section 2, but I think I’ll make “multiple definitions” example in a later section.


soegaard2
2021-2-26 17:55:54

> In section 7 I realize that what you’re doing is > very interesting: you’re manipulating objects at run-time. That’s a > way to test what we want macros to do — but in a laboraroty. I > decided to go back to section 6 again for a new look with this thought > in mind. That’s an important point. I’ll try to make it clearer.


soegaard2
2021-2-26 17:57:28

The example without ~@ : Yeah - I think, I’ll remove it again. Wasn’t too sure about the relevance, when I wrote it.


soegaard2
2021-2-26 17:59:49

Sorry about the mistake in the exercise. It was meant to be:

(define result0 (with-syntax ([(num ...) (syntax (1 2 3))]) (syntax ???-template)))

(equal? (syntax->datum result0) (list 1 2 3))


soegaard2
2021-2-26 18:01:19

And then the solution becomes, (define result0 (with-syntax ([(num ...) (syntax (1 2 3))]) (syntax (num ...))))

(equal? (syntax->datum result0) (list 1 2 3))


soegaard2
2021-2-26 18:02:04

I’ll need to go over the other exercises as well.


soegaard2
2021-2-26 18:06:24

Wrt to your example, I suggest: (define methods '(web3_clientVersion web3_sha3)) (define hyphenated-methods (map underscore-camel->hyphens methods) (define (try4) (with-syntax ([(m ...) hyphenated-methods]) (syntax (begin (define m 1) ...)))) Note that the symbols must be rewritten before you use them in the template.


soegaard2
2021-2-26 18:07:38

Alternatively: (define methods '(web3_clientVersion web3_sha3))

(define (try5) (with-syntax ([(m ...) (map underscore-camel->hyphens methods)]) (syntax (begin (define m 1) ...))))


soegaard2
2021-2-26 18:09:15

Note that, if you want to use the example in macro, the list of methods needs to be available at compile time. Use begin-for-syntax to do that: (begin-for-syntax (define methods '(web3_clientVersion web3_sha3)) (define hyphenated-methods (map underscore-camel->hyphens methods)) (define (try4) (with-syntax ([(m ...) hyphenated-methods]) (syntax (begin (define m 1) ...))))


soegaard2
2021-2-26 18:09:36

Thanks again for the feedback.


evyatar2013
2021-2-26 19:47:32

hey, what’s the correct racket incantation to run a module and then embed yourself in a repl after evaluation (similar to drracket)



evyatar2013
2021-2-26 19:50:30

Thank you!


jjlammi
2021-2-26 22:16:54

When I add the missing rules of the ancestors to definition by hand, it works! See the definition lines 7 to 11 and results on REPL. However, it does not anything if REPL is used for entering the code lines, i.e. everything must be given as definitions and run as usually.


samth
2021-2-27 03:01:37

The problem with the repl is a bug, if you use a snapshot (see http://snapshot.racket-lang.org\|snapshot.racket-lang.org) starting tomorrow it’ll be fixed