在发了博文之后,我又花了一些时间尝试解决这个问题……经过几次尝试之后,我找到了另一种pattern,括号并不再是必要的了:
复制代码 代码如下:
eval(function () {
var s = '', ww = [v] > (s += v);
var ws = [n] > ww(' (' + n + ') ');
pnview3(14, [n] > ww(' [' + n + '] '),
1, 37,
ws, [] > ww(' ... '),
2, 1
);
document.write(s);
} .lamda0());
不过,由于运算符优先级的关系,比较、门、赋值等运算符仍然不能直接写在(伪)lambda表达式中。
也就是说
复制代码 代码如下:
function(a, b){ a == b }
仍然需要写成
复制代码 代码如下:
[a, b] > (a == b)
另外,选择的pattern本身是具有实际效果的——当把一个数组和另一样东西进行比较的时候,脚本引擎会先尝试把两边都转化成数值,如果不成功就转化成字符串再比较。
不过我想正常情况下应该很少有人会拿数组跟别的东西这么比——所以甚至不需要主动去避免,只要用不到(伪)lambda表达式的时候不特意去这样用就没问题了。
新的实现代码如下:
复制代码 代码如下:
/*!
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再次抽疯,这次还是没有下载。