[comp.lang.c++] Better Encapsulation: Overload Keywords

blythe@kuhub.cc.ukans.edu (06/24/91)

In C++'s effort to encapsulate data and methods, it has missed some points.


A Proposal:	Overloading Keywords

	One of the best things about C++ is its ability to overload an
operator for a certain combination of objects.  These operators are then
implemented as a function by the compiler.  Why not keywords also?  In
specific, the selection keywords (if...else and switch) and the iteration
keywords (while, do, and for) are the only keywords I see having good
potential when overloaded.  Take the following normal code as my example:

	class An_Object 
	{
		int ready;
		...
	public:
		int status(void);
		...
	};                
	int An_Object::status(void)
	{
		return(ready);
	}
	int main(void)
	{
		An_Object object;
		...
		while(object.status())
		{
			...
		}
		...
	}

The code deciding the termination of the loop is in the object, which is good
encapsulation.  I was once told that the best objects will know everything
you plan to do with them, implemented through member functions (methods).
Notice though that the while statement is directly interacting with the
object;  the object doesn't know how to execute a loop so the while is
obviously needed.  What I am saying is that the object should know how to 
interact with the while, which is even better encapsulation than the above
example.  Take the following code for example:

	class An_Object 
	{
		int ready;
		...
	public:
		An_Object keyword while;
		...
	};
	An_Object::keyword while
	{
		ready;		//statement to be evaluated by a while loop
	}
	int main(void)
	{
		An_Object object;
		...
		while(object)	//better encapsulation
		{
			...
		}
		...
	}

Every time the while loop is executed the statement defined inside the
object is evaluated, it's that simple for the while.  Overloading other 
keywords may prove to be a little more challenging, but not much.
	Overloaded operators are implemented as functions by C++ compilers.  
Overloaded keywords could be implemented as functions placed inside the 
real keywords or the statements could simply be placed in the correct place
by a preprocessor.

Overloaded operators let us get away from code like this:
		result = add(complex_number_1, complex_number_2);
to simply:
		result = complex_number_1 + complex_number_2;
		
Overloaded keywords could let us get away from code like this:
		while(object.status()) {...}
to simply:
		while(object) {...}


	Thank you for your time.  Any comments are welcome.

	Garrett Arch Blythe.

barmar@think.com (Barry Margolin) (06/24/91)

In article <1991Jun23.223737.31644@kuhub.cc.ukans.edu> blythe@kuhub.cc.ukans.edu writes:
>	One of the best things about C++ is its ability to overload an
>operator for a certain combination of objects.  These operators are then
>implemented as a function by the compiler.  Why not keywords also?  In
>specific, the selection keywords (if...else and switch) and the iteration
>keywords (while, do, and for) are the only keywords I see having good
>potential when overloaded.

If C++ had a real boolean type, and required the test expression of an
"if", "while", "do", and "for" statements to be of this type (perhaps with
a built-in conversion from integral and pointer types, for
back-compatibility) then much of this could be done by defining a
conversion from the class to boolean.

The "for" statement is a bit more complex if you want the overloading to be
able to take over the initialization and stepping as well.  You'd probably
need an alternative syntax; maybe:

	for (<lval> = <expression>)
	  <statement>

where <expression> should evaluate to a class object.  The interface would
probably be similar to iterators in CLU.  I'm not sure how you could
combine traditional "for" loops with the overloaded kind in one statement.

I'm not sure what an overloaded "switch" statement would be like.  Would
the labels still be integer constants?  If so, then a conversion from the
class to int would be sufficient.

Of course, all these suggestions about using conversions only work if the
same conversion is useful in all the contexts.  If you want the test in a
"while" statement to be true in a different case from the test in an "if"
statement, it won't work.  However, I think that would be a very bad idea.
The equivalence between

	while (<expr>) <statement>

and

<label>: if (<expr>) {
	    <statement>
	    goto <label>;
	 }

is generally considered fundamental; choices between the various forms of
control flow are supposed to be based on style, not semantics.
-- 
Barry Margolin, Thinking Machines Corp.

barmar@think.com
{uunet,harvard}!think!barmar

alanb@sdl.mdcbbs.com (06/25/91)

In article <1991Jun24.163530.14631@Think.COM>, barmar@think.com (Barry Margolin) writes:
> In article <1991Jun23.223737.31644@kuhub.cc.ukans.edu> blythe@kuhub.cc.ukans.edu writes:
>>	One of the best things about C++ is its ability to overload an
>>operator for a certain combination of objects.  These operators are then
>>implemented as a function by the compiler.  Why not keywords also?  In
>>specific, the selection keywords (if...else and switch) and the iteration
>>keywords (while, do, and for) are the only keywords I see having good
>>potential when overloaded.
> 
> If C++ had a real boolean type, and required the test expression of an
> "if", "while", "do", and "for" statements to be of this type (perhaps with
> a built-in conversion from integral and pointer types, for
> back-compatibility) then much of this could be done by defining a
> conversion from the class to boolean.
>
[Discussion of "for" omitted. CLU style iterators would be nice though.]

We have a C preprocessor that provides a boolean type and enforces the rule
that test expressions must be booleans (e.g. if (pointer != NULL), not
if (pointer)). 
(Now we use C++, we just have a coding convention).

If you allow conversion from integral and pointer types, you have lost the 
type enforcement you might want, so why not just define
operator (void *) for the classes you want to use in while loops?
Something like

{ if (my_status) return this; else return NULL );

if (anobject) { foo(); }
is now equivalent to
if (anobject.status()) { foo(); }
and while uses the same test as if.

(this assumes you never want to coerce to a pointer other than when your
if/while condition is true - in many cases this is reasonable.)

(The preprocessor also provided function prototypes before ANSI C was around, 
and workarounds for assorted platform compiler bugs - I'm not claiming that
just having a boolean type is necessarily worth the effort).

> Barry Margolin, Thinking Machines Corp.
> 
> barmar@think.com
> {uunet,harvard}!think!barmar

Alan Braggins       alanb@sdl.mdcbbs.com
"Any resemblance between these opinions,..."

rae@alias.com (Reid Ellis) (06/26/91)

<blythe@kuhub.cc.ukans.edu> writes:
|while(object)	//better encapsulation
|{
|	...
|}
...
|Overloaded keywords could let us get away from code like this:
|		while(object.status()) {...}
|to simply:
|		while(object) {...}

This can easily be accomplished right now by providing an "operator
void *" method, like the iostream classes do.  This is why you can say:

	while(cin)
	{
		cin >> buf;
		// etc..
	}


					Reid
--
Reid Ellis                                            
rae@utcs.toronto.edu        ||           rae@alias.com
CDA0610@applelink.apple.com ||  +1 416 362 9181 [work]

marc@dumbcat.sf.ca.us (Marco S Hyman) (06/28/91)

In article <1991Jun25.224022.20072@alias.com> rae@alias.com (Reid Ellis) writes:
 > This can easily be accomplished right now by providing an "operator
 > void *" method, like the iostream classes do.  This is why you can say:
 > 
 > 	while(cin)
 > 	{
 > 		cin >> buf;
 > 		// etc..
 > 	}

Many have recommended overloading void * to do this instead of overloading int
(which happens to be my favorite).   Is there a particular reason for
prefering void * to int?

// marc
-- 
// home: marc@dumbcat.sf.ca.us		pacbell!dumbcat!marc
// work: marc@ascend.com		uunet!aria!marc