Hi -jn-

At 11:32 AM 12/15/99 -0600, you wrote:
>BORING PREFACE:
>
>Perhaps I should clarify my purpose.  My 25+ year career in computing
>(including 12 years teaching math and computing science) has routinely

[snip]

With all due respect ... ;-)

>ACTUAL REPLY:
>
>[EMAIL PROTECTED] wrote:
>> ...
>> I think the built-in help is usually pretty clear on this issue:
>> 
>> >> ? next
>> Returns the series at its next position.
>> [...]
>> >> ? insert
>> Inserts a value into a series and returns the series after the insert.
>> [...]
>> 
>> There's nothing in the description of NEXT to make you think it
>> modifies the series, and the description of INSERT makes it clear
>> that the series will be modified... So I don't think it's quite
>> fair to say that series operators are all lumped together.
>> 
>
>Actually, your example illustrates exactly the point I was trying to
>make.  Both are described as doing something with "the series", but
>sometimes "the series" refers to a particular VIEW of the data, while
>other times "the series" refers to the underlying data itself.  The
>phrase "at its next position" implies that position is an attribute of
>the series itself.  

My problem with what you are doing here is not so much where you are
heading. It is the reason you give for heading there. You see, you
formulate two different things, 

1. inserting a value into a series and 
2. returning a series at its next position 

as one anonymous action, namely "doing something":

"Both are described as doing something with "the series", ...

You combine "return at its next position" and "insert into the series" into
one word "something" in "doing something with 'the series'". 

You then confront us with the idea that, whilst we are "doing something"
twice, we get two different results. Problem. 

Having abstracted from what we were specifically doing, namely 
1. returning the series at the next position vs. 
2. inserting a value in a series, 
we are no longer able to explain the different results as resulting from
two differen activities, therefore we need to invent new nouns that allow
us to explain the differences as resulting from one act ("doing something")
performed on two different objects, "VIEWS" and "underlying data". The
difference is now re-introduced as a difference not in what we are doing,
but in who we are doing it to.

Therefore my feeling is that the problem you formulate in order to propose
a solution is one you just happily constructed. 

Ok. So what. Perhaps the solution you propose is useful, even if the
problem is a construct?

You account for the difference by proposing that "series" refers to two
different things, "sometimes" referring to "a particular VIEW of the data,
while other times" referring "to the underlying data itself."

Is "the series" really referring two different things in the text you
quote? May we take a closer look? 

At face value, what is different in the quotes is the "something" being
done "with the series". In the first case the unmodified series is returned
"at its next position". In the second case the series is modified before it
is "returned after the insert". Note that "after the insert" is intended to
mean "at the position immediately following the last inserted element."

Let's review the similarities:

Both 'next and 'insert RETURN "the series":
? next
"Returns the series ..."
? insert
"... returns the series ..."

Both of them return the series AT SOME POSITION. They differ with respect
to which position that is:
? next
"Returns the series AT ITS NEXT POSITION."
? insert
"... returns the series AFTER THE INSERT."

"How" the position of the returned series is determined is different. The
"what" being returned here is the same, namely "the series" at some position.

There is yet another difference regarding the two explanations. Whereas
'next does nothing other than return "the series" at its next position,
'insert first modifies the series, by adding elements to it: "Inserts a
value into a series ...".

Based on the above, we can say that  
1. A series IS a data storage into which we may insert data. 
2. A series HAS a current position at which the data storage is accessed
3. Both the data stored by the series as well as the series' current
position can be controlled by using REBOL functions. 
3. Modifying the current position does not modify the data. 
4. When the data is modified, the modifications always begin at the current
position of the series. (One could complain and refer to 'append, which
inserts stuff at the tail of a series, and not at its current position. But
I would refer to append's source, which uses tail to position the series
immediately behind its last element and then uses insert to insert a value
at that position. So, append itself modifies the current position of the
series in order to achieve its purpose. Therefore append proves this point
and doesn't contradict it.)
5. Modifying the data may modify the current position (insert, remove), but
does not have to (replace) and occassionally does (append). 
6. The current position of a series is local.
7. The data of a series is global. 

Points 6 and 7 deserve an illustration:
>> a: [insert next [1 2 3 4] 'abc]
== [insert next [1 2 3 4] 'abc]
>> reduce a
== [[2 3 4]]
>> a
== [insert next [1 abc 2 3 4] 'abc]

Two operations were performed in the block referenced by 'a when 'a was
reduced:

1. 'next was applied to the series' current position.
2. 'insert block 'abc was applied to the series at the position which
resulted from evaluating the expression next [1 2 3 4].
3. Because 'next was applied before 'insert, the literal word 'abc was
inserted in position 2 of the series.

What is being demonstrated here is that the current position is local
whereas the storage is global:

1. Since 'next affects the current position, the modifications caused by
'next are local and are consumed by 'insert. 

2. Since the modifications caused by 'insert affect the data, which is
global, they are persistent and permanent. 

3. Since 'insert affects the series, whose local current position value is
2, the content is modified at position 2, and therefore a reminder of the
local affect of 'next is preserved in the global data of the series,
reflected by the relative position of the new element 'abc in the series.

Therefore, when we inspect a's content after reduce, the block has been
modified to [1 abc 2 3 4] but not to [abc 2 3 4], which would be the case
if the serie's current position was global like the serie's data.

-jn-, when you say that:

>sometimes "the series" refers to a particular VIEW of the data, while
>other times "the series" refers to the underlying data itself.  

I don't see any harm in using the words VIEW and "underlying data",
provided we keep in mind that in using them we are making a hypothetical
distinction that only reflects some of the details of what is going on

The relationship between current position index and the data, are not well
represented. VIEW stands in a co-dependancy relationship to "the underlying
data". 

The VIEW is a view OF the underlying data, that's one dependancy. The
underlying data is accessed and modified at the position of the VIEW, that
is the co- of co-dependancy. When VIEW is the series at position 2 and the
underlying data is modifed, the modification to the underlying will data be
affected by the VIEW, since it will affect the underlying data at the
VIEW's position, namely 2. 

The choice of the terms VIEW and underlying data express the idea of the
VIEW's dependancy, depending on the underlying data, but the inverse
dependancy, that the underlying data is always modified at some VIEW's
position, is not reflected by this terminology quite as well.

Still, thinking in terms of "VIEW" and "underlying data" can be helpful.

On the other hand, I prefer to keep the vocabulary needed to describe REBOL
to a minimum. I also like to exploit the similarity of principles, to keep
the volume of information needed to reason about REBOL to a minimum. If we
just stick with the idea that the current position of a series is local,
whereas the data storage is global, we can consider a series to be
something similar to a function. The idea of global and local values,
persistent changes and temporary changes arises in the same manner, when we
discuss the behavior of functions:

For instance, we always warn newbies that each time the following function
is called, digits will be added to a string referenced by a local word,
unless make string! or copy "" are used to guarantee a fresh string each
time the function is evaluated:

>> f: func [/local a] [ a: "" for i 1 6 1 [insert tail a i] print a]
>> f
123456
>> f
123456123456
>> f
123456123456123456

The word 'a is local, but the string it references, like all literal
values, is global. I like the idea that you can think of a series as
somewhat analogus to a function. The data-storage is global, whereas
current position is local. Or you can picture a series as something liken a
use context:

series: use [current-position] [
  current-position: 1 
  data-storage: "data" 
  [current-position data-storage]
]

next-func: func [] [ 
  set series/1 ((get series/1) + 1) 
  return at get series/2 get series/1
]

back-func: func [] [ 
  set series/1 ((get series/1) - 1) 
  return at get series/2 get series/1
]

>> next-func series
== "ata"
>> next-func series
== "ta"
>> back-func series
== "ata"
>> back-func series
== "data"

Of course this is not what a series really is. But it does kind of
communicate the similarity, it provides an imprecise analogy. I believe
that thinking of REBOL in terms of inexact analogies and precise
distinctions allows you to master more of REBOL in a shorter time than
trying to develop a comprehensive terminology. 

My fear is that

a) Since REBOL really isn't all that complicated, a mathematically precise,
computer language scientifically comprehensive account of REBOL will just
make REBOL appear more complicated than it is and will make it more
difficult for REBOL's target audience to take conceptual possession of REBOL.

b) Perhaps the Tokyo super train - which is controlled by fuzzy logic -
demonstrates that if we approach understanding REBOL with more of a fuzzy
approach, we'll get our jobs done faster, if not to say just in time. Look
for similarities and identify enough distinguishing details to rapidly
implement a system that is close enough to expectations to be acceptable.

Anyway, I'm glad you brought it up, I'm always happy for an opportunity to
reflect conceptually on what I'm doing all day with REBOL and I'm sure that
continuing this thread will provide different people with different
insights as and when they need them, occassionally.

Elan


>That understanding would lead to the conclusion
>that
>
>    a: "123456"
>    b: next a
>
>leave 'a and 'b referring to distinct series values, as 'next or
>'length? yield different values when applied to 'a and 'b.  So I'm
>suggesting that making clear the distinction between a view and the
>underlying data would help clarify what is really happening (at least
>to slow learners like me).  

Doesn't the distinction between the local character of the current position
and the global character of the data storage sufficiently explain what is
"really happening"?

>In the same vein, I was recently surprised
>by
>
>    >> a: "123456"
>    == "123456"
>    >> b: next a
>    == "23456"
>    >> append b "-YOW!"
>    == "123456-YOW!"
>    >> b
>    == "23456-YOW!"
>
>in which "the series" returned by 'append is clearly different from
>"the series" referred to by 'b.
>

If you look at append's source, you will find that the function 'head is
responsible for this behavior:

append: func [
    {Appends a value to the tail of a series and returns the series head.}
    series [series! port!]
    value
    /only {Appends a block value into a block series as a block}
][    head either only [insert/only tail series :value
    ] [
        insert tail series :value
    ]
]


======

Regarding the any-string! problem: REBOL's error message is incorrect,
since make does support datatypes. Any-type! should not be categorized by
type? as being of type datatype! (which is the reason for the erroneous
error message):

>> type? string!
== datatype!
>> s: make string! ""
== ""
>> type? any-string!
== datatype!
>> s: make any-string! ""
** Script Error: Cannot use make on datatype! value.
** Where: s: make any-string! ""

Sure you can use make on datatype! values. It's just any-string! is not a
datatype! value.

Elan

Reply via email to