Remove duplicates in streams (Scheme) - stream

I'm trying to remove duplicates in my streams in scheme R5RS. Here's my code.
(define (remove-duplicates lst)
(cond ((stream-null?? lst) stream-null?)
((not (memq (stream-car lst) (stream-cdr lst)))
(cons-stream (stream-car lst) (remove-duplicates (stream-cdr lst))))
(else (remove-duplicates (stream-cdr lst)))))
(define (memq item x)
(cond ((stream-null?? x) #f)
((eq? item (stream-car x)) x)
(else (memq item (stream-cdr x)))))
I can't see why this doesn't work. Any solutions or help would be appreciated.

"Doesn't work" is a very vague problem description, but I'll try to answer anyway.
memq isn't lazy, and even if it were, you can't test for membership in infinite streams for relatively obvious reasons.
To keep the stream lazy, you can't decide whether an item should be included by looking "forwards", only "backwards" - the future is concealed to you and you can only base your decisions on the past.
You need to turn the problem around - instead of filtering out all instances except the last, you keep the first and filter out the rest, if any turn out to exist when you finally get there.
(In an endless stream, it's easy to remove something once you've found it, but it's impossible to discover that something isn't there.)
stream-filter is useful for filtering, and the result might look something like this:
(define (remove-duplicates lst)
(if (stream-null? lst)
stream-null
(stream-cons (stream-car lst)
(remove-duplicates
(stream-filter (lambda(x) (not (eq? x (stream-car lst))))
(stream-cdr lst))))))

Related

Delayed "let" in SICP

SICP indicates cdr is opened up:
In section 3.5.4 , i saw this block:
(define (integral delayed-integrand initial-value dt)
(define int
(cons-stream initial-value
(let ((integrand (force delayed-integrand)))
(add-streams (scale-stream integrand dt)
int))))
int)
Normally if this was something like:
(define (stream-map proc s)
(if (stream-null? s)
the-empty-stream
(cons-stream (proc (stream-car s))
(stream-map proc (stream-cdr s)))))
The stream-cdr s would be evaluated as (cons-stream (stream-car (cdr s)) delay<>) even when the actual call would be in a delay. ie even though the stream-map function itself is delayed, the arguments are pre-computed. [Is this correct? - By the applicative model, the arguments should be substituted for ,before the function is "called", but is the call evaluation when delay is forced or when it's just specified]
Then why is let not pre-computed?
What i think? I think let is a lambda function with the variable as the arguments, so it's execution is delayed
(let ((var1 e1) (var2 e2)) e3)
is same as
Lambda (var1 var2) e3 (with var1 bound to e1 and var2 bound to e2)
Can someone please help me confirm this? Thanks
In SICP type streams the car of a stream is not delayed, but the cdr is.
The whole expression,
(let ((integrand (force delayed-integrand)))
(add-streams (scale-stream integrand dt)
int))
, is delayed since it is the second argument to cons-stream. What kind of expression is delayed doesn't matter so you can have a call, evaluation of variable or even a let there.
"the arguments are pre-computed. is this correct?"
No. (cons-stream a (func (stream-cdr b))) is just like
(cons-stream a
(lambda ()
;; our code is placed here, verbatim, as a whole:
(func (stream-cdr b))
)
)
const-stream is a macro, it just moves pieces of code around.
The lambda might be enclosed in a memo-proc call for the memoization, to do call-by-need, but it'll still have the code we wrote, like (func (stream-cdr b)), placed inside the lambda, "textually", by cons-stream. Which is a macro, just moving pieces of code around.
Regarding the snippet which you've added to the question, the authors were just being imprecise. What is meant there is, when (stream-cdr stream) in (stream-filter pred (stream-cdr stream)) will be called, it will produce (cons 10008 (delay .... )), as shown. Not before.
Where it says "which in this case is" is should have said "which in this case is the same as".
In section 3.5.1 Streams Are Delayed Lists the book says:
To make the stream implementation automatically and transparently interleave the construction of a stream with its use, we will arrange for the cdr of a stream to be evaluated when it is accessed by the stream-cdr procedure rather than when the stream is constructed by cons-stream.

Scheme: problem about display when using `delay` expression

This is a problem related to ex3.51 in SICP, here is the code
(define (cons-stream x y)
(cons x (delay y)))
(define (stream-car stream) (car stream))
(define (stream-cdr stream) (force (cdr stream)))
(define (stream-map proc s)
(if (stream-null? s)
the-empty-stream
(cons-stream
(proc (stream-car s))
(stream-map proc (stream-cdr s)))))
(define (stream-enumerate-interval low high)
(if (> low high)
the-empty-stream
(cons-stream
low
(stream-enumerate-interval (+ low 1) high))))
(define (stream-ref s n)
(if (= n 0)
(stream-car s)
(stream-ref (stream-cdr s) (- n 1))))
(define (show x)
(display x)
x)
;test
(stream-map show (stream-enumerate-interval 0 10))
the output is 012345678910(0 . #<promise>).
but I thought the delay expression in cons-stream delayed the evaluation, if i use a different processing function in stream-map like lambda (x) (+ x 1) the output (1 . #<promise>) is more reasonable, so why does display print all the numbers?
The problem is with this definition:
(define (cons-stream x y)
(cons x (delay y)))
It defines cons-stream as a function, since it uses define.
Scheme's evaluation is eager: the arguments are evaluated before the function body is entered. Thus y is already fully calculated when it is passed to delay.
Instead, cons-stream should be defined as a macro, like
(define-syntax cons-stream
(syntax-rules ()
((_ a b) (cons a (delay b)))))
or we can call delay explicitly, manually, like e.g.
(define (stream-map proc s)
(if (stream-null? s)
the-empty-stream
(cons
(proc (stream-car s))
(delay
(stream-map proc (stream-cdr s))))))
Then there'd be no calls to cons-stream in our code, only the (cons A (delay B)) calls. And delay is a macro (or special form, whatever), it does not evaluate its arguments before working but rather goes straight to manipulating the argument expressions instead.
And we could even drop the calls to delay, and replace (cons A (delay B)) with (cons A (lambda () B)). This would entail also reimplementing force (which is built-in, and goes together with the built-in delay) as simply (define (force x) (x)) or just calling the (x) manually where appropriate to force a stream's tail.
You can see such lambda-based streams code towards the end of this answer, or an ideone entry (for this RosettaCode entry) without any macros using the explicit lambdas instead. This approach can change the performance of the code though, as delay is memoizing but lambda-based streams are not. The difference will be seen if we ever try to access a stream's element more than once.
See also this answer for yet another take on streams implementation, surgically modifying list's last cons cell as a memoizing force.

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.

Getting #stream as an output in Drracket

Streams of order and data are given and I need to order the data according to the order-stream.
#lang racket
(define the-empty-stream '())
(define (stream-car stream)
(car stream))
(define-syntax cons-stream
(syntax-rules ()
((cons-stream x y)
(cons x (delay y)))))
(define (stream-cdr stream)
(force (cdr stream)))
(define stream-null? null?)
(define (integers-starting-from n)
(stream-cons n (integers-starting-from (+ n 1))))
(define integers (integers-starting-from 1))
(define order-stream (stream-cons 2 1))
(define data-stream (stream-cons 5 6))
(define (reorder order-stream data-stream)
(cond ((stream-null? order-stream) the-empty-stream)
((stream-null? data-stream) the-empty-stream)
(else (stream-cons (stream-ref data-stream
(stream-car order-stream))
(reorder (stream-cdr order-stream) data-stream)))))
When I execute (reorder order-stream data-stream) I get #stream as output instead of 6 . #promise. This is my programming assignment so instead of giving complete code please give some hints instead.
Racket has a built-in stream-cons, which you're accidentally calling, instead of cons-stream as you intended to use.
Look at what you have:
(define (reorder order-stream data-stream)
^^^^^^^^^^^^
(cond ((stream-null? order-stream) the-empty-stream)
((stream-null? data-stream) the-empty-stream)
(else (stream-cons (stream-ref data-stream
(stream-car order-stream))
(reorder (stream-cdr order-stream) data-stream)))))
^^^^^^^^^^^^^^^^^^^^^^^^^
(define (stream-cdr stream)
(force (cdr stream)))
what kind of thing (stream-cdr stream) is expected to return?
and then you're calling
(define order-stream (cons-stream 2 1))
What is order-stream's cdr?
Stream programming is fun. For instance, to calculate partial sums of a stream, p-s [a,b,c...] = a, a+b, a+b+c, ..., we can write
(define (partial-sums xs init)
(cons-stream init
(partial-sums (stream-cdr xs)
(+ (stream-car xs) init))))
We can easily abstract away the + as a general binary operation argument:
(define (scanl + xs init)
(cons-stream init
(scanl + (stream-cdr xs)
(+ (stream-car xs) init))))
and call it as, e.g.
(define factorials (scanl * integers 1))
Another, interesting way to define scanl, is
(define (scanlist + xs init)
(define rs (cons-stream init
(combine-streams + xs rs)))
rs)
Writing combine-streams (a.k.a. zipWith in Haskell) is a straightforward deal.
In Racket, be sure to work in full language, where define is recursive, analogous to letrec (not let), or else the last one won't work (can you see why?).

Streams and the substitution model

I am wondering how the substitution model can be used to show certain things about infinite streams. For example, say you have a stream that puts n in the nth spot and so on inductively. I define it below:
(define all-ints
(lambda ((n <integer>))
(stream-cons n (all-ints (+ 1 n)))))
(define integers (all-ints 1))
It is pretty clear that this does what it is supposed to, but how would someone go about proving it? I decided to use induction. Specifically, induction on k where
(last (stream-to-list integers k))
provides the last value of the first k values of the stream provided, in this case integers. I define stream-to-list below:
(define stream-to-list
(lambda ((s <stream>) (n <integer>))
(cond ((or (zero? n) (stream-empty? s)) '())
(else (cons (stream-first s)
(stream-to-list (stream-rest s) (- n 1)))))))
What I'd like to prove, specifically, is the property that k = (last (stream-to-list integers k)) for all k > 1.
Getting the base case is fairly easy and I can do that, but how would I go about showing the "inductive case" as thoroughly as possible? Since computing the item in the k+1th spot requires that the previous k items also be computed, I don't know how this could be shown. Could someone give me some hints?
In particular, if someone could explain how, exactly, streams are interpreted using the substitution model, I'd really appreciate it. I know they have to be different from the other constructs a regular student would have learned before streams, because they delay computation and I feel like that means they can't be evaluated completely. In turn this would man, I think, the substitution model's apply eval apply etc pattern would not be followed.
stream-cons is a special form. It equalent to wrapping both arguments in lambdas, making them thunks. like this:
(stream-cons n (all-ints (+ 1 n))) ; ==>
(cons (lambda () n) (lambda () (all-ints (+ n 1))))
These procedures are made with the lexical scopes so here n is the initial value while when forcing the tail would call all-ints again in a new lexical scope giving a new n that is then captured in the the next stream-cons. The procedures steam-first and stream-rest are something like this:
(define (stream-first s)
(if (null? (car s))
'()
((car s))))
(define (stream-rest s)
(if (null? (cdr s))
'()
((cdr s))))
Now all of this are half truths. The fact is they are not functional since they mutates (memoize) the value so the same value is not computed twice, but this is not a problem for the substitution model since side effects are off limits anyway. To get a feel for how it's really done see the SICP wizards in action. Notice that the original streams only delayed the tail while modern stream libraries delay both head and tail.

Resources