6 ms·
I really consider your comment to be FUD about Common Lisp. The language is not so aesthetic in many places, but the language was very certainly thoughtfully de
by reikonomusha 6y ago
I really consider your comment to be FUD about Common Lisp. The language is not so aesthetic in many places, but the language was very certainly thoughtfully designed and iterated on. Features by and large work surprisingly well together to form a cohesive language. I don’t agree about things being “tacked on”, which is voluminously evidenced in the discussions about each and every feature.
The standard could have been bigger and more comprehensive. But it’s just a non-problem most of the time. Threading is de facto standard and extremely well understood in its interactions with Common Lisp as defined.
Common Lisp is an extremely capable language to get things done cleanly. It just does things in a way that simply feels different from later languages.
If you want to talk about bolted on features, look no further than the plethora of Scheme libraries.
- dan-robertson 6y agoI’ve written a lot of Common Lisp and I while there was obviously a lot of thought that went into its design, I wouldn’t call it cohesive. Why are streams not CLOS objects (in the spec; I know about gray-streams)? Why can’t equality operators be extended to user-defined types? Why does the language even need so many equality operators and specialised functions like sbref? Why have both setf function names and a load of functions like rplca? Why is a setf function name invalid as the car of a form, even though only expressions (apart from atoms and lambdas) are disallowed? Why can’t the user make hash tables work for their own data-types? Why aren’t structs a first-class part of the object system like classes (unless you have the MOP)? Why can’t you have anonymous classes even though you can have anonymous functions and objects whose class was replaced with a new definition? Why can’t the user extend the sequence functions like map with their own sequences? Why are arrays so custom compared to the rest of the object system? Why pathnames? Why do so many things have bad names (e.g. getf and putf vs setf, set and get and setq, ...) If your answer is performance or compatibility with 1980s operating systems or lisp implementations, then sure that’s a reason for the design but it doesn’t make the design cohesive, complete and composable. I think CL is a good language despite this rather than because of it and I would suggest that your claim of it working “surprisingly well” supports that.
- kazinator 6y agoI've written a not-so-small-anymore Lisp implementation, and wouldn't call it cohesive. Even a one-person design won't be cohesive without a laser focus on cohesivity, which guides every design decision, and which sacrifices compatibility with anything existing, also. > Why can’t equality operators be extended to user-defined types? That's a loaded question where a bad answer is worse than no answer. I have taken a crack at it by inventing a concept called "equality substitution". Equality for a new user-defined type is defined using a one-argument method, which takes an instance of that type itself. When an object of that type is compared with something using equal, then that method is called, and the return value is used instead; that is then iterated on. If an object has no such method, then its identity is used: the opposite argument must be that same object. Thus, custom equality works by substituting some ordinary object: hence, "equality substitution". For instance some employee object may have an equal function which returns the employee ID (an integer). Then employee object whose ID is 42, is equal to the integer 42, and therefore any other employee object whose ID is 42, or any other non-employee object also which returns 42. To make it safer, the function could return a cons instead like (employee . 42), where the type symbol appears in the car. That cons is then equal only to another cons which has employee in car and 42 in cdr. Equality substitution neatly solves the problem of hashing also. The hash able implementation uses the equality substitute of an object as the key: that's the value it hashes, and that's the value it compares. The programmer need not define a custom hashing function, which is an error-prone, low-level task that we would not like to foist upon application programmers. Now, not everyone will find it appealing that (equal non-cons-object '(employee . 42)) can yield true. They might say, if you believe that no answer is better than a bad answer, why on Earth did you do such a thing? > Why pathnames? Portability of code among very diverse historic operating systems, installations of which are no longer in deployment. Pathnames in CL may be a pain in the but, but they are arguably a better abstraction than raw strings. Mainly the thing that is wrong with CL pathnames is that the spec leaves certain behaviors implementation-defined in such a way that two people writing a CL implementation on POSIX, say, will end up with different behaviors. There is more than one way that POSIX path strings can correspond to pathnames objects. Oh, like for instance in foo.tar.gz, is "gz" the :type? Or is "tar.gz" the :type? That creates ironic situations whereby we can't port a Lisp program to the one single plaform using two implementations of the language, such that the behavior is identical! A new revision of ANSI CL could solve this: it could specify that on Microsoft Windows, the correspondence between pathname objects and strings is such and such, and on POSIX such and such, and so forth.