6 ms·
> I sometimes wonder why Lisp has not been more popular in the technology industry. Is it the lack of sufficient marketing? Is it the lack of an extensive libra
by s_kilk 8y ago
> I sometimes wonder why Lisp has not been more popular in the technology industry. Is it the lack of sufficient marketing? Is it the lack of an extensive library ecosystem?
Data-point of one here, but I was instantly turned off by the conflation of the empty-list, nil, and boolean-false. I could tell instantly that I'd have a hard time interfacing with data from other real-world systems, so I decided to skip CL and stick to Clojure and various Schemes for my lispy kicks.
- xyrouter 8y agoIsn't that true in Python too?
- s_kilk 8y agoNot really, the empty list, None, and False are distinct values in Python. In [1]: [] is None Out[1]: False In [2]: [] is False Out[2]: False In [3]: [] == False Out[3]: False In [4]: [] == None Out[4]: False In [5]: False is None Out[5]: False In [6]: False == None Out[6]: False This kind of relatively fine-grained distinction between different types of data is essential for operation in a world where other systems presume that you can handle these distinctions.
- kleiba 8y agoHowever: if not []: print("looks boolean to me...")
- rtpg 8y agoPython code rarely looks like this For things like optional arguments you usually use None with an "if l is None" parameter Meanwhile you can't iterate over None, so [x for x in None] blows up Closure (to my understanding) allows a null value in the place of any empty seq. This seems like a major bug swallower to me
- yen223 8y ago> Python code rarely looks like this Using implicit truthiness to test for empty sequences is idiomatic Python, for better or worse.
- rtpg 8y agoSorry, you're actually very right. I think I misread this in the case of a default argument example (which at least for codebases I work with are diligent about doing None tests for ) but if you know that the value is set to a sequence then the boolean test is common
- s_kilk 8y agoCan't win em all I suppose :P My point is that, for me, Common Lisp is particularly defficient in this regard, in a way that means I can't really consider using Common Lisp for development work today.
- s_kilk 8y ago(Nice to see the Lisp Defence Force out in strength.)
- kazinator 8y agoDifferent programming languages play different games with booleans, empties, undefinedness and such. In all of them, people are able to Get Stuff Done, correctly handling inputs from the world. In the POSIX shell, a failed termination status of a command is a false condition. Storing false as a datum is usually represented by an empty or unset variable. Yet, people are able to write robust shell scripts to boot systems, build programs and so on. Everything you wrote is based on a guess; not even anecdotal experience. That is below the expected level of discussion on HN. The nil/empty/false thing is an excellent tradeoff in code that manipulates lists, rendering it succinct. For instance an expression like (when attributes (do-this ...)) means, (do-this ...) when attributes are present; i.e. the list of attributes is not empty. All the default nil return values that occur are automatically empty lists, which is very convenient. For instance a two-clause if (if condition then) returns nil if condition is false. If the caller expects a list, then that is perfect; it's the empty list. All these little conveniences dove-tail together to clarify the code. The empty/false conflation doesn't do anything in code that doesn't manipulate lists. For instance, if you're manipulating numbers, or strings, there is no ambiguity: nil isn't a number and it isn't a string. It is distinct from 0, 0.0, and "". You cannot have a meaningful opinion about this that anyone should take seriously unless you have experience with it: having experienced both the convenience in writing list manipulation code (particularly code-writing code) and the situations in which the ambiguity between nil (the atom) and nil (the empty list) was actually a problem.
- rauhl 8y ago> Data-point of one here, but I was instantly turned off by the conflation of the empty-list, nil, and boolean-false. Oddly enough, that’s almost always something I consider a feature, even when I'm interfacing with the outside world. If I’m expecting a list, then NIL is just an empty list; if I'm expecting a value, then distinguishing NIL & false hasn’t caused me trouble. Worst-case, it’s been something I take care of at the mapping level, and don’t worry about anywhere else. In return, actually using Lisp is really pleasant. Using Scheme tends to be a lot more verbose, because it makes a distinction where it doesn’t really have to.
- lisper 8y agoYou can easily change that behavior if you really want to. (in-package :my-package) (shadow 'if) (defmacro if (condition then else) `(cl:if (true? ,condition) ,then ,else)) (defgeneric true? (thing) t) Defining appropriate defmethods to make things work the way you want is left as an exercise.
- kazinator 8y agoHowever, wanting to is rather a problem for the psychiatrist's couch.
- lisper 8y agoWhy? I actually agree with the OP that conflating the empty list and the boolean false value is a mistake. (I don't think it's enough of a big deal for me to want to change it, but in a perfect world I do think it is better to distinguish them.)
- kazinator 8y agoYour guess was wrong; there is no such hard time. There is no difficulty in precisely mapping data from the "real world" onto Lisp data structures, in both directions. If it doesn't have nil that is also false and the empty list, it is not a Lisp. The conflation is a stroke of genius. I was immediately attracted to Lisp because of its clever handling of lists and booleans. Also how nil is a symbol, but () means the same thing as an alternative spelling. People who wake these things out are imbeciles who are mutilating their language to the point it shouldn't be called Lisp. How nil works in Lisp has a tremendous virtue: it blows away a lot of useless verbiage from code that manipulates code. Ancient Lisp in the 1960's didn't allow car and cdr on the empty list nil. The Interlisp people realized that it was an inconvenience to always have to test consp before using car or cdr so they turned the functions polymorphic, allowing (car nil) -> nil, and (cdr nil) -> nil. According to the HOPL History of Lisp paper, the MacLisp and Interlisp people held a conference. They didn't agree on some things, but MacLisp adopted (car nil) -> nil and (cdr nil) -> nil from Interlisp. It's a compelling idea; taking it out of a supposed Lisp dialect is a counterproductive regression.
- osteele 8y ago> If it doesn't have nil that is also false and the empty list, it is not a Lisp. Scheme is generally considered a Lisp.
- kazinator 8y ago{by whom} Not by me. I'm a skilled Lisp programmer, yet Scheme isn't usable to me a the rudimentary coding level using the core language. There are stumbling blocks at every turn against straightforward Lisp coding. How can it be a Lisp? I can't even rely on Scheme to evaluate the function arguments left to right. Many forms have an "undefined" return value; in Lisp, everything returns a defined value, as a fundamental tenet! Remember Alan Perlis: "Lisp programmers know the value of everything, but the cost of nothing." Well, Scheme programmers do not in fact know the value of everything; it is often undefined! Might Scheme not be a dialect of C, in fact? The expression f(i++, i++) is directly translatable from C to Scheme, undefinedness of behavior intact! "Lisp" has to do with the little design details, not superficial resemblance. Calling every language with parentheses a Lisp is like calling every web browser "Netscape". Chrome is Google Netscape, Firefox is Mozilla Netscape; Explorer is Microsoft Netscape. How can they all not be "Netscape"? They run Javascript, process HTML and CSS, fetch URLs and render content. Also, MS-DOS and Windows are Unix! Proof: their filesystem design has a directory structure in which "." means this directory and ".." means parent. There is a "cd" command in the command interpreter, and slash is accepted as a path separator such that the leading slash indicates an absolute path. Piping between processes is done with |. Gee, how can DOS and Windows not be Unix? Superficial resemblances mean that we can dilute any name we want, as thinly as we want, to the point that it means nothing.