Editing a stream - Racket - stream

Well, I am trying to get some things in racket, I am currently studying streams. I try to create a function that will edit a stream, for example add a pair of (int, element) in place of each stream's element.
For example initial_stream : <1,2,3, …>
edited_stream : <(int . 1) (int . 2) (int . 3) ….. >
I wrote this but it seems to enter an endless loop (with int=>13)
(define (stream-add-zero s)
(cons (cons 13 (car (s))) (stream-add-zero (cdr (s)))))
Thanks in advance.

If by "stream" you mean Racket's lazy stream data structure, this can be done with an application of stream-map.
(define initial-stream (in-naturals))
(define edited-stream (stream-map (λ (i) (cons 'int i)) initial-stream))
;; sanity check
(require rackunit)
(check-equal? (stream-ref edited-stream 3) '(int . 3))
This is assuming the int in your edited_stream was a symbol.

Related

Racket: Creating a stream using a macro instead of a function

I'm currently attempting to create a stream using a macro, as shown below:
(define-syntax create-stream
(syntax-rules (using starting at with increment )
[(create-stream name using f starting at i0 with increment delta)
(letrec
([name (lambda (f current delta)
(cons current (lambda () (name (f (+ current delta) delta)))))])
(lambda () (name f i0 delta)))
]))
What happens though is I get a compilation error later on when I try to pass it the following lambda function, which says "lambda: not an identifier, identifier with default, or keyword".
(create-stream squares using (lambda (x) (* x x)) starting at 5 with increment 2)
What I suspect is happening is that by attempting to use lambda in a macro, it's shadowing the actual lambda function in Racket. If this is true, I'm wondering in what way one can create a stream without using lambda, since as far as I can tell, there needs to be a function somewhere to create said stream.
Also this is a homework problem, so I do have to use a macro. My equivalent function for creating the stream would be:
(define create-stream
(letrec ([name (lambda (f current delta) (cons current (lambda () (name (f (+ current delta) delta)))))])
(lambda () (name f i0 delta))))
What I suspect is happening is that by attempting to use lambda in a macro, it's shadowing the actual lambda function in Racket
No, that's not correct.
The problem here is that you use f and delta in binding positions, in (lambda (f current delta) ...). That means after (create-stream squares using (lambda (x) (* x x)) starting at 5 with increment 2) is expanded, you will get code like:
(lambda ((lambda (x) (* x x)) current 2) ...)
which is obviously a syntax error.
You can see this yourself by using the macro stepper in DrRacket.
The fix is to rename the identifiers to something else. E.g.,
(define-syntax create-stream
(syntax-rules (using starting at with increment )
[(create-stream name using f starting at i0 with increment delta)
(letrec
([name (lambda (f* current delta*)
(cons current (lambda () (name (f* (+ current delta*) delta*)))))])
(lambda () (name f i0 delta)))
]))
This will make your code start running, but there are still other several bugs in your code. Since this is your homework, I'll leave them to you.
Your current problem essentially boils down to this (broken) code
(let ((x 0))
(define y x))
This is not equivalent to (define y 0) - y's definition is local to the let-binding.
The solution is to flip the definitions around and make the letrec local to the define:
(define name
(letrec (... fn definition ...)
(lambda () (fn i0))))

Varadic zip in Racket

I've seen the other answers on zipping functions in Racket but they are first of all not quite right (a zip should only zip up to the shortest sequence provided so that you can zip with infinite streams) and most importantly not varadic so you can only zip two streams at a time.
I have figured out this far
(define (zip a-sequence b-sequence) (for/stream ([a a-sequence]
[b b-sequence])
(list a b)))
which does work correctly
(stream->list (zip '(a b c) (in-naturals)))
=> '((a 0) (b 1) (c 2))
but is not varadic. I know I can define it to be varadic with define (zip . sequences) but I have no idea how to build the for/stream form if I do.
Does this have to be a macro to be doable?
Would this work for you?
#lang racket
(define (my-zip . xs)
(match xs
[(list x) (for/stream ([e x]) (list e))]
[(list x xs ...)
(for/stream ([e x] [e* (apply my-zip xs)])
(cons e e*))]))
(stream->list
(my-zip (in-naturals) '(a b c) '(1 2 3 4 5 6)))
;;=> '((0 a 1) (1 b 2) (2 c 3))
A common implementation of zip is:
(require data/collection) ; for a `map` function that works with streams
(define (zip . xs)
(apply map list xs))
... and if you prefer the point-free style, this can be simply:
(require racket/function)
(define zip (curry map list))
These do have the limitation that they require all input sequences to have the same length (including infinite), but since they are computed lazily, they would work in any case until one of the sequences runs out, at which point an error would be raised.
(zip (cycle '(a b c))
(naturals)
(cycle '(1 2 3))) ; => '((a 0 1) (b 1 2) (c 2 3) (a 3 1) ...
[Answer updated to reflect comments]

delete! function for R5RS

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.

Why use this style of lambda in Racket?

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?

Scheme streams with Taylor series

I've been doing some homework, wrote some code and can't actually find the reason why it doesn't work. The main idea of this part of the work is to make a stream that will give me elements of Taylor series of cosine function for a given X (angle i guess). anyways here is my code, I'd be happy if some one could point me to the reasons it doesn't work :)
(define (force exp) exp)
(define (s-car s) (car s))
(define (s-cdr s) (force (cdr s)))
; returns n elements of stream s as a list
(define (stream->list s n)
(if (= n 0)
'()
(cons (s-car s) (stream->list (s-cdr s) (- n 1)))))
; returns the n-th element of stream s
(define stream-ref (lambda (s n)
(if (= n 1)
(s-car s)
(stream-ref (s-cdr s) (- n 1)))))
; well, the name kinda gives it away :) make factorial n!
(define (factorial x)
(cond ((= x 0) 1)
((= x 1) 1)
(else (* x (factorial (- x 1))))))
; this function is actually the equation for the
; n-th element of Taylor series of cosine
(define (tylorElementCosine x)
(lambda (n)
(* (/ (expt -1 n) (factorial (* 2 n))) (expt x (* 2 n)))))
; here i try to make a stream of those Taylor series elements of cosine
(define (cosineStream x)
(define (iter n)
(cons ((tylorElementCosine x) n)
(lambda() ((tylorElementCosine x) (+ n 1)))))
(iter 0))
; this definition should bind cosine
; to the stream of taylor series for cosine 10
(define cosine (cosineStream 10))
(stream->list cosine 10)
; this should printi on screen the list of first 10 elements of the series
However, this doesn't work, and I don't know why.
I'm using Dr.Scheme 4.2.5 with the language set to "Essentials of Programming Languages 3rd ed".
Since I was feeling nice (and nostalgic about scheme) I actually waded through your code to finde the mistakes. From what I can see there are 2 problems which keeps the code from running as it should:
If I understand your code correctly (force exp) should evaluate exp, however you directly return it (unevaluated). So it probably should be defined as (define (force exp) (exp))
The second problem is in your lambda: (lambda() ((tylorElementCosine x) (+ n 1)) ) will evaluate to the next element of the taylor series, while it should evaluate to a stream. You probably want something like this: (lambda() (iter (+ n 1)) )
I haven't checked if the output is correct, but with those modifications it does at least run. So if there are any more problems with the code the should be in the formula used.
However I'd suggest that next time you want help with your homework you at least tell us where exactly the problem manifests and what you tried already (the community does frown on "here is some code, please fix it for me" kind of questions).

Resources