Java 迭代函数

Java 迭代函数,java,function-pointers,functor,Java,Function Pointers,Functor,在Java中可以做类似的事情吗 for (Object o : objects) { for (Function f : functions) { f(o); } } 我只调用了一小部分函数,但我需要编写它们,如下所示: for (Object o : objects) { for (Function f : functions) { for (Function g : functions) { f(g(o)); } } } 我希望避免写出

在Java中可以做类似的事情吗

for (Object o : objects) {
  for (Function f : functions) {
    f(o);
  }
}
我只调用了一小部分函数,但我需要编写它们,如下所示:

for (Object o : objects) {
  for (Function f : functions) {
    for (Function g : functions) {
      f(g(o));
    }
  }
}
我希望避免写出数百行函数调用

我试着研究函数指针和函子,但没有找到任何相关的东西。

你不能使用
f(g(o))
语法,但你可以使用(有合适的接口)
f.call(g.call(o))

(为了简洁起见,例外消息被省略了。显然,我会将它们放在生产代码中。)

示例用法:

MathUnary[] ops = {
    new MathUnary("sin"), new MathUnary("cos"), new MathUnary("tan")
};

for (UnaryFunction<Double, Double> op1 : ops) {
    for (UnaryFunction<Double, Double> op2 : ops) {
        op1.call(op2.call(arg));
    }
}
MathUnary[]ops={
新数学(“sin”)、新数学(“cos”)、新数学(“tan”)
};
for(一元函数op1:ops){
for(一元函数op2:ops){
op1.call(op2.call(arg));
}
}

也许你可以尝试一种能让你把这些联系在一起的方法。这可能是一个很好的设计,但我无法从您的示例中看出。

Java实际上并不完全执行函子,但您可以非常接近接口。我想试试这样的东西

public interface Function {
    Object doWork(Object o);
}

public class Function1 implements Function {
    public Object doWork(Object o) {
        ...
    }
}

...
然后在代码中创建一个数组或列表,其中包含函数1、函数2。。。对象并运行与您的代码非常相似的东西

for (Object o : objects) {
      for (Function f : functionList) {
          f.doWork(o);
      }
}
或者,对于两个嵌套级别:

for (Object o : objects) {
      for (Function f : functionList1) {
            for (Function g : functionList2) {
                f.doWork(g.doWork(o));
            }
      }
}
@Seth——这是您的泛型示例。由于泛型在运行时不存在,我不理解为什么您担心失去“灵活性”。如果您使用泛型,那么您只是在使用对象

如果希望F的行为根据G的返回类型而变化,那么只需声明F执行类似于F的操作,easy peasy

//=== Function.java

public interface Function<ReturnType, Type> {
    ReturnType doWork(Type arg);
}

//=== SomethingWeird.java

import java.util.*;

// yo dawg, i heard you liked functions.  so i put a function in yo'
// function, so you can derive while you derive.
public class SomethingWeird {
    public static <FReturnType, FType, GType> List<FReturnType> collateOrSomething(
        Iterable<GType> objects,
        Iterable<Function<FReturnType, FType>> fList,
        Iterable<Function<FType, GType>> gList
    ) {
        List<FReturnType> results = new ArrayList<FReturnType>();
        for (GType garg : objects) {
            for (Function<FReturnType, FType> f : fList) {
                for (Function<FType, GType> g : gList) {
                    results.add(f.doWork(g.doWork(garg)));
                }
            }
        }
        return results;
    }
}

//=== SomethingWeirdTest.java

import java.util.*;

import org.junit.*;
import static org.junit.Assert.*;

public class SomethingWeirdTest {
    // this is kinda silly, and...
    public static class F1 implements Function<Integer, Double> {
        @Override
        public Integer doWork(Double arg) {
            return arg.intValue();
        }

    }

    // ...this has all kinds of autoboxing madness, but...
    public static class F2 implements Function<Integer, Double> {
        @Override
        public Integer doWork(Double arg) {
            double ceil = Math.ceil(arg);
            return (int) ceil;
        }       
    }


    // ...why you'd want to do something like this is quite beyond me...
    public static class G1 implements Function<Double, String> {
        @Override
        public Double doWork(String arg) {
            return Math.PI * arg.length();
        }
    }

    // ...ditto this...
    public static class G2 implements Function<Double, String> {
        @Override
        public Double doWork(String arg) {
            return Math.E * arg.length();
        }

    }

    // oh, yeah, it was so we could test this weird thing
    @Test
    public void testCollateOrSomething() {
        List<String> data = Arrays.asList("x", "xx", "xxx");
        List<Function<Integer, Double>> fList = Arrays.asList(new F1(), new F2());
        List<Function<Double, String>> gList = Arrays.asList(new G1(), new G2());
        List<Integer> results = SomethingWeird.collateOrSomething(data, fList, gList);

        assertEquals(12, results.size());

        // x
        assertEquals(3, (int) results.get(0));
        assertEquals(2, (int) results.get(1));
        assertEquals(4, (int) results.get(2));
        assertEquals(3, (int) results.get(3));

        // xx
        assertEquals(6, (int) results.get(4));
        assertEquals(5, (int) results.get(5));
        assertEquals(7, (int) results.get(6));
        assertEquals(6, (int) results.get(7));

        // xxx
        assertEquals(9, (int) results.get(8));
        assertEquals(8, (int) results.get(9));
        assertEquals(10, (int) results.get(10));
        assertEquals(9, (int) results.get(11));
    }
}
/==Function.java
公共接口功能{
返回式定位销(arg型);
}
//==SomethingWeird.java
导入java.util.*;
//老兄,我听说你喜欢函数。所以我在yo's中加入了一个函数
//函数,因此可以在派生时进行派生。
公共课有点奇怪{
公共静态列表比较程序(
可拆卸物体,
易飞的飞人,
易变闪光
) {
列表结果=新建ArrayList();
对于(GType garg:objects){
for(函数f:fList){
for(功能g:gList){
结果:添加(f.doWork(g.doWork(garg));
}
}
}
返回结果;
}
}
//==SomethingWeirdTest.java
导入java.util.*;
导入org.junit.*;
导入静态org.junit.Assert.*;
公共类一些奇怪的测试{
//这有点傻,而且。。。
公共静态类F1实现函数{
@凌驾
公共整数doWork(双参数){
返回arg.intValue();
}
}
//…这有各种各样的自动装箱疯狂,但是。。。
公共静态类F2实现函数{
@凌驾
公共整数doWork(双参数){
double-ceil=Math.ceil(arg);
返回(int)ceil;
}       
}
//…你为什么要做这样的事我完全不懂。。。
公共静态类G1实现函数{
@凌驾
公共双道具(字符串arg){
返回Math.PI*arg.length();
}
}
//……这也是。。。
公共静态类G2实现函数{
@凌驾
公共双道具(字符串arg){
返回Math.E*arg.length();
}
}
//哦,是的,这样我们就可以测试这个奇怪的东西了
@试验
公共无效测试抵押物某物(){
列表数据=数组。asList(“x”、“xx”、“xxx”);
List fList=Arrays.asList(新的F1(),新的F2());
List gList=Arrays.asList(新的G1(),新的G2());
列出结果=一些奇怪的东西。对照物(数据、列表、gList);
assertEquals(12,results.size());
//x
assertEquals(3,(int)results.get(0));
assertEquals(2,(int)results.get(1));
assertEquals(4,(int)results.get(2));
assertEquals(3,(int)results.get(3));
//xx
assertEquals(6,(int)results.get(4));
assertEquals(5,(int)results.get(5));
assertEquals(7,(int)results.get(6));
assertEquals(6,(int)results.get(7));
//xxx
assertEquals(9,(int)results.get(8));
assertEquals(8,(int)results.get(9));
assertEquals(10,(int)results.get(10));
assertEquals(9,(int)results.get(11));
}
}

在外部循环的对象上调用由内部循环组成的函数:f(g(o))Oops,错过了参数。对不起,泛型当然有效(毫无疑问)。但是,如果一切都是对象,那么在运行时您会有更大的灵活性吗?对于具有泛型的解决方案,如上面带有双精度的解决方案,基本上必须使g的返回值始终与f的参数相匹配。对于普通的旧对象,f的逻辑可以根据g的返回类型而有所不同。FunctionalJava库()已经为这种场景拼凑了一组包装类(在本例中是一组具有不同类型arity的泛型类)。哇。Functional Java的设计显然考虑到了代码高尔夫(或模糊处理:-P)…包名
fj
,函数类型
F
,方法名为
F
。我喜欢图书馆背后的想法,但我不会选择那些名字-P
for (Object o : objects) {
      for (Function f : functionList) {
          f.doWork(o);
      }
}
for (Object o : objects) {
      for (Function f : functionList1) {
            for (Function g : functionList2) {
                f.doWork(g.doWork(o));
            }
      }
}
//=== Function.java

public interface Function<ReturnType, Type> {
    ReturnType doWork(Type arg);
}

//=== SomethingWeird.java

import java.util.*;

// yo dawg, i heard you liked functions.  so i put a function in yo'
// function, so you can derive while you derive.
public class SomethingWeird {
    public static <FReturnType, FType, GType> List<FReturnType> collateOrSomething(
        Iterable<GType> objects,
        Iterable<Function<FReturnType, FType>> fList,
        Iterable<Function<FType, GType>> gList
    ) {
        List<FReturnType> results = new ArrayList<FReturnType>();
        for (GType garg : objects) {
            for (Function<FReturnType, FType> f : fList) {
                for (Function<FType, GType> g : gList) {
                    results.add(f.doWork(g.doWork(garg)));
                }
            }
        }
        return results;
    }
}

//=== SomethingWeirdTest.java

import java.util.*;

import org.junit.*;
import static org.junit.Assert.*;

public class SomethingWeirdTest {
    // this is kinda silly, and...
    public static class F1 implements Function<Integer, Double> {
        @Override
        public Integer doWork(Double arg) {
            return arg.intValue();
        }

    }

    // ...this has all kinds of autoboxing madness, but...
    public static class F2 implements Function<Integer, Double> {
        @Override
        public Integer doWork(Double arg) {
            double ceil = Math.ceil(arg);
            return (int) ceil;
        }       
    }


    // ...why you'd want to do something like this is quite beyond me...
    public static class G1 implements Function<Double, String> {
        @Override
        public Double doWork(String arg) {
            return Math.PI * arg.length();
        }
    }

    // ...ditto this...
    public static class G2 implements Function<Double, String> {
        @Override
        public Double doWork(String arg) {
            return Math.E * arg.length();
        }

    }

    // oh, yeah, it was so we could test this weird thing
    @Test
    public void testCollateOrSomething() {
        List<String> data = Arrays.asList("x", "xx", "xxx");
        List<Function<Integer, Double>> fList = Arrays.asList(new F1(), new F2());
        List<Function<Double, String>> gList = Arrays.asList(new G1(), new G2());
        List<Integer> results = SomethingWeird.collateOrSomething(data, fList, gList);

        assertEquals(12, results.size());

        // x
        assertEquals(3, (int) results.get(0));
        assertEquals(2, (int) results.get(1));
        assertEquals(4, (int) results.get(2));
        assertEquals(3, (int) results.get(3));

        // xx
        assertEquals(6, (int) results.get(4));
        assertEquals(5, (int) results.get(5));
        assertEquals(7, (int) results.get(6));
        assertEquals(6, (int) results.get(7));

        // xxx
        assertEquals(9, (int) results.get(8));
        assertEquals(8, (int) results.get(9));
        assertEquals(10, (int) results.get(10));
        assertEquals(9, (int) results.get(11));
    }
}