【问题标题】:Scala implicit conversion misleadingScala隐式转换误导
【发布时间】:2019-11-25 15:58:08
【问题描述】:

我对下面的 scala'a 隐式转换代码块有点困惑。

object Run {
   implicit class IntTimes(x: Int) {
      def times [A](f: =>A): Unit = {  //Definition
         def loop(current: Int): Unit =

         if(current > 0){
            f
            loop(current - 1)
         }
         loop(x)
      }
   }
}

object Demo {
   def main(args: Array[String]) {
      4 times println("hello")     //Call
   }
}

如果我们看一下“times”方法定义,它接受一个函数参数 -> 不接受任何输入并返回 A 作为输出。但是在“times”的调用中,函数 println 被传递,它接受一个字符串(“hello”)作为 i/p 并且什么都不返回(Unit)。

这与定义正好相反。但这按预期工作。这是如何工作的?

【问题讨论】:

  • println("hello") 不是函数。是一个符合=> Unit 类型的表达式,因此它是times 方法 的有效值。另外,=> A 并不意味着它需要一个函数,它需要一个by name parameter
  • 感谢您的回复。实际上,从一本 Scala 书籍中,我得到了理解。我在下面的评论中提供了更多详细信息。
  • 抱歉回复晚了,here你可以检查它是否按照我的解释工作。

标签: scala implicit-conversion


【解决方案1】:
def times [A](f: =>A): Unit = {  //Definition

在此声明中,f 不是函数参数,而是 按名称 参数。这意味着每次需要f 的值时,都会对传入f 的表达式求值。

在示例中,表达式为 println("hello"),因此计算了 4 次。

【讨论】:

  • 感谢您的回复!实际上,我正在关注 Scala 书中的编程 - 第 2 版(由 Martin Odersky 撰写)。在第 9 章(控制抽象)中,在 -218 和 219 页,给出了:“def myAssert(predicate: () => Boolean)”可以替换为:“def byNameAssert(predicate: => Boolean)” I已单独给出方法签名以供快速参考。
  • 如果我们看这本书,“def times [A](f: =>A)”可以解释为“def times [A](f: () => A)” 所以理想情况下,将 println("hello") 传递给 times 方法应该抛出类型不匹配错误,因为 String 参数作为输入(不应该传递任何内容)。我在这里错过了一些关键点吗?如果您需要更多信息,请告诉我。谢谢!
  • 看起来“可以替换”的意思是“可以以不同的方式实现”而不是“等同于”。不管书上说什么,两者并不等价,如果将times 的签名更改为(f: () => A),它将无法编译。
  • 完全正确!感谢蒂姆的解释。总结一下:“def myAssert(predicate: () => Boolean)”不等于“def byNameAssert(predicate: => Boolean)”。
  • 您可以接受它以表明它已经回答了您的问题。
猜你喜欢
  • 1970-01-01
  • 2012-04-15
  • 2018-09-16
  • 2011-09-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多