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))
  }
}

二、第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())
  }

}

相关推荐
结衣结衣.4 分钟前
C++ 类和对象的初步介绍
java·开发语言·数据结构·c++·笔记·学习·算法
学习使我变快乐6 分钟前
C++:静态成员
开发语言·c++
TJKFYY6 分钟前
Java.数据结构.HashSet
java·开发语言·数据结构
杰哥在此15 分钟前
Python知识点:如何使用Multiprocessing进行并行任务管理
linux·开发语言·python·面试·编程
小白学大数据15 分钟前
User-Agent在WebMagic爬虫中的重要性
开发语言·爬虫·http
ROBIN__dyc21 分钟前
C语言基本概念
c语言·开发语言
zaim12 小时前
计算机的错误计算(一百一十四)
java·c++·python·rust·go·c·多项式
学习使我变快乐2 小时前
C++:const成员
开发语言·c++
500了3 小时前
Kotlin基本知识
android·开发语言·kotlin
不知所云,5 小时前
qt cmake自定义资源目录,手动加载资源(图片, qss文件)
开发语言·qt