mirror of
https://github.com/carp-lang/Carp.git
synced 2024-09-17 16:38:14 +03:00
Docs: Make ref-let pattern a bit clearer (#1016)
This commit is contained in:
parent
eb85906e52
commit
541630569c
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user