为什么用提取器替换我的Scala案例类会破坏我的高阶函数?
假设我有一个包装整数的简单case类,以及一个接受带有整数到包装器的函数的高阶方法.
case class Wrapper(x :Int) def higherOrder(f : Int => Wrapper) = println(f(42)) 然后,我可以调用高阶函数,传入包装器生成的apply函数.令人惊讶的是,我也可以传递包装器的名称. higherOrder(Wrapper.apply) // okay higherOrder(Wrapper) // okay,wow! 这真的很酷.它允许我们将case类的名称视为一个函数,它可以促进表达式抽象.有关这种凉爽的一个例子,请参阅这里的答案. What does “abstract over” mean? 现在假设我的case类不够强大,我需要创建一个提取器.作为一个有点人为的用例,假设我需要能够对解析为整数的字符串进行模式匹配. // Replace Wrapper case class with an extractor object Wrapper { def apply(x :Int) = new Wrapper(x) def unapply(s :String) :Option[Wrapper] = { // details elided } } class Wrapper(x :Int) { override def toString = "Wrapper(" + x + ")" // other methods elided } 在这个变化下,我仍然可以将Wrapper.apply传递给我的高阶函数,但是传入Wrapper不再有效. higherOrder(Wrapper.apply) // still okay higherOrder(Wrapper) // DOES NOT COMPILE ^^^^^^^ // type mismatch; found : Wrapper.type (with underlying type Wrapper) // required: (Int) => Wrapper 哎哟!这就是为什么这种不对称令人不安的原因. Odersky,Spoon和Venners的建议(Scala编程,第500页)说
当然很正确,但如果他们使用案例类名称作为函数,我们将打破我们的客户.由于这样做可以实现强大的抽象,一些肯定会. 因此,当将它们传递给更高阶函数时,我们如何使提取器的行为与案例类相同? 解决方法
简单地说,Wrapper(对象)不是一个Function,它只是一个带有apply方法的对象.这与对象也是一个提取器完全无关.
试试这个: class Wrapper(val x: Int) { override def toString = "Wrapper(" + x + ")" // other methods elided } object Wrapper extends (Int => Wrapper) { def apply(x: Int) = new Wrapper(x) def unapply(w: Wrapper): Option[Int] = Some(w.x) } def higherOrder(f: Int => Wrapper) = println( f(42) ) 我还将参数设置为Wrapper并在参数中交换并在unapply定义中返回值,以便它匹配case-class行为. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |