Home   Archive   Permalink



copy

After puzzling this a while, I've decided to volunteer for pinata duty. Nick will recognize a couple of paraphrased examples of his.
    
unexpected: [
     varName: "-"
     append varName "*"
     print varName
]
do unexpected
do unexpected
do unexpected
print ""
expected: [
     varName: copy "-"
     append varName "*"
     print varName
]
do expected
do expected
do expected
    
After working over Nick's original code a while, I came to believe the actual reason for unexpected: is because it is trying to re-initialize a variable WITHIN A LIST. To me, it seems quite reasonable to expect some data safety within a list, so the result of unexpected: seems "expected" to me.    
It follows that using copy in expected: in some way still unknown to this semi-noob, allows the re-initialization.    
    
It's just that I'm not one to do something just because someone says so, and Nick's blanket advice in Section 5.4 of his Cross Platform App Development ... tutorial says pretty much that. I include a modified copy of one of his examples of same.
    
low-receipts: []     ; Create blank list with copy [], NOT [] ; oh, really?
receipts: [$5.23 $95.98 $7.46 $34]
foreach receipt receipts [
     if receipt < $10 [append low-receipts receipt]     ; add to blank list
]
print low-receipts
    
Ok, thrash away. I'm a big boy. I can take it.

posted by:   yoffset       24-Mar-2014/18:16:26-7:00



unexpected: func [] [
     low-receipts: []
     receipts: [$5.23 $95.98 $7.46 $34]
     foreach receipt receipts [
         if receipt < $10 [append low-receipts receipt]
     ]
     print low-receipts
]
unexpected
unexpected
unexpected
    
expected: func [] [
     low-receipts: copy []
     receipts: [$5.23 $95.98 $7.46 $34]
     foreach receipt receipts [
         if receipt < $10 [append low-receipts receipt]
     ]
     print low-receipts
]
expected
expected
expected

posted by:   Nick       24-Mar-2014/22:31:10-7:00



Just do it :) (tI'll save you headaches during moments when you're not so careful, doing silly things like using global variables, etc.)

posted by:   Nitck       24-Mar-2014/22:33:08-7:00



It's a technical point, to be sure. Since you don't refute my theory, I'll assume it has a measure of "truthyness". An enormous amount of Rebol code is nested series, so re-initializing could happen a lot.    
    
Using r3-gui.r3 as an example, every new chunk of material is preceded by the Context function. Although documentation of context is sketchy, it appears to add a measure of constant-like and locality to the material, a good thing with global, dynamic variables and no constant datatype.
    
Your tutorial is for new programmers, and "Just do it :)" is good advice.

posted by:   yoffset       25-Mar-2014/1:23:56-7:00



I probably derived my example from http://www.rebol.com/docs/core23/rebolcore-6.html#section-5.3 It explains there that although the variable word is local, the actual value of the string is global.
    
A basic point made at http://www.rebol.com/r3/docs/functions/copy.html is that "To save memory, all strings, blocks, and other series are accessed by reference (e.g. as pointers.) If you need to modify a series, and you do not want it to change in other locations, you must use copy first."
    
So this makes sense:
    
x: "asdf"
y: x
z: copy x
    
append y "q"
    
probe x
probe y
probe z
    
The problem usually shows up when you're using some series re-assigned from another reference that you're not aware of at the moment, perhaps hidden in some imported code which you've written previously, or in code that someone else wrote. For example, put the definitions of 'x, 'y, and 'z in some imported code and perform the append operation, without inspecting the definition of 'y, and you'll run into the unexpected change in the 'x value. You'd be surprised how often that can bite you during moments of less then perfect diligence. Here's an example you'll probably run into:
    
view layout [
     t: text-list
     f: field [append t/data f/text show t]
]
    
In this case, do this:
    
view layout [
     t: text-list
     f: field [append t/data copy f/text show t]
]
    
So in cases where using 'copy doesn't affect the performance of code significantly, I tend to use 'copy on string and block literals values, just to be sure that I'm dealing with a unique value, and not a reference which may affect some other value.

posted by:   Nick       25-Mar-2014/8:21:56-7:00



Thanks for that. I hadn't read that far yet.
http://www.rebol.com/r3/docs/functions/copy.html
I knew there had to be pointer utilization somewhere.

posted by:   yoffset       25-Mar-2014/12:47:57-7:00



http://www.rebol.com/r3/docs/concepts/series-copy.html
- at the bottom explains it clearly.
Thanks Nick

posted by:   yoffset       25-Mar-2014/18:28:25-7:00