加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

为什么用提取器替换我的Scala案例类会破坏我的高阶函数?

发布时间:2020-12-16 18:46:21 所属栏目:安全 来源:网络整理
导读:假设我有一个包装整数的简单case类,以及一个接受带有整数到包装器的函数的高阶方法. case class Wrapper(x :Int)def higherOrder(f : Int = Wrapper) = println(f(42)) 然后,我可以调用高阶函数,传入包装器生成的apply函数.令人惊讶的是,我也可以传递包装器
假设我有一个包装整数的简单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页)说

You could always start with case classes,and then,if the need arises,change to extractors. Because patterns over extractors and patterns over case classes look exactly the same in Scala,pattern matches in your clients will continue to work.

当然很正确,但如果他们使用案例类名称作为函数,我们将打破我们的客户.由于这样做可以实现强大的抽象,一些肯定会.

因此,当将它们传递给更高阶函数时,我们如何使提取器的行为与案例类相同?

解决方法

简单地说,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行为.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读