zoukankan      html  css  js  c++  java
  • 函数式编程之Functional.js源码解析(一)

    先简单介绍下Functional.js吧

    functional.js 是模仿 Haskell 语言标准库 Prelude 制作的函数式编程库,主要实现了:


    • 扩展的克里化函数
    • 运算符函数化
    • 紧缩的匿名函数语法
    • 无须指定参数的匿名函数语法
    • 函数向导语法
    • 基本的通用列表操作
    • 部分扩展基于对象化

    其中,扩展语法由字符串表示。未能实现的特性有:

    • 尾递归优化
    • 模式匹配(包括参数匹配、列表匹配、情况分析)
    • 惰性运算(包括无穷列表)
    • 列表领悟
    • 扩展绑定、同时绑定
    • 其它列表操作(以及对于列表操作的基于对象化)

    最近没事研究了下Function.js的源码,咱们先从to-function.js开始

    to-function.js主要是让字符串变成相应的函数

    第一个函数String.prototype.lambda 在下一篇文章再讨论,先来看下它的缓存机制

    ps:先贴上lambda函数源码,下篇文章重点讨论

    String.prototype.lambda = function() {
        var params = [],
            expr = this,
            sections = expr.ECMAsplit(/\s*->\s*/m);
        if (sections.length > 1) {
            while (sections.length) {
                expr = sections.pop();
                params = sections.pop().split(/\s*,\s*|\s+/m);
                sections.length && sections.push('(function('+params+'){return ('+expr+')})');
            }
        } else if (expr.match(/\b_\b/)) {
            params = '_';
        } else {
            // test whether an operator appears on the left (or right), respectively
            var leftSection = expr.match(/^\s*(?:[+*\/%&|\^\.=<>]|!=)/m),
                rightSection = expr.match(/[+\-*\/%&|\^\.=<>!]\s*$/m);
            if (leftSection || rightSection) {
                if (leftSection) {
                    params.push('$1');
                    expr = '$1' + expr;
                }
                if (rightSection) {
                    params.push('$2');
                    expr = expr + '$2';
                }
            } else {
                // `replace` removes symbols that are capitalized, follow '.',
                // precede ':', are 'this' or 'arguments'; and also the insides of
                // strings (by a crude test).  `match` extracts the remaining
                // symbols.
                var vars = this.replace(/(?:\b[A-Z]|\.[a-zA-Z_$])[a-zA-Z_$\d]*|[a-zA-Z_$][a-zA-Z_$\d]*\s*:|this|arguments|'(?:[^'\\]|\\.)*'|"(?:[^"\\]|\\.)*"/g, '').match(/([a-z_$][a-z_$\d]*)/gi) || []; // '
                for (var i = 0, v; v = vars[i++]; )
                    params.indexOf(v) >= 0 || params.push(v);
            }
        }
        return new Function(params, 'return (' + expr + ')');
    }
    
    //cache函数
    String.prototype.lambda.cache = function() {
    
        var proto = String.prototype,  //保留String的prototype的引用
    
             cache = {},     //存储缓存结果缓存对象   
    
           uncached = proto.lambda,     //保留没有缓存时的引用 
    
          cached = function() {	        
    
                   var key = '#' + this; // avoid hidden properties on Object.prototype	      
    
                  return cache[key] || (cache[key] = uncached.call(this));        };  
        //cached函数用来取得缓存后的结果,如果没有进行缓存则将其加入缓存中,里边的this指向调用该函数的对象
    cached.cached = function(){}; cached.uncache = function(){ proto.lambda = uncached }; //uncache函数用来清掉缓存 proto.lambda = cached; //重置lambda函数为缓存后的结果,下次再调用lambda时直接从缓存中读取,提高运行速度 }

    其实这里的缓存原理与懒惰函数的原理本质是一样的

    var f=function(a){
       var e=a*a;
       f.a=e;
       f=function(){
          return "我已经缓存了"+e;
       }
      return e
    }
    alert(f(3));
    alert(f(4));//此处输出结果任然为9
    
    基本原理就是第一次计算后重置该函数,第二次调用时直接返回第一次结算的结果!
  • 相关阅读:
    四则运算测试脚本运行情况
    AAA
    (2015秋) 软工作业成绩公布(12月26号更新)
    判断闰年的Java算法
    B
    A
    Where Amazing Happens
    安利一发资料站
    C
    B
  • 原文地址:https://www.cnblogs.com/hust/p/2019633.html
Copyright © 2011-2022 走看看