Hi Eric,
you have a problem with the fact that REBOL's visual representation of
values in the REBOL console is ambiguous. I had a long exchange about that
with Ladislav. We were able to sort out things at the time.
In the message you comment on, I am NOT talking about how REBOL displays a
literal string in the console. I am talking about how REBOL EVALUATES
literal strings (and other series values).
If you're curious, here are some more detailed replies.
you wrote:
>Hi Elan,
>
>I've read your 1400+ line refutation of Joel's explanation of a function. I
>agree with much of what you say, but there is one point I don't think is
>quite right:
>
>>2.3 Conclusion:
>>2.3.1 An empty literal string does not reference "the empty string" because
>>a string! value does not have the capability to reference something. That
>>capability is reserved for values of type word!
>
>(I think Joel may have used the phrase "the empty string" as a concept rather
>than meaning "the unique empty string in the example".)
No point in guessing what someone may have said.
>
>You "prove" this with the following demonstration:
>
>>2.2 Each of the two literal strings is an independent entity. Since you
>>speak of "the empty string" and you say " as is the fifth element", your
>>formulation suggests that the two literal strings are identical, since they
>>are both references to "the empty string". If they are identical, the
>>function same? should return true. However, same? returns false:
>>
>>>> same? "" ""
>>== false
>
>In the case of the "the two literal strings" in the function F being
>described it's true, and it's true with your illustration
>
>>>> same? "" ""
>>== false
>
>In this latter illustration both literal strings are independent entities,
>because REBOL creates both of them when it parses the string {same? "" ""}
>typed in at the console. That still is no guarantee that all "literal
>strings" are mutually independent entities.
They are.
>
>What about this case:
>
>>> a: [""]
>== [""]
>>> insert a first a
>== [""]
>>> a
>== ["" ""]
>>> same? first a second a
>== true
>
>The block referenced by (bound to) 'a now contains two string values, both of
>which reference the same empty string.
Your example reflects an ambiguity in the way REBOL visually represents
data in the REBOL shell or console. I will refer to the visual
representation of values in the console as the "display of values". REBOL's
display of values does not comprehensively reflect how REBOL evaluates values.
I considered the simple case of identical strings in a way that avoids the
ambiguity of REBOL's display of values.
>> a: ""
>> b: :a
>> same? a b
== true
You may have noticed that the same DISPLAY ambiguity resulted in a rather
long thread with Ladislav about functions. The notation used to display the
RESULT OF evaluating the word func [] [] is identical to the code entered
when you instruct REBOL to BEGIN EVALUATING func [][]. Yet quite a few
things change DURING the evaluation of the word func. The display of
evaluated expressions (strings, functions) in some instance does not report
all the relevant information about the values being displayed. In the case
of the function there is no notation that reminds you that the EVALUATED
function func is being displayed. In the case of the literal string there
is no notation to indicate whether strings are identical or not.
Ladislav had a problem distinguishing between (simplified) these two blocks:
[func [] []]
[func [] []]
The first block contains the word func and two empty blocks. The second
block contains a function:
>> [func [][]]
== [func [] []]
>> reduce [func [][]]
== [func [][]]
Here we end up with what looks the same.
>> first [func [][]]
== func
>> first reduce [func [][]]
Why didn't first reduce [func [][]] return anything visible at all?
>> type? first [func [][]]
== word!
>> type? first reduce [func [][]]
== function!
Aha, because the reduced block contains a function, even though it looks
the same as the first block in the REBOL display. REBOL's visual
representation of values in the console is incomplete. Here, we can't tell
the difference between a function and the (unevaluated) word func followed
by two blocks [][].
The reason we can't tell the difference is because REBOL uses the exact
same notation to display a function that we use to instruct REBOL to create
a function. When we instruct REBOL to create a function, we can protect
these instructions from being immediately evaluated, by inserting them in a
block. A function can also be inserted in a block. Our instructions to
create a function are not the same thing as a function that has already
been created. A block containing our instructions and a block containing a
created function, however, do look the same.
In your example we were not able to tell whether the strings were identical
by looking at the REBOL display. A literal string is not its visual
representation in the REBOL console. A literal string is a string datatype
that is directly expressed in the language (see REBOL User's Guide version
2.1.1 Chapter 1).
My comments were not directed at how REBOL DISPLAYS values. My comments
were directed at how REBOL EVALUATES them.
>
>This is one of the major points that Joel was trying to make
I don't know that that is the case, since I haven't read Joel's essay yet
(too much work.) But if this is one Joel's major points as you claim, then
Joel has fallen victim to REBOL's ambiguous display of values. It doesn't
require a new conceptual theory of REBOL to patch up the discrepancies
between REBOL's display of values and REBOL's evaluation semantics. The
display is a convenience, the evaluation semantics can be investigated only
be intercepting them at the time an evaluation is ongoing.
You can never trust that you see something. You have to make sure that what
you are seeing is what you think it is, by accessing it programmatically
and investigating whether it acts as you expect it to.
>in his series
>essay, and one that deserves careful attention. Even series values that look
>literal
Again, ambiguity of display. A literal string is the not the visual
representation of a literal string. A literal string is a term.
>(that are not directly bound to a word) have a relationship of
>reference to the underlying data which they represent.
>
Series values do not REPRESENT. Series values do not represent some
UNDERLYING data. Series values do not have a relationship of a REFERENCE TO
the underlying data. I haven't read Joel's essay on series and therefore I
cannot comment on what he says. I can comment only on what you are saying
here.
See my point 2 in my previous email. I've copied it here for your convenience:
>>>>>>>>>>>>>>>>>>>>>> Beginning of quote
[snipped]
Reference in REBOL has a specific meaning. It describes a process that
occurs when a set-word! type value is evaluated. Either the evaluation
succeeds, in which case the value that was set-worded becomes a word, i.e.
it now owns a valid reference to another value. Or the evaluation fails, in
which case the value does not acquire a reference to a value:
>> a: 1
== 1
>> a
== 1
>> type? "a"
== string!
>> "a": 1
** Syntax Error: Invalid word-get -- :.
** Where: (line 1) "a": 1
A string cannot be a reference.
A string CAN act as an argument to the function make with the type
designator set-word!:
>> make set-word! "a"
== a:
Here the string is an argument only. By the time it has become a set-word!
it is no longer a string:
>> string? make set-word! "a"
== false
2.1 Only the word! family of values (word!, lit-word!, set-word!) can
reference something:
We construct abc as a set-word! and assign 'a as a reference to the
set-word! abc: WITHOUT providing a value for 'abc to reference:
>> a: make set-word! "abc"
== abc:
>> type? :a
== set-word!
When we evaluate 'a, REBOL attempts satisfy abc: as a set-word! value.
REBOL complains that abc has not been supplied a value to reference:
>> a
** Script Error: abc needs a value.
** Where: a
Now we follow the same steps to create 'a as a reference to a string, again
WITHOUT providing a value for the string to reference (as we did in the
case of the set-word! abc:):
>> a: make string! "abc"
== "abc"
>> type? :a
== string!
Now we evaluate 'a
>> a
== "abc"
REBOL does not complain that the string "abc"'s reference has not been
satisfied by a value. That is because a string is not a reference!
<<<<<<<<<<<<<<<<<<<<<<<< End of quote
>Even series values that look
>literal (that are not directly bound to a word) have a relationship of
>reference to the underlying data which they represent.
Let's look at this formulation step by step:
1. "series values that look literal"
Is looking some way a property of series values? Why refer to the looks of
series values? What series values do not look literal? You add an
explanation in parentheses:
2. "(that are not directly bound to a word)"
a) series values that are not bound to a word:
You assume we can distinguish series values based on whether they are or
are not bound to a word. Do you really believe that? Is being bound to a
word a property of a series values? If we take the following expression:
a: "abcd"
Has something - and if so what - about the literal string "abcd" changed
when the expression is evaluated? Now we evaluate
b: :a
Now the identical series "abcd" is being referenced by 'a and 'b. Has the
series changed again?
No. What has changed has only to do with the word. The word 'a was bound to
the series "abcd". That certainly changed something about the word 'a. It
did not change anything about the series the word was bound to. The same
thing is true for the word 'b.
What does it mean that the word 'a or the word 'b was bound? It means
something terribly simple. All it means is that whenever REBOL looks up
whether the word is bound to a value, REBOL will find that the word is bound:
?>> value? 'b
== true
and whenever REBOL replaces the word by the value it is bound to, i.e.
whenever REBOL dereferences or resolves the word, it will retrieve the
series "abcd".
Binding is a wonderfully simple term. And the series is not bound to the
word. The word is bound to the series.
Since binding a word to a series does not modify the series, binding is not
a property of the series, it is a property of the word being bound, you
cannot use the word binding as a word to distinguish one series from another.
You may object that to speak of a "bound value" is in common usage when we
look at the garbage collection. Aren't "bound values" exempt from being
disposed of by the garbage collector? Yes, we do say that. But here we are
speaking loosely, not terminologically correct. It is an abbreviated
formulation for the fact that the garbage collector respects a word's
association with a value by exempting the value from being removed. WHETHER
a value exists is affected by whether words are bound to it, HOW a value
exists, once it does, is not affected by whether words are bound to it.
Whenever series values DO exist, you cannot distinguish one series from
another based on whether or not a word is bound to it.
So, you want to talk about series values that look literal, namely (perhaps
"for instance") series values that are not bound to a word. If I am
supposed to understand which series values we are talking about, by
ignoring series values that "are bound to a word", then I'm supposed to
distinguish series values from series values, the only difference being
that some are bound to a word and others aren't. Since the only time a
series is affected by being referenced by a word is when the series is
garbage collected, being referenced by a word prevents garbage collection,
and I am to think of strings that differ from strings that are referenced
by words, i.e. are exempt from garbage collection, I conclude I am to think
of strings that are garbage collected. I'm pretty sure that is not what you
mean ;-)
>Even series values that look
>literal (that are not directly bound to a word) have a relationship of
>reference to the underlying data which they represent.
b) "... even series values that look literal ..."
I commented on the ambiguity of REBOL's visual representation or display of
values. What things look like is not a good basis for figuring out in
detail what they will behave like. Some details are well represented by
REBOL's display. Other properties of values are not well, or not at all
represented by REBOL's display. So, what things look like doesn't mean very
much. I take it that you simply mean "literal series values", but for some
reason you are trying to avoid saying that. I'm not quite sure why.
>Even series values that look
>literal (that are not directly bound to a word) have a relationship of
>reference to the underlying data which they represent.
I simplify (abstract by ignoring details I have refuted ("bound to a word
is meaningless") or which I think are non-essential and misleading ("look
like")):
"Literal series values have a relationship of reference to the underlying
data which they represent."
3. You introduce a term, underlying data. I don't know what you mean by
"underlying data". Is your term "underlying data" in significant ways
different from saying that a series is "an ordered collection of elements"
(= underlying data) that has a position index into those elements?
Since a series is an ordered collection of elements, it does not have a
RELATIONSHIP OF REFERENCE to the ordered collection of elements. Otherwise
you would be stating that a series has a relationship of reference to
itself. Now, you can construct a series that references itself:
self-referencing-series: [1 2 3 :self-referencing-series]
but, since we discovered during the version 2.0 beta (or was it after 2.0
was released) that when self referencing series are recursively resolved
they instantly crash REBOL, the self reference is not recursively resolved
by REBOL:
>> reduce self-referencing-series
== [1 2 3 [1 2 3 :self-referencing-series]]
While you can construct a series the references itself, series by default
are not self-referencing constructs.
I can do without assuming that series "have a reference to" some
"underlying data".
Perhaps you are struggling with the fact that all references share the
series' data, whereas each reference may have a different position index?
You are trying to formulate that conceptually?
That is simply done, provided you use REBOL terms:
In REBOL a series is an ordered collection of elements with a position
index that is bound in the context, in which the series is evaluated.
For instance, if a series is evaluated in the context of a function, within
the context of the function the position index is bound to a value. If a
series is being referenced by a word, then the position index of the series
is bound to a value within the context of that word. In other words, a word
extends the context of the binding of a position index indefinitely, i.e.
as long as the word references that binding.
Since the current position index of a series is a property of a series, a
series whose current position index is bound to an integer value is
different from a series whose current position index is bound to a
different integer value ... with respect to the values of the current index
position.
That's all.
>
>Another point where I think you go slightly wrong is further down:
>
>>>
>>>The subtle point over which so many of us have tripped (judging by
>>>the discussions on the mailing list) is that the the adjacent
>>>quotation marks in the text entered to define 'trick serve simply
>>>as the INITIAL VALUE of the second element of 'trick, and that
>>>subsequent modifications (via any reference) to that second element
>>>will persist as long as 'trick does. That is the only point where
>>>the concept of "global" appears, as far as I can tell. Values are
>>>not subject to garbage collection as long as there is any reference
>>>(or chain of references) to them from the global context. "Local"
>>>doesn't enter into it at all.
>>
>>Wrong.
>>
>>>> false-abstraction-2: [append "" "X" ]
>>== [append "" "X"]
>>>> do false-abstraction-2
>>== "X"
>>>> do false-abstraction-2
>>== "XX"
>>>> do false-abstraction-2
>>== "XXX"
>>>> do false-abstraction-2
>>== "XXXX"
>>>> do false-abstraction-2
>>== "XXXXX"
>>>> false-abstraction-2
>>== [append "XXXXX" "X"]
>>
>>Here the literal string in false-abstraction-2 was modified, even though it
>>wasn't being referenced by anything global.
>
>It's true that much of what Joel said about contexts being destroyed and
>local values being thereafter subject to garbage collection was mistaken.
>(BTW, I've noticed that in 2.2 the behavior of local values assigned to words
>local to a function is more predictable now.)
>
>Still, I think that the important point Joel makes here is basically right.
>Notice he said a "chain of references". For example, in your example the ""
>in:
>
>>> false-abstraction-2: [append "" "X" ]
>
>does serve "as the initial value" of the second element of the block
>referenced by 'false-abstraction-2. That's because REBOL created a string
>based on its parsing of the characters "" in the string
>{false-abstraction-2: [append "" "X" ]} , which was typed in at the console.
It's irrelevant that
"REBOL created a string
based on its parsing of the characters """
Since when do we discuss programming languages in terms of "entering
something at the console"? We discuss programming languages in terms what
the tokens mean within the context of the programming language. The process
by which REBOL transforms character sequences into tokens has no bearing on
the meaning of tokens when REBOL evaluates them. You are confusing yourself
(see below...)
>Thereafter the second element of the block serves as a reference to the data
>underlying that value.
There is no data underlying the value. The value is the data (see my replay
of 2.x).
>The value persists, and the data to which it refers
>persists (in the sense that the garbage collector doesn't gobble it up),
you haven't explained anything: Since the value is the data you are saying
that the value persists, and the value persists. There is nothing to explain.
>because it's contained in a block referred to by a word. That is indeed a
>"chain of references".
The block is referenced by a word. The literal string is not referenced by
a word. Why does the literal string persist when the literal string is not
being referenced by a word? What has happened to the chain of references here?
>
>I don't even think it's quite right to call the second element of the block
>referenced by 'false-abstraction-2 a literal string.
Review the User's Guide.
>I think you could say it
>was initialized from a literal string, but as it exists within the block
>itself, it is a string value, no different in quality from one directly
>referenced by a word.
If you happened to have read the beginning this reply to you, you will
notice that I spend some time insisting that there is no difference between
a literal string and a literal string being referenced by a word.
>
>
>In conclusion, here's a puzzle, easily solved: how did I make this function?
>
>>> source f
>f: func [x /local a b][a: "" b: copy "" append a x print b]
>>> f "I'm a geek"
>
>>> f ", not!"
>I'm a geek
>>> f " OK?"
>I'm a geek, not!
>
A puzzle? :-) What's the question? Well, this is what REBOL says:
>> f: func [x /local a b][a: "" b: copy "" append a x print b]
>> f "I'm a geek"
>> f ", not!"
>> f " OK?"
Perhaps you entered the missing lines manually in the editor of your email
client?
>See you,
you bet.
>Eric
>
Elan