Continuo da qui, copio qui.

The key to organizing programs so as to more clearly reflect the signal-flow structure is to concentrate on the “signals” that flow from one stage in the process to the next. If we represent these signals as lists, then we can use list operations to implement the processing at each of the stages. For instance, we can implement the mapping stages of the signal-flow diagrams using the `map`

procedure from 2.2.1 [qui]:

Filtering a sequence to select only those elements that satisfy a given predicate is accomplished by

```
(define (filter predicate sequence)
(cond ((null? sequence) nil)
((predicate (car sequence))
(cons (car sequence)
(filter predicate
(cdr sequence))))
(else (filter predicate
(cdr sequence)))))
```

For example,

ho usato `filter`

predefinito in Racket ma non ditelo a nessuno, *nèh!*

Accumulations can be implemented by

```
(define (accumulate op initial sequence)
(if (null? sequence)
initial
(op (car sequence)
(accumulate op
initial
(cdr sequence)))))
```

**sì**, il solito `nil`

, con Racket dovrei ricordarmi di usare `null`

.

All that remains to implement signal-flow diagrams is to enumerate the sequence of elements to be processed. For `even-fibs`

, we need to generate the sequence of integers in a given range, which we can do as follows:

```
(define (enumerate-interval low high)
(if (> low high)
nil
(cons low
(enumerate-interval
(+ low 1)
high))))
```

To enumerate the leaves of a tree, we can use (*Note*: This is, in fact, precisely the `fringe`

procedure from Exercise 2.28 [qui]. Here we’ve renamed it to emphasize that it is part of a family of general sequence-manipulation procedures.):

```
(define (enumerate-tree tree)
(cond ((null? tree) nil)
((not (pair? tree)) (list tree))
(else (append
(enumerate-tree (car tree))
(enumerate-tree (cdr tree))))))
```

Now we can reformulate `sum-odd-squares`

and `even-fibs`

[post precedente] as in the signal-flow diagrams. For `sum-odd-squares`

, we enumerate the sequence of leaves of the tree, filter this to keep only the odd numbers in the sequence, square each element, and sum the results:

```
(define (sum-odd-squares tree)
(accumulate
+
0
(map square
(filter odd?
(enumerate-tree tree)))))
```

For `even-fibs`

, we enumerate the integers from 0 to `n`

, generate the Fibonacci number for each of these integers, filter the resulting sequence to keep only the even elements, and accumulate the results into a list:

```
(define (even-fibs n)
(accumulate
cons
nil
(filter even?
(map fib
(enumerate-interval 0 n)))))
```

The value of expressing programs as sequence operations is that this helps us make program designs that are modular, that is, designs that are constructed by combining relatively independent pieces. We can encourage modular design by providing a library of standard components together with a conventional interface for connecting the components in flexible ways.

Modular construction is a powerful strategy for controlling complexity in engineering design. In real signal-processing applications, for example, designers regularly build systems by cascading elements selected from standardized families of filters and transducers. Similarly, sequence operations provide a library of standard program elements that we can mix and match. For instance, we can reuse pieces from the `sum-odd-squares`

and `even-fibs`

procedures in a program that constructs a list of the squares of the first `n + 1`

Fibonacci numbers:

```
(define (list-fib-squares n)
(accumulate
cons
nil
(map square
(map fib
(enumerate-interval 0 n)))))
```

We can rearrange the pieces and use them in computing the product of the squares of the odd integers in a sequence:

```
(define
(product-of-squares-of-odd-elements
sequence)
(accumulate
*
1
(map square (filter odd? sequence))))
```

We can also formulate conventional data-processing applications in terms of sequence operations. Suppose we have a sequence of personnel records and we want to find the salary of the highest-paid programmer. Assume that we have a selector salary that returns the salary of a record, and a predicate programmer? that tests if a record is for a programmer. Then we can write

```
(define
(salary-of-highest-paid-programmer
records)
(accumulate
max
0
(map salary
(filter programmer? records))))
```

These examples give just a hint of the vast range of operations that can be expressed as sequence operations.

**Note**: Richard Waters (1979) developed a program that automatically analyzes traditional Fortran programs, viewing them in terms of maps, filters, and accumulations. He found that fully 90 percent of the code in the Fortran Scientific Subroutine Package fits neatly into this paradigm. One of the reasons for the success of Lisp as a programming language is that lists provide a standard medium for expressing ordered collections so that they can be manipulated using higher-order operations. The programming language APL owes much of its power and appeal to a similar choice. In APL all data are represented as arrays, and there is a universal and convenient set of generic operators for all sorts of array operations.

Sequences, implemented here as lists, serve as a conventional interface that permits us to combine processing modules. Additionally, when we uniformly represent structures as sequences, we have localized the data-structure dependencies in our programs to a small number of sequence operations. By changing these, we can experiment with alternative representations of sequences, while leaving the overall design of our programs intact. We will exploit this capability ~~ in 3.5 ~~ [prossimamente], when we generalize the sequence-processing paradigm to admit infinite sequences.