I've been following the list since I started to play with Racket (~6 months), but I've never had the courage to write a macro. It was like a kind of magic that I wanted to manipulate, but I was afraid to do that.
## Context. Story time! I discovered Racket because a friend asked me to teach him to how to program. Inspired by the Lego kit for robotic that I saw years ago, I created a little language (move forward and rotate) and started to ask him to accomplish some tasks with the language. The day after that, I searched for "teach kids how to program" (my friend is not a kid .. but what would be a better way to teach someone?) and I found "Turtles" which led me to read an article from Papert. The text was mind blowing. I am Brazilian, and I can't say for all of us, but I was raised with a black/white (or right/wrong) mindset. This mindset shaped the way that I've been approaching life. Basically, I always had one chance to get things right. Yeah! I love programming and it is a nightmare to try to get things right at first (it is so easy to be stuck with this mindset). So, even though I loved programming, I also hated it. But the ideas in Papert's article was liberating, I've never thought that exploring without fear of failure would be so natural. I wanted more of it! I kept searching and found "The Little Lisper", which I consumed it vigor. Then I found some of Matthias' work in programming education and finally Racket. As I said, I've been following the list for a while. And man, that is a wonderful community. OK! My friend and I never really started those classes, but I am grateful for his first interest on that. I've learned that if I want to learn something I have to explore it without fear! Then, I decided to do the [Advents of Code 2018](https://adventofcode.com/2018) in Racket. My goal was use functional programming and immutability as much as I can. I started with Typed Racket, but I found hard to freely explore while having to satisfy the compiler. `#lang racket` was the best option for me. What about writing macros? I've been postponing it until April 26th. I was watching [Inside Racket Seminar 6. Sam Tobin-Hochstadt on match](https://www.youtube.com/watch?v=IikGK8XP5_Q) and thinking how these people can write such big programs in an untyped laguange. I remembered to see something about "bottom-up programming" in [Racket pages](https://docs.racket-lang.org/style/Units_of_Code.html) and I started to search for it. I found the key idea: building the solution from bottom-up give you chance to build a language for the problem. It became clear when I saw [Daniel Friedman & Jason Hemann - Implementing a microKanren](https://www.youtube.com/watch?v=0FwIwewHC3o) in action (by the way, I am a big fan of Friedman) and [Bottom Up vs Top Down Design in Clojure - Mark Bastian](https://www.youtube.com/watch?v=Tb823aqgX_0). I went back to my problem and found that I have a code like (define empty-unit #\.) (define (empty-unit? v) (eq? #\. v)) (define rock-unit #\.) (define (rock-unit? v) (eq? #\# v)) which I really wanted to express like (define-enum unit (empty #\.) (rock #\#)) It is time for writing my first macro! ## Macro time! My first try was something like this (define-syntax (define-unit.wrong stx) (syntax-case stx () [(_ name value) (let ([name? (string->symbol (format "~a?" name))]) #'(begin (define name value) (define (name? other-value) (eq? value other-value))))])) which failed with ; /Users/wander/myprojects/aoc/2018/day17.rkt:118:48: name: pattern variable cannot be used outside of a template ; in: name ; [Due to errors, REPL is just module language, requires, and stub definitions] I didn't understand the error message, and had no idea of how to move forward. I searched the error message and found [Greg Hendershott's Fear of Macros - Pattern matching](https://www.greghendershott.com/fear-of-macros/pattern-matching.html) (by the way, I am big fan of Greg). After reading his write-up, became easier to read the Racket documentation. That was my first macro: (require (for-syntax racket/syntax)) (define-syntax (define-unit stx) (syntax-case stx () [(_ name value) (with-syntax ([name? (format-id #'name "~a?" #'name)]) #'(begin (define name value) (define (name? other-value) (eq? value other-value))))])) (define-unit empty-unit #\.) (define-unit rock-unit #\#) (define-unit dry-unit #\d) (define-unit water-unit #\~) Dude! I was so excited! I did my first macro and it wasn't that scare. I barely could sleep because I did something cool and I also wanted to improve my solution with a "more complex syntax". The next night, I did my second macro: (define-syntax (define-enum stx) (syntax-case stx () [(_ name (e v) ...) #`(begin #,@(for/list ([x (syntax->list #'((e v) ...))]) (define xs (syntax->list x)) (define e-name (car xs)) (define e-value (cadr xs)) (with-syntax* ([elem (format-id e-name "~a-~a" #'name e-name)] [elem? (format-id #'elem "~a?" #'elem)] [value (cadr xs)]) #'(begin (define elem value) (define (elem? other-value) (eq? elem other-value))))))])) (define-enum unit (dry #\d) (empty #\.) (rock #\#) (water #\~)) (unit-dry? unit-empty) ; returns #f ## Thanks you all My journey has much more than I shared, and there are many others that inspired me up to this point. Thank you all! In short, I am felling right now on shoulder of giants! -- You received this message because you are subscribed to the Google Groups "Racket Users" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. For more options, visit https://groups.google.com/d/optout.

