代码改变世界

[改进]还是那个让JavaScript具有(类似)Lambda表达式编程能力

  Nana's Lich  阅读(3096)  评论(8编辑  收藏  举报

之前的一篇博文中我介绍了一种方法可以让JavaScript具有一种近似于Lambda表达式的编程能力——

但是它有一些缺点,其中妨碍它的使用的最主要的一条就是“多了一层括号,让代码变得难以阅读”。

 

在发了博文之后,我又花了一些时间尝试解决这个问题……经过几次尝试之后,我找到了另一种pattern,括号并不再是必要的了:

1
2
3
4
5
6
7
8
9
10
11
12
eval(function () {
  var s = '', ww = [v] > (s += v);
  var ws = [n] > ww(' <a href="#" rel="noopener nofollow">(' + n + ')</a> ');
 
  pnView3(14, [n] > ww(' [' + n + '] '),
   1, 37,
   ws, [] > ww(' ... '),
   2, 1
  );
 
  document.write(s);
} .lamda0());

 

不过,由于运算符优先级的关系,比较、门、赋值等运算符仍然不能直接写在(伪)Lambda表达式中。

也就是说

1
function(a, b){ a == b }

仍然需要写成

1
[a, b] > (a == b)

 

另外,选择的pattern本身是具有实际效果的——当把一个数组和另一样东西进行比较的时候,脚本引擎会先尝试把两边都转化成数值,如果不成功就转化成字符串再比较。

不过我想正常情况下应该很少有人会拿数组跟别的东西这么比——所以甚至不需要主动去避免,只要用到(伪)Lambda表达式的时候特意去这样用就没问题了。

 

新的实现代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
/*!
L-amda "a-Lambda", a module provides Alternate "Lambda" style programming ability for JavaScript.
Created By NanaLich. 2010-09-10
This module is published under WTFPL v2, so you just DO WHAT THE Fxxx YOU WANT TO with it.
*/
 
!function () {
  function attachEntry(o, a, m) {
    var i, j, n;
    o = [].concat(o);
 
    while (i = o.shift()) {
      for (j in a) {
        if (!i[n = a[j]]) i[n] = m;
      }
    }
  }
 
  var xx = /"(?:\\[\s\S]|[^\x22])*"|'(?:\\[\s\S]|[^\x27])*'|([^\s\w]\s*)\[(\s*|\s*[A-Z$_][\w$]*\s*(?:,\s*[A-Z$_][\w$]*\s*)*)\]\s*(>)\s*(\(?)/gi;
  var xy = /[\n\r),;\]}]|$/.source;
 
  function rxClone(rx) {
    return new RegExp(rx.source, (rx.global ? 'g' : '') + (rx.ignoreCase ? 'i' : '') + (rx.multiline ? 'm' : ''));
  }
  attachEntry(RegExp, ['clone'], rxClone);
  attachEntry(RegExp.prototype, ['clone'], function () { return rxClone(this); });
 
  function translateLambda(s) {
    var m, l = 0, r = '', x = xx.clone(); // 由于firefox、safari等浏览器对全局匹配正则表达式有过度的优化,所以这里采用一种迂回的办法创建不重复的正则表达式实例
 
    while (m = x.exec(s)) {
      var h = m[0];
 
      switch (h.charAt(0)) { // 判断期待的语法成分
        case '$': // 函数传参
        case ')':
        case ']':
        case '"': // 匹配到了字符串
        case "'":
          continue; // 以上皆跳过
      }
 
      var p, q, t, k = m[4].length, y = new RegExp(k ? '\\)' : xy, 'g');
 
      r += s.substring(l, p = m.index); // 在结果字符串上附加之前余留的内容
      y.lastIndex = l = p + h.length; // 从伪运算符之后开始寻找右括号或者其它符号
 
      while (q = y.exec(s)) {
        q = q.index;
        try {
          t = 'return(' + s.substring(l, q) + ');';
          new Function(t); // 语法测试
 
          r += m[1] + 'function(' + m[2] + '){ ' + translateLambda(t) + ' }'; // 翻译里面的内容
 
          x.lastIndex = l = q + k; // 下一次查找从当前边界之后开始
 
          break;
        } catch (ex) { }
      }
      if (!q) l = p; // 说明找不到右括号或者有效的代码,直接附加所有匹配的内容
    }
 
    try {
      r += s.substr(l);
 
      new Function(r); // 语法测试
      return r;
    } catch (ex) { // 失败,返回原文
      return s;
    }
  };
 
  var lamdaAliases = ["translateLambda", "lambda", "lamda"];
  attachEntry(String, lamdaAliases, translateLambda);
  attachEntry(String.prototype, lamdaAliases, function () { return translateLambda(this); });
 
  var funPrototype = Function.prototype;
  attachEntry(Function, lamdaAliases, function (func) { return translateLambda('0,' + func); });
  attachEntry(funPrototype, lamdaAliases, function () { return translateLambda('0,' + this); });
 
  var lamda0aliases = ['lambdaInit', 'lambda0', 'lamda0'];
  attachEntry(Function, lamda0aliases, function (func) { return translateLambda('!' + func + '()'); });
  attachEntry(funPrototype, lamda0aliases, function () { return translateLambda('!' + this + '()'); });
} ();

这次为函数增加了专门的方法,去掉了之前蹩足的判断、也增加了新方法稍微简化调用过程;

修正了有额外空格时无法判断期望语法成分的BUG。

 

另外由于Codeplex再次抽疯,这次还是没有下载。

编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· .NET周刊【3月第1期 2025-03-02】
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
点击右上角即可分享
微信分享提示