2020-06-14 06:54:06 +03:00
|
|
|
# Carp Patterns
|
|
|
|
|
|
|
|
This doc captures some common programming patterns in Carp.
|
|
|
|
|
|
|
|
## Ref-let
|
|
|
|
|
2020-07-26 01:30:37 +03:00
|
|
|
You may occasionally want to compute the result of running two different
|
2020-06-14 18:01:05 +03:00
|
|
|
ownership-taking functions on a non-ref argument from an enclosing scope.
|
|
|
|
Consider the following function:
|
2020-06-14 06:54:06 +03:00
|
|
|
|
2020-11-24 21:28:15 +03:00
|
|
|
```clojure
|
2020-06-14 06:54:06 +03:00
|
|
|
(defn needs-ref-let [x]
|
2020-11-24 21:28:15 +03:00
|
|
|
(Pair.init (Maybe.or-zero x) (Maybe.or-zero x)))
|
2020-06-14 06:54:06 +03:00
|
|
|
```
|
|
|
|
|
2020-11-24 21:28:15 +03:00
|
|
|
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.
|
2020-06-14 06:54:06 +03:00
|
|
|
|
2020-11-24 21:28:15 +03:00
|
|
|
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`:
|
2020-06-14 06:54:06 +03:00
|
|
|
|
2020-11-24 21:28:15 +03:00
|
|
|
```clojure
|
2020-06-14 06:54:06 +03:00
|
|
|
(defn needs-ref-let [x]
|
|
|
|
(let [x* &x]
|
2020-11-24 21:28:15 +03:00
|
|
|
(Pair.init (Maybe.or-zero @x*) (Maybe.or-zero @x*))))
|
2020-06-14 06:54:06 +03:00
|
|
|
```
|
|
|
|
|
2020-07-26 01:30:37 +03:00
|
|
|
`x*`, which is just a reference to the `x` argument, allows you to flexibly
|
2020-06-14 18:01:05 +03:00
|
|
|
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`
|
2020-11-24 21:28:15 +03:00
|
|
|
itself again:
|
2020-06-14 06:54:06 +03:00
|
|
|
|
2020-11-24 21:28:15 +03:00
|
|
|
```clojure
|
2020-06-14 06:54:06 +03:00
|
|
|
(defn needs-ref-let [x]
|
|
|
|
(let [x* &x]
|
2020-11-24 21:28:15 +03:00
|
|
|
(Pair.init (Maybe.or-zero @x*) (Maybe.or-zero x))))
|
2020-06-14 06:54:06 +03:00
|
|
|
```
|
2020-11-24 21:28:15 +03:00
|
|
|
|
|
|
|
---
|
|
|
|
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
|
2020-12-16 12:09:00 +03:00
|
|
|
[docs/memory.md](Memory.md)
|