by-names参数如何在高阶函数中起作用?

tib*_*bbe 6 scala

我试图理解名字类型注释在高阶函数的上下文中的含义.这是一个例子:

object Test { 
  def apply[A, B](f: (=> A) => B, x: => A): B = f(x) 
  def const[A](ignored: A): Int = 1
  val res: Int = apply(const, ???)
}
Run Code Online (Sandbox Code Playgroud)

const它的参数是严格的(即它缺少一个=>注释),那么为什么不强制它的参数(???在这种情况下是这样)并引发异常?

是否有一篇描述语义的论文?

我在这里寻找权威的答案.

0__*_*0__ 5

函数f中的参数apply是一个Funcion1采用类型的call-by-name参数A并返回一个B.因此,f(x)不会评估call-by-name参数x,而是直接将其引用传递给f.

理解res如下有助于:

def res[C]: Int = apply[C, Int](const, ???)
Run Code Online (Sandbox Code Playgroud)

您的示例中的哪个位置C是非特定类型.现在const在这一行推断出什么类型参数?是的=> C.很遗憾,您无法输入该参数:

def res[C]: Int = apply[C, Int](const[=> C], ???)  // illegal syntax
Run Code Online (Sandbox Code Playgroud)

但是你可以验证发生了什么:

def res[C]: Int = apply[C, Int](const[Nothing], ???)
Run Code Online (Sandbox Code Playgroud)

给你

<console>:10: error: type mismatch;
 found   : Nothing => Int
 required: => C => Int
         def res[C]: Int = apply[C, Int](const[Nothing], ???)
                                              ^
Run Code Online (Sandbox Code Playgroud)

此类型在内部显示constFunction0[Int](因此Scala隐式将call-by-name或"thunk"参数视为不带参数的函数).您可以再次验证这一点:

def const[A](ignored: A): Int = if (ignored.isInstanceOf[Function0[_]]) 1 else 0
Run Code Online (Sandbox Code Playgroud)

现在Test.res会给你1(意思ignored是确实是Function0).


所以以不同的方式回答这个问题,const有一个急切的类型参数A,但这并不重要,因为A在你的例子中成为一个函数,你永远不会应用该函数,因此???永远不会执行.


一些争论,以为什么既是一个"咚"或括号无功能和空括号功能(Function0)Scala中.