3 ms·
> Vaporization basically ties everything to the stack, and prevents values stored on the heap from becoming dissociated with it. So if some code somewhere hand
by tom_mellior 6y ago
> Vaporization basically ties everything to the stack, and prevents values stored on the heap from becoming dissociated with it.
So if some code somewhere hands me a list that contains references to some heap data, how do you track this? For example, say at some point in the program I have a reference called "refs" that happens to be bound to a list of references to some objects a, b, and c. Then I do:
refs = drop_first refs
so that refs is now [b, c]. We lost/dropped/gave up a. How do we know how a was tied to the stack? How many other references might point at the object previously referenced by a? Can we collect that object now? Is this the case where reference counting kicks in? In which case, the category of "closure references" is probably more general than I thought.
- slightknack 6y agoBecause Passerine is pass-by-value, it only allows each reference to be owned by one object. > So if some code somewhere hands me a list that contains references to some heap data, how do you track this? Passerine is a high-level language, so it does not give the programmer control over whether something is a list of references to data on the heap or a list of values. Assuming `a`, `b`, and `c` have been defined, If I write this: list = [a, b, c] `a`, `b`, and `c` will be moved into the list upon construction. If I do something like: list = [a, b, c] print (foo a c) `b` will be moved into the list, and copies of `a` and `c` will be moved into the list. So, to now answer your question: list = [a, b, c] list = drop_first list > We lost/dropped/gave up a. How do we know how a was tied to the stack? `a` was tied to the stack because it's in `[a, b, c]`, which is tied to the stack via `list`. > How many other references might point at the object previously referenced by a? Can we collect that object now? By definition, none - `a` is a unique value. Now that we dropped `a`, there are guaranteed to be no other references of `a`, so we can collect that object now. > Is this the case where reference counting kicks in? No, the reference counting is a small optimization for sharing immutable values in closures. If a closure captures a value, say a large list, we don't want to go around copying this willy-nilly: big_list = [...] c = () -> { -- big list is copied when the closure is made -- this happens because the reference in the closure can outlive local stack frame a -> first big_list } -- these calls to c do not copy big_list again a_outer = c () a_another = c () Closures need to copy values immutably to prevent the construction of cycles. I wrote a long explanation on why this is the case, but I've decided to move it to the blog post when I publish it. I thought of a way to efficiently count references acyclically, but I need to work it out before I made any more claims. Hope this helps!