【PL理论深化】(6) Ocaml 语言: 函数 | 匿名函数 | 函数可以接受多个参数 | OCaml 是一种将函数视为 first-class 的语言

  • 💬 写在前面:本章我们继续介绍如何使用 OCaml 进行函数式编程。介绍如何使用 let 定义函数,讲解匿名函数,函数可以接受多个参数,以及讨论 OCaml 将函数视为 first-class。

目录

0x00 函数

0x01 匿名函数(anonymous function)

0x02 函数可以接受多个参数

0x03 OCaml 是一种将函数视为 first-class 的语言


0x00 函数

定义函数时也是使用 let,下面我们来定义一个计算开方的函数 square :

x:= x^2

# let square x = x * x;;
val square : int -> int = <fun>

在函数的名字后面写上函数的参数的名字,然后在等号后面定义函数的主体。

函数 square 定义了一个接受参数 x 并返回 x * x 作为结果的函数。

定义函数后,OCaml 解释器会告诉你该函数的类型。

在这个例子中,int -> int 表示这是一个以整数为参数并返回整数的函数。

上面提到的 <fun> 表示定义的值是一个函数。对于函数,OCaml 解释器不会显示具体的值。

定义函数之后,可以像下面这样调用并使用它:

# square 2;;
- : int = 4
# square (2 + 5);;

- : int = 49
# square (square 2);;
- : int = 16

.

我们也可以用如下方式定义 square 函数:

# let square = fun x -> x * x;;
val square : int -> int = <fun>

在这里,`fun x -> x * x` 表示一个接受参数 x 并返回 x * x 的函数,

而名字 square 用来指代这个函数值。这样定义函数的方式与前面定义的方式完全相同。

可以认为编译器在内部将 `let square x = x * x` 处理为 `let square = fun x -> x * x`。

0x01 匿名函数(anonymous function)

通过 `fun x -> x * x` 定义的函数被称为 匿名函数 (anonymous function)。

举另一个例子,定义一个检查参数 x 是否为负数的函数 neg。

在这个例子中,函数的主体是一个条件表达式。

# let neg x = if x < 0 then true else false;;
val neg : int -> bool = <fun>
# neg 1;;
- : bool = false
# neg (-1);;
- : bool = true

在 OCaml 中,函数调用表达式通常写作 e_1,e_2 的形式,其中 e_1 和 e_2 可以是任意的表达式。

例如在上面调用 square 的三个例子中,e_1 都是 square,而 e_2 分别是 2, 2 + 5, square 2。

e_1 也可以直接是匿名函数,例如:

# (fun x -> x * x) 3;;
- : int = 9
# (fun x -> if x > 0 then x + 1 else x * x) 1;;
- : int = 2

0x02 函数可以接受多个参数

例如,我们可以编写一个函数,它接受两个整数 x 和 y 作为参数,并返回它们各自平方的和。

# let sum_of_squares x y = (square x) + (square y);;
val sum_of_squares : int -> int -> int = <fun>

# sum_of_squares 3 4;;
- : int = 25

OCaml 告诉我们,该函数的类型是 `int -> int -> int`,这意味着它接受两个整数并返回一个整数。

或者,将类型解释为 `int -> (int -> int)`,这意味着它接受一个整数参数,

并返回一个从整数到整数的函数,实际上,可以这样解释和使用上述定义的函数:

# let f = sum_of_squares 3;;
val f : int -> int = <fun>
# f 4;;
- : int = 25

定义了变量 f 为 sum_of_squares 3 的值,其定义为一个接受整数 y 并返回函数:

(\textrm{square}\,\, \, 3)+(\textrm{square}\,\, \, y)

因此,可以通过 f4 调用来获得其值,结果为 25。

定义递归函数的方法也是相同的,但在 let 后面必须加上关键字 rec。

例如,可以如下定义阶乘函数 factorial:

# let rec factorial a =
    if a = 1 then 1 else a * factorial (a - 1);;
val factorial : int -> int = <fun>
# factorial 5;;
- : int = 120

0x03 OCaml 是一种将函数视为 first-class 的语言

OCaml 是一种将函数视为 first-class 的语言,这意味着定义和使用函数的方式非常灵活。

在编程语言中,要使一个值称为 first-class,必须能将其存储在变量中,

作为函数的参数传递,并且能作为函数的返回值返回。

例如,在 C 语言中,整数, 字符等值被视为 first-class。

在 OCaml 中,函数也被视为 first-class。

因此可以像下面这样,一个函数可以接受另一个函数作为参数:

# let sum f a b =
(if f a then a else 0) + (if f b then b else 0)
val sum : (int -> bool) -> int -> int -> int = <fun>
# let even x = x mod 2 = 0;;
val even : int -> bool = <fun>
# sum even 3 4;;
- : int = 4
# sum even 2 4;;
- : int = 6

在上述中,even 是一个函数,接受整数 x 作为参数,如果 x 是偶数则返回 true。

换句话说,even 的定义体 x mod 2 是一个布尔表达式,用于计算 x 除以 2 的余数是否为 0。

函数 sum 接受三个参数 f, a, b,其中 f 是一个从整数到布尔值的函数。

这个函数应用于 a 和 b,并在计算结果为 true 时返回它们的和。

例如,sum even 3 4 中,我们将函数 even 作为 sum 的第一个参数传递,因此返回值为 4。

函数也可以返回另一个函数:

# let plus a = fun b -> a + b;;
val plus : int -> int -> int = <fun>
# let plus1 = plus 1;;
val plus1 : int -> int = <fun>
# plus1 1;;
- : int = 2
# plus1 2;;
- : int = 3
# let plus2 = plus 2;;
val plus2 : int -> int = <fun>
# plus2 1;;
- : int = 3

函数 plus 接收一个参数 a,返回一个函数 fun b -> a + b 。

类型 int -> int -> int 可以解释为 int -> (int -> int)

意味着它接收一个整数并返回一个从整数到整数的函数。

变量 plus1 被定义为 plus 1,因此 plus1 是一个接收参数 b 并返回 1 + b 的函数。

.

类似地,plus2 是一个接收整数参数并将其加上2的函数。

像 sum 和 plus 这样接受或返回其他函数的函数称为高阶函数。

如果编程语言支持高阶函数,我们就可以更抽象地思考和编程,

这样可以更方便地命名和抽象编程模式,从而编写更简洁易读的程序。

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

📜 参考资料 

- R. Neapolitan, Foundations of Algorithms (5th ed.), Jones & Bartlett, 2015.

- T. Cormen《算法导论》(第三版),麻省理工学院出版社,2009年。

- T. Roughgarden, Algorithms Illuminated, Part 1~3, Soundlikeyourself Publishing, 2018.

- J. Kleinberg&E. Tardos, Algorithm Design, Addison Wesley, 2005.

- R. Sedgewick&K. Wayne,《算法》(第四版),Addison-Wesley,2011

- S. Dasgupta,《算法》,McGraw-Hill教育出版社,2006。

- S. Baase&A. Van Gelder, Computer Algorithms: 设计与分析简介》,Addison Wesley,2000。

- E. Horowitz,《C语言中的数据结构基础》,计算机科学出版社,1993

- S. Skiena, The Algorithm Design Manual (2nd ed.), Springer, 2008.

- A. Aho, J. Hopcroft, and J. Ullman, Design and Analysis of Algorithms, Addison-Wesley, 1974.

- M. Weiss, Data Structure and Algorithm Analysis in C (2nd ed.), Pearson, 1997.

- A. Levitin, Introduction to the Design and Analysis of Algorithms, Addison Wesley, 2003. - A. Aho, J. Hopcroft, and J. Ullman, Data Structures and Algorithms, Addison-Wesley, 1983.

- E. Horowitz, S. Sahni and S. Rajasekaran, Computer Algorithms/C++, Computer Science Press, 1997.

- R. Sedgewick, Algorithms in C: 第1-4部分(第三版),Addison-Wesley,1998

- R. Sedgewick,《C语言中的算法》。第5部分(第3版),Addison-Wesley,2002

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【C语言】--常见类型和概念

❤️个人主页: 起名字真南 &#x1f495;个人专栏:【数据结构初阶】 【C语言】 目录 第一个C语言程序main函数printf函数库函数关键字字符和ASCII码字符串和\0转义字符 第一个C语言程序 #include<stdio.h> int main() {printf("Hello World\n");return 0; }ma…

【神经网络】CNN网络:深入理解卷积神经网络

&#x1f388;个人主页&#xff1a;豌豆射手^ &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共同学习、交流进步&#xff01; CNN网络&#xff1a;深入理解…

springboot集成达梦数据库,打包后,tomcat中启动报错

背景&#xff1a;springboot集成达梦数据库8&#xff0c;在工具idea中正常使用&#xff0c;但是打包后&#xff0c;无法启动&#xff0c;报错 pom引入的依赖 但是这种情况&#xff0c;只有在idea中启动没问题的解决方法 需要修改引入的依赖&#xff0c;再次打包就可以 <d…

PatchMixer:一种用于长时间序列预测的Patch混合架构

前言 《PatchMixer: A Patch-Mixing Architecture for Long-Term Time Series Forecasting》原文地址&#xff0c;Github开源代码地址GitHub项目地址Some-Paper-CN。本项目是译者在学习长时间序列预测、CV、NLP和机器学习过程中精读的一些论文&#xff0c;并对其进行了中文翻译…

苹果电脑压缩pdf文件,苹果电脑里如何压缩pdf文件

压缩PDF文件是现代办公和日常生活中经常需要处理的一项任务&#xff0c;无论是为了节省存储空间、方便网络传输&#xff0c;还是为了在移动设备上更流畅地阅读文档&#xff0c;学会有效地压缩PDF都显得尤为重要。在本文中&#xff0c;我们将详细探讨压缩PDF的方法&#xff0c;从…

Mac安装多版本node

Mac下使用n模块去安装多个指定版本的Node.js&#xff0c;并使用命令随时切换。 node中的n模块是&#xff0c;node专门用来管理node版本的模块&#xff0c;可以进行node版本的切换&#xff0c;下载&#xff0c;安装。 1.安装n npm install -g n 2.查看版本 n --version 3.展…

LeetCode题练习与总结:随机链表的复制--138

一、题目描述 给你一个长度为 n 的链表&#xff0c;每个节点包含一个额外增加的随机指针 random &#xff0c;该指针可以指向链表中的任何节点或空节点。 构造这个链表的 深拷贝。 深拷贝应该正好由 n 个 全新 节点组成&#xff0c;其中每个新节点的值都设为其对应的原节点的…

IT入门知识第八部分《云计算》(8/10)

目录 云计算&#xff1a;现代技术的新篇章 1. 云计算基础 1.1 云计算的起源和发展 云计算的早期概念 云计算的发展历程 1.2 云计算的核心特点 按需自助服务 广泛的网络访问 资源池化 快速弹性 按使用量付费 1.3 云计算的优势和挑战 成本效益 灵活性和可扩展性 维…

日语培训日语等级考试柯桥小语种学习语言学校

什么是外来语 外来语是指在日本的国语中使用的来源于外国语言的词汇。但狭义上的外来语则是指来源于欧美国家语言的词汇&#xff0c;其中大部分是来源于英美语系的词汇。日语中的汉语词汇很多&#xff0c;大多是自古以来从中国引进的&#xff0c;从外来语的定义看&#xff0c;汉…

运算符重载详解(完全版)

1.运算符重载 C为了增强代码的可读性引入了运算符重载&#xff0c;运算符重载是具有特殊函数名的函数&#xff0c;也具有其返回值类型&#xff0c;函数名字和参数列表&#xff0c;其返回值类型与参数列表都与普通的函数类似 函数名&#xff1a;关键字operator后面接需要重载的…

记因hive配置文件参数运用不当导致 sqoop MySQL导入数据到hive 失败的案例

sqoop MySQL导入数据到hive报错 ERROR tool.ImportTool: Encountered IOException running import job: java.io.IOException: Hive exited with status 64 报错解释&#xff1a; 这个错误表明Sqoop在尝试导入数据到Hive时遇到了问题&#xff0c;导致Hive进程异常退出。状态码…

Lua网站开发之文件表单上传

这个代码示例演示如何上传文件或图片&#xff0c;获取上传信息及保存文件到本地。 local fw require("fastweb") local request require("fastweb.request") local response require("fastweb.response") local cjson require("cjson&q…

windterm多窗口同时操作多台服务器

在配置k8s等多服务器环境时&#xff0c;我们要对多台服务器进行相同的操作&#xff0c;使用多窗口同步输入实现一次命令多段执行 初始配置&#xff0c;服务器都已连好 分屏窗口&#xff0c;按下altw->alth水平分屏&#xff0c;按下altw->altv,垂直分屏 按下ctrlshiftm,…

SAP消息号 VF028

客户在VF11冲销发票之后&#xff0c;没有生成正式的财务凭证&#xff0c;然后VF02的时候出现如下报错&#xff1a; “自动清算出具发票凭证XXXXXXX&#xff08;被冲销凭证号&#xff09;且不可能取消凭证XXXXXXX&#xff08;冲销凭证号&#xff09; 原因&#xff1a;销售订单2…

小程序下拉刷新,加载更多数据,移动端分页

文章目录 页面结构图WXML页面代码js代码wxss代码总结备注 参考&#xff1a;https://juejin.cn/post/7222855604406796346 页面结构图 一般页面就4个结构&#xff1a;最外滚动层、数据展示层、暂无数据层、没有更多数据层。 如图&#xff1a; WXML页面代码 <scroll-view …

[吃瓜教程]南瓜书第3章对数几率回归

第三章 对数几率回归 3.1 算法原理 对数几率回归&#xff08;Logistic Regression&#xff09;是一种统计方法&#xff0c;主要用于二分类问题。它通过拟合一个对数几率函数&#xff08;logit function&#xff09;&#xff0c;即对数几率&#xff08;log-odds&#xff09;与…

oracle 11g rac创建实例时发现只给一节点创建了实例 二节点没创建的处理方法

由于操作失误没有在二节点创建实例 删除数据库重新dbca建库 [oracleracdg1-1 dbs]$ dbca -silent -deleteDatabase -sourceDB rac11dg1 -sysDBAUserName sys -sysDBAPassword oracle_4U Connecting to database 4% complete 9% complete 14% complete 19% complete 23% …

常见网络攻击威胁分享

今天我来分享一下比较常见的网络攻击形式&#xff0c; ARP 欺骗攻击、CC 攻击和 DDoS 流量攻击是较为常见且危害巨大的攻击方式。 一、ARP欺骗攻击 ARP&#xff08;AddressResolutionProtocol&#xff0c;地址解析协议&#xff09;是用于将IP地址转换为MAC地址的协议。ARP欺骗…

ActiViz集成到WPF中的空域问题

文章目录 一、场景1、WPF控件2、集成ActiViz或者VTK 二、问题1、需求2、空域问题 三、解决方案1、用WindowsFormsHost包裹住ElementHost&#xff0c;然后将WPF的控件放在ElementHost职中&#xff1a;2、用Window或者Popup去悬浮3、使用第三方库Microsoft.DwayneNeed&#xff08…

springcloud-gateway 路由加载流程

问题 Spring Cloud Gateway版本是2.2.9.RELEASE&#xff0c;原本项目中依赖服务自动发现来自动配置路由到微服务的&#xff0c;但是发现将spring.cloud.gateway.discovery.locator.enabledfalse 启动之后Gateway依然会将所有微服务自动注册到路由中&#xff0c;百思不得其解&a…