I am doing exercise 3.13 from SICP but I am unsure of my answer.
Exercise 3.13: Consider the following make-cycle procedure, which uses
the last-pair procedure defined in Exercise 3.12:
(define (make-cycle x) (set-cdr! (last-pair x) x) x)
Draw a box-and-pointer diagram that shows the structure z created by
(define z (make-cycle (list 'a 'b 'c)))
What happens if we try to compute (last-pair z)?
I'm trying to understand why
(last-pair z)
becomes an infinite loop. Ignoring the box-and-pointer diagram, here is how I understand it:
(set-cdr! (last-pair x) x)
(last-pair x) would be the pair (cons 'c '()), then when we do set-cdr! the pair would become:
(cons 'c (cons 'a (cons 'b (cons 'c (cons 'a (cons 'b (cons 'c (cons 'a (cons 'b (cons 'c ...))))))))))
is my understanding correct?
No.
Your answer appears to indicate that (last-pair x) is the result of calling cons infinitely many times.
Not so.
x is still just 3 cons cells, but the last one points to the first one, creating a loop (a snake biting itself on the tail).
Related
I am trying to follow along this Racket tutorial:
https://cs.uwaterloo.ca/~plragde/flaneries/TYR/Pure_Functional_Programming.html
and it describes these alternatives to the actual implementations. I know what cons, first and rest do, and I understand how lambda functions work, but I cannot figure out how these successfully implement cons, first and rest.
(define (cons f r) (lambda (b) (if b f r)))
(define (first lst) (lst true))
(define (rest lst) (lst false))
Maybe I have misinterpretted what they are supposed to be. Here is what the tutorial says:
As another example of the use of closures, consider the following "alternative" implementation of the basic list primitives.
Could someone clarify?
#lang racket
(define (cons f r) (lambda (b) (if b f r)))
Here cons has been redefined to be a procedure which takes two arguments f and r, and returns a procedure which takes one argument b. Let's try it:
cons-func.rkt> (define a-cons (cons 1 2))
Now we have called the cons procedure with the values 1 and 2; cons has returned a procedure which we have named a-cons.
cons-func.rkt> a-cons
#<procedure:...ratch/cons-func.rkt:3:19>
Now, a-cons is a procedure that takes a single argument; if that argument is true, then the first of two values passed in the earlier call to cons is returned; if instead the argument to a-cons is false, then the second of the two earlier arguments is returned:
cons-func.rkt> (a-cons true)
1
cons-func.rkt> (a-cons false)
2
There are two values stored in the closure returned by our new cons, and both of them can be retrieved. This is effectively a cons cell. Let's add some sugar to make this nicer to use. Here first and rest just do what we did by hand a moment ago:
(define (first lst) (lst true))
(define (rest lst) (lst false))
Now we can access the two parts of our cons cell in the usual way:
cons-func.rkt> (first a-cons)
1
cons-func.rkt> (rest a-cons)
2
This new implementation of cons cells is not compatible with the old one. For example, we have not redefined car and cdr, and the normal implementation of those procedures will not work with our new cons cells:
cons-func.rkt> (car a-cons)
; car: contract violation
; expected: pair?
; given: #<procedure:...ratch/cons-func.rkt:3:19>
We can use our new cons cells to define list:
(define (list . xs)
(if (null? xs)
'()
(cons (car xs)
(apply list (cdr xs)))))
Here we are cheating a bit, using the dot syntax to capture an arbitrary number of arguments in a list (the regular kind). We use car and cdr to take this list apart (because they work with regular lists), and reassemble it with the new cons into a closure-based list.
cons-func.rkt> (define a-list (list 'a 'b 'c))
cons-func.rkt> a-list
#<procedure:...ratch/cons-func.rkt:3:19>
Here you can see that the list created by our new list procedure, named a-list, is itself a procedure. We can call our first and rest procedures on a-list:
cons-func.rkt> (first a-list)
'a
cons-func.rkt> (rest a-list)
#<procedure:...ratch/cons-func.rkt:3:19>
cons-func.rkt> (first (rest a-list))
'b
cons-func.rkt> (first (rest (rest a-list)))
'c
cons-func.rkt> (rest (rest (rest a-list)))
'()
So, it seems that our closure-based cons cells behave as regular cons cells, though the underlying implementation is not compatible with Rackets own cons and list accessor procedures, and we can use these closure-based cons cells to create closure-based lists. If someone had the time and inclination, they could probably implement a whole Scheme around these closure-based cons cells.
Defining a data structure is a process of 2 steps.
defining the axioms of the data structure, i.e. the abstract data structure
defining the implementation which must obey the axioms.
Whatever implementation you create is correct as time as the axioms are true in that implementation.
The axioms for the lisp constructor differ from implementation to implementation. In scheme they are so
(CAR (CONS x y)) = x
(CDR (CONS x y)) = y
Each implementation that creates the functions CONS, CAR, CDR that obey this is correct and can be used as implementation for cons cells contructor.
The things are not so direct however, as the axioms of CONS can interact with other axioms of the system. For example, some systems impose the axiom:
(EQ (CONS x y) (CONS X Y))
and in this case you need to take care in the implementation such that cons to check if there is already a (X . Y) pair allocated, and not duplicate the memory.
The other answers detail the implementation of cons with functions.
Explanation through the substitution method:
The results you want are
(first (cons a b))
—> a
and
(rest (cons a b))
—> b
These are all the requirements for the three primitives.
Now consider (cons x y): replace f and r in the definition of cons with x and y – that is,
(cons x y)
—> (lambda (b) (if b x y))
Now, (first (cons x y)) is
(first (lambda (b) (if b x y)))
—> ((lambda (b) (if b x y)) true)
—> (if true x y)
—> x
and (rest (cons x y)) is
(first (lambda (b) (if b x y)))
—> ((lambda (b) (if b x y)) false)
—> (if false x y)
—> y
i would like to make an infinite stream (x, f(x), f(f(x),f(f(f(x))),...) and the procedure should take x as an value and f as an procedure. I tried the following code but i don't know if it is true... how can i improve my code?
(define (f_stream x f) (cons-stream x (f_stream (f x) (lambda (x)
(sin x)) (f x)))) (sin x)) (f x))))
(define (f x) (sin x))
What did you is close, but you put extra stuff about 'sin' into it while it should be generic. All you needed was this:
(define (f_stream x f) (cons-stream x (f_stream (f x) f)))
notice f is passed as a function instead of using lambda.
I'm trying to write a delete! function that mutates a list and removes from it a specified value. This is the code I have so far.
(define (extend! l . xs)
(if (null? (cdr l))
(set-cdr! l xs)
(apply extend! (cdr l) xs)))
(define (delete! lis y)
(define returnLis '())
(for-each (lambda(x) (if(not(eq? x y))
(extend! returnLis x))) lis)
returnLis)
The problem I am having is that I am trying to add to an empty list which can't be done in Scheme.
Desired outcome:
(delete! '(1 2 3 4 5) 3)
=> (1 2 4 5)
Your extend function use actually would make a copy of each element in a fresh pair, but since the initial value is '() it cannot be set-cdr!. The whole point of mutating something is that old variables will continue point to the changed data and making a copy won't do that.
You need to see the pairs. You want to remove 3
[1,-]->[2,-]->[3,-]->[4,-]->[5,-]->()
So When you have found 3, you need to change the cdr of the pair that holds 2 and pint it the pair that holds 3s cdr like this:
[1,-]->[2,-]->[4,-]->[5,-]->()
Something like this then:
(define (delete lst e)
(if (and (not (null? lst)) (not (null? (cdr lst))))
(if (equal? (cadr lst) e)
(set-cdr! lst (cddr lst))
(delete (cdr lst) e))
'undefined))
(define test (list 1 2 3 4 5))
(delete lst 3)
lst ; ==> (1 2 4 5)
Notice I'm using list since a quoted literal cannot be used here since you are not allowed to change constant data like '(1 2 3 4 5). The result will be undefined or it will signal an error.
It won't work if the element in question is the first. It's because the variable points to the first pair and this only changes the pointers in pairs, not bindings. One could just switch the two first and delete the second, but in the event you have a one element list you are still stuck. Scheme implementations of mutable queues usually have a head consisting of a dummy element not considered part of the list to delete the first element.
All you need is a head-sentinel technique:
(define (delete! lis y)
(define returnLis (list 1))
(for-each (lambda(x) (if(not(eq? x y))
(extend! returnLis x))) lis)
(cdr returnLis))
Well, not all... because as it is, this is a quadratic algorithm. It re-searches the returnLis from top anew while adding each new element with extend!. Better just maintain the last cdr cell and update it:
(define (delete! lis y)
(define returnLis (list 1))
(define last-cell returnLis)
(for-each (lambda(x) (cond ((not(eq? x y))
; (extend! last-cell x)
(set-cdr! last-cell (list x))
(set! last-cell (cdr last-cell)))))
lis)
(cdr returnLis))
But, as #Sylwester points out, with this approach you shouldn't use an exclamation mark in the name, as this will return a freshly built list instead of mutating the argument's structure.
I am brushing up on my low Racket knowledge and came across this streams in racket excellent post. My question is about this snip:
(define powers-of-two
(letrec ([f (lambda (x) (cons x (lambda () (f (* x 2)))))])
(lambda () (f 2))))
I understand the reason for the 'inner lambdas' but why did the OP use a lambda for the whole function? Couldn't it be done like this just as effectively?
(define (powers-of-two)
(letrec ([f (lambda (x) (cons x (lambda () (f (* x 2)))))])
(f 2)))
I experimented and see no difference. My question is whether this is just a matter of style, or if there is some reason that the former is preferable.
There is no difference. Since f in the second example doesn't close over anything, it can be lifted outside the powers-of-two function, which is equivalent to the first example.
One reason why the first might be preferable is that there is only ever one f function that needs to be created. With the second one, a new f function would be created every time someone called (powers-of-two).
I tried timing them both though, and neither was significantly faster than the other.
(define (name arg)
arg)
This is the short form of writing:
(define name
(lambda (arg)
arg))
So what happens with the first example is that the letrect happens right away and the function returned would be (lambda () (f 2)) with f in it's closure.
The second makes a procedure called powers-of-two that , when applied (powers-of-two) will return the same as the first powers-of-two is.. Think of it as a powers-of-two-generator.
Thus:
(define powers-of-two
(letrec ([f (lambda (x) (cons x (lambda () (f (* x 2)))))])
(lambda () (f 2))))
(define (powers-of-two-generator)
(letrec ([f (lambda (x) (cons x (lambda () (f (* x 2)))))])
(f 2)))
(powers-of-two) ; ==> (2 . procedure)
(define powers-of-two2 (powers-of-two-generator)) ; ==> procedure
(powers-of-two2) ; ==> (2 . procedure)
Do you see the difference?
(defun simplify (x)
(if (and (not (null x)) (listp x))
(if (and (equal '(car x) '(cadr x)) (equal '(car x) 'not))
(simplify (cddr x))
(cons (car x) (simplify (cdr x)))
)
'nil
)
)
This lisp function is meant to take an expression as an argument then remove superfluous 'not's from it and return it. It checks if the argument is a non-empty list and returns nil if it isn't (base case). If it is non-empty, I want to check if the car(x) = car(cdr(x)) = 'not'. If they aren't detected to be a pair of 'not's then it should recurse and build on a list to return. If they are detected to be both 'not' then it should still recurse but also skipping both car(x) and car(cdr(x)). Right now all this code does is return an expression identical to the argument so I assume the problem is that my condition in the nested if statement isn't being set off properly, how can I check if car(x) and cadr(x) are both 'not'?
"when you assume..."
Actually, the test is semi-ok (but you'll end up taking (car nil) if x is (not) ). The problem is the recursion. Try it on paper:
(simplify '(and (not (not y)) (or x (not (not z))))`
(car x) is not not.
so: (cons (car x) (simplify (cdr x))
Now x is '((not (not y)) (or x (not (not z))))So(car x)is(not (not y)), which is not equal tonot`. Recurse again
Now x is ((or x (not (not z)))and(car x)is(or x (not (not z)))`. But you probably get the picture.
Hint: (map simplify x) and fix your termination condition to return x if x is an atom.
(equal '(car x) '(cadr x)) is always false, because the list (car x) is different from the list (cadr x). If you want to get the car and cadr of some particular x, you need to not quote these expressions.