D
Daniel O'Connell [C# MVP]
Michael C said:If other types implement these operators at some point, wouldn't it be
incumbent on the programmer to overload the operators if they wanted
different behavior?
Well, consider this:
[1...100] is an IList<int>.
[1...100] + [1...22] is effectivly IList<int> + IList<int>. As such a +
operator that operates on ILists is needed. However, if you provide a class
that implements IList<T> and overload operator+, what happens? I'm more
concerned about the general meaning than anything else. A psuedooperator
that adds lists adds all lists, I don't think its particularly clean to
limit it to one kind of list. Thus, you have potential conflicts.
The other issue, -[50...75] is confusing. Is it going to remove *every*
instance of 50...75 or just the first one, or just a segment running from 50
to 75? With a comprehension exactly what is going to happen is spelled out,
there is no room for confusion.
Confusion is at the core of this project. Not a lot of the desired end
results have been agreed upon, nor the underlying problem defined. One
person defines the problem as simple x..y ranges, in which overlapping
segments make no sense; one sees the usefulness of multiple ranges with
endpoints that are non-contiguous, another thinks overlap may be useful
somewhere down the road to somebody; another person sees ranges as being
part of a larger list type which may contain overlapping ranges or
non-contiguous ranges. So let's take a step back.
Confusion is often the nature of ideas discussed on public forums. There are
alot of ideas flying around, granted, and I'm tryign to cull through them
and get sane behaviour. I don't think that to many ideas or too many
opinions kills off a potential features value so much as makes it difficult
to discern the core idea and what needs to be done. Given enough time there
is a good chance a general consensus will be reached.
If not, no offense inteded to anyone, but as I am the one implementing it, I
am taking it upon myself to try to filter that and create the best possible
solution, even if one idea or another has to go by the wayside because of
it. The hard part is dumping my own ideas on the issue, however, .
Everyone's goals are a touch different. I'm pushing for a very abstract
concept where each individual syntax exists independently but can be
combined. I can't say for certain what exactly everyone else wants.
If we are looking at [1..100] as a list, which may contain multiple
ranges,
then let's start with the + operator. If the list allows multiple ranges,
the + operator would produce the following result:
[1..100] + [25..75] = [1..100, 25..75]
Therefore the += operator would produce similar results:
x = [1..100];
x += [25..75]; // x = [1..100, 25..75]
I suggested the * operator because a programmer might want to produce a
single range with no overlap in some situations (i.e., looping where
overlap
makes no sense). The | operator might make sense here also:
[1..100] * [25..150] = [1..150]
This leads to the shorthand *= also. As for the minus operator, that is
dependent partially on the definition of the actual problem from above.
Regardless, my thoughts are that most programmers expect their minus
operator to work inversely to the plus operator. So the - operator, as
inverse of the + operator, would provide the following:
x = [1..100, 25..75];
x += [25..75]; // x = [1..100, 25..75, 25..75]
x -= [25..75]; // x = [1..100, 25..75] - removes one range, as + adds one
range
Perhaps an operator could be agreed upon that also removes all of a
certain
type of ranges (i just put in the ! cause I'm running out of keyboard
chars -- think of it as a placeholder):
x = [1..100, 25..75];
x != [25..75]; // removes all subranges 25..75 from the list
These are just ideas, but the problem has to be clearly defined first.
I agree that there is a need to be able to express these ideas. I see you
prefer operators while I prefer the comprehension style. I am concerned
about operator overloading issues as above, but my primary goal with
comprehensions is that they are more flexible(and probably less performant,
bringing up your favorite adage again). A comprehension isn't limited to
joining, removing, and intersecting, but can be used to perform complex
operations on list contents, including transformations and lookups:
[yield GetValue(value) for 1...1000] for example;
I think the biggest problem is there *isn't* a problem, per se. Instead
there are places where several people can see room for improvement or where
they feel features would fit well(me and my list comprehension fetish, for
example). This leads to the issue of things that are nice to have, that may
well be noticeable improvements to the language and yet you still can't find
a valid arugment for supporting them. The best I can say is that I am
interested in exploring a clearer way to deal with ranges and lists.
As it stands, with the inclusion of generics I can only think of a single
real problem with the langauge, which is basically the general crappiness of
the casting operator.
Don't fret, just take a step back and clearly define the problem in terms
of
the end result. I have a pretty good idea of the end result I would like,
End results aren't the hard part. I have a pretty good grasp of the end
result and as much of a problem as one can muster here. The problem is every
practical way of tacking that result ends up having one showstopper issue or
another. Given the desire to maintain consistency, alot of rules have to be
considered and no one solution I've dreamt up yet maintains every rule and
still provides the feature set we are looking at. Many of the problems are
issues irregardless of if you use operators or comprehensions, the problem
comes in with lists, more specifically lists of lists, themselves.
but it doesn't necessarily mesh with all the other ideas being thrown
around. With that in mind, how about + to put a list in the list, and |
to
put the list's contents in the list w/ overlap and * to copy contents w/o
overlap... In that case:
[1..100] + [25..75] = [1..100, [25..75]]
[1..100] | [25..75] = [1..100, 25..75] // if this operator were
implemented
with overlap
[1..100] * [25..150] = [1..150] // if this operator were implemented with
no
overlap
How you would implement the list inside of a list, and what operator - if
any - to remove items from the list, is another story...
Thanks,
Michael C.