top | item 30800520

The Lisp Curse (2017)

64 points| gphilip | 3 years ago |winestockwebdesign.com

89 comments

order

at_a_remove|3 years ago

The results (many many packages doing fifty to eighty percent of what you need) are what drove me from Perl and what makes me very uncomfortable with the growing disdain for the standard library in Python. I really don't want to write my own XML libraries or whatever, I would rather just import whatever the standard solution is. I also do not want to have to do a roundup of the available solutions and try to figure out which is most applicable, then hope that it will actually do the job.

A lot of people are very into whatever the language is, but for me, I want a huge standard library.

badsectoracula|3 years ago

> Making Scheme object-oriented is a sophomore homework assignment. On the other hand, adding object orientation to C requires the programming chops of Bjarne Stroustrup.

C++ added a ton of additional stuff to C. The original Objective-C is a much simpler approach on adding object orientation to C and at its core it'd all be about finding expressions like

    [foo bar:baz boo:hoo]
and replacing them with something like

    obj_send(foo, msg_foobarboo, baz, hoo);
and linking with an underlying runtime that handles message passing of course.

An alternative would be Turbo Pascal 5.5-style OOP where

    struct foo : base {
        foo();
        ~foo();
        void blah();
    }
    foo::foo(){ base(); }
    foo::~foo(){ ~base(); }
    void foo::blah(){}
would be accepted but aside from the C++-like syntax for constructors, destructors (which handle the hidden VMT field) and methods nothing is done automatically and instead you are expected to explicitly construct and destroy the objects (if needed), e.g.

   struct foo foo;
   foo.foo(); /* call constructor chain */
   foo.~foo(); /* call destructor chain */
or

   struct foo* foo = malloc(sizeof(struct foo));
   foo->foo(); /* call constructor chain */
   foo->~foo(); /* call destructor chain */
   free(foo);
Note that Objective-C handles (or handled at the past, not sure how things changed nowadays) allocation and construction in separate steps too.

Of course unlike a language with Lisp-like macros you'd need to modify a compiler or write a preprocessor to do the above, which makes it a bit harder, but in any case adding object orientation to C does not mean you have to make it as complex as C++.

xscott|3 years ago

Yeah, I agree. If you're willing to use a garbage collection library [0], you can even have a pleasant syntax for ObjectiveC style OOP in C:

    var result = call(foo, "bar: %s boo: %f", baz, hoo);
The garbage collector will pick up the stray memory and release other resources (files) as needed, and all the standard compilers will check the varargs format string for you.

Dynamic typing, arbitrary messages, and no memory leaks. Just like Lisp. It's not perfect (string message could have typos, and might use %p for objects), but it's not too bad.

[0] https://en.wikipedia.org/wiki/Boehm_garbage_collector

edgyquant|3 years ago

What’s the point of a constructor that isn’t called immediately? Couldn’t you just use any arbitrary function at that point?

arethuza|3 years ago

"The hardest problem in computer science is not being an opinionated jerk about everything."

From the author's home page.

Edit: Potentially ignoring that quote - I can't help observing that although I used Common Lisp as my main development language for 6 years in an academic research environment and really enjoyed it I've never wanted to use it since then...

rileyphone|3 years ago

I would argue that rather than some curse of expressiveness, the lackluster showing from the community in recent years has been the results of a premature standards process. Common Lisp hasn't changed since before I was born, and while to some people that denotes stability, it also leaves new features to be done in the manner the author describes, as 80% projects by lone hackers. The language is more than capable of supporting modern development, but simply requires learning too much context and historical baggage to be appealing to any but the most devoted. This has little to do with expressivity, but more with history and economics. Most successful languages have one or more companies devoting resources to the language and libraries. Lisp has multiple implementations of the language but no blessed one, which means the fossilized standards are the point of departure for each of them, many remnants of the era of software you can buy.

There are still a lot of interesting things happening with Lisp, but I can't see how Common Lisp will be the path forward. Of course, there have been many challengers seeking to upset it as King Lisp, including this site's very own Arc. Clojure has seen the most commercial success in recent years, though the extent that it's actually a Lisp is debatable. I'm a fan of Kernel [0], which makes macros first class members of the language, like everything else. Who knows, but saying it's power will necessarily lead to its downfall is a kind of fatalistic mentality that I have little patience for.

[0] https://web.cs.wpi.edu/%7Ejshutt/kernel.html

substation13|3 years ago

I'm curious; what is Clojure missing a Lisp?

johnisgood|3 years ago

> Dr. Mark Tarver — twice-quoted, above — wrote a dialect of Lisp called Qi. It is less than ten thousand lines of macros running atop Clisp. It implements most of the unique features of Haskell and OCaml. In some respects, Qi surpasses them. For instance, Qi's type inferencing engine is Turing complete. In a world where teams of talented academics were needed to write Haskell, one man, Dr. Tarver wrote Qi all by his lonesome.

Check out https://github.com/factor/factor. Check out how much stuff they have implemented early on, just 2-4 guys tops. I found it really impressive.

toolslive|3 years ago

> Employers much prefer that workers be fungible, rather than maximally productive.

lisper|3 years ago

This. A maximally productive non-fungible employee has leverage, and employers hate that more than just about anything.

davidgrenier|3 years ago

I just wish more people understood that something being Turing Complete isn't a feature, it's a flaw.

lisper|3 years ago

Turing completeness may be a flaw, but it is nearly impossible to avoid.

tharne|3 years ago

How so?

ashton314|3 years ago

Mathematicians and physicists would rather use another's toothbrush than another's notation.

Perhaps The Curse is because Lisp programmers are generally of the same ilk as mathematicians and physicists?

Flankk|3 years ago

> Real Hackers have also known, for a while, that C and C++ are not appropriate for most programs that don't need to do arbitrary bit-fiddling.

Strongly disagree with this statement. I've read it so many places now that it has to be a meme. I actually wish I could use C++ on the web instead of this JS nightmare ecosystem. I don't understand where the idea comes from. I'm never "bit-fiddling" in C++ and almost never need to use pointers.

klibertp|3 years ago

In my experience the best for "bit-fiddling" is Erlang (and, by extension, Elixir) which offers bit-string literals[1], along with pattern matching on them. It's trivial to implement any binary protocol or parse any binary file format with these. It makes bit-fiddling pleasant and fun, but nobody ever mentions Erlang in these discussions.

That's because most programmers are incapable of making any informed decision about the language they use (and, even more so, about languages they don't use). There's a strong tribal mentality, a lot of cargo-cults, and the very narrow perspective on what's possible and (more importantly) what's desirable is prevalent.

[1] https://www.erlang.org/doc/programming_examples/bit_syntax.h...

bayesian_horse|3 years ago

Whoever says things like that probably means "appropriate" in the sense that you can get your stuff done with another language using a fraction of the implementation time.

And whoever wishes to use C++ on websites... who is stopping you since Webassembly? Speaking about ecosystems... I also don't think the package management ecosystem in C++ is that much better, right? And there are enough horror stories about illegibility and foot-guns even in modern C++ code, rivaling the worst YOLO frontend style...

C++ requires you to be a lot more verbose and precise for almost everything. That translates to more work, and the benefit isn't automatically worth anything.

mtreis86|3 years ago

On the opposite end, Common Lisp is actually pretty decent for bit twiddling. It has the operators from the PDP instruction set, LDB and DPB, which load and deposit bytes of varying length from and into other numbers.

vaylian|3 years ago

Webassembly might be the solution to your problem

dkersten|3 years ago

I like working in C++, after a decade of working in Java, Python, Javascript and Clojure, I find working in C++ (which I learned before these other languages) to be quite fun and pleasant, at least with relatively modern C++.

I've been, on and off, working on a little toy game engine, for a few years. Its a mix of keeping up with C++ advancements, learning various concepts like physically based rendering, and just the fun of crafting a big project, with no constraints other than my time and ability, no deadlines, no expectation of releasing anything. Its cathartic and enjoyable. I really do enjoy it.

Last September, I got frustrated with something I was working on in a more serious capacity. It was some server software, it responded to HTTP requests, it accessed third party services over HTTP and Websockets, it talked to a Postgres database. Overall it was an event driven system that transformed data and generated actions that would be applied by talking to third party services. The "real" version was written in Clojure and it worked pretty well. I really like Clojure, so all good.

But because I was frustrated with some things about how it ran and the resources it took up, I wondered what it would be like if I developed a little lean-and-mean version in C++. So I gave it a try as a side project for a few weeks. I used doctest[1] for testing, immer[2] for Clojure-like immutable data structures, [3] lager for Elm-like application state and logic management, Crow[4] for my HTTP server, ASIO[5] and websocketpp[6] for Websockets, cpp-httplib[7] as a HTTP client and PGFE[8] for Postgres, amongst some other little utility libraries. I also wrote it in a Literate Programming style using Entangled[9], which helped me keep everything well documented and explained.

For the most part, it worked pretty well. Using immer and lager helped keep the logic safe and to the point. The application started and ran very quickly and used very little cpu or memory. However, as the complexity grew, especially when using template heavy libraries like lager, or dealing with complex things like ASIO, it became very frustrating to deal with errors. Template errors even on clang became incomprehensible and segmentation faults when something wasn't quite right became pretty hard to diagnose. I had neither of these problems working on my game engine, but both became issues on this experiment. After a few weeks, I gave up on it. I do think I could have made it work and definitely could go back and simplify some of the decisions I made to make it more manageable, but ultimately, it was more work than I had free time to dedicate to it.

So my experience was that, yes, you can write high level application logic for HTTP web backends in C++. You can even use tools like immer or lager to make it feel very functional-programming in style and make the application logic really clean. Its not hard to make it run efficiently both in terms of running time and memory usage, certainly when comparing to Clojure or Python. However, I found that over all, it just wasn't as easy or productive as either of those languages and I spent more time fighting the language deficiencies, even with modern C++, than I do when using Clojure or Python.

I think I would think very long and hard before seriously considering writing a web backend in C++. If I had the time, I'd love to retry the experiment but using Rust, to see how it compares.

[1] https://github.com/doctest/doctest

[2] https://github.com/arximboldi/immer

[3] https://github.com/arximboldi/lager

[4] https://github.com/CrowCpp/crow

[5] https://think-async.com/Asio/

[6] https://www.zaphoyd.com/projects/websocketpp/

[7] https://github.com/yhirose/cpp-httplib

[8] https://github.com/dmitigr/pgfe

[9] https://entangled.github.io/

rurban|3 years ago

nit: it's (2011) not (2017)

otherwise, he speaks from my heart. social issues only

adregan|3 years ago

OP posted despite the opening paragraph!

> Update on October 6, 2017. N.B.: Please stop submitting this to Hacker News! Look at the Hacker News search results for this essay. Check out the note for the first entry: Come on, everyone! Let's beat the dead horse one more time!

Past discussions https://hn.algolia.com/?query=The%20Lisp%20Curse&type=story&...

badsectoracula|3 years ago

AFAIK it is common to repost a story here if there has been enough time since the last post since there can be new voices, opinions, etc since the last time it was posted. Dang sometimes posts a comment with links to previous discussions too.

Perhaps the author is confusing the norms with Reddit where in many subreddits reposts are often frowned upon.

iamwil|3 years ago

Dunno, I've been on HN since 2007 and this is the first time I've seen this story.

usefulcat|3 years ago

shrug. The way things work is people upvote things because they find them interesting. If enough people hadn't upvoted it, it would never have showed up on the front page, and most people probably wouldn't have seen it. Anyway, I'm not sure why they care that it gets resubmitted..

coldtea|3 years ago

That's a plea from 5 years ago.

People resubmit stories all the time, new and better (or different) discussions form around each resubmission, and new people get to read it.

_hcuq|3 years ago

If Lisp is do efficient for development, why are there essentially no commercial products that use it?

hajile|3 years ago

StandardML vs go is a great illustration.

StandardML is just as fast, is more simple to learn with more simple syntax and basically zero gotchas, has more powerful syntax, has an actually sound type system (which has better generics than the ones proposed in go), does a better job at defining public functionality (via modules), has a better CST model, and many other great features.

The only area where it loses is standard libraries and marketing. Google invested millions into these two things, so people use their decidedly inferior language.

You'll find that pretty much every big language has a big company behind it that threw tons of money at its development.

jcranmer|3 years ago

The usual answer here, as several of my sibling comments have pointed out, is that popularity and quality are not necessarily correlated. Since this has already been discussed, I won't delve further.

Another answer that hasn't been discussed much is that... maybe it isn't better for development. The article discusses one way in which this could be true: that technical superiority essentially leads to a hopeless community fragmentation that more or less forces it to be inferior in terms of community effects (which are, presumably, more important for commercial development rather than individual development).

A different facet, though, is that I believe the better language isn't the one that gives you more powerful tools to write correct code, but the one that keeps you from writing incorrect code (while still letting you write correct code). A salient example here is goto. Most modern languages don't have the goto keyword anymore, but they instead retain things like break, continue, and early routine... all of which are restricted forms of goto. By using only these restricted forms instead of the general form, it is much easier to immediately see what the code is doing (and presumably quicker to understand why), even though it may strictly be less powerful.

tharne|3 years ago

> If Lisp is do efficient for development, why are there essentially no commercial products that use it?

Same reason most of us use QWERTY keyboards instead of one the many better layouts available. After a long enough time as the dominant tool, things get locked in regardless of whether or not they're the best tool for the job. C-Style languages gained dominance early on and became the defacto standard.

a4isms|3 years ago

> If Lisp is [so] efficient for development, why are there essentially no commercial products that use it?

I’m sorry you’ve been downvoted for asking this question, even if it was a rhetorical question.

It’s easily the most important question to ask in the professional programming area, and it’s worth the effort to truly grok the answers rather than look up what everyone seems to say and then repeat it as gospel.

It may be asked and answered ad nauseam, bit it’s worth answering in the context of the very article discussing the Lisp curse.

Read TFA. What if every programmer rolling their own version of everything makes it an astoundingly good language for people but terrible for gaining industry-wide adoption?

JavaScript had this problem with every framework implementing its own OOP. Ember.js comes to mind as a recent example. The language stewards added a class keyword to ES6 in large part to quash further Balkanization of JS OOP.

Why didn’t JS wither while Lisp did? Ah! The answer is very relevant to your question. Every popular language began as the scripting language for an explosively successful platform.

JavaScript being the only way to script browsers bought it over a decade of time to fix its warts while it really wasn’t a “good” general-purpose language strictly on its merits.

Likewise, C and C++ were the scripting languages of Unix and Windows native application development. Ruby is the scripting language of Rails, for another example.

What is Lisp the scripting language of? A CS wag would reply, “Lisp!” And that is simply not good enough to motivate enough people to standardize the things that would lead to widespread adoption.

It’s a social problem, just as TFA says. Which leads us to a different essay about Lisp succeeding and failing:

https://en.wikipedia.org/wiki/Worse_is_better

leobg|3 years ago

Alan Kay‘s answer to this question:

“Another interesting answer assumed that “the test of time” is somehow a cosmic optimization. But as every biologist knows, Darwinian processes “find fits” to an environment, and if the environment is lacking, then the fits will be lacking. Similarly, if most computer people lack understanding and knowledge, then what they will select will also be lacking. There is abundant evidence today that this is just what has happened.”

davidgrenier|3 years ago

The answer is always that popularity doesn't correlate with merit.

TurboHaskal|3 years ago

For the same reason we are using VHS and have JavaScript running in the browser.

83457|3 years ago

With Clojure out there now I think the number of products using a Lisp is underestimated.