source: Dev/trunk/src/client/dojox/lang/functional/fold.js @ 529

Last change on this file since 529 was 483, checked in by hendrikvanantwerpen, 11 years ago

Added Dojo 1.9.3 release.

  • Property svn:executable set to *
File size: 4.4 KB
Line 
1define(["dojo/_base/lang", "dojo/_base/array", "dojo/_base/kernel", "./lambda"],
2        function(lang, arr, kernel, df){
3
4// This module adds high-level functions and related constructs:
5//      - "fold" family of functions
6
7// Notes:
8//      - missing high-level functions are provided with the compatible API:
9//              foldl, foldl1, foldr, foldr1
10//      - missing JS standard functions are provided with the compatible API:
11//              reduce, reduceRight
12//      - the fold's counterpart: unfold
13
14// Defined methods:
15//      - take any valid lambda argument as the functional argument
16//      - operate on dense arrays
17//      - take a string as the array argument
18//      - take an iterator objects as the array argument (only foldl, foldl1, and reduce)
19
20        var empty = {};
21
22        lang.mixin(df, {
23                // classic reduce-class functions
24                foldl: function(/*Array|String|Object*/ a, /*Function*/ f, /*Object*/ z, /*Object?*/ o){
25                        // summary:
26                        //              repeatedly applies a binary function to an array from left
27                        //              to right using a seed value as a starting point; returns the final
28                        //              value.
29                        if(typeof a == "string"){ a = a.split(""); }
30                        o = o || kernel.global; f = df.lambda(f);
31                        var i, n;
32                        if(lang.isArray(a)){
33                                // array
34                                for(i = 0, n = a.length; i < n; z = f.call(o, z, a[i], i, a), ++i);
35                        }else if(typeof a.hasNext == "function" && typeof a.next == "function"){
36                                // iterator
37                                for(i = 0; a.hasNext(); z = f.call(o, z, a.next(), i++, a));
38                        }else{
39                                // object/dictionary
40                                for(i in a){
41                                        if(!(i in empty)){
42                                                z = f.call(o, z, a[i], i, a);
43                                        }
44                                }
45                        }
46                        return z;       // Object
47                },
48                foldl1: function(/*Array|String|Object*/ a, /*Function|String|Array*/ f, /*Object?*/ o){
49                        // summary:
50                        //              repeatedly applies a binary function to an array from left
51                        //              to right; returns the final value.
52                        if(typeof a == "string"){ a = a.split(""); }
53                        o = o || kernel.global; f = df.lambda(f);
54                        var z, i, n;
55                        if(lang.isArray(a)){
56                                // array
57                                z = a[0];
58                                for(i = 1, n = a.length; i < n; z = f.call(o, z, a[i], i, a), ++i);
59                        }else if(typeof a.hasNext == "function" && typeof a.next == "function"){
60                                // iterator
61                                if(a.hasNext()){
62                                        z = a.next();
63                                        for(i = 1; a.hasNext(); z = f.call(o, z, a.next(), i++, a));
64                                }
65                        }else{
66                                // object/dictionary
67                                var first = true;
68                                for(i in a){
69                                        if(!(i in empty)){
70                                                if(first){
71                                                        z = a[i];
72                                                        first = false;
73                                                }else{
74                                                        z = f.call(o, z, a[i], i, a);
75                                                }
76                                        }
77                                }
78                        }
79                        return z;       // Object
80                },
81                foldr: function(/*Array|String*/ a, /*Function|String|Array*/ f, /*Object*/ z, /*Object?*/ o){
82                        // summary:
83                        //              repeatedly applies a binary function to an array from right
84                        //              to left using a seed value as a starting point; returns the final
85                        //              value.
86                        if(typeof a == "string"){ a = a.split(""); }
87                        o = o || kernel.global; f = df.lambda(f);
88                        for(var i = a.length; i > 0; --i, z = f.call(o, z, a[i], i, a));
89                        return z;       // Object
90                },
91                foldr1: function(/*Array|String*/ a, /*Function|String|Array*/ f, /*Object?*/ o){
92                        // summary:
93                        //              repeatedly applies a binary function to an array from right
94                        //              to left; returns the final value.
95                        if(typeof a == "string"){ a = a.split(""); }
96                        o = o || kernel.global; f = df.lambda(f);
97                        var n = a.length, z = a[n - 1], i = n - 1;
98                        for(; i > 0; --i, z = f.call(o, z, a[i], i, a));
99                        return z;       // Object
100                },
101                // JS 1.8 standard array functions, which can take a lambda as a parameter.
102                reduce: function(/*Array|String|Object*/ a, /*Function|String|Array*/ f, /*Object?*/ z){
103                        // summary:
104                        //              apply a function simultaneously against two values of the array
105                        //              (from left-to-right) as to reduce it to a single value.
106                        return arguments.length < 3 ? df.foldl1(a, f) : df.foldl(a, f, z);      // Object
107                },
108                reduceRight: function(/*Array|String*/ a, /*Function|String|Array*/ f, /*Object?*/ z){
109                        // summary:
110                        //              apply a function simultaneously against two values of the array
111                        //              (from right-to-left) as to reduce it to a single value.
112                        return arguments.length < 3 ? df.foldr1(a, f) : df.foldr(a, f, z);      // Object
113                },
114                // the fold's counterpart: unfold
115                unfold: function(/*Function|String|Array*/ pr, /*Function|String|Array*/ f,
116                                                /*Function|String|Array*/ g, /*Object*/ z, /*Object?*/ o){
117                        // summary:
118                        //              builds an array by unfolding a value
119                        o = o || kernel.global; f = df.lambda(f); g = df.lambda(g); pr = df.lambda(pr);
120                        var t = [];
121                        for(; !pr.call(o, z); t.push(f.call(o, z)), z = g.call(o, z));
122                        return t;       // Array
123                }
124        });
125});
Note: See TracBrowser for help on using the repository browser.