Java 支持柯里化吗?
我想知道是否有任何方法可以在 Java 中实现这一点。我认为如果没有对闭包的原生支持,这是不可能的。
I was wondering if there is any way to pull that in Java. I think it is not possible without native support for closures.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(17)
Java 8(2014 年 3 月 18 日发布)确实支持柯里化。 missingfaktor 的答案中发布的示例 Java 代码可以重写为:
...这非常好。就我个人而言,随着 Java 8 的推出,我认为没有理由使用替代 JVM 语言,例如 Scala 或 Clojure。当然,它们提供其他语言功能,但这不足以证明过渡成本和较弱的 IDE/工具/库支持(IMO)的合理性。
Java 8 (released March 18th 2014) does support currying. The example Java code posted in the answer by missingfaktor can be rewritten as:
... which is quite nice. Personally, with Java 8 available I see little reason to use an alternative JVM language such as Scala or Clojure. They provide other language features, of course, but that's not enough to justify the transition cost and the weaker IDE/tooling/libraries support, IMO.
在 Java 中,柯里化和部分应用是绝对可能的,但所需的代码量可能会让您望而却步。
一些代码来演示 Java 中的柯里化和部分应用:
FWIW 这里是上面 Java 代码的 Haskell 等价物:
Currying and partial application is absolutely possible in Java, but the amount of code required will probably turn you off.
Some code to demonstrate currying and partial application in Java:
FWIW here is the Haskell equivalent of above Java code:
使用 Java 8 进行柯里化有很多选项。函数类型 Javaslang 和 jOOλ 都提供开箱即用的柯里化(我认为这是 JDK 中的一个疏忽),并且 独眼巨人 函数模块 有一组用于 Currying JDK 函数和方法引用的静态方法。例如,
消费者也可以使用“柯里化”。例如,要返回一个具有 3 个参数的方法,其中 2 个参数已应用,我们会执行类似的操作
Javadoc
There are a lot of options for Currying with Java 8. Function type Javaslang and jOOλ both offering Currying out of the box (I think this was an oversight in the JDK), and Cyclops Functions module has a set of static methods for Currying JDK Functions and method references. E.g.
'Currying' is also available for Consumers. E.g to return a method with 3 params, and 2 of those already applied we do something similar to this
Javadoc
编辑:从 2014 年和 Java 8 开始,Java 中的函数式编程现在不仅是可能的,而且也不难看(我敢说很漂亮)。例如,请参阅Rogerio 的回答。
旧答案:
如果您要使用函数式编程技术,Java 并不是最佳选择。正如 Missingfaktor 所写,您将不得不编写大量代码才能实现您想要的目标。
另一方面,您并不局限于 JVM 上的 Java - 您可以使用 Scala 或 Clojure 是函数式语言(事实上,Scala 既是函数式语言,又是面向对象语言)。
EDIT: As of 2014 and Java 8, functional programming in Java is now not only possible, but also not ugly (I dare to say beautiful). See for example Rogerio's answer.
Old answer:
Java isn't best choice, if you are going to use functional programming techniques. As missingfaktor wrote, you will have to write quite big amount of code to achieve what you want.
On the other hand, you are not restricted to Java on JVM - you can use Scala or Clojure which are functional languages (Scala is, in fact, both functional and OO).
柯里化需要返回一个函数。这对于 java 来说是不可能的(没有函数指针),但我们可以定义并返回一个包含函数方法的类型:
现在让我们柯里化一个简单的除法。我们需要一个Divider:
和一个DivideFunction:
现在我们可以进行柯里化除法:
Currying requires to return a function. This is not possible with java (no function pointers) but we can define and return a type that contains a function method:
Now let's curry a simple division. We need a Divider:
and a DivideFunction:
Now we can do a curried division:
可以使用 Java 7 MethodHandles 来模拟柯里化:
http://www.tutorials.de/threads/java- 7-currying-mit-methodhandles.392397/
One can emulate currying with Java 7 MethodHandles:
http://www.tutorials.de/threads/java-7-currying-mit-methodhandles.392397/
是的,请自行查看代码示例:
这是一个简单的示例,其中 curriedAdd 是一个返回另一个函数的柯里化函数,这可用于存储时参数的部分应用在柯里化中,它本身就是一个函数。当我们将其打印到屏幕上时,现在会完全应用这一点。
此外,稍后您可以看到如何以 JS 风格使用它,如下所示
Yes, see the code example for yourself:
This is simple example with curriedAdd being a curried function which returns another function, and this can be used for partial application of parameters as stored in curried which is a function in itself. This is now later applied fully when we print it on screen.
Moreover, later you can see how you can use it in kind of JS style as
嗯,Scala、Clojure 或 Haskell(或任何其他函数式编程语言...)绝对是用于柯里化和其他函数式技巧的语言。
话虽如此,当然可以使用 Java 进行柯里化,而无需人们所期望的大量样板文件(嗯,必须明确类型,但会造成很大伤害 - 只需看一下柯里化示例即可; -))。
下面的测试展示了这两种情况,将
Function3
柯里化到Function1 =>中。函数1 => Function1
:以及部分应用,尽管在本例中它并不是真正的类型安全:
这取自我刚刚在明天一小时内的 JavaOne 之前为了好玩而实现的概念验证”因为我很无聊”;-) 代码可以在这里找到:https://github.com/ktoso/jcurry
总体思路可以扩展为 FunctionN => FunctionM,相对容易,尽管“真正的类型安全”对于部分应用程序示例来说仍然是一个问题,并且柯里化示例将需要 jcurry 中的大量样板代码,但它是可行的。
总而言之,这是可行的,但在 Scala 中它是开箱即用的;-)
Well, Scala, Clojure or Haskell (or any other functional programming language...) are definitely THE languages to use for currying and other functional tricks.
Having that said is certainly possible to curry with Java without the super amounts of boilerplate one might expect (well, having to be explicit about the types hurts a lot though - just take a look at the
curried
example ;-)).The tests bellow showcase both, currying a
Function3
intoFunction1 => Function1 => Function1
:as well as partial application, although it's not really typesafe in this example:
This is taken from a Proof Of Concept I've just implemented for fun before JavaOne tomorrow in an hour "because I was bored" ;-) The code is available here: https://github.com/ktoso/jcurry
The general idea could be expanded to FunctionN => FunctionM, relatively easily, though "real typesafety" remains a problem for the partia application example and the currying example would need a hell lot of boilerplaty code in jcurry, but it's doable.
All in all, it's doable, yet in Scala it's out of the box ;-)
Java 8 的另一种可能性:
您还可以定义如下所示的实用方法:
这为您提供了一种可以说更易读的语法:
One more take on the Java 8 possibilities:
You can also define utility methods like this one:
Which gives you an arguably more readable syntax:
在 Java 中柯里化方法总是可能的,但它不以标准方式支持它。尝试实现这一点很复杂,并且使代码非常难以阅读。 Java 不是适合此目的的语言。
Currying a method is always possible in Java, but it does not support it in a standard way. Trying to achieve this is complicated and makes the code pretty unreadable. Java is not the appropriate language for this.
对于 Java 6+,还有另一种选择
,那么你可以通过这种方式实现柯里化
An another choice is here for Java 6+
then you could achieve currying by this way
虽然您可以在 Java 中进行柯里化,但它很丑陋(因为它不受支持)。在 Java 中,使用普通循环和简单表达式更简单、更快。如果您发布一个使用柯里化的示例,我们可以建议执行相同操作的替代方案。
While you can do Currying in Java, it is ugly (because its not supported) In Java is it simpler and faster to use plain loops and simple expressions. If you post an example of where you would use currying, we can suggest alternatives which do the same thing.
在 Java 8 中使用 Currying 的优点是,它允许您定义高阶函数,然后以链式、优雅的方式传递一阶函数和函数参数。
这是微积分(导数函数)的示例。
The advantage of using Currying in Java 8 is that it lets you define high order functions and then pass a first order function and function arguments in a chained, elegant way.
Here is an example for Calculus, the derivative function.
这是一个用于 Java 中柯里化和部分应用的库:
https://github.com/ Ahmed-Adel-Ismail/J-Curry
它还支持将 Tuple 和 Map.Entry 解构为方法参数,例如将 Map.Entry 传递给带有 2 个参数的方法,因此 Entry.getKey() 将转到第一个参数,Entry.getValue() 将转到第二个参数
更多详细信息请参见 README 文件
This is a library for currying and partial application in Java :
https://github.com/Ahmed-Adel-Ismail/J-Curry
It also supports destructuring Tuples and Map.Entry into method parameters, like for example passing a Map.Entry to a method that takes 2 parameters, so the Entry.getKey() will go to the first parameter, and the Entry.getValue() will go for the second parameter
More details in the README file
是的,我同意@Jérôme 的观点,Java 8 中的curring 不像Scala 或其他函数式编程语言那样以标准方式支持。
Yes, I agree with @Jérôme, curring in Java 8 is not supported in a standard way like in Scala or other functional programming languages.
虽然所有其他答案都集中在特定示例上,但我仍然想提供一个通用解决方案,将二进制函数转换为柯里化函数。
While all the other answers focus on specific examples, I still wanted to provide a general solution to turn binary functions into curried ones.