World: r4wp
[Rebol School] REBOL School
older newer | first last |
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 [901x2] | 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. |
Why this doesn't work? e: func [] [f] context [f: does [print "ok"] do bind 'e self] ;error: f has no value or when I BIND the F inside E, still doesn't work: o: context [f: does [print "ok"]] bind first second :e o e ** Script Error: f has no value while this one works: do bind first second :e o == ok doesn't F stay BINDed? | |
DocKimbel 28-Aug-2012 [903] | In your first try (bind 'e self), you're binding only this 'e word, not the :e function body, so if you replace it with: bind second :e self, it will work. In second try, you're never binding 'e function body, you've just binded a new instance of 'f word that you have created using FIRST. That's why it works when you add DO, you're evaluating that new 'f instance which has the correct binding. Just remove FIRST, it will bind 'e body block and you'll get the result you've expected. >> e: func [] [f] >> o: context [f: does [print "ok"]] >> bind second :e o == [f] >> e ok |
Endo 28-Aug-2012 [904] | Got it, thanks a lot. I didn't know that FIRST gives me a "new" word, I thought that I'm BINDing *the* word itself and it should stay BINDed. This confused me a bit: >> o: context [a: 1 b: 2 c: 3] >> foreach x bind [a b c] o [probe get x] ;this works, BINDs block to O >> foreach x [a b c] [probe get bind x o] ;this works too, BINDs the word 'X to O |
DocKimbel 28-Aug-2012 [905x2] | No, it doesn't bind 'x, it binds x, which is evaluated to 'a, 'b or 'c. |
If you write in the loop: bind 'x o, it will fail, because 'x is not defined in o. | |
Endo 28-Aug-2012 [907x2] | I see, thank you. And in the first line, it doesn't BIND *the block* to O, it BINDs the block of words (which are 'a, 'b and 'c) to O. It's clear now. Thanks! |
Another interesting problem I have: I have a script as follow: REBOL [] probe system/options/args halt I encap this script, no problem, it works as expected, console opens and "none" appears: none ** Press enter to quit... If I run it with some params like "test.exe --test" ["--test"] ** Press enter to quit... But if I run it with some parameters, like -c, --sec, it prints nothing? (-c and --sec seems to be special for rebol.exe but it works with -s which is special too) ** Press enter to quit... Why and how PROBE doesn't produce an output? | |
DocKimbel 28-Aug-2012 [909] | Try with system/script/args instead. |
Endo 28-Aug-2012 [910x4] | Let me simplify: REBOL [] print "ok" print system/script/args ask "test" When I encap this script and run with a parameter like "-cxx" it doesn't print ANYTHING. no "ok" no "test" nothing. BUT when I WRITE system/script/args to a file it looks it is there. REBOL [] print "ok" write %test.txt system/script/args ;there is "-cxx" in test.txt file. |
yes I tried both "options" and "script", same result. | |
It's very weird, so we don't have a chance to use a parameter starting with -c (and many other) in our encapped executables. | |
More simplified, encap following script, run it with -c, -w or --sec, it prints nothing. Run it with -i, -t, -? it prints "ok". REBOL [] print "ok" halt | |
DocKimbel 28-Aug-2012 [914] | Might be a bug where encapped REBOL tries to consume its own command-line options (while it shouldn't). |
Endo 28-Aug-2012 [915x2] | It looks like. I thought that it confusing with REBOL's own command-line parameters but it happens only for some of them not for all. So no chance to use *some* parameters. |
Aha PRINT and PROBE doesn't work in encapped executable if command-line parameter includes a "c" character. | |
DocKimbel 28-Aug-2012 [917] | Any "c" character? I guess then that I was very lucky with Cheyenne: http://cheyenne-server.org/wiki/Main/Command :-) |
Endo 28-Aug-2012 [918] | Definitely!! But we should keep that in mind. |
older newer | first last |