Re: foreach enhancement

Tech-Archive recommends: Repair Windows Errors & Optimize Windows Performance

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


Date: Mon, 12 Jul 2004 21:15:37 -0500


>
>
> Why not just making {1,2,3} an array literal? It is just a shorthand for
> new
> int[]{1,2,3}.

Primarily because I'm concerned that {1,2,3} isn't syntactically possible.
{ <expression> } is legal syntax in C#(creates a block), how do you tell the
difference in that and {<listexpression>} ? Considering 10...30 as a
generator expression, { 10...30; } is ambigious outside of the ;, and I
don't particually care for distinguishing two very different syntaxes with a
single contained semicolon.
[] has no stand alone meaning I can think of, its tied to identifiers and
attributes, but I think it would be far more feasible to write a compiler
that works that way. Its certainly not guarenteed, but I think the chances
are better.

Attributes may throw some nasty bits into field assignments, I fear. One
could also probably use
<0...10> as well, but again I would have to experiment with a compiler to
know for sure.

> The type is taken from the element literals, the compiler must just ensure
> that all variables in the array literal have the same type.
>
> 0..10 is a set literal (or maybe "enumerable ordered set generator
> literal"
> :) ).
>

This does generate a set, I'll agree. However I think it fits better as a
sequence(or ordered set) generator instead of as a set expression\literal.
Instead of returning a "set", it returns an enumerator.

> So we can write if (a in 0..10) and we don't need the brackets.
> if we have multiple ranges we can use parentheses: if (a in (0..10,
> 30..40))

I'd rather write:
if (a in 0...30 || a in 30...40)

instead of adding extra parantheses. I worry about the compiler architecture
that would require(parentheses have specific meanings already, this would
overload them, which i'm always hesitant to do).

>
>
> We can simply that by default operator+(Type t, int n) is used for
> increment.
> If it is not present in the type we have to explicity state an increment
> value.
> This loop enumerates all days between today and the 31.12.2020 (we set the
> increment to TimeSpan.TicksPerDay here)
>
> foreach (DateTime dt in DateTime.Today..new DateTime(31,12,2020) :
> TimeSpan.TicksPerDay ) {}

This works pretty well, I have to admit. I didn't think of the various
TimeSpan values, although operator+(DateTime,TimeSpan) would be ideal in
this situation as well.

>
>> You could use an increment clause but I'm not sure how to get that to
>> work
> with
>> datetime without adding considerable complexity to the language(timespan
>> literals would help here, but they are rather rarely used things and
>> probably don't warrent addition).
>>
>> The other option is to special case the in operator(or, as I'd rather do,
>> rename it to isin) as you suggested so that it doesn't emit the generator
>> expression, instead taking the values from it. This could be complicated
> to
>> do in situatinos like:
>>
>> int lowerBound = 555;
>> int upperBound = 8137;
>> if (x isin [lowerBound...upperBound])
>
>
> What do you mean with that? Why do we need to rename "in" to "isin"?

Syntactic clarity, basically. in has a meaning.
Consider
foreach (x in y)
and
if (x in y)

in that case, in has two *very* different meanings in two *very* similar
situations. Using isin would skip that by creating a new keyword without
existing meaning in similar circumstances. things like default(which I don't
agree with, defaultof makes more sense) work because the usages are
different(default(x) and switch { default: break; } are very different.

I'm not advocating using isin in foreach, just as general containment
keyword.
>
>> For what its worth, isin would be an operator that takes a value x and
>> checks if it is in the list(or range) specified, returning a bool. It
> would
>> be able to stand alone, in other words
>> bool valid = 12 isin myNumberList;
>
> This gives me the idea that it should be possible to store such a set
> literal in a variable. And which already existing keyword wouldn't fit
> better:
>

That requires definition of a new type, ISet, which we don't have yet.
However I wouldn't be terribly against the concept. Although a readonly
array would do the job fine. This however does lead back into the needs of
the general collections in the BCL.

Now, if you would *stop* insisting that it is a set literal and instead
consider it array or list literals, you don't need any additions,
IList\ICollection and Array do the job sufficently.

> set mySet = (1..10, 30..100);

Again, parentheses wouldn't work here due to their existing meaning(grouping
expressions). Thats why I've proposed brackets a few times.

In this situation, however, you are forced to decide on ordered sets and on
lists. With lists you end up with two different sets of values added,
whereas if you are using sets you would use unions, etc instead. That would
clear up the need for parentheses here for a set

1...10 union 30...100 (can't think of a symbol for unions off hand).

Generator expressions could use set syntax while list literals could use
commas to seperate several list generators.

This does lead to the need of a set type, one that is defined by an equation
instead of by a literal and members are generated via an iterator as needed.

Sounds a bit functional, doesn't it.

>
> if (a in mySet) {}
>
>> The minimum requirements for ranges would probably have to be
>> T operator+(T,int) //Allow default increments, ie x...y where x
> and y are T
>> T operator+(T,T) //Allow incrementing using T, ie x...y : z
>> where
> x, y, and z are T
>> bool operator==(T,T)
>> bool operator!=(T,T)
>> bool operator<(T,T)
>> bool operator>(T,T)
>> bool operator>=(T,T)
>> bool operator<=(T,T)
>
> I think we do not need operator!=(T,T). operator+(T,int) is only required
> if
> no increment literal is specified and operator+(T,X) is only required if
> an
> increment literal of type X is specified.

I agree on addition, standard adding rules works pretty well.

You have a point on !=, can't think of a use. However != is supposed to be
implemented when == is, so its required by default.
>
> --
> cody
>
> [Freeware, Games and Humor]
> www.deutronium.de.vu || www.deutronium.tk
>
>



Relevant Pages

  • Re: how to create a big list of list
    ... You can get one easily by writing a generator expression: ... If what you want is to have a huge multi-dimensional array for numerical ... lists may not be the best option. ... third-party NumPy library and use its types. ...
    (comp.lang.python)
  • Re: garbage collection problem in large linked lists
    ... Instead all buckets are allocated at once in an array. ... VG.net, which must be very scalable, but only for lists which would normally ... Linked lists require pointer dereferencing in order to traverse. ... When you run out of space, you allocate a new smaller array. ...
    (microsoft.public.dotnet.framework.performance)
  • Re: Dict sharing vs. duplication
    ... array to enforce unique keys and I use lists to enforce order. ... API in a page or two of Tcl code, it isn't so much a missing feature ... OpenACS database API which creates a new specialized data structure, ...
    (comp.lang.tcl)
  • Re: Translating python to scheme
    ... Scheme has mutation, and there are reasons to use it. ... confusing when considering a 2d array. ... in other languages: Lisp Lists and Vectors. ...
    (comp.lang.scheme)
  • Re: CLISP: 2dim array to list of lists
    ... so your question below has nothing specific to clisp. ... I've a 2 dimensional array which I'd like to convert to a list of ... the reason why I'd like to convert the array to a list of lists is ... clisp is a specific implementation of Common Lisp aka CL aka Lisp ...
    (comp.lang.lisp)