|
23 | 23 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *)
|
24 | 24 |
|
25 | 25 |
|
26 |
| -(** A stdlib shipped with BuckleScript *) |
| 26 | +(** A stdlib shipped with BuckleScript |
| 27 | +
|
| 28 | + This stdlib is still in beta status, but we encourage you to try it out and |
| 29 | + provide feedback. |
| 30 | +
|
| 31 | + {b Motivation } |
| 32 | +
|
| 33 | + The motivation of creating such library is to provide BuckleScript users a |
| 34 | + better end-to-end user experience, since the original OCaml stdlib was not |
| 35 | + writte with JS platform in mind, below are a list of areas this lib aims to |
| 36 | + improve: {ol |
| 37 | + {- 1. Consistency in name convention: camlCase, and arguments order} |
| 38 | + {- 2. Exception thrown functions are all suffixed with {i Exn}, e.g, {i getExn}} |
| 39 | + {- 3. Beter peformance and smaller code size running on JS platform} |
| 40 | + } |
| 41 | +
|
| 42 | + {b Name Convention} |
| 43 | +
|
| 44 | + For higher order functions, it will be suffixed {b U} if it takes uncurried |
| 45 | + callback. |
| 46 | +
|
| 47 | + {[ |
| 48 | + val forEach : 'a t -> ('a -> unit) -> unit |
| 49 | + val forEachU : 'a t -> ('a -> unit [\@bs]) -> unit |
| 50 | + ]} |
| 51 | +
|
| 52 | + In general, uncurried version will be faster, but it is less familiar to |
| 53 | + people who have a background in functional programming. |
| 54 | +
|
| 55 | + {b A special encoding for collection safety} |
| 56 | +
|
| 57 | + When we create a collection library for a custom data type, take {i Set} for |
| 58 | + example, suppose its element type is a pair of ints, |
| 59 | + it needs a custom {i compare} function. However, the {i Set} could not |
| 60 | + just be typed as [ Set.t (int * int) ], |
| 61 | + its customized {i compare} function needs to be |
| 62 | + manifested in the signature, otherwise, if the user create another |
| 63 | + customized {i compare} function, and the two collection would mix which |
| 64 | + would result in runtime error. |
| 65 | +
|
| 66 | + The original OCaml stdlib solved the problem using {i functor} which is a big |
| 67 | + closure in runtime; it makes dead code elimination much harder. |
| 68 | + We introduced a phantom type to solve the problem |
| 69 | +
|
| 70 | + {[ |
| 71 | + type t = int * int |
| 72 | + module I0 = |
| 73 | + (val Bs.Dict.comparableU ~cmp:(fun[\@bs] ((a0,a1) : t) ((b0,b1) : t) -> |
| 74 | + match compare a0 b0 with |
| 75 | + | 0 -> compare a1 b1 |
| 76 | + | c -> c |
| 77 | + )) |
| 78 | + let s0 = Bs.Set.make (module I0) |
| 79 | + module I1 = |
| 80 | + (val Bs.Dict.comparableU ~cmp:(fun[\@bs] ((a0,a1) : t) ((b0,b1) : t) -> |
| 81 | + match compare a1 b1 with |
| 82 | + | 0 -> compare a0 b0 |
| 83 | + | c -> c |
| 84 | + )) |
| 85 | + let s1 = Bs.Set.make (module I1) |
| 86 | + ]} |
| 87 | +
|
| 88 | + Here the compiler would infer [s0] and [s1] having different type so that |
| 89 | + it would not mix. |
| 90 | +
|
| 91 | + {[ |
| 92 | + val s0 : Bs.Set.t ((int * int), I0.id) |
| 93 | + val s1 : Bs.Set.t ((int * int), I1.id) |
| 94 | + ]} |
| 95 | +
|
| 96 | +
|
| 97 | + {b Collection Hierachy} |
| 98 | +
|
| 99 | + In general, we provide a generic collection module, but also create specialized |
| 100 | + modules for commonly used data type, take {i Bs.Set} for example |
| 101 | +
|
| 102 | + {[ |
| 103 | + Bs.Set |
| 104 | + Bs.Set.Int |
| 105 | + Bs.Set.String |
| 106 | + ]} |
| 107 | +
|
| 108 | + The specialized module {i Bs.Set.Int}, {i Bs.Set.String} is in general more |
| 109 | + efficient |
| 110 | + |
| 111 | +*) |
27 | 112 |
|
28 | 113 | (** {!Bs.Dict}
|
29 | 114 |
|
|
0 commit comments