[读书日志]从零开始学习Chisel 第九篇:Scala的内建控制结构(敏捷硬件开发语言Chisel与数字系统设计)

6.Scala的内建控制结构

6.1 if表达式

和大部分编程语言的if表达式使用上没有区别,单句话不需要加花括号,多个语句需要加花括号,直接来看一段代码:

scala> def whichInt(x:Int) = {| if(x == 0) "Zero"| else if(x > 0) "Positive Number"| else "Negative Number"| }
def whichInt(x: Int): Stringscala> whichInt(-1)
val res33: String = Negative Number
6.2 while循环

while循环的使用方法与C语言类似,有while型循环和do...while型循环,直接来看下面的代码:

scala> def fac_loop(num:Int): Int = {| var res: Int = 1| var num1: Int = num| while(num1 != 0) {| res *= num1| num1 -= 1| }| res| }
def fac_loop(num: Int): Intscala> fac_loop(5)
val res34: Int = 120

while的风格是指令式的,if被称为表达式,因为它可以返回有用的值,而while被称为循环,因为它不会返回有用的值。Scala兼容这种形式,因为它看起来更容易阅读。实际上所有的while循环都可以通过其他函数式风格来实现,常用的各式函数的自我递归调用。例如将上面的函数重写为如下,它是一个函数式风格的求阶乘函数:

scala> def fac(num:Int): Int =| if (num == 1) 1 else num*fac(num-1)
def fac(num: Int): Intscala> fac(5)
val res35: Int = 120
6.3 for表达式与for循环

实现循环,推荐使用for循环。for循环是函数式风格的,而没有引入指令式风格。它的一般形式如下:

for(seq) yield expression,整个for表达式算一个语句,在这里seq代表一个序列。能放进for表达式中的对象必须是一个可迭代的集合,如常用列表,数组,映射,区间,迭代器,流和所有的集,它们都混入了特质Iterableyield是产生的意思,表示把前面序列中符合条件的元素拿出来,逐个应用到后面的表达式中,得到的所有结果按顺序形成一个新的集合对象。将seq展开来是这样的:

for {p <- persons			//一个生成器n = p.name				//一个定义if(n startWith "To")	//一个过滤器
} yield n

seq是由生成器,定义,过滤器三条语句组成的,以分号隔开或者放在花括号中自动推断分号。

生成器p -> person右侧是一个可迭代的集合对象,把它的每个元素逐一拿出来与左侧的模式进行匹配(模式匹配见后面的章节)如果匹配成功,那么模式中的遍历就会绑定上该元素的对于部分;如果匹配失败,则直接丢弃该元素。在这个例子中,p是一个无需定义的变量名,它构成了变量模式,简单地指向person的每个元素。

定义就是一个赋值语句,这里的n也是一个无须定义的变量名。定义并不常用,可有可无。

过滤器是一个if语句,只有它后面的表达式为真时生成器的元素才会向后传递,否则丢弃这个元素。在这里是判断person的元素的name字段是否以“To”开头。

编写以下的test.scala文件:

class Person(val name: String)object Alice extends Person("Alice")
object Tom extends Person("Tom")
object Tony extends Person("Tony")
object Bob extends Person("Bob")
object Todd extends Person("Todd")val persons = List(Alice, Tom, Tony, Bob, Todd)val To = for {p <- personsn = p.nameif(n.startsWith("To"))
} yield n@main def test() = println(To)

注意,刚才像上面原书上的写法会导致警告。对于没有被声明@infix的方法,推荐使用句点调用方法。编译后输出如下:

jia@J-MateBookEGo:~/scala_test$ scala test.scala
Compiling project (Scala 3.6.2, JVM (21))
Compiled project (Scala 3.6.2, JVM (21))
List(Tom, Tony, Todd)

for循环表达式都从生成器开始,如果一个for表达式中有多个生成器,就成为嵌套的for循环。

scala> for {| i <- 1 to 9| j <- 1 to 9| } yield i*j
val res0: IndexedSeq[Int] = Vector(1, 2, 3, 4, 5, 6, 7, 8, 9, 2, 4, 6, 8, 10, 12, 14, 16, 18, 3, 6, 9, 12, 15, 18, 21, 24, 27, 4, 8, 12, 16, 20, 24, 28, 32, 36, 5, 10, 15, 20, 25, 30, 35, 40, 45, 6, 12, 18, 24, 30, 36, 42, 48, 54, 7, 14, 21, 28, 35, 42, 49, 56, 63, 8, 16, 24, 32, 40, 48,56, 64, 72, 9, 18, 27, 36, 45, 54, 63, 72, 81)

这是99乘法表的生成代码。每当生成器生成一个匹配的元素,后面的定义会重新求值。如果后面的定义与生成器元素的值无关,尽量将定义写在外面。如果只是把每个元素应用到一个Uint类型的表达式,则是一个for循环,不是for表达式,关键字yield也可以省略:

scala> var sum = 0
var sum: Int = 0scala> for(x <- 1 to 100) sum += xscala> sum
val res1: Int = 5050
6.4 用try表达式处理异常
6.4.1抛出一个异常

可以用new构造一个异常对象,并用关键字throw手动抛出异常:

scala> throw new IllegalArgumentException
java.lang.IllegalArgumentException... 30 elided
6.4.2 try-catch

try后面可以用花括号包含任意条代码,当这些代码产生异常时,JVM不会立即抛出,而是被catch捕获,catch捕获异常后,按其后面的定义进行相应的处理。

scala> def intDivision(x:Int, y:Int) = {| try {| x / y| } catch {| case ex: ArithmeticException => println("The divisor is Zero!")| }| }
def intDivision(x: Int, y: Int): Int | Unitscala> intDivision(10,0)
The divisor is Zero!
val res3: Int | Unit = ()
6.4.3 finally

try表达式的完整形式是try-catch-finally,无论有没有异常产生,finally中的代码都会执行。通常它的作用是执行一些清理工作,比如关闭文件。try表达式可以返回有用值,但尽量避免这样的做法。

6.5 match表达式

match表达式作用类似于switch,是把作用对象与定义的模式逐个比较,按匹配的模式执行相应的操作。

scala> def something(x: String) = x match {| case "Apple" => println("Fruit!")| case "Tomato" => println("Vegetable!")| case "Cola" => println("Beverage!")| case _ => println("Huh?")| }
def something(x: String): Unitscala> something("Cola")
Beverage!scala> something("Toy")
Huh?
6.6 关于conyinue和break

一言以蔽之,这是指令式编程常用的关键字,但它们并不是必须的。使用导入库的方法可以使用,但Scala不推荐使用这两个关键字,需要通过自己修改代码实现其他的方案。

6.7 关于变量的作用域

变量的作用域是以花括号为边界的,重名的情况下优先使用内部变量,超出内部变量的范围则使用外部变量。

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

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

相关文章

AI大模型-提示工程学习笔记5

卷首语&#xff1a;我所知的是我自己非常无知&#xff0c;所以我要不断学习。 写给AI入行比较晚的小白们&#xff08;比如我自己&#xff09;看的&#xff0c;大神可以直接路过无视了。 零提示是什么 “零提示”&#xff08;Zero-shot&#xff09;是指在没有提供任何特定示例…

全国青少年信息学奥林匹克竞赛(信奥赛)备考实战之循环结构(while循环应用)

在 C 编程的世界里&#xff0c;循环结构是掌控程序流程的关键工具之一&#xff0c;而while循环更是其中的经典。它就像一个不知疲倦的小卫士&#xff0c;只要条件满足&#xff0c;就会持续执行特定的代码块&#xff0c;可以解决诸多复杂的编程任务。本文就一同深入探索while循环…

CK18——肝损伤无创诊断标志物

肝脏作为人体至关重要的代谢与解毒器官&#xff0c;极易遭受病毒、药物、酒精及不良饮食等多种因素的损害&#xff0c;进而引发一系列如非酒精性脂肪肝&#xff08;NAFLD&#xff09;、肝纤维化、肝硬化、肝细胞癌以及各类肝炎等病症。因此&#xff0c;确定一种高可靠性、非侵入…

.NET Core + Kafka 开发指南

什么是Kafka Apache Kafka是一个分布式流处理平台,由LinkedIn开发并开源,后来成为Apache软件基金会的顶级项目。Kafka主要用于构建实时数据管道和流式应用程序。 Kafka 架构 从下面3张架构图中可以看出Kafka Server 实际扮演的是Broker的角色, 一个Kafka Cluster由多个Bro…

软件体系结构与设计模式

在软件开发中&#xff0c;软件体系结构和设计模式是两个至关重要的概念。它们帮助开发者设计出易于理解、可扩展、可维护的系统。尽管这两个概念密切相关&#xff0c;但它们分别关注系统的不同方面&#xff1a;软件体系结构关注的是系统整体结构的设计&#xff0c;而设计模式则…

[离线数仓] 总结二、Hive数仓分层开发

接 [离线数仓] 总结一、数据采集 5.8 数仓开发之ODS层 ODS层的设计要点如下: (1)ODS层的表结构设计依托于从业务系统同步过来的数据结构。 (2)ODS层要保存全部历史数据,故其压缩格式应选择压缩比率,较高的,此处选择gzip。 CompressedStorage - Apache Hive - Apac…

Unity3D仿星露谷物语开发19之库存栏丢弃及交互道具

1、目标 从库存栏中把道具拖到游戏场景中&#xff0c;库存栏中道具数相应做减法或者删除道具。同时在库存栏中可以交换两个道具的位置。 2、UIInventorySlot设置Raycast属性 在UIInventorySlot中&#xff0c;我们只希望最外层的UIInventorySlot响应Raycast&#xff0c;他下面…

阿里云代理商热销产品推荐

在数字化浪潮的推动下&#xff0c;企业对于云计算的依赖日益加深。阿里云&#xff0c;作为中国领先的云计算服务提供商&#xff0c;为企业提供了丰富多样的云产品和服务。本文将聚焦于阿里云代理商热销产品推荐&#xff0c;探讨其如何帮助企业高效利用云资源&#xff0c;加速数…

Python入门教程 —— 多任务

1.线程 1.1.线程安全问题 线程访问全局变量 import threading g_num = 0 def test(n):global g_numfor x in range(n):g_num += xg_num -= xprint(g_num)if __name__ == __main__:t1 = threading.Thread(target=test, args=(10,))t2 = threading.Thread(target=test, args=(…

江科大STM32入门——IIC通信笔记总结

wx&#xff1a;嵌入式工程师成长日记 &#xff08;一&#xff09;简介 STM32内部集成了硬件I2C收发电路&#xff0c;可以由硬件自动执行时钟生成、起始终止条件生成、应答位收发、数据收发等功能&#xff0c;减轻CPU的负担 支持多主机 支持7位/10位地址模式 支持不同的通讯速…

vue3 vite 动态加载路由遇到的问题

记录一下动态加载路由遇到的问题 正常使用import引入静态路由是没问题的 component: () > import(/components/ExampleComponent.vue)动态引入的时候写成import就不行了 由于后端给的路由格式比较反人类…我这边先递归把获取到的数据格式做了一个整合. const processedDa…

MySQL安装,配置教程

一、Linux在线yum仓库安装 打开MySQL官方首页&#xff0c;链接为&#xff1a;https://www.mysql.com/ 界面如下&#xff1a; 在该页面中找到【DOWNOADS】选项卡&#xff0c;点击进入下载页面。 在下载界面中&#xff0c;可以看到不同版本的下载链接&#xff0c;这里选择【My…

Elixir语言的面向对象编程

Elixir语言的面向对象编程探讨 引言 Elixir是一种基于Erlang虚拟机的函数式编程语言&#xff0c;旨在支持可扩展性和维护性。尽管Elixir的核心特性是函数式编程模型&#xff0c;但它依然能够实现面向对象编程&#xff08;OOP&#xff09;的某些特性。本文将深入探讨如何在Eli…

【工具】HTML自动识别用户正在讲话 以及停止讲话

【工具】HTML自动识别用户正在讲话 以及停止讲话 <!DOCTYPE html> <html lang"zh"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>语…

HTML5 滑动效果(Slide In/Out)详解

HTML5 滑动效果&#xff08;Slide In/Out&#xff09;详解 滑动效果&#xff08;Slide In/Out&#xff09;是一种常见的动画效果&#xff0c;使元素从一侧滑入或滑出&#xff0c;增强页面的动态感和用户体验。以下是滑动效果的详细介绍及实现示例。 1. 滑动效果的特点 动态视…

面试题: 对象继承的方式有哪些

在 JavaScript 中&#xff0c;对象继承可以通过多种方式实现。每种方法都有其特点和适用场景。以下是几种常见的对象继承方式&#xff1a; 1. 原型链继承&#xff08;Prototype Chain Inheritance&#xff09; 这是最基础的对象继承方式&#xff0c;利用了 JavaScript 的原型…

React路由拦截器详解

在React中&#xff0c;路由拦截器是一种机制&#xff0c;用于在导航到特定路由之前执行一些逻辑&#xff0c;比如权限校验、用户认证或动态路由控制。通常&#xff0c;React使用react-router-dom库来管理路由&#xff0c;通过<Routes>和<Route>定义路由规则。 实现…

力扣经典题目之219. 存在重复元素 II

今天继续给大家分享一道力扣的做题心得今天这道题目是 219. 存在重复元素 II&#xff0c;我使用 hashmap 的方法来解题 题目如下&#xff0c;题目链接&#xff1a;219. 存在重复元素 II 1&#xff0c;题目分析 此题目给我们了一个整数数组 nums 和一个整数 k &#xff0c;需要…

四、VSCODE 使用GIT插件

VSCODE 使用GIT插件 一下载git插件与git Graph插件二、git插件使用三、文件提交到远程仓库四、git Graph插件 一下载git插件与git Graph插件 二、git插件使用 git插件一般VSCode自带了git&#xff0c;就是左边栏目的图标 在下载git软件后vscode的git插件会自动识别当前项目 …

消息队列MQ(二)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 MQ学习笔记 前言一、发送者的可靠性1. 生产者重试机制2. 生产者确认机制3. 实现生产者确认 二、MQ的可靠性1. 数据持久化2. LazyQueue 前言 在用MQ实现异步调用时&#xff0…