Scala函数笔记

Scala 函数笔记

作为面向函数的编程语言,scala函数中传入的参数是不可以直接修改的

方法vs函数

  • 方法可以作为一个表达式的一部分出现(调用函数并传参),但是方法(带参方法)不能作为 最终的表达式,但是函数和无参方法可以作为最终的表达式出现。

  • 参数列表对于方法是可选的,但是对于函数参数列表是强制的 方法可以没有参数列表,参数列表也可以为空;而函数必须有参数列表(也可以为空)。

  • 方法名意味着方法调用,但函数名却代表的是函数自身。

    因为方法不能作为最终的表达式存在,所以如果你写了一个方法的名字并且该方法不带参数(没有参数列表或者无参)该表达式的意思是:调用该方法得到最终的表达式。

    因为函数可以作为最终表达式出现,如果你写下函数的名字,函数调用并不会发生,该方法自身将作为最终的表达式进行 返回,如果要强制调用一个函数,你必须在函数名后面写()

  • 方法可以自动(称之ETA扩展)或手动强制转换为函数;但是函数不可以转换成方法。 在期望出现函数的地方使用方法,该方法自动转换成函数;手动强制转换可以使用 “方法名 _” 转 换成函数

值函数

Scala的语法规定,将函数赋值给变量,并且在函数后面加上空格和下划线的形式成为值函数

def test(str:String){
	println(str+":hello")
}
def main(args:Array[String]){
  val func=test _;
  func("zun");
  
}

匿名函数

Scala定义匿名函数的语法规则就是,(参数名: 参数类型) => 函数体

将函数赋值给变量,其中3*x被称为字面量

val triple=(x:Double)=>3*x

变长参数

  def sum(args: Int*): Int = {
    // arg是一个Seq类型
    var result = 0
    for (arg <- args) {
      result += arg
    }
    result
  }
 // 1 to 5生成一个Range类型对象,所以使用_*将1 to 5当做参数序列
sum(1 to 5 :_* )

高阶函数

接收其他函数作为参数的函数,也可以将函数作为返回值,被称作高阶函数(higher-order function)

  1. 高阶函数可以自动推断出参数类型,调用时不需要写明类型
  2. 对于只有一个参数的函数,调用时还可以省去其小括号
  3. 如果仅有的一个参数在右侧的函数体内只使用一次,则还可以将接收参数省略,并且将参数用_ 来替代(下图中 main 函数分别展示了高阶函数的这些中写法,大家要熟悉)
    在这里插入图片描述

高阶函数的意义在哪?虽然减少代码量,可以实现更复杂的功能,但是对于新手来说学习成本高,可维护性低。增加程序员学习成本。

函数组合

def f()=>"hello"
def g()=>"hi"
val fcomg=f _ compose g _

尾递归

在函数尾部调用另一个函数,解决递归的栈溢出问题。

递归是一个不断压栈的过程

使用

@annotation.tailrec

进行检查是否为尾递归

闭包

变量不在有效区域,但是还可以访问,即为闭包

def getGreetingFunc(msg: String) =
  (name: String) => println(msg + ", " + name)
//两次调用,分别传入msg,name,第一次执行完之后继续存在创建的函数中

//柯里化形式
def getGreetingFunc(msg: String)(name: String) = println(msg + ", " + name)
//getGreetingFunc("hell0")("scala")


局部函数

即在函数内部定义函数,局部函数可以访问夫函数参数。刚开始时以为局部函数没什么作用。但是后来发现其一大作用就是可以将函数进行二次包装,使函数更加精美。

比如在编写斐波那契函数时,其实可以仅仅使用loop函数完成计算并满足尾递归,但是函数的参数很多。

使用局部函数二次包装之后就显得精美很多

def fib(n: Int): Int = {
    @scala.annotation.tailrec
    def loop(n: Int, prev: Int, curr: Int): Int =
      if (n == 1) prev
      else if (n == 2) curr
      else loop(n - 1, curr, prev + curr)
    loop(n, 0, 1)
  }

隐式转换

  1. 隐式值:省略参数的情况下进行搜索

    • 同时出现隐式值、默认值、传值时,编译器的优先级为:传值 >隐式值 >默认值
    • 隐式匹配时,不能有二义性
    • 如果隐式值、默认值、传值都没有的情况下,使用隐式值的地方便会报错:
  2. 隐式函数

    • 隐式转换函数与函数名无关,只与函数签名(函数参数类型,函数的返回值类型)有关。
    • 隐式转换函数是以implicit关键字作用于带有单个参数的函数上。这种函数将会自动应用,将值从一种类型转换 为另外一种类型。
    • 隐式转换函数是以implicit关键字作用于带有单个参数的函数上。这种函数将会自动应用,将值从一种类型转换 为另外一种类型。
    • 隐式转换函数可以有多个(隐式转换列表),但是需要保证当前环境下只有一个隐式函数被识别。
  3. 隐式类

    隐式类基本介绍 Scala2.10以后提出了隐式类,可以使用implicit声明类,隐式类非常强大,同样可以扩展类的功能,比前面使用 隐式转换丰富类库功能更加方便,在集合中隐式类会发挥重要的作用。
    隐式类有如下几个特点:

    1. 构造参数只能有一个
    2. 必须定义在“类”、“半生对象”、包对象的其中一个里面,即:它不能是一个顶级类。
    3. 不能是case class(案例类)。
    4. 作用域内不能有阈值相同名称的标识符。
发布了36 篇原创文章 · 获赞 8 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_42297075/article/details/104175200