斯卡拉。当curried函数参数以不同方式实例化时,编译器失败

时间:2015-05-28 21:02:05

标签: scala dsl currying

我是Scala的新手,试图掌握DSL创作技巧。当 a)我直接实例化B类而 b)当我通过包装方法执行相同操作时,无法弄清楚为什么编译器在以下两种情况下表现不同值。

contains

1 个答案:

答案 0 :(得分:1)

你的第一个例子:

createA aMethod new B { s: String => }

可能会编译,但它没有按照您的期望进行。您实际上是在构建一个B实例,其自身类型为String(有关更多信息,请参阅thisthis)。然后,该语句的返回类型是一个Function,它将String的Function转换为Unit并返回Unit。更简单地说,您没有为函数aMethod提供参数p的值。

你在这三个例子中的问题只是一个语法问题。编译器真的很困惑,不知道你在哪里给它一个函数以及你在哪里扩展类。在这种情况下,我喜欢显式添加函数调用的句点和parens。现在,所有这三个都应该编译并执行您想要的操作:

createA.aMethod(new B) { s: String =>
}

createA.aMethod(createB){ s: String =>
}

val bb = new B
createA.aMethod(bb){ s: String =>
}

编辑: 通过直接调用适用于curried函数的替代方案,这可能是您最好的选择:

class A {
  def aMethod(b: B)(p: String => Unit): Unit = {}
}

def main(args: Array[String]) {
  createA aMethod new B apply { s: String =>
  }

  createA aMethod createB apply { s: String =>
  }

  val bb = new B
  createA aMethod bb apply { s: String =>
  }
}

如果你讨厌使用'apply',你也可以用你想要的任何名称构建一个对象:

class A {
  def aMethod(b: B) = new {
    def myCoolName(p: String => Unit): Unit = {}
  }
}

def main(args: Array[String]) {
  createA aMethod new B myCoolName { s: String =>
  }

  createA aMethod createB myCoolName { s: String =>
  }

  val bb = new B
  createA aMethod bb myCoolName { s: String =>
  }
}

另一种方法是使用方法而不是咖喱:

class A {
  def aMethodNotCurried(b: B, p: String => Unit): Unit = {}
}

def mainNotCurried(args: Array[String]) {
  createA aMethodNotCurried (new B, { s: String =>
  })

  createA aMethodNotCurried (createB, { s: String =>
  })

  val bb = new B
  createA aMethodNotCurried (bb, { s: String =>
  })
}