Object-oriented languages often come with a “collections” library that provides a variety of data structures for storing collections of objects. Methods on collections usually pass the collection as the first argument for two reasons: (1) the collection is the primary object being operated on, and (2) in many languages, method dispatch only works on the first argument.
In Lisp, however, lists are a collection type that is derived from a more primitive data type, the cons cell. Lists are not fully abstracted from cons cells and many list operations are actually defined as operations on cons cells. Rather than the list argument always coming first, there is little rhyme or reason to the order of arguments in list operations. This becomes evident when you try to use higher-order operations on lists.
cons
constructs a cons cell, with two fields, a car
and a cdr. The car is traditionally written to the left of the cdr,
and cons
takes the car as the first argument.
In Lisp, there is no special constructor for lists. The user
directly constructs the underlying cons cell and simply “declares in
his head” that the result is a list. Hence when we are extending a
collection with an item, the collection is the second argument
to cons
rather than the first. In a “modern”
curly-brace, object-oriented language, we would extend mylist by
writing mylist.cons(item)
Here’s where it makes a difference:
The fold-left
function iterates down a list and calls
a combining function on each element of the list. The first
argument to the combining function is the accumulated answer, the
second is the element being accumulated. If we want to accumulate
into a list, the accumulated list is passed first and the new item
is passed second. This means that cons
is not
suitable as the combining function in fold-left
because
the arguments come in the wrong order:
(defun bad-reverse (list) (fold-left #’cons ’() list)) ;; does not reverse a list (defun xcons (cdr car) ;; takes original list first (cons car cdr)) (defun reverse (list) (fold-left #’xcons ’() list)) ;; correcty reverses a list
Many list operations, remove
and adjoin
for example, take their arguments in an inconvenient order
for fold-left
.
No comments:
Post a Comment