This shows you the differences between two versions of the page.

cl:functions:reduce [2019/09/14 05:00] |
cl:functions:reduce [2020/02/27 02:00] (current) |
||
---|---|---|---|

Line 1: | Line 1: | ||

+ | ====== Function REDUCE ====== | ||

+ | |||

+ | ====Syntax==== | ||

+ | * **reduce** //function// //sequence// ''&key'' //key// //from-end// //start// //end// //initial-value// → //result// | ||

+ | |||

+ | ====Arguments and Values==== | ||

+ | //function// - a //[[CL:Glossary:designator]]// for a //[[CL:Glossary:function]]// that might be called with either zero or two //[[CL:Glossary:argument|arguments]]//. | ||

+ | //sequence// - a //[[CL:Glossary:proper sequence]]//. | ||

+ | //key// - a //[[CL:Glossary:designator]]// for a //[[CL:Glossary:function]]// of one argument, or **[[CL:Constant Variables:nil]]**. | ||

+ | //from-end// - a //[[CL:Glossary:generalized boolean]]//. The default is //[[CL:Glossary:false]]//. | ||

+ | //start//, //end// - //[[CL:Glossary:bounding index designator|bounding index designators]]// of //sequence//. The defaults for //start// and //end// are ''0'' and **[[CL:Constant Variables:nil]]**, respectively. | ||

+ | //initial-value// - an //[[CL:Glossary:object]]//. | ||

+ | //result// - an //[[CL:Glossary:object]]//. | ||

+ | |||

+ | ====Description==== | ||

+ | **reduce** uses a binary operation, //function//, to combine the //[[CL:Glossary:element|elements]]// of //sequence// //[[CL:Glossary:bounded]]// by //start// and //end//. | ||

+ | |||

+ | The //function// must accept as //[[CL:Glossary:argument|arguments]]// two //[[CL:Glossary:element|elements]]// of //sequence// or the results from combining those //[[CL:Glossary:element|elements]]//. The //function// must also be able to accept no arguments. | ||

+ | |||

+ | If //key// is supplied, it is used is used to extract the values to reduce. The //key// function is applied exactly once to each element of //sequence// in the order implied by the reduction order but not to the value of //initial-value//, if supplied. | ||

+ | |||

+ | The //key// function typically returns part of the //[[CL:Glossary:element]]// of //sequence//. If //key// is not supplied or is **[[CL:Constant Variables:nil]]**, the //sequence// //[[CL:Glossary:element]]// itself is used. | ||

+ | |||

+ | The reduction is left-associative, unless //from-end// is //[[CL:Glossary:true]]// in which case it is right-associative. | ||

+ | |||

+ | If //initial-value// is supplied, it is logically placed before the subsequence (or after it if //from-end// is //[[CL:Glossary:true]]//) and included in the reduction operation. | ||

+ | |||

+ | In the normal case, the result of **reduce** is the combined result of //function//'s being applied to successive pairs of //[[CL:Glossary:element|elements]]// of //sequence//. | ||

+ | |||

+ | If the subsequence contains exactly one //[[CL:Glossary:element]]// and no //initial-value// is given, then that //[[CL:Glossary:element]]// is returned and //function// is not called. If the subsequence is empty and an //initial-value// is given, then the //initial-value// is returned and //function// is not called. | ||

+ | |||

+ | If the subsequence is empty and no //initial-value// is given, then the //function// is called with zero arguments, and **reduce** returns whatever //function// does. This is the only case where the //function// is called with other than two arguments. | ||

+ | |||

+ | ====Examples==== | ||

+ | <blockquote> | ||

+ | (reduce #'[[CL:Functions:math-multiply|*]] '(1 2 3 4 5)) <r>120 </r> | ||

+ | (reduce #'[[CL:Functions:append]] '((1) (2)) :initial-value '(i n i t)) <r>(I N I T 1 2) </r> | ||

+ | (reduce #'[[CL:Functions:append]] '((1) (2)) :from-end t :initial-value '(i n i t)) <r>(1 2 I N I T) </r> | ||

+ | (reduce #'[[CL:Functions:math-subtract|-]] '(1 2 3 4)) | ||

+ | ≡ ([[CL:Functions:math-subtract|-]] ([[CL:Functions:math-subtract|-]] ([[CL:Functions:math-subtract|-]] 1 2) 3) 4) <r>-8 </r> | ||

+ | (reduce #'[[CL:Functions:math-subtract|-]] '(1 2 3 4) :from-end [[CL:Constant Variables:t]]) ;Alternating sum. | ||

+ | ≡ ([[CL:Functions:math-subtract|-]] 1 ([[CL:Functions:math-subtract|-]] 2 ([[CL:Functions:math-subtract|-]] 3 4))) <r>-2 </r> | ||

+ | (reduce #'[[CL:Functions:math-add|+]] '()) <r>0 </r> | ||

+ | (reduce #'[[CL:Functions:math-add|+]] '(3)) <r>3 </r> | ||

+ | (reduce #'[[CL:Functions:math-add|+]] '(foo)) <r>FOO </r> | ||

+ | (reduce #'[[CL:Functions:list]] '(1 2 3 4)) <r>(((1 2) 3) 4) </r> | ||

+ | (reduce #'[[CL:Functions:list]] '(1 2 3 4) :from-end [[CL:Constant Variables:t]]) <r>(1 (2 (3 4))) </r> | ||

+ | (reduce #'[[CL:Functions:list]] '(1 2 3 4) :initial-value 'foo) <r>((((foo 1) 2) 3) 4) </r> | ||

+ | (reduce #'[[CL:Functions:list]] '(1 2 3 4) :from-end [[CL:Constant Variables:t]] :initial-value 'foo) <r>(1 (2 (3 (4 foo)))) </r> | ||

+ | </blockquote> | ||

+ | |||

+ | ====Side Effects==== | ||

+ | None. | ||

+ | |||

+ | ====Affected By==== | ||

+ | None. | ||

+ | |||

+ | ====Exceptional Situations==== | ||

+ | Should be prepared to signal an error of type type-error if //sequence// is not a //[[CL:Glossary:proper sequence]]//. | ||

+ | |||

+ | ====See Also==== | ||

+ | * {\secref\TraversalRules} | ||

+ | |||

+ | ====Notes==== | ||

+ | None. | ||

+ | |||

+ | \issue{MAPPING-DESTRUCTIVE-INTERACTION:EXPLICITLY-VAGUE} \issue{REDUCE-ARGUMENT-EXTRACTION} \issue{SUBSEQ-OUT-OF-BOUNDS} \issue{RANGE-OF-START-AND-END-PARAMETERS:INTEGER-AND-INTEGER-NIL} \issue{REDUCE-ARGUMENT-EXTRACTION} | ||