Dennis Ritchie -- An Appreciation

I

ImpalerCore

On Tue, 2011-11-29, Joe keane wrote:

...



Operator overloading ties in with many of the other C++ features -- I
don't think it would be very useful as an isolated feature.

It depends on how you view the difference between something like

c_day_duration c_date_subtract( struct c_greg_date date1,
struct c_greg_date date2 );

vs

c_day_duration operator-( struct c_greg_date date1,
struct c_greg_date date2 );

I would be lying if I didn't desire this kind of overloading at some
verbose points in my code, at least for struct types where
mathematical operations made some sense. But I can certainly get by
without it. The point is that I don't think one would need a class
abstraction to make use of it.

Best regards,
John D.
 
I

Ian Collins

Sorry, but it is NOT useful. In those other languages, it is a curse. It
leads to many bugs, and plenty of confusing code where it is difficult to
tell what a simple-looking line of code is actually doing without digging
through piles of other code to track down the relevant overloading.

That statement could be make about just about any language feature!

If you want a counter augment, look at all the baggage that had to be
added to C to support complex numbers.
Overloading is not the C way. It is not standard C and not portable.

That I agree with.
 
J

jacob navia

Le 30/11/11 23:10, ImpalerCore a écrit :
It depends on how you view the difference between something like

c_day_duration c_date_subtract( struct c_greg_date date1,
struct c_greg_date date2 );

vs

c_day_duration operator-( struct c_greg_date date1,
struct c_greg_date date2 );

I would be lying if I didn't desire this kind of overloading at some
verbose points in my code, at least for struct types where
mathematical operations made some sense. But I can certainly get by
without it. The point is that I don't think one would need a class
abstraction to make use of it.

You don't. lcc-win has operator overloading without any classes or other
"goodies".

For instance

z = (a+b-1)/(b*(b-a));

or

z = div(subtract(sum(a,b),1),mult(b,subtract(b,a))))


Which you prefer?

This is so OBVIOUS that the people arguing against it look
completely ridiculous.
 
J

jacob navia

Le 30/11/11 23:09, Quentin Pope a écrit :
Sorry, but it is NOT useful. In those other languages, it is a curse. It
leads to many bugs, and plenty of confusing code where it is difficult to
tell what a simple-looking line of code is actually doing without digging
through piles of other code to track down the relevant overloading.

Operator overloading work best with number and numerical data.

Please consider:


z = (a+b-1)/(b*(b-a));

or

z = div(subtract(sum(a,b),1),mult(b,subtract(b,a))))


Which you prefer?

This is so OBVIOUS that the people arguing against it look
completely ridiculous.


Overloading is not the C way. It is not standard C and not portable.

This isn't a reason, an argument or whatever. It is just

"That's the way it is".

And when somebody asks:

but WHY should we go on like that?

you answer

"That's the way it is".
C has a much better solution - explicit function calls.

Yes, see above:

z = div(subtract(sum(a,b),1),mult(b,subtract(b,a))))

and I assumed that the result is returned in the stack... what is
a horror with bignumbers...

Otherwise you have:

tmp1 = sum(a,b);
tmp1 = subtract(tmp1,1);
tmp2 = subtract(b,a);
tmp2 = mult(b,tmp2);
z = div(tmp1,tmp2);

Even better!

Look at GMP for a
good example of a C interface for numerical types without any need for
overloading.

Of course, it is alwayssupposed that the real users will
use the overloaded ibterface that calls back to C.
 
I

Ian Collins

Le 30/11/11 23:10, ImpalerCore a écrit :

You don't. lcc-win has operator overloading without any classes or other
"goodies".

For instance

z = (a+b-1)/(b*(b-a));

Do you use pass by value, or do you pass by reference under the hood?
 
J

jacob navia

Le 01/12/11 00:21, Ian Collins a écrit :
Do you use pass by value, or do you pass by reference under the hood?

Of course by reference... qfloats are 120 bytes long...
For a function of 2 arguments you would have to push 240 bytes
each time... impossible.
 
J

James Kuyper

Sorry, but it is NOT useful. In those other languages, it is a curse. It
leads to many bugs, and plenty of confusing code where it is difficult to
tell what a simple-looking line of code is actually doing without digging
through piles of other code to track down the relevant overloading.

Any feature of any language can be misused. I you have to look "through
piles of other code to track down the relevant overloading", in order to
know what the overload is doing, then it should not have been overloaded
- it's just that simple.

The expression a + b gives the result of adding a to b; if the meaning
of that phrase is not crystal clear for the relevant type(s), WITHOUT
having to read the code or documentation for the operator overload, then
operator+() should never have been overloaded for that(those) type(s).

This design rule is frequently violated; that's not exactly an uncommon
feature of good design rules.

Vectors, arrays, complex numbers, quaternions, tensors in general are
all examples of types for which the meaning of operator+() is crystal
clear to anyone who knows enough about those types to justify writing
code that uses them. operator*() is a trickier matter for most of those
types, because they have at least two different plausible meanings for
a*b. That's an argument for things like .outer_product() and
..inner_product(), etc.
Overloading is not the C way. It is not standard C and not portable.

Of course, that goes without saying.
 
J

James Kuyper

kind of my point ....

I think operator overloading is a gain of about zero.

I've never written in C and been like 'darn it, if i only had operator
overloading!'.

I have (except for the minced oath - and I didn't use a real oath, either).

....
The opereator overloading is a candy bar.

C's scalar types represent characters, numbers, or pointers. It also has
derived types that are arrays, and functions. Operator overloads can
make a class type look like one of those kinds of types, and they can be
a very useful, reasonable thing to define, if the class represents an
extension to the idea of characters, numbers, pointers, arrays or
functions. When used for any other purpose, they tend to obfuscate code,
rather than clarify it. Any member function whose meaning doesn't fit
the usual meaning of a given operator should not be implemented as an
overloaded of that operator.

The use of >> and << for I/O, and the use of + for string concatenation,
both clearly violate this design principle, and I cannot defend them.
However, but by now such usage is a well-established convention, and
unlikely to be changed.
 
N

Nick Keighley

Le 30/11/11 23:09, Quentin Pope a écrit :

read up on "blub" or the The Sapir-Whorf Hypothesis


I think Jacob has demonstrated you can do useful things with operator
overloading in a C-like language


I keep on hearing this. But if you confine it to arithmetic types it
seems pretty useful. Lots of programming lanaguage features can be
abused. Perhaps C should stop using pointers?
Operator overloading work best with number and numerical data.

Please consider:

z = (a+b-1)/(b*(b-a));

or

z = div(subtract(sum(a,b),1),mult(b,subtract(b,a))))

Which you prefer?

the LISP people would say the second one was more consistent but would
be even better in proper prefix notation...

(set! z (/ (- (+ a b) 1) (* b (- b a))))

but of course /they/ are crazy...

<snip>
 
N

Nick Keighley

I have (except for the minced oath - and I didn't use a real oath, either).

...


C's scalar types represent characters, numbers, or pointers. It also has
derived types that are arrays, and functions. Operator overloads can
make a class type look like one of those kinds of types, and they can be
a very useful, reasonable thing to define, if the class represents an
extension to the idea of characters, numbers, pointers, arrays or
functions.

operator overloading in C++ can also be used for conversion operators
as well.
 
J

JohnF

Nick Keighley said:
read up on "blub" or the The Sapir-Whorf Hypothesis

Very interesting. I've been aware of Sapir-Whorf for
a long time regarding linguistics, but hadn't been
aware of its interpretation with respect to programming
languages. Googling blub and sapir-whorf, and then reading
http://en.wikipedia.org/wiki/Linguistic_relativity
brings the following question to mind:
Doesn't Church's thesis and Turing completeness
kind of take the steam out of any "linguistic relativity"
idea applied to programming languages? At best, there's
maybe some "stylistic relativity", depending on how you
prefer designing/writing code. But regarding what's
computable, and what computable functions a given language
can express, that's pretty much a done deal. No???
 
M

Malcolm McLean

The expression a + b gives the result of adding a to b; if the meaning
of that phrase is not crystal clear for the relevant type(s), WITHOUT
having to read the code or documentation for the operator overload, then
operator+() should never have been overloaded for that(those) type(s).
mytype x = 1,
mytype y;

x = sqrt(-x);
y = 0 * x;

What should y be? You can't always be crystal clear.
 
J

James Kuyper

mytype x = 1,
mytype y;

x = sqrt(-x);
y = 0 * x;

What should y be? You can't always be crystal clear.

If the overloaded operator (or function) can't be crystal clear, don't
overload it. That's my point.

Offhand, I can't think of any type for which it would be reasonable to
overload all of the operators used above, and sqrt(), unless the value
of 'y' came out as (mytype)0 in the end - but I wouldn't be surprised if
you could come up with a reasonable counter-example (it's trivial, of
course, to come up with an unreasonable counter-example).

Your example is NOT clear solely because the name 'mytype' conveys no
special meaning. Good design is not just about the interface of a type,
but also involves the name of the type. The only thing that particular
type name conveys is information about the ownership of the type. If the
name of the type doesn't convey the information the user needs to know
in order to understand what the above code means, then it wasn't
properly named, or the user doesn't know enough about the meaning of the
type to justify using it.
 
J

James Kuyper

operator overloading in C++ can also be used for conversion operators
as well.

Yes, and that's something that's essential for implementation of smart
pointer types, for instance.
 
N

Nick Keighley

Very interesting. I've been aware of Sapir-Whorf for
a long time regarding linguistics, but hadn't been
aware of its interpretation with respect to programming
languages.

my own application. Though doubtless plenty of other people thought of
it first. I think there's a good reason SW is still a hypothesis; that
is that not all linguists believe it. People seem to be pretty
flexible at stretching their language to cover new situtations.
Googling blub and sapir-whorf, and then reading
   http://en.wikipedia.org/wiki/Linguistic_relativity
brings the following question to mind:
   Doesn't Church's thesis and Turing completeness
kind of take the steam out of any "linguistic relativity"
idea applied to programming languages? At best, there's
maybe some "stylistic relativity", depending on how you
prefer designing/writing code. But regarding what's
computable, and what computable functions a given language
can express, that's pretty much a done deal. No???

yes you can compute anything in any reasonable programming language
(all well known programmign languages are "reasonable" from this point
of view), but the set of computations that can be computed easily and
conventiently is much smaller.

I /could/ write a Lisp compiler in COBOL but I suspect I wouldn't
enjoy it.

If I'm using an old dialect of Basic I won't automatically think of
recursion as a way to solve a problem.

I'm deliberatly learning languages outside the imperitive/OO camp. It /
does/ change the way you look at things.
 
W

Willem

JohnF wrote:
) Doesn't Church's thesis and Turing completeness
) kind of take the steam out of any "linguistic relativity"
) idea applied to programming languages? At best, there's
) maybe some "stylistic relativity", depending on how you
) prefer designing/writing code. But regarding what's
) computable, and what computable functions a given language
) can express, that's pretty much a done deal. No???

No.

What Turing is saying, in a sense, is that you can always emulate the
features of language A in language B, and therefore you can compute the
same things. However, you have to be familiar with language A to be able
to emulate its features in language B.

The upside to this is: if you learn a very different language, such as lisp
or haskell or prolog, or even ruby, you can then go back to C and implement
the new features that make programming so much easier, but which you never
knew existed before you learned those languages.


Claiming that it is only "stylistic relativity" is like claiming that the
invention of the train really wasn't that important, because people could
get where they wanted already simply by walking.


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
 
J

Joel C. Salomon

Do you use pass by value, or do you pass by reference under the hood?

Of course by reference... qfloats are 120 bytes long...
For a function of 2 arguments you would have to push 240 bytes
each time... impossible.[/QUOTE]

When I first read about lcc's operator overloading, these two aspects
struck me as not in the "spirit of C": function names with operator
symbols inside them and the invention of reference parameters.

[As an aside, to Jacob: How much complexity is added to the grammar to
accommodate things like "operator+"? Is this as intrusive as it seems
on first blush?]

That said, operator overloading is a handy idea. Before he left Bell
Labs, Ken Thompson added operator overloading to the Plan 9 C compiler.
I believe this extension is still available in the 8c/6c C compilers
distributed with Google Go. It's... different than Jacob's C++-inspired
idea. See Jim McKie's quoting Ken's documentation at
<http://9fans.net/archive/2001/05/482>.

I think operator overloading is a nice feature (in either form); YMMV as
to which (if any) is a better fit to C.

--Joel
 
8

88888 Dihedral

JohnF wrote:
) Doesn't Church's thesis and Turing completeness
) kind of take the steam out of any "linguistic relativity"
) idea applied to programming languages? At best, there's
) maybe some "stylistic relativity", depending on how you
) prefer designing/writing code. But regarding what's
) computable, and what computable functions a given language
) can express, that's pretty much a done deal. No???

I agree with you. But Turing died to young, I'll pay my regrets to the mass
not to understand his works in time. H was living like another famous artiest
who cut his own ear.
 
J

Joe keane

Until you you have to implement a specialised numeric type or a smart
pointer.

I have done so several times in C, and i chose not to use overloading.

Of course i like to write in C, then make a C++ wrapper:

extern "C"
{
int qz_add(struct qz *x, struct qz *y, struct qz *res);
int qz_addw(struct qz *x, struct qz *y, struct qz *res, int w);
int qz_mul(struct qz *x, struct qz *y, struct qz *res);
...
}

class Qz
{
struct qz p;

inline int add(Qz& x, Qz& y)
{ return qz_add(&x.p, &y.p, &this->p); }
inline int addw(Qz& x, Qz& y, int w)
{ return qz_addw(&x.p, &y.p, &this->p, w); }
inline int mul(Qz& x, Qz& y);
{ return qz_mul(&x.p, &y.p, &this->p); }
...

[inline Qz operator +(Qz& x, Qz& y)
{ Qz tmp; (void) tmp.add(x, y); return tmp; }
[inline Qz operator +()(Qz& x, Qz& y, int w)
{ Qz tmp; (void) tmp.addw(x, y, w); return tmp; }
inline Qz operator *(Qz& x, Qz& y)
{ Qz tmp; (void) tmp.mul(x, y); return tmp; }]
...
};

[throw in some 'const']
 
I

Ian Collins

I have done so several times in C, and i chose not to use overloading.

You didn't have a choice.
Of course i like to write in C, then make a C++ wrapper:

How odd.
extern "C"
{
int qz_add(struct qz *x, struct qz *y, struct qz *res);
int qz_addw(struct qz *x, struct qz *y, struct qz *res, int w);
int qz_mul(struct qz *x, struct qz *y, struct qz *res);
...
}

class Qz
{
struct qz p;

inline int add(Qz& x, Qz& y)
{ return qz_add(&x.p,&y.p,&this->p); }
inline int addw(Qz& x, Qz& y, int w)
{ return qz_addw(&x.p,&y.p,&this->p, w); }
inline int mul(Qz& x, Qz& y);
{ return qz_mul(&x.p,&y.p,&this->p); }
...

[inline Qz operator +(Qz& x, Qz& y)

So you avoided operator overloading by using it?
{ Qz tmp; (void) tmp.add(x, y); return tmp; }
[inline Qz operator +()(Qz& x, Qz& y, int w)
{ Qz tmp; (void) tmp.addw(x, y, w); return tmp; }
inline Qz operator *(Qz& x, Qz& y)
{ Qz tmp; (void) tmp.mul(x, y); return tmp; }]
...
};

[throw in some 'const']

I hope you C is better than your C++.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,578
Members
45,052
Latest member
LucyCarper

Latest Threads

Top