Scala之函数Day-2

Scala

函数(Function)

概述

  1. 将一段逻辑进行封装便于进行重复使用,被封装的这段逻辑就是函数。在Scala中,必须通过def来定义函数

  2. 基本语法

    def 函数名(参数列表) : 返回值类型 = {函数体return 返回值
    }
    
  3. 案例

    // 案例:定义函数计算两个整数的和
    // 标准写法
    def sum(a: Int, b: Int): Int = {return a + b
    }
    // 因为在Scala中,所有的结构都必须有返回值
    // 所以在函数中,如果不指定,默认会将最后一行的计算结果作为返回值
    // 也因此可以省略return不写
    def sum(a: Int, b: Int): Int = {a + b
    }
    // 如果函数体只有一句话,那么此时也可以省略{}不写
    def sum(a: Int, b: Int): Int = a + b
    // 参数类型非常明确,并且可以由计算结果来确定返回值类型
    // 那么也就意味着此时可以推导出结果类型,因此可以省略返回值类型不写
    def sum(a: Int, b: Int) = a + b
    
  4. 练习:定义一个函数,判断一个数字是否是质数

    package com.fesco.methodobject MethodExer1 {def main(args: Array[String]): Unit = {println(isPrime(19))println(isPrime(25))}// 判断数字是否是质数/*定义函数,明确问题:1. 是否需要参数 - 是否有未知量来参与运算,需要在调用函数的时候传入这个数据2. 明确结果类型 - 判断是不是的问题,那么结果类型应该是布尔值3. 明确计算逻辑*/def isPrime(n: Int): Boolean = {// 判断传入的参数n是否是一个质数// 1及以下的数字,不是质数if (n <= 1) falseelse if (n == 2) trueelse {for (i <- 2 until n) {if (n % i == 0) return false}// 如果整个循环结束,都没有返回false,那么说明所有数字都无法整除true}}}
    
  5. 案例

    // 打印n行*组成的三角形
    def printStar(n: Int): Unit = {for (i <- 1 to n)println("*" * i)
    }
    // 可以推导出结果类型
    def printStar(n: Int) = {for (i <- 1 to n)println("*" * i)
    }
    // 如果返回值类型是Unit,那么此时可以省略=不写
    def printStar(n: Int) {for (i <- 1 to n)println("*" * i)
    }
    // 如果代码只有一行,并且返回值类型还是Unit,那么此时=或者{}只能省略其一
    def printStar(n: Int) =  for (i <- 1 to n) println("*" * i)
    
  6. 案例

    package com.fesco.methodobject MethodDemo3 {def main(args: Array[String]): Unit = {// 如果函数在调用的时候没有参数,()可以写可以不写println(rand100())println(rand100)// 如果函数在定义的时候就没有(),那么调用的时候也不能写()println(rand)}// 产生1-100之间的随机数def rand100():Int = (Math.random() * 100 + 1).toInt// 函数没有参数的,因此()可以省略def rand:Int = (Math.random() * 100 + 1).toInt}
    

参数

可变参数
  1. 所谓可变参数,指的是在调用函数的时候,参数个数可以变化

  2. 案例

    package com.fesco.methodobject MethodDemo4 {def main(args: Array[String]): Unit = {println(sum(4.2, 1.84, 8.741, 7.2, 2.05))}// 计算传入的数字的和// 通过*来定义可变参数def sum(nums: Double*): Double = {var sum = 0.0for (n <- nums)sum += n// 将结果返回sum}}
    
  3. 注意:函数中最多只能定义一个可变参数,并且必须放在参数列表的末尾

默认参数
  1. 默认参数,在定义函数的时候,就给参数一个默认值。在调用函数的时候,如果指定了值,就使用指定的来计算;如果没有指定,就使用默认值来计算

  2. 案例

    package com.fesco.methodobject MethodDemo5 {def main(args: Array[String]): Unit = {// 在调用函数的时候,如果没有传入折扣,那么就使用默认值println(offPrice(180))// 如果传入了折扣,那么就按照传入的折扣来计算println(offPrice(150, 0.88))}// 案例:计算打折之后的价格// 如果需要打折,那么就指定折扣// 如果不需要打折,希望off就是1def offPrice(price: Double, off: Double = 1.0): Double = {if (off <= 0 || off > 1) throw new IllegalArgumentExceptionprice * off}
    }
    

函数的调用

  1. Scala中,也是通过函数名(参数)的形式来调用函数,但是Scala提供了省略调用和带名调用

  2. 省略调用:如果函数没有参数,那么在调用函数的时候可以省略()不写

    println()
    // 省略调用
    println
    
  3. 如果函数定义的时候有(),那么在调用的时候可以写()也可以不写();如果函数定义的时候就没有(),那么调用的时候就不能有()

  4. 带名调用:在调用函数的时候,指定参数名来赋值

    package com.fesco.methodobject MethodDemo6 {def main(args: Array[String]): Unit = {info("bob", "男", 19)info(name = "bob", gender = "男", age = 19)// 带名调用的时候,参数顺序可以不一致info(gender = "男", age = 19, name = "bob")message(name = "David", age = 15)println(offPrice(180, off = 0.92))}def info(name: String, gender: String, age: Int) = println(s"姓名:$name\n性别:$gender\n年龄:$age")// 默认参数def message(name: String, gender: String = "男", age: Int) = println(s"姓名:$name\n性别:$gender\n年龄:$age")def offPrice(price: Double, vip: Int = 0, off: Double = 1) = {if (vip <= 0) price * offelse if (vip <= 3) price * 0.95 * offelse if (vip <= 7) price * 0.9 * offelse price * 0.85 * off}}
    

函数和方法

  1. Java中,函数就是方法,方法也是函数。在Scala中,函数的范围会比方法要稍微大一点

  2. Scala中,函数可以定义在任何位置,即函数可以定义在类或者函数内

    object MethodDemo7 {def main(args: Array[String]): Unit = {// 在函数中定义函数def sum(x: Int, y: Int) = x + yprintln(sum(3, 5))}}
    
  3. 如果需要细分:定义在类中的函数称之为方法,定义在其他地方的就是函数

  4. 在Scala中,函数是"一等公民",即函数可以定义在任何地方,也可以被当作参数进行传递,当作结果进行返回,当作变量被赋值

  5. 函数赋值给变量/常量

    package com.fesco.functionobject FunctionDemo1 {def main(args: Array[String]): Unit = {// 函数作为"一等公民",可以被定义在任何位置def rand(): Int = (Math.random() * 100).toInt// 调用函数打印结果println(rand())// 将函数的计算结果赋值给变量/常量val r = rand()println(r)val r2 = randprintln(r2)// 不是调用rand函数,而是把rand函数作为数据传递给f// 所以此时可以认为,f既是一个常量,也是一个函数// 常量f的数据类型是:() => Intval f: () => Int = rand _println(f)// 调用函数fprintln(f())def sum(x: Int, y: Int): Int = x + y// 将sum函数作为一个整体数据,赋值给常量s// 此时可以认为s既是一个常量,也是一个函数// s的数据是一个函数// sum的参数类型是(Int, Int),返回值是Int// 所以s的数据类型:(Int, Int) => Intval s: (Int, Int) => Int = sum _// 打印常量s的数据println(s)// 调用s中的函数println(s(3, 5))// 匿名函数val a1: (Int, Int) => Int = (x: Int, y: Int) => x + yprintln(a1)println(a1(2, 4))// 定义常量a2的时候,已经指定了要封装的参数的类型,在定义函数的时候就可以省略参数类型val a2: (Int, Int) => Int = (x, y) => x + yprintln(a2)println(a2(2, 4))}}
    

高阶函数

  1. 当一个函数的参数是另一个函数,或者返回值是另一个函数的时候,这个函数就是高阶函数

  2. 将函数作为参数进行传递

    package com.fesco.functionobject FunctionDemo2 {def main(args: Array[String]): Unit = {// 需求:定义一个函数,对两个整数进行计算,返回一个整数/*1. 明确参数a. 两个整数是未知的,所以需要以参数形式来体现b. 对这俩整数来进行计算,计算规则是未知的,所以同样,需要将计算规则以参数形式来体现2. 计算逻辑要利用传入的规则对两个参数来进行计算*/def calcInt(x: Int, y: Int, f: (Int, Int) => Int): Int = f(x, y)// 定义计算规则def times(x: Int, y: Int): Int = x * y// 调用calcInt函数,传入参数和规则println(calcInt(3, 6, times))// 新规则def subtract(x: Int, y: Int): Int = x - y// 传入规则println(calcInt(3, 6, subtract))// 可以直接传入规则println(calcInt(3, 6, (x: Int, y: Int) => {x - y}))// 当函数体只有一句的时候,{}可以省略println(calcInt(3, 6, (x: Int, y: Int) => x - y))// 定义calcInt函数的时候,就已经指定了规则f中的参数类型和结果类型,所以参数类型可以省略println(calcInt(3, 6, (x, y) => x - y))// 在匿名函数中,依次调用了参数,并且只调用一次,那么可以省略参数列表不写,用_来依次代替每一个参数println(calcInt(3, 6, _ - _))println(calcInt(3, 6, _ * _))}}
    
  3. 将函数作为结果进行返回

    package com.fesco.functionobject FunctionDemo3 {def main(args: Array[String]): Unit = {// 定义一个函数,可以依次传入两个整数求和// 可以先传入一个整数,然后再传入另一个整数// 如果只有一个参数,可以省略()不写// def sum(x: Int): (Int) => Int = {// def sum(x: Int): Int => Int = {// 如果在定义函数的时候,没有写返回值类型,而是由编译器自动推导,那么返回函数的时候,必须添加_/*def sum(x: Int) = {def add(y: Int): Int = x + yadd _}*/// 如果在定义函数的时候,指定了返回值类型,那么返回函数的时候,可以不用添加_def sum(x: Int): Int => Int = {def add(y: Int): Int = x + yadd}val r = sum(5)// r接收到是add函数println(r)// 再传入第二参数val n = r(8)println(n)// 可以第一个参数不变,改变第二个参数println(r(6))// 传入两个参数val n2 = sum(3)(6)println(n2)}}
    

闭包(closure)

  1. 闭包,指的是一个函数,如果访问了外部变量的值,那么此时这个函数以及它所处的函数,构成了闭包

  2. 闭包的特点:会延长外部函数中变量的生命周期

    package com.fesco.functionobject ClosureDemo {def main(args: Array[String]): Unit = {// 函数rand中,接收了一个变量n// 正常情况下而言,当rand函数执行结束之后,rand函数所占用的内存应该立即释放// 因此变量n应该也立即销毁 -> 此时变量n的生命周期随着函数rand的结束而结束def rand(n: Int): Int = (Math.random() * n).toIntprintln(rand(10))println(rand(50))def random(n: Int) = {def r() = (Math.random() * n).toIntr _}// 当执行完这句话之后,random函数就应该执行完了// random函数执行完成之后,如果变量n随着random函数一起被销毁// 那么会导致产生嵌套的r函数无法执行,所以此时n不会被销毁而是被保留// 此时n的生命周期不再随着random函数结束而结束// n的生命周期被延长,这个过程就称之为闭包val result = random(5)println(result())}}
    

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/807738.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

openlayer实现webgis端绘制制图及编辑

在WebGIS端制图是指通过Web浏览器界面实现地理信息数据的可视化、编辑、分析以及地图产品的制作。这一过程通常涉及以下几个关键环节&#xff1a; **1. 前端技术栈&#xff1a; •HTML/CSS/JavaScript&#xff1a;作为Web开发的基础&#xff0c;用于构建用户界面布局、样式设…

Win11又来「重大」更新!

ChatGPT狂飙160天&#xff0c;世界已经不是之前的样子。 新建了免费的人工智能中文站https://ai.weoknow.com 新建了收费的人工智能中文站ai人工智能工具 更多资源欢迎关注 Windows 11预览通道的22635.3420版本迎来了几个比较大的改进&#xff0c;主要有三个方面&#xff1a; …

一种快速移植 OpenHarmony Linux 内核的方法

移植概述 本文面向希望将 OpenHarmony 移植到三方芯片平台硬件的开发者&#xff0c;介绍一种借助三方芯片平台自带 Linux 内核的现有能力&#xff0c;快速移植 OpenHarmony 到三方芯片平台的方法。 移植到三方芯片平台的整体思路 内核态层和用户态层 为了更好的解释整个内核…

python-study-day1-(病人管理系统-带sql)

MainWindow代码 from tkinter import * from tkinter import messagebox from tkinter.ttk import Comboboxclass MianWindow(Frame):def __init__(self, masterNone):super().__init__(master, padx30, pady20)self.flag 0self.pack(expandTrue, fillBOTH)self.id StringVa…

深入OceanBase内部机制:系统架构与组件精讲

码到三十五 &#xff1a; 个人主页 心中有诗画&#xff0c;指尖舞代码&#xff0c;目光览世界&#xff0c;步履越千山&#xff0c;人间尽值得 ! 目录 1️⃣OceanBase 整体架构1.1 分区1.2 分片1.3 日志流1.4 对等节点1.5 多租户 2️⃣OceanBase 架构与组件详解2.1 存储层2.2 …

Disk Drill Enterprise for Mac v5.5.1515数据恢复软件中文版

Disk Drill 是 Mac 操作系统固有的Mac数据恢复软件&#xff1a;使用 Recovery Vault 轻松保护文件免遭意外删除&#xff0c;并从 Mac 磁盘恢复丢失的数据。支持大多数存储设备&#xff0c;文件类型和文件系统。 软件下载&#xff1a;Disk Drill Enterprise for Mac v5.5.1515激…

keepalived2.2.8+drbd9+nfs高可用存储部署

目录 一.本文基于上一篇文章keepalived环境来做的&#xff0c;主机信息如下 二.为两台虚拟机准备添加一块新硬盘设备 三.安装drbd9 1.使用扩展源的rpm包来下载 2.创建资源并挂载到新增的硬盘 3.主设备升级身份 4.主备两个设备手动切换身份演示 四.安装配置nfs 五.安装…

【YOLOv8】Yolov5和Yolov8网络结构的分析与对比

目录 一 YOLOv5 二 YOLOv8 yolo通常采用backbone-neck-head的网络结构。 Backbone 主要负责从输入图像中提取高层次的语义特征,常包含多个卷积层和池化层&#xff0c;构建了一个深层次的特征提取器。Neck通常用来进一步整合与调整backbone提取的特征&#xff0c;有利于将不同…

大话设计模式——24.迭代器模式(Iterator Pattern)

简介 提供一种方法顺序访问一个聚合对象中各个元素&#xff0c;而又不暴露该对象的内部实现。&#xff08;Java中使用最多的设计模式之一&#xff09; UML图 应用场景 Java的集合对象&#xff1a;Collection、List、Map、Set等都有迭代器Java ArrayList的迭代器源码 示例 简…

uniapp的h5项目 用命令起这个项目(vue-cli)

这里其实就相当于给uniapp h5套了一个vue-cli的壳&#xff08;纯属个人感觉&#xff09; 首先需要安装vue-cli 脚手架 npm install -g vue/cli然后创建项目&#xff08;这里需要在hbuilder创建&#xff09; vue create -p dcloudio/uni-preset-vue uniapp安装成功后它的结构…

python 用requests.get 把远程文件下载到本地

def download_file(url, save_path):response requests.get(url, streamTrue)if response.status_code 200:with open(save_path, wb) as f:for chunk in response.iter_content(chunk_size8192):if chunk:f.write(chunk)print(f"文件已成功下载到 {save_path}")el…

OSCP靶场--Dibble

OSCP靶场–Dibble 考点(前端鉴权参数修改node.js代码注入 suid cp提权 ) 1.nmap扫描 ## ┌──(root㉿kali)-[~/Desktop] └─# nmap 192.168.173.110 -sV -sC -Pn --min-rate 2500 -p- Starting Nmap 7.92 ( https://nmap.org ) at 2024-04-09 06:36 EDT Nmap scan repor…

Jackson配置处理LocalDateTime、LocalDate等java8时间类型失效的问题解决

目录 前言 一、问题排查过程 1.1 SpringMvc是如何处理请求报文和响应报文 1.2 JacksonConfig配置排查 二、导致Jackson配置失效的原因 2.1 没有addSerializer 2.2 添加了EnableMvc注解 2.3 另外有地方配置了Jacksonhttpconver覆盖了配置 总结 前言 上一篇文章《使用Ja…

java es相关操作

一.es 后期修改分片数量 在Elasticsearch中一旦索引创建后&#xff0c;分片的数量就不能直接更改。如果需要更改分片的数量&#xff0c;你需要按照以下步骤操作&#xff1a; 创建一个新的索引&#xff0c;并指定所需的分片数量。 将旧索引的数据复制到新索引中。 关闭旧索引…

K8-Prometheus部署与应用

Prometheus //Prometheus 概述&#xff1a; Prometheus 是一个开源的服务监控系统和时序数据库&#xff0c;其提供了通用的数据模型和快捷数据采集、存储和查询接口。它的核心组件 Prometheus server 会定期从静态配置的监控目标或者基于服务发现自动配置的目标中进行拉取数据…

C/C++的内存管理

栈帧最主要的作用就是存储局部数据 C语言中动态内存管理方式 C语言动态内存管理 该篇详细的讲述了C语言动态内存管理的使用&#xff0c;不太懂的小伙伴可以去了解一下 C中动态内存管理方式 首先&#xff0c;C语言内存管理的方式在C中可以继续使用。但有些地方就无能为力而且使用…

Volatility-内存取证案例1-writeup--xx大赛

题目提示&#xff1a;flag{中文} 按部就班 &#xff08;1&#xff09;获取内存镜像版本信息 volatility -f 文件名 imageinfo 通过上述可知&#xff0c;镜像版本为Win7SP1X64。 &#xff08;2&#xff09;获取进程信息&#xff1a; volatility -f 镜像名 --profile第一步获取…

第2章:计算机系统基础知识-文字摘抄(上篇)

计算机系统的分类示意图 计算机系统 嵌入式计算机 电信设备 基站网络交换移动终端 家用电子设备 视听设备厨卫电器 可穿戴电子设备医疗设备交通设备国防设备金融设备 通用计算机 个人计算机 台式电脑平板电脑 网络服务器 云存储云计算 超级计算机 计算机硬件组成 处理器存…

Python 爬虫基础:利用 BeautifulSoup 解析网页内容

1. 理解 Python 爬虫基础 在当今信息爆炸的时代&#xff0c;网络上充斥着海量的数据&#xff0c;而网络爬虫作为一种数据采集工具&#xff0c;扮演着至关重要的角色。网络爬虫是一种自动化的程序&#xff0c;可以模拟浏览器访问网页&#xff0c;获取所需信息并进行提取和整合。…

【EasyExcel使用两个Java对象来接受一个excel文件】

需求背景&#xff1a; 有时候上传文件想要写一个通用的逻辑&#xff0c;就是说&#xff0c;这个excel前面几个字段是基础字段&#xff0c;后面几个字段是定制字段。 那么为了以后上传不同的文件&#xff0c;就需要编写不同的listener去解析每种不同的excel文件&#xff0c;但是…