美文网首页
三.函数

三.函数

作者: 阿猫阿狗Hakuna | 来源:发表于2018-11-06 16:52 被阅读9次

           函数是可重用逻辑的核心构件。函数式编程语言特别强调支持创建高可重用、可组合的函数。
           在Scala中,函数式可重用的命名表达式。函数可以参数化,可以返回一个值。
           尽可能构建纯(pure)函数,纯函数式指:

    • 有一个或多个输入参数
    • 只使用输入参数完成计算
    • 返回一个值
    • 对于相同的输入总返回相同的值
    • 不使用或影响函数之外的任何数据
    • 不受函数之外的任何数据的影响
    语法:定义无输入的函数
    def <identifier> = <expression>
    
    语法:定义函数时指定返回类型
    def <identifier>: <type> = <expression>
    
    语法:完整函数定义
    def <identifier>(<identifier>: <type>[, ...]): <type> = <expression>
    
    例子:基本数学运算
    def multiplier(x: Int, y: Int): Int = { x * y }
    

           最后一行将成为表达式的返回值,相应也是函数的返回值。有些情况下,可能需要在函数的表达式块结束前退出并返回一个值,可以使用return关键字来显式指定函数返回值。

    例子:提前退出
    scala> def safeTrim(s: String): String = {
         |   if (s == null) return null
         |   s.trim()
         | }
    

    1.过程

           过程(procedure)是没有返回值的函数。如果有一个简单的函数,没有显式的返回类型,而且最后是一个语句,Scala编译器就会推导出这个函数的返回类型为Unit。

    scala> def log(d: Double) = println(f"Got value $d%.2f")
    log: (d: Double)Unit
    
    scala> def log(d: Double): Unit = println(f"Got value $d%.2f")
    log: (d: Double)Unit
    

    2.用空括号定义函数

           要定义和调用一个无输入的函数(即没有输入参数的函数),可以使用空括号。这样可以很清楚地区分函数和值。

    语法:用空括号定义函数
    def <identifier>()[: <type>] = <expression>
    
    例子:
    def hi(): String = "hi"
    

    注意:有副作用(会修改其范围之外的数据)的函数,在定义时应当加空括号。

    3.使用表达式块调用函数

           使用一个参数调用函数时,可以利用一个用大括号包围的表达式块发送参数,而不是用小括号包围值。通过使用表达式块调用函数,可以完成一些计算和其他动作,然后利用这个块的返回值调用函数。

    语法:用表达式块调用函数
    <function identifier> <expression block>
    

           有些情况下可能更适合使用表达式块来调用函数,例如必须向函数发送一个计算值时。不必先计算一个量然后把它保存在局部值中再传递给函数,完全可以在表达式块中完成计算。表达式块会在调用函数之前计算,而且表达式块的返回值将用作这个函数的参数。

    例子:如何在一个表达式块中计算值来调用一个函数:
    scala> def formatEuro(amt: Double) = f"$amt%.2f"
    formatEuro: (amt: Double)String
    
    scala> formatEuro(3.4645)
    res9: String = 3.46
    
    scala> formatEuro { val rate = 1.32; 0.235 + 0.7123 + rate * 5.32}
    res10: String = 7.97
    

    4.递归函数

           递归函数就是调用自身的函数,要检查某类参数或外部条件来避免函数陷入无限循环。

    例子:得到一个整数的给定整数次幂
    scala> def power(x: Int, n: Int): Long = {
         |   if (n >= 1) x * power(x, n-1)
         |   else 1
         | }
    power: (x: Int, n: Int)Long
    
    scala> power(2,8)
    res11: Long = 256
    

    5.嵌套函数

           可以在函数中定义另一个内部函数,这个内部函数只能在该函数中使用。

    例子:取3个整数,返回其中值最大的整数
    scala> def max(a: Int,b: Int,c: Int) = {
         |   def max(x: Int, y: Int) = if (x > y) x else y
         |   max(a,max(b,c))
         | }
    max: (a: Int, b: Int, c: Int)Int
    
    scala> max(42,182,19)
    res12: Int = 182
    

           Scala函数按函数名以及其参数类型列表来区分。所以它们之间不会发生冲突。不过,即使函数名和参数类型相同,它们也不会冲突,因为局部(嵌套)函数优先于外部函数。

    6.用命名参数调用函数

           调用函数的惯例是按原先定义时的顺序指定参数。但是在Scala中,可以按名调用参数,这样就可以不按顺序指定参数。

    语法:按名指定参数
    <function name>(<parameter> = <value>)
    
    例子:
    scala> def greet(prefix: String,name: String) = s"$prefix $name"
    greet: (prefix: String, name: String)String
    
    scala> val greeting = greet(name = "Jack", prefix = "Mr")
    greeting: String = Mr Jack
    

    7.有默认值的参数

           可以为任意参数指定默认值,使得调用者可以忽略这个参数。

    语法:为函数参数指定默认值
    def <identifier>(<identifier>: <type> = <value>): <type>
    
    例子:
    scala> def greet(prefix: String = "", name: String) = s"$prefix $name"
    greet: (prefix: String, name: String)String
    
    scala> val greeting = greet(name = "Paul")
    greeting: String = " Paul"
    

           可以重新组织这个函数,让必要的参数在前,这样就可以直接调用这个函数而不再需要使用参数名:

    scala> def greet(name: String, prefix: String = "") = s"$prefix $name"
    greet: (name: String, prefix: String)String
    
    scala> val greeting = greet("Ola")
    greeting: String = " Ola"
    

           最好让必要参数在前,有默认值的参数在后。

    8.Vararg参数

           Scala支持vararg参数,所以可以定义输入参数个数可变的函数。vararg参数后面不能跟非vararg,因为无法加以区分。
           要标志一个参数匹配一个或多个输入实参,在函数定义中需要该参数类型后面增加一个星号(*)

    例子:vararg参数创建求和函数
    scala> def sum(items: Int*): Int = {
         |   var total = 0
         |   for (i <- items) total += i
         |   total
         | }
    sum: (items: Int*)Int
    
    scala> sum(10, 20, 30)
    res13: Int = 60
    

    9.参数组

           Scala中可以把参数表分解为参数组(parameter groups),每个参数组分别用小括号分隔。

    例子:
    scala> def max(x:Int)(y:Int) = if (x > y) x else y
    max: (x: Int)(y: Int)Int
    
    scala> val larger = max(20)(39)
    larger: Int = 39
    

    10.类型参数

           Scala中,可以传递类型参数,类型参数指示了值参数或返回值使用的类型。

    语法:定义函数的类型参数
    def  <function-name>[type-name](<parameter-name>: <type-name>): <type-name>...
    
    例子:
    scala> def identity[A](a: A): A = a
    identity: [A](a: A)A
    
    scala> val s: String = identity[String]("Hello")
    s: String = Hello
    
    scala> val d: Double = identity[Double](2.717)
    d: Double = 2.717
    

    11.方法和操作符

           实际中,函数常存在于对象中,用来处理对象的数据,所以对函数更适合的说法通常是“方法”。
           方法(method)是类中定义的一个函数,这个类的所有实例都会有这个方法。

    语法:用中缀点记法调用方法
    <class instance>.<method>[(<parameters>)]
    
    例子:加法
    scala> d.+(2.721)
    res14: Double = 68.363
    

           Scala中所有的算术运算符其实都是方法,写为简单的函数,它们使用相应的操作符符号作为函数名,并绑定到一个特定类型。

    12.练习

    练习(1):
    scala> def compute(r: Double): Double = { 3.14 * r * r }
    
    

    相关文章

      网友评论

          本文标题:三.函数

          本文链接:https://www.haomeiwen.com/subject/ljruxqtx.html