LINQ语法糖

qiezi 2007-05-04
LINQ语法挺诱人的,不过基本上也就是语法糖了,目前的新一代语言都把语法糖作为重点。

D里面简单试验了一下,参考了 http://msdn2.microsoft.com/en-us/library/aa479865.aspx 第一个例子,排序没有实现:

import std.stdio;
import std.string : toupper;

T[] where(T)(T[] s, bool delegate(T) dg) {
	T[] result;
	foreach(i; s)
		if (dg(i))
			result ~= i;
	return result;
}

T[] orderby(T)(T[] s, int delegate(T,T) dg) {
	return s;
}

T[] select(T)(T[] s, T delegate(T) dg) {
	T[] result;
	foreach(i; s)
		result ~= dg(i);
	return result;
}

void main() {
    char[][] names = [ "Burke", "Connor", "Frank", 
                       "Everett", "Albert", "George", 
                       "Harris", "David" ];

    char[][] result = names .where((char[] s){return s.length == 5;})
                            .orderby((char[] s1, char[] s2){ return -1; })
                            .select((char[] s){ return s.toupper(); });
	
    foreach(name; result)
        writefln(name);
}

输出:
引用

BURKE
FRANK
DAVID

排序没有实现。
qiezi 2007-05-04
第3个例子:
http://msdn2.microsoft.com/en-us/library/aa479865.aspx#linqprojec_topic3
import std.stdio;
import std.string : toupper;

T[] where(T)(T[] s, bool delegate(T) dg) {
	T[] result;
	foreach(i; s)
		if (dg(i))
			result ~= i;
	return result;
}

T[] orderby(T)(T[] s, int delegate(T,T) dg) {
	return s;
}

T[] select(T)(T[] s, T delegate(T) dg) {
	T[] result;
	foreach(i; s)
		result ~= dg(i);
	return result;
}

void main() {
    char[][] names = [ "Burke", "Connor", "Frank", 
                       "Everett", "Albert", "George", 
                       "Harris", "David" ];
	
	bool filter(char[] s) {
		return s.length == 5;
	}

	int sortfunc(char[] s1, char[] s2) {
		return -1;
	}

	char[] project(char[] s) {
		return s.toupper();
	}

	char[][] result = names .where(&filter)
							.orderby(&sortfunc)
							.select(&project);
	
	foreach(name; result)
		writefln(name);
}

输出:
引用

BURKE
FRANK
DAVID

排序没有实现。
qiezi 2007-05-04
可以看到LINQ里面的实现和我这里很相似,它能做到如此简洁归功于它的lambda表达式和松散的函数调用形式。

D目前的函数直接量语法已经精简了许多,但还没有精简到这种程度。
oldrev 2007-05-04
如果允许像ruby一样当函数有参数时还能省略括号就能达到linq的效果了。

我感觉用mixin还可以简化一下:


char[][] result = names .where("s.length == 5")  
        .orderby("-1")  
        .select("s.toupper");  

qiezi 2007-05-04
嗯,不过也不是特别好看亚,会影响编译时错误输出,还是从语言层面上解决比较好。
qiezi 2007-05-04
又做了个groupby:
import std.stdio;

T[][I] groupby(T,I)(T[] s, I delegate(T) dg) {
	T[][I] result;
	foreach(item; s) {
		I i = dg(item);
		result[i] ~= item;
	}
	return result;
}

void main() {
    char[][] names = [ "Burke", "Connor", "Frank", 
                       "Everett", "Albert", "George", 
                       "Harris", "David" ];

	char[][][uint] result = names .groupby((char[] s){return s.length;});
	
	foreach(length, names; result) {
		writefln("Strings of length ", length);
		foreach(name; names)
			writefln(name);
	}
}

输出:
引用

Strings of length 5
Burke
Frank
David
Strings of length 6
Connor
Albert
George
Harris
Strings of length 7
Everett
qiezi 2007-05-04
Sum:

import std.stdio;

I sum(T,I)(T[] s, I delegate(T) dg) {
	I result;
	foreach(i; s)
		result += dg(i);
	return result;
}

T sum(T)(T[] s) {
	T result;
	foreach(i; s)
		result += i;
	return result;
}

void main() {
    char[][] names = [ "Burke", "Connor", "Frank", 
                       "Everett", "Albert", "George", 
                       "Harris", "David" ];

	int totalLength = names .sum((char[] s){return s.length;});
	
	writefln("Total length: ", totalLength);

	int[] arr = [1,2,3,4,5];

	writefln("Sum: ", arr.sum());
}

输出:
引用

Total length: 46
Sum: 15

好像到后面就不再是那种第一眼看到的LINQ语法啦,不过那个文档里就是这么写的,我模仿一下而已。。。感觉这不就是FP,或者是ruby的block换了件马甲就出来了?

不过LINQ是针对泛型接口来实现的,应用比较广,我这里仅适合数组。
DavidL 2007-05-05
相当有意思!像个SQL,不过其实SQL的语法并不好用
Global site tag (gtag.js) - Google Analytics