numrec.js 3.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. // wrapped by build app
  2. define("dojox/lang/functional/numrec", ["dijit","dojo","dojox","dojo/require!dojox/lang/functional/lambda,dojox/lang/functional/util"], function(dijit,dojo,dojox){
  3. dojo.provide("dojox.lang.functional.numrec");
  4. dojo.require("dojox.lang.functional.lambda");
  5. dojo.require("dojox.lang.functional.util");
  6. // This module provides recursion combinators:
  7. // - a simplified numeric linear recursion combinator.
  8. // Acknoledgements:
  9. // - recursion combinators are inspired by Manfred von Thun's article
  10. // "Recursion Theory and Joy"
  11. // (http://www.latrobe.edu.au/philosophy/phimvt/joy/j05cmp.html)
  12. // Notes:
  13. // - recursion combinators produce a function, which implements
  14. // their respective recusion patterns. String lambdas are inlined, if possible.
  15. (function(){
  16. var df = dojox.lang.functional, inline = df.inlineLambda,
  17. _r_i = ["_r", "_i"];
  18. df.numrec = function(/*Object*/ then, /*Function|String|Array*/ after){
  19. // summary:
  20. // Generates a function for the simplified numeric linear recursion pattern.
  21. // All parameter functions are called in the context of "this" object.
  22. // description:
  23. // This is a simplification of the linear recursion combinator:
  24. // - the generated function takes one numeric parameter "x",
  25. // - the "cond" is fixed and checks for 0.
  26. // - the "before" is fixed and the generated function is called with "x - 1".
  27. // - the "above is called with two parameters: the return from the generated
  28. // function, and with "x".
  29. // - as you can see the recursion is done by decreasing the parameter,
  30. // and calling itself until it reaches 0.
  31. // then:
  32. // The value, which is used upon termination of the recursion.
  33. // It will be returned as the value of the generated function.
  34. // above:
  35. // The lambda expression, which is called after the recursive step.
  36. // It accepts two parameters: the returned value from the recursive step, and
  37. // the original parameter. The returned value will be returned as the value of
  38. // the generated function.
  39. var a, as, dict = {},
  40. add2dict = function(x){ dict[x] = 1; };
  41. if(typeof after == "string"){
  42. as = inline(after, _r_i, add2dict);
  43. }else{
  44. a = df.lambda(after);
  45. as = "_a.call(this, _r, _i)";
  46. }
  47. var locals = df.keys(dict),
  48. f = new Function(["_x"], "var _t=arguments.callee,_r=_t.t,_i".concat( // Function
  49. locals.length ? "," + locals.join(",") : "",
  50. a ? ",_a=_t.a" : "",
  51. ";for(_i=1;_i<=_x;++_i){_r=",
  52. as,
  53. "}return _r"
  54. ));
  55. f.t = then;
  56. if(a){ f.a = a; }
  57. return f;
  58. };
  59. })();
  60. /*
  61. For documentation only:
  62. 1) The original recursive version:
  63. var numrec1 = function(then, after){
  64. var after = df.lambda(after);
  65. return function(x){
  66. return x ? after.call(this, arguments.callee.call(this, x - 1), x) : then;
  67. };
  68. };
  69. 2) The original iterative version (before minification and inlining):
  70. var numrec2 = function(then, after){
  71. var after = df.lambda(after);
  72. return function(x){
  73. var ret = then, i;
  74. for(i = 1; i <= x; ++i){
  75. ret = after.call(this, ret, i);
  76. }
  77. return ret;
  78. };
  79. };
  80. */
  81. });