
PLT Scheme used to supply a defmacro
; it’s still available as a package: https://docs.racket-lang.org/compatibility/defmacro.html

But for “casual” macros I’d recommend https://docs.racket-lang.org/syntax/Defining_Simple_Macros.html#%28form._%28%28lib._syntax%2Fparse%2Fdefine..rkt%29._define-syntax-parse-rule%29%29

gensym and hygiene may not be a big deal, but if you want some quick casual macro, it’s nice not to deal with them.

It’s nice for things mostly to “just work”, especially when a macro expands into N other macros that get expanded, wrt hygiene and error messages and all that.

Yeah, I think macros generating macros would be a nightmare to write without hygiene. It’s like… quoting/unquoting/gensym everywhere.

Many common lispers say this is not a problem in practice? (2006 Pascal Constanza Responding to ‘ Lisp is not an acceptable lisp ’ )



“PLT Scheme”, so cute :heart: > Posted on Aug. 26th, 2009

Yeah, I’m not so sure it’s still “no big deal” when you write a library like Racket’s class system or typed Racket almost entirely out of macros.

Well, in that case you could just write a macro that helps you with that, and takes care of checking if the identifiers are bound or not, and maybe design a kind of template language that makes the whole simple. Oh, wait…

Those are weak arguments, IMO. It’s like arguing pointers are bad because you can shoot yourself in the foot with them. So is dynamic typing, garbage collection or reference counting or hammers, table saws, and pretty much every other tool humans have ever made. :wink:
Some tools are trickier or require a little more care to work with. And - for many problems - they may be a poor choice. Other tools may be better suited or easier for newcomers to work with, etc. But every level of abstraction intended to simplify also takes away. It’s unavoidable. This is true whether talking about programming tools, physical tools, et al.
It’s up to the experienced user to decide what level of abstraction gives them - for the problem at hand - the best combination of freedom, safety, performance, expressiveness, etc.

I agree with you about choosing the best fit for the problem/challenge/scale at hand. I think Racket does exactly that. It lets you do casual macros (“I just want to DRY some code in this one module”) easily/safely. It lets you hack raw syntax with no guard rails, if you want take that upon yourself. It lets you build a “tower of languages” reliably. All of these.
Of course, having so many choices, it’s not always easy to know which ones to use, or even sometimes that they exist. (I feel like I know a moderate amount of the “syntax zoo”, but every few months I’m surprised to learn something else — sometimes because it was added relatively recently, but sometimes something that’s been around for many years. :smile:)

So that’s a communication problem, somewhat like Alexis was tweeting about, although IIUC a different problem.

Specifically for eval-when, I’d recommend reading Matthew’s classic: https://www.cs.utah.edu/plt/publications/macromod.pdf\|https://www.cs.utah.edu/plt/publications/macromod.pdf

One area I think Racket (and other languages) do a good job is in having a pretty good initial starting point of expressive + performant + safe that you can start working with until you have a much better handle on what the problem actually is. Then you’ll be in a much better place to make further choices within the Racket ecosystem or switch to something else entirely if that’s what the problem calls for.

I don’t know if there is a video of Matthew presenting this paper, but this video with @samth is pretty good. https://www.youtube.com/watch?v=pK2E63mhRxI

@massung I expect you’ve already read <https://www.cs.utah.edu/plt/publications/macromod.pdf|Composable and Compilable Macros> , but if not, it’s a good read, and I found the ideas compelling.

I lean toward minimalism (or at least I tell myself that), so I was attracted to Scheme over CL. Racket is hardly minimal compared to Scheme, but the more I looked into it, the more acceptable I found the “extra” stuff with respect to macros, modules, etc. But, it’s certainly subjective.

lol - sorry @camoy - just noticed you posted the exact article :)

I think the main thing that people from CL dislike is hygiene, which is somewhat orthogonal to the module system / eval-when
/ phase system.

Doesn’t hygiene make it easier to combine many macros in interesting ways though?

It’s a yes for me. But I guess @massung is not gonna be convinced by this assertion.

With simple macros I’ve found syntax-case
and hygiene do make macros better/easier than in CL. But, overall I like the CL macro system more. I don’t think that’s a knock against scheme/Racket, but more just a testament to what I’m familiar with and that my personal abstraction level “sweet spot” is generally lower than that of others.

I’m sympathetic with this position as that learning is a sunk cost, and racket defmacro is available for those in that situation.

I just like there to be either very little abstraction or so much that what I’m doing is highly opinionated (and I don’t have to think much rather than just doing). In between those just frustrates me.
As an example of that in CL vs. Racket macros… in CL there’s literally one way to make a macro: defmacro
. Yes, it’s a bit lower level, but that’s the entry point to making it happen. The only additional piece of knowledge I need is gensym
(and maybe eval-when
, but damned if that isn’t rare as can be). In Racket that’s not the case. There’s literally…
• define-syntax
• define-syntax-rule
• syntax-rules
• syntax-case
• syntax-id-rules
• … The list goes on. Then there’s #'
for syntax quotes, syntax quasiquoting, etc. All of these things are quite valuable and nice to have, but they are abstraction layers. I - personally - don’t know that they make things easier as opposed to more confusing for newcomers.

In CL it’s all just cons lists. While in Racket we’re talking about lists + syntax objects. Those syntax objects are very valuable. But it’s… more. That’s all. :slightly_smiling_face:

Side-note: I think this “thread” has come up a few times in the past couple months. Could probably link to the last time it came up and everyone would just groan, nod, and move on :stuck_out_tongue_winking_eye:

> don’t know that they make things easier as opposed to more confusing for newcomers It also depends on whether the newcomers absolutely don’t know anything before, or they have an exposure to something similar but different.
When I TA’ed intro to CS, which uses Racket, people who don’t know CS before seem to have better time accepting S-exp, idea of linked list, etc. Whereas people who have seen Python will kinda fight against this “inferior” language.

And I think this is true for every transition from one to another lol

Yes! When macros has to take code apart and reassemble them and maintain the appropriate scopes in definition contexts, I can’t imagine how gensym could ever work.

The funny thing is I posted the tweet because I was responding to the aspect that it is more than just macros > Racket has largely failed to communicate its metaprogramming technology by continuing to call it “the macro system”, because it’s really a large collection of technologies for opening the compiler and runtime, and “the macro system” is the glue

Macro=glue

There’s a quote from Dijkstra that says: > It is practically impossible to teach good programming to students that have had a prior exposure to BASIC: as potential programmers they are mentally mutilated beyond hope of regeneration. I kinda feel like these days you could swap Python for BASIC and the quote would still be approximately as true as it ever was (by which I mean it is clearly hyperbolic, but there’s an element of truth in it) (said quote pinched from https://en.wikiquote.org/wiki/Edsger_W._Dijkstra#How_do_we_tell_truths_that_might_hurt?_(1975))

Fwiw, I just use define-syntax
with syntax-parse
. I think syntax-case
and friends should sorta be considered legacy at this point.

Not to say that there aren’t other parts of the Racket macro system that are definitely difficult for newcomers though.

I found this out the hard way. I wish this information was implied more often in literature about racket

( syntax-case
almost never being a better choice than syntax-parse
that is)

I have no experience doing formal and structured teaching of programming to people interested in CS. I have only taught some python to biologists who wanted to know as little programming as they could get away with. Counterintuitively I found python to be a very hard language to teach to this audience because you need to introduce too many similar and overlapping concepts before someone can make simple use of numpy and maybe some opencv. In order for a 5 line (useful) program to make sense I need to introduce most of the following one way or another: functions, arguments, operators, methods, classes, objects, expressions, statements, code blocks, positional/keyword arguments, evaluation as opposed to writing to standard output. It was very frustrating for everyone involved and people unjustly felt stupid that they had such a hard time understanding “the easiest programming language”.

yeah I really think we should push for the docs to more explicitly recommend syntax-parse
over syntax-case
throughout