Reduction of Lists (MIT/GNU Scheme 10.1.6)

Next: Miscellaneous List Operations, Previous: Mapping of Lists, Up: Lists [Contents][Index]

### 7.8 Reduction of Lists

procedure: reduce-left procedure initial list

  Combines all the elements of list using the binary operation procedure. For example, using `+` one can add up all the elements:

      (reduce-left + 0 list-of-numbers)

  The argument initial is used only if list is empty; in this case initial is the result of the call to `reduce-left`. If list has a single argument, it is returned. Otherwise, the arguments are reduced in a left-associative fashion. For example:

      (reduce-left + 0 '(1 2 3 4))            ⇒ 10
      (reduce-left + 0 '(1 2))                ⇒ 3
      (reduce-left + 0 '(1))                  ⇒ 1
      (reduce-left + 0 '())                   ⇒ 0
      (reduce-left + 0 '(foo))                ⇒ foo
      (reduce-left list '() '(1 2 3 4))       ⇒ (((1 2) 3) 4)

procedure: reduce-right procedure initial list

  Like `reduce-left` except that it is right-associative.

      (reduce-right list '() '(1 2 3 4))      ⇒ (1 (2 (3 4)))

procedure: fold-right procedure initial list

  Combines all of the elements of list using the binary operation procedure. Unlike `reduce-left` and `reduce-right`, initial is always used:

      (fold-right + 0 '(1 2 3 4))             ⇒ 10
      (fold-right + 0 '(foo))                 error→ Illegal datum
      (fold-right list '() '(1 2 3 4))        ⇒ (1 (2 (3 (4 ()))))

  `Fold-right` has interesting properties because it establishes a homomorphism between (`cons`, `()`) and (procedure, initial). It can be thought of as replacing the pairs in the spine of the list with procedure and replacing the `()` at the end with initial. Many of the classical list-processing procedures can be expressed in terms of `fold-right`, at least for the simple versions that take a fixed number of arguments:

      (define (copy-list list)
        (fold-right cons '() list))

      (define (append list1 list2)
        (fold-right cons list2 list1))

      (define (map p list)
        (fold-right (lambda (x r) (cons (p x) r)) '() list))

      (define (reverse items)
        (fold-right (lambda (x r) (append r (list x))) '() items))

procedure: fold-left procedure initial list

  Combines all the elements of list using the binary operation procedure. Elements are combined starting with initial and then the elements of list from left to right. Whereas `fold-right` is recursive in nature, capturing the essence of `cdr`-ing down a list and then computing a result, fold-left is iterative in nature, combining the elements as the list is traversed.

      (fold-left list '() '(1 2 3 4))         ⇒ ((((() 1) 2) 3) 4)

      (define (length list)
        (fold-left (lambda (sum element) (+ sum 1)) 0 list))

      (define (reverse items)
        (fold-left (lambda (x y) (cons y x)) () items))

procedure: any predicate list list …

  (SRFI 1) Applies predicate across the lists, returning true if predicate returns true on any application.

  If there are n list arguments list1 … listn, then predicate must be a procedure taking n arguments and returning a boolean result.

  `any` applies predicate to the first elements of the list parameters. If this application returns a true value, `any` immediately returns that value. Otherwise, it iterates, applying predicate to the second elements of the list parameters, then the third, and so forth. The iteration stops when a true value is produced or one of the lists runs out of values; in the latter case, `any` returns `#f`. The application of predicate to the last element of the lists is a tail call.

  Note the difference between `find` and `any`—`find` returns the element that satisfied the predicate; `any` returns the true value that the predicate produced.

  Like `every`, `any`’s name does not end with a question mark—this is to indicate that it does not return a simple boolean (`#t` or `#f`), but a general value.

      (any integer? '(a 3 b 2.7))   => #t
      (any integer? '(a 3.1 b 2.7)) => #f
      (any < '(3 1 4 1 5)
             '(2 7 1 8 2)) => #t

  The non-standard procedure `there-exists?` is similar, except that it takes a single list and a predicate argument, in that order.

procedure: every predicate list list …

  (SRFI 1) Applies predicate across the lists, returning true if predicate returns true on every application.

  If there are n list arguments list1 … listn, then predicate must be a procedure taking n arguments and returning a boolean result.

  `every` applies predicate to the first elements of the list parameters. If this application returns false, `every` immediately returns false. Otherwise, it iterates, applying predicate to the second elements of the list parameters, then the third, and so forth. The iteration stops when a false value is produced or one of the lists runs out of values. In the latter case, `every` returns the true value produced by its final application of predicate. The application of predicate to the last element of the lists is a tail call.

  If one of the lists has no elements, `every` simply returns `#t`.

  Like `any`, `every`’s name does not end with a question mark—this is to indicate that it does not return a simple boolean (`#t` or `#f`), but a general value.

  The non-standard procedure `for-all?` is similar, except that it takes a single list and a predicate argument, in that order.

Next: Miscellaneous List Operations, Previous: Mapping of Lists, Up: Lists [Contents][Index]