Docs: Make ref-let pattern a bit clearer (#1016)

This commit is contained in:
Scott Olsen 2020-11-24 13:28:15 -05:00 committed by GitHub
parent eb85906e52
commit 541630569c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -8,34 +8,42 @@ You may occasionally want to compute the result of running two different
ownership-taking functions on a non-ref argument from an enclosing scope.
Consider the following function:
```
```clojure
(defn needs-ref-let [x]
(Pair.init (inc x) (dec x)))
(Pair.init (Maybe.or-zero x) (Maybe.or-zero x)))
```
Carp will complain about this function since `inc` and `dec` both
*take-ownership* of the non-ref argument, `x` -- this is nice since it ensures
we don't somehow mutate the memory associated with `x` -- if we did, we would
get unpredictable results, especially in multi-threaded contexts in which `inc`
and `dec` may try to access `x` simultaneously.
Carp will complain about this function since `Maybe.or-zero` *takes ownership*
of the non-ref, managed argument `x`<sup>1</sup> -- this is nice since it ensures we
don't somehow mutate the memory associated with `x` -- if we did, we would get
unpredictable results, especially in multi-threaded contexts in which
`Maybe.or-zero` may try to access `x` simultaneously.
But you may still want to compute both `inc` and `dec` on the single `x` value!
For these cases, it's useful to introduce a variable bound to a `Ref` to `x`:
But you may still want to compute both `Maybe.or-zero` calls on the single `x`
value! For these cases, it's useful to introduce a variable bound to a `Ref`
to `x`:
```
```clojure
(defn needs-ref-let [x]
(let [x* &x]
(Pair.init (inc @x*) (dec @x*))))
(Pair.init (Maybe.or-zero @x*) (Maybe.or-zero @x*))))
```
`x*`, which is just a reference to the `x` argument, allows you to flexibly
copy `x` at will throughout the function body. Of course, the second copy here
is actually unnecessary, since once we've copied `x` once, we're free to use `x`
itself again, since there's no longer threat of bad mutations or races between
`inc` and `dec`:
itself again:
```
```clojure
(defn needs-ref-let [x]
(let [x* &x]
(Pair.init (inc @x*) (dec x))))
(Pair.init (Maybe.or-zero @x*) (Maybe.or-zero x))))
```
---
1: In Carp, sumtypes like `Maybe` are *managed* by the borrow checker. This
means that Carp will ensure any memory associated with them has proper
ownership and is deleted when they are no longer needed. Not all types are
managed. `Int`, for example, is not a managed type, and so the issue described
above won't be relevant for `Int` arguments. For more information see
[docs/memory.md](docs/memory.md)