4 ms·
It is one of the very few languages where the source code is made of a data structure that the language is very good at manipulating. Thus, writing code that g
by flavio81 9y ago
It is one of the very few languages where the source code is made of a data structure that the language is very good at manipulating.
Thus, writing code that generates code, be it at runtime or at compile-time, is downright easy in Lisp. This opens up enormous possibilities not found in other languages.
Also, on regular programming languages, your code executes only at run time. In Lisp, or at least in Common Lisp (and probably on Scheme as well), there are three times: Read time, Compile time, and Run time, and your code can selectively run at one of those three. This also opens up lots of possibilities.
Another feature is that it is really suitable to interactive development in a way that isn't matched by any other language except for Smalltalk. It allows, for example, changing the definition of a function while your code is running.
Now, two features that are particular to some Lisps:
Scheme has continuations. Continuations are like magic teleportation within your code. They are very powerful.
Common Lisp has the Common Lisp Object System (CLOS), possibly the most powerful OOP system out there. It rocks!
- Slackwise 9y agoWhenever I want someone to understand Lisp being a homoiconic metaprogramming language, I link them this: http://www.defmacro.org/ramblings/lisp.html http://www.defmacro.org/ramblings/lisp.html
- flavio81 9y agoThat's a great link!
- geokon 9y agomaybe someone can help me understand. I now get homoiconisity but the example he uses doesn't seem to explain why the macro is needed. He explains a problem that can be solved by writing a function. Instead he presents what seems to be in effect an unevaluated function... so what's the point?
- yorwba 9y agoI agree that the macro example is not chosen well. Macros are just functions that take their arguments unevaluated and output code, so each macro call could be replaced by a function call where the arguments are wrapped in a list and the function executes the code directly instead of generating it. Then the only reason you'd have to use macros is if you want to do something at compile time. Like generating specialized code so the compiler can optimize it, instead of reinterpreting the describing data on each invocation. Or like reading the database schema to generate accessors.
- geokon 9y agoBut as the article states, compile time is (or can be) at runtime.. so it's a bit difficult for me to wrap my head around its practical effect :)
- Jach 9y agoLisp has several time phases that may or may not interleave, so yeah it can be confusing.. but keeping things simple and mostly only thinking about macros at compile time or read time can still go a long way. Ultimately an important and practical high level effect is macros let you create new syntax, not just computation at compile time to save some function calls at runtime. Want infix math? You can have infix math: https://github.com/rigetticomputing/cmu-infix https://github.com/rigetticomputing/cmu-infix Going crazy with lexical nesting (similar to callback hell, but imagine each callback needs to close over the environment it's called from, not just defined in)? A one-liner might help: https://fare.livejournal.com/189741.html https://fare.livejournal.com/189741.html Want powerful looping constructs, powerful OOP, pattern matching, etc? Of course you can stick with simple macros that are little more than function wrappers, but you can do a lot more.
- Chattered 9y agoMacro examples are often poor, and my advice is to always favour functions, since then you are working with actual values. For instance, with-open-file should be a higher order function, not a macro as it is in CL. That leaves a few other uses: macros as compiler extensions for generating fast code (see "Paradigms in Common LISP" for a lovely example of a parser generator). But heed warnings about premature optimisation. It leaves macros for novel binding strategies. List comprehensions, do-notation, destructuring-bind, pattern matching, CL's LOOP and macros that anonymously bind a pronoun like "it". I have no shame in using macros for really succinct control structures where delaying evaluation with a lambda would just look gross (see "or" and "and" macros), but maybe that's just a cry for lazy evaluation :P
- tunesmith 9y agoThe problem for me is that I've learned to avoid macros in other languages. It seems to me that when you've got a fairly complex program, you need a fairly complex mental model of what the program "is" to understand it. But if you introduce macros, or code writing code, then you have a much more complex mental model since now even what the code "is" can change. What is it about lisp that makes this an easier sell?
- reikonomusha 9y agoWhen the "atoms" of your language are causing whatever problem you're solving to be difficult to express, then it may be wise to introduce new "atoms" to make the idea easier to express. The new atoms are supposed to communicate intent faster and more concisely, and decrease the burden of understanding what's going on. That's the role of an abstraction, especially syntactic abstractions.
- willismichael 9y agoIt is true that even in a Lisp, unfettered use of macros can result in write-only code, so you do have to be careful about what kind of cognitive burden you are imposing upon people who will have to read your code. With that said, I tried to learn about metaprogramming in a number of other languages, and Lisp is the first one with a metaprogramming model that I could actually grok, because the meta-language is equivilant to the language itself. Lisp macros are more or less just plain old code that manipulates data structures. When I'm working on a lisp project, I give myself a budget of a very small number (often just 1 or 2) of magic macros that I can build for it. Other than that, I only use macros in the core library, or well-known third party libraries that other people are likely to be familiar with.
- flavio81 9y ago>The problem for me is that I've learned to avoid macros in other languages. Macros in other languages are significntly unlike Lisp macros. You should take a look at the Practical Common Lisp book (available for free online) to have an idea on how you can easily leverage Lisp macros for more readable, succint, easy to understand code. >But if you introduce macros, or code writing code, then you have a much more complex mental model In Lisp, you use the different tools available (macros, CLOS, readtables, etc) to achieve a simpler translation between the problem domain and your actual source code. If you are using them to create more convoluted, harder-to-understand code, then "you're doing it wrong", just as you can, for example, write rather clean C code versus code that would win the IOCCC (International Obfuscated C Code Competition).