The idea is that some repeated patterns can be encoded in a functions, but other repeated patters need more abstraction. Try to find some repeated pattern.
Some real example from a internal site for 500 users in the university:
The idea is that I have a parameter with the data of the current user, a parameter is like a global variable but each tread has it's own copy so it's "thread safe". Sometimes I want to iterate over all the users inside one of the administrations form. So I have to write in racket something like:
(The last three parenthesis should be in the same line, but if you like c-like formatting, let's put them in their own line.)
I had to repeat this pattern a few times. It is boring and error prone. Perhaps I have to add a lock for the user profile. Perhaps I need an special case if the user in the iteration is the administrator. But let's keep the example simple.
Now I can use a macro to define the pattern:
(define-syntax-rule (for/users body ...)
(for ([u (in-list all-users)])
(parameterize ([current-user u])
body ...
)
)
)
This is the simplest way to define a macro in scheme and racket. It has no error checks. It has no room for variants. There are more advanced methods to write good macros. One important point is that there is some magic to ensure that the variable `u` used inside the macro don't mess with a variable `u` defined outside the macro.
The nice part is that the macro looks almost like the code I want to repeat. I only need to use `body ...` in the definition in the first line and then replace the interesting part with `body ...`. Here is the magic! In the easy case, the macros look almost like normal code!
Now I can use it as any normal thing in the language, for example
(for/users
(writeln (user->name (current-user))
)
(define count 0)
(define sum 0)
(for/users
(set! count (+ count 1))
(set! sum (+ sum (user->age (current-user))))
)
(define average (/ sum count))
(writeln average)
I hope the examples are self descriptive.
The idea inside the lispy word is that users should write macros when it is necessary to write macros. Try to use them sparsely. Try to make them blend with the language. Try to make them intuitive to use.
A bad example of a macro is:
(define-syntax-rule (show x y)
(writeln (list y x y))
)
It's a bad macro because it looks like a normal function but the expressions are evaluated out of order and one of them is evaluated twice. So
(define n 7)
(show n (set! n (+ n 1))
(writeln n)
will show
(#void 8 #void)
9
but the user probably expect
(7 #void)
8
So write macros, but write them sparsely and wisely.
My recommendation is to enjoy Elixir, try to find repeated patters, try to enclose the patters in functions. When that fails try to write good macros. When you understand why you want more macros and more macros try racket (or scheme/lisp/clojure/...).
Some real example from a internal site for 500 users in the university:
The idea is that I have a parameter with the data of the current user, a parameter is like a global variable but each tread has it's own copy so it's "thread safe". Sometimes I want to iterate over all the users inside one of the administrations form. So I have to write in racket something like:
(The last three parenthesis should be in the same line, but if you like c-like formatting, let's put them in their own line.)I had to repeat this pattern a few times. It is boring and error prone. Perhaps I have to add a lock for the user profile. Perhaps I need an special case if the user in the iteration is the administrator. But let's keep the example simple.
Now I can use a macro to define the pattern:
This is the simplest way to define a macro in scheme and racket. It has no error checks. It has no room for variants. There are more advanced methods to write good macros. One important point is that there is some magic to ensure that the variable `u` used inside the macro don't mess with a variable `u` defined outside the macro.The nice part is that the macro looks almost like the code I want to repeat. I only need to use `body ...` in the definition in the first line and then replace the interesting part with `body ...`. Here is the magic! In the easy case, the macros look almost like normal code!
Now I can use it as any normal thing in the language, for example
I hope the examples are self descriptive.The idea inside the lispy word is that users should write macros when it is necessary to write macros. Try to use them sparsely. Try to make them blend with the language. Try to make them intuitive to use.
A bad example of a macro is:
It's a bad macro because it looks like a normal function but the expressions are evaluated out of order and one of them is evaluated twice. So will show but the user probably expect So write macros, but write them sparsely and wisely.My recommendation is to enjoy Elixir, try to find repeated patters, try to enclose the patters in functions. When that fails try to write good macros. When you understand why you want more macros and more macros try racket (or scheme/lisp/clojure/...).