1、Scala的方法语法:

object Hello {
def main(args : Array[String]) : Unit = { // scala 允许在方法的声明中再声明方法,并且调用
def someFunction(x : Int, y : String): Unit = {
println("this function has been called! (In this main method)")
} // 调用方法中声明的
someFunction(100, "str") // 调用这个对象声明的
val returnVal = Hello.someFunction(2, "ol")
} // 在对象中也可以声明方法,支持和方法中重名
def someFunction(x : Int, y : String): Int = {
println("this function has been called! (In this single instance)")
return 100
}
}

2、参数和返回值

    // 没有参数 没有返回值
def method01(): Unit = {
print("method01")
}
// 有参数 没有返回值
def method02(x : Int, y : String): Unit = {
print("method02")
}
// 有参数 有返回值
def method03(x : Int, y : String): Int = {
print("method01")
return 100
}
// 没有参数 有返回值
def method04(): Int = {
return 300
}

3、参数特性

// 在参数类型后面加上*号表示该参数是可变参数
def method(str : String*): Unit = {
println(str)
}
method("hello", "scala") // 打印结果是一个数组序列 ArraySeq(hello, scala) // 多个参数必须将可变参数放在最后一个
def method2(x : Int, y : Double, string: String*): Unit = { } // 默认参数
def method3(name : String = "这是默认值"): Unit = {
println(name)
} method3() // 这样无参也可以被调用,因为已经设定了一个默认值在这里 C++是支持这种操作的
method3("jojo") // 带名参数,这个参数的意思是,你可以在调用的时候强制指定注入的参数是给哪个参数的
def method4(name : String, age : Int, gender : Boolean): Unit = { }
// 带名参数的意义就在于支持打乱顺序入参
method4(gender = true, name = "张三", age = 30)

4、函数特性:

// Lambda表达式特性

// 1、可以省略return,Scala支持 函数体的最后一段代码最为返回的结果
def f0(str : String) : String = {
str // 这里就省略的了 return
}
println(f0("param")) // 2、函数体只有一段代码可以省略阔话表示
def f1(str : String) : String = str // 3、如果类型可以推断出来,则不需要强制声明返回类型是什么
def f2(str : String) = str // 4、写了Return就必须声明返回类型
def f3(str : String) : String = return str // 5、明确了返回类型为Unit,则 return没有任何意义
def f4(str : String) : Unit = return str // 这个str无意义 // 6、Unit返回类型 可以直接向Java一样声明
def f5(str : String) {
println(str)
} // 7、没有参数,但是声明的时候写了,调用可以没有括号,加括号也行
def f6() {
println("str")
}
f6() // 这样调用正常
f6 // 这样调用也没问题 // 8、如果声明的时候就没有参数列表,调用绝不能写括号
def f7 {
println("str")
}
f7 // 调用正常
// f7() // 这样调用编译报错 // 如果不关心名称,只需要逻辑处理,这里也可以匿名声明
(name : String) => {
println(name)
}

5、函数可以作为参数注入

    val funcRef = (string : String) => {
println(string)
} // 定义一个函数,参数可以是一个函数
def funcForFunc(function: String => Unit): Unit = {
function("asdas");
} // 这里很奇怪的一点是,参数为什么可以在里面注入,而外面只需要声明入参数函数?
funcForFunc(funcRef) // 我有点想明白了,这样的话,参数是顶死的,但是允许套用不同的方法,只要方法符合这个参数的方法类型要求即可被套用 // 语法缩写 // 1、参数类型可以省略不写,只要能够被推导出来
funcForFunc((name) => {println(name)}) // 2、参数只有一个可以不写参数括号
funcForFunc(name => {println(name)}) // 3、执行的语句只有一行可以不写花括号表示
funcForFunc(name => println(name)) // 4、参数只使用过一次的情况,可以不声明参数了,直接使用下划线表示
funcForFunc(println(_)) // 5、最后是调用推断
funcForFunc(println)

用法案例介绍:

    // 定义一个二元运算的函数,只操作固定的1和2个值,具体的运算由注入的函数实现
def calcForThis(fun : (Int, Int) => Int) : Int = {
fun(100, 200)
} val sum = (a : Int, b : Int) => a + b
val minus = (a : Int, b : Int) => a - b
val max = (a : Int, b : Int) => if (a > b) a else b
val min = (a : Int, b : Int) => if (a > b) b else a // 调用
val s = calcForThis(sum)
// val s = calcForThis(minus)
// val s = calcForThis(max)
// val s = calcForThis(min) // 匿名函数简化 // 原始完整调用
println(calcForThis((a : Int, b : Int) => a + b))
// 对匿名简化
println(calcForThis((a, b) => a + b))
// 参数简化
println(calcForThis( _ + _))

这和Java或者之前学习的编程不太一样

我们创建各种方法,是为了对参数进行处理,方法是为了封装逻辑

现在感觉是反过来,参数是既定的,封装的成方法了,这个感觉写起来像那个接口的感觉一样

6、函数的进一步操作

    // 1、在函数体中声明函数,然后又调用函数
def foo() {
println("foo ...")
}
foo() // 2、作为值进行传递
def foo2() : Int = {
100
}
val res = foo2() // 将函数的返回值传递给 res
val res2 = foo2() _ // 将函数自己作为值传递给 res2
val res3:() => Int = foo2 // 如果明确变量类型? 可以不使用下划线将函数作为整体传递给参数 // 3、函数入参 作为函数参数
def subjectFunction(paramFunction : (Int, Int) => Int): Int = {
paramFunction(100, 314) // subjectFunction 主体函数, paramFunction参数函数
}
subjectFunction(_ + _)
subjectFunction(_ * _) // 4、函数作为返回值返回
def f1() = { // 声明外层一个f1函数
def f2() = { // 在内层中声明一个f2函数 }
f2 _ // 并且返回f2这个函数
}
val s = f1() // 调用就是把f2函数传递给s

7、对集合的一些处理操作

    // 对数组进行操作,如何操作作为一个抽象来定义,处理完毕返回一个新的数组
def arrOp(arr : Array[Int], op : Int => Int) : Array[Int] = {
for (elem <- arr) yield op(elem)
} // 声明一个加一操作
def increaseOne(elem : Int) = {
elem + 1
} // 使用
val sourceArr = Array(1, 10, 30, 100) // 声明一个原始的数组
val newArr = arrOp(sourceArr, increaseOne) // 注意这里给方法的时候是把方法本身传递,而不是调用
println(newArr.mkString(",")) // 简化调用
val newArr2 = arrOp(sourceArr, _ + 1)

8、案例练习:

    // 声明匿名函数给fun变量
val fun = (a : Int, a2 : String, a3 : Char) => {
if(a == 0 && a2 == "" && a3 == '0') false
else true
} // 调用
println(fun(0, "", '0'))

9、初见柯里化

    // 但是这段声明的语法看不太懂
def func(i: Int): String => (Char => Boolean) = {
def f1(s : String) : Char => Boolean = {
def f2(c : Char) : Boolean = {
if(i == 0 && s == "" && c == '0') false
else true
}
f2
}
f1
} // 简写
def func2(i: Int): String => (Char => Boolean) = {
(s : String) => {
(c : Char) => {
if(i == 0 && s == "" && c == '0') false else true
}
}
}
// 最外层有声明参数类型,也可以被省略
def func3(i: Int): String => (Char => Boolean) = {
s => c => if(i == 0 && s == "" && c == '0') false else true
}
// 柯里化?
def func4(i: Int)(s: String)(c : Char):Boolean = {
if(i == 0 && s == "" && c == '0') false else true
} // 这里肯定看不懂
println(func(0)("")('0')) // 这样来拆解出来 是这样调用的,只是没有变量接受,直接匿名进行调用了
val resultFunction1 = func(0)
val resultFunction2 = resultFunction1("")
val res = resultFunction2('0')
println(res)

10、案例:

    // 闭包 & 柯里化

    // 闭包概念 : 一个函数,访问了外部的局部变量的值,这个函数和所在的范围称为闭包
// 意义在于外部函数知晓完毕出栈之后,需要保留部分的参数内容,给内部函数进行计算和调用 // 案例 将固定加数作为另一个参数传入,但是是作为第一层参数传入
def addByParam():Int => Int = {
val a = 4
def addByPa2(b : Int): Int = {
a + b
}
addByPa2
} def addByParam2(a:Int):Int => Int = {
def addByPa2(b : Int): Int = {
a + b
}
addByPa2
} def addByParam3(a:Int):Int => Int = a + _
// 柯里化 把一个参数列表的多个参数,变成多个参数列表
val res = addByParam2(39)(42) def addCurrying(a : Int)(b : Int) = {
a + b
}
addCurrying(39)(42)

11、递归 Recursive

    /**
* Scala的递归
* 1、方法调用的是自身
* 2、必须存在可以结束的逻辑
* 3、参数应该有规律
* 4、递归必须声明返回类型
*/
// 阶乘案例
def factorial(n : Int): Int = {
if (n == 0) return 1
factorial(n - 1) * n
} // 尾递归
def tailFact(n : Int)= {
def loop(n : Int, currRes : Int) : Int = {
if (n == 0) return currRes
loop(n - 1, currRes * n)
}
loop(n, 1)
}

12、抽象控制

    // 控制抽象

    /**
* 这里演示一段Java写法
*/
val a = 100 // 声明一个常量
def someFunction(s : Int) = { // 声明函数
println(s)
}
someFunction(100) // 一般来说就是直接注入实际可见的值
someFunction(a) // 或者是变量 /**
* Scala 希望不出现这些变量和字面值
* 因为函数代表了一切内容
*/
def returnTen() = 10
someFunction(returnTen()) // 要以这种方法来进行入参的表达方式,就是控制抽象

13、传名参数

    // 传名参数,强调的是参数是一段代码块,执行包括代码块中的内容
def fun(a : => Int) = {
println(s"a : ${a}")
println(s"a : ${a}")
} def f1() = {
println("f1 called")
12
} // 使用
fun(f1()) // f1被调用了两遍 a即表示函数,出现一次调用一次 fun(23) // 为什么可以传递23? /**
* 因为23就是一个函数的返回
*/
() => 23

14、实现自定义循环的案例

    // 实现自定义循环
def customWhile(condition : Boolean):(=> Unit)=> Unit= {
def doCustomLoop (operate : => Unit): Unit = {
if (condition) {
operate
customWhile(condition) (operate)
}
}
doCustomLoop _
} // 柯里化表达
def customWhile2(condition: => Boolean)(operate: => Unit): Unit = {
if (condition) {
operate
customWhile2(condition)(operate)
}
} var n = 10
customWhile2(n > 0) {
println(n)
n -= 1
}

15、懒加载处理

    val sum = (a : Int,b : Int) => {
println("sum has been called")
a + b
}
val minus = (a : Int,b : Int) => {
println("minus has been called")
a - b
} val result1 : Int = minus(11, 31)
// 惰性加载
lazy val result2 : Int = sum(11, 31) println("- - - 函数应该被调用了 - - -")
println(s"函数应该被调用了 ${result2} ${result1}")

【Scala】03 函数的更多相关文章

  1. Python函数03/函数名的第一类对象及使用/f 格式化/迭代器/递归

    Python函数03/函数名的第一类对象及使用/f 格式化/迭代器/递归 目录 Python函数03/函数名的第一类对象及使用/f 格式化/迭代器/递归 内容纲要 1.函数名的第一类对象及使用 2.f ...

  2. Scala语法03 - 函数

  3. scala匿名函数

    package com.ming.test import scala.math._ object AnonymousFunc { def valueAtOneQuarter(f:(Double)=&g ...

  4. Scala应用函数

    我们使用“_” 来代替单个的参数,实际上你也可以使用“_”来代替整个参数列表,比如说,你可以使用 print _ 来代替 println (_). someNumbers.foreach(printl ...

  5. Scala 匿名函数

    Scala 中定义匿名函数的语法很简单,箭头左边是参数列表,右边是函数体. 使用匿名函数后,我们的代码变得更简洁了. 下面的表达式就定义了一个接受一个Int类型输入参数的匿名函数: var inc = ...

  6. Scala学习——函数高级操作

    scala函数高级操作 一.字符串高级操作 多行字符串和插值 package top.ruandb.scala.Course06 object StringApp { def main(args: A ...

  7. Scala学习——函数

    一.函数的定义(def) object FunctionApp { //定义函数:方法体内最后一行为返回值,不需要使用return def add(a:Int,b:Int):Int={ a + b } ...

  8. Scala的函数,高阶函数,隐式转换

    1.介绍 2.函数值复制给变量 3.案例 在前面的博客中,可以看到这个案例,关于函数的讲解的位置,缺省. 4.简单的匿名函数 5.将函数做为参数传递给另一个函数 6.函数作为输出值 7.类型推断 8. ...

  9. PHP学习笔记03——函数

    <!DOCTYPE unspecified PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www. ...

  10. javascript . 03 函数定义、函数参数(形参、实参)、函数的返回值、冒泡函数、函数的加载、局部变量与全局变量、隐式全局变量、JS预解析、是否是质数、斐波那契数列

    1.1 知识点 函数:就是可以重复执行的代码块 2.  组成:参数,功能,返回值 为什么要用函数,因为一部分代码使用次数会很多,所以封装起来, 需要的时候调用 函数不调用,自己不会执行 同名函数会覆盖 ...

随机推荐

  1. Linux Shell命令提示样式修改

    对linux shell命令样式进行美化. 修改前的效果: 修改后的效果: 直接给出.bashrc脚本代码: 1 # ~/.bashrc: executed by bash(1) for non-lo ...

  2. ETL工具-nifi干货系列 第五讲 处理器GenerateFlowFile

    1.今天我们一起来学习处理器GenerateFlowFile.这个处理器创建带有随机数据或自定义内容的 FlowFiles.GenerateFlowFile 对于负载测试.配置和模拟非常有用.从工具栏 ...

  3. C程序函数调用&系统调用

    理解程序的执行 我们要知道CPU可以自由地访问寄存器.内存.另外,程序是由操作系统执行的,所以操作系统能够控制程序的所有执行情况,限制程序的行为. 程序地执行过程: 程序是一个二进制文件,包含程序的代 ...

  4. javascript class 方法的this指向问题

    踩坑记录 JavaScript 的 class 里面有两种定义方法的方式 普通函数(fun1) 箭头函数(fun2) class Obj { func1() { // write some code. ...

  5. spring项目中读取resources下的文件

    spring项目中读取resources下的文件 我们都知道,spring项目经过maven打包后,可以打成jar包或可解压的war包 a. war包是需要外置的web容器去运行的,是需要先解压的 b ...

  6. IDEA环境编译Spring源码

    一.下载源码 1.官网下载 官网地址 如下图 2.github git下载 github地址 如下图 3.gitee git下载(国内推荐使用) gitee地址 如图 查看对应的gradle版本 在下 ...

  7. linux命令查看内存命令free -h whereis locate find查找命令

    linux命令查看内存命令free -h  whereis locate find查找命令 1.free -h root@hz-auto-eureka-test-03:/usr/local/tomca ...

  8. #PowerBi 1分钟学会,用PowerBi获取数据库最近90天的数据(DATE_SUB)

    在powerbi报表中,我们往往会对数据源进行日常刷新,powerbi链接了数据库的情况下,根据日期灵活取数是我们必须掌握的一个技能. 在本文中,我们将介绍如何使用 SQL 的 DATE_SUB 函数 ...

  9. tar命令 --null -T 参数详解

    tar 命令的 --null 和 -T 参数可以一起使用,以从 null 设备读取文件名,并将这些文件名传递给 tar 命令来处理. --null 参数的作用是将文件名作为 null 字符分隔的字符串 ...

  10. ubuntu 18.0.4.6部署k8s 1.24

    一.系统安装 https://ubuntu.com/download/server 二.安装containerd sudo su - apt-get remove docker \ docker-cl ...