我试图理解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>
单独地,它们看起来很好(除了forOddOnly,它应该会因为偶数值而崩溃但是没有)
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的实现,因为它适用于所有Int in apply
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
这不会抛出异常 阶&GT; (new forOddOnly)(2) res67:Int = 2
小于100的打印值工作正常 阶&GT; val lessThan100:PartialFunction [Int,Unit] = {case d if d&lt; 100 =&gt; println(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 - 在下面的代码中,我使用'andThen'和forEvenOnly函数并且使用了lessthan100。对于大于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
问题代码。对于大于100的偶数值,isDefinedAt返回true但代码崩溃 阶&GT; 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 - 使用forThen和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)
答案 0 :(得分:1)
我认为这解决了问题1和问题3。
来自Standard Library scaladoc(强调添加):
来电者有责任之前致电
isDefinedAt
调用apply
,因为如果isDefinedAt
为false,则无法保证apply
将抛出异常以指示错误情况。如果 如果不抛出异常,评估可能会导致任意值。PartialFunction和scala.Function1之间的主要区别是 PartialFunction 的用户可以选择来执行某些操作 与声明在其域外的输入不同。
因此,在调用具有未定义的传递参数的PF时,不需要运行时异常。如果没有为该输入定义PF,则结果根本没有定义。
问题2的答案也可以在andThen()
的描述中的同一页上找到:
返回一个与相同域的部分函数作为此部分函数,它将参数x映射到k(this(x))。
如果您有val pfR = pfA andThen pfB
,那么pfR
将与pfA
具有相同的域。