Sure... IEnumerable was inconvenient suggesting a separate class to service
the enumeration, IEnumerator, and multiple operations: Current, MoveNext,
Reset. (I'll warp the definition of "operation" for a second if you don't
mind).
However, it existed within intuitive language semantics, whereas the new
"yield" keyword, while highly convenient, is also one of the most gross
warping of language concepts to date...
public IEnumerator GetEnumerator() {
foreach(foobar o in _co) yield return o;
}
So, it essentially redefines the concepts of how functions are supposed to
behave, as well as how return values interact with return types. It also
introduces the new keyword with a very specialized purpose.
One way to explain "yield", is to say that it boxes your object into an
IEnumerator, saves the execution state of your function, and also restores
the execution state the next time your function is called, even before the
keyword is invoked during regular instruction flow, so it establishes the
loop's next startup state. Therefore, it redefines the laws of instruction
sequencing, and is sort of a quantum keyword that exists in multiple spots at
once during the existance of that function.
It would make sense to have IEnumerate be an allowed combination of
IEnumerable and IEnumerator, and to add a GetNext function that can return
the proper generic variable type. Then make "yield" its own return-style
keyword:
(** Proposed Syntax:
public class Woo : IEnumerate
{
...
public object GetNext() {
if(_collection==null) return null;
foreach(object obj in _collection) {
yield obj;
}
}
...
}
**)
This would still allow the full existing enumeration capability, but would
introduce this new style in a cleaner and more intuitive way. 4 5644
Marshal,
The problem with condensing the two interfaces into one is that you end
up losing the fact that a type can say "I can have my contained items
iterated through, and this is the mechanism by which you do it". That's
different from your interface, which says "I can have my contained items
iterated through, and ^I^ will do it". The IEnumerable/IEnumerator
functions are better, IMO, because it will allow for better encapsulation of
code, at the least.
The other problem with your proposal is that you can't tell if there are
any more items in your iteration. Yeah, you could check against return
value of GetNext for null, but if you are enumerating value types, then you
can't do this, since they can't be null (unless you use Nullable types, but
that wasn't around in 1.0, and you would have to do this ugly case logic to
determine if it was a value type or not, and then if it was null).
Using your method would end up looking something like this:
// An object, to check for null.
object o = null;
// The type of the object.
T t;
// Loop. You have to check for null here since your implementation would
return
// null if there are no items in the enumeration. The assumption here
// is that at the end of the loop, you would return null.
while ((o = collection.GetNext()) != null)
{
// Cast to the original object.
t = (T) o;
// Do some stuff.
}
This is a little more messy than what you have to do now. First, you
need to have the object instance just to check null, and you have a nasty
assignment and comparison in the while statement. Compare that to how
foreach is expanded by the compiler using the current IEnumeration interface
(and assuming that collection implements IEnumeration):
// The type t.
T t;
while (!collection.MoveNext())
{
// Get the value.
t = collection.Current;
}
You have t, and you know if you hit the end, but without that ugliness
in between (the o variable checking for null).
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com
"Marshal" <Ma*****@discussions.microsoft.com> wrote in message
news:17**********************************@microsof t.com... Sure... IEnumerable was inconvenient suggesting a separate class to service the enumeration, IEnumerator, and multiple operations: Current, MoveNext, Reset. (I'll warp the definition of "operation" for a second if you don't mind).
However, it existed within intuitive language semantics, whereas the new "yield" keyword, while highly convenient, is also one of the most gross warping of language concepts to date...
public IEnumerator GetEnumerator() { foreach(foobar o in _co) yield return o; }
So, it essentially redefines the concepts of how functions are supposed to behave, as well as how return values interact with return types. It also introduces the new keyword with a very specialized purpose.
One way to explain "yield", is to say that it boxes your object into an IEnumerator, saves the execution state of your function, and also restores the execution state the next time your function is called, even before the keyword is invoked during regular instruction flow, so it establishes the loop's next startup state. Therefore, it redefines the laws of instruction sequencing, and is sort of a quantum keyword that exists in multiple spots at once during the existance of that function.
It would make sense to have IEnumerate be an allowed combination of IEnumerable and IEnumerator, and to add a GetNext function that can return the proper generic variable type. Then make "yield" its own return-style keyword:
(** Proposed Syntax: public class Woo : IEnumerate { ... public object GetNext() { if(_collection==null) return null; foreach(object obj in _collection) { yield obj; } } ... } **)
This would still allow the full existing enumeration capability, but would introduce this new style in a cleaner and more intuitive way.
> The problem with condensing the two interfaces into one is that you end up losing the fact that a type can say "I can have my contained items iterated through, and this is the mechanism by which you do it". That's different from your interface, which says "I can have my contained items iterated through, and ^I^ will do it". The IEnumerable/IEnumerator functions are better, IMO, because it will allow for better encapsulation of code, at the least.
My proposal should be equivilent with the current proposals on using
"yield", it just cleans up the syntax. In both cases, you can still use
IEnumerable and IEnumerator for the reasons you point out, and both proposals
on "yield" are used for the ^I^ will do it case anyway.
The other problem with your proposal is that you can't tell if there are any more items in your iteration...
Again, it's basically a cleaner way of expressing the existing yield syntax,
which has no problem terminating the enumeration in magic code. I was imaging
it being used in a foreach statement.
If the GetNext function is called directly as in your example, then I would
expect it should throw an exception if the caller tries to read beyond the
end of the array. They should write something like:
(** Proposed Syntax:
collection.Reset();
while(collection.HasValues) { o = collection.GetNext(); ... }
**)
However, they should be as unlikely to do that, as they would be to call
GetEnumerator directly in the current model which uses yield. If they did so
in the current model, it would not appear as intuitive.
Using your method would end up looking something like this:
// An object, to check for null. object o = null;
// The type of the object. T t;
// Loop. You have to check for null here since your implementation would return // null if there are no items in the enumeration. The assumption here // is that at the end of the loop, you would return null. while ((o = collection.GetNext()) != null) { // Cast to the original object. t = (T) o;
// Do some stuff. }
This is a little more messy than what you have to do now. First, you need to have the object instance just to check null, and you have a nasty assignment and comparison in the while statement. Compare that to how foreach is expanded by the compiler using the current IEnumeration interface (and assuming that collection implements IEnumeration):
// The type t. T t;
while (!collection.MoveNext()) { // Get the value. t = collection.Current; }
You have t, and you know if you hit the end, but without that ugliness in between (the o variable checking for null).
-- - Nicholas Paldino [.NET/C# MVP] - mv*@spam.guard.caspershouse.com
See inline: The other problem with your proposal is that you can't tell if there are any more items in your iteration... Again, it's basically a cleaner way of expressing the existing yield syntax, which has no problem terminating the enumeration in magic code. I was imaging it being used in a foreach statement.
Ok, so it's cleaner, but at what cost? Clean doesn't mean anything if
actually implementing it is not.
If the GetNext function is called directly as in your example, then I would expect it should throw an exception if the caller tries to read beyond the end of the array. They should write something like:
(** Proposed Syntax: collection.Reset(); while(collection.HasValues) { o = collection.GetNext(); ... } **)
There is a specific reason why the designers of .NET didn't use
something like HasValues and GetNext. The reason for that is that a good
number of people actually forget to code the call to move to the next item
in the enumeration, leading to infinite loops. With the way it is now (with
the all to MoveNext returning whether or not there are elements), you don't
have that problem.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com However, they should be as unlikely to do that, as they would be to call GetEnumerator directly in the current model which uses yield. If they did so in the current model, it would not appear as intuitive.
Using your method would end up looking something like this:
// An object, to check for null. object o = null;
// The type of the object. T t;
// Loop. You have to check for null here since your implementation would return // null if there are no items in the enumeration. The assumption here // is that at the end of the loop, you would return null. while ((o = collection.GetNext()) != null) { // Cast to the original object. t = (T) o;
// Do some stuff. }
This is a little more messy than what you have to do now. First, you need to have the object instance just to check null, and you have a nasty assignment and comparison in the while statement. Compare that to how foreach is expanded by the compiler using the current IEnumeration interface (and assuming that collection implements IEnumeration):
// The type t. T t;
while (!collection.MoveNext()) { // Get the value. t = collection.Current; }
You have t, and you know if you hit the end, but without that ugliness in between (the o variable checking for null).
-- - Nicholas Paldino [.NET/C# MVP] - mv*@spam.guard.caspershouse.com
Marshal wrote: Sure... IEnumerable was inconvenient suggesting a separate class to service the enumeration, IEnumerator, and multiple operations: Current, MoveNext, Reset. (I'll warp the definition of "operation" for a second if you don't mind).
IEnumerable expresses that enumeration is supported, "I am iterable, you
can obtain that enumeration by invoking GetEnumerator()".
IEnumerator expresses a "pointer" into an enumeration, "This is how far
you are along the enumeration".
IEnumerator have Current/MoveNext(), JAVA Iterator have hasNext() and
next(), C++ iterators have "++" and "*". Actually I don't recall seeing
any protocol for iteration that don't have seperate
advance/advance-check and value obtain, and thus multiple operations.
I would say that whether Reset() should be included in IEnumerator is
open to discussion.
So, it essentially redefines the concepts of how functions are supposed to behave, as well as how return values interact with return types. It also introduces the new keyword with a very specialized purpose.
It lets you define a generator for IEnumerator using function-syntax.
Other languages have this too, python and it is essential in ruby.
Whether this "redefines the concepts of how functions work" or not...
well, you are really just defining a function that returns an
enumerator. There is no "quantum magic" here, only compiler assisted
closure greneration.
Notice that the caller of the function doesn't care if actual "quantum
magic" was used to implement the IEnumerator returned. The implementer u
could do it by implementing the closure, MoveNext() and Current by hand
in a class that stores the relevant state and implement IEnumerator.
Function-syntax is rather nice for describing enumeration, and
syntactic-sugar support for storing the used local-variables in a
helper-class and implementing Current/MoveNext() is convinient to me in
that syntax.
One way to explain "yield", is to say that it boxes your object into an IEnumerator, saves the execution state of your function, and also restores the execution state the next time your function is called, even before the keyword is invoked during regular instruction flow, so it establishes the loop's next startup state. Therefore, it redefines the laws of instruction sequencing, and is sort of a quantum keyword that exists in multiple spots at once during the existance of that function.
Another way to explain it would be that it generates an IEnumerators
MoveNext() and Current functions from the closure available in the
function. This is a known technique known from functional programming: a
higher-order function.
It would make sense to have IEnumerate be an allowed combination of IEnumerable and IEnumerator, and to add a GetNext function that can return the proper generic variable type. Then make "yield" its own return-style keyword:
I don't see the benefit of combining IEnumerable and IEnumerator, see above.
The problems in combining the two concepts is manifest in our
example-code. Where is _collection coming from (the interface-usage
prevents you from having a protocol of accepting it at construction time).
(** Proposed Syntax: public class Woo : IEnumerate { ... public object GetNext() { if(_collection==null) return null; foreach(object obj in _collection) { yield obj; } } ... } **)
I don't really understand how this is substantially different from or
better than:
public static IEnumerator Enumerate(ICollection c) {
foreach ( object o in c )
yield return o;
}
Which fits into the current enumeration-idiom in C#.
The choice of "yield return" vs. just "yield" is open to discussion, but
i suspect "yield return" was chosen because no program containing that
sequence of tokens would be valid in previous C# revisions.
This would still allow the full existing enumeration capability, but would introduce this new style in a cleaner and more intuitive way.
Perhaps you are finding the IEnumerable/IEnumerator design
non-intuitive, and perhaps transfer that onto the "yield return" construct?
I find that the IEnumerable/IEnumerator design is spot-on and I haven't
really seen any languages which doesn't make that distinction in one
form or another.
Perhaps you need just a little more assimilation before you accept the
design ;) (notice smiley.... i'm not being hostile here)
--
Helge Jensen
mailto:he**********@slog.dk
sip:he**********@slog.dk
-=> Sebastian cover-music: http://ungdomshus.nu <=- This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics |
by: Andrew James |
last post by:
Gentlemen,
I'm currently in the process of designing a language which will be used
to specify sets of files on a WebDAV server, encoded in a URL. The aims
of the language are to (in no particular...
|
by: Justin Wright |
last post by:
I know that I can set up an enumeration as follows ( just typed in quick so
may have syntax errors ):
<xsd:simpleType name="colors">
<xsd:restriction base="xsd:string">
<xsd:enumeration...
|
by: Tristan Miller |
last post by:
Greetings.
Do any popular browsers correctly support <q>, at least for Western
languages? I've noticed that Mozilla uses the standard English
double-quote character, ", regardless of the lang...
|
by: Randy Yates |
last post by:
In Harbison and Steele's text (fourth edition, p.111)
it is stated,
The C language does not specify the range of integers that the
integral types will represent, except ot say that type int may...
|
by: Tony Whitter |
last post by:
Does anyone know how much changed between the final draft dated October 2002
and the Ecma-334 C# Language Specification 2nd edition dated December 2002
and if there is a change history document...
| |
by: Eric Gunnerson [MS] |
last post by:
You may download the new specification at the C# Developer Center
(http://msdn.microsoft.com/vcsharp/language). There is a discussion forum
for the C# language on that same page.
If you don't...
|
by: Marshal [DirectX MVP 2003] |
last post by:
In anticipation of the chat, I have filtered all of my current enhancement
aleration ideas through the software development community, via the following
postings:
C# Language Specification -...
|
by: albert.neu |
last post by:
Hello!
What is the difference between "library parts" of C99 and "language
parts" of C99.
see...
|
by: Vneha |
last post by:
Q:- What is the difference between Sun Java tutorials and Java Language specification?
Q:- What if i start studying Java Language Specification and leave the tutorials because i have seen that...
|
by: marktang |
last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
|
by: jinu1996 |
last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
| |
by: Hystou |
last post by:
Overview:
Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
|
by: tracyyun |
last post by:
Dear forum friends,
With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
|
by: agi2029 |
last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
|
by: isladogs |
last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM).
In this session, we are pleased to welcome a new...
|
by: conductexam |
last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...
|
by: muto222 |
last post by:
How can i add a mobile payment intergratation into php mysql website.
| |
by: bsmnconsultancy |
last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence...
| |