函数基础
函数定义
关键字: fun
语法
let f = fun x -> x*x-2*x //->左边的是函数参数,右边的是对函数参数的处理过程
或者是这样:
//这种定义方式不需要使用fun关键字
let f x =
let x1 = x-2
x*x1 //函数返回值
形参和实参
定义
let f = fun x -> x*x-2*x //->左边的是形参,右边的是实参
引用型参数
全部引用
let f = ref x y =
!x <- 2
!y <- 5
(x,y)
选择引用
let f x ref y = //其中只有y被引用了
!y <- 5
(x,y)
空参数和空返回值
语法
let f = fun() -> //需要在fun后面加一对小括号
System.Console.WriteLine("Hello world!")
ignore (f())
这个函数既没有参数,也没有返回值,注意在调用是需要使用ignore关键字来忽略返回值。
局部变量和全局变量
概念
在一个函数内部定义的变量在程序的其它位置不起作用,但在函数外部定义的变量在函数内部起作用。
更多调用方式
参数前置与函数复合
函数复合
语法
let f1 = fun x -> x*x-2*x
let f2 x =
let x1 = x-2
x1*x
let o = f2 (f1 6)
System.Console.WriteLine(o) //输出的结果是(6*6-2*6-2)*(6*6-2*6)=528
参数前置
上面的一段代码其实还有另外一种写法,参数可以写在函数名的前面,但是在有一个以上的参数时这样写会降低代码可读性。
let f1 = fun x -> x*x-2*x
let f2 x =
let x1 = x-2
x1*x
let o = 6 |> f1 |> f2 //这行代码的意思是把6作为参数传给f1,再把f1的计算结果作为参数传给f2,o就是f2的计算结果
System.Console.WriteLine(o) //输出的结果仍然是528
函数局部应用
除了在定义里提到的那种以外,函数还有另外一种定义方式如下(在下文中,定义里提到的那种被称为第一种方法,下面提到的被称为第二种方法)。
let f1 = fun(x,y) -> x*x-2*y //参数既可以用空格隔开,也可以放在一对小括号里用逗号隔开
使用这两种定义方式定义的函数调用方式也是不一样的
f1(2,2) //在调用这样定义的函数时传入的参数也需要用小括号括起来再用逗号隔开
其实,从本质上来说这两种定义方式在语法上并无区别,区别是第一种传入的是两个整数类型的参数,而第二种传入的参数是一个数组,但这两种方式的用处并无区别,只是第二种方法更接近于数学的表达方式。
第二种方法定义的函数在参数前置调用时的语法如下
let f1 = fun(x,y) -> x*x-2*y
let f2(x)=
let x1 = x-2
x1*x
let o = (2,3) |> f1 |> f2
System.Console.WriteLine(o) //输出的结果是8
运算符作函数
在F#中,类似于加减乘除的二元运算符也可以作为函数使用,注意在调用时需要用小括号把运算符括起来。
let o = (+) 2 5 //o的值是7
模式匹配
模式匹配表达式
语法
let f x =
match x with
| 5 -> "优" //|后是返回当前值的条件,这个例子中即为x的值;->后是满足条件时返回的值
| 4 -> "良"
| 3 -> "中"
| _ -> "差" //_条件意为除了其它列出的条件以外的所有情况下返回当前值
模式匹配表达式还有另外一种用法,分段函数,如下所示
let f x =
match x with
| _ when (x<0) -> "负数" //when限定了返回当前值的参数范围
| _ when (x>0) -> "正数"
| _ -> "0"
模式匹配表达式也可用于多参数函数
let f x y =
match x,y with
| (1,_) -> y //当x=1时返回y
| (_,1) -> x //当y=1时返回x
| _ -> x+y
通配符与
let f x y z =
match x,y,z with
| (_,_,1) & (1,_,_) -> "匹配" //当x=z=1时返回当前值
| _ -> x+y+z
通配符或
let f x y =
match x,y with
| (_,1) | (1,_) -> x-y //当x=1或y=1时返回当前值
| _ -> x+y
匹配机制
使用模式匹配语句时,要注意这两点
- 模式的组合要完整,需要包含各种情况
- 程序在匹配时,是按照由先到后的顺序匹配的,情况范围可以叠加,但最好不要出现永远不可能匹配到的情况
记录和联合类型匹配
记录
语法
type Name = {First:string;Last:string}
let f8 x y =
match x with
| {First = fi;Last = _} when fi = y -> true //判断First的值是否等于y参数
| _ -> false
let fn = "Ray"
let o7 = f8 {First = "Ray";Last = "Adas"} fn //x参数是一个记录
System.Console.WriteLine(o7) //输出的是true
联合类型
语法
type Transport = | Car | Truck | Bus
let f9 x =
match x with
| Car -> 100
| Truck -> 60
| Bus -> 80
let o8 = f9 Car
System.Console.WriteLine(o8) //输出的是100
调用CLR函数
概述
F#支持占位符的语法,如下所示
System.Console.WriteLine("{0}年{1}月",2020,10) //输出结果是2020年10月
F#有一个特性——就是支持函数封装,如下所示
// p1和p2实现的功能实际上是一样的,都是用kate编辑器打开对应的文件,只是代码量的区别
let runfile app file =
System.Diagnostics.Process.Start(app,file)
let p1 = runfile "kate" "./res/test.txt"
let runKate = runfile "kate"
let p2 = runKate "./res/test2.txt"
常用字符串函数
访问字符串长度
语法
let testStr = "RayAdas"
let x = testStr.Length //Length即是字符串的长度
System.Console.WriteLine(x) //输出的是7
截取字符串
截前
语法
let testStr = "RayAdas"
let outStr1 = testStr.Substring(3) //去掉字符串中第三个字符及其左边的内容
System.Console.WriteLine(outStr1) //输出的是Adas
截后
语法
let testStr = "RayAdas"
let outStr2 = testStr.Remove(3) //去掉字符串中第三个字符以后的内容
System.Console.WriteLine(outStr2) //输出的是Ray
插入字符串
语法
let testStr = "RayAdas"
let outStr3 = testStr.Insert(3," ") //在字符串第三个字符后插入一个空格
System.Console.WriteLine(outStr3) //输出的是Ray Adas
替换字符串
语法
let testStr = "Ray Adas"
let outStr4 = testStr.Replace(" ","~") //把字符串中的空格替换成~
System.Console.WriteLine(outStr4) //输出的是Ray Adas
字符串填充
注意点
- 函数左边的参数是填充后的字符串长度
- 函数右边的参数是填充的内容,必须为Char类型
- PadLeft函数向左填充;PadRight函数向右填充
示例
let testStr = "RayAdas"
let outStr5 = testStr.PadLeft(10,'*')
let outStr6 = testStr.PadRight(10,'*')
System.Console.WriteLine(outStr5) //输出的是***RayAdas
System.Console.WriteLine(outStr6) //输出的是RayAdas***
字符串裁剪
语法
let testStr2 = "*******GNU "
let outStr7Temp = testStr2.Trim('*') //删去字符串首尾的*号
let outStr7 = outStr7Temp.Trim() //不传入参数默认删去字符串首尾的空格
System.Console.WriteLine(outStr7) //输出的是GNU