In this section, we are introduced to streams. Implementation of streams require lazy evaluation. Since all of user-created functions in Scheme is eagerly evaluated, we need to use macros. They can be declared using the define-syntax
command as follows:-
In this exercise, we are tasked with creating a generalized stream-map
function that can take multiple streams and a procedure that takes as many arguments as the number of streams provided. The code can be implemented as follows:-
In this exercise, we are tasked with executing the following code:-
0 is printed immediately since stream-map
immediately accesses the first element. Subsequently, the next elements are accessed and their values are displayed. Calling (stream-ref x 5)
accesses the first five elements and diplays their value. Calling (stream x 7)
next displays only 6 and 7 because the previous values have already been memoized by the delay
macro. Thus the values were returned without displaying them first. Also, each call displays the final number twice. Once is from the actual show
and the other is the value returned by stream-ref
.
In this exercise, we are tasked with tracing the value of sum
as the following code is executed:-
At this point sum
is 0 since it has not been mutated yet.
At this point sum
is 1 since the stream-map
processes the first value in the interval stream and calls accum
.
At the end of this call, sum
holds the value of 6. This is because stream-filter consumes value until the first element that passes its criteria. That first value would be .
At the end of this call, sum
holds the value of 10. This is because the first element in seq
that is divisible by five is .
At the end of this call, sum
holds the value of 136 which is the 7th event value of seq
is .
At the end of this call, sum
holds the value of 210. This is because display-stream
goes through all of seq
. Thus the final value is .
If the delay
function has not been memoized, we will get different values in this case. This is because of the side-effect in the function given to stream-map
. Each time the stream is used, the value of sum
would have mutated and it would be hard to predict the value. By memoization, we restrict the side effect to only the first time the stream is resolved.
In this exercise, we are asked to describe the elements of the stream defined as follows:-
The first element is obviously 1 as defined. The second element is the sum of first element with itself. Thus it is 2. The third element would be the sum of the second element with itself. It will be 4. In essense, we get . Another way to look at it would be through the following code transformation:-
As can be seen, the given stream is the same as the one already given in the book which gives the same value.
In this exercise, we are taked with defining a stream for calculating factorial using mul-streams
function. The code to do so is as follows:-
We can then define factorials
stream using the following code:-
In this exercise, we are asked to define partial-sums
, a function that takes in a stream and outputs . The function can be defined as follows:-
In this exercise, we are aked to define S
which is a stream of numbers beginning with 1 and contains numbers whose multiples are 2, 3 and 5. We are given a hint that (scale-stream S 2)
, (scale-stream S 3)
and (scale-stream S 5)
also belongs in S
. Given this and a merge function, S
can be defined as follows:-
In this task, we asked for the number of additions performed when fibonacci number is calculated by the given fibs
stream. Since the dela
function is memoized, the time taken for calculating fibs
is since all n-1 terms required for its computation has already been computed and can be recovered in time. Now, if the streams is not memoized, as calculated in Chapter 1, we take time to calculate.
In this exercise, we are given the following stream:-
When we call (expand 1 7 10)
, we get the following:-
Next, when we call (expand 3 8 10)
, we get the following:-
In essence, this stream performs long division to calculate with the given radix or base.
In this exercise, we are tasked wtih creating a procedure integrate-series
which takes as input a stream , , ,… which denotes a polynomial and gives its stream which denotes its integrated polynomial without the constant term, as a stream , , ,… . First, let us define integrate-series
as following:-
Next, we need to define cosine-series
and sine-series
using this function. It can be done as follows:-
The series are defined using mutual recursion. As more terms are needed, the counterpart generates enough terms.
In this exercise, we are tasked with writing a mul-series
function that multiplies two series streams as defined in the above exercise. It can be done as follows:-
We are basically calculating
In this exercise, we are tasked with writing a function that computes the inverse of a series. It can be done as follows:-
In this exercise, we are tasked with creating div-series
which divides two power series. It should work for all denominators with non-zero constant. We can go about it as follows:-
In this exercise, we are given the following modified version for sqrt-stream
:-
The reason is that each recursive call of (sqrt-stream x)
constructs a new stream. This means extracting value from this stream would take fresh computations. This is exactly what would happen if we did not memoize delay
.
In this exercise, we are tasked with implementing stream-limit
which takes a stream and a tolerance number. The function then examines the stream until it finds two successive elements which differ by less than tolerance and return the second number. It can be implemented as follows:-
In this exercise, we are tasked with creating a stream to compute . Then, we apply Euler’s series acceleration transformation to examine the convergence characteristics. The ln2-stream
can be defined as follows:-
Taking into account , let us examine the convergences,
As can be seen, recursive acceleration provides the best convergence.
In this exercise, we are given the following code to generate pairs of integers:-
We are tasked with examining the pairs generated by calling (pairs integers integers)
and calculated the number of pairs preceding given pairs at least approximately.
(1 100)
The first level of call gives (1 1)
as the first pair and interleaves (1 2) (1 3) (1 4) ...
with (pairs (2 3 ...) (2 3 ...))
. This means (1 x)
appears as every second element. (1 2)
has 1 preceding element. (1 3)
has 3 preceding elements. (1 4)
has 5 preceding elements. This gives the relationship where (1 n)
has elements before it. Thus, (1 100)
has 197 elements preceding it.
(99 100)
For finding the number of preceding elements for (99 100)
, lets us peel out the (1 x)
terms, from the previous case. This results in (2 x)
occuring every other terms in a sequence interleaved with (pairs (3 4 ...) (3 4 ...))
. Overall, this leads to (2 x)
occuring every terms in the overall sequence. Extending this, we can conclude that the terms (n x)
occur every steps. Next, we need to determine the first terms in such a sequence (x x)
. As can be seen, (1 1)
is the first element, (2 2)
is the third element and (3 3)
is the seventh element. Extending this, we can see that (n n)
occurs as the term number in proportion to term spacing. Thus, the term (99 99)
occurs as term number and (99 100)
occurs terms after that. We thus get terms preceding (99 100)
(100 100)
As determined in the previous segment, (100 100)
has preceding elements.
In the above exercise, the pairs
stream generates pair of form (i j)
where . In this exercise, we are tasked with generating a stream with all pairs without this condition. This can be done by modifying the pairs
function as follows:-
In this exercise, we are given an alternative definition for pairs
by Louis Reasoner as follows:-
This would not work. When we evaluate (pairs integers integers)
, we would also recursively evaluate (pairs (stream-cdr integers) (stream-cdr integers))
immediately to feed as an argument to interleave
. This would lead to an infinite recursion and stack to blow up.
In this exercise, we are tasked with defining a stream triples
that produces a stream of triples (i j k)
where . Then, we are tasked with using triples
to generate the stream of all Pythagorean triples. The code is as follows:-
In this exercise, we are tasked with writing weighted-pairs
which is similar to pairs
except it also takes a weighing function and produces pairs ordered according to the weights. The code is as follows:-
Note that we assume weights are monotonously increasing for pairs (x y) (x (+ y 1)) (x (+ y 2))...
.
Let us see the code for the required orders.
In this exercise, we are tasked with generating a stream of Ramanujam numbers. The code for that is as follows:-
Running this code, we get the following numbers:-
In this exercise, we are tasked with generating a stream of all numbers that can be written as the sum of two squares in three different ways. We can do that similar to ramanujam-numbers
stream above:-
The first five such numbers are as follows:-
In this exercise, we are tasked with creating a stream simulating a circuit . We need to create a function RC
that takes resistance R and capacitance C along with time step dt and returns a function. This function should take the stream representing the time sequence of currents i and initial voltage and return a stream of output voltage v. The code for that is as follows:-
In this exercise, we are tasked with filling out the code given by Eva Lu Ator to simplify zero-crossings
function. The code is as follows:-
We are given a function from Louis Reasoner to smooth out a stream of numbers by averaging successive numbers to produce a smoothed zero-crossings function. The given code is as follows:-
The main mistake being done in the code is that we are feeding the current averge and last value to the sign-change-detector
. The correct method is to feed the previous average and the current average. Thus the correct code is as follows:-
We are advised by Eva Lu Ator to modularize our code so as to separate out the smoothing algorithm and the crossings calculation. The code to do that is as follows:-
We are required to modify the given integral
procedure to use a delayed integrand function. The modified function is as follows:-
In this exercise, we are asked to design a signal-processing system to solve . The code is as follows:-
We are now asked to modify solve-2nd
to solve equations of form . The code to do that is as follows:-
In this exercise, we are asked to simulate an series RLC circuit with R, L and C as the resistance, inductance and capacitance. The circuit can be simulated as follows:-
The stream for R = 1 ohm, CC = 0.2 farad, LL = 1 henry, dt = 0.1 second, and initial values iL0 = 0 amps and vC0 = 10 volts can be generated as follows:-
In this exercise, we are tasked with creating a random stream function that takes a command streams containing either 'generate
or ('reset n)
. The code for that is as follows:-
In this exercise, we are tasked with implementing estimate-integral
which can perform Monte Carlo integration. The code for that is as follows:-