From f45671f79f7151b209145856b6d407cd742625d2 Mon Sep 17 00:00:00 2001 From: Feihong Hsu Date: Fri, 21 Jun 2024 11:59:49 -0500 Subject: [PATCH 1/3] Revert back to OCaml 5.1.1 --- docs/sandwich-tests/index.md | 6 +++--- melange-for-react-devs.opam | 4 ++-- package.json | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/sandwich-tests/index.md b/docs/sandwich-tests/index.md index 530325ef..567932f8 100644 --- a/docs/sandwich-tests/index.md +++ b/docs/sandwich-tests/index.md @@ -41,10 +41,10 @@ Open `melange-for-react-devs.opam` and add a corresponding entry in the ``` depends: [ - "ocaml" {>= "5.2.0"} + "ocaml" {>= "5.1.1"} "reason" {>= "3.10.0"} "dune" {>= "3.8"} - "melange" {>= "4.0.0-52"} + "melange" {>= "4.0.0-51"} "reason-react" {>= "0.14.0"} "reason-react-ppx" {>= "0.14.0"} "melange-fest" {>= "0.1.0"} // [!code ++] @@ -79,7 +79,7 @@ The output will look something like this: ``` # switch compiler description -→ ~/melange-for-react-devs ocaml-base-compiler.5.2.0 ~/melange-for-react-devs +→ ~/melange-for-react-devs ocaml-base-compiler.5.1.1 ~/melange-for-react-devs default ocaml.5.1.0 default [NOTE] Current switch has been selected based on the current directory. diff --git a/melange-for-react-devs.opam b/melange-for-react-devs.opam index 150163a6..f162590d 100644 --- a/melange-for-react-devs.opam +++ b/melange-for-react-devs.opam @@ -7,10 +7,10 @@ license: "MIT" homepage: "https://github.com/melange-re/melange-for-react-devs" bug-reports: "https://github.com/melange-re/melange-for-react-devs" depends: [ - "ocaml" {>= "5.2.0"} + "ocaml" {>= "5.1.1"} "reason" {>= "3.10.0"} "dune" {>= "3.8"} - "melange" {>= "4.0.0-52"} + "melange" {>= "4.0.0-51"} "reason-react" {>= "0.14.0"} "reason-react-ppx" {>= "0.14.0"} "melange-fest" {>= "0.1.0"} diff --git a/package.json b/package.json index eca913dc..041a45b8 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "preinstall:opam": "opam update", "install:opam": "opam install -y . --deps-only --with-test", "check-npm-deps": "opam exec opam-check-npm-deps", - "init": "opam switch create . 5.2.0 -y --deps-only && npm run install:npm-opam", + "init": "opam switch create . 5.1.1 -y --deps-only && npm run install:npm-opam", "install:npm-opam": "npm install && npm run install:opam && npm run check-npm-deps", "dune": "opam exec -- dune", "build": "npm run dune -- build", From 993a68abee258f95b191f669540830deb147e0a6 Mon Sep 17 00:00:00 2001 From: Feihong Hsu Date: Fri, 21 Jun 2024 12:07:10 -0500 Subject: [PATCH 2/3] Replace deprecated OCaml manual URLs with their current equivalents --- docs/better-sandwiches/index.md | 2 +- docs/burger-discounts/index.md | 4 ++-- docs/discounts-lists/index.md | 2 +- docs/promo-component/index.md | 2 +- docs/styling-with-css/index.md | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/better-sandwiches/index.md b/docs/better-sandwiches/index.md index bf8035e3..e821f264 100644 --- a/docs/better-sandwiches/index.md +++ b/docs/better-sandwiches/index.md @@ -336,7 +336,7 @@ chapter. [^1]: Technically, undeclared variables produce a warning and it's possible to tell OCaml to not treat them as compilation errors. A common way to do this is via the [built-in `warning` - attribute](https://v2.ocaml.org/manual/attributes.html#ss:builtin-attributes). + attribute](https://ocaml.org/manual/5.2/attributes.html#ss:builtin-attributes). [^2]: You may be wondering why a unicorn sandwich costs $80. Well, that is just the price of ethically-sourced unicorn meat. All the "guests" at the diff --git a/docs/burger-discounts/index.md b/docs/burger-discounts/index.md index 9968d2c5..417a7821 100644 --- a/docs/burger-discounts/index.md +++ b/docs/burger-discounts/index.md @@ -337,7 +337,7 @@ switch (burgers) { ``` OCaml [only allows you to pattern match on arrays of fixed -length](https://v2.ocaml.org/manual/patterns.html#sss:pat-array), so to fix +length](https://ocaml.org/manual/5.2/patterns.html#sss:pat-array), so to fix this, we must instead match on a tuple of the first and second elements of the array: @@ -546,7 +546,7 @@ and [demo](https://react-book.melange.re/demo/src/burger-discounts/) for this ch [^1]: The official term for something like `Item.Burger` (module name followed by value name) is [access - path](https://v2.ocaml.org/manual/names.html#sss:refer-named), but this term + path](https://ocaml.org/manual/5.2/names.html#sss:refer-named), but this term isn't widely used. [^2]: Another valid way to discard the return value of a function is: diff --git a/docs/discounts-lists/index.md b/docs/discounts-lists/index.md index e43ffe19..cf4d8bf0 100644 --- a/docs/discounts-lists/index.md +++ b/docs/discounts-lists/index.md @@ -476,7 +476,7 @@ Add this new test to `DiscountTests` and make sure it passes: Use [List.filteri](https://melange.re/v4.0.0/api/re/melange/Stdlib/List/#val-filteri) -and [mod operator](https://v2.ocaml.org/manual/expr.html#ss:expr-operators). +and [mod operator](https://ocaml.org/manual/5.2/expr.html#ss:expr-operators). ::: diff --git a/docs/promo-component/index.md b/docs/promo-component/index.md index 6347cb33..278cb03b 100644 --- a/docs/promo-component/index.md +++ b/docs/promo-component/index.md @@ -27,7 +27,7 @@ In a couple of the documentation comments, you see square brackets (`[]`): Whatever is inside the brackets gets rendered in a monospace source code font. This is one example of the [markup -language](https://v2.ocaml.org/releases/5.0/manual/ocamldoc.html#ss:ocamldoc-formatting) +language](https://ocaml.org/manual/5.2/ocamldoc.html#ss:ocamldoc-formatting) used inside documentation comments. ## `Promo` component diff --git a/docs/styling-with-css/index.md b/docs/styling-with-css/index.md index 088ce67b..d6ffdeda 100644 --- a/docs/styling-with-css/index.md +++ b/docs/styling-with-css/index.md @@ -26,7 +26,7 @@ line to the top of `Order.re`: ``` The `{||}` string literal is known as a [quoted -string literal](https://v2.ocaml.org/manual/lex.html#sss:stringliterals), and it +string literal](https://ocaml.org/manual/5.2/lex.html#sss:stringliterals), and it is used to represent strings of arbitrary content without escaping[^3]. They are similar to the `{js||js}` string literals we first saw in the [Celsius Converter](/celsius-converter-exception/#solutions) chapter, with the difference From 509e7252093879d1f501f2e2c7da58a515b6ae7a Mon Sep 17 00:00:00 2001 From: Feihong Hsu Date: Fri, 21 Jun 2024 21:12:56 -0500 Subject: [PATCH 3/3] Change "polymorphic variant constructor" to "variant tag" --- docs/promo-codes/index.md | 52 +++++++++++++++++------------------ docs/promo-component/index.md | 25 ++++++++--------- 2 files changed, 37 insertions(+), 40 deletions(-) diff --git a/docs/promo-codes/index.md b/docs/promo-codes/index.md index 4547d1dc..6659122d 100644 --- a/docs/promo-codes/index.md +++ b/docs/promo-codes/index.md @@ -253,10 +253,10 @@ instead use a *polymorphic variant*: <<< Discount.re#get-free-burgers-poly{13-14} Polymorphic variants are similar to the variants you've seen before, the main -difference being that you don't need to declare the constructors beforehand. -Instead, you can freely use polymorphic variant constructors inside a function, -and the type of the function is inferred from the usage. For example, the type -of `Discount.getFreeBurgers` is now +difference being that you don't need to define the *variant tags* beforehand. +Instead, you can freely use variant tags (like `` `NeedTwoBurgers`` and `` +`NeedOneBurger``) inside a function, and the type of the function is inferred +from the usage. For example, the type of `Discount.getFreeBurgers` is now ```reason list(Item.t) => result(float, [> `NeedOneBurger | `NeedTwoBurgers ]) @@ -264,8 +264,7 @@ list(Item.t) => result(float, [> `NeedOneBurger | `NeedTwoBurgers ]) ::: tip -The name of a polymorphic variant constructor must start with the backtick (`` ` -``) character. +The name of a variant tag must start with the backtick (`` ` ``) character. ::: @@ -293,14 +292,14 @@ list(Item.t) => result(float, [> `NeedMegaBurger ]) ## Fixing the tests -Fixing the tests is mostly a mechanical and consists of these steps: +Fixing the tests is mostly a mechanical effort and consists of these steps: - Replace `Some` with `Ok` -- Replace `None` with ``Error(`SomeConstructor)`` +- Replace `None` with ``Error(`SomeTag)`` - Replace `equal` with `deepEqual` -However, there is a little wrinkle. What if you misspell one of the polymorphic -variant constructors? +However, there is a little wrinkle. What if you misspell one of the variant +tags? ```reason{5} test("1 burger, no discount", () => @@ -315,9 +314,9 @@ The constructor should be called `` `NeedOneBurger`` but here it's been misspelled as `` `NeedOneBurgers``, yet it still compiles! This is due to the open-ended nature of polymorphic variants. The compiler knows that `Discount.getFreeBurgers` currently can't return ``Error(`NeedOneBurgers)``, but -because the constructors for polymorphic variants don't need to be defined -up-front, it has no way to know that the function will **never** return -``Error(`NeedOneBurgers)`` in the future. +because variant tags don't need to be defined up-front, it has no way to know +that the function will **never** return ``Error(`NeedOneBurgers)`` in the +future. ## Runtime representation of polymorphic variants @@ -333,12 +332,12 @@ clarity): + _0: 'NeedOneBurger' ``` -You can see that polymorphic variant constructors without arguments are just -strings in the JS runtime. +You can see that variant tags without arguments are just strings in the JS +runtime. -For reference, the runtime representation for polymorphic variant -constructors with arguments is an object with `NAME` and `VAL` fields. For -example, `` `foo(42)`` becomes `{"NAME": "foo", "VAL": 42}`. +For reference, the runtime representation of a variant tag with an argument is +an object with `NAME` and `VAL` fields. For example, `` `foo(42)`` becomes +`{"NAME": "foo", "VAL": 42}`. ## Variants vs polymorphic variants @@ -375,12 +374,11 @@ correctly, so prefer to use the functions in `Js.String` on a sequence of numbers - Polymorphic variants are like the variants we've already seen but with some differences: - - The constructors don't need to defined before they are used - - The constructors must start with the backtick (`` ` ``) character - - A polymorphic variant constructor without arguments becomes a string in the - JS runtime - - A polymorphic variant constructor with argument(s) becomes an object in the - JS runtime. The keys in the object are `NAME` and `VAL`. + - The variant tags don't need to defined before they are used + - A tag must start with the backtick (`` ` ``) character + - A variant tag without arguments becomes a string in the JS runtime + - A variant tag with argument(s) becomes an object in the JS runtime. The keys + in the object are `NAME` and `VAL`. ## Exercises @@ -463,6 +461,6 @@ and [demo](https://react-book.melange.re/demo/src/promo-codes/) for this chapter [^1]: It was quite a sight to see a giant burger zipping around the fairgrounds on a Segway while being chased by a small army of juggalos. -[^2]: Instead of creating a polymorphic variant constructor out of the phrase - "burger that has every topping", we save ourselves some typing by using the - much shorter "megaburger". +[^2]: Instead of creating a variant tag out of the phrase "burger that has every + topping", we save ourselves some typing by using the much shorter + "megaburger". diff --git a/docs/promo-component/index.md b/docs/promo-component/index.md index 278cb03b..a5bb571f 100644 --- a/docs/promo-component/index.md +++ b/docs/promo-component/index.md @@ -364,9 +364,9 @@ of data goes like this: 1. If the result of `discountFunction(items)` is `Ok(value)`, then return `` `Discount(value)`` -Because we use polymorphic variant constructors, we don't need to define a new -type. If you hover over the `discount` variable in your editor you'll see that -its inferred type is: +Because we use polymorphic variant tags, we don't need to define a new type. If +you hover over the `discount` variable in your editor you'll see that its +inferred type is: ```reason [> `CodeError(Discount.error) @@ -436,15 +436,15 @@ occur. In the next chapter, we'll integrate this `Promo` component into your compatible with your Melange packages - A good strategy for rendering mutually-exclusive states is to create a single switch expression that maps your inputs to each state, where each state is - represented by a different polymorphic variant constructor. + represented by a different variant tag. ## Exercises 1. Render the different error messages for the `` `DiscountError`` branch of `Promo`'s switch expression. Here's what message should be shown for each -constructor: +tag: -| Polymorphic variant constructor | Message | +| Variant tag | Message | | ------------------------------- | ------- | | `` `NeedOneBurger`` | Buy at least 1 more burger to enjoy this promotion | | `` `NeedTwoBurgers`` | Buy at least 1 more burgers to enjoy this promotion | @@ -565,18 +565,17 @@ The type signature of `getDiscountFunction` remains unchanged, returning a function encased in `Ok` when it succeeds. In contrast, `getDiscountPair` returns a 2-tuple encased in `Ok`: -- The first element of the tuple is a polymorphic variant constructor indicating - which function was returned, e.g. `` `FreeBurger``, `` `HalfOff``, etc. +- The first element of the tuple is a variant tag indicating which function was + returned, e.g. `` `FreeBurger``, `` `HalfOff``, etc. - The second element of the tuple is the discount function -The polymorphic constructor serves to give test code something to compare -against: +The variant tag serves to give test code something to compare against: <<< DiscountTests.re#use-discount-function-pair{2-3,20-21} -Recall that the runtime representation of a polymorphic constructor without -arguments is just a string. They can be compared using `Fest.deepEqual` without -any surprises. +Recall that the runtime representation of a variant tag without arguments is +just a string. They can be compared using `Fest.deepEqual` without any +surprises. Run `npm run test` to verify that all tests are passing again.