我试图理解orElse和andhen是如何工作的但是当与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>
单独来说,它们看起来很好(除了forddOnly,它应该会因为偶数值而崩溃但是没有)
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
Question 1 - In following code, the function forOddOnly behaves differently. It doesnt crash for even values but I want it to. Do I need to use 'case' to get this behaviour? I anticipate that the problem could be in implementation of forOddOnly because it works for all 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
this doesn't throw exception scala>(new forOddOnly)(2)res67:Int = 2
打印值小于100工作精细scala> val lessThan100:PartialFunction [Int,Unit] = {case d如果d <100 => 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
Question2 - In following code, I use 'andThen' with forEvenOnly function and lessthan100. The isDefinedAt returns true for even values greater than 100 but passing the value of 100 or more crashes the code. This makes calling isDefinedAt unreliables. Why am I getting this and how to solve it? isDefinedAt works fine for all odd values as expected (and code also crashes is odd value is passed). If I change the implementation of forOddOnly and use 'case', it works but can't I get the same behaviour using 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
problem code. isDefinedAt returns true for even values greater than 100 but code crashes 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)
Question 3 - using andThen with forOddOnly crashes for values more than 99 but not for even values. I guess the there is some common mistake I am making in all these examples
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)
1 回答
我认为这解决了问题1和问题3 .
来自Standard Library scaladoc(重点补充):
因此,在调用具有未定义的传递参数的PF时,不需要运行时异常 . 如果没有为该输入定义PF,则根本不定义结果 .
问题2的答案也可以在
andThen()
的描述中的同一页面上找到:如果您有
val pfR = pfA andThen pfB
,则pfR
将与pfA
具有相同的域 .