`
xugang8289
  • 浏览: 8456 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

[转载]scala中的by-name parameter详解

阅读更多
[转载自 Gossip@caterpillar]

个人翻译为简体中文, 供自己学习使用

scala中的by-name parameter介绍:

到目前為止,所定义的带参数的函数,必须先根据参数的表达式计算出值,然后才能调用该函数。例如:

def sum(a: Int, b: Int) = a + b

println(sum(1 + 2, 3 + 4))       // 显示10

在调用函数sum之前,1+2和3+4都会先被计算出结果,然后以sum(3, 7)的方式来调用sum函数,a 和 b 这两个参数称为传值参数(By-value paramenter)。

考虑另一种情况, 如果你想开发以下函数:

def unless(cond: Boolean, func: () => Any) = {
    if(!cond) {       
         func()   
    }
}

unless(false, () => println("XD"))
unless(true,  () => println("Orz"))

这个函数的作用是:除非cond为true, 否则就执行传入的函数字面量。所传入的函数字面量是无参的函数,不过 () => 仍然不能省略,也就是说你不能够写成以下形式:

unless(false, println("XD"))   // 该形式编译时错误

如果你想要省略()=>, 则可以这样定义该函数:

def unless(cond: Boolean, expr: => Any) = {   
    if(!cond) {
         expr   
    }
}

unless(false, println("XD"))
unless(true,  println("Orz"))

在这个定义下, expr的参数类型是 =>Any , 称之为传名参数 (By-name parameter)。
可以看到, 在调用,unless函数时, 直接写了println("XD")这个表达式,省略了()=>部分。
事实上, 省略()=>并不是这个例子的重点, 重点在于println("XD")表达式,不会被马上执行,真正执行是在cond参数为false时,也就是unless函数中if结果为true时。

传名参数的命名由此而来, 献给予所给定的参数表达式一个名称,然后以这个名称代替参数表达式的执行结果来调用该函数,真正执行该表达式的位置则是在你所定义的函数内部。

需要注意的是,传名参数并不是一个函数字面量,它只是一个表达式的别名。所以你不能按照下面的写法来用:

def unless(cond: Boolean, expr: => Any) = {
    if(!cond) {
        expr()   // 不能有括號
    }
}

对于scala中短路的与&&和短路或 || 其实都是方法的名称, 那它们是如何实现短路作用的呢?其实就是用传名参数实现的。以下是模拟短路与 && 的函数:

def and(c1: Boolean, c2: => Boolean) = {
    if(c1) c2 else c1
}

println(and(5 > 3, 10 > 3))  // true
println(and(5 > 3, 10 < 3))  // false
println(and(1 > 3, 10 > 3))  // false

以下這個範例可以證明上面的and函式確實有捷徑運算的作用:

def and(c1: Boolean, c2: => Boolean) = {   
    if(c1) c2 else c1
}
println(and(5 > 3, {print("run.. "); 10 > 3}))  // 顯示 run.. false
println(and(1 > 3, {print("run.. "); 10 > 3}))  // 顯示 false

由于第一个and函数被调用时,5>3成立,所以必须要检测第二个表达式, 因而会显示run...的信息。而第二个and函数调用时,1>3为false,所以就不需要检测第二个表达式了,直接返回false,所以不会显示run...的信息。

在scala中,没有until的功能,也就是除非条件成立,否则就反复执行一些功能,一下是模拟until功能的函数:

def until(cond: => Boolean, expr: => Unit) {
    if(!cond) {      
       expr       
        until(cond, expr)   
    }
}

var count = 10
until(count == 0, {   
   println(count)   
   count -= 1
})

如果将第一个参数改为cond:Boolean,那么until函数将永远不会停止, 因为count == 0会先运算为false,在传递给until函数。所以until函数中的!cond将永远为true,所以一直跑下去。直到堆栈溢出为止。

事实上, 如果使用scala中的currying特性, 可以让unless和util函数看起来就像语言的内置控制结构一样。这也是scala支持扩展性的一个方式。

(完)
分享到:
评论

相关推荐

    scala-parser-combinators-2.11-1.0.4-API文档-中文版.zip

    赠送jar包:scala-parser-combinators_2.11-1.0.4.jar; 赠送原API文档:scala-parser-combinators_2.11-1.0.4-javadoc.jar; 赠送源代码:scala-parser-combinators_2.11-1.0.4-sources.jar; 赠送Maven依赖信息...

    scala-parser-combinators_2.12-1.1.0-API文档-中英对照版.zip

    赠送jar包:scala-parser-combinators_2.12-1.1.0.jar; 赠送原API文档:scala-parser-combinators_2.12-1.1.0-javadoc.jar; 赠送源代码:scala-parser-combinators_2.12-1.1.0-sources.jar; 赠送Maven依赖信息...

    scala-compiler-2.11.8-API文档-中英对照版.zip

    赠送jar包:scala-compiler-2.11.8.jar; 赠送原API文档:scala-compiler-2.11.8-javadoc.jar; 赠送源代码:scala-compiler-2.11.8-sources.jar; 赠送Maven依赖信息文件:scala-compiler-2.11.8.pom; 包含翻译后...

    scala-parser-combinators_2.11-1.0.4-API文档-中英对照版.zip

    赠送jar包:scala-parser-combinators_2.11-1.0.4.jar; 赠送原API文档:scala-parser-combinators_2.11-1.0.4-javadoc.jar; 赠送源代码:scala-parser-combinators_2.11-1.0.4-sources.jar; 包含翻译后的API...

    scala-intellij-bin-2016.3.9

    总的来说,"scala-intellij-bin-2016.3.9"插件是Scala开发者在IntelliJ IDEA中高效工作的重要工具,它通过丰富的特性集和与IDE的紧密集成,使得Scala编程变得更加顺畅和愉快。如果你是Scala的爱好者或者正在从事...

    scala-intellij-bin-2020.2.3.zip

    总之,"scala-intellij-bin-2020.2.3.zip" 提供了在IntelliJ IDEA中进行高效Scala开发所需的工具集。通过使用这个插件,开发者可以充分利用Scala的高级特性,并享受到IDE带来的强大代码辅助和调试功能,从而提升开发...

    scala-intellij-bin-2018.3.2.zip

    scala-intellij-bin-2018.3.2.zip插件,亲测可用!!!scala-intellij-bin-2018.3.2.zip插件,亲测可用!!!scala-intellij-bin-2018.3.2.zip插件,亲测可用!!!

    scala-compiler-2.11.12-API文档-中文版.zip

    赠送jar包:scala-compiler-2.11.12.jar; 赠送原API文档:scala-compiler-2.11.12-javadoc.jar; 赠送源代码:scala-compiler-2.11.12-sources.jar; 赠送Maven依赖信息文件:scala-compiler-2.11.12.pom; 包含...

    scala-intellij-bin-0.41

    "scala-intellij-bin-0.41"是专门为IntelliJ IDEA设计的一个Scala插件,版本号为0.41,用于增强IDE对Scala语言的支持。 这个插件的安装和使用对于Scala开发者至关重要,因为它可以提供以下关键功能: 1. 语法高亮...

    scala-intellij-bin-2023.1.15.zip

    "scala-intellij-bin-2023.1.15.zip" 是一个包含IntelliJ IDEA针对Scala开发的特定版本的二进制发行包。 这个压缩包很可能包含了以下内容: 1. **IntelliJ IDEA安装程序**:这是主应用程序,允许用户在本地计算机...

    scala-library-2.11.8-API文档-中文版.zip

    赠送jar包:scala-library-2.11.8.jar; 赠送原API文档:scala-library-2.11.8-javadoc.jar; 赠送源代码:scala-library-2.11.8-sources.jar; 赠送Maven依赖信息文件:scala-library-2.11.8.pom; 包含翻译后的API...

    scala-compiler-2.12.7-API文档-中英对照版.zip

    赠送jar包:scala-compiler-2.12.7.jar; 赠送原API文档:scala-compiler-2.12.7-javadoc.jar; 赠送源代码:scala-compiler-2.12.7-sources.jar; 赠送Maven依赖信息文件:scala-compiler-2.12.7.pom; 包含翻译后...

    scala-intellij-bin-2021.1.22.zip

    总的来说,"scala-intellij-bin-2021.1.22.zip" 提供了一个完整的Scala开发环境,适合那些希望在IntelliJ IDEA中进行Scala编程的开发者。通过安装和使用这个插件,开发者可以提高工作效率,深入理解并享受Scala语言...

    scala-reflect-2.11.8-API文档-中英对照版.zip

    赠送jar包:scala-reflect-2.11.8.jar; 赠送原API文档:scala-reflect-2.11.8-javadoc.jar; 赠送源代码:scala-reflect-2.11.8-sources.jar; 赠送Maven依赖信息文件:scala-reflect-2.11.8.pom; 包含翻译后的API...

    scala插件 scala-intellij-bin-2018.3.5.zip scala-intellij-bin-2018.3.6.zip

    总的来说,`scala-intellij-bin-2018.3.5.zip` 和 `scala-intellij-bin-2018.3.6.zip` 插件极大地提升了Scala和Spark开发者在IntelliJ IDEA中的开发体验,提高了工作效率。无论是初学者还是经验丰富的开发者,都能...

    scala-SDK-4.7.0-vfinal-2.12-linux.gtk.x86_64.tar.gz

    scala-SDK-4.7.0-vfinal-2.12-linux.gtk.x86_64.tar.gz scala-SDK-4.7.0-vfinal-2.12-linux.gtk.x86_64.tar.gz

    scala-parser-combinators_2.12-1.1.0-API文档-中文版.zip

    赠送jar包:scala-parser-combinators_2.12-1.1.0.jar; 赠送原API文档:scala-parser-combinators_2.12-1.1.0-javadoc.jar; 赠送源代码:scala-parser-combinators_2.12-1.1.0-sources.jar; 赠送Maven依赖信息...

    scala-intellij-bin-2016.3.1.zip

    在本压缩包"scala-intellij-bin-2016.3.1.zip"中,包含的是IntelliJ IDEA的一个版本,专门针对Scala语言进行了优化。 IntelliJ IDEA是JetBrains公司开发的,它以其智能代码补全、强大的代码分析和重构工具而闻名。...

    scala-intellij-bin-2017.2.13

    "Scala-intellij-bin-2017.2.13"是针对IntelliJ IDEA的一个特定版本——2017.2.13的Scala插件,这个插件使得在IntelliJ中编写、调试和运行Scala代码变得轻而易举。 Scala插件的安装和配置是开发Scala项目的关键步骤...

    scala-actors-2.10 jar包

    scala-actors-2.10 jar包,可以解决 scala-actors-2.10以上版本带来的不兼容问题

Global site tag (gtag.js) - Google Analytics