Scala详解(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.method
    ​
    object 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.method
    ​
    object 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.method
    ​
    object 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.method
    ​
    object 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.method
    ​
    object 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 + y
    ​println(sum(3, 5))
    ​}
    ​
    }
  3. 如果需要细分:定义在类中的函数称之为方法,定义在其他地方的就是函数

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

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

    package com.fesco.function
    ​
    object 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.function
    ​
    object 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.function
    ​
    object 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 + y
    ​add _}*/// 如果在定义函数的时候,指定了返回值类型,那么返回函数的时候,可以不用添加_def sum(x: Int): Int => Int = {def add(y: Int): Int = x + y
    ​add}
    ​
    ​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.function
    ​
    object ClosureDemo {
    ​def main(args: Array[String]): Unit = {
    ​// 函数rand中,接收了一个变量n// 正常情况下而言,当rand函数执行结束之后,rand函数所占用的内存应该立即释放// 因此变量n应该也立即销毁 -> 此时变量n的生命周期随着函数rand的结束而结束def rand(n: Int): Int = (Math.random() * n).toInt
    ​println(rand(10))println(rand(50))
    ​def random(n: Int) = {def r() = (Math.random() * n).toInt
    ​r _}// 当执行完这句话之后,random函数就应该执行完了// random函数执行完成之后,如果变量n随着random函数一起被销毁// 那么会导致产生嵌套的r函数无法执行,所以此时n不会被销毁而是被保留// 此时n的生命周期不再随着random函数结束而结束// n的生命周期被延长,这个过程就称之为闭包val result = random(5)println(result())
    ​}
    ​
    }

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

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

相关文章

博客系统项目测试(selenium+Junit5)

在做完博客系统项目之后&#xff0c;需要对项目的功能、接口进行测试&#xff0c;利用测试的工具&#xff1a;selenium以及Java的单元测试工具Junit进行测试&#xff0c;下面式测试的思维导图&#xff0c;列出该项目需要测试的所有测试用例&#xff1a; 测试结果&#xff08;全…

Composer 安装与配置

Composer 是 PHP 领域中非常重要的一个工具&#xff0c;它作为 PHP 的依赖管理工具&#xff0c;帮助开发者定义、管理、安装项目所依赖的外部库。Composer 的出现极大地简化了 PHP 项目的构建和管理过程&#xff0c;使得开发者可以更加专注于代码的编写和功能的实现。 Compose…

当年明月在,曾照彩云归

肯定是非常辛苦和疲惫的 感谢一路走来帮助我的人 参考资料 小红书up主 哈嘿哈 孤独的演说家 白菜 run 今天你喝水了吗 HongReee 是个笨蛋呀 北航六人行 极限30天 青辰 懒哥 研究生啦(李珂欣) 林酱 QQ 雨梧桐🍁 Ctrl 林林 什么技术+答辩老师+代码什么作用+准备ppt+系统如何实…

Android12 user版本无法进入recovery问题

1.前言 之前Android9的时候公司自己写了一个简单的OTA在线升级&#xff0c;调用Recovery升级系统。后来Android12的时候想使用AB升级&#xff0c;发现我这套代码AB升级完成了之后&#xff0c;重启却无法切到B&#xff0c;所以造成升级一直是失败的。后来想着要不还是把AB关掉直…

linux下安装nacos2.2.0

1、获取下载地址并下载 1.1、打开nacos官网 1.2、找到对应版本&#xff0c;点进去 ## 1.3、复制地址 1.4下载 # 进入要安装的目录&#xff0c;cd /usr/local/src # 执行wget https://github.com/alibaba/nacos/releases/download/2.2.0/nacos-server-2.2.0.tar.gz2、 安装…

springboot数字化智慧城市管理系统源码

目录 ​系统开发环境 系统功能模块 系统特点 1、智慧城管移动端 2、案件受理 3、AI视频智识别分析 系统应用价值 1、提升案件办理效率 2、提升监管效能 3、提升行政执法水平 4、推进行政执法创新 智慧城管综合执法办案系统功能 现场移动执法 一般程序案件的网上办…

Modern C++:提升开发效率的语法糖详解与实例

引言 Modern C&#xff0c;特指自C11以来的一系列标准更新&#xff0c;引入了大量旨在增强语言表达力、提高代码清晰度与开发效率的新特性。其中&#xff0c;被称为“语法糖”的便捷语法构造尤为引人注目。这些语法糖不仅简化了程序员的日常编码工作&#xff0c;减少了出错几率…

D00178-变压器设备漏油的检测数据集338张含VOC标签

数据集一部分来自真实场景&#xff0c;由于真实场景下样本较少&#xff0c;共338张&#xff0c;采用VOC标注格式 完整链接见文末 完整链接&#xff1a; D00178-变压器设备漏油的检测数据集338张含VOC标签

今日arXiv最热大模型论文:清华大学发布,ChatGML又添新功能,集成“自我批评”,提升数学能力

引言&#xff1a;数学问题解决在大语言模型中的挑战 在当今的人工智能领域&#xff0c;大语言模型&#xff08;Large Language Models&#xff0c;LLMs&#xff09;已经在理解和生成人类语言方面取得了显著的进展。这些模型在文本摘要、问答、角色扮演对话等多种语言任务上展现…

现在租一个服务器多少一个月啊?

现在租一个服务器多少一个月&#xff1f;优惠价格低至3.8元1个月&#xff0c;租用一个月云服务器收费价格表&#xff1a;阿里云和腾讯云2核2G3M服务器优惠价格61元一年&#xff0c;折合一个月5元&#xff0c;京东云轻量云主机5.8元一个月&#xff0c;华为云服务器优惠价格3.8元…

CSS设置内外边距

目录 内边距&#xff08;paddingj&#xff09;&#xff1a; 前言&#xff1a; 设置内边距&#xff1a; 外边距&#xff08;margin&#xff09;&#xff1a; 前言&#xff1a; 设置外边距&#xff1a; 补充(折叠)&#xff1a; 内边距&#xff08;padding&#xff09;&#…

数组、数组对象去重

一、纯数组 1. 纯数组 - 利用new Set()集合 Array.from(new Set(arr)); Set是es6新增的数据结构&#xff0c;似于数组&#xff0c;但并非真正的数组&#xff0c;我们可以称之为类数组对象&#xff0c;它的一大特性就是所有元素都是唯一的&#xff0c;没有重复的值。 Array.f…

Spring MVC 文件上传和下载

文章目录 Spring MVC 中文件上传利用 commons-fileupload 文件上传使用 Servlet 3.1 内置的文件上传功能 Spring MVC 中文件下载 Spring MVC 中文件上传 为了能上传文件&#xff0c;必须将 from 表单的 method 设置为 POST&#xff0c;并将 enctype 设置为 multipart/form-data…

阿里云服务器怎么购买价格更便宜?优惠大揭秘!

阿里云服务器租用价格表2024年最新&#xff0c;云服务器ECS经济型e实例2核2G、3M固定带宽99元一年&#xff0c;轻量应用服务器2核2G3M带宽轻量服务器一年61元&#xff0c;ECS u1服务器2核4G5M固定带宽199元一年&#xff0c;2核4G4M带宽轻量服务器一年165元12个月&#xff0c;2核…

cesium 平滑显示billboard 透明度

描述&#xff1a;加载billboard的时候&#xff0c;要么是显示&#xff0c;要么是隐藏&#xff0c;不能平滑的显示&#xff0c;有个从不显示到显示的过程 解决方案&#xff1a;创建billboard的时候给一个color&#xff0c;颜色为(255,255,255)&#xff0c;透明度从0-1 let opaci…

C#:循环中断

任务描述 实现九九乘法表&#xff0c;按照编程要求&#xff0c;使用break跳出循环 测试说明 测试过程&#xff1a; 平台将编译用户补全代码&#xff0c;并根据程序的输出判断程序是否正确。 以下是测试样例&#xff1a; 测试输入&#xff1a; 预期输出&#xff1a; we found…

A Learning-Based Approach for IP Geolocation(2010年)

下载地址:Towards IP geolocation using delay and topology measurements | Proceedings of the 6th ACM SIGCOMM conference on Internet measurement 被引次数:185 Eriksson B, Barford P, Sommers J, et al. A learning-based approach for IP geolocation[C]//Passive …

【UE Niagara】自定义模块的简单使用

效果 步骤 新建一个Niagara系统&#xff0c;使用“Empty”模板&#xff0c;这里命名为“NS_Custom” 打开“NS_Custom”&#xff0c;添加一个“Spawn Burst Instantaneous”来单次生成1个粒子 在“Emitter State”模块中&#xff0c;设置生命循环模式为“Self”&#xff0c;循…

【洛谷 B3611】【模板】传递闭包 题解(有向图+邻接矩阵+Floyd算法+传递闭包+位运算)

【模板】传递闭包 题目描述 给定一张点数为 n n n 的有向图的邻接矩阵&#xff0c;图中不包含自环&#xff0c;求该有向图的传递闭包。 一张图的邻接矩阵定义为一个 n n n\times n nn 的矩阵 A ( a i j ) n n A(a_{ij})_{n\times n} A(aij​)nn​&#xff0c;其中 a i…

【vue】toRef,toRefs

toRef&#xff1a;把一个 响应式对象 转换为对应的ref变量toRefs&#xff1a;把一个 响应式对象 转换为对应的ref对象 代码 <template><P>mname: {{ mname }} </P><P>mage: {{ mage }} </P><P>msex: {{ msex }} </P><P>mhobb…