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
  • 相关阅读:
    “智商平平”学软件
    一个多线程示例程序的BUG修复
    金旭亮《C#面向对象程序设计》2011完整版发布
    《.NET 4.0网络开发入门之旅》7:填平缓冲区陷阱
    《.NET 4.0网络开发入门之旅》5:与Socket的“再次见面”
    《.NET 4.0网络开发入门之旅》6:“麻烦”的数据缓冲区
    软件天才与技术民工
    .NET 4.0 技术亮点剖析——在中科院计算所的讲座PPT及源码下载
    C#实现程序的开机启动
    C#获取当前时间、日期
  • 原文地址:https://www.cnblogs.com/humz/p/10679849.html
Copyright © 2011-2022 走看看