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
  • 相关阅读:
    linux 进程等待 wait 、 waitpid
    数理逻辑量词的引入
    Android自己定义动态布局 — 多图片上传
    Dynamics CRM 2015/2016 Web API:Unbound Custom Action 和 Bound Custom Action
    iOS 9应用开发教程之显示编辑文本标签文本框
    iOS 9应用开发教程之ios9中实现按钮的响应
    iOS 9应用开发教程之使用代码添加按钮美化按钮
    iOS 9应用开发教程之ios9的视图
    iOS 9应用开发教程之定制应用程序图标以及真机测试
    iOS 9应用开发教程之编辑界面与编写代码
  • 原文地址:https://www.cnblogs.com/humz/p/10679849.html
Copyright © 2011-2022 走看看