Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala 关于“按名称调用”函数与“0-arity”函数区别的几个问题_Scala - Fatal编程技术网

Scala 关于“按名称调用”函数与“0-arity”函数区别的几个问题

Scala 关于“按名称调用”函数与“0-arity”函数区别的几个问题,scala,Scala,这里有一些关于这方面的讨论,但我有一些具体的问题,我无法找到答案。所以,通过名称调用,我指的是=>Ttype,通过0-arity函数,我指的是()=>T 我理解(我认为)概念上的差异,但可能我遗漏了一些东西,因为我还有很多问题: 如果我们总是可以使用()=>T,为什么我们会有=>T的概念呢 每种语言都有语法/功能限制吗?现在我发现只有=>不能用作类字段。这是唯一的限制吗 生成的代码是否总是相同的 我应该总是更喜欢=>T?为什么 调用=>Ta类型正确吗?在我看来,它在scala中没有任何类型表示

这里有一些关于这方面的讨论,但我有一些具体的问题,我无法找到答案。所以,通过名称调用,我指的是
=>T
type,通过0-arity函数,我指的是
()=>T

我理解(我认为)概念上的差异,但可能我遗漏了一些东西,因为我还有很多问题:

  • 如果我们总是可以使用
    ()=>T
    ,为什么我们会有
    =>T
    的概念呢
  • 每种语言都有语法/功能限制吗?现在我发现只有
    =>
    不能用作类字段。这是唯一的限制吗
  • 生成的代码是否总是相同的
  • 我应该总是更喜欢
    =>T
    ?为什么
  • 调用
    =>T
    a类型正确吗?在我看来,它在scala中没有任何类型表示
  • 1) 使用它更方便,尤其是在DSL中:

    def printAndGet[T](f: => T) = {
      val res = f
      println(res + " printed") 
      res
    }
    
    scala> :paste
    // Entering paste mode (ctrl-D to finish)
    
    val k = printAndGet {
      val a = 5
      5 * a 
    }
    
    // Exiting paste mode, now interpreting.
    
    25 printed
    k: Int = 25
    
    2)
    =>T
    只能是方法或函数的参数。实际上,
    =>T
    ()=>T
    是不可交换的:

    scala> def aaa(f: => String) = f
    aaa: (f: => String)String
    
    scala> val a: Function1[() => String, String] = aaa _
    <console>:8: error: type mismatch;
     found   : (=> String) => String
     required: (() => String) => String
           val a: Function1[() => String, String] = aaa _
                                                    ^
    
    字节码也可能不同。例如,编译器更可能从
    =>T
    内联代码,而不为其生成lambda。所以,关键的区别在于,
    ()=>T
    实际上是一个对象(一等公民),
    =>T
    不是

    4) 请参见1,但有时您可能需要确保用户知道计算可能会延迟-
    ()=>T
    比这更好

    5) 这是类型签名的一部分,只需看看eta扩展:

    scala> def aaa(f: => String) = {f}
    aaa: (f: => String)String
    
    scala> aaa _ //convert method into a function
    res7: (=> String) => String = <function1>
    
    scala> val a: ( => String) =>  String = aaa _
    a: (=> String) => String = <function1>
    
    scala>defaaa(f:=>String)={f}
    aaa:(f:=>字符串)字符串
    scala>aaa//convert方法为函数
    res7:(=>String)=>String=
    scala>vala:(=>String)=>String=aaa_
    答:(=>字符串)=>字符串=
    
    但是scala不认为它是独立类型:

    scala> val a: Function1[( => String), String] = aaa _
    <console>:1: error: no by-name parameter type allowed here
           val a: Function1[( => String), String] = aaa _
                              ^
    
    scala>vala:Function1[(=>String),String]=aaa_
    :1:错误:此处不允许按名称参数类型
    val a:Function1[(=>String),String]=aaa_
    ^
    
    考虑一下这个评论——关于#2,您不能使用按名称类型归属,因此对于重载的
    f(i:Int)
    f(i:=>Int)
    ,您不能
    f(0:=>Int)
    。与你关于“独立”型的观点相似。1)我理解。我不明白为什么我们需要特殊的
    =>T
    符号?我们总是可以使用
    ()=>T
    ,并假设任何表达式都是
    ()=>
    类型,而不是
    =>T
    。2)这似乎不是真的。我至少可以将其用作本地val:
    defaa(f:=>String)={val g=f;println(g)}
    然后
    aa{println(“已处理”);“return val”}
    。我想知道它还有什么其他用途be@Archeg2)您的本地val只有
    T
    类型,而不是
    =>T
    ,无法生成干净的
    =>T
    类型请参见我尝试调整重载分辨率的第一条注释。
    scala> def aaa(f: => String) = {f _}
    aaa: (f: => String)() => String
    
    scala> def aaa(f: => String) = {f}
    aaa: (f: => String)String
    
    scala> aaa _ //convert method into a function
    res7: (=> String) => String = <function1>
    
    scala> val a: ( => String) =>  String = aaa _
    a: (=> String) => String = <function1>
    
    scala> val a: Function1[( => String), String] = aaa _
    <console>:1: error: no by-name parameter type allowed here
           val a: Function1[( => String), String] = aaa _
                              ^