reduce express sequence manipulation using compact expressions.
For example, let's sum all primes in an interval .
def sum_primes(a, b): total = 0 x = a while x < b: if is_prime(x): total += x x += 1 return total
This runs in constant space. But what if we wrote instead:
def sum_primes(a, b): return sum(filter(is_prime, range(a, b))) def is_prime(x): return x > 1 and all(map(lambda y: x % y, range(2, x)))
This also runs in !
Let's write these functions in Scheme.
sum aren't defined, so we'll define them along with
(define (range a b) (if (>= a b) nil (cons a (range (+ a 1) b)))) (define (sum s) (reduce + s)) (define (prime? x) (and (> x 1) (null? (filter (lambda (y) (= 0 (remainder x y))) (range 2 x))))) (define (sum-primes a b) (sum (filter prime? (range a b))))
sum-primes doesn't run in constant space. The reason is, unlike Python's
filter function, the scheme
filter doesn't work lazily. That, along with the fact that we're interpreting Scheme in Python, leads to slower runtime.
A stream is a list, but the rest of the list is only computed when needed (lazy lists).
(car (cons 1 nil)) --> 1
(car (cons-stream 1 nil)) --> 1
(cdr (cons 1 nil)) --> ()
(cdr-stream (cons-stream 1 nil)) --> ()
(cons 1 (cons 2 nil))
(cons-stream 1 (cons-stream 2 nil))
Here, errors only occur when expressions are evaluated.
(cons 1 (cons (/ 1 0) nil)) leads to an ==ERROR==.
(cons-stream 1 (cons-stream (/ 1 0) nil)) evaluates to
(1 . #[promise (not forced)])
Let's try this out:
(define (range-stream a b) (if (>= a b) nil (cons-stream a (range-stream (+ a 1) b))))
(range 1 1000) crashes, but
(range-stream 1 1000) is perfectly fine.
Stream ranges are implicit.
A stream of consecutive integers
(define (int-stream start) (cons-stream start (int-stream (+ start 1))))
The rest of a constant stream is a constant stream.
(define ones (cons-stream 1 ones))
Combine two by separating each into
(define (add-streams s t) (cons-stream (+ (car s) (car t)) (add-streams (cdr-stream s) (cdr-stream t)))) (define ints (cons-stream 1 (add-streams ones ints)))
For any prime , any larger prime must not be divisible by .
The stream of integers not divisible by any is:
This recurrence is called the Sieve of Eratosthenes.
(define (sieve s) (cons-stream (car s) (sieve (filter-stream (lambda (x) (< 0 (remainder x (car s)))) (cdr-stream s)))))