Scala函数

文章目录


一、第1关:方法

任务描述

本关任务:根据三角形的三边长 a、b、c,返回三角形的面积。

任意三角形面积公式-海伦公式

已知三角形三边a、b、c,则

S

三角形

p(p−a)(p−b)(p−c)

p=

2

1

(a+b+c)

相关知识

为了完成本关任务,你需要掌握:

什么是方法;

方法的使用。

方法

定义函数最常用的方式是作为某个对象的成员。这种函数被称为方法(method)。换句话来说在类中定义的函数即是方法。

定义方法的基本格式是:

def 方法名称 (参数列表):返回值类型 = 方法体

如果你不写等于号和方法主体,那么方法会被隐式声明为抽象(abstract),包含它的类型也将是一个抽象类型。

方法定义由一个 def 关键字开始,接着为该方法的名称,紧接着是可选的参数列表(意味着可写可不写),一个冒号 : 和方法的返回类型,一个等于号 = ,最后是方法的主体。

接着我们来看几个定义方法的示例:

参数列表为空,返回类型为 Unit 的方法:

def f1() : Unit = {

println("f1")

}

返回 Unit 类型的函数,但是没有显式指定返回类型。(当然也可以返回非 Unit 类型的值):

def f2() = {

println("f2")

}

如果参数列表有多个时,可以使用逗号连接,当用 return 进行返回时,方法中必须明确指定返回值类型:

def addInt( a:Int, b:Int ) : Int = {

var sum:Int = 0

sum = a + b

return sum

}

返回值类型有多种可能,此时也可以省略 Unit:

def f3(content: String) = {

if(content.length >= 3)

content + "喵喵喵~"

else

3

递归方法必须明确指定方法返回值类型:

def factorial(n: Int): Int = {

if(n <= 0)

1

else

n * factorial(n - 1)

}

方法的最简形式:

def m = 100

方法的调用

Scala 提供了多种不同的方法调用方式:

直接通过方法名(参数列表)调用:

functionName( 参数列表 )

如果方法使用了实例的对象来调用,我们可以使用类似 Java 的格式 (使用 . 号):

instance.\]functionName( 参数列表 ) 这里我们主要介绍第一种: 示例: object Test { def main(args: Array\[String\]) { println( "Returned Value : " + addInt(5,7) ); } def addInt( a:Int, b:Int ) : Int = { var sum:Int = 0 sum = a + b return sum } } 执行结果: Returned Value : 12 注意:当方法没有参数列表或参数列表为空时,调用该方法时可以省略方法后的括号。 编程要求 仔细阅读右侧编辑区内给出的代码框架及注释,在 Begin-End 间编写程序代码,定义一个 area 方法,该方法具有三个参数,类型都是 Int 型,分别代表三角形的三条边长,返回值类型为 Double;要求根据三角形的三边长,返回三角形的面积。 测试说明 平台将使用测试集运行你编写的程序代码,若全部的运行结果正确,则通关。 例: 测试输入: 3 4 5 预期输出: 三角形的面积为:6.00 ### 实验代码: ```python import scala.io.StdIn object Triangle { /********** Begin *********/ def area(a: Int, b: Int, c: Int): Double = { val s = (a + b + c) / 2.0 math.sqrt(s * (s - a) * (s - b) * (s - c)) } /********** End *********/ def main(args: Array[String]): Unit = { val a: Int = StdIn.readInt() val b: Int = StdIn.readInt() val c: Int = StdIn.readInt() printf("三角形的面积为:%.2f", area(a, b, c)) } } ``` ![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/d6a55841aaa74bdababc2eea289bf56e.png) ## 二、第2关:Scala函数以及函数调用 任务描述 本关任务:计算小明请完 5 顿饭之后还剩多少钱。 相关知识 为了完成本关任务,你需要掌握: 什么是函数; 如何调用函数。 函数定义 Scala 作为支持函数式编程的语言,Scala 函数式编程是 Scala 的重中之重,高级函数也是其独特的一个特性。首先,函数/变量同是一等公民,函数与变量同等地位,函数的定义可以单独定义,可以不依赖于类、接口或者 object,可以独立存在、独立使用,并且可以赋值给变量。 我们上一关所学习的方法就是函数的一种形式。接下来我们来看函数的定义: (函数的参数列表)=\>{函数体内容} 由于该函数需要被别人调用,所以要用一个变量来引用。 val 变量名称 =(函数的参数列表)=\>{函数体内容} 示例: // 将 x 的值加 1 val increase = (x:Int) =\> x+1 =\> 表示该函数将左侧的内容(任何整数 x)转换成右侧的内容(x+1)。 因此,这是一个将任何整数 x 映射成 x+1 的函数。 复杂的定义形式: val 变量名称:(输入参数类型) =\> 返回值类型 =(输入参数的引用)=\>{函数体内容} 示例: // 计算 x 和 y 的和 val add: (Int, Int) =\> Int = (x:Int, y:Int)=\> x+y 如果你想要在函数中包含多于 1 条语句,可以将函数体用花括号括起来,每条语句占一行,组成一个代码块(block)。跟方法一样,当函数值被调用时,所有的语句都会被执行,并且该函数的返回值就是对最后一个表达式求值的结果。 参数列表对于方法是可选的,但是对于函数是强制的。 方法可以没有参数列表,参数列表也可以为空。但是函数必须有参数列表(参数列表可以为空)。 而函数可以直接赋值给变量,可以让函数很方便的传递。 函数调用 传值调用和传名调用 Scala 的解释器在解析函数参数(function arguments)时有两种方式: 传值调用(call-by-value):先计算参数表达式的值(reduce the arguments),再应用到函数内部; 传名调用(call-by-name):将未计算的参数表达式直接应用到函数内部。 object Test { def main(args: Array\[String\]): Unit = { callByValue(something()) println("------------------------------") callByName(something()) } def something() = { println("calling something") } def callByValue(x: Int) = { println("x1=" + x) println("x2=" + x) } def callByName(x: =\> Int) = { println("x1=" + x) println("x2=" + x) } } 执行结果: calling something x1=1 x2=1 *** ** * ** *** calling something x1=1 calling something x2=1 从执行结果上来看,我们可以得出: 在进入函数内部前,传值调用方式就已经将参数表达式的值计算完毕,而传名调用是在函数内部进行参数表达式的值计算的。 这就造成了一种现象,每次使用传名调用时,解释器都会计算一次表达式的值。 指定函数参数名调用 一般情况下函数调用参数,就按照函数定义时的参数顺序一个个传递。但是我们也可以通过指定函数参数名,并且不需要按照顺序向函数传递参数。 object Test { def main(args: Array\[String\]) { printInt(7,5); // 默认按参数顺序调用 println("------------------------------") printInt(b=5, a=7); // 指定函数参数名调用 } def printInt( a:Int, b:Int ) = { println("Value of a : " + a ); println("Value of b : " + b ); } } 执行结果: Value of a : 7 Value of b : 5 *** ** * ** *** Value of a : 7 Value of b : 5 注意:当参数列表为空时,直接写方法名可以调用方法,而函数名只是代表函数对象本身。因为保存函数字面量的变量(又称为函数名或者函数值)本身就是实现了 FunctionN 特质的类的对象,要调用对象的 apply 方法,就需要使用obj()的语法。所以函数名后面加括号才是调用函数。如下: 如果我们想要直接操纵方法的话,可以使用下划线(_)将方法转换为函数。 object TestMap { def ttt(f:Int =\> Int):Unit = { val r = f(10) println® } val f0 = (x : Int) =\> x \* x //定义了一个方法 def m0(x:Int) : Int = { //传递进来的参数乘以10 x \* 10 } //将方法转换成函数,利用了神奇的下滑线 val f1 = m0 _ def main(args: Array\[String\]): Unit = { ttt(f0) //通过m0 _将方法转化成函数 ttt(m0 _) // 如果直接传递的是方法名称,scala相当于是把方法转成了函数 ttt(m0) } } 编程要求 仔细阅读右侧编辑区内给出的代码框架及注释,在 Begin-End 间编写程序代码,计算小明请完 5 顿饭之后还剩多少钱。具体要求如下: 变量 money 定义了小明的钱数,初始值为 1000 元; eat 方法中定义了每请一顿饭消耗多少元; balance 方法实现计算小明还剩多少元的功能; 定义一个 printMoneyByValue 方法,该方法传名调用 balance 函数,类型为 Int 的参数,打印连续五次调用所给参数后,小明还剩多少元; 定义一个 printMoneyByName 方法,该方法传值调用 balance 函数,类型为 Int 的参数,打印连续五次调用所给参数后,小明还剩多少元; 输出格式:"你的余额现在为:xx",xx 为剩余钱数。 测试说明 平台将使用测试集运行你编写的程序代码,若全部的运行结果正确,则通关。 例: 测试输入:无 预期输出: 你的余额现在为:950 *** ** * ** *** 你的余额现在为:650 ### 实验代码: ```python object Test { var money = 1000 // 吃一顿消费50 def eat(): Unit = { money = money - 50; } // 余额 def balance(): Int = { eat() money } /********** Begin *********/ def printMoneyByValue(balanceFunc: => Int): Unit = { val currentMoney = balanceFunc println(s"你的余额现在为:$currentMoney") } def printMoneyByName(mealCost: Int): Unit = { for (_ <- 1 to 5) { eat() } val remainingMoney = money println(s"你的余额现在为:$remainingMoney") } /********** End *********/ def main(args: Array[String]): Unit = { printMoneyByValue(balance()) println("-------------------") printMoneyByName(balance()) } } ``` ![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/e32bb1f0876a4f82ab4ac2cc3960b221.png) *** ** * ** ***

相关推荐
Java水解4 小时前
Scala深入面向对象:类、对象与伴生关系
后端·scala
数据智能老司机7 小时前
精通 Python 设计模式——分布式系统模式
python·设计模式·架构
数据智能老司机8 小时前
精通 Python 设计模式——并发与异步模式
python·设计模式·编程语言
数据智能老司机8 小时前
精通 Python 设计模式——测试模式
python·设计模式·架构
数据智能老司机8 小时前
精通 Python 设计模式——性能模式
python·设计模式·架构
c8i8 小时前
drf初步梳理
python·django
每日AI新事件8 小时前
python的异步函数
python
这里有鱼汤9 小时前
miniQMT下载历史行情数据太慢怎么办?一招提速10倍!
前端·python
databook18 小时前
Manim实现脉冲闪烁特效
后端·python·动效
程序设计实验室19 小时前
2025年了,在 Django 之外,Python Web 框架还能怎么选?
python