Experience of Learning Lisp

Discussion of Common Lisp
tayssir
Posts: 35
Joined: Tue Jul 15, 2008 2:33 pm

Re: Experience of Learning Lisp

Post by tayssir » Sat Jul 18, 2009 1:57 am

Like what? The only thing that bugs me is (file-position s n) instead of (setf (file-position s) n)
Take a look at:

Code: Select all

(cons    collection item)
(gethash item       collection)
(elt     collection item)
(nth     item       collection)
(aref    collection items)
(assoc   items      collection)
(getf    collection item)
I'm reminded of Dave Moon's comment (he worked on Lisp Machines): "By the way, Java takes a “the right thing” approach and Lisp takes a relatively “worse is better” approach. So what do you think of that rpg?"

And there was this evil little joke stuck in 'loop':

Code: Select all

(loop for k being the hash-keys of h using (hash-value v)
      ...)
It's maybe funny the first 100 times you type it out. (Not common enough to dedicate an emacs hotkey, not rare enough to be ignored... Maybe I should've written loop-mode.) One nice thing about Clojure is that lists aren't privileged so much compared to other common general-purpose containers like maps, vectors and sets. Whereas using hashtables in CL is much less convenient.

skypher
Posts: 34
Joined: Thu Jul 03, 2008 6:12 am

Re: Experience of Learning Lisp

Post by skypher » Sat Jul 18, 2009 2:01 am

mrove wrote:Thanks a lot for all of your replies. I certainly realize that going into something new one's perspectives lack experience, so I'm grateful to get insights from people who have not only had the same (or similar) thoughts I am having, but have the benefit of experience and hindsight to balance things.
Do make frequent use of this forum to ask specific questions about Common Lisp code or design. This way you'll not only profit from thinking about problems yourself but also from the experience of others.

skypher
Posts: 34
Joined: Thu Jul 03, 2008 6:12 am

Re: Experience of Learning Lisp

Post by skypher » Sat Jul 18, 2009 2:23 am

Code: Select all

(cons    collection item)
It's the other way round (because you cons an ITEM onto a COLLECTION).

Code: Select all

(gethash item       collection)
(elt     collection item)
(nth     item       collection)
(aref    collection items)
(assoc   items      collection)
(getf    collection item)
Some of those are easily justifiable (e.g. GETF gets a place, GETHASH gets a value associcated with a hash) while others are not. It's not as incoherent as you made it to look here. It's also more simple in CL to look it up quickly, a simple (describe 'foo) in the REPL will set you straight.

Also note that NTH, ELT and AREF use indices while the others take different clues.
"By the way, Java takes a “the right thing” approach
...and is inflexible as hell (objects everywhere, interfaces instead of MI, ...).

Common Lisp gets things done, and gets them done effectively and in a way you can rely on. That's the point of it.

tayssir
Posts: 35
Joined: Tue Jul 15, 2008 2:33 pm

Re: Experience of Learning Lisp

Post by tayssir » Sat Jul 18, 2009 5:06 am

It's the other way round (because you cons an ITEM onto a COLLECTION).
A wonderful example where CL's inconsistency can trip a user up, causing a typo on the most basic operator of the bunch. ;) The art of the meta-example...
Some of those are easily justifiable (e.g. GETF gets a place, GETHASH gets a value associcated with a hash) while others are not. It's not as incoherent as you made it to look here.
I suspect that the fact that some have easy justifications -- while others don't -- is precisely why it's 'inconsistent.' That's why we speak of inconsistency rather than (say) randomness or consistency.

(But it's possible my list is glib or obscuring some axis of consistency, dunno. I haven't used CL much this year.)
Common Lisp gets things done, and gets them done effectively and in a way you can rely on. That's the point of it.
I pity the poor person who argues with that statement on a primarily Common Lisp forum.

I wrote a page listing "Lisp gotchas", but unfortunately something bad happened with the ALU wiki and I can't find it... (Was it programmed in Common Lisp? If so, that may have been less maintainable than going with an inexpensive service coded in a more mainstream language. For example, this Lisp forum was implemented in PHP.) I find that I've forgotten many of CL's inconsistencies, since I stopped using it this year.

This is not to say that CL is any less inconsistent than others; after all, it's one of my two favorite languages, and the inconsistencies are relatively insignificant though noticeable. (The other language is a descendant of CL, and I have no judgement on which is 'better' in some absolute sense.) The focus of this conversation is that you indeed have more power to fix inconsistencies.

tayssir
Posts: 35
Joined: Tue Jul 15, 2008 2:33 pm

Re: Experience of Learning Lisp

Post by tayssir » Sat Jul 18, 2009 5:34 am

[duplicate post removed]
Last edited by tayssir on Sat Jul 18, 2009 10:28 am, edited 1 time in total.

Harleqin
Posts: 71
Joined: Wed Dec 17, 2008 5:18 am
Location: Bonn, Germany

Re: Experience of Learning Lisp

Post by Harleqin » Sat Jul 18, 2009 7:19 am

tayssir wrote:
It's the other way round (because you cons an ITEM onto a COLLECTION).
A wonderful example where CL's inconsistency can trip a user up, causing a typo on the most basic operator of the bunch. ;) The art of the meta-example...
I think that this just shows that you have not understood CONS. Note that a list is just a shorthand for a bunch of cons cells connected in a defined way. (cons collection item) is not necessarily a mistake---unless you expected the collection to be a proper list before and after.
"Just throw more hardware at it" is the root of all evil.
Svante

gugamilare
Posts: 406
Joined: Sat Mar 07, 2009 6:17 pm
Location: Brazil
Contact:

Re: Experience of Learning Lisp

Post by gugamilare » Sat Jul 18, 2009 9:24 am

tayssir wrote:
Like what? The only thing that bugs me is (file-position s n) instead of (setf (file-position s) n)
Take a look at:

Code: Select all

(cons    item       collection) ; fixed :)
(gethash item       collection)
(elt     collection item)
(nth     item       collection)
(aref    collection items)
(assoc   items      collection)
(getf    collection item)
I somewhat agree and disagree with you.

I agree that nth, nth-value (which wasn't mentioned) and also gethash are reversed. I believe assoc isn't reversed because it does not belong to this group, but to the same group as find, member, remove, mapcar, ... assoc is about finding some item by walking through the list, not fetching something from a predetermined position.

Code: Select all

(assoc item collection) ~ (find item collection :key #'car)
The same could be argued about gethash, but that is not my opinion. By the way, the thing that most confuses me is sort (and, of course, stable-sort). They should be in this "walking through" group, and as such it should be called like (sort predicate sequence) instead of (sort sequence predicate).

Since I never use nth (in these cases I either use an array or destructuring-bind, first, second, third...), I don't care about it being reversed 8-)

About cons, it shouldn't be in this group in the first place, since it constructs, not fetches, and it is not reversed for a logical reason (it is (cons first rest) because the first element comes before the rest).

And a general rule about doubts in the sequence of arguments (and what arguments are accepted): use slime and look at emacs' status bar - it never fails ;)
tayssir wrote:And there was this evil little joke stuck in 'loop':

Code: Select all

(loop for k being the hash-keys of h using (hash-value v)
      ...)
It's maybe funny the first 100 times you type it out. (Not common enough to dedicate an emacs hotkey, not rare enough to be ignored... Maybe I should've written loop-mode.)
Hum... No arguments here :) That is one of the reasons why I like Iterate better than loop. In any case, there comes maphash for the salvation ;)
Well, not complete salvation, I agree :( but traversing hashtables is mostly useful for copying hashtables and other rare ocasions, and maphash deals with 99% of the cases very nicely.
Harleqin wrote:
tayssir wrote:A wonderful example where CL's inconsistency can trip a user up, causing a typo on the most basic operator of the bunch. ;) The art of the meta-example...
I think that this just shows that you have not understood CONS.
Well said :p
tayssir wrote:
Some of those are easily justifiable (e.g. GETF gets a place, GETHASH gets a value associcated with a hash) while others are not. It's not as incoherent as you made it to look here.
I suspect that the fact that some have easy justifications -- while others don't -- is precisely why it's 'inconsistent.' That's why we speak of inconsistency rather than (say) randomness or consistency.
I believe this is about disagreement. Disagreement sucks, there isn't much we can do about it.

CL sure does have its inconsistencies (just look at the map--- functions (how they are named) and you'll see a mess). But isn't it true in all languages? And also between different libraries - each library uses its creator's own conventions, and each one's conventions are different from each other. I believe this is a very small issue with CL, the smaller one, it is just a matter of getting used to it. The lack of standardization of modern tools (threads, sockets...), as I already mentioned, is much worse than this... Well, nothing that some compat libs like bordeaux-threads and usocket (or other socket lib) can't take care of :) but it would be much nicer and consistent if they were standardized, then you could rely on it being there always.

tayssir
Posts: 35
Joined: Tue Jul 15, 2008 2:33 pm

Re: Experience of Learning Lisp

Post by tayssir » Sat Jul 18, 2009 10:01 am

Harleqin wrote:I think that this just shows that you have not understood CONS. Note that a list is just a shorthand for a bunch of cons cells connected in a defined way. (cons collection item) is not necessarily a mistake---unless you expected the collection to be a proper list before and after.
No, the other fellow (skypher) was correct in pointing out the typo -- he was immediately able to grasp the context, which was about constructing a proper list. But thank you for helping us stumble onto yet another inconsistency (and I hope that was your subtle point ;) ):

Code: Select all

CL-USER> (listp (cons 1 2))
T

CL-USER> (list-length (cons 1 2))
; Evaluation aborted.
; The value 2 is not of type LIST.
;    [Condition of type TYPE-ERROR]
(Incidentally Clojure doesn't exhibit this particular behavior; (cons 1 2) throws an error, as the documentation clearly defines the 2nd parameter to be a seq.)

To use anecdotal evidence, constructing a proper list was far and away the most common use-case for CONS at the Lisp companies I worked with; IIRC, improper lists only occasionally popped up with alists. This is why I suspect my post doesn't require special explanation to most Common Lisp users. And for those which do require it, perhaps it's because of the mental confusion which CL's inconsistencies engender?

And do people use alists (where you do typically have improper lists) in contexts were hashtables are more appropriate, due to.. maybe not an 'inconsistency'.. but a conceptual incompleteness compared to other languages?

gugamilare
Posts: 406
Joined: Sat Mar 07, 2009 6:17 pm
Location: Brazil
Contact:

Re: Experience of Learning Lisp

Post by gugamilare » Sat Jul 18, 2009 10:34 am

tayssir wrote:But thank you for reminding me of another inconsistency (and I hope that was your subtle point ;) ):

Code: Select all

CL-USER> (listp (cons 1 2))
T

CL-USER> (list-length (cons 1 2))
; Evaluation aborted.
; The value 2 is not of type LIST.
;    [Condition of type TYPE-ERROR]
(Incidentally Clojure doesn't exhibit this particular behavior; (cons 1 2) throws an error, as the documentation clearly defines the 2nd parameter to be a seq.)
IMO, that is not a good thing for Clojure to do. You could use cons to construct trees or pairs, not only sequences.

The function listp tests if the argument is a list, not a proper list.
tayssir wrote:And do people use alists (where you do typically have improper lists) because using hashtables is a pain, due to.. maybe not an 'inconsistency'.. but a conceptual incompleteness compared to other languages?
I disagree, with all the respect. People use alists when either the "table" is small or when you need to traverse it frequently. Hashtables are used quite often when the problem is accessing values related to keys. In other words, alist is a sequence and hashtable is a table. Walking through a hashtable is not very efficient, and I get the felling that doing it is not the right way to solve problems most times as well. That is the reason there isn't much of a need to create all sorts of hashtable functions like there are for lists or vectors. If such functions were in fact needed, there would be some library to do that.

tayssir
Posts: 35
Joined: Tue Jul 15, 2008 2:33 pm

Re: Experience of Learning Lisp

Post by tayssir » Sat Jul 18, 2009 1:06 pm

I disagree, with all the respect. People use alists when either the "table" is small or when you need to traverse it frequently. Hashtables are used quite often when the problem is accessing values related to keys. In other words, alist is a sequence and hashtable is a table. Walking through a hashtable is not very efficient, and I get the felling that doing it is not the right way to solve problems most times as well. That is the reason there isn't much of a need to create all sorts of hashtable functions like there are for lists or vectors. If such functions were in fact needed, there would be some library to do that.
[As you were responding, but before you submitted it, I edited my post with the clarification, "in contexts were hashtables are more appropriate," where 'appropriateness' is presumably decided by the lisp user's intent. (This is easily verified, since otherwise my post would automatically say it was edited.) You know, I quickly wrote that clarification because anything which appears vaguely critical about Lisp tends to be read with much more scrutiny on Lisp forums, to the extent that you have to be as pre-cise and aggressively willing to clarify misinterpretations as that fearsome Knight of the Lambda Calculus who recently passed away.]

Well, that goes to show you probably read the low-level efficiency chapter in PAIP. Congratulations, you're one of those skilled lisp programmers I keep hearing about. ;)

However, I think most people just use what's convenient, even if it compromises their intent somewhat. (Like performance similar to hashtables, and the simple ability to add/remove. (If fast performance on small tables is desired, then that optimization can be made. But people tend to worry more about the difference between constant- and linear-time performance.)

But I fear we have blundered onto yet another lisp inconsistency, far more insidious than even the preceding ones. How do people frequently construct an alist?

Code: Select all

CL-USER> (defvar *foo*
           '((:a . 1)
             (:b . 2)))

;; “I just sensed a glitch in the Matrix.”
Ok, so they're playing with this table, and soon attempt to set the value of one of the keys via a destructive operation like (setf (cdr ...)). Like in the Hyperspec.

Oops.

It's undefined to destructively modify "literals" like quoted lists. Missiles may well be on their way to your home. (As mentioned in another thread, Lisp is a DARPA technology, so this is likelier than we might expect.)

People have been bewildered after falling prey to this problem. Real-world implementations differ on the semantics: LispWorks did one thing and SBCL another.

Post Reply