From 32584be74a99be82029fb7bf531e1687a6fbb21e Mon Sep 17 00:00:00 2001 From: Jimmy Hu Date: Wed, 14 Nov 2018 12:57:48 +0800 Subject: [PATCH 1/3] upgrade to new bs-platofrm --- README.md | 89 +++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 57 insertions(+), 32 deletions(-) diff --git a/README.md b/README.md index 7961c74..b55c6d2 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,7 @@ This has been heavily inspired by the [Rust Cookbook](https://brson.github.io/ru * [Js.Dict](#jsdict) * [Associative list](#associative-list) * [Hashtbl](#hashtbl) + * [Belt.HashMap.String](#belthashmapstring) + [Use a Set in a recursive type](#use-a-set-in-a-recursive-type) * [Promises](#promises) + [Creating new Promises](#creating-new-promises) @@ -182,8 +183,8 @@ let () = Use [Random module](http://caml.inria.fr/pub/docs/manual-ocaml/libref/Random.html) to generate random numbers ```ml -let () = - Js.log (Random.int 5) +let () = Random.init (int_of_float (Js.Date.now ())) +let () = (Random.int 5) |> Js.log ``` #### Log a message to the console @@ -240,29 +241,30 @@ let () = Js.log "no matches" ``` -Or using [bs-revamp](https://github.com/glennsl/bs-revamp) with the same input: - -```ml -input |> Revamp.matches("]*>(.*?)<\\/p>", ~flags=[Revamp.IgnoreCase]) - |> Rebase.Seq.forEach(Js.log); -``` - #### Dasherize camelCased identifiers inside string literals using Regular Expression -Uses [bs-revamp](https://github.com/glennsl/bs-revamp) - ```ml let code = {| let borderLeftColor = "borderLeftColor"; let borderRightColor = "borderRightColor"; |} +let matchLetter letter _ _ = "-" ^ (Js.String.toLowerCase letter) + +let matchLiterals _ p1 _ _ = + let t = + Js.String.unsafeReplaceBy0 + [%re "/[A-Z]/g"] matchLetter p1 in + {j|"$t"|j} + let () = - code |> Revamp.replace {|"([^"]*)"|} (* Matches the content of string literals *) - (Revamp.replace "[A-Z]" (fun letter -> (* Matches uppercase letters *) - "-" ^ letter |> Js.String.toLowerCase)) (* Convert to lower case and prefix with a dash *) - |> Js.log - + (code |> + Js.String.unsafeReplaceBy1 + [%re + "/\"([^\"]*)\"/g"] + matchLiterals) + |> Js.log + (* Outputs: let borderLeftColor = "border-left-color"; let borderRightColor = "border-right-color"; @@ -349,7 +351,7 @@ let () = ###### Hashtbl -Mutable, string key type, cross-platform +Mutable, string key type ```ml let painIndexMap = Hashtbl.create 10 @@ -370,6 +372,29 @@ let () = painIndexMap |> Hashtbl.iter (fun k v -> Js.log {j|key:$k, val:$v|j}) ``` +###### Belt.HashMap.String + +Mutable, string key type, BuckleScript only + +```ml +open Belt +let painIndexMap = HashMap.String.make ~hintSize:10 +let () = + let open HashMap.String in + set painIndexMap "western paper wasp" 1.0; + set painIndexMap "yellowjacket" 2.0; + set painIndexMap "honey bee" 2.0; + set painIndexMap "red paper wasp" 3.0; + set painIndexMap "tarantula hawk" 4.0; + set painIndexMap "bullet ant" 4.0 + +let () = + HashMap.String.set painIndexMap "bumble bee" 2.0 + +let () = + painIndexMap |. HashMap.String.forEach (fun k -> fun v -> Js.log {j|key:$k, val:$v|j}) +``` + #### Use a Set in a recursive type The task is to make something like this using Set: @@ -432,7 +457,7 @@ let timer = accidentally partially apply the function *) let _ : Js.Global.timeoutId = Js.Global.setTimeout - (fun () -> (resolve "Done!")[@bs]) + (fun () -> (resolve "Done!")[@bs]) 1000 in () ) @@ -452,7 +477,7 @@ let _ : unit Js.Promise.t = (* Chaining *) let _ : unit Js.Promise.t = Js.Promise.then_ - (fun value -> Js.Promise.resolve (Js.log value)) + (fun value -> Js.Promise.resolve (Js.log value)) (Js.Promise.then_ (fun value -> Js.Promise.resolve (value + 1)) (Js.Promise.resolve 1)) @@ -474,7 +499,7 @@ let _ : unit Js.Promise.t = let open Js.Promise in all2 (resolve 1, resolve "a") |> then_ (fun (v1, v2) -> - Js.log ("Value 1: " ^ string_of_int v1); + Js.log ("Value 1: " ^ string_of_int v1); Js.log ("Value 2: " ^ v2); resolve ()) @@ -514,20 +539,20 @@ let _ : unit Js.Promise.t = * In general, we should not rely on rejecting/catching errors for control flow; * it's much better to use a `result` type instead. *) -let betterOk : (string, _) Js.Result.t Js.Promise.t = +let betterOk : (string, _) Belt.Result.t Js.Promise.t = Js.Promise.make (fun ~resolve ~reject:_ -> - resolve (Js.Result.Ok ("everything's fine")) [@bs]) + resolve (Belt.Result.Ok ("everything's fine")) [@bs]) -let betterOhNo : (_, string) Js.Result.t Js.Promise.t = +let betterOhNo : (_, string) Belt.Result.t Js.Promise.t = Js.Promise.make (fun ~resolve ~reject:_ -> - resolve (Js.Result.Error ("nope nope nope")) [@bs]) + resolve (Belt.Result.Error ("nope nope nope")) [@bs]) let handleResult = Js.Promise.then_ (fun result -> Js.Promise.resolve ( match result with - | Js.Result.Ok text -> Js.log ("OK: " ^ text) - | Js.Result.Error reason -> Js.log ("Oh no: " ^ reason))) + | Belt.Result.Ok text -> Js.log ("OK: " ^ text) + | Belt.Result.Error reason -> Js.log ("Oh no: " ^ reason))) let _ : unit Js.Promise.t = handleResult betterOk @@ -559,6 +584,8 @@ let person = [%obj { }; age = 32 }] + +let _ = Js.log (## (## person name) first) ``` #### Raise a javascript exception, then catch it and print its message @@ -713,8 +740,8 @@ external withAsyncCallback : ((Js.Json.t -> unit) -> unit) -> unit = "" [@@bs.va let withAsyncCallback: (doneFn -> unit) -> unit = fun f -> withAsyncCallback (fun done_ -> - f (function | Some value -> value |> Js.Json.string |> done_ - | None -> Js.false_ |> Js.Json.boolean |> done_)) + f (function | Some value -> value |> Js.Json.string |> done_ + | None -> false |> Js.Json.boolean |> done_)) ``` @@ -774,7 +801,6 @@ let () = ## Node-specific #### Read lines from a text file -Uses [bs-node](https://github.com/reasonml-community/bs-node) ```ml let () = Node.Fs.readFileAsUtf8Sync "README.md" @@ -783,7 +809,7 @@ let () = ``` #### Read and parse a JSON file -Uses [bs-json](https://github.com/reasonml-community/bs-json) and [bs-node](https://github.com/reasonml-community/bs-node) +Uses [bs-json](https://github.com/reasonml-community/bs-json) ```ml let decodeName text = Js.Json.parseExn text @@ -804,11 +830,10 @@ let () = ``` #### Run an external command -Uses [bs-node](https://github.com/reasonml-community/bs-node) ```ml let () = (* prints node's version *) - Node.(ChildProcess.execSync "node -v" (Options.options ~encoding:"utf8" ())) + Node.(Child_process.execSync "node -v" (Child_process.option ~encoding:"utf8" ())) |> Js.log ``` From 178e6f627f8ef11cf98c17bd956593bcd7f0ba6c Mon Sep 17 00:00:00 2001 From: Jimmy Hu Date: Thu, 15 Nov 2018 19:48:21 +0800 Subject: [PATCH 2/3] add or change some code after the review --- README.md | 62 ++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 50 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index b55c6d2..1aa7e06 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ This has been heavily inspired by the [Rust Cookbook](https://brson.github.io/ru * [Js.Dict](#jsdict) * [Associative list](#associative-list) * [Hashtbl](#hashtbl) - * [Belt.HashMap.String](#belthashmapstring) + * [Belt.HashMap](#belthashmap) + [Use a Set in a recursive type](#use-a-set-in-a-recursive-type) * [Promises](#promises) + [Creating new Promises](#creating-new-promises) @@ -183,8 +183,10 @@ let () = Use [Random module](http://caml.inria.fr/pub/docs/manual-ocaml/libref/Random.html) to generate random numbers ```ml -let () = Random.init (int_of_float (Js.Date.now ())) -let () = (Random.int 5) |> Js.log +(* To make sure you have a different seed when your program runs each time *) +let () = Js.Date.now () |> int_of_float |> Random.init + +let () = Random.int 5 |> Js.log ``` #### Log a message to the console @@ -240,9 +242,37 @@ let () = | None -> Js.log "no matches" ``` +Or using [bs-revamp](https://github.com/glennsl/bs-revamp) with the same input: + +```ml +input |> Revamp.matches("]*>(.*?)<\\/p>", ~flags=[Revamp.IgnoreCase]) + |> Rebase.Seq.forEach(Js.log); +``` #### Dasherize camelCased identifiers inside string literals using Regular Expression +Uses [bs-revamp](https://github.com/glennsl/bs-revamp) + +```ml +let code = {| + let borderLeftColor = "borderLeftColor"; + let borderRightColor = "borderRightColor"; +|} + +let () = + code |> Revamp.replace {|"([^"]*)"|} (* Matches the content of string literals *) + (Revamp.replace "[A-Z]" (fun letter -> (* Matches uppercase letters *) + "-" ^ letter |> Js.String.toLowerCase)) (* Convert to lower case and prefix with a dash *) + |> Js.log + +(* Outputs: + let borderLeftColor = "border-left-color"; + let borderRightColor = "border-right-color"; +*) +``` + +or use `Js.String` + ```ml let code = {| let borderLeftColor = "borderLeftColor"; @@ -351,7 +381,7 @@ let () = ###### Hashtbl -Mutable, string key type +Mutable, string key type, cross-platform ```ml let painIndexMap = Hashtbl.create 10 @@ -372,15 +402,24 @@ let () = painIndexMap |> Hashtbl.iter (fun k v -> Js.log {j|key:$k, val:$v|j}) ``` -###### Belt.HashMap.String +###### Belt.HashMap -Mutable, string key type, BuckleScript only +Use a generic `Belt.HashMap` to demo a mutable hash map with string type key. In fact, You can use `Belt.HashMap.String` instead. ```ml open Belt -let painIndexMap = HashMap.String.make ~hintSize:10 +module StrHash = + Id.MakeHashable(struct + type t = string + let hash (x : t) = String.length x + let eq (a : t) (b : t) = a = b + end) + +let painIndexMap = HashMap.make ~hintSize:10 ~id:(module StrHash) + let () = - let open HashMap.String in + let open HashMap in + set painIndexMap "western paper wasp" 1.0; set painIndexMap "yellowjacket" 2.0; set painIndexMap "honey bee" 2.0; @@ -389,10 +428,11 @@ let () = set painIndexMap "bullet ant" 4.0 let () = - HashMap.String.set painIndexMap "bumble bee" 2.0 + HashMap.set painIndexMap "bumble bee" 2.0 let () = - painIndexMap |. HashMap.String.forEach (fun k -> fun v -> Js.log {j|key:$k, val:$v|j}) + HashMap.forEach painIndexMap + (fun k -> fun v -> Js.log {j|key:$k, val:$v|j}) ``` #### Use a Set in a recursive type @@ -584,8 +624,6 @@ let person = [%obj { }; age = 32 }] - -let _ = Js.log (## (## person name) first) ``` #### Raise a javascript exception, then catch it and print its message From 2c355b4537aefc88b5be32b60f7d6221e968fd74 Mon Sep 17 00:00:00 2001 From: Jimmy Hu Date: Sat, 24 Nov 2018 23:58:29 +0800 Subject: [PATCH 3/3] handwrite ocaml --- README.md | 34 +++++++++++++--------------------- 1 file changed, 13 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 1aa7e06..912e8b5 100644 --- a/README.md +++ b/README.md @@ -184,7 +184,7 @@ Use [Random module](http://caml.inria.fr/pub/docs/manual-ocaml/libref/Random.htm ```ml (* To make sure you have a different seed when your program runs each time *) -let () = Js.Date.now () |> int_of_float |> Random.init +let () = Random.init (Js.Date.now () |> int_of_float) let () = Random.int 5 |> Js.log ``` @@ -282,18 +282,13 @@ let code = {| let matchLetter letter _ _ = "-" ^ (Js.String.toLowerCase letter) let matchLiterals _ p1 _ _ = - let t = - Js.String.unsafeReplaceBy0 - [%re "/[A-Z]/g"] matchLetter p1 in - {j|"$t"|j} + let t = Js.String.unsafeReplaceBy0 [%re "/[A-Z]/g"] matchLetter p1 in {j|"$t"|j} + +let () = + code + |> Js.String.unsafeReplaceBy1 [%re "/\"([^\"]*)\"/g"] matchLiterals + |> Js.log -let () = - (code |> - Js.String.unsafeReplaceBy1 - [%re - "/\"([^\"]*)\"/g"] - matchLiterals) - |> Js.log (* Outputs: let borderLeftColor = "border-left-color"; @@ -411,15 +406,13 @@ open Belt module StrHash = Id.MakeHashable(struct type t = string - let hash (x : t) = String.length x - let eq (a : t) (b : t) = a = b + let hash = String.length + let eq = (=) end) let painIndexMap = HashMap.make ~hintSize:10 ~id:(module StrHash) - let () = let open HashMap in - set painIndexMap "western paper wasp" 1.0; set painIndexMap "yellowjacket" 2.0; set painIndexMap "honey bee" 2.0; @@ -427,12 +420,11 @@ let () = set painIndexMap "tarantula hawk" 4.0; set painIndexMap "bullet ant" 4.0 -let () = - HashMap.set painIndexMap "bumble bee" 2.0 +let () = HashMap.set painIndexMap "bumble bee" 2.0 -let () = - HashMap.forEach painIndexMap - (fun k -> fun v -> Js.log {j|key:$k, val:$v|j}) +let () = + HashMap.forEach painIndexMap + @@ fun k v -> Js.log {j|key:$k, val:$v|j} ``` #### Use a Set in a recursive type