Ocaml学习笔记 语句

    技术2022-05-20  28

    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

    对表达式的值进行模式匹配,在这从pattern1到pattern 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、


    最新回复(0)