帮助理解Java中的函数对象或函子 [英] Help with understanding a function object or functor in Java

查看:103
本文介绍了帮助理解Java中的函数对象或函子的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有人能解释一下仿函数是什么并提供一个简单的例子吗?

Can someone explain what a functor is and provide a simple example?

推荐答案

功能对象就是这样。既是对象又是函数的东西。

A function object is just that. Something which is both an object and a function.

除此之外:将函数对象称为仿函数是对术语的严重滥用:一种不同的仿函数是数学中的核心概念,在计算机科学中具有直接作用(参见Haskell Functors)。这个术语在ML中的使用方式略有不同,所以除非你用Java实现其中一个概念(你可以!),请停止使用这个术语。它使简单的事情变得复杂。

Aside: calling a function object a "functor" is a serious abuse of the term: a different kind of "functors" are a central concept in mathematics, and one that has a direct role in computer science (see "Haskell Functors"). The term is also used in a slightly different way in ML, so unless you are implementing one of these concepts in Java (which you can!) please stop using this terminology. It makes simple things complicated.

回到答案:
Java没有第一类函数,也就是说,你不能传递一个函数作为函数的参数。这在语法代码表示的多个层次上都是正确的,并且类型系统缺少函数构造函数

Back to the answer: Java does not have "first class functions" that is to say, you can not pass a function as an argument to a function. This true at multiple levels, syntactically, in the byte code representation, and in that the type system lacks the "function constructor"

换句话说,你不能写类似这样的事情:

In other words, you can't write something like this:

 public static void tentimes(Function f){
    for(int i = 0; i < 10; i++)
       f();
 }
 ...
 public static void main{
    ...
    tentimes(System.out.println("hello"));
    ...
 }

这真烦人,因为我们想要能够执行诸如图形用户界面库之类的操作,您可以将回调功能与单击按钮相关联。

This is really annoying, since we want to be able to do things like have Graphical User Interface libraries where you can associate a "callback" function with clicking on a button.

那我们该怎么办?

嗯,一般解决方案(由其他海报讨论)是使用我们可以调用的单个方法定义接口。例如,Java一直使用一个名为 Runnable 的接口,它看起来像:

Well, the general solution (discussed by the other posters) is to define an interface with a single method that we can call. For example, Java uses an interface called Runnable for these kinds of things all the time, it looks like:

public interface Runnable{
    public void run();
}

现在,我们可以从上面重写我的例子:

now, we can rewrite my example from above:

public static void tentimes(Runnable r){
    for(int i = 0; i < 10; i++)
       r.run();
}
...
public class PrintHello implements Runnable{
    public void run{
       System.out.println("hello")
    }
}
---
public static void main{
    ...
    tentimes(new PrintHello());
    ...
 }

显然,这个例子是人为的。我们可以使用匿名内部类使这个代码更好一点,但这得到了一般的想法。

Obviously, this example is contrived. We could make this code a little bit nicer using anonymous inner classes, but this gets the general idea.

这是故障的地方: Runnable 仅适用于不带任何参数的函数,并且不返回任何有用的函数,因此最终为每个作业定义一个新接口。例如,Mohammad Faisal的答案中的接口 Comparator 。提供更通用的方法,以及采用语法的方法,是Java 8(Java的下一个版本)的主要目标,并且被大量推送到Java 7中。这在函数抽象机制之后称为lambda在Lambda微积分中。 Lambda Calculus(也许)是最古老的编程语言,也是计算机科学的理论基础。当Alonzo Church(计算机科学的主要创始人之一)发明它时,他使用希腊字母lambda作为函数,因此得名。

Here is where this breaks down: Runnable is only usable for functions that don't take any arguments, and don't return anything useful, so you end up defining a new interface for each job. For example, the interface Comparator in Mohammad Faisal's answer. Providing a more general approach, and one that takes syntax, is a major goal for Java 8 (The next version of Java), and was heavily pushed to be included in Java 7. This is called a "lambda" after the function abstraction mechanism in the Lambda Calculus. Lambda Calculus is both (perhaps) the oldest programming language, and the theoretical basis of much of Computer Science. When Alonzo Church (one of the main founders of computer science) invented it, he used the Greek letter lambda for functions, hence the name.

其他语言,包括函数式语言(Lisp,ML,Haskell,Erlang等),大多数主要动态语言(Python,Ruby,JavaScript等)和其他应用程序语言(C#,Scala,Go,D等)支持某种形式的Lambda Literal。即使C ++现在也有它们(从C ++ 11开始),虽然在这种情况下它们有点复杂,因为C ++缺乏自动内存管理,并且不会为你保存堆栈帧。

Other languages, including the functional language (Lisp, ML, Haskell, Erlang, etc), most of the major dynamic languages (Python, Ruby, JavaScript, etc) and the other application languages (C#, Scala, Go, D, etc) support some form of "Lambda Literal." Even C++ has them now (since C++11), although in that case they are somewhat more complicated because C++ lacks automatic memory management, and won't save your stack frame for you.

这篇关于帮助理解Java中的函数对象或函子的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆