zoukankan      html  css  js  c++  java
  • Ocaml入门(4)

    递归函数

    函数当然可以递归,而且更鼓励用递归而不是循环。

    不过,递归需要关键字声明出来。

    utop # let rec sum lst = match lst with
      |[]-> 0
      |h::tail -> h + sum tail;;
    val sum : int list -> int = <fun>   
    utop # sum [1;2;3;4];;
    - : int = 10  

    看另一个例子,去掉相邻的重复元素。

    utop # let rec rr lst = match lst with
      | []-> []
      | [x]-> lst
      | h1::h2::tail -> if h1=h2 then rr (h2::tail) else h1::rr tail;;
    val rr : 'a list -> 'a list = <fun>    
    utop # rr [1;2;2;3;3;3;4;5];;
    - : int list = [1; 2; 3; 5]    

     选项

    Option 是OCaml中常用的类型。它表示可能是某个值,或者可能什么都没有。

    utop # let div x y =
      if y=0 then None else Some (x/y);;
    val div : int -> int -> int option = <fun>  
    utop # div 6 3;;
    - : int option = Some 2  
    utop # div 6 0;;
    - : int option = None   

    从Option类型的值中取得有效值,需要用“解构”来提取。

    op # let Some x = div 9 3;;
    Characters 4-10:
    Warning 8: this pattern-matching is not exhaustive.
    Here is an example of a value that is not matched: None val x : int = 3

    匹配成功,但编译器给出个语法上的警告,因为无法确定等号右边返回的就是个Some x 的形式,还可能是None呢。

    局部绑定

    utop # let x=5 in x * 2 + 1;;
    - : int = 11 

    x=5 的绑定只在in后的语句中有效。x并不是全局可访问的。

    局部绑定是个表达式,最终返回一个值,就是in语句返回的值。

    当然,局部绑定是可以嵌套的。

    utop # let x = 5 in let y = 6 in x * x + y * y;;
    - : int = 61  

    记录和变体

    utop # type pp = {x:int; y:int};;
    type pp = { x : int; y : int; }  

    记录与tuple相比,每个域有有个名字,这样就可以不按顺序给出每个域的值。

    utop # let a = {y=3;x=4};;
    val a : pp = {x = 4; y = 3}   

    当然,可以采用解构赋值(更准确说,叫绑定)。

    utop # let {x=vx} = a;;
    val vx : int = 4 

    解构也可出现在参数的位置。

    op # let f {x=vx;y=vy} = vx*vx+ vy*vy;;
    val f : pp -> int = <fun>  
    utop # f {x=2;y=5};;
    - : int = 29  

    用在参数位置,可以简化。

    utop # let f {x;y} = x*x+y*y;;
    val f : pp -> int = <fun>  

    可以像Option一样,新的类型也可以组合自多个类型。

    utop # type ppp = {x:int;y:int;z:int};;
    type ppp = { x : int; y : int; z : int; }  
    utop # type p2p3 = P2 of pp | P3 of ppp;;
    type p2p3 = P2 of pp | P3 of ppp  utop # let g p = match p with P2 {x;y} -> "p2" | P3 {x;y;z} -> "p3";; val g : p2p3 -> string = <fun>

     数组

    op # let a = [|1;2;6;9|];;
    val a : int array = [|1; 2; 6; 9|]  
    utop # Array.length a;;
    - : int = 4      
    utop # a.(2) <- 100;;
    - : unit = ()     
    utop # a;;
    - : int array = [|1; 2; 100; 9|]  

    Ocaml 鼓励不使用变量的编程。而数组中的元素是可变的。

    但Ocaml也提供了面向可变性编程,面向过程编程的手段。比如数组,for循环。

    记录类型的值默认是不能更改的。但可以用mutable来修饰,变成可以修改的类型。

    # type r1 = {mutable x:int; mutable y:int};;
    type r1 = { mutable x : int; mutable y : int; }  
    utop # let a = {x=5;y=10};;
    val a : r1 = {x = 5; y = 10}   
    utop # a.x <- 100;;
    - : unit = ()      
    utop # a;;
    - : r1 = {x = 100; y = 10}   

    Ref

    如果记录中只有一个字段,其用法就如同其它语言中的普通变量。因为这种用法比较有代表性,Ocaml就预先做了个类型。测一下:

    utop # let a = {contents=10};;
    val a : int ref = {contents = 10}   

    OCaml提供了预定义的一些函数(或运算符),使得操作更简单直观。

    utop # let x = ref 0;;
    val x : int ref = {contents = 0} 
    utop # !x;;
    - : int = 0     
    utop # x := !x + 1;;
    - : unit = ()     
    utop # !x;;
    - : int = 1 

    for与while循环

    utop # for i=1 to 10 do
      print_int i
    done;;
    utop # while !p<10 do
      p := !p + 1;
      print_int !p
    done;;
  • 相关阅读:
    汤姆大叔的博客
    ajax
    兼容谷歌的光标居中写法
    浅谈服务治理与微服务
    Java线程面试题合集(含答案)
    java设计模式之装饰者模式
    java集合类详解
    java线程-看这一篇就够了
    javaIO详解
    java反射详解
  • 原文地址:https://www.cnblogs.com/gyhang/p/4778842.html
Copyright © 2011-2022 走看看