1. 7
1.

2. 1

It’s not clear from the examples how the ownership model works with fields. If I destructively read a field that is a pointer, does it make the field null? How do I then deal with all of the nulls everywhere?

1. 1

Hi, author here. I don’t know! Haven’t gotten that far yet. What do you think would make most sense?

I’m imagining two options:

``````type Node {
left  *Node
right *Node
}

fun option_1_a(n Node) {
let a = n.left  // moves value to a
n.left          // error: n.left is dead
somefun(n)      // error: n is partially dead
} // drop(n.right), drop(a)

fun option_1_b(n &Node) { // n is a reference
let a = n.left  // error: cannot move borrowed value
}

fun option_2_a(n Node) {
let a = n.left     // error: cannot move pointer field
let b = &n.left    // ok; references the field (&Node)
let c = mut&n.left // ok since n is mutable (mut&Node)
} // drop(n.right), drop(n.left)

fun option_2_b(n &Node) { // n is a reference
let b = &n.left    // ok; references the field (&Node)
let c = mut&n.left // error: mut. ref to immutable value
}
``````
1. 1

Pony addresses this by making `=` a kind of swap, so `a=b` stores `b` in `a` and evaluates to the old value of `a`. This makes it fairly concise to preserve linear types. The problem with your first option is that it is dynamic state that needs to be tracked and isn’t expressed in your type system. The type of `n.left` is not actually `Node*`, it’s `Node* | Invalid`, but the `Invalid` option is ephemeral state. This leads to the kind of situation where you have some expressions that you can’t outline. Effectively, your scope must destroy `n`.

1. 1

Very interesting, making “=“ a kind of swap operation!

2. 1

Surprised this isn’t for the Compis. COMAL 4 lyfe!

1. 3

“Compis” is a variation on the Swedish word “kompis”, meaning “buddy” or “comrade.” It’s also a nod to one of the first computers I used as a kid.