我没有遵循Java 7 lambda提案的过程和发展,我甚至不确定最新的提案措辞是什么。将此视为咆哮/意见,而不是真理的陈述。另外,我已经很久没有使用Java了,所以语法可能有些生锈,而且不正确。
首先,Java语言的lambdas是什么?句法糖。虽然一般来说,lambda使代码能够就地创建小的函数对象,但这种支持已经通过使用内部类在Java语言中预设了 - 在某种程度上。
那么 lambdas 的语法有多好呢?它的性能在哪些方面优于以前的语言结构?哪里可以更好?
对于初学者来说,我不喜欢lambda函数有两种可用语法的事实(但这符合C#的行,所以我想我的观点并不普遍。我想如果我们想糖衣,那么比即使双语法不添加任何其他内容也更甜。我更喜欢第二种语法,更通用,但需要额外的写作成本和简短的版本。#(int x)(x*x)
#(int x){ return x*x; }
return
;
为了真正有用,lambdas可以从定义变量的范围和闭包中获取变量。为了与内部类保持一致,lambdas仅限于捕获“有效的最终”变量。与该语言先前功能的一致性是一个不错的功能,但为了甜蜜起见,能够捕获可以重新分配的变量会很好。为此,他们正在考虑通过引用捕获上下文中存在并带有注释的变量,从而允许赋值。对我来说,这似乎很奇怪,因为lambda如何使用变量是在变量的声明位置而不是在定义lambda的位置确定的。单个变量可以在多个 lambda 中使用,这会强制它们在所有 lambda 中具有相同的行为。@Shared
Lambdas尝试模拟实际的函数对象,但建议并没有完全实现:保持解析器的简单性,因为到目前为止,标识符表示一个对象或一个保持一致的方法,调用lambda需要使用lambda名称后面的a:将返回。这带来了一种新的语法,用于与语言其他部分不同的lambda,其中以某种方式作为虚拟通用接口上的同义词,但是,为什么不让它完整呢?!
#(int x)(x*x)!(5)
25
!
.execute
Lambda<Result,Args...>
可以创建新的通用(虚拟)接口。它必须是虚拟的,因为接口不是一个真正的接口,而是一个这样的系列:,,...他们可以定义一个单一的执行方法,我希望像C++一样,但如果这是一个负担,那么任何其他名称都可以,将 the 作为方法执行的快捷方式:Lambda
Lambda<Return>
Lambda<Return,Arg1>
Lambda<Return,Arg1,Arg2>
operator()
!
interface Lambda<R> {
R exec();
}
interface Lambda<R,A> {
R exec( A a );
}
然后编译器只需要翻译成 ,这很简单。lambda 语法的转换将要求编译器识别正在实现的正确接口,并且可以匹配为:identifier!(args)
identifier.exec( args )
#( int x )(x *x)
// translated to
new Lambda<int,int>{ int exec( int x ) { return x*x; } }
这也将允许用户定义在更复杂的情况下可以用作lambda的内部类。例如,如果 lambda 函数需要捕获以只读方式注释的变量,或者在捕获位置维护捕获对象的状态,则可以手动实现 Lambda:@Shared
new Lambda<int,int>{ int value = context_value;
int exec( int x ) { return x * context_value; }
};
其方式类似于当前的内部类定义,因此对于当前的Java用户来说是自然的。例如,这可以在循环中用于生成乘数 lambda:
Lambda<int,int> array[10] = new Lambda<int,int>[10]();
for (int i = 0; i < 10; ++i ) {
array[i] = new Lambda<int,int>{ final int multiplier = i;
int exec( int x ) { return x * multiplier; }
};
}
// note this is disallowed in the current proposal, as `i` is
// not effectively final and as such cannot be 'captured'. Also
// if `i` was marked @Shared, then all the lambdas would share
// the same `i` as the loop and thus would produce the same
// result: multiply by 10 --probably quite unexpectedly.
//
// I am aware that this can be rewritten as:
// for (int ii = 0; ii < 10; ++ii ) { final int i = ii; ...
//
// but that is not simplifying the system, just pushing the
// complexity outside of the lambda.
这将允许使用lambdas和接受lambda的方法,这两者都使用新的简单语法:或者对于糖衣干扰预期语义的特定情况,使用更复杂的手动方法。#(int x){ return x*x; }
总的来说,我相信lambda提案可以在不同的方向上进行改进,它添加语法糖的方式是一个泄漏的抽象(你已经在外部处理了lambda特有的问题),并且通过不提供较低级别的接口,它使用户代码在不完全适合简单用例的用例中可读性降低。: