Pairing pairs in racket - scheme

Using racket cons function I can pair two numbers into one pair for example (cons 1 2) would return a pair (1 . 2), but I can't use cons to make a pair of two pairs, (cons (cons 1 2) (cons 3 4)) returns ((1 . 2) 3 . 4), what I want is ((1 . 2) . (3 . 4))
How can I do such a thing ?

The two datums ((1 . 2) 3 . 4) and ((1 . 2) . (3 . 4)) are exactly the same. So don't worry, you've got it right.

Related

cons return a list and pair in scheme

I just started to learn scheme. My question is why does (cons 3 (4)) return a list (3 4) but (cons (4) 3) returns a pair ((4) . 3)? should (cons 3 (4)) returns (3 . (4)) as well?
Both (3 4) and (3. (4))are the list (cons 3 (cons 4 '()))), and if you enter '(3 . (4)) in your REPL, you will most likely see '(3 4) as the result.
The difference you're seeing is just an output convention; a pair where the cdr is a list is not printed with dot notation.

Can someone explain the difference between Cons and Append in scheme?

I read both of them and they seem to both construct a single list, what's their difference?
cons is the constructor for all pairs.
A proper list is () (the empty list, aka nil) or a pair where the cdr is a proper list. Any chain of pairs where the last one has () as it's cdr is a proper list (in addition to the empty list itself).
A dotted list is a pair that does not have a proper list as it's cdr. Thus a chain of pairs where the last cdr is not () matches this.
;; dotted lists
(cons 1 2) ; ==> (1 . 2)
(cons 1 (cons 2 3)) ; ==> (1 2 . 3) or (1 . (2 . 3))
;; proper lists
(cons 1 '()) ; ==> (1) or (1 . ())
(cons 1 (cons 2 '())) ; ==> (1 2) or (1 . (2 . ()))
append is a procedure that uses cons to make a list with all the elements of the argument lists left to right. A common implementation of append for just two lists would be:
(define (append lst tail)
(if (null? lst)
tail
(cons (car lst)
(append (cdr lst)
tail))))
append will fail if one of the arguments except the last is not a proper list. Tail and can be any value:
(append '(1 2 3) '(4 5)) ; ==> (1 2 3 4 5) or (1 . (2 . (3 . (4 . (5 . ())))))
(append '(1 2 3) '(4 5 . 6)) ; ==> (1 2 3 4 5 . 6) or (1 . (2 . (3 . (4 . (5 . 6)))))
(append '(1 2 3) #f) ; ==> (1 2 3 . #f) or (1 . (2 . (3 . #f)))
(append '(1 2 . 3) '(4 5 . 6)) ; ==> error `car` of number not allowed

Cons in scheme explanation

(cons 1 2) gives us (1 . 2).
(cons 3 4) gives us (3 . 4).
So why does (cons (cons 1 2) (cons 3 4)) give us ((1 . 2) 3 . 4)?
Why isn't it ((1 . 2) (3 . 4))?
Well, it wouldn't be ((1 . 2) (3 . 4)) because that would be a list containing two elements, each a cons pair. I'm guessing what you meant was: why isn't it ((1 . 2) . (3 . 4))?
Well, actually the following two expressions are equivalent:
'((1 . 2) . (3 . 4))
'((1 . 2) 3 . 4)
This has to do with how Scheme's dotted notation works in tandem with its representation of proper lists. Remember that this:
'(1 . (2 . (3 . (4 . ()))))
...would simply be printed as this:
(1 2 3 4)
However, this:
'(1 . (2 . (3 . 4)))
...would be printed like this:
(1 2 3 . 4)
Note that Scheme tries to use the simplified list notation as long as it can—it only falls back to explicitly dotting things once it reaches a pair which doesn't have a pair or the empty list as its cdr element.
Therefore, in your original example, the second element of that cons pair is a pair, so Scheme uses the list notation. That lets it drop the second set of parentheses and the extra dot, yielding the result you encountered.

Scheme explanation - cdr and car

I've got this example :
(apply + 2 (cdadr '(1 ((2 . 3) 4))))
This returns 6? Why is (cdadr '(1 ((2 . 3) 4))) 4??
I don't get it.Shouldn't it be 3?
The result is the list '(4), not the number 4.
You have a list with two elements, where 1 is the first element, and the list ((2 . 3) 4) is the second element.
In other words, the cdr of the list is (cons ((2 . 3) 4)) '()), or (((2 . 3) 4)).
> (cdr '(1 ((2 . 3) 4)))
'(((2 . 3) 4))
This is a list with one element - the list ((2 . 3) 4) - which is of course the car.
> (car (cdr '(1 ((2 . 3) 4))))
'((2 . 3) 4)
and, finally,
> (cdr (car (cdr '(1 ((2 . 3) 4)))))
'(4)
A list (a b c) is short for (a . (b . (c . ()))).
Therefore '(1 ((2 . 3) 4))) is short for '(1 ((2 . 3) . (4 . ())) . ()).
To make sure, we test it in the REPL:
> ''(1 ((2 . 3) . (4 . ())) . ())
'(1 ((2 . 3)) 4)
cdadr is short for (cdr (car (cdr _))).
Here car extract the first part of a pair (car '(a . d)) = a
and cdr extract the second part of a pair (cdr '(a . d)) = d
Let's see what happpens:
> (cdr '(1 ((2 . 3) . (4 . ())) . ()))
'(((2 . 3) 4))
> (car (cdr '(1 ((2 . 3) . (4 . ())) . ())))
'((2 . 3) 4)
> (cdr (car (cdr '(1 ((2 . 3) . (4 . ())) . ()))))
'(4)
> (apply + 2 '(4))
6
Note that ((2 . 3) 4) is the same as ((2 . 3) . (4 . ())) and that the cdr of this (4 .()) aka (4).

Lisp: How to get all possible combinations of the elements from lists contained on a list?

I need to write a function in Common-Lisp that takes a list of lists and returns a list containing all the possible combinations of the elements from the sublists.
So, for example calling the function on a list such as ((1 2) (1 2)) should return a list like ((1 1) (1 2) (2 1) (2 2)). The input list can be of any length and the sublists are not guaranted to have the same length.
I know how to get this with paired elements from the sublists ( inputtting ((1 2) (1 2)) returns ((1 1) (2 2)), but that's not good enough for the arc-consistency algorithm I'm trying to write, and I'm stuck.
Thank you.
If you don't want to use a library, here's code to do the same thing, and works with any number of lists:
(defun combinations (&rest lists)
(if (endp lists)
(list nil)
(mapcan (lambda (inner-val)
(mapcar (lambda (outer-val)
(cons outer-val
inner-val))
(car lists)))
(apply #'combinations (cdr lists)))))
[2]> (combinations '(1 2))
((1) (2))
[3]> (combinations '(1 2) '(3 4))
((1 3) (2 3) (1 4) (2 4))
[4]> (combinations '(1 2) '(3 4) '(5 6))
((1 3 5) (2 3 5) (1 4 5) (2 4 5) (1 3 6) (2 3 6) (1 4 6) (2 4 6))
wvxvw removed their answer that pointed to a function from Alexandria, but it does provide a very similarly named function that actually does what you want. Instead of alexandria:map-combinations, you need alexandria:map-product, e.g.
(apply #'alexandria:map-product #'list '((1 2) (1 2)))
evaluates to
((1 1) (1 2) (2 1) (2 2))

Resources