#### 4.2.4 Operator Reduction

The `reduce-operator` declaration is provided to inform the compiler that certain names are n-ary versions of binary operators. Here are some examples:

Declaration:

    (declare (reduce-operator (cons* cons)))

Replacements:

    (cons* x y z w) → (cons x (cons y (cons z w))),
    (cons* x y) → (cons x y)
    (cons* x) → x
    (cons*) error→ too few arguments

Declaration:

    (declare (reduce-operator (list cons (null-value '() any))))

Replacements:

    (list x y z w) → (cons x (cons y (cons z (cons w '()))))
    (list x y) → (cons x (cons y '()))
    (list x) → (cons x '())
    (list) → '()

Declaration:

    (declare (reduce-operator (- %- (null-value 0 single) (group left))))

Replacements:

    (- x y z w) → (%- (%- (%- x y) z) w)
    (- x y) → (%- x y)
    (- x) → (%- 0 x)
    (-) → 0

Declaration:

    (declare (reduce-operator (+ %+ (null-value 0 none) (group right))))

Replacements:

    (+ x y z w) → (%+ x (%+ y (%+ z w)))
    (+ x y) → (%+ x y)
    (+ x) → x
    (+) → 0

Note: This declaration does not cause an appropriate definition of `%+` (in the last example) to appear in your code. It merely informs the compiler that certain optimizations can be performed on calls to `+` by replacing them with calls to `%+`. You should provide a definition of `%+` as well, although it is not required.

Declaration:

    (declare (reduce-operator (apply (primitive cons)
                                     (group right)
                                     (wrapper (global apply) 1))))

Replacements:

    (apply f x y z w)
       → ((access apply #f) f (cons x (cons y (cons z w))))
    (apply f x y)
       → ((access apply #f) f (cons x y))
    (apply f x) → (apply f x)
    (apply f) → (apply f)
    (apply) → (apply)

declaration: reduce-operator name …

  The general format of the declaration is (brackets denote optional elements):

      (reduce-operator
        (name
          binop
          [(group ordering)]
          [(null-value value null-option)]
          [(singleton unop)]
          [(wrapper wrap [n])]
          [(maximum m)]
        ))

  where

  - n and m are non-negative integers.
  - name is a symbol.
  - binop, value, unop, and wrap are simple expressions in one of these forms:
    `'constant`

      A constant.

    `variable`

      A variable.

    `(primitive primitive-name [arity])`

      The primitive procedure named primitive-name. The optional element arity specifies the number of arguments that the primitive accepts.

    `(global var)`

      A global variable.

  - null-option is either `always`, `any`, `one`, `single`, `none`, or `empty`.
  - ordering is either `left`, `right`, or `associative`.

  The meaning of these fields is:

  - name is the name of the n-ary operation to be reduced.
  - binop is the binary operation into which the n-ary operation is to be reduced.
  - The `group` option specifies whether name associates to the right or left.
  - The `null-value` option specifies a value to use in the following cases:
    `none`
    `empty`

      When no arguments are supplied to name, value is returned.

    `one`
    `single`

      When a single argument is provided to name, value becomes the second argument to binop.

    `any`
    `always`

      binop is used on the “last” argument, and value provides the remaining argument to binop.

    In the above options, when value is supplied to binop, it is supplied on the left if grouping to the left, otherwise it is supplied on the right.

  - The `singleton` option specifies a function, unop, to be invoked on the single argument given. This option supersedes the `null-value` option, which can only take the value `none`.
  - The `wrapper` option specifies a function, wrap, to be invoked on the result of the outermost call to binop after the expansion. If n is provided it must be a non-negative integer indicating a number of arguments that are transferred verbatim from the original call to the wrapper. They are passed to the left of the reduction.
  - The maximum option specifies that calls with more than m arguments should not be reduced.