Scala-07:函数式编程

Scala-07:函数式编程

什么是函数式编程 ?

解决问题时,将问题分解成一个一个的步骤,将每个步骤进行封装(函数),通过调用这些封装好的步骤,解决问题。

例如:请求->用户名、密码->连接 JDBC->读取数据库

Scala 语言是一个完全函数式编程语言。万物皆函数。

函数的本质:函数可以当做一个值进行传递

在 Scala 中函数式编程和面向对象编程完美融合在一起了

一、Scala的函数基础

1:Scala的函数语法

定义函数的关键字  函数名(参数名 : 参数类型) : 返回值类型 = {
	
	函数体
	
}

在这里插入图片描述

2:函数与方法的区别

(1)为完成某一功能的程序语句的集合,称为函数。

(2)类中的函数称之方法。

准确的来说,Java中常常把函数和方法混用,认为函数就是方法,方法就是函数。在Scala中,将函数和方法中进行了区分,类中的函数才称之为方法,在Scala 语言可以在任何的语法结构中声明任何的语法 ,函数没有重载和重写的概念;方法可以进行重载和重写

def main(args:Array[String]):Unit = {
	
	def say( name : String ) : Unit = {
		println("hello , " + name)
	}
	
	say("tom")
}

上面这种写法在main中声明一个函数的使用方法在java中是肯定不能使用的,而在scala中就可以使用

函数的声明最主要的两个要素:参数和返回值

参数:

  1. 可以没有参数
  2. 可以有一个参数
  3. 可以有多个参数

返回值

  1. 可以有返回值
  2. 可以无返回值
//没有参数也没有返回值
def test1() : Unit = {
	println("这是一个没有参数也没有返回值的函数")
}

//有一个参数没有返回值
def test2( arg : String) : Unit = {
	println("这是一个有一个参数没有返回值的函数,参数是:" + arg)
}

//有多个参数没有返回值的函数
def test3( arg1 : Int , arg2 : Int ) : Unit = {
    println("这是一个有多个参数没有返回值的函数,参数是:" + arg1 + arg2)
}

//没有参数有返回值
def test4() : String = {
    return "这是一个没有参数又返回值得函数"
}

//有一个参数有返回值
def test5( arg : String ) : String {
    return "这是一个有一个参数有返回值的函数,参数是:" + arg
}

//有多个参数又返回值的函数
def test6(arg1 : String ,arg2 : String) : String {
    return "这是一个有多个参数有返回值的函数,参数是:" + arg1 + arg2
}

3:函数参数

(1)可变参数

(2)如果参数列表中存在多个参数,那么可变参数一般放置在最后

(3)参数默认值,一般将有默认值的参数放置在参数列表的后面

(4)带名参数

4:函数至简原则

(1)return 可以省略,Scala 会使用函数体的最后一行代码作为返回值

(2)如果函数体只有一行代码,可以省略花括号

(3)返回值类型如果能够推断出来,那么可以省略(:和返回值类型一起省略)

(4)如果有 return,则不能省略返回值类型,必须指定

(5)如果函数明确声明 unit,那么即使函数体中使用 return 关键字也不起作用

(6)Scala 如果期望是无返回值类型,可以省略等号

(7)如果函数无参,但是声明了参数列表,那么调用时,小括号,可加可不加

(8)如果函数没有参数列表,那么小括号可以省略,调用时小括号必须省略

(9)如果不关心名称,只关心逻辑处理,那么函数名(def)可以省略

二、函数高级

1:高阶函数

函数可以作为值进行传递

函数作为值进行传递的方法有两种实现方法,一个是指定参数和返回值类型,另一个是在函数后加空格和“_”

第一种:指定参数和返回值类型

def fun(num Int) : Int = {
	println("fun方法被调用")
	return num + 1
}

var f1 : Int => Int = fun

println(f1(12))

第二种:函数后加空格和“_”

def fun(num Int) : Int = {
	println("fun方法被调用")
	return num + 1
}

var f1  = fun _

println(f1(12))
函数作为参数进行传递
// (1) 定义一个函数, 函数参数还是一个函数签名; f 表示函数名称;(Int,Int)表示输入两个 Int 参数;Int 表示函数返回值
def f1(f: (Int, Int) => Int): Int = { 
        f(2, 4) 
    } 
     
    // (2)定义一个函数,参数和返回值类型和 f1 的输入参数一致 
    def add(a: Int, b: Int): Int = a + b 
     
    // (3)将 add 函数作为参数传递给 f1 函数,如果能够推断出来不是调用,_可以省略 
    println(f1(add)) 
	println(f1(add _)) 
	//可以传递匿名函数 
}
函数可以作为函数返回值返回
def f1() = { 
    def f2() = { 

    } 
    f2 _ 
} 
 
val f = f1() 
// 因为 f1 函数的返回值依然为函数,所以可以变量 f 可以作为函数继续调用 
f() 
// 上面的代码可以简化为 
f1()()

2:匿名函数

没有名字的函数就是匿名函数。

(x:Int)=>{
    //函数体
} 

x:表示输入参数类型;

Int:表示输入参数类型;

函数体:表示具体代码逻辑

传递匿名函数至简原则:

(1)参数的类型可以省略,会根据形参进行自动的推导

(2)类型省略之后,发现只有一个参数,则圆括号可以省略;其他情况:没有参数和参数超过 1 的永远不能省略圆括号。

(3)匿名函数如果只有一行,则大括号也可以省略

(4)如果参数只出现一次,则参数省略且后面参数可以用_代替

// (1)定义一个函数:参数包含数据和逻辑函数 
        def operation(arr: Array[Int], op: Int => Int) = { 
            for (elem <- arr) yield op(elem) 
        } 
 
        // (2)定义逻辑函数 
        def op(ele: Int): Int = { 
            ele + 1 
        } 
 
        // (3)标准函数调用 
        val arr = operation(Array(1, 2, 3, 4), op) 
        println(arr.mkString(",")) 
 
        // (4)采用匿名函数 
        val arr1 = operation(Array(1, 2, 3, 4), (ele: Int) => { 
            ele + 1 
        }) 
        println(arr1.mkString(",")) 
 
        // (4.1)参数的类型可以省略,会根据形参进行自动的推导; 
        val arr2 = operation(Array(1, 2, 3, 4), (ele) => { 
            ele + 1 
        }) 
        println(arr2.mkString(",")) 
 
        // (4.2)类型省略之后,发现只有一个参数,则圆括号可以省略;其他情
况:没有参数和参数超过 1 的永远不能省略圆括号。 
        val arr3 = operation(Array(1, 2, 3, 4), ele => { 
            ele + 1 
        }) 
        println(arr3.mkString(",")) 
 
        // (4.3) 匿名函数如果只有一行,则大括号也可以省略 
        val arr4 = operation(Array(1, 2, 3, 4), ele => ele + 1) 
        println(arr4.mkString(",")) 
 
        //(4.4)如果参数只出现一次,则参数省略且后面参数可以用_代替 
        val arr5 = operation(Array(1, 2, 3, 4), _ + 1) 
        println(arr5.mkString(",")) 
    } 

3:函数柯里化&闭包

闭包:函数式编程的标配

1)说明

闭包:如果一个函数,访问到了它的外部(局部)变量的值,那么这个函数和他所处的环境,称为闭包

函数柯里化:把一个参数列表的多个参数,变成多个参数列表。

def create() = {
	var arr : Array[Int] = Array(1,2,3,4,5)
	def add(elem : Int) = {
        //内部调用外部的变量
		arr.+:(elem)
	}
	//获得add的值
	add _
	
}

var f = create()
println(f(3).mkString(","))
println(create()(4).mkString(","))

4:递归

一个函数/方法在函数/方法体内又调用了本身,我们称之为递归调用

 def test(i : Int) : Int = { 
     	//跳出的逻辑
        if (i == 1) { 
            1 
        } else { 
            //递归
            i * test(I - 1) 
        } 
    } 

5:控制抽象

值调用:把计算后的值传递过去
def f = ()=>{ 
            println("f...")
            10 
        } 
 
        foo(f()) 
    } 
 
    def foo(a: Int):Unit = { 
        println(a) 
        println(a) 
    } 
名调用:把代码传递过去
def main(args: Array[String]): Unit = { 
 
        def f = ()=>{ 
            println("f...") 
            10 
        } 
 
        foo(f()) 
    } 
 
  //def foo(a: Int):Unit = { 
    def foo(a: =>Int):Unit = {//注意这里变量 a 没有小括号了 
        println(a) 
        println(a) 
    } 

6:惰性加载

当函数返回值被声明为 lazy 时,函数的执行将被推迟,直到我们首次对此取值,该函数才会执行。这种函数我们称之为惰性函数。

lazy val res = sum(10, 30) 
    println("----------------") 
    println("res=" + res) 
} 

def sum(n1: Int, n2: Int): Int = { 
    println("sum 被执行。。。") 
    return n1 + n2 
}

注意:lazy 不能修饰 var 类型的变量

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

牧码文

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值