Re: foreach enhancement

From: Daniel O'Connell [C# MVP] (onyxkirx_at_--NOSPAM--comcast.net)
Date: 07/16/04


Date: Thu, 15 Jul 2004 22:43:54 -0500


>> The problem here is that 1...3 *would* basically be an
>> IEnumerable\IEnumerator. It is a sequence generator which is expressed by
>> enumerable objects in the runtime. Making all of this work without
> breaking
>> the rules of the language is pretty tough. I've been considering a new
>> operator, <-, which assigns each value in an enumerable object to a
> variable
>
>
> Now I understand. Maybe you can treat x..y as a special type, because in
> contrast to an IEnumerable the size of the range is known at execution
> time
> and has not to be enumerated first, so no temporary arraylist has to be
> generated as it would otherwise be the case.
>
Treating it as a special type is a possibility, but I am in general hesitant
to define behaviour based on syntax instead of semantics.
> But I'd rather make the assigment of all subitems to the array explicit
> than
> implicit,
> so I vote for your "content operator", although I'd rather use # instead
> of
> <-.

I'm still considering this particular issue. Finding good syntax is pretty
tough. The original concept behind <- was based around another piece of
syntax which I've more or less discounted at this point.
A different, perhaps better perhaps not, solution may be to perform
automated input on expressions typed IEnumerable explicitly instead of any
other, yet I'm still not sure.
I am concerned with the # syntax due to # being used already by compiler
directives.
>
>> I'm talking optimization of range literals. For the case foreach (int i
>> in
>> 1...1000) I see no reason to generate an object, instead a for loop like
> you
>> suggested is generatable. However, for code like
>> foreach(int i in 1...1000, 1000...1, 2...5 : .5, 3...5838) a generator
>> object would probably make more sense as it would *vastly* simplify the
>> output code and probably the break statement as well.
>
>
> But for the compiler it won't make any difference wheather you have 2 or
> 20
> ranges in the loop will it?
> Outputting for each range a separate loop is the most performant solution.
> The only problem is if the loop *body* is very large you really have a
> code
> bloat.
> In that case outputting a single foreach loop which iterates over a
> constructed RangeEnumerator object will be the right way.
>

It won't make significant difference to the compiler, but as you noted if
the code starts to bloat or conditions start to grow to much the compiler
should shift. I imagine there is a point where the enumerator is more
performant than inline for's and you would certainly not want a huge amount
of code generated due to a single expression. For starters I'll probably
only support optimizing 2 ranges and consider adding additional
optimizations if I think it makes sense. It is only a proof of concept after
all.

>> Since this is a proof-of-concept implementation, I am also looking at
>> slightly more complicated subjects like haskell&python like list
>> comprehensions(which I think effectivly become mini-iterators). My
> existing
>> implementatino ideas are too unpolished to post right now(6 pages of
>> rambling is to much), but the current syntax allows you to do things like
>> sequence unions and intersections, value mutation, value analysis, etc.
>> some rough samples:
>> [1...1000 where value%2 == 0] //returns all even numbers between 1 &1000,
>> inclusive
>> [yield Math.Pow(value,2) for 1...1000 where Math.Pow(value,2)%2 == 0]
>> //returns the square of each value which has an even square
>
>
> Now you are really going to far :) Are you sure this would fit into C#?
> Your first example can be solved using the optionally increment clause
> and for more complicated things I would create my own enumerator.

Nope, I'm not sure about anything, ;). The entire point of this is to
experiment with ti and see how it works. List comprehensions are fairly
popular in the functional world and I am rather curious as to if they *can*
be fit into C# and if they will make life easier or not. I figure if I'm
going this far I may as well do the whole shebang and see what everyoen
thinks after they use it.

>
> foreach (int a in GetAllPowerOfTwoWherePowerOfTwoIsEven(1, 1000))
> {
> list.Add(a);
> }
>
yes and you can say foreach(int a in GetAllNumbersBetween(1,1000))
{
    list.Add(a);
}

just as well. It's kind of illogical to use the argument you are fighting
for your base concept to argue down another feature, isn't it? :)
> Using C#'s new anonymous methods you could do:
>
> [delegate{foreach(int a in 1..1000){if (Math.Pow(value,2)%2 == 0)yield
> return Math.Pow(value,2); }}]

I don't think you can use iterators in anonymous methods, though I could be
wrong.

>
> Btw, a great enhancement for the ArrayList class would be an AddRange
> method
> and a Ctor that takes an IEnumerable as parameter which fills the list
> with
> all enumerated elements.
>

Yeah, that would make sense.
>> But, as I said these are *very* rough and I'm not sure how or if I'll
>> bother. I do like the concept though and they are quite popular in
>> python.
>>
>> I'll post more on syntax reasoning if anyone is interested.
>
>
> Iam very interested in it. Do you have a homepage?

No, sadly. Me and http are not particulary close friends(this is probably
due to my long running campaign to discredit http, html, and most related
technologies as garbage). As such I don't really keep web pages going too
often. I did have a blog[1] for a little while but after a few posts I
stopped using it.

Most of my ideas show up here sometime or another. I will try to writeup all
the various things I've considered *or* I will forward port all my mono
modifications and provide a complete patch containing these list features
with everything else.

1. http://www.dotnetjunkies.com/weblog/doconnell/

Maybe I'll start updating things there as work gets done on this feature.



Relevant Pages

  • Re: Class and Iterator Design Question
    ... >>>would'nt it make more sense to have yield work coroutinish ... >> generator?). ... > of yielding better than returning an Enumerator, ... If you want external iterators, I don't think Generator is the ...
    (comp.lang.ruby)
  • Re: Class and Iterator Design Question
    ... basically integrating the enumerator ... That sounds unnecesarily complex. ... Anyway, yes, just like a Generator, and for all the usage of yield, not ...
    (comp.lang.ruby)
  • Re: Cleaner syntax for .map (is there already a way, or ruby2 idea?)
    ... Trans wrote in: ... } I know that people.every could return some kind of generator or enumerator, which could then be fed "email_addr" symbolically... ... David A. Black dblack@xxxxxxxxxxxx ...
    (comp.lang.ruby)