【发布时间】:2017-03-30 23:43:17
【问题描述】:
我试图了解 orElse 和 andThen 是如何工作的,但是当与 orElse 和 andThen 一起使用时,“isDefinedAt”的行为是出乎意料的。在我的实现中, isDefinedAt 返回 true 但函数崩溃。这使得实现不可靠。我该如何解决这个问题?
我写了以下 3 个偏函数
PF1
// a function which is defined for even values only. Returns the value
scala> val forEvenOnly:PartialFunction[Int,Int] = {case d if ( (d % 2) == 0) => d}
forEvenOnly: PartialFunction[Int,Int] = <function1>
PF2
// a function which is defined for odd values only. Returns the value
//wanted to try an alternate syntax
scala> class forOddOnly extends PartialFunction[Int,Int] {
| def apply(x:Int) = x
| def isDefinedAt(x:Int) = (x % 2 !=0)
| }
defined class forOddOnly
PF3
//a function which prints a value if it is less than 100
scala> val lessThan100:PartialFunction[Int,Unit] = {case d if d<100 =>println(d)}
lessThan100: PartialFunction[Int,Unit] = <function1>
就个人而言,它们似乎工作得很好(除了 OddOnly 应该会在偶数值时崩溃但不会崩溃)
scala> val forEvenOnly:PartialFunction[Int,Int] = {case d if ( (d % 2) == 0) => d}
forEvenOnly: PartialFunction[Int,Int] = <function1>
scala> forEvenOnly(1)
scala.MatchError: 1 (of class java.lang.Integer)
scala> forEvenOnly(2)
res60: Int = 2
scala> forEvenOnly.isDefinedAt(1)
res61: Boolean = false
scala> forEvenOnly.isDefinedAt(2)
res62: Boolean = true
问题 1 - 在以下代码中,函数 forOddOnly 的行为有所不同。它不会因为偶数而崩溃,但我想要它。我需要使用“案例”来获得这种行为吗?我预计问题可能出在 forOddOnly 的实现中,因为它适用于 apply 中的所有 Int
scala> class forOddOnly extends PartialFunction[Int,Int] {
| def apply(x:Int) = x // I cannot change it to def apply(x:Int) = if (x % 2 != 0 ) x. This will not compile
| def isDefinedAt(x:Int) = (x % 2 !=0)
| }
defined class forOddOnly
scala> (new forOddOnly).isDefinedAt(1)
res64: Boolean = true
scala> (new forOddOnly).isDefinedAt(2)
res65: Boolean = false
scala> (new forOddOnly)(1)
res66: Int = 1
这不会引发异常 scala> (new forOddOnly)(2) res67: Int = 2
打印小于 100 的值可以正常工作 scala> val lessThan100:PartialFunction[Int,Unit] = {case d if dprintln(d)} lessThan100: PartialFunction[Int,Unit] =
scala> lessThan100(1)
1
scala> lessThan100(100)
scala.MatchError: 100 (of class java.lang.Integer)
scala> lessThan100.isDefinedAt(1)
res86: Boolean = true
scala> lessThan100.isDefinedAt(100)
res87: Boolean = false
问题2 - 在下面的代码中,我使用带有 forEvenOnly 函数和小于 100 的“andThen”。对于大于 100 的偶数值,isDefinedAt 返回 true,但传递 100 或更大的值会使代码崩溃。这使得调用 isDefinedAt 变得不可靠。为什么我会得到这个以及如何解决它? isDefinedAt 按预期对所有奇数值都有效(并且代码也崩溃是奇数值被传递)。如果我更改 forOddOnly 的实现并使用“case”,它可以工作,但我不能使用 apply 获得相同的行为吗?
scala> val printEvenLessThan100 = forEvenOnly andThen lessThan100
printEvenLessThan100: PartialFunction[Int,Unit] = <function1>
scala> printEvenLessThan100.isDefinedAt(1)
res88: Boolean = false
scala> printEvenLessThan100(1)
scala.MatchError: 1 (of class java.lang.Integer)
scala> printEvenLessThan100.isDefinedAt(2)
res89: Boolean = true
scala> printEvenLessThan100(2)
2
问题代码。 isDefinedAt 为大于 100 的偶数返回 true,但代码崩溃 scala> printEvenLessThan100.isDefinedAt(102) res94: Boolean = true
scala> printEvenLessThan100(102)
scala.MatchError: 102 (of class java.lang.Integer)
scala> printEvenLessThan100.isDefinedAt(101)
res91: Boolean = false
scala> lessThan100(101)
scala.MatchError: 101 (of class java.lang.Integer)
问题 3 - 将 andThen 与 forOddOnly 一起使用会导致大于 99 的值崩溃,但不会导致偶数值崩溃。我想我在所有这些例子中都犯了一些常见的错误
scala> val printOddLessThan100 = (new forOddOnly) andThen lessThan100
printOddLessThan100: PartialFunction[Int,Unit] = <function1>
scala> printOddLessThan100(1)
1
//does not crash
scala> printOddLessThan100(2)
2
scala> printOddLessThan100.isDefinedAt(100)
res102: Boolean = false
scala> printOddLessThan100(100)
scala.MatchError: 100 (of class java.lang.Integer)
scala> printOddLessThan100.isDefinedAt(101)
res97: Boolean = true
scala> printOddLessThan100(101)
scala.MatchError: 101 (of class java.lang.Integer)
当我使用 orElse 和 andThen 组合所有函数时,也会发生同样的情况
scala> val printIntLessThan100 = forEvenOnly orElse (new forOddOnly) andThen lessThan100
printIntLessThan100: PartialFunction[Int,Unit] = <function1>
scala> printIntLessThan100(1)
1
scala> printIntLessThan100(2)
2
//why does this return true when the code actually crashes
scala> printIntLessThan100.isDefinedAt(101)
res83: Boolean = true
scala> printIntLessThan100(101)
scala.MatchError: 100 (of class java.lang.Integer)
【问题讨论】:
标签: scala