123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141 |
- /*
- Copyright (c) 2004-2012, The Dojo Foundation All Rights Reserved.
- Available via Academic Free License >= 2.1 OR the modified BSD license.
- see: http://dojotoolkit.org/license for details
- */
- if(!dojo._hasResource["dojox.lang.functional.lambda"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
- dojo._hasResource["dojox.lang.functional.lambda"] = true;
- dojo.provide("dojox.lang.functional.lambda");
- // This module adds high-level functions and related constructs:
- // - anonymous functions built from the string
- // Acknoledgements:
- // - lambda() is based on work by Oliver Steele
- // (http://osteele.com/sources/javascript/functional/functional.js)
- // which was published under MIT License
- // Notes:
- // - lambda() produces functions, which after the compilation step are
- // as fast as regular JS functions (at least theoretically).
- // Lambda input values:
- // - returns functions unchanged
- // - converts strings to functions
- // - converts arrays to a functional composition
- (function(){
- var df = dojox.lang.functional, lcache = {};
- // split() is augmented on IE6 to ensure the uniform behavior
- var split = "ab".split(/a*/).length > 1 ? String.prototype.split :
- function(sep){
- var r = this.split.call(this, sep),
- m = sep.exec(this);
- if(m && m.index == 0){ r.unshift(""); }
- return r;
- };
-
- var lambda = function(/*String*/ s){
- var args = [], sects = split.call(s, /\s*->\s*/m);
- if(sects.length > 1){
- while(sects.length){
- s = sects.pop();
- args = sects.pop().split(/\s*,\s*|\s+/m);
- if(sects.length){ sects.push("(function(" + args + "){return (" + s + ")})"); }
- }
- }else if(s.match(/\b_\b/)){
- args = ["_"];
- }else{
- var l = s.match(/^\s*(?:[+*\/%&|\^\.=<>]|!=)/m),
- r = s.match(/[+\-*\/%&|\^\.=<>!]\s*$/m);
- if(l || r){
- if(l){
- args.push("$1");
- s = "$1" + s;
- }
- if(r){
- args.push("$2");
- s = s + "$2";
- }
- }else{
- // the point of the long regex below is to exclude all well-known
- // lower-case words from the list of potential arguments
- var vars = s.
- replace(/(?:\b[A-Z]|\.[a-zA-Z_$])[a-zA-Z_$\d]*|[a-zA-Z_$][a-zA-Z_$\d]*:|this|true|false|null|undefined|typeof|instanceof|in|delete|new|void|arguments|decodeURI|decodeURIComponent|encodeURI|encodeURIComponent|escape|eval|isFinite|isNaN|parseFloat|parseInt|unescape|dojo|dijit|dojox|window|document|'(?:[^'\\]|\\.)*'|"(?:[^"\\]|\\.)*"/g, "").
- match(/([a-z_$][a-z_$\d]*)/gi) || [], t = {};
- dojo.forEach(vars, function(v){
- if(!(v in t)){
- args.push(v);
- t[v] = 1;
- }
- });
- }
- }
- return {args: args, body: s}; // Object
- };
- var compose = function(/*Array*/ a){
- return a.length ?
- function(){
- var i = a.length - 1, x = df.lambda(a[i]).apply(this, arguments);
- for(--i; i >= 0; --i){ x = df.lambda(a[i]).call(this, x); }
- return x;
- }
- :
- // identity
- function(x){ return x; };
- };
- dojo.mixin(df, {
- // lambda
- rawLambda: function(/*String*/ s){
- // summary:
- // builds a function from a snippet, or array (composing),
- // returns an object describing the function; functions are
- // passed through unmodified.
- // description:
- // This method is to normalize a functional representation (a
- // text snippet) to an object that contains an array of
- // arguments, and a body , which is used to calculate the
- // returning value.
- return lambda(s); // Object
- },
- buildLambda: function(/*String*/ s){
- // summary:
- // builds a function from a snippet, returns a string, which
- // represents the function.
- // description:
- // This method returns a textual representation of a function
- // built from the snippet. It is meant to be evaled in the
- // proper context, so local variables can be pulled from the
- // environment.
- s = lambda(s);
- return "function(" + s.args.join(",") + "){return (" + s.body + ");}"; // String
- },
- lambda: function(/*Function|String|Array*/ s){
- // summary:
- // builds a function from a snippet, or array (composing),
- // returns a function object; functions are passed through
- // unmodified.
- // description:
- // This method is used to normalize a functional
- // representation (a text snippet, an array, or a function) to
- // a function object.
- if(typeof s == "function"){ return s; }
- if(s instanceof Array){ return compose(s); }
- if(s in lcache){ return lcache[s]; }
- s = lambda(s);
- return lcache[s] = new Function(s.args, "return (" + s.body + ");"); // Function
- },
- clearLambdaCache: function(){
- // summary:
- // clears internal cache of lambdas
- lcache = {};
- }
- });
- })();
- }
|