Given
#;> (cons (cons 1 2) 3)
((1 . 2) . 3)
When we try
#;> (cons 3 (cons 1 2))
(3 1 . 2)
What governs where the . is used? What would the memory representation of these constructs be?
Scheme implementations usually print things that look like lists in list form:
-> (cons 1 (cons 2 '()))
'(1 2)
In your example, (cons 3 (cons 1 2)) would be a list if it weren't for the last 2. So your implementation makes a best effort to print it as a list until the 2. The other example does not contain any part that looks like a list, so it just prints as nested pairs.
Related
In Python the data structure looks like this: [([1 2 3], [8 9 10])] (a list of tuple, where tuple is of size 2, and each tuple element is a list again)
How would I represent the same in Scheme r5rs?
This is what I tried: (list (cons `(1 2 3) `(8 9 10)))
But running (display (list (cons `(1 2 3) `(8 9 10)))) gives (((1 2 3) 8 9 10)) whereas I want (((1 2 3) (8 9 10)))
Edit
Using only lists (as per #Will Ness answer here):
(list ; a pair of elements,
(list 1 2 3) ; 1 each is itself
(list 8 9 10))) ; 2 a list
works.
And I can access the 2nd element of the tuple by
(cadr (car x)) which gives (8 9 10) (which is correct)
I was just thinking how would I build this up using cons since my tuple will only contain 2 elements and from what I know cons are used to represent a pair in Scheme. Any ideas on how to do this using cons?
[([1 2 3], [8 9 10])] (a list of tuple, where tuple is of size 2, and each tuple element is a list again)
(list ; a list of
(list ; a pair of elements,
(list 1 2 3) ; 1 each is itself
(list 8 9 10))) ; 2 a list
Scheme is untyped, so we can just use lists for tuples. It is simpler that way -- the access is uniform. The first is car, the second cadr.
Your way is correct as well. What really determines whether it is or not is how you can access your data to retrieve its constituents back. And with your way you can indeed, too: the first element will be car and the second -- cdr.
(update to the question edit:) whether you use (cons 1 (cons 2 '())) or (list 1 2) is immaterial. the resulting structure in memory is the same.
There is an infinity of ways to represent data. You have been presented a way. Here is other way:
(define mk/data
(lambda (a b)
(lambda (?)
(cond ((eq? ? 'repr) (list (list a b)))
((eq? ? 'first) a)
((eq? ? 'second) b)))))
(define data/test (mk/data '(1 2 3) '(8 9 10)))
(data/test 'repr)
(data/test 'first)
(data/test 'second)
This is another way how the big systems actually represent data.
I am trying to answer a scheme question, for a part of this question I have to make a list of lists:
(define (join a b (result '()))
(cons (list a b) result))
So I am taking in two characters, and placing them in a list, then I need to place each sublist into a list of lists, this function is being called recursively with two characters each time, so it is supposed to work like this:
join 1 4
=> ((1 4))
join 2 5
=> ((1 4) (2 5))
join 3 6
=> ((1 4) (2 5) (3 6))
However, I am getting ((3 6) (2 5) (1 4)), so the elements need to be reversed, I tried reversing my cons function to (cons result (list a b)) but then I get (((() 1 4) 2 5) 3 6), how can I get the list the right way around, or is there an easier way to do what I'm doing?
If you need to add elements at the end of a list use append; cons is for adding elements at the head. Try this:
(define (join a b (result '()))
(append result (list (list a b))))
Notice that append combines two lists, that's why we have to surround the new element inside its own list. Also, it's not a good idea to add elements at the end, using append is more expensive than using cons - if possible, rethink your algorithm to add elements at the head, and reverse the result at the end.
This can easily be done like this:
(define (group-by-2 lst)
(let loop ((lst lst) (rlst '()))
(if (or (null? lst) (null? (cdr lst)))
(rcons->cons rlst)
(loop (cdr lst)
(rcons (list (car lst)
(cadr lst))
rlst)))))
(group-by-2 '(1 2 3 4 5 6 7 8))
; ==> ((1 2) (2 3) (3 4) (4 5) (5 6) (6 7) (7 8))
Now rcons is like cons but it makes a reverse list. (rcons 1 (rcons 2 (rcons 3))) ; ==> {3 2 1} however it is not a list so you have to convert it to a list (rcons->list (rcons 1 (rcons 2 (rcons 3))) ; ==> (3 2 1)
The magic functions are really not that magical:
(define rcons cons)
(define rcons->cons reverse)
So in fact I didn't really have to make that abstraction, but hopefully I made my point. It doesn't matter how you organize the intermediate data structure in your programs so why not make the best for the job you are doing. For lists it's always best to iterate from beginning to end and make from end to beginning. Every insert O(1) per element and you do a O(n) reverse in the end. It beats doing append n times that would make it O(n²)
Can anybody tell how to insert an element in the list in different positions and return a list of those possible combination as lists using only recursion?
For example, list is (2 3) and element to insert is 1.
Output:
list(
list (1 2 3)
list (2 1 3)
list (2 3 1)
)
The first step is to determine what the output should look like, and in this case it should be a list of lists.
The second step is usually to break the problem down into cases of the input list.
The case of the empty list is pretty simple - the result is a list that contains one singleton list
(define (insert i ls)
(if (null? ls)
(list (list i))
(...)))
For the case of the non-empty list, it's helpful to examine the structure of the expected result.
(insert 1 '(2 3))
-->
((1 2 3) (2 1 3) (2 3 1))
Note that only the first element of the result has 1 as its first element, and we can easily create this with (cons 1 '(2 3)).
The other elements all have the first element of the input list as their first element, and if you look at their tails, (1 3) and (3 1), you'll see that they are the results of the recursion (insert 1 '(3)).
What's missing is that you need to cons the 2 onto each one of them afterwards.
Now we have all the necessary parts - in summary
(define (insert i ls)
(if (null? ls)
(list (list i))
(cons (cons i ls) (<...something...> (insert i (cdr ls))))))
Where I've left a "<...something...>" part for you to figure out.
Normally, we pass two arguments to cons, in RACKET
eg:
(cons 23 '(1 2 3))
which outputs '(23 1 2 3)
Is there any procedure to do the following
(procedure '(1 2 3) 23) => '(1 2 3 23)
Try this:
(append '(1 2 3) '(23))
=> '(1 2 3 23)
That's fine for appending a single element. If you're planning to repeatedly add many elements at the end, it's better if you cons everything at the head and then reverse the list when you're done. Why? because using append for building an output list will quickly degenerate into an O(n^2) solution (see: Schlemiel the Painter's algorithm)
In Lisp/Scheme/Racket if you want a procedure, writing it makes it largely indistinguishable from built in procedures:
#lang racket
(define (procedure a-list an-atom)
(cond
[(not (list? a-list)) (error "procedure: first argument not a list")]
[(pair? an-atom) (error "procedure: second argument is a list")]
[else
(append a-list (list an-atom))]))
Then use it:
> (procedure '(1 2 3) 23)
'(1 2 3 23)
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