我有一个函数,在遗留代码中计算(字符串A,int B)
map.moveCamera(CameraUpdateFactory.newLatLngZoom(route.startLocation, 10));
在B上应用的计算取决于A的值。
在功能风格上,我可以将其分解为:
Double calculate(String A,int B) {
if(A.equals("something")){ return B*1.02; }
if(B.equals("some")) return B*1.0;
else return B;
}
然后我会打电话给<{p>,而不是打电话给Function<String, Function<Integer,Double>> strategyA = (a)-> {
if(A.equals("something")) return b -> b*1.02;
if(B.equals("some")) return b -> return b -> b*1.0;
else return b -> b;
}
calculate(a,b)
第二种风格是否优于第一种风格。根据我的理解,这涉及战略模式和功能分解和Currying。
如果第二种方法确实更好,你会如何说服某人?
答案 0 :(得分:3)
在Java中,提供命名代码的首选方法是保留方法。没有理由将方法表达为函数,只是为了具有“更多功能风格”。为什么函数支持被添加到Java中的原因是,您有时希望将对代码的引用传递给另一个方法或函数。在这种情况下,接收方法定义了所需的函数签名,而不是您要封装的代码。
因此,如果接收方法只想将ObjIntConsumer<String>
和String
对传递给它,那么您的int
方法可能会被称为(String,int) → Double
,而不会对此感兴趣结果。否则,它可能使用表示BiFunction<String,Integer,Double>
签名的自定义功能接口。或者当你接受拳击时,Function
会这样做。
Currying允许您重用现有的接口,如{{1}}来表示具有多个参数的函数,当没有内置接口时,但给定生成的通用签名,这将至少出现在Java代码中的一个位置使用这样的curried函数,可读性受到很大影响,因此在大多数情况下,在大多数情况下,定义一个新的功能界面将比curry更受欢迎......
对于其他编程语言,对函数类型使用不同的语法和类型推断(或者首先使用实际函数类型,而不是在函数接口上设置),这将是完全不同的。
答案 1 :(得分:2)
我同意Holger的观点,在大多数情况下,仅仅为了使用函数式编程而使用函数编写代码是没有意义的。函数只是一个额外的工具,可以让您以更好的方式编写代码,如集合处理。
然而,您的示例有一个有趣的事情,即您使用String
参数a
,然后执行一些计算然后返回另一个函数。如果第一个操作需要很长时间,这可能有时有用:
Function<String, Function<Integer,Double>> f = (a) -> {
if (some-long-computation(a)) return b -> b*1.02;
if (some-other-long-computation(a)) return b -> return b -> b*1.0;
else return b -> b;
}
当您使用f
参数调用String
时,该函数将运行some-long-computation
和some-other-long-computation
并返回所需的函数:
Function<Integer,Double> fast = f.apply("Some input"); // Slow
Double d1 = fast.apply(123); // Fast!
Double d1 = fast.apply(456); // Fast!
如果f
是普通方法,则将其称为f("Some input", 123)
两次,然后是
f("Some input", 456)
会慢一些,因为您需要运行两次昂贵的计算。当然,这是你可以在没有函数编程的情况下处理的东西,但它是一个返回函数实际上非常适合的地方。