Mike and Jon,
Relative to the collection ontology issues of foreach()/forever() and the
read/write nature of iteration.
I did some research over the weekend. I covered the linguistics of
'iteration' in human language, the mathematical community and (of course)
programming. I ended up with about 60 PDF files of blogs, articles, and
specs.
My final focus was the evolution of the C# 'iteration' specifications in
Ander's (Inventor of C# - and his MS dev team) statements in the C# specs.
The intent of this investigation was to verify your statements on the read
only (or not) nature of the 'enumerator' in C#.
The final (and most important) reference point is Anders specifications
for C# V 2. From the C# V2 spec he writes. (Start Quoted section)
(Hejlsberg.book Page 470 Friday, October 10, 2003 7:35 PM)
The generic and nongeneric enumerable interfaces contain a single member,
a GetEnumerator method that takes no arguments and returns an enumerator
interface. An enumerable acts as an enumerator factory. Properly
implemented enumerables generate independent enumerators each time their
GetEnumerator method is called. Assuming the internal state of the
enumerable has not changed between two calls to GetEnumerator, the two
enumerators returned should produce the same set of values in the same
order. This should hold even if the lifetime of the enumerators overlap
as in the following code sample.
using System;
using System.Collecti ons.Generic;
class Test
{
static IEnumerable<int > FromTo(int from, int to) {
while (from <= to) yield return from++;
}
static void Main() {
IEnumerable<int > e = FromTo(1, 10);
foreach (int x in e) {
foreach (int y in e) {
Console.Write(" {0,3} ", x * y);
}
Console.WriteLi ne();
}
}
}
(End Quoted section)
Numerable articles and presentations mention the 'read only' nature of
'enumerators' to emphasize the 'repeatable results' aspect of 'iterators'
above.
I contrast the above reference point (Anders statement) with the
mathematical definition of 'Iterative Method' found at;
www.wikipedia.org
which states;
(Quoted section)
In computational mathematics, an iterative method attempts to solve a
problem (for example an equation or system of equations) by finding
successive approximations to the solution starting from an initial guess.
This approach is in contrast to direct methods, which attempt to solve the
problem in one-shot (like solving a linear system of equations Ax = b by
finding the inverse of the matrix A).
......
Probably the first iterative method appeared in a letter of Gauss to a
student of his. He proposed solving a 4-by-4 system of equations by
repeatedly solving the component in which the residual was the largest.
The theory of stationary iterative methods was solidly established with
the work of D.M. Young starting in the 1950s. The Conjugate Gradient
method was also invented in the 1950s, with independent developments by
Cornelius Lanczos, Magnus Hestenes and Eduard Stiefel, but its nature and
applicability were misunderstood at the time. Only in the 1970s was it
realized that conjugacy based methods work very well for partial
differential equations, especially the elliptic type.
(End quoted section)
The proposed C# V3 forevery() - ISequencer feature would be used in code
structures where collections are inherently writable, changable, and
iterations have changing results. Collections are seen more as 'living
places' for 'traveling items' that move about under their own volition or
under external impetus. The collections are also exist in a 'binding
matrix' that is used for navigation and migration decisions.
Thus, the 'stackable' forevery() computation features support an
indeterminate 'changing' nature of iteration results.
A set of 'dynamic conventions', such as new items (created during in
iteration pass)
go to end of list, provide for repeatablity of process (not result).
Real world examples would exist in the context of incoming data
composition of perception mechanisms for satellite telemetry, a machine
trying to understand what a person is saying and underwater robots.
In these applications data items go through stages of data processing
fostered by their location (which collection they belong to).
Writable iteration (sequencers) applies constantly changing 'aggregate
state space' phenomena to individual items in their individual journey
through the data processing system.
I am still in research mode and wish to review more material.
Later this week I will post a summary statement on
need for a authoritative collection ontology from the Microsoft folks that
can help to reduce some of the confusion (mine and others) related to
iterative terminology in C#. (I quickly checked Microsoft eBooks on
computing before any research).
I note that your combined understanding of iterators in C# is much better
than mine.
The code syntax issues of (1) ref/out [data channel], (2) terminology and
(3) foreach() vs forevery() are separate but inter-related. I will focus
the remaining posts (in this thread) to issues 2 and 3. These issues are
basically issues of semantics in the C# collection ontology.
I do have one short post on 'iterative data channels' (return, the enumerator
itself (in the foreach() statement), the ref/out). I will put that in a
separate
post.
I would like to defer to terms used in the C# C5 collection library out of
Copenhagen (IT University Technical Report Series TR-2006-76) but I need
to complete my linguistic groundwork first.
Mike, your excellent comment;
I think writable iterators are weird -- they appear very "functional ", but
go against that paradigm as they mutate rather than copy.
is very true. The application context (mentioned above) has a
fundamentally different view of mutability let alone the deterministic
implications because of the constant change nature of the collection
content. Thus your use of the word 'paradigm' is exactly the sematic issue
I am trying to understand.
This is the exact impetus; semantic clarity of the C# collection ontology
and its resulting syntactic expression that I wish to understand. With
this in mind I will be reviewing both of your statements on the mutable
nature of 'enumerators' this week.
Thanks, again, for your patience with my response time.
With all due respect I want to thank you ahead of time for any continued
input. Also thank you again for you input in helping me understand the 'C#
enumerator semantics'.
Shawnk
PS. The forevery() establishes an focused complementary collective processing
paradigm to complement foreach() via a read vs write functional basis.
"Mike" wrote:
"Jon Skeet [C# MVP]" <sk***@pobox.co m> wrote in message
news:11******** *************@e 56g2000cwe.goog legroups.com... Shawnk wrote:
<snip>
I'm not sure it's particularly necessary, but I'm not entirely averse
to it...
<more snips>
That's how I feel about it. I think its noble to make something that works
no matter what the underlying collection is (again, assuming there is one)
but there are some problems:
(1) To me it's not necessarily easier to read -- it can actually be so
"generic looking" that it's hard to tell whats actually happening. I think
destructive operations should be explicit. (Maybe if I came from an STL
background I'd feel differently.)
(2) You're kind of assuming iterators that work by maintaining a "cursor"
though a collection. C# iterators are moving toward using "yield" which
saves activation state and acts as a limited sort of co-routine, which has
many advantages; however, making Current writable is not possible in general
using this method of writing iterators. (But I guess your distinction of
Sequencer vs. Enumerator is basically a cursor.)
(3) Different collections have different interfaces -- for example, if you
had a priority queue, and you do a "move out", where does the priority (or
other baggage for a particular container class) go which needs to stay
semantically "attached" to the item before it can be added to another queue?
(4) IMHO, the basic collection type is usually an obvious choice up-front
90% of the time, so spending too much time on anything past read-only
iterators isn't worth the complexity. Plus, if you have the collection
black-boxed behind an opaque type anyway and the interface to the outside
world is stable, you can change the complex data-munging code without
disturbing your clients - better to not let them get a hold of your
collections themselves anyway - publish your own GetEnumerator() calls that
can return the interior ones, or ones you code.
(5) I think writable iterators are weird -- they appear very "functional ",
but go against that paradigm as they mutate rather than copy.
But I guess if there is a solution that is natural in the c# world (whether
the "proxy" version or an out/ref version) then I could be convinced -
still, I wonder if the effort is worth the gain.
m
Jon