Scala有partial functions,它们是只适用于输入类型的某些值的函数,但不是全部:
val isEven: PartialFunction[Int, String] = {
case x if x % 2 == 0 => x+" is even"
}
assert(isEven(10) equalsIgnoreCase "10 is even")
assert(isEven.isDefinedAt(11) == false)
字符串
而且,更有用的是,scala允许将“partialness”应用于trait
的子类型:
sealed trait BaseTrait
case class Foo(i : Int) extends BaseTrait
case class Bar(s : String) extends BaseTrait
val fooPartialFunc : PartialFunction[BaseTrait, Int] = {
case f : Foo => 42 + f.i
}
assert(fooPartialFunc(Foo(8)) == 50)
assert(fooPartialFunc.isDefinedAt(Bar("hello")) == false)
型
Java 8中的等价物是什么?
大多数谷歌搜索结果混淆了“部分函数”和柯里化,例如“部分应用函数”。
3条答案
按热度按时间xsuvu9jc1#
一种Java 8惯用但不完全忠实的方法
Java 8中最典型的是Optional类:
字符串
如果你熟悉Optional,那么你会看到字符串连接
i + " is even"
只有在过滤条件i % 2 == 0
为true时才被计算。如果你不熟悉Java的Optional,你也可以用if/else
来写:型
这应该完全清楚,当且仅当保护条件计算为true时,才计算字符串串联。
一种更可靠但不那么惯用的方法(Java)
使用简单的方法,您调用函数,并获得一个Optional,它要么包含函数的实际值,要么不包含。但Scala的PartialFunction稍微复杂一点。从您链接到的文档中:
即使isDefinedAt为a:A返回true,调用apply(a)仍然可能抛出异常,因此以下代码是法律的:
型
因此,我们希望能够检查函数是否为输入“定义”,即使试图计算该输入是否实际上是错误的。
因此,更可靠的方法是使用
Optional<Supplier<...>>
。外部Optional
让您知道是否有计算要执行,内部Supplier
让您执行该计算(如果您选择)。因此示例将变为:型
或者,使用
if/else
:型
isPresent()
仍然会检查函数是否定义,但是get()
现在会返回Supplier
,它的get()
方法将实际计算值:型
gstyhher2#
Java似乎没有直接提供
PartialFunction
,但它提供了一些接口,你可以用它们来定义自己的PartialFunction<X,Y>
。PartialFunction<X, Y>
本质上就是:Predicate<X>
,用于测试X
类型的值是否在域中Function<X, Y>
用于实际调用的函数定义 * 如果 * 函数是为参数值定义的。下面,我简要介绍了如何使用
Predicate
和Function
来实现PartialFunction
。在这个草图中,我只定义了三个最重要的方法:isDefinedAt
本质上就是Predicate
stest
。apply
调用test
,如果成功,则调用applyIfDefined
,它表示“函数的实际主体”(Scala中case
s的右侧)orElse
演示了fallback-behavior的组合结构(与普通函数组合非常不同)以下是完整的Java代码:
字符串
上面例子的输出是:
型
如果你想使用它与某种“case类”,你也可以这样做,但为此,你必须首先提供一个case类的实现。
fcy6dtqo3#
Vavr为Java带来了很多Scala的好东西。
如果你同意第三方库,它可能是最好的选择。
字符串
更复杂的例子你可以找到here