Live data from Hacker News

Why didn't Common Lisp fix the world?

quora.com

111–120 of 127 posts

Re: Why didn't Common Lisp fix the world?

#111
post #16

Yes. I have. People with gray beard, strong views on programming languages, politics and UFOs. I always assumed that were dressed up for the occasion and not really real; like someone doing a role playing game or maybe being Santa for the kids during Christmas.

We detached this subthread from https://news.ycombinator.com/item?id=11712496 and marked it off-topic.

Re: Why didn't Common Lisp fix the world?

#113
post #8

Why on earth would it fix the world? It was a step forward in the history of programming languages; but somehow the end of it, the final fix? Why would anyone expect that? Programming languages are about providing a useful way for humans to formulate and implement their ideas. Starting by turning things on their head reverse polish notation style is bad start as it is counter intuitive to nearly everyone.

>Why on earth would it fix the world? It was a step forward in the history o Exactly. Haskell took until 1998 to really come together! ;-) (And cabal hell lasts forever .)

> (And cabal hell lasts forever.)

Obligatory: "have you tried Stack?"

Re: Why didn't Common Lisp fix the world?

#114
post #94

Earlier quoted context omitted.

It puzzles me too, that people are not using the most powerful development technique. I cannot imagine not using macros for pretty much everything I do.

I've written a handful of Clojure and Emacs Lisp, but I don't get macros. How is a macro different than passing a quoted list to a function? Maybe I just need to start slinging more lisp, but I don't see how they're particularly different from functions.

> How is a macro different than passing a quoted list to a function?

Macro is a function that is executed in compile time. Think of it as a way of extending your compiler with new functionality. For example, your language does not have support for pattern matching originally. It's not a problem - you can define a macro that adds such a functionality to a language. You cannot do it with functions - it must be compiled and optimised before execution, and functions cannot introduce new identifiers into a scope.

Another simple example would be something like list comprehensions - also introducing variables and also requiring optimisations in compile time.

And at extreme level, macros can be used to turn your host language into something totally different. Not just add few new features, but turn it into another language. Lisp can become an ML or Haskell, or Prolog, or Java, or whatever else you can imagine. Macros can change syntax, can implement new semantics. None of it can be done with just functions.

Re: Why didn't Common Lisp fix the world?

#115
post #113

Earlier quoted context omitted.

>Why on earth would it fix the world? It was a step forward in the history o Exactly. Haskell took until 1998 to really come together! ;-) (And cabal hell lasts forever .)

> (And cabal hell lasts forever.) Obligatory: "have you tried Stack?"

Obligatory: I'm dealing with a package so old that lts-1.0 has a Base too recent for what I'm dealing with. But it's research code whose recent versions have gone in a totally different direction from what I need right now, so I have to cope.

Re: Why didn't Common Lisp fix the world?

#116
post #10

Common Lisp doesn't have type checking and well defined namespace. And it has eval. That's certainly a no go for people like me. Most programmers in the world don't have to invent/implement a radical new idea in five minutes.

Late edit: Sorry, I meant that CL doesn't have a well defined scope, not a namespace.

Re: Why didn't Common Lisp fix the world?

#118
post #33

Earlier quoted context omitted.

Agreed, but it's not just the parentheses - "car-or-zero"? Really? If you have a language where you can say "at least it's not APL", that's not a feature...

That's where Common Lisp's roots that go back to the first version that ran as subroutines to punched card FORTRAN on a vacuum tube IBM computer show. Contents of Address and Decrement Registers -> car and cdr, for normal list processing they're often renamed or aliased first and rest. BUT, they hang around because of old code, and they're composable, e.g. the 2nd Lisp Machine design and first to be semi-mass produce…

Oh, I know the history, I just dislike "because we've always done it this way" as a rule. Imagine having a code full of "moo x > 5", with "moo" instead of "if" because that was the sound made by the favorite pet of the initial programmer...

Re: Why didn't Common Lisp fix the world?

#119
post #45
post #29

Earlier quoted context omitted.

>i feel like a lot of lisps are trying to drag this "everything is a list" I think you are speaking out of ignorance here. "everything is a list" is just a metaphor. Everything is either list or atom and almost everything is atom.

> Everything is either list or atom and almost everything is atom. how can you both say this and that i'm talking out of ignorance? you're basically confirming my words. larger point i was making is that "everything is a list" abstraction/metaphor influenced the decision to not include native representation of other data structures into the language. because parens are enough to represent everything. well they aren't…

Consider this snippet of C code:

    struct foo {
        int x;
    }
Do you care how the structure definition is represented in your compiler? is it a list, a vector or a custom data-structure? You don't know, and it doens not matter to you. Besides, it is totally different from what you manipulate at runtime (for type definitions, not much). Consider the second snippet:

    for(int i = 0; i 
Should the internal representation for the block delimited by braces be necessary the same as the one used to represent the fields in the previous structure? I mean, do the brace characters always map to the same internal data-structure? Probably not. In C, the concrete syntax has generally nothing to do with the abstract syntax. This is not the case in Lisp, because each syntax is used to parse a specific type of data.

In Clojure, you write #{...} and the reader (LispReader.java) sees the sharpsign followed by brace and builds a set containing the values inside the braces. That set is contained inside the AST, and acts as a literal value. That value is shared among all invocations of your code, meaning that if you call the enclosing function at different places, the same literal object is shared. Since this data is immutable, this is not really a problem because when you add more elements at runtime, the original literal is not modified. OTOH, you can still invoke EvalReader, #=(), which evaluates code at read-time. I believe that you can put mutable data-structures into the AST and obtain funny results by mutating it during execution.

How is it different from Common Lisp? Not much.

Common Lisp is less restrictive because the readtable can be customized. Also, the standard data-structures are mutable (however, the behavior is undefined if you try to mutate literal data; some compilers warn you about that). I don't think I ever needed to have hash-table as a literal, it seems practically useless because if you want a hash-table in your source code, odds are that it contains few elements. If so, an association list is simpler (and more efficient).

If you really really need a complex data-structure in your source code, you are more likely to use LOAD-TIME-VALUE anyway, because it works better with a compiler: not all data-structures are (nor should be) automatically serialisable in the object file (they could containt transient data, for example). In other words, your original code has little to do with the machine code that is produced and eventually loaded (possibly in another environment). LOAD-TIME-VALUE is a way to execute code at load-time to produce such data-structures in your code: I have a parser which pre-computes some regexes, and this is not something that has an equivalent in Clojure, as far as I know.

So my first point is: you can have literals of any type in your source code in Common Lisp (like in Clojure). All of them have dedicated syntax, like vectors of arbitrary dimensions #2A((1 2)(3 4)), bit vectors #*1111, complex numbers #C(0 1), pathnames #P"/tmp/foo", and of course strings. Likewise, you have a generic syntax for structures. Suppose you define a structure FOO with a single slot X, then #S(foo :x 10) is a literal of that type.

However, not all data-structures have such syntax: maybe it was not deemed necessary to represent literal hash-tables in source code, or maybe it did not make it to the standard, I don't know. I personally don't miss it and I am happy to use auto-complete the few times I need a hash-table. However, if you want you can customize your Lisp easily; for example, load the FSET library and provide a custom syntax over immutable data-structures. If you look at Maxima, it has a lot of custom syntax. And I am not talking about macros, but about changing the readtable which reads Lisp objects from a stream. An example of this is RUTILS[0], which provides the #h(equal "k1" v1 "k2" v2) syntax for hash-table. But note that this notation is only used to produce a list, namely the code required to produce a hash-table at runtime and populate it.

Which brings me to my second point: there is a big difference with Clojure in that Common Lisp doesn't use different types to provide syntactic sugar. For example, in Clojure [] is for vectors, {} is for maps and #{} is for sets. That literally means that when you have a binding, you allocate a vector. When you destructure a map with map-notation, you use internally a map. So the language is mixing two concepts: syntactic sugar and actual internal representation. I find this rather hackish but I can live with it because it probably has little incidence. I think it adds complexity to the compiler which has to walk different kinds of code. Besides, the usage of such syntax is not regular: sometimes vectors are for unevaluated data, sometimes for bindings or destructuring, so you still need context to know what you are doing. Those are minor points, and I understand that Clojure can look more convenient to use. However Common Lisp being a little more wordy is not a problem for me.

[0] http://lisp-univ-etc.blogspot.fr/2016/05/improving-lisp-ux-o...

Re: Why didn't Common Lisp fix the world?

#120
post #119
post #45

Earlier quoted context omitted.

> Everything is either list or atom and almost everything is atom. how can you both say this and that i'm talking out of ignorance? you're basically confirming my words. larger point i was making is that "everything is a list" abstraction/metaphor influenced the decision to not include native representation of other data structures into the language. because parens are enough to represent everything. well they aren't…

Consider this snippet of C code: struct foo { int x; } Do you care how the structure definition is represented in your compiler? is it a list, a vector or a custom data-structure? You don't know, and it doens not matter to you. Besides, it is totally different from what you manipulate at runtime (for type definitions, not much). Consider the second snippet: for(int i = 0; i Should the internal representation for the…

you're talking from the perspective of an experienced lisper. i'm talking from perspective of somebody that wasn't convinced by CL but was later convinced by Clojure. that is the whole point of the thread - why hasn't lisp caught on, and i'm an example of both failure and success in that regard.

i mostly agree with all you've said, just few comments:

> I think it adds complexity to the compiler which has to walk different kinds of code.

either you deal with complexity or your users will have to. it's not always clear where the boundary should be though i like where clojure puts it.

> I understand that Clojure can look more convenient to use. However Common Lisp being a little more wordy is not a problem for me.

s/me/experienced commonlisper/

aaand that's the whole point.

Post reply on HN