Why the result of (cons (list 1 2) (list 3 4)) is ((1 2) 3 4)?
I wonder why the result length is 3(3 elements). My intuition makes me think that
(list 1 2) is a list, (list 3 4) is also a list. By using cons procedure, result should be two elements with each element a list, but the result is not as I expect.
Can anybody tell me why? Thanks.
(list a b c) is equivalent to (cons a (list b c)) by definition (or, if you continue the transformation, (cons a (cons b (cons c nil))).
So if you write (cons 1 (list 3 4)), this is equivalent to (cons 1 (cons 3 (cons 4 nil))), or to (list 1 3 4).
Now, replace 1 with (list 1 2), and you get this: (cons (list 1 2) (cons 3 (cons 4 nil))), or equivalently (list (list 1 2) 3 4) (or, fully written out, (cons (cons 1 (cons 2 nil)) (cons 3 (cons 4 nil)))).
The key here is that cons is not append, nor list (which treat all their elements equally): it is inherently asymetrical, when dealing with lists. The left spot holds the element ("head"); the right one holds the rest of the list ("tail").
Related
A common and simple way of appending two lists is as follows:
(define (append a b)
(if (null? a)
b
(cons (car a) (append (cdr a) b))))
Why does this work? When we reach the final element of a, my clearly incorrect belief is that we will be calling (cons [the original list a, built out of many calls to (cons (car a) ...)] [the original list b]). In short, I can't see why function does not return (cons a b), which would be a cons cell containing two lists. Even if I'm wrong about the a part, why is it valid to add b to our output as a whole list, without first breaking it down in to its individual elements?
I suspect that a worked example will be of great value to an answer.
Nowhere is a consed to b. Instead, the elements of a are consed to b, starting from the last element of a. Consider:
(append '() '(1 2 3))
--> '(1 2 3) ; there are no elements in `a` to cons onto `b`
(append '(y) '(1 2 3))
--> (cons (car '(y)) (append (cdr '(y)) '(1 2 3)))
--> (cons 'y (append '() '(1 2 3)))
--> (cons 'y '(1 2 3)) ; the last element of `a` is consed onto `b`
--> '(y 1 2 3)
(append '(x y) '(1 2 3))
--> (cons (car '(x y)) (append (cdr '(x y)) '(1 2 3)))
--> (cons 'x (append '(y) '(1 2 3)))
--> (cons 'x (cons (car '(y)) (append (cdr '(y)) '(1 2 3))))
--> (cons 'x (cons 'y (append '() '(1 2 3))))
--> (cons 'x (cons 'y '(1 2 3))) ; the last element of `a` is consed onto `b`
--> (cons 'x '(y 1 2 3)) ; then the next-to-last element of `a`, and so on
--> '(x y 1 2 3)
Second sentence of Section 2.2.2 (Hierarchical Structures) of SICP: the authors say that ((1 2) 3 4) (a list of three elements) can be constructed by (cons (list 1 2) (list 3 4)).
I think (wrongly so, of course) that it will construct ((1 2) (3 4)) (two elements) instead because:
3 and 4 will be enclosed in a nested list not in the top-level cons, and
cons constructs a pair of items, and pair means 2 elements not 3.
What am I failing to understand here?
A list is a chain of pairs, ending with a pair whose cdr is the empty list.
(list 3 4) is two pairs, equivalent to
(cons 3 (cons 4 '()))
So (cons (list 1 2) (list 3 4)) is 3 pairs, equivalent to
(cons (list 1 2) (cons 3 (cons 4 '())))
In general, if you have a list old-list, you can create a new list with a new element on the front with:
(cons new-element old-list)
You would get what you expected if you wrote
(list (list 1 2) (list 3 4))
Give a single function to access the element a in the list L.
(define L '(1 2 (a 3 4 5)))
Following the form (define id expr) which binds id to the result of expression I have tried the following:
(define L '(1 2 (a 3 4 5) (car(cdr L))))
cdr accesses the tail of the list, i.e. a 3 4 5, if I am not mistaken, and then I apply car on the tail to access the head of the list, i.e a. However, it is not working on DrRacket IDE.
I think you meant to do this:
(define L '(1 2 (a 3 4 5)))
(car (car (cdr (cdr L))))
=> 'a
Which can also be written as:
(caaddr L)
=> 'a
You included the (car(cdr L)) part inside the list L.
> (define L '(1 2 (a 3 4 5) (car(cdr L))))
> L
(list 1 2 (list 'a 3 4 5) (list 'car (list 'cdr 'L))) ;; oh no
But that still doesn't extract the 'a because you need to access car of the inner list:
(define L '(1 2 (a 3 4 5)))
(car (car (cdr (cdr L))))
;; or (caaddr L)
How can I add a parentheses in a list? For example,
(multiply '(1 2) '(1 2 3))
It should output ((1 2 3) (2 4 6))
This is what I have now
(define multiply
(lambda (los1 los2)
(cond
((null? los1) '())
((null? los2) '())
(else (cons (* (car los1) (car los2))
(append (multiply(list (car los1)) (cdr los2))
(multiply(cdr los1) los2)))))))
The output I get is (1 2 3 2 4 6).
P/S: If this is a bad question or anything, don't hesitate to tell me or scold me. I am trying to learn to use stackoverflow.
Think about what the implications of the input and the output are. I imagine that you cannot do this with one single recursive procedure, but you can do it with two.
(list-multiply 5 '(1 2 3))
; ==> (5 10 15)
When you have that you iterate over the first list and use list-multiply for each element and of course the second argument is never iterated, it's just passed along.
(multiply '(1 2) '(1 2 3))
; ==> (cons (list-multiply 1 '(1 2 3))
; (cons (list-multiply 2 '(1 2 3))
; '()))
; ==> ((1 2 3) (2 4 6))
You can implement this simply by useinfg higher order functions:
(define (multiply lst1 lst2)
(map (lambda (e1)
(map (lambda (e2) (* e1 e2)) lst2))
lst1))
Notice the double map. One that iterates lst1 to make elements in the result and a second map that multiplies the one element with each element of the list. You might imagine that since these look similar the two recursive functions probably have a lot in common too.
PS: Learn to solve your problems without list and append. (list 1 2 3) is just a procedure that is equivalent to (cons 1 (cons 2 (cons 3 '()))) and (append '(1 2 3) '(4 5 6)) is equivalent to (cons 1 (cons 2 (cons 3 '(4 5 6)))). Try always building lists from end to beginning and in the event you need the opposite it might just need a reverse in the end.
How can I check if a list in lisp is a dotted pair?
CL-USER 20 : 3 > (dotted-pair-p (cons 1 2))
T
CL-USER 20 : 3 > (dotted-pair-p '(1 2))
NIL
CL-USER 20 : 3 > (dotted-pair-p '(1 2 3))
NIL
I tried checking if length=2 but got error:
CL-USER 28 : 1 > (= (length (cons 2 3)) 2)
Error: In a call to LENGTH of (2 . 3), tail 3 is not a LIST.
A lisp list in "dotted pair notation" looks something like:
(1 . ()).
Since this is homework, I'll let you take this to the logical conclusion. Compare
(LIST 1 2) => (1 . (2 . ()))
with
(CONS 1 2) => (1 . 2).
What is different between these two? How can you tell the difference using predicates?
Remember all proper lisp lists end with the empty list. Ask yourself how do you access the second element of a cons pair? The solution from there ought to be clear.
Because a list always ends with the empty list, while a pair doesn't:
(listp (cdr '(1 2))) => T
(listp (cdr '(1 . 2))) => NIL
(not(listp(cdr (cons 1 2))))=> T
(not(listp(cdr (list 1 2))))=> nill
A dotted pair is a cons cell where it's CDR is not a cons itself (recursive definition). So this '(1 . 2) is a dotted pair, but this '(1 . ()) isn't, since it is just the printed representation of and the same as '(1).
(defun dotted-pair-p (x)
(and (consp x)
;; Check that CDR is not a list with LISTP
;; since (CONSP ()) ;;=> NIL
;; and the CDR of a pair can't be NIL for it
;; to be dotted.
(not (listp (cdr x)))))
(dotted-pair-p '(1 . 2)) ;T
(dotted-pair-p '(1 . ())) ;NIL
Dotted lists (lists whose last cons cell is dotted) are defined in Common Lisp by LIST*. We can now use the above function to define a predicate for them too:
(defun list*p (x)
(dotted-pair-p (last x)))
(list*p (list* 1 2 3 4)) ;T
(list*p (list 1 2 3 4)) ;NIL
You can check if a list is dotted (ends with a non-nil atom) with:
(defun dotted-listp (l)
(cond ((null l) nil)
((atom l) t)
(t (dotted-listp (cdr l)))))