From e0a90ec56c0f55b13e39ed65c57c47a43e7f2b25 Mon Sep 17 00:00:00 2001 From: Andrew Gilbert Date: Fri, 27 Mar 2020 23:14:08 -0700 Subject: [PATCH 1/2] Grammar cleanup on Record docs Fix some typos and touch up style --- docs/record.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/docs/record.md b/docs/record.md index 68523bd89c..d6f22bbb2a 100644 --- a/docs/record.md +++ b/docs/record.md @@ -9,9 +9,9 @@ Records are like JavaScript objects but are - fixed in field names and types - very fast - a bit more rigidly typed -- compiles to a JavaScript object still +- still compiled to JavaScript objects -Because record compiles to a straightforward JS object, you can directly model incoming JS objects as Reason records, **no conversion functions needed**. This is extremely convenient when interoperating with existing JS libraries, since most of them use objects in their APIs and you wouldn't need to wrap those with a layer of Reason APIs. +Because a record compiles to a straightforward JS object, you can directly model incoming JS objects as Reason records, **no conversion functions needed**. This is extremely convenient when interoperating with existing JS libraries, since most of them use objects in their APIs and you wouldn't need to wrap those with a layer of Reason APIs. ## Usage @@ -58,7 +58,7 @@ let name = me.name; ### Record Needs an Explicit Definition -Record is one of the very few features in Reason where we mandate you to pre-declare its type before using it. For various performance and type checking reasons. In the above example, if you only write `let me = {age: 5, name: "Baby Reason"}` without an explicit type declaration somewhere above, the type system will give you an error. If the type definition resides in another file or module, you need to indicate it: +For various performance and type checking reasons, records are one of the very few features in Reason where we require you to pre-declare a type before using it. In the above example, if you only write `let me = {age: 5, name: "Baby Reason"}` without an explicit type declaration somewhere above, the type system will give you an error. If the type definition resides in another file or module, you need to indicate it: ```reason /* file School.re */ @@ -86,7 +86,7 @@ var me = { ``` -Either of the above 3 says "this record's definition is found in the School file/module". The first one, the regular type annotation, is preferred. +Any of the three examples above says "this record's definition is found in the School file/module". The first one, the regular type annotation, is preferred. ### Immutable Update @@ -161,7 +161,7 @@ var someHorsePower = { ``` -**Note that there's no punning for a single record field**! `{foo}` doesn't do what you expect (it's a block that returns the value `foo`). +**Note that there's no punning for a single record field!** `{foo}` doesn't do what you expect; it's a block that returns the value `foo`. ## Tips & Tricks @@ -186,16 +186,16 @@ getAge(kraken); getAge(me); ``` -The type system will complain that `me` is a `person`, and that `getAge` only works on `monster`. If you need such capability, use Reason objects, described [here](object.md). +The type system will complain that `me` is a `person`, and that `getAge` only works on `monster`. If you need this capability, use Reason objects, described [here](object.md). ## Design Decisions -After reading the constraints in the previous sections, and if you're coming from a dynamic language background, you might be wondering why one would bother with record in the first place instead of imitating JS and use a catch-all object concept for everything. +If you're coming from a dynamic language background, you might be wondering why one would bother with records in the first place instead of imitating JS and using a catch-all object concept for everything. -The reason is that JavaScript objects can be _really_ slow. Some code might add fieds, remove fields, iterate over them, pass the keys themselves somewhere else, etc. The JS engines nowadays try to "guess" your object's usage patterns and sometime optimize that into a solid C++ struct, but some other time fail to do so and convert your overly dynamic object into a hash map, with a sudden >100x performance degradation (imagine an object field access needing to hash the key and traverse the hashmap to find it). +The reason is that JavaScript objects can be _really_ slow. Code can add fields, remove fields, iterate over them, or pass the keys themselves somewhere else. JS engines nowadays try to "guess" your object's usage patterns and optimize it into a solid C++ struct. Sometimes they fail to do so and convert your overly dynamic object into a hash map, with a sudden >100x performance degradation: every field access is forced to hash the field name and traverse the hash map to find it. -We love simplicify, but a single all-powerful data structure that is the JS object is a bit too naive. This is why Reason separates the above use-cases into record, and proper hashmap (documented later). This way, you get to leverage the consistently fast record experience, like in the above immutable update section. Field access is also guaranteed to be super fast. +We love simplicify, but the single all-powerful data structure that is the JS object is too simplistic. Reason separates the known and unknown key use cases into record and proper hash map (documented later). This way, you can leverage the consistently fast record experience, as shown in the immutable update section above. Field access is also guaranteed to be super fast. -"But doesn't a Reason record compile to a JS object anyway"? Yes, but those records will trigger the JS engines' optimistic object optimizations, since they see that you never tried to e.g. add or remove record fields, iterate through the keys, etc., and therefore they'll never transform your those compiled JS objects into C++ hash maps or other slow data structures. Basically, Reason's type system enforced the disciplined usage of this data structure so that you can guarantee that it will never be accidentally slow. +"But doesn't a Reason record compile to a JS object anyway?" Yes, but those records will trigger the JS engines' optimistic object optimizations, since they see that you never tried to, say, add or remove record fields or iterate through the keys, and therefore they'll never transform your compiled JS objects into C++ hash maps or other slow data structures. Basically, Reason's type system enforced the disciplined usage of this data structure so that you can guarantee that it will never be accidentally slow. -(And yes, we're aware that it's comical for a language feature to transform into a dynamic-looking JS object, then transformed again by the JS engines into a C++ struct, then end up where we started in the first place. Such is modern engineering.) \ No newline at end of file +(And yes, we're aware that it's comical for a language feature to transform into a dynamic-looking JS object, then be transformed again by the JS engines into a C++ struct, only to end up where we started in the first place. Such is modern engineering.) From d762ddb38dab2b537e2f6894d55232b53e3031b1 Mon Sep 17 00:00:00 2001 From: Andrew Gilbert Date: Fri, 27 Mar 2020 23:52:04 -0700 Subject: [PATCH 2/2] Proofread README Clean up grammar and styling. --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index c66ce3a62f..6f108aa969 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,14 @@ # Reason Website -This code is used to generate https://reasonml.github.io. It pulls in files from `docs/` and `website/` to generate html files served on the site. +This code is used to generate https://reasonml.github.io. It pulls in files from `docs/` and `website/` to generate HTML files served on the site. -`website/` contains the JS, CSS, images and other files (and blog, which contains some markdown files too, these are separated from `docs/`, not too important). +`website/` contains the JS, CSS, images and other files (and some markdown files in `blog` which are separated from `docs/`; it's not too important). `cd website && yarn && yarn start` to start the development server & watcher. Don't use `yarn build`. It's mostly for debugging. -In the end, we spit out normal HTML, with all the JS dependencies (barring a few critical ones) removed, including ReactJS itself. It's a full, static website, super lightweight, portable, unfancy but good looking. Works with JS turned off too. +In the end, we spit out normal HTML with all but a few critical JS dependencies removed, including ReactJS itself. It's a full static website: super lightweight, portable, unfancy, but good looking. And it works with JS turned off! Two special files: @@ -19,7 +19,7 @@ During your development, most changes will be picked up at each browser refresh. ## Translations -The entire site can be translated via the [Crowdin project](https://crowdin.com/project/reason). This repo only has the canonical english documentation. Don't manually edit things in `i18n/`. +The entire site can be translated via the [Crowdin project](https://crowdin.com/project/reason). This repo only has the canonical English documentation. Don't manually edit things in `i18n/`. ## Debugging @@ -27,9 +27,9 @@ The entire site can be translated via the [Crowdin project](https://crowdin.com/ ## Building and Deploying -Changes from `source` branch are automatically picked into `master` branch by CI, then published. +Changes from the `source` branch are automatically picked into `master` branch by CI and then published. -# Build the Playground +# Building the Playground ``` cd website && yarn