user1076329
user1076329

Reputation: 61

good style in lisp: cons vs list

Is it good style to use cons for pairs of things or would it be preferable to stick to lists?

like for instance questions and answers:

(list
    (cons
        "Favorite color?"
        "red")
    (cons
        "Favorite number?"
        "123")
    (cons
        "Favorite fruit?"
        "avocado"))

I mean, some things come naturally in pairs; there is no need for something that can hold more than two, so I feel like cons would be the natural choice. However, I also feel like I should be sticking to one thing (lists).

What would be the better or more accepted style?

Upvotes: 4

Views: 1651

Answers (3)

user797257
user797257

Reputation:

You would need to decide for yourself based upon circumstances. There isn't a universal answer. Different tasks work differently with structures. Consider the following:

  • It is faster to search in a hash-table for keys, then it is in the alist.
  • It is easier to have an iterator and save its state, when working with alist (hash-table would need to export all of its keys as an array or a list and have a pointer into that list, while it is enough to only remember the pointer into alist to be able to restore the iterator's state and continue the iteration.
  • Alist vs list: they use the same amount of conses for even number of elements, given all other characters are atoms. When using lists vs alists you would have to thus make sure there isn't an odd number of elements (and you may discover it too late), which is bad.
  • But there are a lot more functions, including the built-in ones, which work on proper lists, and don't work on alists. For example, nth will error on alist, if it hits the cdr, which is not a list.
  • Some times certain macros would not function as you'd like them to with alists, for example, this:

(destructuring-bind (a b c d) 
  '((100 . 200) (300 . 400)) 
   (format t "~&~{~s~^,~}" (list a b c d)))

will not work as you might've expected.

  • On the other hand, certain procedures may be "tricked" into doing something which they don't do for proper lists. For instance, when copying an alist with copy-list, only the conses, whose cdr is a list will be copied anew (depending upon the circumstances this may be a desired result).

Upvotes: 2

Vsevolod Dyomkin
Vsevolod Dyomkin

Reputation: 9451

The default data-structure for such case should be a HASH-TABLE.

An association list of cons pairs is also a possible variant and was widely used historically. It is a valid variant, because of tradition and simplicity. But you should not use it, when the number of pairs exceeds several (probably, 10 is a good threshold), because search time is linear, while in hash-table it is constant.

Using a list for this task is also possible, but will be both ugly and inefficient.

Upvotes: 3

C. K. Young
C. K. Young

Reputation: 222973

What you have there is an association list (alist). Alist entries are, indeed, often simple conses rather than lists (though that is a matter of preference: some people use lists for alist entries too), so what you have is fine. Though, I usually prefer to use literal syntax:

'(("Favorite color?" . "red")
  ("Favorite number?" . "123")
  ("Favorite fruit?" . "avocado"))

Alists usually use a symbol as the key, because symbols are interned, and so symbol alists can be looked up using assq instead of assoc. Here's how it might look:

'((color . "red")
  (number . "123")
  (fruit . "avocado"))

Upvotes: 9

Related Questions