Live data from Hacker News

Why I still Lisp

mendhekar.medium.com

1–10 of 240 posts

Re: Why I still Lisp

#3
> What improves (and guarantees) software quality is rigorous testing. To deliver high quality software, there is no other solution.

This is 100% false. You can’t inject quality into a bad design via testing. You can’t guarantee quality or correctness through testing. Testing is the second worst place to find errors.

You get a MUCH higher roi by producing thoughtful written designs and getting them peer reviewed. And again with code reviews. (Peer review is best but self review can also be very effective.) I’m not saying don’t test — testing is valuable, especially because it forces you to design for testability, and a suite of automated tests is valuable when making changes later.

Re: Why I still Lisp

#4
> Languages based on the λ-calculus make it really easy to “play back the code” in your head.

This really depends on the expression.. I've seen behemoth expressions such that you have no choice but write down intermediate results, or start explicitly breaking it down into sub-bindings so you could step through the code. And yes, you can usually step through subexpressions in the debugger, but if you have to debug anyway, it hardly matters that you can 'play back' the code in your head.

I also noticed there is a tendency in lispy languages to avoid introducing variable bindings just for the sake of naming the subexpression, because it often comes with a `(let ((name (subexpression))) rest-of-code)`, which also results in extra tabulation for the rest of the body. Compare with variable introduction in languages like python/js/c++/rust, etc., where such thing wouldn't cause touching the rest of the function/clause. I guess it's more of a 'functional language' artifact, e.g. in Haskell you'd probably have a similar issue.

The simple rules don't remove the complexity, the evaluation state has to live somewhere.

> I have never had a static type checker (regardless of how sophisticated it is) help me prevent anything more than an obvious error (which should be caught in testing anyway).

Err, really? Never dereferenced a null pointer, or tried using a list instead of a set? Static types are testing, it doesn't replace it, but massively saves mechanical work on writing dozens of dumb tests. Having tests is very important for documentation, regressions, end-to-end/integartion testing, but every test for something stupid as 'throws on passing null' is just a time drain (unless you're launching rockets or something of course).

Anyway, it's possible to have the best of both worlds by using gradual typing like mypy or JS flow -- you get all the runtime benefits (flexibility/ability to temporary violate invariants) and you gradually harden code which makes sense to type. I really wish Elisp (the lisp I'm mostly dealing with) had some sort of types, at least for simple things list 'associative list', 'string', 'function reference', 'nullable thing', this would massively save me time on catching bugs. It has runtime type checks for `defcustom` things, but never seen type checking anywhere else (except for occasional runtime asserts).

> The biggest advantage of this form of syntax is a form of minimalism — you don’t need spurious syntactic constructs to convey concepts.

> call these things macros, or syntactic extensions. In other words, you can extend the syntax of your language to introduce new abstractions.

I find these two sentences a bit contradictory ;) Anyway, I personally like macros, if used sparingly it can really help. One great upside of s-expressions for me is that you can do some cool things like 'find and replace' for whole subexpressions (for monkey patching third party code, for example). I use `el-patch` [0] in my emacs config and `advice-patch` for surgically changing the default behaviors of some org-mode functions to compile my blog [1].

That said a similar sort of thing is possible, for example, in python with `patchy` [2], and perhaps many other languages? But I guess it's not as organic as in lisps, e.g. `advice-patch` implementation is less than 100 LOC, whereas in case of python you have to rely on existing heavy lifting done by `ast` module.

As of simple syntax, it really gets in the way sometimes, e.g. I'm always annoyed by constant quoting in Elisp because the same type of brackets (only `()`) is used. In comparison, in Clojure it's much more readable with (), [], {} (and more).

> Lisp is not an interpreted language. It is not slow

A bit of nitpicking, but... which Lisp? :) Anyway, these days it's often meaningless to say 'slow' without having a specific workload in mind and having done benchmarking; hardware improvements make it very hard to reason about.

> all implementations come with lots and lots of levers to tweak performance for most programs. In some cases the programs might need assistance from faster languages like C and C++ because they are closer to the hardware, but with faster hardware, even that difference is becoming irrelevant.

Well, this is true of most languages.

[0] https://github.com/raxod502/el-patch#el-patch

[1] https://github.com/karlicoss/beepb00p/blob/a4fd7cb95e1705412...

[2] https://github.com/adamchainz/patchy#patchy

Re: Why I still Lisp

#5
Wow. I thought I recognized that name - the author of this post interviewed me for a job several years ago when I was first learning how to code. It didn't work out as I was waaaaaaay too junior at the time but I'll always remember that interview fondly.

My background was more in math and my interests were in PL theory, so he quizzed me on the lambda calculus, and turned me onto Essentials of Programming Languages by Friedman & Wand (and off the bad compiler books I had been reading previously), and pointed me towards material for further study in programming languages and lambda calculus.

The interview was still fairly practically oriented despite those detours, and I learned a great deal that helped me to quickly find a solid technical role not long after. But more importantly, he and his colleagues who interviewed me were incredibly kind and respectful, and instilled this sense that both computer science and software engineering could be a lot of fun. :)

Re: Why I still Lisp

#6
A great read for a lazy Sunday morning. The author's tastes in programming languages agree with my own, and he's defending them in an eloquent way so it's an article I read drinking coffee and nodding my head.

Also describing Miranda as "Ugly Haskell's beautiful mom", and invoking old Hindi movie censorship to belittle static type checking is just mmph.

Re: Why I still Lisp

#7
> This feature, called tail call optimization (or TCO), has been around for a few decades and it is a sad commentary on the state of our programming languages that none of the modern languages support it.

TCO is part of ECMAScript specification, although apparently only Safari supports it.[0]

[0] https://2ality.com/2015/06/tail-call-optimization.html

Re: Why I still Lisp

#8
I think Lisp is going to live forever as a niche tool for people who "get" it.

I use Clojure on a daily basis. Not necessarily because it is best Lisp, but rather because I am working with Java applications and being able to reuse the same Java code I have already developed is a huge boon to me. If I was able to choose, I would be using Common Lisp.

The way I use it is to quickly develop adhoc tools and PoCs and more rarely small UIs in re-frame.

Working with Lisp is a joy for me and I always get this feeling of frustration when I have to go back to Java, especially if I have to translate to Java what I just prototyped in Clojure.

Unfortunately, where I work (financial systems for financial institutions), I have trouble finding enough people, mature enough to be able to even propose working projects in Clojure.

Close in my org structure there is a set of Clojure projects where the company got badly burnt. The code is a mess and a huge headache for management. The guys who wrote it were either promoted (claiming outstanding work on the project but not wanting to maintain it) or left. Now new developers are barely able to change anything without blowing it up.

This underlines the fact that Lisp projects can very easily end in spectacular disasters. You have to be really incompetent to write a typical Java service in a way where it is no longer possible to develop it at all, but in Clojure it is just enough to get couple of people that are intelligent enough to write macros but not experienced enough to understand the dangers of lack framework forcing the structure of your application.

Re: Why I still Lisp

#9

> What improves (and guarantees) software quality is rigorous testing. To deliver high quality software, there is no other solution. This is 100% false. You can’t inject quality into a bad design via testing. You can’t guarantee quality or correctness through testing. Testing is the second worst place to find errors. You get a MUCH higher roi by producing thoughtful written designs and getting them peer reviewed. And…

I agree that testing is not a panacea, but I also don't think it is completely divorced from design.

I see testing and design as cooperative processes, I agree that design is almost always the highest yielding process in any non-trivial program, but I think of testing almost as a design phase that tries to invert the design to look for weaknesses.

Re: Why I still Lisp

#10
post #7

> This feature, called tail call optimization (or TCO), has been around for a few decades and it is a sad commentary on the state of our programming languages that none of the modern languages support it. TCO is part of ECMAScript specification, although apparently only Safari supports it.[0] [0] https://2ality.com/2015/06/tail-call-optimization.html

Which, considering JavaScript is a language many compile to, sucks. I have said it many times: recursion is unbiased. Compiling a languages looping facility to something recursive is simple. Forcing one looping facility into the shape of another looping facility is the path to suffering.
Post reply on HN