Re: foreach enhancement

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


Date: Sat, 17 Jul 2004 20:58:52 -0500


"Michael C" <nospam@lol.net> wrote in message
news:%jkKc.35962$Kz3.3462581@news4.srv.hcvlny.cv.net...
>
> "Daniel O'Connell [C# MVP]" <onyxkirx@--NOSPAM--comcast.net> wrote in
> message news:OgRMJ0FbEHA.2812@tk2msftngp13.phx.gbl...
>> > [for x, y in [1..1000, -2..2000]]
>>
>> What order does that return? all x's then all y's? or x, then y then x
> then
>> y and so on? How do you yield pairs? How do you perform joins?
>>
>
> To my thinking, this would return an enumeration for x [1..1000] and a
> nested loop of y [-2..2000]. The syntax is similar to Python but the
> behavior I'd have to look up. Not sure if Python nests the y inside the x
> or if it performs the y loop subsequently to the x loop.
>
>>
>> Again, I'm not sure if this really makes much sense. Each of these
> examples
>> is basically useless uses of the words. The for\foreach syntax doesn't
>> add
>> anything to the list without some kind of processing.
>>
>
> The differentiation was strictly for your benefit - to ease your
> implementation, since one requires strong typing and will let you know
> upfront that it might be very optimizable; the other to let you know that
> strong typing is not an option, and that optimization will not be able to
> be
> as good. As long as you're willing to write the code to determine this
> without the hints, you're good to go. It also appears that we're not as

I think determining the two *shouldn't* be too terribly difficult.
Implementation is usually the easy part, its defining the proper behaviour
and making it work with every other rule that you have to abide by that will
make you tear your hair out and keep it in a rasin canister.

Thanks for the thought though.
> concerned with optimization of for loops and typing - since lists will be
> strongly typed. From what you've said, it appears that
>
> [yield value in [1..10]]
>
> is functionally and programmatically equivalent to
>
> [yield value in [1,2,3,4,5,6,7,8,9,10]]
>
> So that it cannot be optimized down to
>
> for (value = 1; value <= 10; value++)
>
> But rather something more like
>
> foreach (value in new int [] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10})
>
> Is this correct? If so, then the for/foreach examples I presented are
> unnecessary. Just to make sure we're on the same page, we're no longer
> concerned with optimization, right?
>

They are both semantically identical; that is they *will* have the same end
result. However the actual implementation and function of the two may be
*very* different and the compiler itself will certainly be able to know the
difference. Since ranges have a defined start and end bound in many cases,
it wouldn't be hard for the compiler to play tricks and efficently generate
lists that take up very little space until they are actually used by
reserving indexes that exist as an enumerator but not actually generating
the values until they are accessed. A list comprehension is a different
matter and will usually result in a completely generated list since in most
any circumstance you use a where expression the ability to determine range
length goes out the window. It wouldn't be impossible for the compiler to
evaluate mathematic only where expression for ints and other baisc types and
determine the actual number of results, I'm just not sure I would want to go
that far unless it showed significant value.

It also wouldn't be beyond the compiler to take expressions like
[1,2,3,4,5,6,7,8,9,10] and transform them into 1...10 (or vice versa) if it
felt execution or memory efficency would benifit. For exceedingly small
cases like this, I would probably lean towards generating
[1,2,3,4,5,6,7,8,9,10] instead of forcing generation of each value.
Similarly if someone was insane enough to put 800000 direct sequential
entries of longs into a list I would think collapsing it into a range would
be better.

A pragma is probably appropriate to explicitly enable or disable this type
of optimization over a range, atleast for the proof of concept
implementation. It'd make testing easier and help out if there is a
particualr reason you want one or the other that the compiler can't
understand(like a massive number of random index lookups).

>> Beyond that, since the lists are mostly strongly typed, I think you could
>> achieve optimizations using either for or foreach in the majority of
> cases,
>> even though it would include a sacrifice in clarity of the code to IL
>> mapping.
>
> Well, again if we're dealing with strongly typed lists, then the why the
> implicitly typed 'value' keyword? Just have the user declare a strongly
> typed variable. It seems like we're bouncing back and forth on some of
> these issues here. Do the lists have to be strongly typed, is implicit
> typing an issue, what type of optimizations are you looking to implement?
>
> The clarity of the code to IL mapping is probably not as critical to most
> developers as it will be to you, since you're developing the actual tool.
> As long as it doesn't cause you concern, it probably isn't too much of an
> issue.
>
> I guess one question I just have to ask is what exactly is a list? I've
> worked with lists in various languages, and I'm viewing lists with the
> preconceived notions here. Just for reference, how would *you* expand the
> following statements out in C#?
>
Each of these is under my desires as well as under what the rules *would* do
in the compiler:
my intent first, actual effective results second
> List a = [1..100, 10..30, 500, 35];
literally, not going to type everything out: what is typed
values 1 through 100, then 10 through 30, 500, and 35
same for the compiler
>
> List b = ["hello", "how are you?", "goodbye"];
>
As it is here: hello, how are you?, and goodbye.
however, based on range rules the compier would generate each cahracter
seperately. Hopefully I explained that well enough in my other post.
> [yield i in [1..100]]
1 through 100
>
> [yield j in b]
If you follow my rules you get: hello, how are you? and goodbye.
if you follow the actual compiler rules you end up with each character
because b is already a list of each character.

This is where my issue is, creating rules for the compiler that will
evaluate properly, not nessecerily creating a working model in my mind.

>
> And are you staying with strongly typed lists? If not, how would you
> define, in C# terms, a list that is not strongly typed?
A list will be strongly typed where possible. However I'm implicitly typing
value because I don't want to have to type int i in a comprehension:
[yield i foreach int i in 1...1000]
isn't terribly attractive, although it is effective and perhaps nessecery.
Value is already implicitly typed in properties, indexers, etc.

The list [1...1000] *will* evaluate to IList<int>
the list [1D...1000D] will evaluate to IList<double>
etc.

>
> Thanks,
> Michael C.
>
>



Relevant Pages

  • Re: foreach enhancement
    ... or if it performs the y loop subsequently to the x loop. ... strong typing is not an option, and that optimization will not be able to be ... Well, again if we're dealing with strongly typed lists, then the why the ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: Lisp Ruby Scheme
    ... :> the compiler has the guarantee that no side-effects will happen during ... :> construct intermediate lists. ... functional-ness of such leaf functions, at which point it is free to ... perform the same heroic optimization as the supposed Hascal compiler. ...
    (comp.lang.scheme)
  • Re: Just a bit of silliness
    ... But format strings could be eliminated completely: ... This would require a great deal of compiler support, ... parameter lists are declared explicitly, ... Since C doesn't have runtime type information, ...
    (comp.lang.c)
  • Aurora Beta 1
    ... The Aurora compiler has just been updated to Beta 1. ... non-indexed triangle lists. ... The ClassView pane in the IDE now does something. ...
    (comp.lang.misc)
  • Re: More static type fun.
    ... > perception of how common runtime type errors are. ... to invest in unit tests to catch bugs and gotchas in my program would ... and about placating the compiler. ... > to explicitly tell the compiler that you want to use lists with more ...
    (comp.lang.lisp)