Scala函数

一、Java Lambda表达式

Java lambda表达式是Java 8新特性,它是步入Java函数式编程的第一步,它可以像一个对象一样传递,并按要求执行。
函数式接口

  • 一种只含有一个抽象方法声明的接口
  • 可以使用匿名内部类来实例化函数式接口的对象
  • 通过Lambda表达式可以进一步简化代码

Lambda表达式语法

  • (parameters) -> expression

  • (parameters) ->{ statements;...... }

首先新建一个接口OperationInterface

public interface OperationInterface {
    Integer option(Integer a,Integer b);
}

创建测试类TestOperation

// 定义加减乘的Lambda表达式
OperationInterface add = (Integer a,Integer b) -> a+b;
OperationInterface sub = (Integer a,Integer b) -> a-b;
OperationInterface multi = (Integer a,Integer b) -> a*b;
// 调用
System.out.println(add.option(10,20)); // 30
System.out.println(sub.option(10,20)); // -10
System.out.println(multi.option(10,20)); // 200

二、Scala函数

函数定义

  • def 函数名([参数列表]):[返回值]={ 函数体 return [表达式] }

函数调用

  • 函数名(参数列表)

参数传递

在scala中参数传递的方式有两种,一种是传值调用,一种是传名调用

  • ①传值调用(call-by-value):传值调用时,参数只在调用时计算一次,后续重复使用计算的结果
  • ②传名调用(call-by-name):传名调用时,参数在调用时不会计算,只有真正用到参数时才计算
// 定义两个函数
object Demo {  
  // 传名调用,参数名称和参数类型中间有一个=>符号,即b: => Int
  def addByName(a: Int, b: => Int) = a + b 
  // 传值调用  
  def addByValue(a: Int, b: Int) = a + b  
  // 当a=1,b=2+2时,分别执行上述两个方法
  addByName(1,2+2) 
  /*
  	 addByName(1,2+2) 
  => 1+(2+2)
  => 1+4 
  => 5
  */
  addByValue(1,2+2)
  /*
  	 addByValue(1,2+2) 
  => addByValue(1,4)
  => 1+4 
  => 5
  */
}

两种参数传递方式的理解:

// 以猴子吃桃子为例,一共10个桃子,每天吃一个,假设猴子会数桃子数量
object EatPeach{
  // 桃子数量
  var peach_num = 10
  // 吃桃子,桃子数量-1
  def eat={
    peach_num = peach_num - 1
  }
  // 每次吃完,数一次桃子
  def count={
    eat
    peach_num
  }
  // 通过两种方式计算桃子数量
  // 传名调用
  def printByName(x: => Int)={
    for(i <- 1 to 5)
      println("还剩"+x+"个桃子")
  }
  // 传值调用
  def printByValue(x:Int)={
    for(i <- 1 to 5)
      println("还剩"+x+"个桃子")
  }
  // 测试
  def main(args: Array[String]): Unit = {
    println("------传名调用------")
    printByName(count)
    println("------传值调用------")
    printByValue(count)
  }
}

运行结果如下:
在这里插入图片描述
通过上述例子可看出:
传值调用在进入函数体之前就对参数表达式进行了计算,这避免了函数内部多次使用参数时重复计算其值,在一定程度上提高了效率。
传名调用的一个优势在于,如果参数在函数体内部没有被使用到,那么它就不用计算参数表达式的值了。在这种情况下,传名调用的效率会高一点。

命名参数

通常情况下,传入参数与函数定义的参数列表一一对应,命名参数允许使用任意顺序传入参数。如下例子:

// 定义函数
def showMessage(name:String,age:Int)={
	println("Hello:"+name+",age:"+age)
}
// 传递的实参需要依照形参顺序
showMessage("KB09",3)
// 命名参数,通过指定参数名称对参数进行赋值,顺序可变
showMessage(age=18,name = "kb09")

参数缺省值

给定参数一个默认值,当实参为空时,该参数的值就为默认值

def showMessage(name:String="张三",age:Int=24)={
	println("Hello:"+name+",age:"+age)
}
showMessage() // 输出Hello:张三,age:24

匿名函数

顾名思义,即指没有名称的函数

  • 语法:(参数列表)=>{函数体}
// 正常函数,有个名字,本例为sum
def sum(a:Int,b:Int)=a+b
// 匿名函数,没有名字
(a:Int,b:Int)=>a+b
// 使用匿名函数一定用一个变量接收
val sum1 = (a:Int,b:Int)=>a+b
// 使用
sum1(1,2) // 3

高阶函数

高阶函数是指将其他函数作为参数或者使用函数作为输出结果

  • 将其他函数作为参数
// 定义一个函数,参数为(Int,Int)=>Int类型的函数
def fun(f:(Int,Int)=>Int):String={
	val resultValue=f(1000,2000)
	"两数之和为:"+resultValue
}
// 实参为一个匿名函数,该匿名函数作用是求两数之和
val result = fun((a:Int,b:Int)=>a+b)
println(result) // 3000
  • 函数返回值为函数
// 传入一个参数,若该数大于2则返回求两数之和的函数,否则返回求两数之差的函数
def fun2(x:Int):(Int,Int)=>Int={
	if(x>2){
		// 求两数之和的函数
		def add(a:Int,b:Int):Int=a+b
		// 若x>2将add作为返回值
		add
	}else{
		// 求两数之差的函数
		// 匿名函数形式
		(a:Int,b:Int)=>a-b
	}
}
// fun2(1)(1,5)形式为柯里化,下面会讲到
println(fun2(1)(1,5)) // -4
  • 参数为函数,返回值也为函数
// 以下代码可能并无实际意义,主要是为了演示
def fun3(f:(String)=>Int,str:String):(Int,Int)=>Int={
  val num = f(str)
  if(num%3==0){
    (a:Int,b:Int)=>a+b
  }else{
    (a:Int,b:Int)=>a-b
  }
}

println(fun3((s: String) => {
  if (s.equals("上海"))
    1
  else
    2
}, "张三")(1000, 3000))

柯里化

函数可以定义多个参数列表,当使用较少的参数列表调用多参数列表的函数时,会产生一个新的函数,该函数接收剩余的参数列表作为其参数,这被称为柯里化

// fun4、fun5作对比
def fun4(a:Int,b:Int,c:Int,d:Int):Int={
	a+b+c+d
}
println(fun4(1,2,3,4))
def fun5(a:Int)(b:Int)(c:Int)(d:Int):Int={
	a+b+c+d
}
println(1)(2)(3)(4)

隐式参数

隐式参数用implicit修饰,通常与柯里化函数结合使用,如下例:

// 将a作为Int类型隐式值自动传递
implicit val a:Int = 10
// 定义一个函数func5,c为隐式参数,传值时会自动找同类型的隐式值
def fun5(a:Int,b:Int)(implicit c:Int)={
  a+b+c
}
// c为隐式参数,已经定义了a为隐式值,故不需要传参
println("fun5的结果1:"+fun8(10,11)) // 31
// 可通过对隐式参数传参覆盖隐式值
println("fun5的结果2:"+fun8(10,11)(5)) // 26

// fun6与fun5的区别在于给定了隐式参数一个缺省值
def fun5(a:Int,b:Int)(implicit c:Int=5)={
  a+b+c
}
// 给隐式参数c传递空值,用于比较隐式值与缺省值的优先级
println("fun6的结果:"+fun8(10,11)())  // 31

注意:上述比较可以得出结论:对隐式参数赋值三种方式的优先级为:直接传参 > 隐式值 > 缺省值 ;同一类型的隐式值只能有一个,否则会报错

隐式函数

隐式函数也称隐式转换,使用implicit修饰的函数
应用场景:

  • 类型转换
object ImplicitFunc{
  def main(args: Array[String]): Unit = {
  	// 定义了一个隐式函数,该函数的作用是将double类型转成int类型
    implicit def doubleToInt(value:Double):Int=value.toInt
    // 因为有隐式函数,故可以这么操作,隐式函数会自动调用
    val num:Int = 3.5
    println(num) // 3
  }
}
  • 类型增强
object ImplicitFunc{
  def main(args: Array[String]): Unit = {
    implicit def bool2Int(x:Boolean)=if(x) 1 else 0
	println(1+true)  // 2
  }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值