[net.lang.c] Boolean Operators Slighted in C

gwyn@brl-smoke.ARPA (Doug Gwyn ) (04/30/86)

In article <838@ihwpt.UUCP> knudsen@ihwpt.UUCP (mike knudsen) writes:
>Has anyone else noticed that Boolean types and operators
>have less than full citizenship in C?  Examples:
>...
>(3) There is no boolean data type.  No big gripe;
>lots of us say "typedef short bool" in our .h files.

Technically, there are no true Boolean data types in C.
Ints (NOT shorts) are made to serve when a Boolean would
be called for.  I have always considered this a deficiency,
but (except for getting "lint" to cooperate) it can be
remedied by the programmer being careful to keep Boolean
usages distinct from integer usages.  For example, treat
the result of a relational expression as Boolean, not as
a 1 or a 0.  I find that carefully maintaining the
distinction contributes to code correctness and
maintainability.

I generally frown on C language extension via the
preprocessor (as in a recent Byte article), but I make an
exception for Booleans.  The same standard header file
that I mentioned a few days ago (that defines "void" for
machines that don't have it, etc.) contains the following:

typedef int	bool;			/* boolean data */
#define 	false	0
#define 	true	1

flip@osu-cgrg.UUCP (Flip Phillips) (04/30/86)

	[ ... boolean gripes ... ]
> 		
> (3) There is no boolean data type.  No big gripe;
> lots of us say "typedef short bool" in our .h files.

typedef char bool;	uses less space on some machines.
-- 

	Flip Phillips {ucbvax,decvax}!cbosg!osu-cgrg!flip
	Computer Graphics Research Group, The Ohio State University

kwh@bentley.UUCP (KW Heuer) (04/30/86)

In article <838@ihwpt.UUCP> ihwpt!knudsen writes:
>(1) Found out this weekend that you can't say:
>	boolvar ||= boolean_expression

An interesting expression.  The left side of the assignment would have to be
evaluated first, and if already set, do nothing.  I presume the reason this is
omitted is because it's normally written "if (v || e) v=1;" or "if (!v && e)
v=1;" rather than "v = v || e".

Btw, you can't have *all* operators extended with "=".  How would you write
"v = v < e;"?  (Not that it's useful.)

>(2) There isn't any ^^ (XOR) operator either, as in
>	if(divisor <0) ^^ (dividend <0)
>		quotient = -quotient;

There is, but it's spelled "!=".  (Presumably more efficient than "^", though
I think either one should work with a smart compiler.)

>(3) There is no boolean data type.  No big gripe;
>lots of us say "typedef short bool" in our .h files.

I'd assume either "char" (for space) or "int" (for time).  "short" probably
gives you the worst of both worlds.

However, a true boolean datatype would have a couple of advantages:

o  Multiple flag variables with local scope and no address operator (e.g.
   variables declared "register bool") could be packed into a single word.

o  "++x" and "--x" could be defined as "set" and "clear"; "x++" and "x--"
   would then be "test and (set|clear)".  This would obviate such things as
   "if (!flag) { flag=1; printmsg(); }".

Karl W. Z. Heuer (ihnp4!bentley!kwh), The Walking Lint

tps@sdchem.UUCP (Tom Stockfisch) (05/03/86)

In article <778@bentley.UUCP> kwh@bentley.UUCP writes:
>In article <838@ihwpt.UUCP> ihwpt!knudsen writes:
>>(2) There isn't any ^^ (XOR) operator either, as in
>
>There is, but it's spelled "!=".  (Presumably more efficient than "^", though
>I think either one should work with a smart compiler.)
>

Not quite the same.
	3 ^^ 4
would evaluate as 0,
	3 != 4
evaluates as 1.

-- Tom Stockfisch, UCSD Chemistry

jimc@ucla-cs.ARPA (Jim Carter) (05/03/86)

In article <778@bentley.UUCP> kwh@bentley.UUCP (KW Heuer) writes:
>Btw, you can't have *all* operators extended with "=".  How would you write
>"v = v < e;"?  (Not that it's useful.)
I think it's useful!  As written, of course, it's semantically invalid,
but what you really mean is "v <= e" (sic) or, to demonstrate where it's
really useful,
     array[horrendous] [subscript] [list] <= bigexpr;
  rather than 
     if (array[h][s][l] < bigexpr) array[h][s][l] = bigexpr;
Now "<=" already means something else so this syntax is not acceptable.
How about "v < = e" with a mandatory blank?  This is atrocious human
engineering but at least is parseable.  Anybody have any better ideas?
-- 
James F. Carter            (213) 206-1306
UCLA-SEASnet; 2567 Boelter Hall; 405 Hilgard Ave.; Los Angeles, CA 90024
UUCP:...!{ihnp4,ucbvax,{hao!cepu}}!ucla-cs!jimc  ARPA:jimc@locus.UCLA.EDU

greg@utcsri.UUCP (Gregory Smith) (05/03/86)

In article <778@bentley.UUCP> kwh@bentley.UUCP (KW Heuer) writes:
>In article <838@ihwpt.UUCP> ihwpt!knudsen writes:
>>(1) Found out this weekend that you can't say:
>>	boolvar ||= boolean_expression
>
>An interesting expression.  The left side of the assignment would have to be
>evaluated first, and if already set, do nothing.  I presume the reason this is
>omitted is because it's normally written "if (v || e) v=1;" or "if (!v && e)
>v=1;" rather than "v = v || e".
>
Interesting - I was going to suggest if(e)v=1; but that's not the same thing.
I was surprised to find out recently that ` i >> = 1 ' is legal, as opposed to
`>>='. I really think this should produce at least a warning. (4.2BSD)
>
>>(2) There isn't any ^^ (XOR) operator either, as in
>>	if(divisor <0) ^^ (dividend <0)
>>		quotient = -quotient;
>
>There is, but it's spelled "!=".  (Presumably more efficient than "^", though
>I think either one should work with a smart compiler.)

If I had $0.02 for everything that people have said should be done by a smart
compiler... :-) :-) I know, that's what compilers are for.

But it's not quite the same thing. 2 ^^ 1 should be 0, and 2!=1 is 1, and 2^1
is 3. Of course, in the example given, that won't happen. In any case, you
can always say !a != !b.

On the subject of operators, someone said a while back that they had a
compiler with commented-out code to support '/\' and '\/' ( max and min )
operators - and that they had qualms about activating it and then writing
non-portable code. I suggest that they activate it, and then write

#define min(a,b) ((a)\/(b))
#define max(a,b) ((a)/\(b))

in a header, to allow portability. Presumably, the code produced by these
operators should be somewhat better than a>b?a:b. Of course, you still
have to avoid writing min( array[atoi(x1)], i+cindex[getc(file)]) :-).

-- 
"For every action there is an equal and opposite malfunction"
----------------------------------------------------------------------
Greg Smith     University of Toronto      UUCP: ..utzoo!utcsri!greg

kwh@bentley.UUCP (KW Heuer) (05/05/86)

In article <778@bentley.UUCP> I wrote:
>A true boolean datatype would have a couple of advantages:
>
>o  Multiple flag variables with local scope and no address operator (e.g.
>   variables declared "register bool") could be packed into a single word.
>
>o  "++x" and "--x" could be defined as "set" and "clear"; "x++" and "x--"
>   would then be "test and (set|clear)".  This would obviate such things as
>   "if (!flag) { flag=1; printmsg(); }".

I forgot to mention one other:

o  A function returning a bool could be implemented on some machines by
   setting the condition codes instead of storing a full integer value in
   the return register.

Karl W. Z. Heuer (ihnp4!bentley!kwh), The Walking Lint

ark@alice.UucP (Andrew Koenig) (05/05/86)

>>Btw, you can't have *all* operators extended with "=".  How would you write
>>"v = v < e;"?  (Not that it's useful.)
> I think it's useful!  As written, of course, it's semantically invalid,
> but what you really mean is "v <= e" (sic) or, to demonstrate where it's
> really useful,
>     array[horrendous] [subscript] [list] <= bigexpr;
>  rather than 
>     if (array[h][s][l] < bigexpr) array[h][s][l] = bigexpr;
> Now "<=" already means something else so this syntax is not acceptable.
> How about "v < = e" with a mandatory blank?  This is atrocious human
> engineering but at least is parseable.  Anybody have any better ideas?

You have suggested that

	v < = e

should mean

	if (v < e) v = e

but this is not parallel to the other `=' operators.  Instead,
if it means anything at all it should mean

	v = v < e

In other words, afterwards v is either 1 or 0 depending on the
value of e and the previous value of v.

But I can't imagine when I'd ever want to use this in practice.
Maybe we should just leave the language alone.

ggs@ulysses.UUCP (Griff Smith) (05/06/86)

> In article <778@bentley.UUCP> kwh@bentley.UUCP (KW Heuer) writes:
> >Btw, you can't have *all* operators extended with "=".  How would you write
> >"v = v < e;"?  (Not that it's useful.)
> I think it's useful! ...
... [ deleted usual arguments for "op-assign" operators ]
> James F. Carter            (213) 206-1306
> UCLA-SEASnet; 2567 Boelter Hall; 405 Hilgard Ave.; Los Angeles, CA 90024
> UUCP:...!{ihnp4,ucbvax,{hao!cepu}}!ucla-cs!jimc  ARPA:jimc@locus.UCLA.EDU

I think the quality of suggestions is degenerating rapidly.  This is a
blatant type clash.  The "op-assign" interpretation of " <= " is
self-contradictory nonsense.  The expression "v < e" has the
(nonexistent) type "boolean", which implies that the destination is
also boolean.  But that implies that you are using a boolean variable
in the " < " relation, which would be nonsense if "bool" were a real
type.

Instead of proposing yet another obfuscation of the language, why don't
we discuss ways that we can simplify and improve the clarity of our
coding style within the confines of the current language.  Better yet;
quit talking, and do something about it.
-- 

Griff Smith	AT&T (Bell Laboratories), Murray Hill
Phone:		(201) 582-7736
Internet:	ggs@ulysses.uucp
UUCP:		ulysses!ggs  ( {allegra|ihnp4}!ulysses!ggs )

levy@ttrdc.UUCP (Daniel R. Levy) (05/06/86)

In article <12329@ucla-cs.ARPA>, jimc@ucla-cs.ARPA (Jim Carter) writes:
>I think it's useful!  As written, of course, it's semantically invalid,
>but what you really mean is "v <= e" (sic) or, to demonstrate where it's
>really useful,
>     array[horrendous] [subscript] [list] <= bigexpr;
>  rather than
>     if (array[h][s][l] < bigexpr) array[h][s][l] = bigexpr;
>Now "<=" already means something else so this syntax is not acceptable.
>How about "v < = e" with a mandatory blank?  This is atrocious human
>engineering but at least is parseable.  Anybody have any better ideas?
>--
>James F. Carter            (213) 206-1306
>UCLA-SEASnet; 2567 Boelter Hall; 405 Hilgard Ave.; Los Angeles, CA 90024
>UUCP:...!{ihnp4,ucbvax,{hao!cepu}}!ucla-cs!jimc  ARPA:jimc@locus.UCLA.EDU

First, one could use the preprocessor to help:
#define UPMAX(i,j)	if ((i) < (j)) (i) = (j)
...
UPMAX(array[h][s][l],bigexpr);

While the output of cpp would look real messy, comp would handle this just
fine.  Of course, you lose (as with any macro which uses an argument more
than once) if the arguments have side effects such as ++ (but that isn't
the case here, right?).  Or if you know that the optimizer is not smart
enough to catch this and will evaluate the entire array[h][s][l] including
subscripts twice (as well as bigexpr), you can force temp variables:

FOO array[I][J][K];
...
FOO *atmp;
FOO btmp;
...

atmp = &(array[h][s][l]);
btmp = bigexpr;
UPMAX(*atmp,btmp);

As for the lousy human engineering in requiring extra blanks in certain
expressions, don't we have that already in C, e.g.:

a = b/*c;	/* did this mean divide b by *c, or to start a comment? */ ;
a=*b;		/* compiler complains about "ambiguous assignment" here */
-- 
 -------------------------------    Disclaimer:  The views contained herein are
|       dan levy | yvel nad      |  my own and are not at all those of my em-
|         an engihacker @        |  ployer or the administrator of any computer
| at&t computer systems division |  upon which I may hack.
|        skokie, illinois        |
 --------------------------------   Path: ..!{akgua,homxb,ihnp4,ltuxa,mvuxa,
						vax135}!ttrdc!levy

kwh@bentley.UUCP (KW Heuer) (05/06/86)

In article <12329@ucla-cs.ARPA> jimc@ucla-cs.ARPA (Jim Carter) writes:
>In article <778@bentley.UUCP> kwh@bentley.UUCP (KW Heuer) writes:
>>Btw, you can't have *all* operators extended with "=".  How would you write
>>"v = v < e;"?  (Not that it's useful.)
>
>I think it's useful!  As written, of course, it's semantically invalid,

Whoa!  The operator I was referring to was "v = v < e", which is the clear
generalization of "op=" on operator "<".  This is meaningful in C, because
the boolean result of "<" will be interpreted as an integer.  But it is not
generally useful, because one does not normally use a boolean argument to a
comparison operator like "<".

>but what you really mean is "v <= e" (sic) or, to demonstrate where it's
>really useful,
>     array[horrendous] [subscript] [list] <= bigexpr;
>  rather than 
>     if (array[h][s][l] < bigexpr) array[h][s][l] = bigexpr;

Now we're discussing "if (v < e) v = e;" which means "v = max(v,e);".  This
is indeed a useful operation, but the operator is now "max" rather than "<".

>Now "<=" already means something else so this syntax is not acceptable.
>How about "v < = e" with a mandatory blank?  This is atrocious human
>engineering but at least is parseable.  Anybody have any better ideas?

Yes.  I already mentioned this in the discussion about builtins, but I think
it bears repeating.

Introduce a new operator "<>" for max (and "><" for min).
Add the corresponding assignment operator "<>=" (and "><=") with the above
meaning.

The symbol "<>" is currently meaningless in C, though basic and pascal users
would have a fit.  "|>" and "<|" may be better choices.  "\/" and "/\" would
mimic the mathematical notation, but there may be reasons to avoid the use
of backslash in program source.

Karl W. Z. Heuer (ihnp4!bentley!kwh), The Walking Lint

rbj@icst-cmr (Root Boy Jim) (05/06/86)

> > In article <778@bentley.UUCP> kwh@bentley.UUCP (KW Heuer) writes:
> > >Btw, you can't have *all* operators extended with "=".  How would you write
> > >"v = v < e;"?  (Not that it's useful.)
> > I think it's useful! ...
> ... [ deleted usual arguments for "op-assign" operators ]
> > James F. Carter            (213) 206-1306
> > UCLA-SEASnet; 2567 Boelter Hall; 405 Hilgard Ave.; Los Angeles, CA 90024
> > UUCP:...!{ihnp4,ucbvax,{hao!cepu}}!ucla-cs!jimc  ARPA:jimc@locus.UCLA.EDU
> 
> I think the quality of suggestions is degenerating rapidly.  This is a
> blatant type clash.  The "op-assign" interpretation of " <= " is
> self-contradictory nonsense.  The expression "v < e" has the
> (nonexistent) type "boolean", which implies that the destination is
> also boolean.  But that implies that you are using a boolean variable
> in the " < " relation, which would be nonsense if "bool" were a real type.

It would be nonsense IF boolean was a real type. There is no need to
make any distinction between them. It just gets in the way of coding.
APL, the most mathematical language, treats booleans exactly like C.
THERE IS NO SUCH THING AS A BOOLEAN DATA TYPE (to which Doug Gwyn will
reply `there is no such thing as an integer either :-). There may be
boolean OPERATORS, but their range and domain is integers.

> Instead of proposing yet another obfuscation of the language, why don't
> we discuss ways that we can simplify and improve the clarity of our
> coding style within the confines of the current language.  Better yet;
> quit talking, and do something about it.

Like what? Make it like Pascal :-)

> Griff Smith	AT&T (Bell Laboratories), Murray Hill
> Phone:		(201) 582-7736
> Internet:	ggs@ulysses.uucp
> UUCP:		ulysses!ggs  ( {allegra|ihnp4}!ulysses!ggs )

A couple of wild suggestions myself. In the tradition of APL one liners,

1) Chain Lvalues. I would like to be able to write:

	((n *= 10) += (c -= '0');		instead of
	c -= '0'; n *= 10; n += c;

2) More of the same. We all know about *++p. But what if I want to jump
	more than one element? I can't write *(p += 2); Or maybe I
	want to write `p = &(i += 5).

3) Exchange operator. This has probably been discussed before, so pardon
	me if I blunder into that pit. BUT, DMR has stated that one of
	the reasons that exponentiation was left out was because no
	(or few, if any) machine could do it inline, and therefore
	all the compiler would be doing is a function call anyway.
	By the same reasoning, exchange CAN be done efficiently by
	some machines, and the hack of a temporary variable and
	three assignments is a rather stale idiom. The three
	statement XOR trick avoids the temporary, at the expense
	of execution time and clarity.

4) Allow complex statements to be considered as expressions so that
	the comma operator can be used to avoid braces, as in

	if (e) x = y, return z;

5) Allow immediate constants. Currently, there is only one special
	case, that of a character array. One can say char *p = "string";
	and have the string squirreled away and the (magic) address
	stuffed into the pointer. Why not int *p = &5; where the
	integer five is whisked away and replaced by its address.
	Sure would eliminate a lot of housekeeping variables.

6) Eliminate arrays altogether! Well not exactly, but make all
	arrays vectored in all dimensions. This would show
	those quiche eaters what a real tough language C is :-).
	Array syntax would still be available of course, but would
	be translated into glorious pointer notation. And it wouldn't
	matter whether a variable was defined differently than it
	was declared (char x[] or char *x).

7) Negative Structure Offsets. After reading those last few, I don't
	expect anyone to take me seriously, but I am serious. These
	can be real useful for such things as communications, where
	each block is wrapped in another layer. We can even use the
	entry keyword for this (quick before ANSI takes it out :-).
	The advantage is real and twofold. First, all offsets are]
	known at compile time, and second, if the data is redone,
	only the code that uses it need be recompiled. This could
	be a win, especially if other programs used the same data.

8) Allow formal arguments to be declared AFTER the opening brace.
	This would allow prioritization of register variables.

Well that should be enuf to chew on. I'm not really seriously
suggesting munging the language. This is just a thought experiment
in the art of the possible. I'm not even going to mention such
radical changes as explicit end statements (gid rid of braces),
an #include MACRO from FILE, or using backquotes as explicit
substition characters (to allow concatenation of tokens, but it
would break strings with backquotes in them, be them ever so few)
as these would be major redefinitions. Now I will go on vacation
until all the flames die out :-).

	(Root Boy) Jim Cottrell		<rbj@cmr>
	"One man gathers what another man spills"

franka@mmintl.UUCP (Frank Adams) (05/06/86)

In article <12329@ucla-cs.ARPA> jimc@ucla-cs.UUCP (Jim Carter) writes:
>I think it's useful!  As written, of course, it's semantically invalid,
>but what you really mean is "v <= e" (sic) or, to demonstrate where it's
>really useful,
>     array[horrendous] [subscript] [list] <= bigexpr;
>  rather than 
>     if (array[h][s][l] < bigexpr) array[h][s][l] = bigexpr;
>Now "<=" already means something else so this syntax is not acceptable.
>How about "v < = e" with a mandatory blank?  This is atrocious human
>engineering but at least is parseable.  Anybody have any better ideas?

What you talking about isn't "<=".  It's "\/=" (to use a notation which
showed up here recently).  I.e., v = min(v,e), not v = v < e.  The latter
really is pretty useless.

Frank Adams                           ihnp4!philabs!pwa-b!mmintl!franka
Multimate International    52 Oakland Ave North    E. Hartford, CT 06108

ado@elsie.UUCP (Arthur David Olson) (05/07/86)

> The. . .header file that I mentioned a few days ago. . .
> contains the following:
>
> typedef int	bool;			/* boolean data */
> #define 	false	0
> #define 	true	1

My recommendation to folks would be to use the defines that appear in
the 4.?bsd version of "curses.h"--

	# define	TRUE	(1)
	# define	FALSE	(0)

--on a conditional basis in any "nifty_header.h" file, a la:

	#ifndef TRUE
	#define TRUE	(1)
	#define FALSE	(0)
	#endif

Using the "unnecessary" parentheses that appear in "curses.h" will prevent
any "redefined to a different value" diagnostics if you both
	#include "curses.h"
and
	#include "nifty_header.h"
while conditionalizing the definitions as above will prevent
"redefined (though not to a different value)" diagnostics if
you include both files in the order shown above.
--
	UUCP: ..decvax!seismo!elsie!ado		ARPA: elsie!ado@seismo.ARPA
	DEC, VAX, Elsie & Ado are Digital, Borden & Shakespeare trademarks.

cudcv@daisy.warwick.UUCP (Rob McMahon) (05/07/86)

In article <412@brl-smoke.ARPA> gwyn@brl.ARPA writes:
>typedef int	bool;			/* boolean data */
>#define 	false	0
>#define 	true	1

What about
        typedef enum { false, true } bool;
?
-- 
UUCP:   ...!mcvax!ukc!warwick!cudcv
JANET:  cudcv@uk.ac.warwick.daisy
ARPA:   cudcv@daisy.warwick.ac.uk
PHONE:  +44 204 523037
Rob McMahon, Computer Unit, Warwick University, Coventry CV4 7AL, England

sbs@valid.UUCP (Steven Brian McKechnie Sargent) (05/08/86)

This group has lately been besieged with a variety of odd C features,
namely

*	boolean operators and data types
*	builtin functions
*	New operators like "< ="
*	Arguments passed in registers

All these have the same effect of reducing simplicity for doubtful gain.

**
A Boolean data type distinct from integers clutters the language with
another (moderately useless) type and removes handy idioms like
	foo[x == 0] = bar;
(Vide the "enum" type, which doesn't participate in address arithemtic
either.)
Arguments that boolean functions make for more efficient implementations
are pretty puny:
> o  A function returning a bool could be implemented on some machines by
>    setting the condition codes instead of storing a full integer value in
>    the return register.
If the caller wants to use the result of the function as a value, rather
than as input to a branching decision, then it must write branches anyway
to set the value appropriately.  Result: bigger slower code.
> >o  Multiple flag variables with local scope and no address operator (e.g.
> >   variables declared "register bool") could be packed into a single word.
Last I checked, (flags&BOOLEAN_VALUE_OF_MERIT) did what you want.  Packing
and unpacking don't come for free, in space or time.


**
Builtin functions confuse language implementation with programming
environment implementation; C lives in enough different environments
that this is just plain bad planning.  "Inline functions," a la those
of C++, are another matter entirely (although they have been mentioned
repeatedly in discussions of builtin functions).  The benefits that
inline functions offer over CPP macros are: simpler cleaner syntax,
more flexibility because they admit arbitrary control structure within,
and avoidance of horrible botches like putchar(*p++).  The disadvantage,
at least in my mind, is uncertainty as to what happens to the free
variables of an inline function.  Are they bound lexically where the
inline is declared, or are they bound at the point where the inline is
used, assuming the nearest enclosing scope?  Consider:

	int oddval;	// Not odd, as in = 1 (mod 2), but "odd"

	inline max(x, y) {
		++oddval;
		return (x > y)? x: y;
	}

	foo(oddval) {
		int n = max(oddval, 0);
		oddval = max(4, oddval);
		return max(oddval, oddval);
	}

	bar(x) {
		...
		return max(x, 4);
	}

The question that leaps to mind is "what the hell does this code hope
to achieve?"  You can of course write just as silly code using the C
preprocessor; but then the question becomes: Why provide redundant ways
to write this unsafely?

**
New operators like "< =", in addition to being hard to spell and understand,
facilitate usages that just aren't that common.  I hardly ever want to
say x = (x < y), and I don't mind typing the extra characters.  I'm not
interested in paying compiler vendors money for supporting this (or any
other dubious misfeature pounded into the language for "completeness'
sake.")


**
There's also been a discussion about arguments passed in registers,
with one fellow (sorry I forget the name) noting that "microcomputer
people pass arguments in registers."  Well, big computer people do
the same thing, and in both cases the disease is one of not thinking
through to the consequences of your actions.  Suppose you pass arguments
in registers.  Well, if you're like me, you have a lot of variables in
registers.  So in order to pass your arguments, you have to save those
registers somewhere.  Where do you do it?  Put them on the stack, of
course.  Well, suppose that you "know" that %3 and %4 are reserved for
parameter passing: then those registers are unavailable to the caller,
whose code gets correspondingly bigger and slower.  Well, suppose you're
keeping the arguments in %3 and %4, and the callee can use them "in
place" because caller and callee have agreed to do that (in order to
avoid the overhead of explicit parameter moving).  Now, you're writing
spaghetti code, full of "special" communication among routines, with
all the attendant side effects and untraceable bugs.  And why for?
The speed gain from non-standard calling sequences seems marginal at
best: one recent posting discussed at great length the most efficient
way to present arguments to the UNIX open(2) call -- which executes
hundreds or thousands of instructions inside namei, involving perhaps
multiple waits for the disk in order to fetch the inode for the file!
Put the arguments on a linked list of bit-wide elements and force the
kernel to chase them down, if you want: it won't make much of a
difference in how fast your programs run.


**
It's lots of fun to talk about wonderful "features" we'd like to see,
but somebody (ANSI?) might be listening and do something about it.  So,
for my $.02 worth:

*	Always strive to separate language from libraries, libraries
	from host environment, and host environment from development
	environment.  These are all separate entities; make their
	interactions as clean as possible.

*	Keep implementations simple.  This means: eschew oddball
	calling sequences that are hard for debuggers to follow.
	This means: minimize the number of compile-time options --
	the user needs to determine the meaning of his program from
	the source code; don't confuse the process by throwing in
	options that invisibly change this meaning.

*	Be EXTREMELY conservative about adding features.  I have yet
	to see a feature proposed that fixes a crippling problem
	of the language.  Quite the opposite: many proposed features,
	such as unary + to denote evaluation ordering, help a min-
	ority of users while making the language more baroque for
	everybody.


I do go on, don't I?  Oh, well; enjoy, flame back, or whatever.

Blessed be,

S.

wendyt@pyramid.UUCP (Wendy Thrash) (05/08/86)

WARNING:  This article discusses compiler issues, not specifically C
language issues.

In article <268@valid.UUCP> sbs@valid.UUCP (Steven Brian McKechnie Sargent) writes:
>*	Arguments passed in registers...
>... have the same effect of reducing simplicity for doubtful gain.

I don't want to quote too much of the original article -- it was rather long.
The thrust of it was that passing parameters in registers doesn't make things
run faster.  This does not fit with my experience.  When we implemented
parameter passing in registers at Zilog, it was a big win.

The argument that register variables must be pushed on the stack in order
to pass parameters in registers seems tenuous.  If you have only one set
of registers available for variables, you have to save them sometime,
unless the routine you are calling has no register variables itself.  More
commonly, registers used for parameter passing are not used for register
variables; they may be used for temporaries.  It is true that this may cut
down on the number of available registers, but our work showed that we had
enough registers remaining to allow good code generation for most programs.

We did, indeed, allow the callee to use its arguments in place. Mr. Sargent's
statements about "spaghetti code" make no sense at all to me -- this was
a COMPILER;  it was designed to produce efficient assembly language, not
readable assembly language.  When the compiler functioned correctly (as it
usually did) there were no "attendant side effects and untraceable bugs."

I will admit that this parameter passing caused difficulties.  In particular,
varargs code was messy, and debuggers more difficult to implement.  Was it
worth it?  I believe so.  Our emphasis was on speed, and that we had.

Of course, this is all moot on RISC machines with sliding register windows.
The concept of parameter passing in registers is then wired into the
architecture, and there are plenty of registers left for register variables.

---
Disclaimer:  My opinions have obviously been influenced by the parameter
passing in registers of my former employer (Zilog) and the sliding windows
of my current employer (Pyramid).
-- 
Wendy Thrash   {allegra,cmcl2,decwrl,hplabs,topaz,ut-sally}!pyramid!wendyt
Pyramid Technology Corp, Mountain View, CA  +1 415 965 7200 ext. 3001

throopw@dg_rtp.UUCP (Wayne Throop) (05/08/86)

> jimc@ucla-cs.ARPA (Jim Carter)
>>  kwh@bentley.UUCP (KW Heuer)
>>Btw, you can't have *all* operators extended with "=".  How would you write
>>"v = v < e;"?  (Not that it's useful.)
> I think it's useful!  As written, of course, it's semantically invalid,
> but what you really mean is "v <= e" (sic) or, to demonstrate where it's
> really useful,
>      array[horrendous] [subscript] [list] <= bigexpr;
>   rather than 
>      if (array[h][s][l] < bigexpr) array[h][s][l] = bigexpr;

The point is not that it isn't useful to collapse multiple array (or
other clumsy) references.  The point is that in "e1 = e1 < e2", the "<"
operator assumes arguments with numeric semantics and yeilds a value
with boolean semantics.  Since e1 is both an argument and a result, this
expression isn't very meaningful.  The fact that C overloads the numeric
types with boolean meaning doesn't make this a useful thing to do.
Interestingly, if e2 also has boolean semantics, the "e1 < e2" gives the
same result as "!e1 && e2" (ignoring side effects).  Doesn't seem like a
primitive to clammor for in the language, nor does "<" seem like a good
symbol for it if it were a primitive.

Now, I know what all you hackers are saying.  You're saying "But Wayne,
how did you become a LOVE GOD?" (What's that?  net.lang.c?  Not
net.panting.singles?  Sorry, I mean) "But Wayne, I just don't care
diddly about numeric vs boolean type safety debates.  I just want
something that'll WORK." Ok.  Fine.  But you'll probably be looking for
subtle and disgusting bugs in programs that contain oddities like
"e1 = e1 < e2" long after others are happily using working programs that
don't.  So there.
-- 
Wayne Throop      <the-known-world>!mcnc!rti-sel!dg_rtp!throopw

rcd@nbires.UUCP (05/09/86)

> >Btw, you can't have *all* operators extended with "=".  How would you write
> >"v = v < e;"?  (Not that it's useful.)

A more precisely stated rule, for C, would be that you can extend any
dyadic operator whose result type is the same as the type of the first
operand, but...

> I think it's useful!  As written, of course, it's semantically invalid,
> but what you really mean is "v <= e" (sic) or, to demonstrate where it's
> really useful,
>      array[horrendous] [subscript] [list] <= bigexpr;
>   rather than 
>      if (array[h][s][l] < bigexpr) array[h][s][l] = bigexpr;

Cf. Icon, in which the success/failure of a conditional is separate from
its value.  Icon's <= operator (as all of its relational operators) yields
the value of its right operand if it succeeds; otherwise it fails (meaning
no result is produced).  The semantics described above in ">" is just that
of Icon's <:= operator.
-- 
Dick Dunn	{hao,ucbvax,allegra}!nbires!rcd		(303)444-5710 x3086
   ...Cerebus for dictator!

rbutterworth@watmath.UUCP (Ray Butterworth) (05/09/86)

> > lots of us say "typedef short bool" in our .h files.
> typedef char bool;	uses less space on some machines.

And on some machines it uses more space.  Some machines can
reference an int with a single instruction, but checking the
value of a byte might take several.  The one I am using now
does the "if(integer)" test in 4 bytes of machine instructions,
but "if(character)" takes 12 bytes.

So defining it as short or char instead of int might save you
1 or 3 bytes of storage, but it also might cost you several
times this amount EVERY time you reference the variable.
In general you should always use int (or long).  short (or char)
should only be used for structures read in from an external
source or for large arrays where the saving in space for the
data is significantly large.

Of course if you aren't worried about portable efficiencies
do whatever is best for your machine.  On the other hand, I'd
like to think that at least some of the software I write now
will still be running in 10 years, but I have my doubts about
whether or not some of the machines I am using now will still
be here then.  (I can think of some wonderful code I wrote for
an IBM1620 not much more than 10 years ago.)

greg@utcsri.UUCP (Gregory Smith) (05/09/86)

In article <602@brl-smoke.ARPA> rbj@icst-cmr (Root Boy Jim) writes:

>2) More of the same. We all know about *++p. But what if I want to jump
>	more than one element? I can't write *(p += 2); Or maybe I
>	want to write `p = &(i += 5).

You can write *(p += 2). For *p++, you can write *((p += 2 ) - 2 ) if you
really want to. If p is a register, there will be little penalty over
dereferencing *before* the p+=2.
	Why you wanna do p = &(i += 5 ) ?????? Like your immortal
`exit(1,fprintf(stderr,"Arrg!!\n"))' this is an artificial combination of
two unconnected statements. What's wrong with  `i+=5; p= &i'?
( You probably prefer i+=5,p= &i; )
>
>3) Exchange operator. This has probably been discussed before, so pardon
>	me if I blunder into that pit. BUT, DMR has stated that one of
>	the reasons that exponentiation was left out was because no
>	(or few, if any) machine could do it inline, and therefore
>	all the compiler would be doing is a function call anyway.
>	By the same reasoning, exchange CAN be done efficiently by
>	some machines, and the hack of a temporary variable and
>	three assignments is a rather stale idiom. The three
>	statement XOR trick avoids the temporary, at the expense
>	of execution time and clarity.
>
Good stuff. Even machines without an EXG can use a scratch register, which
is better than using a user-supplied temp.
What, by the way, is the XOR trick?

>4) Allow complex statements to be considered as expressions so that
>	the comma operator can be used to avoid braces, as in
>
>	if (e) x = y, return z;
>
Errr... well....
I'm not a compiler guru, but.... In the current ( conventional ) setup,
compilation of expressions is done separately from 'statement processing'
( i.e. returns, ifs, whiles, cases, etc ). Your suggestion would require
that the two be entwined together, which would make generation of really
good code a difficult thing. Currently, when an expression is found, a tree
is built, then the tree is crunched upon, and the code is generated. If
every statement was an expression, then expression trees would need to
have nodes for ifs and whiles, etc... ( starting to get LISPy). This
could of course get very messy, and a really good coder is already a
fairly messy thing to do. Besides, I don't think this would help very
much, except for Obfuscated C entries.

>5) Allow immediate constants. Currently, there is only one special
>	case, that of a character array. One can say char *p = "string";
>	and have the string squirreled away and the (magic) address
>	stuffed into the pointer. Why not int *p = &5; where the
>	integer five is whisked away and replaced by its address.
>	Sure would eliminate a lot of housekeeping variables.
>
Fine by me.
I would also like to suggest struct constants/rvalues. Suppose I have
	struct foo{
		int f1;
		char f2;
		char *bar;
	} foo_var;
I'd like to write something like this ( an executable statement ):

	foo_var = struct foo{		/* set structure value */
		.bar = "Ergo Sum";
		.f1 = 73;
		.f2 = '?';
		};

This allows the use of unnamed (structure constants).

#define cmplx(a,b) struct complex { .r=(a); .i=(b); }
#define J cmplx( 0.0,1.0 )

	cvar1 = cmul( cvar2, cmplx( 2.0, 1.02 ) );

I think it is important that the member names be used instead of the
order. Also, it would be nice if the compiler were smart in cases like

	xchar = struct foo{ .bar="??"; .f2 = ychar+1; .f1 = func(i); }.f2;

not to generate all the code to compute f1 and bar ( Holy side-effects,
Batman! ). The above line could arise by a macro expansion.
I have though out many of the implementation details, and I *still* think
it's a good idea :-). I am very open to suggestions about the syntax.
I will ramble on about/ argue about this later if you want ( and probably
if you don't want 8-) <- peril-sensitive sunglasses. ).


>6) Eliminate arrays altogether! Well not exactly, but make all
>	arrays vectored in all dimensions. This would show
>	those quiche eaters what a real tough language C is :-).
>	Array syntax would still be available of course, but would
>	be translated into glorious pointer notation. And it wouldn't
>	matter whether a variable was defined differently than it
>	was declared (char x[] or char *x).
>
Fully vectored arrays were used in B, and I like C's stuff better.
You can always set up vectored arrays if you want - and still say
array[i][j][k] into the bargain. Of course, you have to set up the
vectors yourself...

>
>8) Allow formal arguments to be declared AFTER the opening brace.
>	This would allow prioritization of register variables.
>
Well, register arguments need to copied from the stack anyway, so
you can declare your own with an explicit copy. But it wouldn't
hurt to let the compiler do it. Since it silly ( presently ) to
say `foo(p){ register char *p;...' this could be taken as an argument
declaration.

I have a related suggestion.

Suppose I have the following:

f(){
	...
	{ int x,y;	...	}
	{ double xy;	...	}
}
I would expect x and y to share the same stack space with xy.
Now look at this ( assume 4 regs available ):

f(){	register i,j,k,l,m;		/* more vars than regs available */
	{ register ii ..... };
}
I think the inner loop should push 'l' ( the lowest priority reg var ) on
the stack and keep 'ii' in that reg, since ii will probably get more use
in the inner block. The register priority would become ii/i/j/k, so if
a further nested block said 'register a,b', the next regs to be kicked out
would be j and k, leaving the priority as a/b/ii/i.
At the end of the block, the value of l would be popped. If the block were
the body of a loop, the pushing/popping would need to be done outside the
actual loop, for speed. Inside the loop, of course, 'l' would be addressed
as an auto.

This allows C programmers one more advantage previously available only to
assembler programmers: the re-use of registers for completely different
things. The problem is that it would make jumping into/out of blocks a
mess. I guess the compiler would have to detect this and generate 'fix'
code for the jumps.

-- 
"Canabee be said2b or not2b anin tire b, if half thabee isnotabee, due2
somain chunt injury?" - Eric's Dilemma
----------------------------------------------------------------------
Greg Smith     University of Toronto      UUCP: ..utzoo!utcsri!greg

davidsen@steinmetz.UUCP (Davidsen) (05/09/86)

In article <210@sdchema.sdchem.UUCP> tps@sdchema.UUCP (Tom Stockfisch) writes:
>In article <778@bentley.UUCP> kwh@bentley.UUCP writes:
>>In article <838@ihwpt.UUCP> ihwpt!knudsen writes:
>>>(2) There isn't any ^^ (XOR) operator either, as in
>>
>>There is, but it's spelled "!=".  (Presumably more efficient than "^", though
>>I think either one should work with a smart compiler.)
>>
>
>Not quite the same.
>	3 ^^ 4
>would evaluate as 0,
>	3 != 4
>evaluates as 1.
>
>-- Tom Stockfisch, UCSD Chemistry


XOR can be defined as an (ugly) macro, I believe.

#define XOR(a,b) (((a) != 0) != ((b) != 0)
/* or if you like small better than readable */
#define XOR(a,b) (!!(a) != !!(b))
-- 
	-bill davidsen

	seismo!rochester!steinmetz!--\
       /                               \
ihnp4!              unirot ------------->---> crdos1!davidsen
       \                               /
        chinet! ---------------------/        (davidsen@ge-crd.ARPA)

"Stupidity, like virtue, is its own reward"

gwyn@BRL.ARPA (VLD/VMB) (05/09/86)

One can define "bool" to be a variety of things,
including an enumeration type, but as C was designed
the result of a relational expression (for example)
is an int; that's what Boolean data in C really "is".

gwyn@BRL.ARPA (VLD/VMB) (05/09/86)

Steven Brian McKechnie Sargent <valid!sbs> says ("> ..."):
> A Boolean data type distinct from integers clutters the language with
> another (moderately useless) type and removes handy idioms like
> 	foo[x == 0] = bar;

Boolean quantities form an important abstract data type distinct from
counters, sets, real numbers, etc.  By not making the distinction,
the language encourages usage errors, the most notorious being
	if ( a = b )
		stuff;
Sure, one can make integers do double (or triple, or ...) duty,
but by now every programmer should realize the value of data
abstraction.

> New operators like "< =", in addition to being hard to spell and understand,
> facilitate usages that just aren't that common.  I hardly ever want to
> say x = (x < y), and I don't mind typing the extra characters.  I'm not
> interested in paying compiler vendors money for supporting this (or any
> other dubious misfeature pounded into the language for "completeness'
> sake.")

Here is an example where proper use of Boolean data would be violated.
A statement like
	x = x < y;
should NEVER be used, since it assigns a Boolean result to an
arithmetic variable.  This means that a "< =" operator is not
a good idea.

I find data abstraction to be a Good Thing, and have produced
much better code since defining a Boolean data type and using
it in a strictly type-correct manner.

peter@baylor.UUCP (05/10/86)

> Not quite the same.
> 	3 ^^ 4
> would evaluate as 0,
> 	3 != 4
> evaluates as 1.

Wrong. Remember:

	3 && 4 = 1

	3 & 4 = 0

^^ was intended by the original poster as a logical operator, not a boolean
one (despite the title of the message).
-- 
-- Peter da Silva
-- UUCP: ...!shell!{baylor,graffiti}!peter; MCI: PDASILVA; CIS: 70216,1076

levy@ttrdc.UUCP (Daniel R. Levy) (05/12/86)

In article <732@steinmetz.UUCP>, davidsen@steinmetz.UUCP (Davidsen) writes:
>XOR can be defined as an (ugly) macro, I believe.
>
>#define XOR(a,b) (((a) != 0) != ((b) != 0)
>/* or if you like small better than readable */
>#define XOR(a,b) (!!(a) != !!(b))
>--
>	-bill davidsen

or even

#define XOR(a,b)	(!(a) != !(b))

since XOR(not-a,not-b) == XOR(a,b)
-- 
 -------------------------------    Disclaimer:  The views contained herein are
|       dan levy | yvel nad      |  my own and are not at all those of my em-
|         an engihacker @        |  ployer or the administrator of any computer
| at&t computer systems division |  upon which I may hack.
|        skokie, illinois        |
 --------------------------------   Path: ..!{akgua,homxb,ihnp4,ltuxa,mvuxa,
						vax135}!ttrdc!levy

grr@cbmvax.cbm.UUCP (George Robbins) (05/12/86)

In article <357@pyramid.UUCP> wendyt@pyramid.UUCP (Wendy Thrash) writes:
[...]
>I don't want to quote too much of the original article -- it was rather long.
>The thrust of it was that passing parameters in registers doesn't make things
>run faster.  This does not fit with my experience.  When we implemented
>parameter passing in registers at Zilog, it was a big win.

*WAS* a big win - meaning maybe it looked good on benchmarks...

[...]
>I will admit that this parameter passing caused difficulties.  In particular,
>varargs code was messy, and debuggers more difficult to implement.  Was it
>worth it?  I believe so.  Our emphasis was on speed, and that we had.

1) pdp-11 style varargs was broken - no way from C to get a those arguments
   that got crammed into registers.

2) Because of the register assignment scheme used, you couldn't even blindly
   pass a list of variable arguments to a routine like printf that did know
   how to deal with them.

3) setjmp/longjmp got broken with respect to restoring register variable
   parameters somewhere along the way.

In the long run, portability seems to have become the more important issue:

Just try porting some of the code in mod.sources and net.sources to the
machine and see how far you can get without having to go into the editor 
and start whacking at source code.  Assume that software developers will
have the same problems porting their wares...

Also, note that Zilog has never delivered its ATT SVID blessed System V port,
and that their next series of machines will contain ATT chips running vanilla
3Bx software...
-- 
George Robbins - now working with,	uucp: {ihnp4|seismo|caip}!cbmvax!grr
but no way officially representing	arpa: cbmvax!grr@seismo.css.GOV
Commodore, Engineering Department	fone: 215-431-9255 (only by moonlite)

hutch@sdcsvax.UUCP (Jim Hutchison) (05/12/86)

()

well now for ||= you can use |= because C defines 0 as false and non-0
as true (Yes, I know that boolean expressions are defined to return 0/1
as defined in K&R if that is still used).

typedef char bool;

#define B_TRUE	((bool)1)
#define B_FALSE	((bool)0)

bool a, b;

		a = B_TRUE;
		b = (x == READY);
		...
		b |= (x == READY);
		b ^= a;

Now this can get you into trouble, because 2 and 1 and 47 are also
"true".  This is o.k. for '|' but not '^'.

You could of course do

		b = (b == 0) ^ (a == 0)

but that looks a bit strained.
-- 
/*	Jim Hutchison	UUCP:	{dcdwest,ucbvax}!sdcsvax!hutch
			ARPA:	Hutch@sdcsvax.ucsd.edu
		    [ Disclaimer eaten by a passing kiwi ]	 */

rbj@icst-cmr (Root Boy Jim) (05/14/86)

	Doug Gwyn responds:
	Steven Brian McKechnie Sargent <valid!sbs> says ("> ..."):
	> A Boolean data type distinct from integers clutters the language with
	> another (moderately useless) type and removes handy idioms like
	> 	foo[x == 0] = bar;
	
	Boolean quantities form an important abstract data type distinct from
	counters, sets, real numbers, etc.  By not making the distinction,
	the language encourages usage errors, the most notorious being
		if ( a = b )
			stuff;

True. It is easily found tho.

	Sure, one can make integers do double (or triple, or ...) duty,
	but by now every programmer should realize the value of data
	abstraction.
	
Or lack of it. I find that the Boolean/Integer schism in Fortran caused
me lots of headaches long ago.

	> New operators like "< =", in addition to being hard to spell and
	> understand,
	> facilitate usages that just aren't that common.  I hardly ever want to
	> say x = (x < y), and I don't mind typing the extra characters. I'm not
	> interested in paying compiler vendors money for supporting this
	> (or any other dubious misfeature pounded into the language for
	> "completeness'sake.")
	
	Here is an example where proper use of Boolean data would be violated.
	A statement like
		x = x < y;
	should NEVER be used, since it assigns a Boolean result to an
	arithmetic variable.  This means that a "< =" operator is not
	a good idea.
	
Wrong you are, Doug. You have been thinking in this Boolean paradigm
for so long that you are missing another Good thing. Implication!
Given that P and Q are `Boolean' variables (0 or 1), the Logical
Implication is described by the operator `<='. Thus, the statement
`x = p <= q;' sets the `boolean' value x to a `boolean' expression.
Since there are no such things as booleans :-), x, p, & q are integers.
It's all a matter of interpretation. APL has no `boolean exclusive or'
operator because the operator `!=' does the same thing (when given
only zero's or one's). There are sixteen different boolean functions
with two inputs and one output. They all fit nicely into C operators:

	p 0 0 1 1
	q 0 1 0 1	Name		Symbol
	---------	----		------
	  0 0 0 0	False		0
	  0 0 0 1	And		&
	  0 0 1 0	Doesn't Imply	>
	  0 0 1 1	Alpha		p
	  0 1 0 0	Not Implied By	<
	  0 1 0 1	Omega		q
	  0 1 1 0	Diff		!= or ^
	  0 1 1 1	Or		|
	  1 0 0 0	Nor		!(p | q)
	  1 0 0 1	Same		==
	  1 0 1 0	Not Omega	!q
	  1 0 1 1	Is Implied By	>=
	  1 1 0 0	Not Alpha	!p
	  1 1 0 1	Implies		<=
	  1 1 1 0	Nand		!(p & q)
	  1 1 1 1	True		1

Neat! I never thought I'd get to use my engineering switching theory again!

	I find data abstraction to be a Good Thing, and have produced
	much better code since defining a Boolean data type and using
	it in a strictly type-correct manner.
	
This fact doesn't bother people who write in APL, widely considered
to be the most mathematical language. Why does it bother you?

	(Root Boy) Jim Cottrell		<rbj@cmr>
	"One man gathers what another man spills"

kwh@bentley.UUCP (KW Heuer) (05/14/86)

In article <268@valid.UUCP> valid!sbs (Steven Brian McKechnie Sargent) writes:
>A Boolean data type distinct from integers clutters the language

I disagree.  I think an explicit boolean datatype *simplifies* the language.
The way I see it, booleans already exist internally.

>and removes handy idioms like
>	foo[x == 0] = bar;

I'd guess that would still be legal, just like "float x = 0;".  The compiler
could know how to convert bool to int.  At worst, you could write "(int)" to
force it.  (I prefer to write "foo[x==0 ? 1 : 0] = bar;", which is no less
efficient since that's how the compiler converts the "internal bool" into an
int anyway.)

>(Vide the "enum" type, which doesn't participate in address arithemtic
>either.)

I'd like to see a syntax to declare an array which is subscripted by an enum
instead of an int.  Having to use a cast is a pain.  (In the example above,
you didn't mean to imply that foo[] would only be indexed by bool, did you?
If so, cancel my comment about "?:".)

>Arguments that boolean functions make for more efficient implementations
>are pretty puny:
>> o  A function returning a bool could be implemented on some machines by
>>    setting the condition codes instead of storing a full integer value in
>>    the return register.
>If the caller wants to use the result of the function as a value, rather
>than as input to a branching decision, then it must write branches anyway
>to set the value appropriately.  Result: bigger slower code.

No slower than putting the same branch in the called function!  Anyway, I
suspect that most boolean functions *are* used in a boolean context rather
than an integer context.

>> >o  Multiple flag variables with local scope and no address operator (e.g.
>> >   variables declared "register bool") could be packed into a single word.
>Last I checked, (flags&BOOLEAN_VALUE_OF_MERIT) did what you want.  Packing
>and unpacking don't come for free, in space or time.

"Packing and unpacking" don't need to be done except in an integer context.
The boolean operations are single instructions.  As for (f&CONST), I'd just
like to reduce the ugliness.  Cf. bitfields.

>**
>Builtin functions confuse language implementation with programming
>environment implementation; C lives in enough different environments
>that this is just plain bad planning.  "Inline functions," a la those
>of C++, are another matter entirely (although they have been mentioned
>repeatedly in discussions of builtin functions).  The benefits that
>inline functions offer over CPP macros are: simpler cleaner syntax,
>more flexibility because they admit arbitrary control structure within,
>and avoidance of horrible botches like putchar(*p++).  The disadvantage,
>at least in my mind, is uncertainty as to what happens to the free
>variables of an inline function.  Are they bound lexically where the
>inline is declared, or are they bound at the point where the inline is
>used, assuming the nearest enclosing scope?  Consider: [example deleted]

I think I agree about builtins.  There's no problem with "putchar(*p++)",
I believe you're thinking of "putc(c, *fp++)".  It's my understanding that
"inline" has the same semantics as "static", but is a hint to the compiler;
your example may force the compiler to forgo the inline expansion.

>**
>New operators like "< =" ...

I originally mentioned this just to point out that there exist operators
which cannot be extended with "op=".  The one person who thought it would be
useful was confusing it with "MAX=".  (Mark Brader has pointed out that B,
a sibling* language to C, actually has these operators (spelled "=<", etc.)
for completeness.  I still think they're useless.)

>**
>... I have yet to see a feature proposed that fixes a crippling problem of
>the language.

Do you know of any "crippling problems" that require new features?

Anyway, it's useful to keep in mind that much of what is said here (by me,
certainly) is not a "proposal", but just an idea to be tossed around in the
think tank.  As an example of such, here's an idea which I do *not* want to
see in the next ANSI draft.

In stepping through a linked list (recursive structure), one often writes
"p=p->next;".  The logic that creates "+=" would suggest that this could be
written "p->=next".  However, "->" is not really an operator since its right
"argument" is not an expression.  An alternate notation would be "p=>next",
where "=>" is a sort of overstrike between "->" and "=".  (I actually had a
case once where this would've been useful -- "p" was an expression with side
effects!)

Karl W. Z. Heuer (ihnp4!bentley!kwh), The Walking Lint
*The original B was a parent language of C; modern B is a sibling.

gwyn@BRL.ARPA (VLD/VMB) (05/14/86)

Index to participants:
	>>> Steven Brian McKechnie Sargent
	>> Doug Gwyn
	> Jim Cottrell

>>> New operators like "< =", in addition to being hard to spell and
>>> understand,
>>> facilitate usages that just aren't that common.  I hardly ever want to
>>> say x = (x < y), and I don't mind typing the extra characters. I'm not
>>> interested in paying compiler vendors money for supporting this
>>> (or any other dubious misfeature pounded into the language for
>>> "completeness'sake.")
>>
>> Here is an example where proper use of Boolean data would be violated.
>> A statement like
>> 	x = x < y;
>> should NEVER be used, since it assigns a Boolean result to an
>> arithmetic variable.  This means that a "< =" operator is not
>> a good idea.
> 
> Wrong you are, Doug. You have been thinking in this Boolean paradigm
> for so long that you are missing another Good thing. Implication!
> Given that P and Q are `Boolean' variables (0 or 1), the Logical
> Implication is described by the operator `<='. Thus, the statement
> `x = p <= q;' sets the `boolean' value x to a `boolean' expression.
> Since there are no such things as booleans :-), x, p, & q are integers.
> It's all a matter of interpretation. APL has no `boolean exclusive or'
> operator because the operator `!=' does the same thing (when given
> only zero's or one's). There are sixteen different boolean functions
> with two inputs and one output. They all fit nicely into C operators:
> [table omitted]

Even Boole knew that Boolean operations can be performed
by appropriate arithmetic on {0,1} operands; that is irrelevant.

The original example, x "< =" y;, interpreted as you suggest, would
mean `set x to "x is not implied by y"', if and only if x and y were
Boolean in the first place.  Not only is this of negligible practical
value, but that meaning of the operator differs from its meaning
when applied to non-Boolean values (the general case, and the one I
had in mind when I argued that it was a bad idea).

>> I find data abstraction to be a Good Thing, and have produced
>> much better code since defining a Boolean data type and using
>> it in a strictly type-correct manner.
> 
> This fact doesn't bother people who write in APL, widely considered
> to be the most mathematical language.

APL doesn't offer real facilities for data abstraction.

> Why does it bother you?

Because as a conscientious software engineer I have to produce
reliable and maintainable systems for people to use.
This requires quality standards well beyond what hackers might
feel to be necessary.

mesans@uvicctr.UUCP (mesans) (05/14/86)

>>Not quite the same.
>>	3 ^^ 4
>>would evaluate as 0,
>>	3 != 4
>>evaluates as 1.
>
>If the left and right hand sides are both already boolean, `!=' works;
>but the following macro always works:
>
>	/* logical exclusive or */
>	#define lxor(a, b)	(((a) != 0) != ((b) != 0))
  Which is equivalent to :
               !a != !b
     which I think you will agree is much simpler, and easyer to
  understand (at least I think so).

      S. John Banner

rbj@icst-cmr (Root Boy Jim) (05/15/86)

	XOR can be defined as an (ugly) macro, I believe.
	
	#define XOR(a,b) (((a) != 0) != ((b) != 0)
	/* or if you like small better than readable */
	#define XOR(a,b) (!!(a) != !!(b))
	-- 
		-bill davidsen
	
/* smaller still */
#define XOR(a,b) (!!(a) == !(b))

	(Root Boy) Jim Cottrell		<rbj@cmr>
	"One man gathers what another man spills"

mnl@cernvax.UUCP (mnl) (05/16/86)

In article <2741@utcsri.UUCP> greg@utcsri.UUCP (Gregory Smith) writes:
>In article <602@brl-smoke.ARPA> rbj@icst-cmr (Root Boy Jim) writes:
>
>>3) Exchange operator. This has probably been discussed before, so pardon
>>	me if I blunder into that pit. BUT, DMR has stated that one of
>>	the reasons that exponentiation was left out was because no
>>	(or few, if any) machine could do it inline, and therefore
>>	all the compiler would be doing is a function call anyway.
>>	By the same reasoning, exchange CAN be done efficiently by
>>	some machines, and the hack of a temporary variable and
>>	three assignments is a rather stale idiom. The three
>>	statement XOR trick avoids the temporary, at the expense
>>	of execution time and clarity.
>>
>Good stuff. Even machines without an EXG can use a scratch register, which
>is better than using a user-supplied temp.
>What, by the way, is the XOR trick?
>
To swap the contents of A and B (no particular language):

A = A XOR B
B = A XOR B
A = A XOR B

On some machines, assuming A and B are in registers, this won't take
any more time than the normal three assignments using a temporary.
-- 
Mark Nelson

mnl@cernvax.bitnet or ...!seismo!mcvax!cernvax!mnl
If the ACM had a sub-group for naturalists, would it be ACM
SIGnature?

kwh@bentley.UUCP (KW Heuer) (05/16/86)

In article <1776@sdcsvax.UUCP> hutch@sdcsvax.UUCP writes:
>well now for ||= you can use |= ...

I think the intent was that "v ||= e" would not evaluate e if v were already
true.  (Same as "v = v || e".)

franka@mmintl.UUCP (Frank Adams) (05/17/86)

In article <147@daisy.warwick.UUCP> cudcv@daisy.warwick.ac.uk (Rob McMahon) writes:
>In article <412@brl-smoke.ARPA> gwyn@brl.ARPA writes:
>>typedef int	bool;			/* boolean data */
>>#define 	false	0
>>#define 	true	1
>
>What about
>        typedef enum { false, true } bool;
>?

I will start using this when I can rely on having an ANSI standard compiler.
At the moment, there are too many compilers where the expression in an if
statement can't be an enum.  (Not to mention compilers which don't support
enums.)

Frank Adams                           ihnp4!philabs!pwa-b!mmintl!franka
Multimate International    52 Oakland Ave North    E. Hartford, CT 06108

franka@mmintl.UUCP (Frank Adams) (05/17/86)

In article <2496@watmath.UUCP> rbutterworth@watmath.UUCP writes:
>> > lots of us say "typedef short bool" in our .h files.
>> typedef char bool;	uses less space on some machines.
>
>And on some machines it uses more space.

Which is why you put it in a .h file, instead of in each program separately.
That way it can fairly easily be changed when you port.

Frank Adams                           ihnp4!philabs!pwa-b!mmintl!franka
Multimate International    52 Oakland Ave North    E. Hartford, CT 06108

kwh@bentley.UUCP (KW Heuer) (05/17/86)

In article <814@bentley.UUCP> I wrote:
>*The original B was a parent language of C; modern B is a sibling.

I stand corrected.  The features I described were part of "old" B.

aglew@ccvaxa.UUCP (05/22/86)

~> Boolean data type in C

I say `typedef unsigned char bool'...

Instead of using macros like lxor, I do
#define boolval(bv) ((bv)!=0)
so I can get away with saying boolval(XXX) ^ boolval(YYY) and the like.
Doesn't help with waning to be able to do BBBBB &&= CCCCC;

"Equal rights for Booleans!" has been my cry for a while - but I meant it
with respect to computer architectures, not C. After all, C can't be expected
to be better than present day architectures - C is just structured assembly
language. :-). On second though, :-(.

Andy "Krazy" Glew. Gould CSD-Urbana.    USEnet:  ihnp4!uiucdcs!ccvaxa!aglew
1101 E. University, Urbana, IL 61801    ARPAnet: aglew@gswd-vms

franka@mmintl.UUCP (Frank Adams) (05/26/86)

In article <822@brl-smoke.ARPA> rbj%icst-cmr@smoke.UUCP writes:
>	I find data abstraction to be a Good Thing, and have produced
>	much better code since defining a Boolean data type and using
>	it in a strictly type-correct manner.
>	
>This fact doesn't bother people who write in APL, widely considered
>to be the most mathematical language. Why does it bother you?

When I was writing in APL, I found that a necessary part of writing good
code was always knowing what the data I was dealing with was.  (This doesn't
mean that one cannot write a function which works for more than one data
type; just that one must explicitly know that that is what one is writing.)
If I wrote AxB, I knew whether A was a Boolean or a number; the ability to
declare it could only have helped.

The fact that one can map Booleans into numbers, and thereby get a number of
Boolean operators from the arithmetic ones, is one of those great mixed
blessings.  There is a real loss in readability when one takes advantage of
such things, as C and APL both do.

I think Pascal and ADA are closer to the mark here, regarding Boolean as an
instance of an enumeration type.  This is not merely clever; it is correct.

Frank Adams                           ihnp4!philabs!pwa-b!mmintl!franka
Multimate International    52 Oakland Ave North    E. Hartford, CT 06108

mike@peregrine.UUCP (Mike Wexler) (05/28/86)

In article <822@brl-smoke.ARPA> rbj@icst-cmr (Root Boy Jim) writes:
>	Boolean quantities form an important abstract data type distinct from
>	counters, sets, real numbers, etc.  By not making the distinction,
>	the language encourages usage errors, the most notorious being
>		if ( a = b )
>			stuff;
>
>True. It is easily found tho.
             ------
How do I easily find these?
Given the following pseudocode fragment
	 int xyz(parameter1,parameter2)
	{
	...
		if (big_expression_1=big_expression_2) statement;
	...
	}
Where the "=" should be a "==" and the function is producing unexpected
results how would you easily track down this failure.  By easily I mean
more easily than compiling the program and noticing the error about using
an arithmetic expression where a boolean one was supposed to be.  If this
isn't what you meant by easily, what did you mean?
-- 
Mike Wexler
Email address:(trwrb|scgvaxd)!felix!peregrine!mike
Tel Co. address: (714)855-3923
;-) Internet address: ucivax@ucbvax.BERKELY.EDU!ucivax%felix!mike@peregrine :-(