User Tools


Differences

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

Link to this comparison view

cl:functions:reduce [2019/09/14 05:00]
cl:functions:reduce [2019/09/22 06: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}