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
  • 相关阅读:
    字串变换
    重建道路
    poj3278 Catch That Cow
    机器人搬重物
    [HNOI2004]打鼹鼠
    曼哈顿距离
    邮票面值设计
    poj1101 The Game
    解决了一个堆破坏问题
    模型资源从无到有一条龙式体验
  • 原文地址:https://www.cnblogs.com/humz/p/10679849.html
Copyright © 2011-2022 走看看