F# 语法概览
F#和C#的语法差别
语法上,F#和C#有两个主要差别:
- 用缩进而非花括号分隔代码块
- 用空白而非逗号分隔参数
F#常见语法元素
以下是F#代码中常见的语法元素
注释
// 这是单行注释
(* 这是多行注释
第二行
最后一行 *)
let 绑定
let myInt =
let myFloat = 3.14
let myString = "hello"
上面的语句没有显式指定 myInt, myFloat, myString 的类型,类型由编译器推断。
列表
let twoToFive = [;;;] // 方括号表示列表,元素用分号分隔
let oneToFive = :: twoToFive // 符号 :: 将值添加到列表头部,得到新列表,结果为 [1;2;3;4;5]
let zeroToFive = [;] @ twoToFive // 符号 @ 连接两个列表,得到新列表,结果为 [0;1;2;3;4;5]
务必注意,列表元素使用分号分隔,而非逗号分隔。
函数
命名函数用 let 关键字定义,匿名函数用 fun 关键字定义。
let square x = x * x // 使用 let 定义命名函数,函数形参不用小括号围住
square // 运行函数,实参也没有小括号 let add x y = x + y // 不可使用 (x,y)
add // 运行函数 // 多行函数,用缩进,不用分号
let evens list =
let isEven x = x% = // 内部函数
List.filter isEven list // List.filter 是库函数 evens oneToFive // 运行函数 // 用小括号指明优先级
let sumOfSquaresTo100 =
List.sum (List.map square [..]) // 如果没有小括号,那么 List.map 会是 List.sum 的参数 // 管道 |>,将操作的输出传给下一个操作
let sumOfSquaresTo100piped =
[..] |> List.map square |> List.sum // 用 fun 关键字定义拉姆达(匿名函数)
let sumOfSquaresTo100withFun =
[..] |> List.map (fun x->x*x) |> List.sum
模式匹配
match..with 用于模式匹配
// 类似于 switch/case
let simplePatternMatch =
let x = "a"
match x with
| "a" -> printfn "x is a"
| "b" -> printfn "x is b"
| _ -> printfn "x is something else" // 下划线匹配任意值 // Some(..) 和 None 有点像可空类型(Nullable)
let validValue = Some()
let invalidValue = None // match..with 匹配 "Some" 和 "None",同时从 Some 中取出值
let optionPatternMatch input =
match input with
| Some i -> printfn "input is an int=%d" i
| None -> printfn "input is missing" optionPatternMatch validValue
optionPatternMatch invalidValue
复杂类型
复杂类型是指元组,记录和联合
// 元组,包含有序但未命名的值,值之间用逗号分隔
let twoTuple = ,2 // 二元组
let threeTuple = "a",,true // 三元组 // 记录,包含命名的字段,字段之间用分号分隔
type Person = {First:string; Last:string}
let person1 = {First="john"; Last="Doe"} // 联合,包含选项,选项之间用竖线分隔
type Temp =
| DegreesC of float
| DegreesF of float
let temp = DegreesF 98.6 // 类型可以递归的组合,例如,下面的 Employee 联合包含 Employee 类型的列表
type Employee =
| Worker of Person
| Manager of Employee list
let jdoe = {First="John";Last="Doe"}
let worker = Worker jdoe
格式化输出
printf 和 printfn 向控制台输出,类似于 C# Console 类的 Write 和 WriteLine 方法。sprintf 输出到字符串,类似于 String 类的 Format 方法。
printfn "Printing an int %i, a float %f, a bool %b" 2.0 true
printfn "A string %s, and something generic %A" "hello" [;;;] // 复杂类型具有内置的美观输出格式
printfn "twoTuple=%A,\nPerson=%A,\nTemp=%A,\nEmployee=%A" twoTuple person1 temp worker let str1 = sprintf "Printing an int %i, a float %f, a bool %b" 2.0 true
let str2 = sprintf "A string %s, and something generic %A" "hello" [;;;]
比较F#和C#:计算平方和
C#版,不使用 linq
public static class SumOfSquaresHelper
{
public static int Square(int i)
{
return i * i;
} public static int SumOfSquares(int n)
{
int sum = ;
for (int i = ; i <= n; i++)
{
sum += Square(i);
}
return sum;
}
}
F#版
let square x = x * x
let sumOfSquares n =
[..n] // 创建 1 到 n 的列表
|> List.map square // 对每个元素求平方,得到新列表
|> List.sum // 将平方列表求和
F# 语法噪音小,没有花括号,分号,并且在这里不需要显式指定类型。
C#版,使用 linq
public static class FunctionalSumOfSquaresHelper
{
public static int SumOfSquares(int n)
{
return Enumerable.Range(, n)
.Select(i => i * i)
.Sum();
}
}
使用 linq 改写的 C# 代码简洁很多,但不能消除语法噪音,参数和返回值的类型也是必须的,仍然不如 F# 版简洁。
例子:快速排序算法
快速排序算法的步骤是:
- 从列表中取出一个数作为基准
- 将小于基准的数放在左边,不小于基准的数放在右边
- 对基准两边的部分进行快速排序
下面是 F# 实现快速排序的例子
let rec quicksort list =
match list with
| [] -> []
| firstElem::otherElements ->
// 小于第一个元素的元素
let smallerElements =
otherElements
|> List.filter (fun e -> e < firstElem)
|> quicksort // 不小于第一个元素的元素
let largerElements =
otherElements
|> List.filter (fun e -> e >= firstElem)
|> quicksort // 连接成新列表
List.concat [smallerElements; [firstElem]; largerElements] printfn "%A" (quicksort [;;;;;;])
如果应用库函数和一些技巧,代码可压缩成:
let rec quicksort = function
| [] -> []
| first::rest ->
let smaller,larger = List.partition ((>=) first) rest
List.concat [quicksort smaller; [first]; quicksort2 larger]
参考网站:http://fsharpforfunandprofit.com/
F# 语法概览的更多相关文章
- 《Go并发编程实战》读书笔记-语法概览
<Go并发编程实战>读书笔记-语法概览 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 本篇博客我们会快速浏览一下Go的语法,内容涉及基本构成要素(比如标识符,关键字,子 ...
- ES6新语法概览
简介 ES6是JavaScript语言的新一代标准,加入了一些新的功能和语法,正式发布于2015年6月,亦称ES2015:该标准由ECMA(欧洲计算机制造联合会)的第39号技术专家委员会(TC39)制 ...
- 【Scala】新手入门,基础语法概览
目录 变量.常量和数据类型 var val 数据类型 条件表达式 块表达式 to循环 for循环 for推导式 scala中的方法和函数 方法的定义 函数的定义 函数和方法的区别 变量.常量和数据类型 ...
- ES6新语法
ES6新语法概览 简介 ES6是JavaScript语言的新一代标准,加入了一些新的功能和语法,正式发布于2015年6月,亦称ES2015:该标准由ECMA(欧洲计算机制造联合会)的第39号技术专家委 ...
- F#周报2019年第25期
新闻 Azure Notebook概览 SpecFlow 3就在这里了! 使用新的Try .NET模版创建交互式文档 逐渐演化的.NET Core框架 Dylan与Linebreakers Oslo ...
- [Oracle] 分析功能(1)- 语法
语法概览 watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvZGJhbm90ZQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQ ...
- 函数式编程之-初窥F#
大量讲解函数式编程语言的书籍最终都会用Fuctor,Monad,Monoids,范畴论等各种词汇吓退命令式语言玩家,所以我试图避开这些问题,揭开这些复杂词汇带来的具有实战意义的成果.另外我会尽量使用C ...
- F#周报2019年第44期
新闻 Elmish.WPF教程 介绍Orleans 3.0 GC配置历史 介绍ONNX运行时1.0 介绍微软Q&A(预览) 使用App中心持续布署与监控你的UWP,WPF与Windows Fo ...
- 20155331 2016-2017-2 《Java程序设计》第七周学习总结
20155331 2016-2017-2 <Java程序设计>第七周学习总结 教材学习内容总结 一.认识Lambda语法 1.Lambda语法概览 Arrays的sort()方法可以用来排 ...
随机推荐
- Viso设置背景
文件 > 形状 > 其它Visio方案 > 背景
- CI Weekly #12 | 微信小程序的自动化测试进阶
岁末将至,站在年终冲刺的尾巴上,flow.ci 新增了个人和团队设置的功能: 上线团队功能,注册时默认创建一个与用户名一致的团队,可设置:团队名称.增减团队成员,后续会不断完善: 增加个人设置,可修改 ...
- office如何去除多页签
写文档会遇到同时打开多个文档,偶尔可能需要对比,而有时office会出现跟浏览器类似的多页签界面.如何去除多页签,office本身没有此加载项,一般都是作为插件或组件形式另外安装,导致我们不知道从哪里 ...
- 笔记:Spark简介
Spark简介 [TOC] Spark是什么 Spark是基于内存计算的大数据并行计算框架 Spark是MapReduce的替代方案 Spark与Hadoop Spark是一个计算框架,而Hadoop ...
- 你真的了解如何将 Nginx 配置为Web服务器吗
阅读之前,建议先阅读初识 Nginx. 之后,我们来了解一下 Nginx 配置. 抽象来说,将 Nginx 配置为 Web 服务器就是定义处理哪些 URLS 和如何处理这些URLS 对应的请求.具体来 ...
- 【java设计模式】之 建造者(Builder)模式
我们还是举上一节的例子:生产汽车.上一节我们通过模板方法模式控制汽车跑起来的动作,那么需求是无止境的,现在如果老板又增加了额外的需求:汽车启动.停止.鸣笛引擎声都由客户自己控制,他想要什么顺序就什么顺 ...
- 阿里云oss总是提示SignatureDoesNotMatch错误怎么办
网上的所有阿里云oss(C#)的例子几乎试遍了,为什么还是提示SignatureDoesNotMatch错误?什么原因?怎么办?下载一个阿里云提供的windows客户端发现,依然提示签名错误. 开始怀 ...
- JAVA中的char类型
1.JAVA中,char占2字节,16位.可在存放汉字 2.char赋值 char a='a'; //任意单个字符,加单引号. char a='中';//任意单个中文字,加单引号. char a=1 ...
- cmake的命令execute_process
execute_process(COMMAND <cmd1> [args1...]] [COMMAND <cmd2> [args2...] [...]] [WORKING_DI ...
- js小功能合集:计算指定时间距今多久、评论树核心代码、字符串替换和去除。
1.计算指定时间距今多久 var date1=new Date('2017/02/08 17:00'); //开始时间 var date2=new Date(); //当前时间 var date3=d ...