Why is elt not as common as car, cdr, first, rest?
Asked Answered
M

2

5

I see this a lot in examples I read in books and articles:

(caddr *something*)

Or the many variants of c***r commands.

It seems a bit ridiculous to me, when you can more clearly just pull things out with elt:

(elt *something* 2)

But I don't see this technique used as much.

Is there a convention I don't understand that prefers the c***r functions?

Malchy answered 14/11, 2013 at 3:19 Comment(1)
I think that the answers include this, but very concisely: Linked lists aren't great for random access. elt (and nth) are random access functions. Most of the code that you'd write for list processing will be more concerned with, e.g., the first and rest of a list, not arbitrary elements. It's rare to see elt or nth for lists because it's not used in much typical code. It's also not very common to see c[ad]+r functions in typical code, because it's not typically the way we work with lists. Unfortunately, books and articles don't always exemplify typical code.Kehr
E
5

elt is a generic function that works on both lists and arrays. It is needed when you want to write a generic algorithm which works in the same way on both data types. But there aren't many such algorithms because this would usually disadvantage lists.

The general convention seems to be that:

  • If you write a general-purpose function to work on lists you would use c(a|d)+r function (these cases are exceedingly rare because most of the time there is a library function for that). This usually happens in Stackoverflow questions code / code for class assignments etc :)

  • Seasoned Lisp programmers would use first, second etc. if possible. This is also some times mentioned in best practices. The best practices would also usually mention that one should create appropriate data structures instead of dealing with non-trivial lists.

  • nth or elt are indeed rare because it's hard to think of a good use case for them. I can imagine how both can be used in macros, where the performance isn't important, but some kind of generality is desirable, for instance if someone would want to deal with strings and lists of characters in the same way. Maybe in some prototyping code, where the programmer isn't yet sure of what data type they are going to use, but that's about it.

Edy answered 14/11, 2013 at 7:22 Comment(3)
what is an example of a library function you might refer to in your first point?Malchy
@OpenLearner here's one typical example: stackoverflow.com/questions/10465096 where there's already alexandria:flattenEdy
note that "generic function" here doesn't mean the Common Lisp generic function that's a part of CLOS, but rather "works with sequences, i.e., both lists and vectors".Kehr
M
5

Functions like caddr, etc can extract components from lists nested inside other lists. But elt only operates on the top-level list, thus it could return a nested list in its entirety, but you'd need to also nest elt commands to extract components, which is what caddr is ultimately doing, so they are not really so comparable.

In some cases, you could interchange them, as they might return the same results if your list has no lists inside it.

Malchy answered 14/11, 2013 at 3:33 Comment(5)
Somewhat similarly and perhaps worthy of mention in this context, (CADR SOME-LIST) is simpler and clearer than (FIRST (REST SOME-LIST)).Funest
I like (SECOND SOME-LIST) and (NTH 1 SOME-LIST).Cladoceran
Another way of putting what @OpenLearner is saying is that elt gives you (directly) only car, cadr, caddr, cadddr,... It does not directly give you cdr, cddr, cdar,... The c(a|d)+r functions paint pictures by their names of just how they destructure list structure.Motch
@Cladoceran second and nth still fail to get at components of a nested list. like elt they operate only the top-most level.Malchy
I mentioned this in a comment, but to reiterate: it's also not all that common to extract arbitrary indexed elements from lists or cons-trees. List processing code favors first/rest (or car/cdr), and code for structured lists/trees (e.g., in macro writing or home grown structures) will typically define domain-specific accessors (e.g., (defun name (x) (first x)) (defun address (x) (second x))) or use destructuring-bind (e.g., (destructuring-bind (name address) x ...)).Kehr
E
5

elt is a generic function that works on both lists and arrays. It is needed when you want to write a generic algorithm which works in the same way on both data types. But there aren't many such algorithms because this would usually disadvantage lists.

The general convention seems to be that:

  • If you write a general-purpose function to work on lists you would use c(a|d)+r function (these cases are exceedingly rare because most of the time there is a library function for that). This usually happens in Stackoverflow questions code / code for class assignments etc :)

  • Seasoned Lisp programmers would use first, second etc. if possible. This is also some times mentioned in best practices. The best practices would also usually mention that one should create appropriate data structures instead of dealing with non-trivial lists.

  • nth or elt are indeed rare because it's hard to think of a good use case for them. I can imagine how both can be used in macros, where the performance isn't important, but some kind of generality is desirable, for instance if someone would want to deal with strings and lists of characters in the same way. Maybe in some prototyping code, where the programmer isn't yet sure of what data type they are going to use, but that's about it.

Edy answered 14/11, 2013 at 7:22 Comment(3)
what is an example of a library function you might refer to in your first point?Malchy
@OpenLearner here's one typical example: stackoverflow.com/questions/10465096 where there's already alexandria:flattenEdy
note that "generic function" here doesn't mean the Common Lisp generic function that's a part of CLOS, but rather "works with sequences, i.e., both lists and vectors".Kehr

© 2022 - 2024 — McMap. All rights reserved.