-
Notifications
You must be signed in to change notification settings - Fork 502
Docs for casing on constants #7481
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,125 @@ | ||
| --- | ||
| sidebar_position: 26 | ||
| --- | ||
|
|
||
| # Case-splitting on constants | ||
|
|
||
| :::info | ||
|
|
||
| This use of `case` in UPLC was introduced with protocol version 11 and requires | ||
| [Plutus Core version](../essential-concepts/versions#plutus-core-version) | ||
| `1.1.0`. | ||
|
|
||
| ::: | ||
|
|
||
| In UPLC, it is possible to branch on expressions of certain built-in types, like | ||
| `Integer` and `Bool`. This can be done with `case` syntax, which is also used | ||
| for [sums-of-products](./encoding#sums-of-products). Using `case` on built-in | ||
| values may improve script performance and size. | ||
| The built-in types that `case` currently supports are: | ||
|
|
||
| - `bool` | ||
| - `unit` | ||
| - `integer` | ||
| - `list` | ||
| - `pair` | ||
|
|
||
| In the future, support for `data` is also planned. | ||
|
|
||
| For each type, the allowed branches and their order differs. See [Supported | ||
| Types](#supported-types) for more detail. | ||
|
|
||
| ## Compiling to `case` in Plinth | ||
|
|
||
| When compiling Plinth code with the [option](./plinth-compiler-options) | ||
| `datatypes=BuiltinCasing`, many standard library functions will be compiled into | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We need to mention that this option is going away post hard fork (see the comment on the |
||
| this use of `case`, such as `fstPair`, `ifThenElse` and `caseList`. Note that | ||
| Plinth's `case ... of ...` syntax is not necessarily compiled to UPLC, as it can | ||
| be more expressive. | ||
|
|
||
| ## Supported types | ||
|
|
||
| ### Bool | ||
|
|
||
| Booleans can be used in `case` with either one or two branches, where the first | ||
| is the `False` branch. Boolean negation can be written for example as: | ||
|
|
||
| ```uplc | ||
| lam b (case b (con bool True) (con bool False)) | ||
| ``` | ||
|
|
||
| When only a single branch is provided, script execution will fail when the | ||
| boolean evaluates to `True`. | ||
|
|
||
| Using a single branch is appropriate when the second branch was supposed to fail | ||
| already, saving script size. | ||
|
|
||
| ### Unit | ||
|
|
||
| Needs exactly one branch. If the expression being cased on evaluates to a unit | ||
| value, evaluation will continue with the expression in that branch. For example, | ||
| this expression evaluates to `con integer 5`. | ||
|
|
||
| ```uplc | ||
| case (con unit ()) (con integer 5) | ||
| ``` | ||
|
|
||
| ### Pair | ||
|
|
||
| A built-in pair expects a single branch: a function that takes both components | ||
| of the pair. | ||
|
|
||
| This example sums the two integer constants in a pair. | ||
|
|
||
| ```uplc | ||
| lam x (case x (lam a (lam b [(builtin addInteger) a b]))) | ||
| ``` | ||
|
|
||
| ### Integer | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Mention that the |
||
|
|
||
| Casing on integers can be used for non-negative integers only, and a variable | ||
| amount of branches may be given. If the expression `e` evaluates to an integer | ||
| `i`, the `i`th branch will be evaluated. If there is no branch, `case` will fail. | ||
|
|
||
| For example, the following expression evaluates to `con string "c"` | ||
|
|
||
| ``` | ||
| case [(builtin addInteger) (con integer 1) (con integer 1)] | ||
| (con string "a") | ||
| (con string "b") | ||
| (con string "c") | ||
| ``` | ||
|
|
||
| If the `i`th branch is not given, or `i` is a negative integer, evaluation will | ||
| fail: | ||
|
|
||
| ``` | ||
| case [(builtin addInteger) (con integer 2) (con integer 2)] | ||
| (con string "a") | ||
| (con string "b") | ||
| (con string "c") | ||
| ``` | ||
|
|
||
| Results in | ||
|
|
||
| ``` | ||
| An error has occurred: | ||
| 'case' over a value of a built-in type failed with | ||
| 'case 4' is out of bounds for the given number of branches: 3 | ||
| Caused by: 4 | ||
| ``` | ||
|
|
||
| Note that there is no way to provide a "catch-all" case for integers. | ||
|
|
||
| ### List | ||
|
|
||
| A `case` on built-in lists may be given one or two branches (similar to | ||
| booleans), where the first one deals with the cons case, and the second one with | ||
| the empty list. If no second branch is given, execution will fail when the list | ||
| turns out to be empty. | ||
|
|
||
| This example implements the `head` function, which fails if the list if empty. | ||
|
|
||
| ```uplc | ||
| lam xs (case xs (lam y (lam ys y))) | ||
| ``` | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should mention other ways of deconstructing builtin types (e.g., for
boolone can useifThenElse), and why using the new builtin casing feature is better.