Skip to content

Commit

Permalink
feat: improve Js.Dict API (#974)
Browse files Browse the repository at this point in the history
* feat: improve Js.Dict API

* chore: add changelog entry
  • Loading branch information
anmonteiro authored Dec 12, 2023
1 parent f60e8ab commit d9d81da
Show file tree
Hide file tree
Showing 5 changed files with 15 additions and 18 deletions.
2 changes: 2 additions & 0 deletions Changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ Unreleased
([#972](https://github.com/melange-re/melange/pull/972))
- BREAKING(runtime): Add labeled arguments to the callbacks in `Js.Global`
([#973](https://github.com/melange-re/melange/pull/973))
- BREAKING(runtime): Add a label to `Js.Dict.map`'s function argument pipe-last
([#974](https://github.com/melange-re/melange/pull/974))

2.2.0 2023-12-05
---------------
Expand Down
19 changes: 8 additions & 11 deletions jscomp/runtime/js_dict.ml
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,8 @@ external unsafeGet : 'a t -> key -> 'a = ""
[@@mel.get_index]
(** [unsafeGet dict key] returns the value associated with [key] in [dict]
This function will return an invalid value ([undefined]) if [key] does not exist in [dict]. It
will not throw an error.
*)
This function will return an invalid value ([undefined]) if [key] does not
exist in [dict]. It will not throw an error. *)

let ( .!() ) = unsafeGet

Expand All @@ -53,8 +52,8 @@ external set : 'a t -> key -> 'a -> unit = ""
[@@mel.set_index]
(** [set dict key value] sets the value of [key] in [dict] to [value] *)

external keys : 'a t -> key array = "Object.keys"

external keys : 'a t -> key array = "keys"
[@@mel.scope "Object"]
(** [keys dict] returns an array of all the keys in [dict] *)

external empty : unit -> 'a t = ""
Expand All @@ -67,24 +66,22 @@ let unsafeDeleteKey : (string t -> string -> unit[@u]) =
}
|}]

external unsafeCreate : int -> 'a array = "Array" [@@mel.new]
external unsafeCreateArray : int -> 'a array = "Array" [@@mel.new]

(* external entries : 'a t -> (key * 'a) array = "Object.entries" (* ES2017 *) *)
let entries dict =
let keys = keys dict in
let l = Js_array.length keys in
let values = unsafeCreate l in
let values = unsafeCreateArray l in
for i = 0 to l - 1 do
let key = Js_array.unsafe_get keys i in
Js_array.unsafe_set values i (key, dict.!(key))
done;
values

(* external values : 'a t -> 'a array = "Object.values" (* ES2017 *) *)
let values dict =
let keys = keys dict in
let l = Js_array.length keys in
let values = unsafeCreate l in
let values = unsafeCreateArray l in
for i = 0 to l - 1 do
Js_array.unsafe_set values i dict.!(Js_array.unsafe_get keys i)
done;
Expand All @@ -109,7 +106,7 @@ let fromArray entries =
done;
dict

let map f source =
let map ~f source =
let target = empty () in
let keys = keys source in
let l = Js_array.length keys in
Expand Down
8 changes: 3 additions & 5 deletions jscomp/runtime/js_dict.mli
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ external set : 'a t -> key -> 'a -> unit = ""
[@@mel.set_index]
(** [set dict key value] sets the [key]/[value] in [dict] *)

external keys : 'a t -> string array = "Object.keys"

external keys : 'a t -> string array = "keys"
[@@mel.scope "Object"]
(** [keys dict] returns all the keys in the dictionary [dict]*)

external empty : unit -> 'a t = ""
Expand All @@ -64,11 +64,9 @@ module Js := Js_internal
val unsafeDeleteKey : (string t -> string -> unit[@u])
(** Experimental internal function *)

(* external entries : 'a t -> (key * 'a) array = "Object.entries" *)
val entries : 'a t -> (key * 'a) array
(** [entries dict] returns the key value pairs in [dict] (ES2017) *)

(* external values : 'a t -> 'a array = "Object.values" *)
val values : 'a t -> 'a array
(** [values dict] returns the values in [dict] (ES2017) *)

Expand All @@ -80,6 +78,6 @@ val fromArray : (key * 'a) array -> 'a t
(** [fromArray entries] creates a new dictionary containing each
[(key, value)] pair in [entries] *)

val map : (('a -> 'b)[@u]) -> 'a t -> 'b t
val map : f:(('a -> 'b)[@u]) -> 'a t -> 'b t
(** [map f dict] maps [dict] to a new dictionary with the same keys,
using [f] to map each value *)
2 changes: 1 addition & 1 deletion jscomp/runtime/js_json.mli
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ external object_ : t Js_dict.t -> t = "%identity"
(** [object_ dict] makes a JSON object of the [Js.Dict.t] [dict] *)

external array : t array -> t = "%identity"
(** [array_ a] makes a JSON array of the [Js.Json.t array] [a] *)
(** [array a] makes a JSON array of the [Js.Json.t array] [a] *)

(** The functions below are specialized for specific array type which
happened to be already JSON object in the Melange runtime. Therefore
Expand Down
2 changes: 1 addition & 1 deletion jscomp/test/js_dict_test.ml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,6 @@ let suites = Mt.[
Eq([|("x", 23); ("y", 46)|], fromArray [|("x", 23); ("y", 46)|] |> entries));
"map", (fun _ ->
Eq( [%obj { foo = "43"; bar = "86" }] |> Obj.magic,
map (fun [@u] i -> string_of_int i) (obj ())))
map ~f:(fun [@u] i -> string_of_int i) (obj ())))
]
;; Mt.from_pair_suites __MODULE__ suites

0 comments on commit d9d81da

Please sign in to comment.