source: Dev/branches/rest-dojo-ui/client/dojox/lang/functional/tailrec.js @ 256

Last change on this file since 256 was 256, checked in by hendrikvanantwerpen, 13 years ago

Reworked project structure based on REST interaction and Dojo library. As
soon as this is stable, the old jQueryUI branch can be removed (it's
kept for reference).

File size: 3.6 KB
Line 
1dojo.provide("dojox.lang.functional.tailrec");
2
3dojo.require("dojox.lang.functional.lambda");
4dojo.require("dojox.lang.functional.util");
5
6// This module provides recursion combinators:
7//      - a tail recursion combinator.
8
9// Acknoledgements:
10//      - recursion combinators are inspired by Manfred von Thun's article
11//              "Recursion Theory and Joy"
12//              (http://www.latrobe.edu.au/philosophy/phimvt/joy/j05cmp.html)
13
14// Notes:
15//      - recursion combinators produce a function, which implements
16//      their respective recusion patterns. String lambdas are inlined, if possible.
17
18(function(){
19        var df = dojox.lang.functional, inline = df.inlineLambda, _x ="_x";
20
21        df.tailrec = function(
22                                        /*Function|String|Array*/ cond,
23                                        /*Function|String|Array*/ then,
24                                        /*Function|String|Array*/ before){
25                // summary:
26                //              Generates a function for the tail recursion pattern. This is the simplified
27                //              version of the linear recursive combinator without the "after" function,
28                //              and with the modified "before" function. All parameter functions are called
29                //              in the context of "this" object.
30                // cond:
31                //              The lambda expression, which is used to detect the termination of recursion.
32                //              It accepts the same parameter as the generated recursive function itself.
33                //              This function should return "true", if the recursion should be stopped,
34                //              and the "then" part should be executed. Otherwise the recursion will proceed.
35                // then:
36                //              The lambda expression, which is called upon termination of the recursion.
37                //              It accepts the same parameters as the generated recursive function itself.
38                //              The returned value will be returned as the value of the generated function.
39                // before:
40                //              The lambda expression, which is called before the recursive step.
41                //              It accepts the same parameter as the generated recursive function itself,
42                //              and returns an array of arguments for the next recursive call of
43                //              the generated function.
44
45                var c, t, b, cs, ts, bs, dict1 = {}, dict2 = {},
46                        add2dict = function(x){ dict1[x] = 1; };
47                if(typeof cond == "string"){
48                        cs = inline(cond, _x, add2dict);
49                }else{
50                        c = df.lambda(cond);
51                        cs = "_c.apply(this, _x)";
52                        dict2["_c=_t.c"] = 1;
53                }
54                if(typeof then == "string"){
55                        ts = inline(then, _x, add2dict);
56                }else{
57                        t = df.lambda(then);
58                        ts = "_t.t.apply(this, _x)";
59                }
60                if(typeof before == "string"){
61                        bs = inline(before, _x, add2dict);
62                }else{
63                        b = df.lambda(before);
64                        bs = "_b.apply(this, _x)";
65                        dict2["_b=_t.b"] = 1;
66                }
67                var locals1 = df.keys(dict1), locals2 = df.keys(dict2),
68                        f = new Function([], "var _x=arguments,_t=_x.callee,_c=_t.c,_b=_t.b".concat(    // Function
69                                locals1.length ? "," + locals1.join(",") : "",
70                                locals2.length ? ",_t=_x.callee," + locals2.join(",") : t ? ",_t=_x.callee" : "",
71                                ";for(;!",
72                                cs,
73                                ";_x=",
74                                bs,
75                                ");return ",
76                                ts
77                        ));
78                if(c){ f.c = c; }
79                if(t){ f.t = t; }
80                if(b){ f.b = b; }
81                return f;
82        };
83})();
84
85/*
86For documentation only:
87
881) The original recursive version:
89
90var tailrec1 = function(cond, then, before){
91        var cond   = df.lambda(cond),
92                then   = df.lambda(then),
93                before = df.lambda(before);
94        return function(){
95                if(cond.apply(this, arguments)){
96                        return then.apply(this, arguments);
97                }
98                var args = before.apply(this, arguments);
99                return arguments.callee.apply(this, args);
100        };
101};
102
1032) The original iterative version (before minification and inlining):
104
105var tailrec2 = function(cond, then, before){
106        var cond   = df.lambda(cond),
107                then   = df.lambda(then),
108                before = df.lambda(before);
109        return function(){
110                var args = arguments;
111                for(; !cond.apply(this, args); args = before.apply(this, args));
112                return then.apply(this, args);
113        };
114};
115
116*/
Note: See TracBrowser for help on using the repository browser.