World: r3wp
[Core] Discuss core issues
older newer | first last |
Geomol 11-Aug-2011 [2020] | Same behaviour in R2 and R3 btw. |
Dockimbel 11-Aug-2011 [2021] | Nothing strange there. The local context indefinite extent is sometimes handy when deferred evaluation is required, but dangerous if side-effects are not controlled strictly. For example, it's handy for creating generators: >> count: use [c][c: 0 does [c: c + 1]] >> count == 1 >> count == 2 >> count == 3 >> count == 4 >> count == 5 >> probe :count func [][c: c + 1] |
Cyphre 11-Aug-2011 [2022x2] | the binding of words in a block is done, when the words are put into the block I don't think this is true. See: x: 10 blk: [] o: context [x: 20] insert blk 'x insert blk in o 'x reduce blk == [20 10] |
So your examples works properly logical. In the first case (F and G usage) the 'v words are bound to particular functions (either F or G). In the case of second F all 'v words are bound only to the F fucntion. | |
Ladislav 11-Aug-2011 [2024x2] | the binding of words in a block is done, when the words are put into the block - that certainly is false |
The first V, which has the value 1, was put in the block, and it's still there somewhere in the system, but we get the V value from the latest F. - this is again false, you should read the bindology article, where the behaviour is analyzed, modelled and explained | |
Geomol 12-Aug-2011 [2026x7] | I guess, I was misunderstood. :/ |
Cyphre, in your example, when you insert the first x in the block, it's the x holding the value 10. To me, the x in the block is bound to the outher x at the time, you insert it into the block. The next x, you insert in the block, is the x from the context o. So at the time, you insert it into the block, that x in the block is bound to the x in o. So the block holds two different x, and they're bound at the time of insertion. That's what I meant, when I said "the binding of words in a block is done, when the words are put into the block". (Words can be rebound at a later time using e.g. BIND, but I'm not looking at that in these examples.) I don't have time and energy to argue with Ladislav right now. :) | |
outher x = outer x (The x holding the value 10.) | |
Ladislav, I took a quick review of your "Bindology". What I mean correspond well with what you write in: http://www.rebol.net/wiki/Bindology#Scope The bug illustrated at the end of http://www.rebol.net/wiki/Bindology#MAKE_OBJECT.21 is interesting! :) | |
That bug is really weird! I put in some prints to show, what's going on: f: func [x] [ get in make object! [ a: "ok" if x = 1 [ a: "bug!" print ["f 2 :" f 2] a: "ok" ] print ["a:" a "x:" x] ] 'a ] When I run it, I get: >> f 1 a: ok x: 2 f 2 : ok a: ok x: 1 == "bug!" I can't get my head around, what's going on internally. | |
It's same result in R3. | |
Doc, I think, you miss my point about recursion. See: >> f: func [v][if v = 4 [exit] print v f v + 1 print v] >> f 1 1 2 3 3 2 1 There are several versions of V, one for each call to F. In my original examples, I put the first version of V in the block, but I see the latest version. | |
Dockimbel 12-Aug-2011 [2033x2] | You're right, I missed your point about recursion. As I understand it, the behavior you're observing is caused by function context values being pushed on stack on recursive calls, as showed by Ladislav's simulation (http://www.rebol.net/wiki/Bindology#Model_of_function_evaluation ). So the value of 'v word bound to 'f context, inserted in a block and evaluated later, depends on the "current" level of 'f function recursion. |
as showed => "as shown" | |
Geomol 12-Aug-2011 [2035] | Yes, you got it. Thanks! I'm not saying, this is a bug, I'm just wondering about the behaviour. It might actaully be seen as a benefit, as this gives us 2 different behaviours depending on, if we use recursive calls or call another function (which can then be recursive), like the G function in my original examples. |
Dockimbel 12-Aug-2011 [2036] | It looks like a side-efffect of the implementation, I do not think that this behavior was planned as a feature. I guess some recursive algorithms could benefit from it, but I fear it can quickly lead to code that is hard to maintain. |
Geomol 12-Aug-2011 [2037x2] | Yeah, that's also my concern. |
Are there other high level languages (or maybe interpreted languages), that can put references to variables into tables? I took a look at Python and Lua, but I don't think, they can. | |
Dockimbel 12-Aug-2011 [2039] | I don't remember seeing such property in another language. What about io or self? |
Ladislav 12-Aug-2011 [2040x4] | I can't get my head around, what's going on internally. - I do not know if you already got your head around or not, but the behaviour is exaplained by the simulation. |
Anyway, the explanation is as follows: since the function F is called twice, it creates two objects having the attribute A. While the first object has got the attribute A set to "ok" initially, it ends up having the attribute A set to the "bug!" string before the F is called for the second time. After the second call to the function F occurs, the function does not "see" the first object's A attribute when setting the A using the a: "ok" expression. | |
Regarding "There are several versions of V, one for each call to F" - the fact is, that there is only one version of the word 'V, not "several". If you wanted to have "several versions of V" you could have used a closure, as is demonstrated later. | |
http://www.rebol.net/wiki/Bindology#Computed_binding_functions_.28Closures.29 | |
Geomol 12-Aug-2011 [2044] | About the bug thing. When returning to the first object, A is set again to "OK" in the line just after the call to F: f 2 a: "OK" ] ... That should be the A in the first object, shouldn't it? So I can't figure out the internals giving the result, we see. |
Ladislav 12-Aug-2011 [2045] | That should be the A in the first object, shouldn't it? - it certainly is not the first object, that is why you see the "bug!" |
Geomol 12-Aug-2011 [2046] | To me, it's like if the following code would return "bug": >> o: context [a: "bug" a: "ok"] >> get in o 'a == "ok" |
Ladislav 12-Aug-2011 [2047] | The fact is, that in the article, there is a simulation fully explaining what is going on. And, moreover, the MAKE OBJECT! [...] binds the [...] block, which is a modification, that does not get "reversed". And, moreover, there is a code that shows how to "cure" it. |
Geomol 12-Aug-2011 [2048] | Anyway, such deep bug in REBOL is worrying. |
Ladislav 12-Aug-2011 [2049x2] | such deep bug in REBOL is not a bug in REBOL at all |
it is just a bug in the example code | |
Geomol 12-Aug-2011 [2051] | wow |
Ladislav 12-Aug-2011 [2052] | There is the code that shows how it should have been written |
Geomol 12-Aug-2011 [2053] | If this is not a bug in REBOL, then there is a bigger problem, as I see it. The language is way too complicated. |
Ladislav 12-Aug-2011 [2054x3] | Actually, it is not. The only thing you should know is, that the MAKE OBJECT! [...] expression modifies the [...] block. If you want to use the block as code (in a recursive, or otherwise repetitive manner), you need to realize that. |
And, there is an easy remedy, the expression: MAKE OBJECT! copy/deep [...] does not modify the [...], so it is OK | |
if you want the things to become simple, you can just define a new non-modifying function and you are safe. | |
Geomol 12-Aug-2011 [2057] | Nah, better start over and make a new language, that is simple in the first place. |
Ladislav 12-Aug-2011 [2058x4] | That does not make sense in this case, when what you need is just a function like: safe-object: func [blk [block!]] [make object! copy/deep blk] and you are done |
So, this is not about the language, this is just about a different function to use. | |
It is obvious, that using the SAFE-OBJECT function you are safe, plain and simple. | |
But, of course, it looks easier (at the first sight) to push somebody to define a new language for you. I can guarantee you, that no matter how hard you push, there will always be something you find "complicated". | |
Gabriele 13-Aug-2011 [2062] | Geomol... what is your definition of simple? Python? REBOL's model is very simple, if you understand it. :-) |
Geomol 14-Aug-2011 [2063] | Gabriele, I guess, you're joking, but to answer your question: it would be simple, if the above function returning "bug!" would instead return "ok" like this function: g: does [ get in make object! [ a: "ok" a: "bug!" get in make object! [ a: "ok" ] 'a a: "ok" ] 'a ] >> g == "ok" |
Gabriele 14-Aug-2011 [2064x2] | It would be simple because it fits your model better? Or because the model to describe that behavior would be simpler? I'm asking because the latter is certainly false, especially if you want to preserve things like dialecting. |
In REBOL, literal blocks are just literal blocks. If you modify them... they are modified. Binding a block modifies the words inside the block, ie. it modifies the block. It can't get any simpler than this. Now, you may argue that MAKE OBJECT! should bind/copy the block instead; the reason it does not is purely performance (as 99.99% of the time the copy is not necessary). In that 0.01% of cases where you need it... you just write MAKE OBJECT! COPY/DEEP [...] instead. | |
Geomol 14-Aug-2011 [2066] | Our understanding of "simple" is different, or I would go as far as saying, your understanding of "simple" is twisted. It would be simple because it fits your model better? Or because the model to describe that behavior would be simpler? I'm asking because the latter is certainly false, especially if you want to preserve things like dialecting. I would say, the model giving my suggested behaviour is simpler. If you disagree, then look at the code again. 'a' is set to "ok" again, after the recursive call. A model giving some other result is not simple. If you think, it is, then describe that model in a simple way! A simple model should also be simple to describe, right? |
Ladislav 14-Aug-2011 [2067x3] | Geomol, the behaviour of self modifying code is never simple to understand, that is where Gabriele and I can agree with you. In contrast to that, what both Gabriele and I call simple is the suggestion to use the SAFE-OBJECT [...] (or MAKE OBJECT! COPY/DEEP [...]) non-modifying expression, which, indeed, exhibits the simple behaviour. |
On the other hand, the behaviour of self-modifying code is not as terribly complicated as you are trying to suggest, since: * Taking into account the modifying properties of the MAKE OBJECT! [...] expression I wanted to write a relatively simple example to show what bug you may run into when ignoring the modifications. * I succeeded immediately without actually running into such a case in practice, i.e. I did not have to hit my head to the wall first to run into this. * It sufficed to think of a case when the modification would twist the block behaviour relatively to what you might find simple. * Since I did it without actually running into it, I am fully entitled to saying, that the behaviour is actually transparent to me. | |
(and, I guess, the same applies to Gabriele as well) | |
older newer | first last |