3 ms·
Yeah, I am aware of the differences. I equivocated about specifying examples, because I worried someone would try to explain them, rather than engage with my ov
by troad 2y ago
Yeah, I am aware of the differences. I equivocated about specifying examples, because I worried someone would try to explain them, rather than engage with my overall point.
My overall point is two-fold. (1) There is nothing in the function name that would indicate the difference between, say, (eq) and (eql) and (equal), any more than you could guess what the difference between (colorise), (clrise) and (clrs) would be on sight. Lisp seems to love doing this. To me, it just seems like an obvious source of very painful bugs (works as expected 99% of the time and then it doesn't).
(2) In many (most?) day-to-day cases, the distinction isn't material, and for those the ecosystem is going to end up preferring one more than the others (which may change over time - hence, 'in vogue'). The references I've seen tend to suggest sticking to (eq) and (equal), for instance, and avoiding (eql) unless you have specific need of it.
For a language that is reputed to be elegant and beautiful, this - well, isn't that. Hence my initial surprise.
- kgwgk 2y ago> (1) There is nothing in the function name that would indicate the difference between, say, (eq) and (eql) and (equal), any more than you could guess what the difference between (colorise), (clrise) and (clrs) would be on sight. Lisp seems to love doing this. To me, it just seems like an obvious source of subtle bugs. What alternative would you suggest? Giving paragraph-length names to the functions? Common Lisp already has some of the more descriptive function names around and they can be inconvenient if the function is used often. (By the way, there is something that helps to remember what those functions do: shorter names are correlated with more primitive and restrictive checks.) Having a single function that performs different checks depending on a parameter? If you don’t know which function to use you don’t know which parameter to use either. Removing the ability to perform different kinds of checks entirely?
- doctor_eval 2y agoI think troad is trying to explain how they feel about learning CL and what they've discovered. They aren't criticising CL. Of course naming things over a long period of time is a complex problem, that's why they acknowledged that there is a lot of cruft from the 60s. I've found their comments, and the constructive responses to them, interesting because I am interested in Lisp but have never learned it. What I don't find interesting is seeing troad's observations strongly challenged, as you are doing, as if somehow by sharing their observations, they now owe us detailed solutions as well. It's not cool.
- kgwgk 2y agoFair enough. In fact I agree with the broad point that having functions that do things is a source of bugs and CL is a huge language with less than perfect names. My point is that having less functions that do less things does not obviously reduce the number of bugs in the end if those things still need to be done. Anyway. I see how a logical argument may be out of place if the thread is understood about sharing feelings and not about challenging claims.
- pfdietz 2y agoI'd suggest changing the name from SORT to NSORT, just for consistency and bug avoidance. :) But it's water under the bridge and one can patch this (or, really, any gripe about function names) by suitable package fu, at the cost of making your code less readable to others.
- kazinator 2y agoI did exactly that in TXR Lisp, after initially following the Common Lisp naming. In the same change, I also made a function called shuffle nondestructive, and introduced nshuffle. It's a backwards compat breakage, but there is a mechanism in the language which helps with such situations. txr -C 237 or setting the TXR_COMPAT environment variable to 237 or lower will restore the destructive behavior of sort and shuffle. People who don't want to fix their code can deploy that way. I hate compatibility breaking changes, but it was a real thorn in my side how sort is destructive without any indication in its name, in a language where destructive versions of functions should be separately named. Now the thing is that sort is not required to be destructive. It is allowed to be. Therefore code written to the language spec will not break if sort becomes pure. But we have to worry about breaking all programs though, not just programs written to the spec. (Unless we are GCC maintainers; different rules apply.) You can't just say, "Oh, programs that call sort on a vector and ignore the return value, expecting the vector to be sorted, are just nonportable junk; let them break."
- pfdietz 2y agoIn general, the "N" versions of functions in the standard say they "maybe" or "might" modify arguments. SORT and NSORT should have been like this, but IIRC SORT was taken from Interlisp, where it was destructive.
- kgwgk 2y agoI agree that there are some inconsistencies in the naming of functions and parameters like destructive/non-destructive variants and predicates among other things. Also strange names like car and cdr (which on the other hand allow for cadr et al.). However, even though they can be confusing, I wouldn’t put the equality functions in the same bag.
- kgwgk 2y ago> (2) In many (most?) day-to-day cases, the distinction isn't material, and for those the ecosystem is going to end up preferring one more than the others (which may change over time - hence, 'in vogue'). The references I've seen tend to suggest sticking to (eq) and (equal), for instance, and avoiding (eql) unless you have specific need of it. I guess they suggest two instead of one because in most cases the difference is material. And I imagine that they also suggest using = to compare numbers. When the distinction doesn’t matter one could just use eq. I’m not sure that this covers most uses though.
- kazinator 2y agoIf you want to test whether x is 1.0 or 1, then (= x 1) is what you want. But = is specific to numbers and blows up on non-numbers. The family of functions whose names begin with eq are special in that they are applicable to all objects; equal will tell you that "abc" is not 1 without complaining.
- kgwgk 2y agoBut - with the exception of equalp - they may fail to identify as equal numbers which are equal (=). I suggested to use = to compare numbers specifically.
- kazinator 2y ago> rather than engage with my overall point So you'd want someone to engage your overall point that there are redundant and deprecated functions, while the specific ones you actually have in mind are not redundant or deprecated (and you know this)? And for that reason, it would be good to keep the specifics out of the discussion? Okay ... > There is nothing in the function name Yes there is: the names get longer with increasing complexity of comparison. The common eq prefix puts them into a family. > avoiding (eql) unless you have specific need of it. eql is the default value of the :test argument in numerous library functions. Rather, you should avoid eq unless you're optimizing. Rarely do you want to compare objects in such a way that (<compare> 12345 12345) might be false! It is idiomatic, though, to use eq in code that manipulates symbols, like (if (eq arg 'foo) ...). If one of the arguments of an equality function is a constant, it's possible to pick the strongest equality function which goes with that constant's type. All equality functions reduce to eq when symbols are compared. > Lisp seems to love doing this. Many operator names in Lisp are short mnemonics. It is like this in older languages, or older parts of languages. Short identifiers keep programs short. Short, mnemonic names are part of the elegance of traditional Lisps. It's not just old versus new; for instance in some very new languages, we see a trend of shortening define to def, or function to fn and such. My TXR Lisp is much newer than Common Lisp, but I shortened some things. Instead of stable-sort, I have ssort. Or instead of symbol-macrolet, I have symacrolet. In Common Lisp, like in many languages, there is a "layer" of newer identifiers that are longer, often hyphenated compounds. You can tell that define-symbol-macro is newer than defun. However, someone making a new language which is inspired by an existing one can challenge those decisions, going by what identifiers are often used, rather than going by the chronological order in which they were introduced in the inspiring language. Symbol macros were introduced in Common Lisp for, I think, supporting with-slots. But symbol macros turn out to be important, deserving short names. Why ssort rather than stable-sort? Part of the reason is that I made a change of introducing nsort as the in-place sort, making sort pure. That then establishes the idea that we have a one letter modifier. The s for stable becomes another one. And in fact, I have one more: c for caching. There are all eight combinations, in the order c, s, n: in other words c?s?n?sort. Thus csnort ("cee snort") is the caching, stable, destructive sort. I don't want to punish the programmer and reader of the code with caching-stable-destructive-sort. This is not Java. You can't cram meaning into the spelling of every identifier, by making it out of a string of English words, because that makes things comically verbose. Languages don't do that. You can't guess what "water" means, if you're new to English, and your native language doesn't have a cognate like "wasser". You just have to learn the vocabulary word. Some words are compounds of other words, others aren't. Only some compounds have compositional meanings, bearing out the obvious guess.
- lispm 2y agoLisp was developed at a time when space was more limited. Generally operators had short names. Page 147 of the Lisp I manual from 1960 has a function listing: https://bitsavers.org/pdf/mit/rle_lisp/LISP_I_Programmers_Manual_Mar60.pdf https://bitsavers.org/pdf/mit/rle_lisp/LISP_I_Programmers_Ma... Generally in Common lisp we have EQ, EQL, EQUAL, EQUALP -> from the most specific to the most general. The most specific has the shortest name: https://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node74.html https://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node74.html EQL is actually often used, since it is also the default equality test in Common Lisp. For example the named TEST argument has the default EQL. That information is slightly hidden. Example: (find 1 '(2 3 2 1 3)) is the same as (find 1 '(2 3 2 1 3) :test 'eql) , since EQL is the default test. One can pass a different equality test predicate, if needed. Some background about naming and equality operators in Lisp: http://www.nhplace.com/kent/PS/EQUAL.html http://www.nhplace.com/kent/PS/EQUAL.html Other languages for example use some of =, ==, ===, is, ... what may the difference be? There were many different naming conventions in Lisp over the decades. One was, as mentioned above, the more specific/primitive operators have shorter names. Later (70s/80s, Lisp got a lot more operators and at some point there were operators with long names introduced. This was not liked by everyone, since one needed to type longer names - completion was often new then (or slow). For example CLOS was added end 80s. Thus it uses names like UPDATE-INSTANCE-FOR-DIFFERENT-CLASS, instead of UPDINSTC ;-) . Generally, a good Lisp IDE should make getting the documentation (and source code) for any operator easy.