![](/i/fill.gif) |
![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
> -----Original Message-----
> From: Warp [mailto:war### [at] tag povray org]
> Ah, so this extension can be used for operator overloading in C#?
> Nobody told me that before.
Actually, it can't, but that's irrelevant.
You said:
"In other words, you simply can write the same thing with a slightly
different syntax, but otherwise there's no difference. I really fail to
see the usefulness of this."
In other words, you see no usefulness in having syntactic sugar. I
think it's useful.
...Ben Chambers
www.pacificwebguy.com
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Chambers wrote:
> In other words, you see no usefulness in having syntactic sugar. I
> think it's useful.
Especially when you want to chain methods together to make things work.
Writing
myCollection.Select(...).Group(...).Transform(...).Sort(...).Output()
is a lot more clear than
Sort(Group(myCollection.Select(...)).Transform(...)).Output()
just like writing
cout << 123 << endl << mystuff.xyz() << endl
is more clear than
cout.write(cout.write(123).endl(), mystuff.xyz()).endl()
or something like that.
Plus, it interacts with other syntax of the language that the compiler turns
into syntax like this. When your C++ sorting template has to know whether
the right call is myThing.compare(otherThing) or
MyUtil.compare(myThing,otherThing), it gets messy. That's exactly what this
is for, so it's pretty much just like what operator overloading is for.
--
Darren New, San Diego CA, USA (PST)
"Ouch ouch ouch!"
"What's wrong? Noodles too hot?"
"No, I have Chopstick Tunnel Syndrome."
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Chambers <ben### [at] pacificwebguy com> wrote:
> Actually, it can't, but that's irrelevant.
> You said:
> "In other words, you simply can write the same thing with a slightly
> different syntax, but otherwise there's no difference. I really fail to
> see the usefulness of this."
> In other words, you see no usefulness in having syntactic sugar. I
> think it's useful.
No. What I said was that I don't see usefulness IN THIS CASE. The
difference is practically nonexistent. It's only in reordering of
names.
--
- Warp
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Warp wrote:
> No. What I said was that I don't see usefulness IN THIS CASE. The
> difference is practically nonexistent. It's only in reordering of
> names.
It lets code generation tools (and LINQ) generate code in one pattern
(distinguished caller syntax) for both methods defined on the class and
methods defined outside the class.
It gives you the same benefit that having the name "operator<" available
does. If you want to do a sort in C of integers, you call
qsort(myArray, myCompare);
int myCompare(int a, int b) {return a < b;}
In C++ you call
qsort(myArray, operator< );
or some such syntax, but without the need to have a specifically named
function just to wrap up the < operator.
Plus, of course, it lets the same member-syntax function mean different
things in different places in your code. Here, xyz.Select(...) means one
function, while there xyz.Select(...) means a different function. This is
important when "here" and "there" are two compiled libraries from two
different sources and you're automatically generating the code.
--
Darren New, San Diego CA, USA (PST)
"Ouch ouch ouch!"
"What's wrong? Noodles too hot?"
"No, I have Chopstick Tunnel Syndrome."
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Darren New wrote:
> In C++ you call
> qsort(myArray, operator< );
> or some such syntax, but without the need to have a specifically named
> function just to wrap up the < operator.
std::sort(myArray) is all you need. Guess *how* the operator< is used by
default?
template <typename T> bool less(const T& x, const T& y) {
return x < y;
}
std::sort uses std::less as the default sorting function.
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Nicolas Alvarez wrote:
> Darren New wrote:
>> In C++ you call
>> qsort(myArray, operator< );
>> or some such syntax, but without the need to have a specifically named
>> function just to wrap up the < operator.
>
> std::sort(myArray) is all you need. Guess *how* the operator< is used by
> default?
>
> template <typename T> bool less(const T& x, const T& y) {
> return x < y;
> }
>
> std::sort uses std::less as the default sorting function.
>
Yep. And now what do you do if the "less" you want to use is actually a
member function of type T? What if the "less" you want to use is
class MyDate {
bool comesBefore(const MyDate& otherDate);
}
--
Darren New, San Diego CA, USA (PST)
"Ouch ouch ouch!"
"What's wrong? Noodles too hot?"
"No, I have Chopstick Tunnel Syndrome."
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Darren New <dne### [at] san rr com> wrote:
> Yep. And now what do you do if the "less" you want to use is actually a
> member function of type T? What if the "less" you want to use is
> class MyDate {
> bool comesBefore(const MyDate& otherDate);
> }
You create a comparator and give that to std::sort. A comparator can be,
for example, a (regular) function which takes two elements and returns bool.
--
- Warp
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Warp wrote:
> Darren New <dne### [at] san rr com> wrote:
>> Yep. And now what do you do if the "less" you want to use is actually a
>> member function of type T? What if the "less" you want to use is
>> class MyDate {
>> bool comesBefore(const MyDate& otherDate);
>> }
>
> You create a comparator and give that to std::sort. A comparator can be,
> for example, a (regular) function which takes two elements and returns bool.
And that's precisely what the C# syntax avoids you having to do, in the
other direction.
It's in there most likely because of LINQ, which is a bit of the language
that turns something that looks a bit like SQL into something that looks
like method calls. If there were two syntaxes for each possible call that
LINQ generated, you'd have a mess. So now
int xyz(this T alpha, U beta)
is a valid overloaded function candidate for
alpha.xyz(beta)
when alpha is a T and beta is a U.
--
Darren New, San Diego CA, USA (PST)
"Ouch ouch ouch!"
"What's wrong? Noodles too hot?"
"No, I have Chopstick Tunnel Syndrome."
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Darren New <dne### [at] san rr com> wrote:
> Warp wrote:
> > Darren New <dne### [at] san rr com> wrote:
> >> Yep. And now what do you do if the "less" you want to use is actually a
> >> member function of type T? What if the "less" you want to use is
> >> class MyDate {
> >> bool comesBefore(const MyDate& otherDate);
> >> }
> >
> > You create a comparator and give that to std::sort. A comparator can be,
> > for example, a (regular) function which takes two elements and returns bool.
> And that's precisely what the C# syntax avoids you having to do, in the
> other direction.
So instead of writing a function which takes two objects and returns
a bool, you write a "member function" which which called with one object,
takes another as parameter, and returns bool?
I'm still not seeing the huge difference.
--
- Warp
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Warp wrote:
> So instead of writing a function which takes two objects and returns
> a bool, you write a "member function" which which called with one object,
> takes another as parameter, and returns bool?
Yes.
> I'm still not seeing the huge difference.
That it's the same syntax regardless of whether it's a member function or a
function the user added later, which makes it easier for code generators.
Just like having operator= on classes makes it easier to write templates
than if you had to know whether to use (i = j) for integers and i.equals(j)
for complex numbers.
That you don't have to remember which functions were added after the fact
and which functions were part of the original class.
That you can chain a sequence of calls together that are both members and
non-members without having to skip back and forth around the line to figure
out what order they get evaluated in.
Writing
myCollection.Select(...).Group(...).Transform(...).Sort(...).Output()
is a lot more clear than
Sort(Group(myCollection.Select(...)).Transform(...)).Output()
just like writing
a = b + c * d - e
is more clear than
a = subtract(add(b, multiply(c, d)), e)
It isn't a "huge" difference, any more than operator overloading makes a
"huge" difference to the language. But that's why it's there. If you don't
see why it's a benefit, you either should just let it go, or read the C#
spec that relates it to the other features of C#.
--
Darren New, San Diego CA, USA (PST)
"Ouch ouch ouch!"
"What's wrong? Noodles too hot?"
"No, I have Chopstick Tunnel Syndrome."
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |