World: r4wp
[Rebol School] REBOL School
older newer | first last |
Ladislav 27-Aug-2012 [852] | It is stil confusing (to me) because the variable 'stack' is declared to be a local variable. - more confusing is that it is not a stack as Brian pointed out |
GrahamC 27-Aug-2012 [853x2] | Arnold, 'stack is local to the function. Ordinarily you would make a copy each time the function is called so that you have an empty new block. But here the function does not so that the block contents are available unchanged between calls. |
So, I guess my question is .. when do local variables get garbage collected? | |
Ladislav 27-Aug-2012 [855x3] | When do local variables get garbage collected? - never, only in case they are not accessible |
,i.e. only in case the function is collected | |
however, the STACK local variable is actually not just "local variable", it is a value in the function body. In this case the only way how the value could be collected is to collect the function | |
GrahamC 27-Aug-2012 [858] | so you would have to unset the function ? Or just set it to none? |
Ladislav 27-Aug-2012 [859x2] | However, the function looks strange to me. I guess that it should have been implemented differently. |
so you would have to unset the function ? - you cannot unset a function. You can only unset the variable referring to it. | |
GrahamC 27-Aug-2012 [861] | yes, that's what I meant |
Maxim 27-Aug-2012 [862] | Arnold, if you are proficient at language C, R2's local word model is the same as static variables in C. |
Ladislav 27-Aug-2012 [863] | E.g. f: func [] [] unset 'f would make the function inaccessible (collectable), but, e.g. g: func [][] g: 1 makes the function inaccessible (collectable) as well |
Maxim 27-Aug-2012 [864] | that wasn't worded how I meant it... |
Ladislav 27-Aug-2012 [865] | R2's local word model is the same as static variables in C. - hmm, there are some significant differences |
Maxim 27-Aug-2012 [866x3] | Arnold, What I meant to say (and what ladislav is trying to say, I think) is that the code inside a function is not Garbage collected, so when a function has a litteral value.. that litteral value is the same at each execution (its static). |
the local values are reset to none at each execution, but they will be re-assigned to the same litteral. | |
(which is why they look like static variables in terms of series which are references) | |
GrahamC 27-Aug-2012 [869] | So, anonymous functions are automatically garbage collected? |
Maxim 27-Aug-2012 [870x2] | no. it depends if they are referenced at least once in a value which is not also GCd. |
so if you have a function in a block, named or not, it won't be GCd if that block is still refered to somewhere. | |
GrahamC 27-Aug-2012 [872] | so let's say you have something in a vid defintion button "Test" [ use [ f ][ f: func [] [] ] ] this is not subject to GC? |
Ladislav 27-Aug-2012 [873x2] | the local values are reset to none at each execution - that should have been: the local variables are reset to NONE at every function call. After the function returns, the local variables are: - in R2 they remember" the last (outermost call) value - in R3 their values are inaccessible |
this is not subject to GC? - Such a function looks like a subject to GC, but you need to find out *when*. - in R2 it is a subject to GC right after the button is pressed and released - in R3 the function *may* persist after the button is pressed for the first time and *before* it is pressed for the second time | |
GrahamC 27-Aug-2012 [875] | @Ladislav, have you written a paper on GC in Rebol ? |
Ladislav 27-Aug-2012 [876x2] | Aha, I was wrong with R2, actually in R2 the function persists between presses as well, but the reasons are different for R2 and R3 |
have you written a paper on GC in Rebol ? - the reason why the function persists between presses in R2 is based on the fact that USE modifies its argument block "leaving" the local variable in it. (it is described in Bindology). In R3 USE is a closure written in REBOL, that is why there may be some "persistence" until the USE function is called next time | |
BrianH 27-Aug-2012 [878x2] | IIRC in R3 closures do a BIND/copy of their bodies at every call, then execute the copy. As soon as the USE is finished executing its context and body are no longer referenced, at least if you didn't save a reference elsewhere. The context containing the 'f and the function it references would be able to be GC'd as soon as the USE returns. |
The CLOSURE function in R2 should behave the same way, though it fakes it with mezz code. | |
Ladislav 27-Aug-2012 [880] | Checked the USE implementation in R3 (source use) and you are right, Brian, so, the function in R3 shall not persist at all. |
BrianH 27-Aug-2012 [881x2] | Yeah, R3's USE does a COPY/deep of the body, then make closure! uses the copy itself, then when executed (IIRC) the closure executes a BIND/copy of its body. So it copies its body more than once, but possibly less than twice. |
Proof: >> b: make closure! reduce [[] [append [] 1]] >> b == [1] >> b == [1] >> mold :b == "make closure! [[][append [] 1]]" | |
GrahamC 27-Aug-2012 [883] | so to control GC one should in such a block unset the contents before leaving it ... |
BrianH 27-Aug-2012 [884x2] | Sorry, didn't get that. In R2 if you are using functions not defined by the CLOSURE function then you might want to set some local variables to none before returning - that's what ALSO was for, btw. In R3 you don't need to unset anything because the GC will collect the set of values associated with the function's local variables after the function returns, or the whole context after a closure returns. |
I guess you could use ALSO for R2's USE blocks too, or you could explicitly COPY/deep the body the way R3's USE does internally. | |
Maxim 27-Aug-2012 [886] | In R3 ... the GC will collect the set of values associated with the function's local variables does it actually perform the GC, actively mark them as potentials, or simply unreference them? |
BrianH 27-Aug-2012 [887x5] | It's a stack frame. Stack frames are automatically available for collection after the particular function call returns. All function words are referenced stack-relative. |
They aren't collected immediately, they are collected when the collector runs. | |
Closures are different; the contexts that they create when they are called are basically the same as object contexts, with no stack-relative indirection needed, but the whole body and context are unreferenced after the call. | |
Whoah, it turns out that R3's closures do more than a regular BIND/copy when they run, they copy strings too. Surprised I hadn't tried that. >> c: make closure! [[] [append "" 1]] >> c == "1" >> mold :c == {make closure! [[][append "" 1]]} | |
Same in R2: MAKE function! does more than a BIND/copy on its body as well, it also copies strings. >> c: closure [] [append "" 1] >> source c c: func [][native action function! [[throw]] [append "" 1]] >> c == "1" >> c == "1" >> source c c: func [][native action function! [[throw]] [append "" 1]] | |
Maxim 27-Aug-2012 [892x2] | I always though BIND/copy was equivalent to BIND COPY/deep |
(which would copy strings AFAIK) | |
BrianH 27-Aug-2012 [894x4] | BIND/copy doesn't copy everything, it just copies everything that's bindable. So, no copying of strings, objects, functions, modules, lists or hashes, but it copies blocks, parens and paths. Words are of course copied because they're literal values. |
At least that's what I was told. Let me check. | |
Functions and objects aren't copied, but everything else seems to be: >> a: reduce ["" #{} 'a/b [] quote () make list! [] make hash! [] does [] context []] == ["" #{} a/b [] () make list! [] make hash! [] func [][] make object! [ ]] >> b: bind/copy a 'a == ["" #{} a/b [] () make list! [] make hash! [] func [][] make object! [ ]] >> map-each [x: y] b [same? :y first at a index? x] == [false false false false false false false true true] | |
I guess that R2's make function! and R3's closures to a BIND/copy after all. | |
GrahamC 27-Aug-2012 [898x3] | What we need is a document that discusses best practice for writing Rebol code. Or is there such a beast? |
Sure we have various idioms that people get used to using, but that's not the same thing | |
Ideally this should be in a book chapter .. perhaps Jerry could include it in his book as a guest chapter ? | |
Endo 28-Aug-2012 [901] | map-each [x: y] [...] is an interesting use. I sometimes needed to get that "index" value but I didn't know that usage so I used forall instead. Good to learn. |
older newer | first last |