For循环

在F#中,for循环的语法如下:

for <identifier> = <start> to <end> do<body>

但是所有函数式编程语言都不鼓励使用for循环,而是使用递归来实现循环。

for循环的一个常见用法是遍历一个数组,例如:

let arr = [|1; 2; 3; 4; 5|]
for i = 0 to arr.Length - 1 doprintfn "%d" arr.[i]

从语义上来看,为什么要用for循环呢?是因为我的很大哦不我的很多……遍历才是for循环的本质。那么,在函数式编程中我们该如何考虑这个问题呢?

函数式编程的核心之一是值,那么集合也应该是一个值。在F#中,数组是一个值,列表也是一个值。那么,我们可以把数组和列表看成是一个值,而不是一个变量。我们应该用函数来直接处理这个值,而不是用for循环来遍历这个值。

F#集合的类型

F#原生提供了几类集合,这几类集合的含义与传统意义上的集合完全相同,例如,数组就是长度固定,得到最后一个元素和长度的时间复杂度为O(1);列表、序列的长度和最后一个元素的时间复杂度为O(n)。诸如此类。一般的算法书中都会有介绍。

  • 列表:[1; 2; 3; 4; 5]
  • 数组:[|1; 2; 3; 4; 5|]
  • 序列:seq {1; 2; 3; 4; 5}
  • 集合:set [1; 2; 3; 4; 5]
  • 映射:map [("a", 1); ("b", 2); ("c", 3)]

按照文档上的原文,这几类的集合的特点如下:

  • List: 有序,不可变序列,元素类型相同,采用链表实现
  • Array: 固定长度,0-based,元素类型相同,元素可变
  • Seq: 惰性序列,元素类型相同
  • Set: 无序,不可变集合,元素类型相同,采用二叉树实现
  • Map: 不可变,字典,用键值key来索引

前面给出了相关字面量的表示方法。定义相应的值的方法如下:

let list = [1; 2; 3; 4; 5]
let arr = [|1; 2; 3; 4; 5|]
let seq = seq {1; 2; 3; 4; 5}
let set = set [1; 2; 3; 4; 5]
let map = map [("a", 1); ("b", 2); ("c", 3)]

既然是值,那么就应该用函数来作用到集合上面,并得到一个新的值。这是函数式编程的核心思想。

方法与管道

对应每个集合类型,F#提供了一系列函数,这些函数的形式如Type.appendType.add,区别与类和对象的成员函数,这些方法都是各个类型的静态函数。另外,这些函数的首字母都是小写的,这也符合.NET的命名规范。完整的方法列表可以参考MSDN。

这些函数的定义有一个共同的特点,他们的最后一个参数都是集合类型,例如:

let list = [1; 2; 3; 4; 5]
List.add 6 list
let list2 = List.append [6; 7; 8] list
let list3 = List.filter (fun x -> x % 2 = 0) list
let list4 = List.map (fun x -> x * x) list

按照这样的方式定义,结合F#中偏应用、F#的管道操作符|>,我们可以很方便的对集合进行操作,例如:

let list = [1; 2; 3; 4; 5]
let sum_sqrt = list |> List.add 6 |> List.append [6; 7; 8] |> List.filter (fun x -> x % 2 = 0) |> List.map (fun x -> x * x)|> List.fold (fun acc, elem -> acc + Math.Sqrt(float elem)) 0.0|> printfn "%f"

可以看到,什么高阶函数,什么map、reduce、filter,都是信手拈来。这就是函数式编程的魅力,针对值和映射编程,而不针对变量、对象、循环、状态编程。实际上F#也能不那么函数,但是这样就不好玩了。

还有一种循环

在程序设计中,还有一种循环,这种循环比较难以抽象为操作一个集合。就比如事件循环,需要操作的是一个队列,当队列里面没有事件的时候,就需要等待。这种循环在F#中可以用while来实现,例如:

while true dolet input = Console.ReadLine()if input = "exit" thenbreakelseprintfn "%s" input

这种循环怎么利用函数式编程的思想来实现呢?这就需要用到递归了。例如:

let rec loop () =let input = Console.ReadLine()if input = "exit" then()elseprintfn "%s" inputloop ()
loop ()

实际上这个问题我现在还是很困扰,虽然我也知道尾递归能够使得这种循环达到一定程度的效率,但是对于这个概念的函数式理解还是不够深刻。这个问题我会在后面的文章中继续探索。等我探索到了,感觉到了有趣,再写。

总结

  1. F#中的集合类型有列表、数组、序列、集合、映射
  2. F#中的集合类型首先是值,应该首选函数式的方式来操作集合
  3. F#中的集合类型的方法都是静态函数,可以用管道操作符|>来操作
  4. F#中的循环可以用递归来实现,这个我也没想明白

F#奇妙游(6):如何不用for循环以及循环相关推荐

  1. F#奇妙游(8):计量单位

    F#的计量单位 从各个意义上,都可以说计量单位很重要.度量衡的统一是社会化大生产和市场交换的基石.这句正确的废话跟F#没有半毛钱的关系,直到我看帮助看到了这个: [<Measure>] t ...

  2. 阿里文娱旗下优酷联合河南卫视推出2022“元宵奇妙游”,创新传承传统文化

    随着中国经济的发展,中华民族越来越自信,国潮风愈演愈烈,中华文化带有典型的中国特色,如今国潮已经悄悄席卷各大行业,中国元素已经成为人们追逐的对象.文化产业亦是如此,河南卫视宣扬民族文化,在各大卫视中脱 ...

  3. shell条件测试操作 if分支 for循环 while 循环

    目录 条件测试操作 条件测试的基本用法: 字符串条件测试: 逻辑组合 数字的条件测试: 编写一个脚本: 对文件进行测试: if判断语句 单分支 双分支 多分支 编写一个脚本: 编写一个脚本: for循 ...

  4. 任意重循环(循环阶数不定、循环层数不定)

    ----哆啦刘小洋 原创,转载需说明出处 文章目录 1 简介 2 普通循环 3 任意重循环算法 4 任意重循环代码 4.1 准备 4.2 第2节代码重写 5 模块化 5.1 AnyLoop1 5.2 ...

  5. Java用while循环for循环解决有一张足够大的纸、折成与珠穆朗玛峰的高度。

    一.解决思路, 定义变量存储珠穆朗玛峰的高度(peakHeight).纸张的高度(paperThickness). 使用while循环,循环条件是(纸张厚度<山峰高度),内部控制纸张折叠,每折叠 ...

  6. java 双重for循环_Java--for循环之双层循环嵌套 执行流程

    for循环单层循环执行流程:http://blog.csdn.net/asheandwine/article/details/76383304 接下来看双层循环: 循环嵌套是指在一个循环语句中再定义一 ...

  7. python中for循环流程图_Python流程控制-while循环-for循环

    写重复代码 是可耻的行为 -------------- 完美的分割线 -------------- 程序在一般情况下是按顺序执行的,编程语言提供了各种控制结构,允许更复杂的执行路径. 循环(loop) ...

  8. python语言流程控制语句的格式while循环_Python流程控制-while循环-for循环

    写重复代码 是可耻的行为 -------------- 完美的分割线  -------------- 程序在一般情况下是按顺序执行的,编程语言提供了各种控制结构,允许更复杂的执行路径. 循环(loop ...

  9. 深度学习入门(五十六)循环神经网络——循环神经网络RNN

    深度学习入门(五十六)循环神经网络--循环神经网络RNN 前言 循环神经网络--循环神经网络RNN 课件 潜变量自回归模型 循环神经网络 使用循环神经网络的语言模型 困惑度(perplexity) 梯 ...

最新文章

  1. [JS] for-each和map()的区别
  2. 什么才是程序员摸鱼的最高境界?
  3. Android程序设计基础
  4. 第一次使用并配置Hibernate
  5. win7中安装redis
  6. audio 相关概念梳理记录
  7. 用Seam-gen起步(二)
  8. Python 简单编写一个注册邮箱
  9. LeetCode(跳跃游戏)
  10. 马尔可夫决策过程(一)
  11. LTspice基础教程-008.LTspice PWL设置
  12. python与idle区别_idle和python区别
  13. arcgis 将地图点转换为屏幕坐标_ArcGIS地图投影和坐标转换方法
  14. 北京大学光华管理学院开通CnOpenData试用
  15. 指数为负数的幂函数 c语言,C语言:求幂函数和指数函数的方法
  16. 往年二本计算机分数线,全国一本、二本院校历年录取分数线汇总
  17. 无法像唐骏一样地成功
  18. 我的30个Firefox扩展推荐
  19. iptables整理总结
  20. 电脑上哪个思维导图软件比较好用?试试MindNow

热门文章

  1. Luogu P3353 在你窗外闪耀的星星
  2. Windows桌面小程序+谷歌浏览器+人工智能算法 = 100+职位一键投递
  3. 故障:电脑开机后显示屏黑屏
  4. poi获取excel2003图表以及相关属性
  5. 如何给服务器端控件(TextBox)添加JavaScritp脚本事件
  6. 什么是云服务器?云服务器有哪些作用?
  7. Comparator进行排序
  8. linux上卸载python_linux下卸载python
  9. Tomcat 优化方案
  10. 编写QQ聊天界面实例