qiezi 发表于 2013-2-5 01:31:32

lambda之路...

DMD最近的版本号加入了闭包,感觉非常有用,虽然有些背后动作,不过我是实用派不介意这个。玩的时候忽然想到为什么没有lambda呢?AST还没影,不过可以利用D强大的模板可以使用字符串来先模拟一下。

我假想的语法是这样的:
int[] arr = ;int[] arr1 = arr.map(lambda!("int x -> x * x"));

上面执行的arr1结果将会是。

在编写过程中发现匿名委托不能够使用模板来这样生成:
template labmda(string expr){    auto lambda = mixin("(int x){return (x);}");}
所以必须在使用的地方去mixin(如果你可以避免这个请告诉我),像这样的:

int[] arr1 = arr.map(mixin("(int x){return (x);}"));
测试很长时间没有找到突破方法去掉这个mixin,所以就在这个起点上向目标前进了。

测试过程中也发现现在的模板对于字符串参数似乎不像以前那么友好了,编译期执行函数则得到了加强,所以使用它来实现:
int indexof(string s, char ch){foreach(i, c; s)if(c == ch)return i;return -1;}int indexof(string s, string sub){for(int i=0; i<s.length-sub.length; i++){if (s == sub)return i;}return -1;}string _RetType(string expr){int end = indexof(expr, '|');if (end == -1)return "";else{int end1 = indexof(expr, "->");assert(end1 > 0, "'->' not found in lambda expression: " ~ expr);if (end > end1) return "";return expr;}}string _ArgTypes(string expr){int start = indexof(expr, '|');int end = indexof(expr, "->");assert(end > 0, "'->' not found in lambda expression: " ~ expr);if (start > end) start = -1;return expr;}string _Body(string expr){int start = indexof(expr, "->");assert(start > 0 && start<expr.length-1, "'->' not found in lambda expression: " ~ expr);return expr;}string lambda(string expr){return"delegate " ~ _RetType(expr) ~ "(" ~ _ArgTypes(expr) ~ "){return (" ~_Body(expr) ~ ");}";}
它支持的lambda语法是这样的:
//参数列表 -> 表达式:int x -> xint x, int y -> x * y//返回值 | 参数列表 -> 表达式:string | int x -> toString(x)
测试:
T[] map(T,T1)(T1[] arr, T delegate(T1) dg){T[] result;result.length = arr.length;foreach(i, v; arr)result = dg(v);return result;}void main(){int[] arr = ;// int[] arr1 = arr.map(int x -> x * x);int[] arr1 = arr.map(mixin(lambda("int x -> x * x")));writefln(arr1);string sep = ";\n";string[] arr2 = arr.map(mixin(lambda("string | int x -> toString(x) ~ sep")));writefln(arr2);}
运行结果:
<div class="quote_title">引用
页: [1]
查看完整版本: lambda之路...