`n`

in `ℤ`

(the set of all integer numbers), take those for which there exists (`∃`

) another integer `k`

, for which the following equation is satisfied: `n = 2k`

.
Or in plain English: All even integers. (because for even integers, there exists another integer that is half the even integer)
Beautiful, eh? In imperative programming, we’d probably do something like this instead:
```
List<Integer> even = new ArrayList<>();
for (int i = /* hmm...? */; i < /* what to put here */; i++)
even.add(i * 2);
```

```
List<Integer> even = new ArrayList<>();
for (int i = /* hmm...? */; i < /* what to put here */; i = i + 2)
even.add(i);
```

- We have to realistically start somewhere
- We have to realistically end somewhere
- We have to store all values in an intermediate collection

*declare*X to be that set, and then

*declare*Y to be a set that is derived from X, and finally materialise Z, which is a very tiny set derived from Y. For this, we may have never needed to materialise all the (even) integers.

### How this compares to SQL

Kevlin made a cunning comparison. Of course, all functional programming aficionados will immediately recognise that languages like Scala have something called a “for comprehension”, which models precisely the mathematical set-builder notation. Java 8 now has the Streams API, which allows us, to some extent, model something similar (although not as powerful). But Kevlin didn’t use those “modern” languages. He used SQL as a comparison. That “arcane” declarative programming language that has been around forever, and that we love so much. Yes, here’s how we can*declare*all the even numbers in SQL:

```
SELECT n
FROM integers
WHERE EXISTS (
SELECT k
FROM integers
WHERE n = 2 * k
)
```

`integers`

“table” could be optimised perfectly. In most databases, we’d probably manually transform the above notation to this equivalent one:
```
SELECT n
FROM integers
WHERE MOD(n, 2) = 0
```

*the same thing*. And if you squint hard enough, you’ll see that Java 8 Streams, for instance, are also pretty much the same thing: I’ve blogged about this recently where all the Java 8 Streams operations are compared to their SQL clause counterparts:

Common SQL Clauses and Their Equivalents in Java 8 Streams

### How is this better?

It’s simple. Both the set-builder notation, and the SQL language (and in principle, other languages’ for comprehensions) are*declarative*. They are expressions, which can be composed to other, more complex expressions, without necessarily executing them. Remember the imperative approach? We tell the machine

*exactly*what to do:

- Start counting from this particular minimal integer value
- Stop counting at this particular maximal integer value
- Store all even integers in between in this particular intermediate collection

- Producing too many integers
- Storing too many integers (or storing them at all)

```
CREATE VIEW even_integers AS
SELECT n
FROM integers
WHERE EXISTS (
SELECT k
FROM integers
WHERE k = 2 * n
)
```

*use*and materialise the even integers, e.g. positive integers less than 100, the optimiser can optimise away the double access to the

`integer`

table and produce only the exact number of values that we’re requesting (without materialising them in intermediate collections):
```
SELECT n
FROM even_integers
WHERE n BETWEEN 0 AND 100
```

### Conclusion

Thinking in terms of sets, in terms of declaring sets, has always been our dream as software engineers. The approach is extremely compelling and elegant. We can delegate a lot of boring algorithmic work to the implementation engine of the declarative programming language. In the case of SQL, it would be a SQL database optimiser, which figures out a great lot of optimisations that we might not have thought of. The above example is trivial. We can perfectly live in a world where we manually iterate over a local integer variable that goes from 0 to 100:```
for (int i = 0; i <= 100; i++)
doSomething(i);
```

### Warning: Don’t oversimplify

This article just illustrates the roots of the SQL mindset in mathematics and functional programming. Do note that modern SQL is*vastly*more sophisticated than its roots, and has moved away from this original paradigm to embrace other paradigms for practical reasons. Don’t limit your SQL usage to what for comprehensions offer. There’s much more to SQL!

Very nice article. But couldn’t you simplify the set builder notation to {2n | n elem ZZ} and the SQL statement to “SELECT 2*n FROM integers”, respectively?

Sure, you could