zoukankan      html  css  js  c++  java
  • Real World OCaml

    ISBN 978-7-5123-7637-3

    English First Edition PDF

    Code Examples

    Install Guidence from cornell/cs3110

    Part I

    based on Core instead of standard library

    1 / 3;;
    (* - : int = 0 *)
    
    1 / 3.;;
    1. /. 3;; 
    2. / 3.;;
    (* Error: This expression has type float but an expression was expected of type int *)
    
    1. /. 3.;;
    (* - : float = 0.333333333333333315 *)
    
    let even x =
      x mod 2 = 0 ;;
    (* val even : int -> bool = <fun> *)
    

    Identifiers for variable names:
    punctuation is excluded, except for _ and ', must start with a lowercase letter or an underscore.
    By default, utop doesn’t print out variables starting with an underscore.

    first-class functions

    Module names
    always start with a capital letter.

    type inference

    let sum_if_true test first second =
      (if test first then first else 0)
      + (if test second then second else 0)
    ;;
    (* val sum_if_true : (int -> bool) -> int -> int -> int = <fun> *)
    
    let sum_if_true (test : int -> bool) (x : int) (y : int) : int =
      (if test x then x else 0)
      + (if test y then y else 0)
    ;;
    

    parametric polymorphism

    generic type & type variable

    let first_if_true test x y =
      if test x then x else y
    ;;
    (* val first_if_true : ('a -> bool) -> 'a -> 'a -> 'a = <fun> *)
    

    * compile time error & runtime exception

    built-in simple types:
    int, float, bool, char, string, unit

    pattern matching

    let t = (3, "four", 5.);;
    (* val t : int * string * float = (3, "four", 5.) *)
    let (x, y, z) = t;;
    

    * tuple: fixed item number, different types

    * list: any item number, the same type

    ~f: labeled argument

    let langs = ["ocaml", "cpp", "c"];;
    (* a singleton list containing a three-tuple
     * val langs : (string * string * string) list = [("ocaml", "cpp", "c")]
     *)
    
    let langs = ["ocaml"; "cpp"; "c"];;
    (* val langs : string list = ["ocaml"; "cpp"; "c"] *)
    List.map langs ~f:String.length;;
    (* - : int list = [5; 3; 1] *)
    
    "python" :: langs;;
    (* - : string list = ["python"; "ocaml"; "cpp"; "c"] *)
    langs;;
    (* - : string list = ["ocaml"; "cpp"; "c"] *)
    
    ["py"; "perl"] @ langs;;
    (* - : string list = ["py"; "perl"; "ocaml"; "cpp"; "c"] *)
    

    The bracket notation for lists is really just syntactic sugar for :: (right-associative).

    Unlike ::, @ is not a constant-time operation (proportional to the length of the first list).

    let my_fav_lang (my_fav :: the_rest) = my_fav;;
    (* Here is an example of a case that is not matched: [] *)
    
    let my_fav_lang langs =
      match langs with
      | first :: the_rest -> first
      | [] -> "ocaml"
    ;;
    

    recursive

    let rec sum l =
      match l with
      | [] -> 0
      | hd :: tl -> hd + sum tl
    ;;
    

    option

    let divide x y =
      if y = 0 then None else Some (x/y) ;;
    (* val divide : int -> int -> int option = <fun> *)
    

    A let paired with an in can be used to introduce a new binding within any local scope, including a function body.
    The in marks the beginning of the scope within which the new variable can be used.

    let x = 7 in
      let y = x * x in
        x + y
    ;;
    

    record

    type point2d = {x : float; y : float};;
    let p = {x = 3.; y = -4.};;
    (* val p : point2d = {x = 3.; y = -4.} *)
    

    variant

    type v = 
      | Int of int
      | Point2D of point2d
    ;;
    (* type v = Int of int | Point2D of point2d *)
    

    array

    let numbers = [| 1; 2; 3; 4 |];;
    (* val numbers : int array = [|1; 2; 3; 4|] *)
    
    numbers.(2) <- 4;;
    (* - : unit = () *)
    

    The unit type has only one possible value, written (), generally used as a placeholder.
    We use unit for the return value of an operation like setting a mutable field that communicates by side effect rather than by returning a value. It’s also used as the argument to functions that don’t require an input value (like void in C or Java).

    mutable record

    type running_sum =
    {
      mutable sum : float;
      mutable samples : int;
    };;
    
    let mean rsum = rsum.sum /. float rsum.samples
    let create () = {sum = 0.; samples = 0}
    let update rsum x =
      rsum.samples <- rsum.samples + 1;
      rsum.sum <- rsum.sum +. x
    ;;
    (* val mean : running_sum -> float = <fun>
     * val create : unit -> running_sum = <fun>
     * val update : running_sum -> float -> unit = <fun>
     *)
    
    let rsum = create ();;
    List.iter [1.;3.;2.;-7.;4.;5.] ~f:(fun x -> update rsum x);;
    mean rsum;;
    

    Anonymous functions
    are declared using the fun keyword, and don’t need to be ex‐ plicitly named.

    ref:
    the standard way of simulating the traditional mutable variables

    let x = {contents = 0};;
    x.contents <- x.contents + 1;;
    (* equivalent to *)
    let x = ref 0;;
    x := !x + 1;;
    
    (* implementations *)
    type 'a ref = {mutable contents : 'a}
    
    let ref x = {contents = x}
    let (!) r = r.contents
    let (:=) r x = r.contents + x
    ;;
    

    The parentheses around ! and := are needed because these are operators, rather than ordinary functions.

    let sum list =
      let sum = ref 0 in
        List.iter list ~f:(fun x -> sum := !sum + x);
      !sum
    ;;
    

    for & while

    out of toplevel

    (* sum.ml *)
    open Core
    
    let rec read_and_accumulate accum =
      let line = In_channel.input_line In_channel.stdin in
      match line with
      | None -> accum
      | Some x -> read_and_accumulate (accum +. Float.of_string x)
    
    let () =
      printf "Total: %F
    " (read_and_accumulate 0.)
    
    corebuild sum.ml
    

    Part II

    anonymous & higer-order function

    let increments = [ (fun x -> x + 1); (fun x -> x + 2) ];;
    (* val increments : (int -> int) list = [<fun>; <fun>] *)
    
    List.map ~f:(fun g -> g 5) increments;;
    (* - : int list = [6; 7] *)
    

    currying

    let abs_diff x y = abs (x - y);;
    (* equivalent to *)
    let abs_diff =
      (fun x -> (fun y -> abs (x - y)));;
    
    (* partial application *)
    let dist_from_3 = abs_diff 3;;
    

    or pattern

    | [] | [_]

    Explicitly marking of recursion doesn’t apply to a pure language like Haskell.

    Predetermined identifiers characters set and strings:
    ! $ % & * + - . / : < = > ? @ ^ | ~
    or mod lsl (logical shift left)

    (+) 1 2;;
    (* - : int = 3 *)
    
    Int.max 3 -4;; (* error *)
    Int.max 3 (-4);;
    
    let (|>) x f = f x;;
    (* val ( |> ) : 'a -> ('a -> 'b) -> 'b = <fun> *)
    

    Negation has lower precedence than function application.

    function keyword

    let some_or_zero function
      | Some x -> x
      | None -> 0
    ;;
    

    __labeled argument __

    let ratio ~num ~denom = float num /. float denom;;
    (* val ratio : num:int -> denom:int -> float = <fun> *)
    
    ratio ~denom:10 ~num:3;;
    

    Label punning:
    you get to drop the text after the : if the name of the label and the name of the variable being used are the same.

    TODO

    1. files
    2. modules
    3. functors
    4. objects
    5. classes

    Part III

    TODO

    1. s-expression
    2. concurrency
    3. FFI
    4. GC
    5. compiler frontend
  • 相关阅读:
    20155239 2016-2017-2 《Java程序设计》第7周学习总结
    20155231 2016-2017-2 《Java程序设计》第4周学习总结
    20155231 2016-2017-2 《Java程序设计》第3周学习总结
    20155231 2016-2017-2 《Java程序设计》第2周学习总结
    20155231 2016-2017-2 《Java程序设计》第1周学习总结
    第三次预作业20155231邵煜楠:虚拟机上的Linux学习
    预备作业2:阅读心得(20155231邵煜楠)
    博客初体验:我期望的师生关系
    安装虚拟机
    20155227第二次预备作业
  • 原文地址:https://www.cnblogs.com/humz/p/10679849.html
Copyright © 2011-2022 走看看