【PL理论】(12) F#:模块 | 命名空间 | 异常处理 | 内置异常 |:? | 相互递归函数

本文主要是介绍【PL理论】(12) F#:模块 | 命名空间 | 异常处理 | 内置异常 |:? | 相互递归函数,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

 

  • 💭 写在前面:本章我们将介绍 F# 的模块,我们前几章讲的列表、集合和映射都是模块。然后我们将介绍 F# 中的异常,以及内置异常,最后再讲解一下相互递归函数。

目录

0x00 F# 模块(Module)

0x01 F# 异常处理(Exception)

0x02 内置异常(Built-in Exceptions)

0x03 相互递归函数

0x04 通过泰勒级数展开来逼近计算 e^x


0x00 F# 模块(Module)

用于代码组织和抽象的特性,模块 (Module) 就是相关类型、值和函数的集合。

类似于面向对象编程中的类,但没有对象的概念。

比如我们说的的列表、集合和映射都是模块。

在这个章节后,我会给出一点练习题,方便大家更好地掌握 F# 基础。

为了方便大家没有负担地有效练习,我会在框架代码中勾勒出模块,你只需要填写就行了:

namespace DataStructuremodule Queue =type t = int list * int listlet empty: t = ([], [])let enqueue (i: int) (queue: t) = ...

另外,这个 namespace 就是命名空间,类似于 C++。

0x01 F# 异常处理(Exception)

F# 中也是可以 raise 捕获异常的,raise ... 会被求值为一个异常并传播。

使用 try-with 来捕获引发的异常,异常会被视为 any type,可以是任何类型 ( `a ) 。 

exception DivByZerolet div (x: int) (y: int) : int =if y = 0 then raise DivByZero else x / ylet printDiv (x: int) (y: int) : unit =try printfn "%d" (div x y) with| DivByZero -> printfn "Divisor is zero" 

0x02 内置异常(Built-in Exceptions)

F# 有不少预定义的异常,要捕获这些错误,你必须使用 |:? 

这是因为 F# 与 C# (.NET) 都是一个爹有着密不可分的关系。

这里提供几种还不错的选择,让你避免记住这些复杂的异常名称:

let doFind1 (k: string) (m: Map<string,int>) : int =try Map.find k m with| :? System.Collections.Generic.KeyNotFoundException -> 0let doFind2 (k: string) (m: Map<string,int>) : int =if Map.containsKey k m then Map.find k m else 0let doFind3 (k: string) (m: Map<string,int>) : int =match Map.tryFind k m with| None -> 0 | Some i -> i

0x03 相互递归函数

相互递归函数 (Mutually Recursive Function),指的是多个函数可以相互递归调用。

简单来说就是你递归调用我,我递归调用你,用 let rec ... and 语法来定义这样的函数。

💬 举个例子:我们来定义三个相互递归的函数

let rec f x =x + g (x - 1)and g y =if y <= 1 then 1 else y * h (y - 1)and h z =if z <= 2 then 0 else f (z - 1) + f (z - 2)

这段代码定义了三个相互递归的函数 f,g,h,它们彼此之间互相调用。

形成了一个循环,每个函数的返回值都依赖于其他函数的返回值,从而实现了相互递归。

0x04 通过泰勒级数展开来逼近计算 e^x

通过泰勒级数展开来逼近计算 e^x

① 首先计算 n 的阶乘:

n!=n\times (n-1)\times(n-2)\times...\times2\times1

我们定义一个递归函数 Fac 计算一个非负整数的阶乘,当输入值 n\leq 1 时,返回1。

否则,返回 n 乘以 (n-1)  的阶乘。

在 Tylor 函数中,Fac 被用来计算泰勒级数展开的分母部分,即 n!  。

② 再通过泰勒级数展开公式 (以 e 为底的指数函数) ,我们展开前十项:

e^x=\sum_{n=0 }^{\infty }\frac{x^n}{n!}\, \, \, \Rightarrow \, \, \, e^x\approx \sum_{n=0 }^{10}\frac{x^n}{n!}

再定义一个递归函数 Taylor 计算 e^x 的泰勒级数展开,当展开的级数项数 n=0 时,返回 1.0

否则计算 x^n/n!  并加上递归调用 Taylor 函数计算更低阶的项。

在 Taylor 函数中,Fac 函数被用来计算每一项的阶乘。

💬 代码演示:通过泰勒级数展开来逼近计算 e^x

let rec Fac n =if n <= 1 then 1else n * Fac (n - 1)let rec Taylor x n =if n = 0 then 1.0else (float x ** float n) / float (Fac n) + Taylor x (n - 1)// 计算 e^x 的值
let calculateExponential x =if System.Double.IsNaN(x) || System.Double.IsInfinity(x) theninvalidArg "x" "x must be a finite number"elseTaylor x 10  // 前10项

这两个函数就相互递归了,因为 Taylor 调用了 Fac 来计算阶乘,而 Fac 也会调用 Taylor。

你可以发现,我们没有使用刚才讲的 "0x03 相互递归",let rec ... and。

因为每次计算阶乘都会重新计算泰勒级数的一部分,导致大量的重复计算:

let rec Fac n =if n <= 1 then 1else n * Taylor (n - 1) 1and Taylor x n =if n = 0 then 1.0else (float x ** float n) / float (Fac n) + Taylor x (n - 1)// 计算 e^x 的值
let calculateExponential x =if System.Double.IsNaN(x) || System.Double.IsInfinity(x) theninvalidArg "x" "x must be a finite number"elseTaylor x 10  // 前10项// 测试计算函数
let result = calculateExponential 1.0
printfn "e^1 的值近似为: %f" result


📌 [ 笔者 ]   王亦优
📃 [ 更新 ]   2024.6.16
❌ [ 勘误 ]   /* 暂无 */
📜 [ 声明 ]   由于作者水平有限,本文有错误和不准确之处在所难免,本人也很想知道这些错误,恳望读者批评指正!

📜 参考资料 

Microsoft. MSDN(Microsoft Developer Network)[EB/OL]. []. .

这篇关于【PL理论】(12) F#:模块 | 命名空间 | 异常处理 | 内置异常 |:? | 相互递归函数的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


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

相关文章

C#使用SQLite进行大数据量高效处理的代码示例

《C#使用SQLite进行大数据量高效处理的代码示例》在软件开发中,高效处理大数据量是一个常见且具有挑战性的任务,SQLite因其零配置、嵌入式、跨平台的特性,成为许多开发者的首选数据库,本文将深入探... 目录前言准备工作数据实体核心技术批量插入:从乌龟到猎豹的蜕变分页查询:加载百万数据异步处理:拒绝界面

Springboot处理跨域的实现方式(附Demo)

《Springboot处理跨域的实现方式(附Demo)》:本文主要介绍Springboot处理跨域的实现方式(附Demo),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不... 目录Springboot处理跨域的方式1. 基本知识2. @CrossOrigin3. 全局跨域设置4.

python+opencv处理颜色之将目标颜色转换实例代码

《python+opencv处理颜色之将目标颜色转换实例代码》OpenCV是一个的跨平台计算机视觉库,可以运行在Linux、Windows和MacOS操作系统上,:本文主要介绍python+ope... 目录下面是代码+ 效果 + 解释转HSV: 关于颜色总是要转HSV的掩膜再标注总结 目标:将红色的部分滤

Java异常架构Exception(异常)详解

《Java异常架构Exception(异常)详解》:本文主要介绍Java异常架构Exception(异常),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1. Exception 类的概述Exception的分类2. 受检异常(Checked Exception)

Python实现自动化接收与处理手机验证码

《Python实现自动化接收与处理手机验证码》在移动互联网时代,短信验证码已成为身份验证、账号注册等环节的重要安全手段,本文将介绍如何利用Python实现验证码的自动接收,识别与转发,需要的可以参考下... 目录引言一、准备工作1.1 硬件与软件需求1.2 环境配置二、核心功能实现2.1 短信监听与获取2.

Python使用date模块进行日期处理的终极指南

《Python使用date模块进行日期处理的终极指南》在处理与时间相关的数据时,Python的date模块是开发者最趁手的工具之一,本文将用通俗的语言,结合真实案例,带您掌握date模块的六大核心功能... 目录引言一、date模块的核心功能1.1 日期表示1.2 日期计算1.3 日期比较二、六大常用方法详

Java报NoClassDefFoundError异常的原因及解决

《Java报NoClassDefFoundError异常的原因及解决》在Java开发过程中,java.lang.NoClassDefFoundError是一个令人头疼的运行时错误,本文将深入探讨这一问... 目录一、问题分析二、报错原因三、解决思路四、常见场景及原因五、深入解决思路六、预http://www

利用Go语言开发文件操作工具轻松处理所有文件

《利用Go语言开发文件操作工具轻松处理所有文件》在后端开发中,文件操作是一个非常常见但又容易出错的场景,本文小编要向大家介绍一个强大的Go语言文件操作工具库,它能帮你轻松处理各种文件操作场景... 目录为什么需要这个工具?核心功能详解1. 文件/目录存javascript在性检查2. 批量创建目录3. 文件

Java使用多线程处理未知任务数的方案介绍

《Java使用多线程处理未知任务数的方案介绍》这篇文章主要为大家详细介绍了Java如何使用多线程实现处理未知任务数,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 知道任务个数,你可以定义好线程数规则,生成线程数去跑代码说明:1.虚拟线程池:使用 Executors.newVir

一文带你深入了解Python中的GeneratorExit异常处理

《一文带你深入了解Python中的GeneratorExit异常处理》GeneratorExit是Python内置的异常,当生成器或协程被强制关闭时,Python解释器会向其发送这个异常,下面我们来看... 目录GeneratorExit:协程世界的死亡通知书什么是GeneratorExit实际中的问题案例