Ask HN: How do you “get” Lisp?
I read most of SICP, and believe me I like the concepts the book puts forward. But I still don't get Lisp. I understand some of the merits: code as data, functional, minimal uniform syntax (s-expressions), macros (meta-programming), etc. But I fail to _appreciate_ those features in the same way I appreciate features in other languages. For example, I can instantly appreciate Elixir's pattern matching capability because it makes control flow fades into the background (in addition to simultaneously destructuring variables), removing a lot of noise; I can appreciate its pipe operator because it makes data flow fades into the background as well, letting me focus on logic composition.
What's the best way to develop an appreciation of Lisp, given that I learn best through examples that clearly demonstrate somethings's value, not by reading a laundry list of features?
20 comments
[ 2.7 ms ] story [ 64.2 ms ] threadI know many people are averse to the idea of macros that makes Lisp so malleable (you can add syntactic abstractions like in-fix expressions etc.) but the same people are not averse to adding new types with classes or new "operators" with functions. I find it curious that many are comfortable at stopping the level of abstraction at just that (types and operations). For some reason, the idea of abstracting away syntax itself or dynamic function definitions (macros) is unpalatable. Why should the comfort for abstraction stop just there? Just like one can make a mess with types and functions, one can make a mess with macros. Just like one can write beautiful and elegant types and functions, one can write beautiful and elegant macros. Does the aversion to macros come due to the traumatic experience people relate to when they think of C/C++ macros?
The main advantage of Lisp/Scheme are the macros. The s-expressions are good because they make writing macros much easier. You don't have to mentally translate from the real language to the internal representation while writing macros.
I made a quick search and Elixir has macros. Do you write macros in Elixir?
The short answer is that Lisp/Scheme had real macros before it was cool.
Where can I find a practical example/tutorial/guide that demonstrates this in the context of building an actual application? I'm sincerely curious.
> I made a quick search and Elixir has macros. Do you write macros in Elixir?
Not much. It's something not encouraged by the language designer and community (since it can result in a lot of "magic" that is hard to understand), and I rarely found myself needing them.
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/...).
[0] https://alarm.cti.depaul.edu/lisptutor/login
As for pattern matching, try something like this https://cs.uwaterloo.ca/~plragde/flaneries/FDS/index.html you'll see how patterns you find by yourself can just be specified and matched, making it much easier to take apart things like suffix trees.
[...and additionally maybe expend the effort to absorb a sizeable practical codebase that others have written]
Maybe the answer to the question will ultimately be "It's not for me", but an experiential approach is the only way to reach an answer that is satisfying.
Ideally I'm looking for the equivalent of Michael Hartl's Ruby on Rails Tutorial. I'm not a ruby/rails developer, but I did follow his tutorial and it was one of the best guides I've followed (pedagogically speaking).
I would be curios if there are a set of guided lessons in Lisp with guided projects. I would like to revisit this language as it is truly an elegant language.
That is exactly what I'm looking for. Practical guidance for building real world applications. If the answer is "Lisp is not for business applications", then fine, at least I have my answer.
If you ever encountered a syntactic limitation in any language, you could go to Lisp and work your way around it either with macros or even simple control flow.
I would recommend to skim through Peter Norvig’s PAIP to get a taste of it. Then, as another user suggested, writing your own pattern matching library would be a great exercise.
The Lisp that's more like Erlang(Elixir). The one that was developed for commercial applications programming is Common Lisp. For me, the book that shows the power of Lisp for applications programming is Norvig's Paradigms of Artificial Intelligence: Case Studies in Common Lisp https://github.com/norvig/paip-lisp
Common Lisp is the result of consensus among industry stakeholders. There is meaningful consistency but no commitment to purity or theory or dogma. More about what people are (were) doing than what "people should do".
YMMV.
---
Changing gears back to your original question, Racket has pattern matching. [1] [2]
[1]: Racket Guide: https://docs.racket-lang.org/guide/match.html
[2]: Racket Reference: https://docs.racket-lang.org/reference/match.html
BTW it is important realise that Common Lisp and Scheme have significant differences. Personally I prefer gnuScheme. I hear that many business applications prefer to use SBCL.
But where does that stuff come from? Structural pattern matching appeared in Lisp.
See papers like:
Format-directed List Processing in LISP [1966]
https://apps.dtic.mil/dtic/tr/fulltext/u2/633242.pdf
METEOR: A LISP Interpreter for String Transformations [1963]
https://dspace.mit.edu/handle/1721.1/6106
I'm pretty sure that the word "destructuring" comes from the Lisp culture. Fifteen, twenty years ago, if someone used "destructuring", it had to be a Lisp programmer.