cons return a list and pair in scheme - 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.

Related

Why the same data is printed differently when built with list or cons? [duplicate]

This question already has answers here:
Dot notation in scheme
(3 answers)
Closed 5 years ago.
I tried to reproduce the same data layout by using different combinations of list and cons. In MIT Scheme, the same data layout seems to be printed differently depending on how it was built.
In example,
> (cons 1 (cons 2 3))
(1 2 . 3)
> (list 1 (cons 2 3))
(1 (2 . 3))
> (cons 1 (list 2 3))
(1 2 3)
> (list 1 (list 2 3))
(1 (2 3))
The underlying data should always be the same. Why does MIT Scheme represents it differently? Is the underlying arrangements of pairs really the same every time?
Each of the inputs is building a different output, so they're printed differently. Notice that the following expressions are equivalent:
(cons 1 (cons 2 3))
; (1 2 . 3)
(list 1 (cons 2 3))
(cons 1 (cons (cons 2 3) '()))
; (1 (2 . 3))
(cons 1 (list 2 3))
(cons 1 (cons 2 (cons 3 '())))
; (1 2 3)
(list 1 (list 2 3))
(cons 1 (cons (cons 2 (cons 3 '())) '()))
; (1 (2 3))
Remember: a list is defined if and only if the cdr part of each cons is also a cons cell, or an empty list.

Reversing list with sublists and atoms in lisp

I am new to a functional programming and trying to reverse a list in lisp. List consists of sublists and atoms. The function (reverse-tree '((1 2) 5 6 (3))) should return ((3) 6 5 (2 1)). Here is my function:
(define (reverse-tree s)
;; giving problem with an atom
(if (not(list? s)) ( reverse-tree s) (reverse (map reverse s)))
)
It works when I do (reverse-tree '((1 2) (3))) => ((3) (2 1)). But it crashes when I do (reverse-tree '((1 2) 5 6 (3))). The error I am getting is reverse: contract violation expected: list?
I am limited to use only: reverse, map, if, cond, list? null? functions.
EDIT, someone marked this question as duplicate, but there is a restriction in this problem, which is not similar to the other question. I cannot use cons, car, cdr, append. Any suggestions?
Think about the problem in pieces. First, if the function is given a list as an argument, you need to reverse that list. That's easy, something like:
(define (reverse-tree tree)
(if (list? tree)
(reverse tree)
...))
But you also need to reverse all sublists in it and all sublists in them and so on. Since that's exactly what our reverse-tree does, we should use map to apply it to all elements in the reversed list (it doesn't actually matter whether you use map before or after reversing the list):
(define (reverse-tree tree)
(if (list? tree)
(map reverse-tree (reverse tree))
...))
But if the input is ((1 2) 3 4 (5 6)), the map will call reverse-tree on the atoms 3 and 4 too. It wouldn't make any sense to reverse them, so we can just return them:
(define (reverse-tree tree)
(if (list? tree)
(map reverse-tree (reverse tree))
tree))
Now it should work:
(reverse-tree '((1 2) 3 4 (5 6)))
;=> ((6 5) 4 3 (2 1))
(reverse-tree '((1 2) 3 4 (5 6 (7 8))))
;=> (((8 7) 6 5) 4 3 (2 1))

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

Racket/ more than one function

How could I address this problem?
Given a function of arity 1 and a list, return a list of applying the function to each element of the original list. For example:
(Mmap add1 '(1 2 3 4)) ; -> '(2 3 4 5)
(Mmap car '((1 2 3) (4 5 6) (7 8 9))) ; -> '(1 4 7)
(Mmap cdr '((1 2 3) (4 5 6) (7 September 8))) ; -> '((2 3) (5 6) (8 9))
I've tried cond and other similar functions, but I really have little idea how to solve it.
(define (myfunc f alist)
(cond
[(empty? alist) empty]
[else (cons (f (first alist)) (myfunc f (rest alist)))]
))
f is your function (e.g. add1, car) and alist is your argument. All you have to do is to construct a list where you apply f to your first argument, and append the rest of the list recursively to that.
Regarding your last example. I assume that September was defined previously as (define September 8). In that case your example won't give you your desired output. The last list will contain 'September instead of 8, because you declared your list with '(), which treats names as symbols.
Furthermore, the output should be '((2 3) (5 6) (8 8)) given that cdr returns the second and subsequent elements of a list. So you probably want (list 7 September 9) as your last list in your input, so that you get '((2 3) (5 6) (8 9)) instead.
You'd have to call the function like this: (myfunc cdr (list (list 1 2 3) (list 4 5 6) (list 7 September 9)))
Edit: Obviously it would make most sense to define September as 9, as it's the ninth month of the year, and call the function like this: (myfunc cdr (list (list 1 2 3) (list 4 5 6) (list 7 8 September)))
Mmap can be defined in terms of #lang racket's function map.
(define Mmap map)

Scheme cons and length

I'm studying scheme and I have just encountered my first problem:
(define x (cons (list 1 2) (list 3 4)))
(length x)
3
why the output is 3 and not 2? I have displayed x
((1 2) 3 4)
why is like that and not ((1 2) . (3 4)) ?
Thanks.
Maybe it's easier to see this way.
You have:
(cons (list 1 2) (list 3 4))
If you
(define one-two (list 1 2))
you have
(cons one-two (list 3 4))
which is equivalent to
(cons one-two (cons 3 (cons 4 '())))
or
(list one-two 3 4)
which is
((1 2) 3 4)
List is the basic data structure of scheme.
Cons is used for making a pair of objects. List is the chain of cons.
eg. list (1 2 3 4) is same as (cons 1(cons 2(cons 3(cons 4 '())))).
See the block pointer representation for make it clear

Resources