Exercise 11: Follow ownership¶
Aim: observe a borrowed read and an escaping captured value. Save ex11.fib.
You will inspect compiler decisions, not add manual retain/release calls.
Type and predict¶
(ns main)
(defun size (s: str) -> i64 (str-len s))
(defun greeting (name: str) -> (fn () str)
(fn () (str "hello, " name)))
(defun main () -> i64
(let ((name "Ada")
(n (size name))
(say (greeting name)))
(do
(println n)
(println name)
(println (say))
0)))
size reads its argument. That read does not stop the caller using name
again. greeting returns a closure: the captured name must remain alive after
that call returns. Fibber borrows for reads and counts escaping values; the
compiler chooses. The type (fn () str) describes a function taking no arguments
and returning a string.
Inspect and change¶
- Find
sizeandgreetingin the explanation. Record the decisions around reading and capturingname. The exact diagnostic layout is not a fixture. - Call
saytwice. Predict whether the first call consumes the greeting. - Produce two greetings with different names and call them in reverse order. Require each closure to retain its own name.
Break and repair¶
Replace (say) with (say 1) in a copy. The closure's function type takes no
arguments. Repair the call and explain why ownership checking does not replace
ordinary type/argument checking. Exercise 12 will provoke an ownership-specific
rejection with two in-out uses of the same place.
Checkpoint¶
Explain what must survive after greeting returns, and why a borrowed read is
different from a value kept by a returned closure. Consult the
ownership guide if your explanation relies
on garbage collection or programmer-written lifetimes.