badkins
2021-2-20 17:41:36

So, just a few seconds into Sam’s “The Great Metaprogram-off” talk, and I learned something: (define-syntax (simple s) #'5) simple I did not expect that to work w/o parens.


zafar.huma
2021-2-20 17:44:11

@zafar.huma has joined the channel


soegaard2
2021-2-20 17:44:29

FWIW I think “identifier macros” were introduced with syntax-case . As far as I remember, they weren’t part of the (older) RnRs specs.


badkins
2021-2-20 17:46:18

How is it possible that simple and (simple 'a) produce the same thing?


soegaard2
2021-2-20 17:48:15

The macro expander in both cases call the same syntax transformer. The syntax transformer in the example receives either #’simple or #’(simple ’a) — but in the example the transformer doesn’t look at input (stx is ignored), and always returns the same output #’5.


badkins
2021-2-20 17:54:24

Yes, but: (define (foo . a) 5) (foo 'a) (foo) foo Produces: 5 5 #<procedure:foo>


badkins
2021-2-20 17:55:18

i.e. there’s a fundamental difference between function application and referring to the function.


greg
2021-2-20 17:59:07

Another fundamental difference is between function application, and macro invocation when expanding. :slightly_smiling_face:


soegaard2
2021-2-20 17:59:48

Let’s say simple is associated with a a syntax-transformer t. The macro expander needs to do something, both when it it sees simple (looks like a variable reference) and when it sees (simple 'a (looks like a function call). The simplest solution is to call the same transformer - and then let the whoever wrote the transformer decided, whether different things happen or not.


badkins
2021-2-20 18:00:06

I realize that @greg, but I still don’t see why simple and (simple) are equivalent


greg
2021-2-20 18:00:36

I didn’t mean to be flippant, I just mean that how the macro expander treats use sites needn’t be the same.


greg
2021-2-20 18:00:56

@soegaard2 actually explained what it does do


badkins
2021-2-20 18:00:57

Ok, I think @soegaard2 just explained it - there’s some hand wavy stuff going on in macro expansion :)


soegaard2
2021-2-20 18:00:58

(syntax-parse stx [(simple . more) <standard-macro-call>] [simple:id <looked like a variable reference>])


badkins
2021-2-20 18:01:37

At this point in my understanding, I think that is a bug, not a feature though :)


badkins
2021-2-20 18:02:00

I much prefer explicit over implicit, but I’m sure there must be some advantages to the implicitness that I’ll discover later.


badkins
2021-2-20 18:03:11

By “bug” I guess I’m referring to the magic in define-syntax - seeing the separate cases in the call to syntax-parse seems fine.


greg
2021-2-20 18:04:00

I mean there is some implicit magic in having macros at all, and giving more power to the macro writer. But I see what you mean. What would you expect simple alone to do instead? error?


badkins
2021-2-20 18:04:38

Yes, I think so, given just what is shown in the example i.e. it doesn’t match.


badkins
2021-2-20 18:05:27

is waiting for the upcoming, “Meta-programming in Racket” book :)


badkins
2021-2-20 18:06:19

Which, by the way, would do more than Rhombus for recruiting new Racket users IMO. There. I said it.


kellysmith12.21
2021-2-20 18:08:10

The expressive power of Racket’s macro system is so great that, I suspect, you’d need a whole series of books, to cover the topic properly.


badkins
2021-2-20 18:09:38

Possibly, but a well-written first book would do wonders, and the parens objection would be shown to be the red herring it is.


kellysmith12.21
2021-2-20 18:11:48

Beautiful Racket is a good book to start with.


greg
2021-2-20 18:13:42

btw I imagine the motivation was to let a macro return a function when that could make sense. You know, how maybe you try to supply a macro to a function like map, but it doesn’t work? This makes it possible to write a macro where it could work (if that makes sense for the macro).

And, if your syntax transformer does not define that default case, you do get an error as you would like.


badkins
2021-2-20 18:13:58

Very good point @kellysmith12.21, and I’m ashamed to say that, though I bought it, I haven’t actually read it yet! I’ve been so busy coding “normal” Racket, that I haven’t made the time to study the meta-programming side. I also appreciate Greg’s “Fear of Macros”. I mean, there’s a lot of great info/documentation, I don’t mean to imply there isn’t. My personality just learns better with a well structured book, in most cases. I’ll shut up until I finish “Beautiful Racket” - it may fill in the gaps I need.


greg
2021-2-20 18:16:16

(define-syntax (simple s) #'5) is a very minimal syntax transformer that almost no one writes, ever. :slightly_smiling_face:


greg
2021-2-20 18:17:12

It does exhibit the surprise factor.


greg
2021-2-20 18:23:45

Silly example: #lang racket/base (require (for-syntax racket/base) (rename-in racket/base [and rkt:and])) (define-syntax (and stx) (syntax-case stx () [(_ v ...) #'(rkt:and v ...)] [_ #'and-function])) (define (and-function . vs) (andmap values vs)) (and #t #f) (apply and (list #t "There, I 'fixed' and."))


badkins
2021-2-20 18:27:02

Interesting. That example is much more clear due to seeing the specific cases.


samth
2021-2-20 19:29:35

I think the confusing part is that it looks like it doesn’t “match” because the definition looks like a function, but there’s no matching happening at all. The seemingly function nature is because all macros are functions from syntax to syntax, not because this is a macro that has to be used like a function.


samth
2021-2-20 19:30:30

If you’re expecting all macros to do some pattern matching based on syntax, then you might guess that there is something there that matches an application like form, but there really isn’t.


badkins
2021-2-20 19:57:32

I think the confusing part for me is having two different expressions (one w/ parens, one w/o parens) produce the same result.


badkins
2021-2-20 19:58:16

i.e. if simple produced 5, but (simple) produced a compile error, it would be less confusing :)


badkins
2021-2-20 19:58:41

hence the surprise


kellysmith12.21
2021-2-20 19:59:30

You can certainly implement simple so that it has that behavior.


badkins
2021-2-20 20:05:15

Macro stepper shows: (define-syntaxes (simple) (lambda (s) 🔒(t-quote-syntax 5))) (#%app call-with-values (lambda () (quote 5)) print-values) (#%app call-with-values (lambda () (quote 5)) print-values) so it appears to have expanded simple to a function call


badkins
2021-2-20 20:06:19

Although the macro stepper did not expand define-syntaxes - if it had, the mystery may have been cleared up :)


kellysmith12.21
2021-2-20 20:06:48

Actually, it expanded simple to (quote 5).


kellysmith12.21
2021-2-20 20:07:37

Because you’re using #lang racket, all module-level expressions are implicitly wrapped to print.


badkins
2021-2-20 20:07:41

Why the need for call-with-values then?


badkins
2021-2-20 20:08:19

I was referring to the invocation of simple


badkins
2021-2-20 20:08:40

not to be confused with the invocation of (simple) which is the line above ;)


badkins
2021-2-20 20:09:06

here’s the full source: (define-syntax (simple s) #'5) (simple 'b) simple


kellysmith12.21
2021-2-20 20:10:12

For printing, each expression is wrapped in a thunk (the zero-argument lambda), which is called by call-with-values, and all the resulting values are passed to print-values.


badkins
2021-2-20 20:12:47

Yes, I skipped to the end which just confused the issue. Stepping through makes more sense.


kellysmith12.21
2021-2-20 20:15:48

The define-syntaxes form was not expanded because it’s a primitive form in Racket; it can’t be expanded any further.


badkins
2021-2-20 20:19:45

Ok, I just got @samth’s comment above. It took me adding a second param to experiment e.g. (define-syntax (simple s t) #'5) :) Maybe (define-syntax (simple stx) #'5) would’ve gotten me there sooner :)


badkins
2021-2-20 20:22:26

World of difference between (define-syntax (simple s) #'5) and (define-syntax-rule (simple s) 5) even though they’re also very similar :)


samth
2021-2-20 21:29:39

Yes, I just used a shorter variable name because I was live coding, but stx would be clearer


jestarray
2021-2-21 01:09:00

event:/ui/chest_open i need to extract “chest_open” from this string, so ill need to find the index of the last slash going backwards and substring it. Is there a built in way to do this in the standard library before i write this myself :0?


samth
2021-2-21 01:19:41

I would use string-split or regexp-split


jestarray
2021-2-21 01:22:28

ohhhhhhhhhhhhh


jestarray
2021-2-21 01:22:51

completely crossed my mind lol, yeah ill just use string split and take the last el of the list