soc*_*soc 21 java extension-methods closures language-design java-7
有人说每种编程语言都有其"复杂性预算",可用于实现其目的.但是,如果复杂性预算耗尽,每次微小变化都会变得越来越复杂,并且难以以向后兼容的方式实施.
从2010年8月开始阅读Lambda(≙Lambda表达式,异常透明度,防御方法和方法引用)的当前临时语法后,我想知道Oracle在考虑这些更改时是否完全忽略了Java的复杂性预算.
这些是我正在考虑的问题 - 其中一些更多是关于语言设计的:
谢谢!
我没有关注Java 7 lambda提案的流程和演变,我什至不确定最新的提案措辞是什么。将此视为咆哮/意见,而不是事实陈述。另外,我已经很久没有使用 Java 了,所以语法可能有些生疏和不正确。
首先,什么是 Java 语言的 lambda?语法糖。虽然一般来说 lambda 允许代码就地创建小型函数对象,但这种支持在某种程度上已经通过使用内部类在 Java 语言中预设了。
那么 lambda 的语法有多好呢?它在哪些方面优于以前的语言结构?哪里可以做得更好?
对于初学者来说,我不喜欢 lambda 函数有两种可用的语法(但这符合 C# 的行,所以我想我的观点并不广泛。我想如果我们想要糖衣,那么
#(int x)(x*x)比#(int x){ return x*x; }即使double 语法不会添加任何其他内容。我更喜欢第二种语法,它更通用,但需要额外的编写成本return和
;简短版本。
为了真正有用,lambda 可以从定义变量的范围和闭包中获取变量。与内部类一致,lambda 仅限于捕获“有效最终”变量。与该语言以前的功能保持一致是一个很好的功能,但为了甜蜜,最好能够捕获可以重新分配的变量。为此,他们正在考虑上下文中存在并用注释的变量将通过引用@Shared捕获,从而允许赋值。对我来说,这似乎很奇怪,因为 lambda 如何使用变量是在变量声明的位置而不是定义 lambda 的位置确定的。单个变量可以在多个 lambda 中使用,这会迫使所有变量具有相同的行为。
Lambda 尝试模拟实际的函数对象,但该提案并没有完全实现:为了保持解析器简单,因为到目前为止,标识符表示一个对象或一个已保持一致的方法,并且调用 lambda 需要!在lambda 名称:#(int x)(x*x)!(5)将返回25. 这为 lambda 带来了一种与该语言的其余部分不同的新语法,它在
某种程度上!代表了虚拟通用接口的同义词,但是,为什么不使其完整呢?.executeLambda<Result,Args...>
Lambda可以创建一个新的通用(虚拟)接口。它必须是虚拟的,因为接口不是真正的接口,而是一系列这样的接口:Lambda<Return>, Lambda<Return,Arg1>,
Lambda<Return,Arg1,Arg2>... 他们可以定义一个执行方法,我希望它像 C++ 一样operator(),但如果这是一个负担,那么任何其他名称都可以,将其!作为方法执行的快捷方式:
interface Lambda<R> {
R exec();
}
interface Lambda<R,A> {
R exec( A a );
}
Run Code Online (Sandbox Code Playgroud)
那么编译器只需要翻译identifier!(args)成
identifier.exec( args ),就很简单了。lambda 语法的翻译需要编译器识别正在实现的正确接口,并且可以匹配为:
#( int x )(x *x)
// translated to
new Lambda<int,int>{ int exec( int x ) { return x*x; } }
Run Code Online (Sandbox Code Playgroud)
这还允许用户定义在更复杂的情况下可用作 lambda 的内部类。例如,如果 lambda 函数需要捕获以@Shared只读方式注释的变量,或者在捕获位置维护捕获对象的状态,则可以手动实现 Lambda:
new Lambda<int,int>{ int value = context_value;
int exec( int x ) { return x * context_value; }
};
Run Code Online (Sandbox Code Playgroud)
其方式与当前内部类定义类似,因此对于当前 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.
Run Code Online (Sandbox Code Playgroud)
这将允许使用 lambda 和接受 lambda 的方法,既可以使用新的简单语法,#(int x){ return x*x; }也可以使用更复杂的手动方法来处理糖衣干扰预期语义的特定情况。
总的来说,我相信 lambda 提案可以在不同的方向上进行改进,它添加语法糖的方式是一种泄漏抽象(您已经在外部处理了 lambda 特有的问题),并且通过不提供较低级别的接口,它可以在不完全适合简单用例的用例中,使用户代码的可读性较差。:
| 归档时间: |
|
| 查看次数: |
1860 次 |
| 最近记录: |