Java 迭代函数
在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)); } } } 我希望避免写出
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));
}
}