F#学习笔记-方法
2010-05-15 13:12 FMax 阅读(264) 评论(0) 编辑 收藏 举报在上篇笔记里介绍完了F#里的基本类型,现在该介绍如果定义方法了。在F#里,定义一个方法跟定义一个基本类型的数据一样,语法是:
let squart x = x * x;;
square是函数名,第一个x是参数,等号后面的部分就是函数的主体部分了。在F#中,函数是没有return关键字的,方法总是返回函数体内的最后一行代码的结果作为方法的结果。在上面的例子中x * x就是这个方法的返回结果。
执行let squart x = x * x;;将得到:
val squart : int –> int
这个可以读作:方法squart获取一个int参数并且返回一个int类型的结果。
而下面这个方法:
let add x y = x + y;;
的执行结果是:
val add : int -> int –> int
这个的读法稍微复杂些:方法add获取一个int参数并且返回一个获取一个int参数并返回一个int结果的方法。呵呵,读起来有点绕口。
在定义方法的时候,很多情况下,我们可以忽略指定参数的类型,F#的编译器会根据代码的上下文推断出参数的类型,以及方法的返回类型。在上面的add方法的例子里,由于没有其他的代码,F#的编译器把参数的类型默认为int类型,如果现在执行:
add 1.0 2.0;;
将得到下面的错误:
add 1.0 2.0;;
----^^^
stdin(7,5): error FS0001: This expression was expected to have type
int
but here has type
float
但是如果是这样:
let add x y = x + y
let sum = add 1.0 2.0
就可以得到正确结果:
val add : float -> float -> float
val sum : float = 3.0
这个时候,方法的参数类型就变成了float类型。或者,我们可以在方法的定义中明确的指出参数的数据类型:
let add (x : float) y = x + y;;
val add : float -> float –> float
由于'+'运算的2个参数的类型是一致的,所以我们只需要指定其中1个参数的类型。
那这样可不可以呢:
let add x y = x + y
let sum = add 1 2
let sum = add 1.0 2.0;;
答案是悲剧的:
let sum = add 1.0 2.0;;
--------------^^^
stdin(20,15): error FS0001: This expression was expected to have type
int
but here has type
float
第二个调用会报异常。原因是第一个调用决定了方法参数的类型。
泛型方法
观察下面方法:
let op x = x;;
得到:
val op : 'a –> 'a
上面的这个方法也等效于:
let op (x : ‘a) = x;; //这个就是明确的指出这个方法是个泛型方法
'a在这里就表示了一个泛型参数。这是由于在这个方法中,任意类型的参数都可以使方法成立。那在之前的add方法的例子里有没有可能也定义成一个泛型方法呢?没有。这是由于在支持'+’运算的类型中,无论是int还是float或者其他的,它们没有一个共同的基类或者接口是支持'+’运算的,类型object肯定是不支持的,也就是说没办法提供一个约束来限定参数的类型范围,所以,编译器没办法根据let sum = add 1 2 & let sum = add 1.0 2.0推断出一个泛型方法同时可以支持int和float类型。还是C#的自动类型转换好啊,呵呵。
作用域
每一个被定义的数据都有它的作用域,在F#里,需要记住的是,每个值在使用前,它应该是被定义过的,也就是说定义的代码必须出现在使用它的代码之前。默认情况下,数据总是被定义在module里的,所以,在被定义之后,去其他地方可被任意使用。我将用几个例子来描述下F#里的作用域,例子总是最好的文档,对吧?:)
let moduleValue = 10
let f x = x + moduleValue;; // after declared, you can use it.
但是:
let f x =
let functionValue = 10
x + functionValue
functionValue;; // this is a wrong example
stdin(34,1): error FS0039: The value or constructor 'functionValue' is not defined
接下来,再看个复杂点的例子:
let GigaBytes x =
let x = x / 1024I // 第二个x是方法参数的x,而第一个x则是方法内定义的x
let x = x / 1024I // 第二个x是上一行定义的x,而非参数x,而第一个x则将覆盖掉上一行定义的x。这里let x = x / 1024I,并不是将原本的x的值修改为 x / 1024I,而是重新定义了一个值。
let x = x / 1024I
x;;
let x = GigaBytes (1I <<< 31);;
val it : System.Numerics.BigInteger = 2 {IsEven = true;
IsOne = false;
IsPowerOfTwo = true;
IsZero = false;
Sign = 1;}
结果是2。呵呵。
IF .. THEN .. ELSE ..
你可以在方法内部使用条件控制语句:if .. then .. [else ..]。
let f x =
if x % 2 = 0 then
printfn “it’s Even”
else
printfn “it is not”;;
或者
let f x =
let result =
if x % 2 = 0 then true
else false
result;;
嵌套
let f x =
let result =
if x % 2 = 0 then
1
else
if x % 3 = 0 then
2
else
3
result;;
也可以简写成
let f x =
let result =
if x % 2 then 1
elif x % 3 then 2
elif x % 5 then 3
else 4;;
如果存在else的情况下,if .. then 以及 else 返回的数据类型必须一致。
> let f x =
if x % 2 then
1
else
false;;
false;;
--------^^^^^
stdin(124,9): error FS0001: This expression was expected to have type
int
but here has type
bool
好了,目前为止,怎么写一个方法应该没什么问题了。
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步