Live data from Hacker News

Understanding the Power of Lisp (2020)

joshbradley.me

81–90 of 140 posts

Re: Understanding the Power of Lisp (2020)

#81
post #24
post #2

The thing is that trying to understand "the power of Lisp" via the toy interpreter from The Roots of Lisp[0] is like trying to understand "the beauty of the sea" after seeing a single five-minute YouTube video explaining it. It will give you the basic idea, but it won't tell you about macros, reader macros, compiler macros, and having the whole language always available to build your abstractions on; it won't tell yo…

I've learned Clojure. Tried and failed to see this unique power of macros. Truly asking for help: can you help explain what can I do with macros that I cannot do with functions? Or, maybe, cannot do with high quality or low complexity using functions?

Macros give you control over evaluation order. Fns don't.

   (or a b)
If a is truthy, b will never evaluate

Re: Understanding the Power of Lisp (2020)

#82
post #58

> Eric Raymond went so far as to say that understanding LISP is a “profound enlightenment experience.” Maybe this is true for language hobbyists or whatever, but every few years throughout my career, I went back to LISP or LISP-like languages and never found it super profound. Do I need to spend more time on a project? I just don't get the same excitement others seem to get.

> Do I need to spend more time on a project?

It depends on your interest. For me in particular Lisp was a "profound enlightenment experience" because:

1. I have been programming for a long time and had so many problems I could not(in practice) solve in any language but Lisp.

2. Lisp gives you two things no other language gives you: very basic Metaprograming(it can read itself) and the ability to design your own DSL(domain specific language).

3. It also gives you REPL(Read eval print loop) immediate feedback other languages tried to copy(but have not been able to replicate entirely).

Having said that, Lisp design is also obsolete today because it was mainly designed in the 1970s. I hate it (specially parentheses and interface) and love it at the same time.

>Do I need to spend more time on a project?

You don't need to do anything, nobody needs to learn a new language for living.

The fastest way to understand what Lisp is all about is to be near a very proficient Lisp programmer, because he will be able to run circles around you solving problems.

That combination of someone proving to you what is possible at the masters level and natural human competition is probably much more powerful than anything else you could do on your own.

We are humans after all, we see a great hunter hunt and only then we desire to be as good as he is and learn from him. We do it subconsciously and that is the reason elite tennis players sell razors so well, people copy naturally those who they admire without being conscious about it.

Re: Understanding the Power of Lisp (2020)

#83
Having only tried out Scheme and Common Lisp (I loved them both, what little I experienced) in my CS classes back in the day, I have always wondered how complex programs in these languages actually look like.

I feel most examples just are the same list-manipulations / Fibonacci- / prime number calculation ad nauseam.

Are there any active projects out there that Lisp family programmers would recommend as a good example of what the language can do and be used for (preferably with common elements such as networking, db connections etc)?

Re: Understanding the Power of Lisp (2020)

#84
post #34

I have the same response to this as I do to every other lisp article. It’s cool, but how have you personally leveraged this advantage that everyone talks about? What big lisp project has the author contributed to, such that they have enough data to sing it’s praises?

I don’t consider myself a Lisp wizard and mostly stick to pretty simple code but to name a few cool things that would have been tedious or impossible in another language:

- A desktop application for a bank in which not only the gui’s content but the look and structure was generated or changed on the fly mimicking the status of a database.

- An interpreter in which most of its classes and methods were automatically generated. The Java rewrite took pretty nasty code generation hacks, visitor pattern madness and way more LOC.

- Some program with a huge cache (glorified hash table) that was not catching simple strings or objects as keys but actual code as s-expressions. I always thought that was pretty cool.

Most if not all of my Lisp (and Perl) projects have been eventually rewritten in Java, and not exactly due to technical issues. I mostly put up with Go these days which is great most of the time but of course makes me yearn for a more powerful language or wished I never dabbled with those.

Re: Understanding the Power of Lisp (2020)

#85
post #44
post #24

Earlier quoted context omitted.

I've learned Clojure. Tried and failed to see this unique power of macros. Truly asking for help: can you help explain what can I do with macros that I cannot do with functions? Or, maybe, cannot do with high quality or low complexity using functions?

Well, for Clojure ... Spend 5 minutes playing with -> [0]. Appreciate how pretty it makes the code and how nice it is for laying out sequential operations. What a fun operator. Then try to implement it yourself as a function. When you discover that you can't, you will have discovered the unique power of macros (note the docs link to source code so you can see the readable 8-line macro implementation). You've also lea…

Note that this cannot be written as a function only because Clojure uses strict (call-by-value) evaluation everywhere and has no way to change this (other than Macros). In theory languages could provide annotations to allow a user to specify whether parameters are call-by-value or call-by-need. Haskell and Scala both provide this.

But I don't think this is a bad example at all, I tend to think of macros as "extending the language/compiler", since they have access to the abstract syntax tree of their inputs, which is what is being done here.

Re: Understanding the Power of Lisp (2020)

#86
post #81
post #24

Earlier quoted context omitted.

I've learned Clojure. Tried and failed to see this unique power of macros. Truly asking for help: can you help explain what can I do with macros that I cannot do with functions? Or, maybe, cannot do with high quality or low complexity using functions?

Macros give you control over evaluation order. Fns don't. (or a b) If a is truthy, b will never evaluate

Note that functions in other languages, like Haskell and Scala, do allow some control over evaluation order. One can annotate function parameters to achieve call-by-value or call-by-need as required.

Macros can analyse/manipulate the abstract syntax tree of their inputs, so I think of them as extending the compiler.

Re: Understanding the Power of Lisp (2020)

#87
post #81
post #24

Earlier quoted context omitted.

I've learned Clojure. Tried and failed to see this unique power of macros. Truly asking for help: can you help explain what can I do with macros that I cannot do with functions? Or, maybe, cannot do with high quality or low complexity using functions?

Macros give you control over evaluation order. Fns don't. (or a b) If a is truthy, b will never evaluate

(or (lambda () a) (lambda () b))

Now you only need to define the function OR...

Re: Understanding the Power of Lisp (2020)

#88
post #40
post #37

Earlier quoted context omitted.

Here's a simple example you can't write in most languages. (first-working (get-it-from-the-cache) (get-it-from-the-database) (get-it-from-an-external-api) (compute-it-the-slow-way) default-value) Note each of those functions could throw an exception. You want to ignore it (or you could log it) and move on to the next.

Maybe I am missing something. Here's how I might write something equivalent in Python: for f in GetFromCache, GetFromDatabase, GetFromAPI, Compute: try: return f() except Exception as ex: log(ex) return default_value (You'd probably define a custom exception class for your application that represents the kinds of errors you can tolerate, so you don't end up swallowing programming errors, but you get the idea.)

That would be the time, where I would consider to write a macro. The macro would capture similar logic, but would provide me no-overhead syntax.

In Common Lisp:

    (defmacro return-first-working (&body body)
      "Expects a sequence of expressions as body.
       Returns the value of the first expression of body
       which returns without error."
      (when body
        `(handler-case ,(first body)
           (error ()
             (return-first-working ,@(rest body))))))

    (return-first-working
      (error "hi")
      (error "there")
      (error "!")
      "hello-world"
      (error "wtf?"))
That way I can easily implement primitive control structures, without resorting to add to my code visibly complex things (like making expressions into functions).

Above is a recursive macro, which takes its subexpressions and returns a simplified expression, reusing itself. That way code transformation itself is described as a recursive process. One can learn how to apply such transformation patterns to the code itself and then it gets relatively easy to write.

Re: Understanding the Power of Lisp (2020)

#89
post #24
post #2

The thing is that trying to understand "the power of Lisp" via the toy interpreter from The Roots of Lisp[0] is like trying to understand "the beauty of the sea" after seeing a single five-minute YouTube video explaining it. It will give you the basic idea, but it won't tell you about macros, reader macros, compiler macros, and having the whole language always available to build your abstractions on; it won't tell yo…

I've learned Clojure. Tried and failed to see this unique power of macros. Truly asking for help: can you help explain what can I do with macros that I cannot do with functions? Or, maybe, cannot do with high quality or low complexity using functions?

Lack of macros makes nothing impossible, but also makes many things harder. I think of them as code generators, tiny compilers on a micro scale; they are invoked by the proper compiler during compilation phase, as opposed to runtime, allowing you to inject code that you'd otherwise need to inline by hand.

It's possible to write pretty complex things like control flow abstractions using just structures and functions/methods, e.g. a CL-esque condition system in Java which only uses classes, static methods, and Java lambdas[0] for its syntax. Possible, but also IMO ugly when compared to the CL counterpart, because the low-level but irrelevant details (such as instantiation via `new` or generics) are still presented to the programmer.

[0] https://github.com/phoe/cafe-latte

Re: Understanding the Power of Lisp (2020)

#90
post #45

Earlier quoted context omitted.

I know a startup that hired a Marxist-collective group of programmers. I was told this story years ago, and they were acquired, so I’ll just name the firm - “White Ops”. This story is so absurd that I’m naming the firm in hopes someone can verify the accuracy of this, although I trust the person that told me the tale. The programmers were based in Canada and only wrote in Haskell. The CTO of White Ops had apparently…

You described every enterprise Java project developed by contractors except that it can’t be rewritten because Java is THE enterprise language.

SOLID and a dozen of DPs and you get there pretty fast. Then you rewrite by another team with their interpretation of SOLID and another dozen of "better suited" DPs and you get there again. On 3rd iteration you just buy something as a service that covers 80% of your needs and consider the rest 20% non-essential business. And life is finally good.
Post reply on HN