bug?
[1/4] from: hallvard:ystad:helpinhand at: 20-Sep-2001 13:26
How is this possible:
>> source dummy
dummy: func [][
return-value: "1"
append return-value "1"
return-value
]
>> print dummy
11
>> print dummy
111
>> print dummy
1111
>> print dummy
11111
>> print dummy
111111
>>
Why doesn't dummy yield "11" all the time?
~H
[2/4] from: koopmans:itr:ing:nl at: 20-Sep-2001 13:48
OK, I'll try....
You create a value and a word in the function context.
You append "1" to the value. The function context lives as long as the
function is defined, not as long as the invocation lasts. So the next time
you call dummy, you append "1" to the value.
If you understand pointers in C, think of return-value as a pointer and
1
of the value the pointer points to. You change the latter every
invocation for the (changed) value "1". If you change "1" to copy "1" it will
work as you expect, because you allocate new memory (a new value).
Redeclaring return-value does not create a new pointer to a new value, as
that pointer already existed in this context.
The trick is that a string value is unique in the value domain, thus if you
use a value, and change it, you actually redefine the value. Changing the
value of a value in a context or so ;-)
Although the above explanation is not 100% correct, the C analogy helps me
most of the time. (and Rebil is written in ANSI C ).
HTH,
Maarten
[3/4] from: joel::neely::fedex::com at: 20-Sep-2001 2:07
Hi, Hallvard,
You've stumbled upon the Great Literal Misconception, which
most serious programmers encounter in their REBOL career! ;-)
The key is that literal values don't behave as you think
they do, if you're used to using them in other languages.
Hallvard Ystad wrote:
> How is this possible:
> >> source dummy
<<quoted lines omitted: 15>>
> >>
> Why doesn't dummy yield "11" all the time?
Taking a simpler case (to focus on the "literal" issue
apart from the behavior of functions), we have
>> foo: [val: "1" append val "1" val]
== [val: "1" append val "1" val]
>> foo
== [val: "1" append val "1" val]
>> do foo
== "11"
The result is as expected, but now look at FOO ...
>> foo
== [val: "11" append val "1" val]
... which keeps on happening.
>> do foo
== "111"
>> foo
== [val: "111" append val "1" val]
Here's a clue, if you're the type who wants to figure out
things by yourself.
>> foreach item foo [print [(type? :item) "^-" (:item)]]
set-word val
string 111
word append
word val
string 1
word val
Here's the key: in most programming languages, the appearance
of a statement corresponding to
val: "1"
means that a new string containing "1" is created and the
variable (in other languages, remember) is set to refer to
that new string. In REBOL, this behavior requires that you
explicitly say
val: copy "1"
So what's happening without the COPY? Everytime that FOO is
DOne, the word VAL is set to refer to the STRING! value at
FOO/2 (not a copy, but that string itself!). Since APPEND
modifies the value of its argument, the second element of FOO
is modified by each evaluation of FOO.
Remember that REBOL does not distinguish between blocks that
contain data
and blocks that "contain code" because all
REBOL blocks really just contain values! (Some of which do
interesting things when the block is DOne or REDUCEd ...)
Therefore the content of a REBOL block is capable of being
modified during evaluation. The fact that the second element
of FOO was *initialized* by a literal in the original source
text is no longer relevant.
>> foo: reduce [
to-set-word "val" to-string 3 - 2
to-word "append" to-word "val" to-string #"0" + 1
to-word "val"]
== [val: "1" append val "1" val]
>> do foo
== "11"
>> foo
== [val: "11" append val "1" val]
Another way to see a similar modifying effect is to consider
the use of two blocks, as follows:
>> tweedledee: ["1"]
== ["1"]
>> tweedledum: [val: tweedledee/1 append val "1" val]
== [val: tweedledee/1 append val "1" val]
>> do tweedledum
== "11"
>> tweedledee
== ["11"]
>> tweedledum
== [val: tweedledee/1 append val "1" val]
Notice that the value to which VAL is set (in this case, the
first and only value in TWEEDLEDEE) is modified by evaluating
TWEEDLEDUM, even though it was initialized from a quoted string
in the source text. This behavior (modifying the referenced
string value) is consistent, regardless of where the string
happens to be located or how it was initialized.
HTH!
-jn-
--
------------------------------------------------------------
Programming languages: compact, powerful, simple ...
Pick any two!
joel'dot'neely'at'fedex'dot'com
[4/4] from: greggirwin:starband at: 20-Sep-2001 6:45
Hi Hallvard,
<<
dummy: func [][
return-value: "1"
append return-value "1"
return-value
]
>>
dummy: func [][
return-value: copy "1"
append return-value "1"
return-value
]
I don't know if this is better than using something like clear "", or
make string! 0, to initialize it, but maybe an expert will let us know
if they have a better way.
--Gregg
Notes
- Quoted lines have been omitted from some messages.
View the message alone to see the lines that have been omitted