3 ms·
I use clojure for 4 years now and I think I had to write macros only twice. In general, I'd advise against them and be wary of libraries that try to solve a lot
by dmichulke 11y ago
I use clojure for 4 years now and I think I had to write macros only twice. In general, I'd advise against them and be wary of libraries that try to solve a lot of things with macros, the main reason being they are not easily composable and make things implicit that should be explicit.
The parens become less of a problem the more you know about clojure. You will find ways to traverse a map with very few parentheses that will make you grasp the code very efficiently. To this end I would recommend anyone starting clojure to do a few clojure koans each day and check their solution against the best solutions. www.4clojure.com
Finally, the tests (assertions via assert, :pre and :post) are indeed THE thing to use for both documentation and type checking and it allows to have kind of static typing where you want it. Of course, exceptions will only occur during run-time but your tests check for errors during run-time anyway, so why force someone to do type checking at compile time?
- sklogic 11y ago> In general, I'd advise against them Why? Macros are the single most important productivity feature in Lisps. Macros allow to implement eDSLs trivially, in the most robust way possible. Yes, you need to follow a certain discipline, but once you get it, you won't ever want to touch a language without macros.
- dmichulke 11y agoMost of the macros in libraries were saving a pair of parentheses at the cost of making code more obscure and, well, less explicit. A few co-workers also liked macros alot so they did stuff that could have been done in functions. I suppose my experience is that clojure's core macros are sufficient and/or I never saw a good eDSL that would have been worse without macros. (Input is welcome) Also, I don't feel I missed out on something because the biggest productivity features for me are being functional, maps-as-objects + dynamic typing, destructuring, emacs (yeah I know), immutability, threaded execution via pmap, Java libs. However, I suppose these productivity features depend strongly on where you come from (for me: Java)
- sklogic 11y ago> Most of the macros in libraries were saving a pair of parentheses This is an epic misuse of macros. > and/or I never saw a good eDSL that would have been worse without macros eDSLs should almost never be implemented without macros (unless they're message DSLs). Macro, essentially, is a compiler. The only alternative is to implement an ad hoc interpreter. And compilers are much, much easier to write, debug and maintain than interpreters - for some very trivial reasons. Compilers can be split into sequences of very simple stages, each doing something simple and comprehensible. It's easy to debug, easy to insert additional steps in between, easy to cut off at any point and replace the backend with something totally different. Interpreters are deeply tangled, naturally, there is no way to modularise them. > the biggest productivity features for me are being functional Using macros and eDSLs is another huge step forward in productivity that will dwarf everything you liked so far in FP.
- eutectic 11y ago> The only alternative is to implement an ad hoc interpreter. You could also have your eDSL calls act as data constructors for an AST and then implement an `eval` function which invokes a run-time compiler.
- sklogic 11y agoThis is not any different from a macro. You still translate your DSL into your host language AST, with the only final step different - runtime eval instead of a compile-time macro. All my macros look like (defmacro something (dsl) (compile-dsl-whatever dsl)). You can always pass the same (compile-dsl-whatever dsl) to (eval ...).
- dkersten 11y agoI've been very successfully applying the data > functions > macros guideline. Yes, this makes eDSL's look very clojurey, but in practice I've not seen this to be a problem. That is: prefer a data-structure based DSL (eg Datomic queries) if possible. If not, prefer function composition. Failing that, macros to the rescue.
- huahaiy 11y agoMy understanding is that the Clojure community discourages the use of macro. The preference is to use data over functions, and functions over macro. The reason is that macros do not compose well. Yes, macros are good for developing DSLs, so they are mostly used in developing libraries, but most application developers do not need to use macro. The wide spread macro usage probably contributed to the fragmentation of CL community. Taking such lessons to heart, Clojure library authors tend to reuse commonly accepted DSL forms, e.g. hiccup is the DSL for writing HTML, and most authors have adopted it when developing their own libraries. I think this is a good thing.
- sklogic 11y agoThen the entire community got it all wrong. DSLs are much, much more composable than functions. You can easily compose just parts of DSLs, building new DSLs on top by combining semantic properties from the existing DSLs. It's just a very different way of thinking about programming in general, and many people just don't get it.
- kazinator 11y agoMacros look like the single most important productivity feature in Lisps only when we are comparing to languages that have borrowed almost everything else, so that we are discounting those other things, consciously or not.
- sklogic 11y agoI'd trade any language without macros to the same language, but with the proper macros added. And then I'll get all the features I want - lambdas, garbage collection, numeric tower, lazy evaluation, any imaginable type system, whatever else (of course, there are some limits, I would not be able to get an image-based system and a REPL if the host language runtime does not allow it). It's a nearly infinite flexibility, no other single feature or a combination of language features can do this.