scheme - can someone explain this output to me? - linked-list

With these defined functions:
(define (foldr op z ls)
(if (null? ls)
z
(op (car ls) (foldr op z (cdr ls)))))
(define (snoc x y) (cons y x))
and when i run this:
(foldr snoc '() (list 1 2 3))
I get this output:
=> (((() . 3) . 2) . 1)
What does this output mean? Can someone please explain it to me in detail?
I need to Draw this answer in terms of box and pointer notation in scheme.

Racket prints cons cells as "dotted pairs" if their cdr isn't a list.
Examples from DrRacket:
> (list 1 2)
'(1 2)
> '(1 . (2 . ()))
'(1 2)
> '(1 . 2)
'(1 . 2)
> (cons 1 2)
'(1 . 2)
> (cons 1 '())
'(1)
> (cons '() 1)
'(() . 1)
(foldr op z ls) takes ls and replaces nil with z and cons with op.
That is, if ls is (cons a (cons b (cons c nil))), then (foldr op z ls) is
(op a (op b (op c z)))
In your example, (foldr snoc '() (list 1 2 3)) is
(snoc 1 (snoc 2 (snoc 3 '())))
Working your way outwards from the innermost snoc,
(snoc 1 (snoc 2 (cons '() 3)))
(snoc 1 (cons (cons '() 3) 2))
(cons (cons (cons '() 3) 2) 1)
which prints (in DrRacket) as dotted pairs
'(((() . 3) . 2) . 1)
(Drawing a diagram left as an exercise.)

Related

SICP 3.52 delayed cdr

Exercise 3.52,
(define sum 0)
(define (accum x)
(set! sum (+ x sum))
sum)
;1: (define seq (stream-map accum (stream-enumerate-interval 1 20)))
;2: (define y (stream-filter even? seq))
;3: (define z (stream-filter (lambda (x) (= (remainder x 5) 0))
; seq))
;4: (stream-ref y 7)
;5: (display-stream z)
Step 1:
;1: ==> (cons-stream 1 (stream-map proc (stream-cdr s)) (Assume stream-cdr is evaluated only when we force the cdr of this stream)
sum is now 1
Step 2:
1 is not even, hence (also memoized so not added again), it calls (stream-filter pred (stream-cdr stream)).
This leads to
evaluation of cdr hence materializing 2 which is even, hence it should call: (cons-stream 2 (stream-cdr stream)).
According to this answer should be 1+2 = 3 , but it is 6
Can someone help with why the cdr's car is materialized before the current cdr is called?
Using Daniel P. Friedman's memoizing tail
#lang r5rs
(define-syntax cons-stream
(syntax-rules ()
((_ h t) (cons h (lambda () t)))))
(define (stream-cdr s)
(if (and (not (pair? (cdr s)))
(not (null? (cdr s))))
(set-cdr! s ((cdr s))))
(cdr s))
we observe:
> sum
0
> (define seq (stream-map accum (stream-enumerate-interval 1 20)))
> sum
1
> seq
(mcons 1 #<procedure:friedmans-tail.rkt:21:26>)
> (define y (stream-filter even? seq))
> sum
6
> seq
(mcons
1
(mcons
3
(mcons 6 #<procedure:friedmans-tail.rkt:21:26>)))
> y
(mcons 6 #<procedure:friedmans-tail.rkt:21:26>)
>
stream-filter? needs to get to the first element of the stream it is constructing in order to construct it. A stream has its head element already forced, calculated, so it must be already present.
In the list of accumulated sums of the enumerated interval from 1 to 20, the first even number is 6:
1 = 1
1+2 = 3
1+2+3 = 6
...

Parsing concrete syntax in Scheme

I wrote a procedure that gets a valid prefix list for subtraction (e.g, "(- 6 5)" for what we know as "6-5"). Here is my code:
(define parse-diff-list
(lambda (datum)
(cond
((number? datum) (const-exp datum)) ;; if datum is a number, return const-exp
((pair? datum) ;; if datum is a pair:
(let ((sym (car datum))) ;; let sym be the first of the pair
(cond
((eqv? sym '-) ;; if sym is minus:
(let ((lst1 (parse-diff-list (cdr datum)))) ;; parse second element of subtraction
(let ((lst2 (parse-diff-list (cdr lst1)))) ;; parse first element of subtraction
(cons (diff-exp (car lst1) (car lst2)) (cdr lst2))))) ;; "perform" the subtraction
((number? sym) ;; if sym is number:
(cons (const-exp sym) (cdr datum))) ;; return const-exp with the remainder of the list, yet to be processed
(else (eopl:error 'parse-diff-list "bad prefix-expression, expected - ~s" sym)))))
(eopl:error 'parse-diff-list "bad prefix-expression ~s" datum))))
(define parse-prefix
(lambda (lst)
(car (parse-diff-list lst))))
It works fine logically, but I don't understand the logic of the indentation in printing. For the input:
(parse-prefix '(- - 1 2 - 3 - 4 5))
It prints:
#(struct:diff-exp
#(struct:diff-exp #(struct:const-exp 1) #(struct:const-exp 2))
#(struct:diff-exp #(struct:const-exp 3) #(struct:diff-exp #(struct:const-exp 4) #(struct:const-exp 5)))
While I would want the following print style:
#(struct:diff-exp
#(struct:diff-exp
#(struct:const-exp 1)
#(struct:const-exp 2))
#(struct:diff-exp
#(struct:const-exp 3)
#(struct:diff-exp
#(struct:const-exp 4)
#(struct:const-exp 5)))
It's more than a petty question for me, as it does create indentations but I don't know how it does it.
Thanks a lot!
Take a look at racket/pretty the pretty printing library.
In particular note the parameter (pretty-print-columns) which
you can set like this:
`(pretty-print-columns 40)`
in order to avoid long lines.
http://docs.racket-lang.org/reference/pretty-print.html
(I am guessing you are using DrRacket based on the way the structures are printing)

Write a stream of sexy prime pairs in SCHEME

I have a SCHEME function is-sexy? which takes one parameter, n, and returns true if n is part of a pair of sexy primes and false otherwise, and a SCHEME function, sexy-primes, which takes an integer, n, as a parameter and returns a list of pairs of prime numbers whose difference is 6 and whose smaller number is less than or equal to n.
How do I define a stream of sexy prime pairs?
(define (is-sexy? n)
(define (is-prime? x)
(define (is-prime?-aux x k)
(cond ((< x 1) #f)
((= x k) #t)
(else
(if (= (remainder x k) 0) #f
(is-prime?-aux x (+ k 1))))))
(cond ((= x 1) #t)
((= x 2) #t)
(else (is-prime?-aux x 2))))
(if (and (is-prime? n)
(or (is-prime? (- n 6)) (is-prime? (+ n 6)))) #t
#f))
(define (sexy-primes n)
(if (= n 0) '()
(if (is-sexy? n) (cons n (sexy-primes (- n 1)))
(sexy-primes (- n 1)))))
This works:
(define (sexyprimes-from k)
(if (is-sexy? k) (cons (cons k (+ k 6)) (delay (sexyprimes-from (+ k 1))))
(sexyprimes-from (+ k 1))))
(define sexy-primes (sexyprimes-from 5))

Alternate two values

I have the code
(define alternate
(letrec ([f (lambda (x) (cons x (lambda () (f (+ x 1)))))])
(lambda () (f 1))))
The result is 1,2,3..
How i could change it to take 1,2,1,2,1,2..
I tried cons inside the f but didn't work.
Any ideas?
You might also find generators useful: docs
Welcome to DrRacket, version 5.3.3.5 [3m].
Language: racket [custom].
> (require racket/generator)
> (define g (generator () (let LOOP () (yield 1) (yield 2) (LOOP))))
> (g)
1
> (g)
2
> (g)
1
> (g)
2
UPDATE:
Even better, use an infinite-generator:
Welcome to DrRacket, version 5.3.3.5 [3m].
Language: racket [custom].
> (require racket/generator)
> (define g (infinite-generator (yield 1) (yield 2)))
> (g)
1
> (g)
2
> (g)
1
> (g)
2
This is straightforward to implement using streams:
(define (alternate)
(stream-map (lambda (x)
(if (even? x) 1 2))
(in-naturals)))
The trick here is that a stream is built using stream-cons, which basically does what you're implementing by hand: it creates a list where its elements are "promises" that get evaluated only when needed.
stream-cons produces a lazy stream for which stream-first forces the evaluation of first-expr to produce the first element of the stream, and stream-rest forces the evaluation of rest-expr to produce a stream for the rest of the returned stream.
This shows how alternate returns an infinite stream of elements of the form 1 2 1 2 1 2 ...
(define alt (alternate))
(stream-ref alt 0)
=> 1
(stream-ref alt 1)
=> 2
(stream-ref alt 2)
=> 1
(stream-ref alt 3)
=> 2
Alternatively, if you need a list of n elements of the sequence use this procedure, which by the way should be part of Racket in the first place:
(define (stream-take s n)
(if (zero? n)
'()
(cons (stream-first s)
(stream-take (stream-rest s) (sub1 n)))))
Now it works as expected:
(define alt (alternate))
(stream-take alt 0)
=> '()
(stream-take alt 1)
=> '(1)
(stream-take alt 2)
=> '(1 2)
(stream-take alt 3)
=> '(1 2 1)
Here's a way to do it as a small modification of your existing code:
(define alternate
(letrec ([f (lambda (x) (cons x (lambda () (f (if (= x 1) 2 1)))))])
(lambda () (f 1))))

Recursion in a stream

I have the code
(define (add-ten s)
(let ([f (lambda(s) ((cons 10 (car (s))) (cdr (s))))])
(f s)))
s could be a stream like powers
(define powers (letrec ([f (lambda (x) (cons x (lambda () (f (* x 2)))))])
(lambda () (f 2))))
My function
(result-for-n-times powers 5)
gives '(2 4 8 16 32).
Now, i want to define a stream (add-ten) that can take the stream powers and gives another stream.So, if i call it
(result-for-n-times (add-ten powers) 5)
would give '((10. 2) (10. 4) (10. 8) (10. 16) (10. 32)).
Try this:
(define powers
(letrec ([f (lambda (x)
(cons x
(lambda () (f (* x 2)))))])
(f 2)))
(define (result-for-n-times s n)
(if (zero? n)
'()
(cons (car s)
(result-for-n-times ((cdr s)) (sub1 n)))))
(define (add-ten s)
(letrec ([f (lambda (x)
(cons (cons 10 (car x))
(lambda () (f ((cdr x))))))])
(f s)))
Notice that the add-ten procedure receives a stream as a parameter, but also it must return a stream. So letrec must be used for defining a procedure that conses each element taken from the original stream, with a promise that keeps on building the stream.
Also notice that you're not actually calling the procedure that defines powers, you either call it at the end of powers' definition or you call it like this: (powers) before passing it to add-ten. Fixing this, it works as expected:
(result-for-n-times (add-ten powers) 5)
=> '((10 . 2) (10 . 4) (10 . 8) (10 . 16) (10 . 32))

Resources