Ocaml学习笔记 语句

来源:互联网 发布:mac退出软件快捷键 编辑:程序博客网 时间:2024/05/21 07:50

Ocaml学习笔记 语句

一、 ;;终结符

在Ocaml中使用;;作为终结符,表示一个赋值语句,一个函数,一个模块或者一个类的终结的。在Ocaml的toplevel中只有输入;;终结符,才会对你输入的程序进行编译,然后执行,输出结果。

二、 let 绑定

BNF定义:

let-binding::= pattern = expr

value-name  { parameter }  [: typexpr] = expr

在Ocaml中是通过let绑定来进行变量的赋值和函数的定义的。

使用示例如下:

1、变量赋值

# let a = 123;;

val a : int = 123

2、函数定义

# let square x = x *. x;;

val square : float -> float =

# square 5.;;

- : float = 25.

在上例中我们用let绑定定义了一个square函数来计算一个浮点数的平方

三、 赋值语句

1、在let绑定中我们演示了一个变量声明并赋值的例子。例子声明了一个全局变量a,并对a进行了赋值,

2、但在Ocaml的函数内部,还有局部变量的概念,同样需要声明一个局部变量,并对局部变量进行复制,同全局变量不同的是需要在赋值结束是要加一个in,用来表明这是一个局部变量

示例如下

# let square x =

let b = x in

b *. b;;

val square : float -> float =

# square 5.;;

- : float = 25.

四、 引用

1、Ocaml是一个常量语言,常量语言的意思就是如果一个变量如果已经定义了,那么它的值在运行时是不可以改变的。这点比较类似java。

2、和java中相似,如果一个变量的值改变了,实际上是重新创建了一个变量,然后将变量指向新创建的变量。

3、同java类似,复杂数据是应用传递的,因此我们可以修改复杂数据的数据成员来改变复杂数据的值

4、Ocaml通过重载操作符的方式,创造了一个引用的概念。

引用的使用如下:

引用的定义,要使用引用,必须用ref关键字来表明取得是引用:

# let a = ref 0;;

val a : int ref = {contents = 0}

引用的取值,要获取变量引用的值,必须通过!操作符来获取引用的内容:

# !a;;

- : int = 0

# a;;

- : int ref = {contents = 0}

引用赋值,引用的赋值是通过:=操作符来实现的。

# a = 3;;

Characters 4-5:

a = 3;;

^

Error: This expression has type int but is here used with type int ref

# a := 3;;

- : unit = ()

# !a;;

- : int = 3

# a;;

- : int ref = {contents = 3}

另外你可以通过:<- 给引用的成员赋值

示例如下:

# let a = ref 10;;

val a : int ref = {contents = 10}

# a.contents <- 15;;

- : unit = ()

# a;;

- : int ref = {contents = 15}

五、 函数

1、 函数定义

Ocaml是一个函数式的语言,支持了很多很复杂的函数特性。在Ocaml中函数可以像数据一项被传递,因此Ocaml中可以很方便的使用复合函数。

函数的定义可以通过let绑定和几个未知参数或者通过function或者fun关键字来定义。let绑定的作用是将一个函数的实现和名称联系起来。有的时候我们可以定义一个无名称的函数。

下面是几个用let绑定定义普通函数和复合函数的例子:

              #let deriv f dx = function x -> (f(x +. dx) -. f(x)) /. dx;;
            val deriv : (float -> float) -> float -> float -> float = 
            #let sin’ = deriv sin 1e-6;;
            val sin’ : float -> float = 
            #sin’ pi;;
            - : float = -1.00000000013961143
#let compose f g = function x -> f(g(x));;
val compose : (’a -> ’b) -> (’c -> ’a) -> ’c -> ’b = 
#let cos2 = compose square cos;;
val cos2 : float -> float = 

在Ocaml中函数相关的关键字有两个 function、fun

其中function关键字定义的函数只能有一个参数,而fun关键字定义的函数可以有多个参数。

function的BNF定义如下:

function pattern1->expr1

|… 

|patternn->exprn

如果使用function作为关键字,那么对应的函数只能有一个参数。参数和pattern1…patternn这n个pattern依次进行匹配,如果patternk匹配成功了,则返回表达式exprk的结果

function使用示例

# let b n = function n -> (n + 1);;

val b : 'a -> int -> int =

# b 3;;

- : int -> int =

# b 3 4;;

- : int = 5

# let c n = function x y -> n + 1;;

Characters 21-22:

let c n = function x y -> n + 1;;

^

Error: Syntax error

fun的BNF定义如下

fun parameter1 …  parametern -> expr

或者:

fun parameter1 ->fun parametern -> expr

fun关键字对应的是n个参数的情况。

fun使用示例

# let c n = fun x y -> n + 1;;

val c : int -> 'a -> 'b -> int =

# c 3;;

- : '_a -> '_b -> int =

# c 3 4;;

- : '_a -> int =

# c 3 4 5;;

- : int = 4

2、 无参函数的定义

有的函数没有参数,但又不能为了防止编译器将函数误认为变量定义,需要加()表示没有参数。()等同于unit。

示例:

# let a = 1 + 1;;

val a : int = 2

# let a () = 1 + 1;;

val a : unit -> int =

# a ();;

- : int = 2

3、 递归函数

递归函数相对于普通函数的区别是要在在函数名称前面加了一个rec,如果不加rec,那么编译器会报错。之所以加rec的原因是因为Ocaml在一个函数被完全声明前,并不知道自己连接的是哪一个。

4、 函数的返回值

函数是将;;之前的表达式作为返回值返回的。

5、 函数组合

函数组合是指:将函数作为参数传递给另外一个函数。接收参数的函数成为复合函数。

复合函数的示例如下:

# let f x = x * x;;

val f : int -> int =

# let compose h g = function x -> h(g(x));;

val compose : ('a -> 'b) -> ('c -> 'a) -> 'c -> 'b =

# compose f f 3;;

- : int = 81

# let compose2 h g = function x -> (h (g(x)));;

val compose2 : ('a -> 'b) -> ('c -> 'a) -> 'c -> 'b =

# compose2 f f 3;;

- : int = 81

六、 流程控制语句

1、 if else语句

if else 语句有两种用法:

这两种用法的BNF定义如下:

if expr then expr  [ else expr

               if … then begin … ; … end else begin … ; … end

其中begin expr end( expr )是等价的。不过对于编程来说用begin end形式更加美观一点。

代码示例如下:

# let test5 x =

if x < 3 then begin

if x = 1 then Printf.printf "1 This is %d" x

end

else begin

if x = 4 then Printf.printf "4 This is %d" x

end

;;

val test5 : int -> unit =

# test5 4;;

4 This is 4- : unit = ()

# test5 1;;

1 This is 1- : unit = ()

# test5 3;;

- : unit = ()

# let test1 x =

if x = 1 then Printf.printf "1 This is %d" x

else

Printf.printf "Not 1 This is %d" x;;

val test1 : int -> unit =

# test1 1;;

1 This is 1- : unit = ()

# test1 2;;

Not 1 This is 2- : unit = ()

let test7 x =

if x < 7 then

( if x = 1 then Printf.printf "1 This is %d" x

else Printf.printf "Not 1 This is %d" x)

else ( if x = 7 then Printf.printf "7 This is %d" x

else Printf.printf "Not 7 This is %d" x);;

val test7 : int -> unit =

# test7 7;;

7 This is 7- : unit = ()

2、 match with语句

BNF定义

match expr

with pattern1 -> expr1

|… 

|pattern n -> exprn

对表达式的值进行模式匹配,在这从pattern1pattern n个模式中,如果模式patternk 匹配成功,则返回表达式exprk的值。如果同时有多个模式匹配成功,则返回在match with语句中出现的第一个匹配成功的表达式的值。如果没有任何模式匹配成功,则会抛出Match_failure的异常

代码示例:

# let rec sum n =

match n with

0 -> 0

| x -> (x + sum (x-1));;

val sum : int -> int =

# sum 10;;

- : int = 55

3、 begin end 语句

请见if else部分

七、 循环语句

1、 for语句

BNF定义:

for name = expr1 to expr2 do expr3 done

代码示例:

# let sum n =

let s = ref 0 in

for i = 0 to n do

s := !s + i

done;

!s;;

val sum : int -> int =

# sum 10;;

- : int = 55

代码中done后面一定要交;,否则程序会编译不通过。

2、 while语句

BNF定义:

while expr1 do expr2 done

代码示例:

# let sum n =

let s = ref 0 in

let i = ref 0 in

while !i < n do

i := !i + 1;

s := !s + !i;

done;

!s;;

val sum : int -> int =

# sum 10;;

- : int = 55

3、

原创粉丝点击