Why does this expression evaluate to 4 (call/cc) - scheme

Sorry this simple continuation example evaluates to 4, but I could not figure out why:
(call/cc
(lambda (k)
(* 5 (k 4))))
Chez Scheme 9.5.3

call/cc lets you get the advantages of continuation passing style without having to write it in continuation passing style. eg.
(define (cars lsts)
(define (cars lsts k)
(cond ((null? lsts) (k '()))
((null? (car lsts)) '())
(else (cars (cdr lsts)
(lambda (r)
(k (cons (caar lsts) r)))))))
(cars lsts values))
;; eg
(cars '()) ; ==> ()
(cars '((1) (2) (3))) ; ==> (1 2 3)
(cars '((1) (2) ())) ; ==> ()
Can be written like this:
(define (cars lsts)
(call/cc
(lambda (bail)
(define (cars lsts)
(cond ((null? lsts) '())
((null? (car lsts)) (bail '()))
(else (cons (caar lsts) (cars (cdr lsts))))))
(cars lsts))))
call/cc& looks like this in CPS:
(define (call/cc& proc k)
(define (exit& v ignored-k)
(k v))
(proc exit& k))
And your simple example can easily be rewritten to continuation passing style:
(call/cc& (lambda (k& real-k)
(k& 4 (lambda (res)
(*& 5 res real-k))))
display)
So looking at that the ignore-k gets ignored and 4 gets passed to the continuation of call/cc& which I have put display which then displays 4 in the repl.

I would explain you by writing a code with the same semantics by using CPS.
((lambda (k)
(k 4
(lambda (v)
(* 5 v))))
(lambda (result stack)
;; this continuation will drop the stack
result))
After you call the continuation K, you also call it using the remained stack, but the stack is dropped.
Had you took into account the remaining stack you would have had:
((lambda (k)
(k 4
(lambda (v)
(* 5 v))))
(lambda (result stack)
;; this continuation will consider the stacked computation
(stack result)))
and in this case the result would have been 20.
But in the semantics from your code, by calling the continuation, you dropped the stack, the not-finished computation.

The continuation will return with the value passed to it (k 4), so 4 is the return value.

Related

Scheme insertion sort without using primitive functions (car, cdr, cons)

I'm trying to write function for insertion sort with and without primitive functions.
My code with primitive functions is below.
(define (insert n d)
(cond ((null? n) d)
((null? d) n)
(else (< (car n) (car d)) (cons (car n) (insert (cdr n) d)) (cons (car d) (insert (cdr d) n)))))
(define (sort n)
(cond ((null? n) '())
(else (insert (list (car n)) (sort (cdr n))))))
How should I revise insert and sort to not use car, cdr, and cons?
Edit: I tried to write the insert function. This is what I have so far.
(define (insert n d)
(let ((rest-digit (truncate (/ n 10))))
(if (null? n) 0
(+ rest-digit (insert (- n 1) d)))))
(insert '(3 2 1) '5)
Edit #2: I think I can use the built-in function expt.
Ultimately you will be using primitive functions. To illustrate let me show you a trick that actually uses cons, car, and cdr under the hood:
(define (my-car lst)
(apply (lambda (a . d) a) lst))
(define (my-cdr lst)
(apply (lambda (a . d) d) lst))
(define (my-cons a d)
(apply (lambda l l) a d))
(define test (my-cons 1 '(2 3)))
test ; ==> (1 2 3)
(my-car test) ; ==> 1
(my-cdr test) ; ==> (2 3)
This abuses the fact that apply takes a list as the final arguments and that rest arguments are cons-ed onto a list in order. cons doesn't work for all pairs:
(my-cons 1 2) ; ERROR: expected list?, got 1
You can make cons, car, and cdr such that they adher to the same rules as primitive cons, but that they are not made of pairs at all. Barmar suggested closures:
(define (ccons a d)
(lambda (f) (f a d))
(define (ccar cc)
(cc (lambda (a d) a)))
(define (ccdr cc)
(cc (lambda (a d) d)))
(define test2 (ccons 1 2))
test2 ; ==> #<function...>
(ccar test2) ; ==> 1
(ccdr test2) ; ==> 2
This works since a and d gets closed over in the returned function and that function passes those values and thus the function acts as an object with two attributes. The challenge with this is that you cannot just pass a list since only "lists" made with ccons will work with ccar and ccdr.
A less classical way is to use vectors:
(define vtag (make-vector 0))
(define (vcons a d)
(let ((v (make-vector 3)))
(vector-set! v 0 vtag)
(vector-set! v 1 a)
(vector-set! v 2 d)
v))
(define (vcar vl)
(vector-ref vl 1))
(define (vcdr vl)
(vector-ref vl 2))
(define (vpair? vl)
(eq? vtag (vector-ref vl 0)))
Or you can use records:
(define-record-type :rpair
(rcons a d)
rpair?
(a rcar)
(d rcdr))
(define test (rcons 1 2))
(rpair? test) ; ==> #t
(rcar test) ; ==> 1
(rcdr test) ; ==> 2
Now I think records just syntax sugar and abstractions and that under the hood you are doing exactly the same as the vector version with less code, but that isn't a bad thing.
EDIT
So from the comments if the only restriction is to avoid car, cdr, and cons, but no restrictions on their sisters we might as well implement with them:
(define (sort lst)
(define (insert e lst)
(if (null? lst)
(list e)
(let ((a (first lst)))
(if (>= a e)
(list* e lst)
(list* a (insert e (rest lst)))))))
(foldl insert
'()
lst))
(sort '(1 5 3 8 5 0 2))
; ==> (0 1 2 3 5 5 8)
And of course my first suggestion works in its place:
(define (sort lst)
(define (my-car lst)
(apply (lambda (a . d) a) lst))
(define (my-cdr lst)
(apply (lambda (a . d) d) lst))
(define (my-cons a d)
(apply (lambda l l) a d))
(define (insert e lst)
(if (null? lst)
(my-cons e '())
(let ((a (my-car lst)))
(if (>= a e)
(my-cons e lst)
(my-cons a (insert e (my-cdr lst)))))))
(foldl insert
'()
lst))
And of course, using substitution rules you can make it utterly ridiculous:
(define (sort lst)
;; insert element e into lst in order
(define (insert e lst)
(if (null? lst)
((lambda l l) e)
(let ((a (apply (lambda (a . d) a) lst)))
(if (>= a e)
(apply (lambda l l) e lst)
(apply (lambda l l)
a
(insert e (apply (lambda (a . d) d) lst)))))))
;; main loop of sort
;; insert every element into acc
(let loop ((lst lst) (acc '()))
(if (null? lst)
acc
(loop (apply (lambda (a . d) d) lst)
(insert (apply (lambda (a . d) a) lst)
acc)))))

Terminate program early and return list

I have a recursive code and need to terminate it when condition is fullfilled. I am capable of display the list when the condition, but then there are another calls on stack that I don't need to process that doesn't let me to return the list.
A variation of Sylwester's solution:
(define (example n)
(call-with-current-continuation
(lambda (return)
(let loop ([n 0])
(if (= n 5) ; done
(return 'the-result)
(loop (+ n 1)))))))
(example 10)
Using the continuation in this way allows one to use an escape continuation instead of a full continuation with call/ec (if your implementation has escape continuations).
The best way to do it is by using an accumulator. Aborting is then just not recursing.
(define (copy-unless-contains-5 lst)
(define (helper lst acc)
(cond
((null? lst) (reverse acc))
((equal? (car lst) 5) #f)
(else (helper (cdr lst) (cons (car lst) acc)))))
(helper lst '()))
If you are recursing with a continuation and that is the optimum way of doing it, then call-with-current-continuation can give you a way to abort waiting continuations and choose what to return.
(define (copy-unless-contains-5 lst)
(call-with-current-continuation
(lambda (abort)
(define (helper lst)
(cond
((null? lst) '())
((equal? (car lst) 5) (abort #f))
(else (cons (car lst) (helper (cdr lst))))))
(helper lst))))
Needless to say this last version is overly complicated. Both work the same:
(copy-unless-contains-5 '(1 2 3 4)) ; ==> (1 2 3 4)
(copy-unless-contains-5 '(1 2 5 3 4)) ; ==> #f

scheme- writing a foldl /fold-left like function that works on first 3 items of the given list

I would like to write a function that gets and infix expression and changes it to prefix.
at first let's assume we only deal with + operator, so I want to change the expression 1+1+1 into: (+ (+ 1 1) 1)
I want to do it using foldl or foldl-like matter:
taking the second item in the list (which is always the operand) appending it with the first and the third (in that order) then I would like the expression we've just appended to become the first item in the list so I would do the same on the rest of the list recursively.
Iv'e tried the following:
(lambda (lst)
(fold-left (lambda (pmLst)
`(,((cadr pmLst) ,(car pmLst) (caddr pmLst)) ,(cddr pmLst)))
'()
lst))
but then I realized that the lambda given to the fold-left has to have 2 arguments but I would like to deal with the first 3 items of the list.
I hope I've made myself clear cause it got a bit tricky..
A fold wont do what you want. If you imagine the expression (5 + 3 + 2) then using a fold with proc as the procedure do this:
(proc 2 (proc '+ (proc 3 (proc '+ (proc 5 '())))))
A way would be to make a function that returns the odd and even elements in their own list so that '(+ 2 - 3) becomes (+ -) and (2 3) and then you could do it like this:
(define (infix->prefix expr)
(if (pair? expr)
(let-values ([(ops args) (split (cdr expr))])
(fold (lambda (op arg acc)
(list op acc (infix->prefix arg)))
(car expr)
ops
args))
expr))
However the size of both is much greater than just rolling your own recursion:
(define (infix->prefix expr)
(define (aux lst acc)
(if (pair? lst)
(aux (cddr lst)
(list (car lst)
acc
(infix->prefix (cadr lst))))
acc))
(if (pair? expr)
(aux (cdr expr) (infix->prefix (car expr)))
expr))
(infix->prefix '(1 + 2 - 3))
; ==> (- (+ 1 2) 3)
There is no operator precedence here. Everything is strictly left to right.

how to call to this map function

I saw a code on a book about how to create a map function in Scheme, the code is the following:
(define map (lambda (f L)
(if null? L '()
(cons (f (car L)) (map f (cdr L))))))
(define square (lambda (x)
(* x x)))
(define square-list (lambda (L)
(map square L)))
Supposedly I can call it with:
(map square-list '(1 2 3 4))
but it is throwing me the following error:
SchemeError: too many operands in form: (null? L (quote ()) (cons (f (car L)) (map f (cdr L))))
Current Eval Stack:
-------------------------
0: (map square-list (quote (1 2 3 4)))
How should I call this function?
You have two errors. First, you forgot to surround the null? check with parentheses (and notice a better way to indent your code):
(define map
(lambda (f L)
(if (null? L)
'()
(cons (f (car L))
(map f (cdr L))))))
Second, you're expected to call the procedure like this:
(square-list '(1 2 3 4 5))
=> '(1 4 9 16 25)
You're missing parens around null? L, i.e. your condition should probably look like
(if (null? L) '()
(cons ...))

Scheme: How to merge two streams

I have got these functions
(define force!
(lambda (thunk)
(thunk)))
(define stream-head
(lambda (s n)
(if (zero? n)
'()
(cons (car s)
(stream-head (force! (cdr s))
(1- n))))))
(define make-stream
(lambda (seed next)
(letrec ([produce (lambda (current)
(cons current
(lambda ()
(produce (next current)))))])
(produce seed))))
(define make-traced-stream
(lambda (seed next)
(letrec ([produce (trace-lambda produce (current)
(cons current
(lambda ()
(produce (next current)))))])
(produce seed))))
(define stream-of-even-natural-numbers
(make-traced-stream 0
(lambda (n)
(+ n 2))))
(define stream-of-odd-natural-numbers
(make-traced-stream 1
(lambda (n)
(+ n 2))))
And I need to make a function that merges the last two, so that if I run
(stream-head (merge-streams stream-of-even-natural-numbers stream-of-odd-natural-numbers) 10)
I must get the output (0 1 2 3 4 5 6 7 8 9).. how is this done?
The best idea I had, which is wrong, have been:
(define merge-streams
(lambda (x y)
(cons (car x)
(merge-streams y (cdr x)))))
Here is a suggestion:
(define (merge-streams s1 s2)
(cond
[(empty-stream? s1) s2)] ; nothing to merge from s1
[(empty-stream? s2) s1)] ; nothing to merge from s2
[else (let ([h1 (stream-car s1)]
[h2 (stream-car s2)])
(cons h1
(lambda ()
(cons h2
(stream-merge (stream-rest s1)
(stream-rest s2))))))]))
It uses some helper functions that must be defined first.

Resources