[comp.lang.c] Assignment in test: OK?

mark@DRD.Com (Mark Lawrence) (09/06/90)

I have a proclivity to code like the following:

   if( (status = FuncCall(foo, bar, gex)) < SomeValue)
	   GripeAboutIt();

or variations thereof.  When I run saber on such code, it babbles a 
warning about the assignment in the test.  Being the gullible naif I am, 
I worry when a heavy duty tool like Saber complains about something.  Is this 
practice considered kosher by those in the know?  Why or why not?
-- 
mark@DRD.Com uunet!apctrc!drd!mark$B!J%^!<%/!!!&%m!<%l%s%9!K(B

gordon@osiris.cso.uiuc.edu (John Gordon) (09/06/90)

	Well, 

		if((fp = fopen("file", "r")) == NULL)

	is very common.  I use it all the time.

burley@world.std.com (James C Burley) (09/06/90)

In article <1990Sep5.185451.25532@DRD.Com> mark@DRD.Com (Mark Lawrence) writes:

   I have a proclivity to code like the following:

      if( (status = FuncCall(foo, bar, gex)) < SomeValue)
	      GripeAboutIt();

   or variations thereof.  When I run saber on such code, it babbles a 
   warning about the assignment in the test.  Being the gullible naif I am, 
   I worry when a heavy duty tool like Saber complains about something.  Is this 
   practice considered kosher by those in the know?  Why or why not?
   -- 
   mark@DRD.Com uunet!apctrc!drd!mark$B!J%^!<%/!!!&%m!<%l%s%9!K(B

Your code is fine IMHO.  But suppose you had written the following
accidentally:

    if (foo = 0)

This is a common mistake.  My guess is that Saber (which I don't know anything
about) is just trying to get you to look at ifs containing assignments, just
in case you meant to say "if (foo == 0)".  In your particular example, I'd
like to think a somewhat smarter analysis by Saber would prevent it from
worrying, since the assignment expression is a subexpression serving as an
operand for a comparison operator.  But getting a programmer to look at more
things than are real problems is preferable to going the other way; and
perhaps Saber just token-analyzes without building expression trees and
suchlike.

BTW, if I ever write a new C-like language, ":=" will be the assignment
operator, "==" the comparison operator, and "=" totally invalid!  Although
I haven't made that mistake more than twice in the past year, the memories
of debugging (without a lint/Saber available) for hours, just to find a case
of that common mistake, stay with me... (-:

James Craig Burley, Software Craftsperson    burley@world.std.com

gordon@osiris.cso.uiuc.edu (John Gordon) (09/07/90)

	One way to avoid the =/== pitfall is to write your code like this:

	if(7 == x) rather than if(x == 7).

	If you write it the first way, and accidentally write = instead of ==,
	you will be trying to assign a value to a constant (!!) and will get
	an error.


---
John Gordon
Internet: gordon@osiris.cso.uiuc.edu        #include <disclaimer.h>
          gordon@cerl.cecer.army.mil       #include <clever_saying.h>
GEnie:    j.gordon14                  

jh4o+@andrew.cmu.edu (Jeffrey T. Hutzelman) (09/07/90)

John,
    Good idea; it works great as long as you aren't trying to compare 2
variables.  However, I think the intent of the original code was to
perform an assignment and then do a test on the result (look carefully;
there's a > or < in there somewhere), similar to the following, which I
use all the time:

if ( ( file_ptr = fopen (filename, mode) ) == NULL )
	{
	/* print a message and exit */
	}

-----------------
Jeffrey Hutzelman
America Online: JeffreyH11
Internet/BITNET:jh4o+@andrew.cmu.edu, jhutz@drycas.club.cc.cmu.edu

>> Apple // Forever!!! <<

george@hls0.hls.oz (George Turczynski) (09/10/90)

In article <1990Sep5.185451.25532@DRD.Com> mark@DRD.Com (Mark Lawrence) writes:
> 
>    I have a proclivity to code like the following:
> 
>       if( (status = FuncCall(foo, bar, gex)) < SomeValue)
> 	      GripeAboutIt();
> 
>    or variations thereof.  When I run saber on such code, it babbles a 
>    warning about the assignment in the test.  Being the gullible naif I am, 

>	...

Oh, it babbles does it ?  What does it babble ?  In future it would be
more useful to know what the warning is about, rather than have someone
tell you what their `opinion' of your code is.  Opinions mean very little.
I might "guess" that perhaps Saber complains because the variable type
of `status' and the return type of `FuncCall()' are different.  In that
case you may have omitted a vital header file or not performed a necessary
CAST.  Who knows ?

Now ...

In article <BURLEY.90Sep6024459@world.std.com>, burley@world.std.com (James C Burley) writes:
> Your code is fine IMHO.  But suppose you had written the following
> accidentally:
> 
>     if (foo = 0)
> 
> This is a common mistake.

(typing mistake ?)

This is only a mistake if you don't know what you're doing (or you have a
typo, in which case it's only a mistake for a short while).  It is, in fact,
perfectly legal C, but isn't what people sometimes want it to mean.

> ...... is just trying to get you to look at ifs containing assignments, just
> in case you meant to say "if (foo == 0)".  In your particular example, I'd

Does Saber warn you that you might have mispelt a variable name ?  I doubt
it.  It should only bother you with DEFINITE problems or things that it is
unsure about.  Lint is for finding out more detailed, obscure and discrete
problems.

> BTW, if I ever write a new C-like language, ":=" will be the assignment
> operator, "==" the comparison operator, and "=" totally invalid!  Although

I will be very cautious of such a language.

-- 
| George P. J. Turczynski.          |---------------------------------------------------- 
| Computer Systems Engineer.        | ACSnet: george@highland.oz | I can't speak for the |
| Highland Logic Pty. Ltd.          | Phone: +61 48 683490       | company, I can barely |
| Suite 1, 348-354 Argyle St        | Fax:   +61 48 683474       | speak for myself...   |
| Moss Vale. NSW. Australia. 2577   |---------------------------------------------------- 

rns@se-sd.SanDiego.NCR.COM (Rick Schubert) (09/11/90)

In <1990Sep7.042759.3804@ux1.cso.uiuc.edu> gordon@osiris.cso.uiuc.edu (John Gordon) writes:

>	One way to avoid the =/== pitfall is to write your code like this:

>	if(7 == x) rather than if(x == 7).

>	If you write it the first way, and accidentally write = instead of ==,
>	you will be trying to assign a value to a constant (!!) and will get
>	an error.

I have seen this suggestion in this newsgroup quite a few times in the past
and I always wonder:

    If you remember to put the constant on the left, won't you also remember
to use `==' rather than `='?

[Personally, I think `if(7 == x) is ugly.]

-- Rick Schubert (rns@se-sd.sandiego.NCR.COM)

cpcahil@virtech.uucp (Conor P. Cahill) (09/11/90)

In article <928@hls0.hls.oz> george@hls0.hls.oz (George Turczynski) writes:
>In article <BURLEY.90Sep6024459@world.std.com>, burley@world.std.com (James C Burley) writes:
>> Your code is fine IMHO.  But suppose you had written the following
>> accidentally:
>> 
>>     if (foo = 0)
>> 
>> This is a common mistake.
>
>(typing mistake ?)
>
>This is only a mistake if you don't know what you're doing (or you have a
>typo, in which case it's only a mistake for a short while).  It is, in fact,
>perfectly legal C, but isn't what people sometimes want it to mean.

This is a BIG mistake because of any and all of the following:

	1. you might have made a typo
	2. someone else will have to determin if you might
	   have made a typo
	3. If it was a typo, these kinds of problems sometimes don't show
	   themselves for years and can be the hardest things to debug because
	   even though there is only a single = there you keep reading the
	   code and seeing two of them.

The fact that it is legal C doesn't really matter here.  That kind of
coding just makes maintenance harder.


-- 
Conor P. Cahill            (703)430-9247        Virtual Technologies, Inc.,
uunet!virtech!cpcahil                           46030 Manekin Plaza, Suite 160
                                                Sterling, VA 22170 

robert@isgtec.uucp (Robert Osborne) (09/11/90)

In article <1990Sep5.185451.25532@DRD.Com> mark@drd.Com (Mark Lawrence) writes:
> [about Saber C warnings for the code...]
>    if( (status = FuncCall(foo, bar, gex)) < SomeValue)
> 	   GripeAboutIt();
>
Does this code yield the warning:
	Assignment in conditional 'if' expression.
I'm not sure of you exact syntax but I've run similiar code through
Saber and it didn't even blink.  We have Saber C here and I've only
ever seen this warning on code that had the form if(x = func(...)).
If the warning is not as above Saber's complaining about something else.

Disclaimer and unabashed recommendation:
	I have no association with Saber Software Inc., other than as
	a very happy user.   Warning:  The use of Saber C is habit
	forming and getting a Saber C demo tape has been known to cause
	purchase soon after.  I heartily recommend this product.  (ISG
	has several licences so they probably agree with me :-)

Rob.
--
Robert A. Osborne   ...uunet!utai!lsuc!isgtec!robert or robert@isgtec.uucp

bomgard@iuvax.cs.indiana.edu (Tim Bomgardner) (09/11/90)

In article <3836@se-sd.SanDiego.NCR.COM> rns@se-sd.SanDiego.NCR.COM (Rick Schubert) writes:
}In <1990Sep7.042759.3804@ux1.cso.uiuc.edu> gordon@osiris.cso.uiuc.edu (John Gordon) writes:
}
}>	One way to avoid the =/== pitfall is to write your code like this:
}
}>	if(7 == x) rather than if(x == 7).
}
}>	If you write it the first way, and accidentally write = instead of ==,
}>	you will be trying to assign a value to a constant (!!) and will get
}>	an error.
}
}I have seen this suggestion in this newsgroup quite a few times in the past
}and I always wonder:
}
}    If you remember to put the constant on the left, won't you also remember
}to use `==' rather than `='?
}
}[Personally, I think `if(7 == x) is ugly.]
}
}-- Rick Schubert (rns@se-sd.sandiego.NCR.COM)

I agree, 'if(7 == x)' is ugly.  It makes me stop, back up, and reread.  My 
conditionals all look like Fortran: 'if (x EQ 7 OR y LT 3)'.  Guess you can
tell where *I* grew up.  Haven't had a problem in years, except once from
someone who was reusing some of my code.

dold@mitisft.Convergent.COM (Clarence Dold) (09/12/90)

in article <1990Sep11.003102.9271@virtech.uucp>, cpcahil@virtech.uucp (Conor P. Cahill) says:

>>>     if (foo = 0)

> This is a BIG mistake because of any and all of the following:

> 	2. someone else will have to determin if you might
> 	   have made a typo

> The fact that it is legal C doesn't really matter here.  That kind of
> coding just makes maintenance harder.

I saw this in some code posted to the net awhile ago:

   if (foo = 0)		/* Really an assignment */

Which is at least intelligible, and (possibly) rules out item 2 above.
I still don't think it is good coding practice.

As someone who makes a living reading other people's code, I wish more
people would not try to outwit the compilers, and just buy a better 
compiler.

-- 
---
Clarence A Dold - dold@tsmiti.Convergent.COM            (408) 435-5293
               ...pyramid!ctnews!tsmiti!dold        FAX (408) 435-3105
               P.O.Box 6685, San Jose, CA 95150-6685         MS#10-007

jeremy@sinope.socs.uts.edu.au (Jeremy Fitzhardinge) (09/12/90)

george@hls0.hls.oz (George Turczynski) writes:

>In article <BURLEY.90Sep6024459@world.std.com>, burley@world.std.com (James C Burley) writes:
>> Your code is fine IMHO.  But suppose you had written the following
>> accidentally:
>> 
>>     if (foo = 0)
>> 
>> This is a common mistake.

My friendly local compiler would say "Constant conditional branch" to this -
a useful warning.  Annoyingly this also pops up with "while(1)" (but not
"for(;;)"). Of course this doesn't help with "if (i = TestThing())", however
this is quite a useful construct.  How many would prefer
	if (thing != NULL)
	{
		fp = fopen(thing, "r");
		if (fp == NULL)
			barf();
	}
to
	if (thing && (fp = fopen(thing, "r"))
		barf();
?

>This is only a mistake if you don't know what you're doing (or you have a
>typo, in which case it's only a mistake for a short while).  It is, in fact,
>perfectly legal C, but isn't what people sometimes want it to mean.
>
>> ...... is just trying to get you to look at ifs containing assignments, just
>> in case you meant to say "if (foo == 0)".  In your particular example, I'd
>
>> BTW, if I ever write a new C-like language, ":=" will be the assignment
>> operator, "==" the comparison operator, and "=" totally invalid!  Although

If you are going to prevent assignment in a conditional, you are preventing
it from being an expression.  This stops things like "a=b=c=0;" from falling
out elegantly.  If you are deadset about making C have the cumbersome expressions
of pascal, you may as well drop the '++', '+=', '--', '-=' operators, and give
'and' a higher precidence than everything else (having decided && is too hard
to type properly).


--
Jeremy Fitzhardinge: jeremy@ultima.socs.uts.edu.au  | To make an omelette, you
No Comment.          jeremy@utscsd.csd.uts.edu.au   | gotta break eggs.
                                                    |                -J.Stalin

chris@mimsy.umd.edu (Chris Torek) (09/12/90)

In article <18326@ultima.socs.uts.edu.au> jeremy@sinope.socs.uts.edu.au
(Jeremy Fitzhardinge) writes:				[??? .edu.au ???]
>... How many would prefer
>	if (thing != NULL)
>	{
>		fp = fopen(thing, "r");
>		if (fp == NULL)
>			barf();
>	}
>to
>	if (thing && (fp = fopen(thing, "r"))
>		barf();
>?

I would, along with most compilers: the second version has an unclosed
left parenthesis. :-)

Anyway, I would (and often do) rewrite examples like the latter as

	if (thing && (fp = fopen(thing, "r")) != NULL)
		barf();

or

	if (thing != NULL && (fp = fopen(thing, "r")) != NULL)
		barf();

(NB: this is what the second quoted example does when the missing close
paren is added, and differs from what the first quoted example does.
In pseudo-code, this is

	if we have a filename and the file can be read
		call barf

while the first quoted example is

	if we have a file name, but the file cannot be read
		call barf

As usual, when making code concise you must be sure to keep it
correct.)
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 405 2750)
Domain:	chris@cs.umd.edu	Path:	uunet!mimsy!chris

burley@world.std.com (James C Burley) (09/12/90)

In article <18326@ultima.socs.uts.edu.au> jeremy@sinope.socs.uts.edu.au (Jeremy Fitzhardinge) writes:

   >> BTW, if I ever write a new C-like language, ":=" will be the assignment
   >> operator, "==" the comparison operator, and "=" totally invalid!  Although

   If you are going to prevent assignment in a conditional, you are preventing
   it from being an expression.  This stops things like "a=b=c=0;" from falling
   out elegantly.  If you are deadset about making C have the cumbersome expressions
   of pascal, you may as well drop the '++', '+=', '--', '-=' operators, and give
   'and' a higher precidence than everything else (having decided && is too hard
   to type properly).


   --
   Jeremy Fitzhardinge: jeremy@ultima.socs.uts.edu.au  | To make an omelette, you
   No Comment.          jeremy@utscsd.csd.uts.edu.au   | gotta break eggs.
						       |                -J.Stalin

I think I was adequately clear in my original comment.  I said exactly what I
meant: if I was designing a new language to be at a C (or C++) level of
power and expressability, but with no compatibility requirements, I would
specify ":=" as the assignment operator, "==" as the comparison operator,
and make "=" by itself an error (at least as a default; perhaps allow people
to "override" this definition if they want).

I said nothing about disallowing assignment in conditionals.  The fact that I
called ":=" the assignment OPERATOR instead of a flag for an assignment
STATEMENT should have been more than adequate to indicate my intentions.
Put another way, I simply would replace the text "=" for the assignment lexeme
with ":=".  Everything else (how it is used and such) would remain the same.

The point is, casual reading of code containing a mistake like

    if (foo = 0)

compared to an equivalent

    if (foo := 0)

one can easily conclude the mistake is easier to find in the latter case.

I doubt anyone could seriously disagree with an argument that it would have
saved much unnecessary debugging effort if, from the beginning, K&R had
realized that making "=" an assignment OPERATOR (thus allowing it to work as
an operator inside an expression) was a mistake -- it meant they had to make
"==" the comparison operator, which no other language I know of ever had to,
because others do not allow assignment as an operator.  Given that most people
would at one point or another accidentally use "=" instead of "==", it would
have been great (20-20 hindsight) if they'd realized this from the beginning
and made ":=" or some such thing the assignment operator, leaving "=" out of
the picture.  Perhaps C fanatics will disagree with this, but I don't take
seriously people who essentially would say "no, '=' is Right because I'm used
to it" when I'm saying if it had been ':=' from the beginning, THAT is what
we'd all be used to, without having to have gone through RUN-time debugging
to find our early mistakes.  (We'd find most or all of these kinds of bugs at
compile time.)

Then there are those languages that require "=<" instead of "<=" as the
"less than or equals" operator, so they can have "<=" mean something else
(implied-by, or something like that), and I think they are repeating the
same mistake unless they have such strong typing that they'll ALWAYS catch
any case where a programmer forgets and uses "<=" instead of "=<".

James Craig Burley, Software Craftsperson    burley@world.std.com

bruce@seismo.gps.caltech.edu (Bruce Worden) (09/13/90)

In article <BURLEY.90Sep12073323@world.std.com> burley@world.std.com (James C Burley) writes:
>The point is, casual reading of code containing a mistake like
>
>    if (foo = 0)
>
>compared to an equivalent
>
>    if (foo := 0)
>
>one can easily conclude the mistake is easier to find in the latter case.

If the `:=' is for assignment and `==' for comparison and both

	if(foo := 0)
and

	if(foo == 0)

are legal, I don't see how `:=' is any better than just `='.  People who
are used to thinking of `:=' as `equal' will type it as freely as we 
type `='.  Only something like Fortran's .EQ. is different enough to 
draw attention to the two different meanings of `is equal to'.

The following is a general comment and is not directed specifically at
Mr. Burley:
I have made the `if(x = y)' mistake myself, but it is always relatively 
easy to find because I would never intentionally write that construct.  
C gives us the ability to be extremely clever by writing things like:

	while(thisfunc(a=(b++ * thatfunc(c=d--))))
	...

but that doesn't mean we should do it.  It might impress some people, but
it is extremely cryptic and there is usually a clearer way to write the
code to do the same thing.  Likewise, if one always writes:

	x = y;
	if(x)
	...

it is not as spiffy looking as `if(x = y)', but it is just as efficient to 
execute and is unambiguous.  I am not objecting to constructs like:

	if((fd=open(path,flags,mode)) != NULL)
	...

but, in those cases, I always make the comparison explicit.
--------------------------------------------------------------------------
C. Bruce Worden                            bruce@seismo.gps.caltech.edu
252-21 Seismological Laboratory, Caltech, Pasadena, CA 91125

brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (09/13/90)

In article <1599@mitisft.Convergent.COM> dold@mitisft.Convergent.COM (Clarence Dold) writes:
> I saw this in some code posted to the net awhile ago:
>    if (foo = 0)		/* Really an assignment */
> Which is at least intelligible, and (possibly) rules out item 2 above.
> I still don't think it is good coding practice.

Probably not, as the if will always evaluate to false. :-)

---Dan

brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (09/13/90)

In article <18326@ultima.socs.uts.edu.au> jeremy@sinope.socs.uts.edu.au (Jeremy Fitzhardinge) writes:
> >> BTW, if I ever write a new C-like language, ":=" will be the assignment
> >> operator, "==" the comparison operator, and "=" totally invalid!  Although
> If you are going to prevent assignment in a conditional, you are preventing
> it from being an expression.  This stops things like "a=b=c=0;" from falling
> out elegantly.

Q has == for comparison, = for assignment with no value, and := for
assignment with a value. (Among others.) So ``a = b'' still works,
``if (a = b)'' is illegal, and the compiler can check all statements
for unused values. The only correct code that has to be rewritten is
``a = b = c = d'' (as ``a = b := c := d'') and a proper ``if (a = b)''
(as ``if (a := b)'').

Followups to alt.lang.cfutures.

---Dan

userAKDU@mts.ucs.UAlberta.CA (Al Dunbar) (09/13/90)

In article <BURLEY.90Sep12073323@world.std.com>, burley@world.std.com (James C Burley) writes:
>In article <18326@ultima.socs.uts.edu.au> jeremy@sinope.socs.uts.edu.au (Jeremy Fitzhardinge) writes:
>
>   >> BTW, if I ever write a new C-like language, ":=" will be the assignment
>   >> operator, "==" the comparison operator, and "=" totally invalid!  Although
>
>   If you are going to prevent assignment in a conditional, you are preventing
>  <stuff deleted>>
>I doubt anyone could seriously disagree with an argument that it would have
>saved much unnecessary debugging effort if, from the beginning, K&R had
>realized that making "=" an assignment OPERATOR (thus allowing it to work as
>an operator inside an expression) was a mistake -- it meant they had to make
>"==" the comparison operator, which no other language I know of ever had to,
>because others do not allow assignment as an operator.  Given that most people
>would at one point or another accidentally use "=" instead of "==", it would
>have been great (20-20 hindsight) if they'd realized this from the beginning
>and made ":=" or some such thing the assignment operator, leaving "=" out of
>the picture.  .....
 
Originally being a Fortran person, the ":=" assignment operator
always seemed to me an abomination, both in terms of style and
inconvenience. Now that I spend more time with C, the =/==
problem (to say nothing of &/&& etc) hasn't bothered me as much
as I once thought it would. This isn't to say that I haven't made
the dreaded mistake, of course. But that's not my point. My point
is that I don't recall anyone confusing the assignment and
comparison operators in (at least pre-90) Fortran:
 
A .EQ. B + C
IF(A = D) GOTO 999
 
The reason is twofold: a) the compiler doesn't allow either
substitution, and b) '=' and '.EQ.' do not look at all alike.
It is just too bad that there are not enough special punctuation
marks to allow unambiguous use of single character operators for
such things as ==, <=, &&, etc.
 
-------------------+-------------------------------------------
Al Dunbar          |
Edmonton, Alberta  |   this space for rent
CANADA             |
-------------------+-------------------------------------------

ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) (09/13/90)

In article <BURLEY.90Sep12073323@world.std.com>, burley@world.std.com (James C Burley) writes:
> Perhaps C fanatics will disagree with this, but I don't take
> seriously people who essentially would say "no, '=' is Right because I'm used
> to it" when I'm saying if it had been ':=' from the beginning, THAT is what
> we'd all be used to, without having to have gone through RUN-time debugging
> to find our early mistakes.

History lesson:  it *WAS* ":=" in the beginning.
C is descended (via B) from BCPL, in which assignment is ":=".
Evidently someone along the way _did_ believe that ":=" was Wrong.
(Actually, Pop admirers know that the Right way is "rvalue -> lvalue". (:-))

-- 
Heuer's Law:  Any feature is a bug unless it can be turned off.

ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) (09/13/90)

In article <1990Sep12.194753.9808@laguna.ccsf.caltech.edu>, bruce@seismo.gps.caltech.edu (Bruce Worden) writes:
> are legal, I don't see how `:=' is any better than just `='.  People who
> are used to thinking of `:=' as `equal' will type it as freely as we 
> type `='.

But there _are_ no people who are used to thinking of ":=" as "equal".
Algol 60, Algol 68, Pascal, Modula, Modula-2, Modula-3, MESA, Ada,
BCPL, ... all use ":=" for assignment.  Is there any well known language
that uses ":=" for equality?  Surely not.

> Only something like Fortran's .EQ. is different enough to 
> draw attention to the two different meanings of `is equal to'.

What "two different meanings"?  Assignment is _not_ a meaning of
"is equal to" and never has been.

> I am not objecting to constructs like:
> 	if((fd=open(path,flags,mode)) != NULL)

You _should_.  Assuming POSIX for open() and ANSI C for NULL,
open() returns an int but NULL may be of type (void *).
The real trouble would come if your C used the other ANSI-blessed
value for NULL, namely 0.  The error value for open() is -1, not 0.
Use
	if ((fd = open(path, flags, mode)) != -1) {
	    ...
	}
-- 
Heuer's Law:  Any feature is a bug unless it can be turned off.

jk@cs.man.ac.uk (John Kewley ICL) (09/14/90)

In article <1990Sep12.194753.9808@laguna.ccsf.caltech.edu>, bruce@seismo.gps.caltech.edu (Bruce Worden) writes:
> are legal, I don't see how `:=' is any better than just `='.  People who
> are used to thinking of `:=' as `equal' will type it as freely as we 
> type `='.
>
> Only something like Fortran's .EQ. is different enough to 
> draw attention to the two different meanings of `is equal to'.
>
> I am not objecting to constructs like:
> 	if((fd=open(path,flags,mode)) != NULL)

My first real language I learnt was a language called S-Algol developed at
St. Andrews University. It had several neat features that were helpful to
novice programmers, the relevent one in this case being:

	let x = 3	! x is a constant of value 3
	let y := 4	! y is a variable of value 4
	y := 5		! assign 5 to variable y
	if y = 5
	then
		write "y = 5'n"
	else
		write "y ~= 5'n"
	for i = 1 to y
	do
		write "i = ", i, "'n"

Types were inferred from expressions provided.

Note that equality and initialisation of constants both use "=" and
that assignment and initialisation of variables use ":="

What to some might be counter-intuitive is that instead of a looping
variable, S-Algol has a looping constant which cannot be altered during the
loop (since it is constant).

S-Algol had many other "nice" features and proved excellent for
programming-in-the-small.
--
        J.K.
 
John M. Kewley, ICL, Wenlock Way, West Gorton, Manchester. M12 5DR
Tel:   (+44) 61 223 1301 X2138  Email: jk@r6.cs.man.ac.uk / jk@nw.stl.stc.co.uk

bruce@seismo.gps.caltech.edu (Bruce Worden) (09/14/90)

In article <3749@goanna.cs.rmit.oz.au> ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) writes:
Quoting me:
>> are legal, I don't see how `:=' is any better than just `='.  People who
>> are used to thinking of `:=' as `equal' will type it as freely as we 
>> type `='.

>But there _are_ no people who are used to thinking of ":=" as "equal".
>Algol 60, Algol 68, Pascal, Modula, Modula-2, Modula-3, MESA, Ada,
>BCPL, ... all use ":=" for assignment.  Is there any well known language
>that uses ":=" for equality?  Surely not.

But that was not my point and I am not interested in arguing with you about 
what goes through people's minds when they type `=' as opposed to `:='.  
Apparently it would be futile for me since you seem to know what every person
in the world thinks when he encounters `:=', or, at least, what he doesn't 
think.

(I think of `=' as `equals' and `==' as `equals equals' when I am typing 
them--arguably the worst possible way to think about it, but I have only made 
the error in question twice and in both cases it was a typing error not a 
logical one.  I would think of `:=' as `equals', too, along with almost any
other symbol that did the same job.  If you really want to emphasize the 
assignment nature of expressions like `x = y;', then an equal sign has no 
place in the symbol you use to do it.  How about `let x take on the value of 
y;'?  No ambiguity there.)

>> Only something like Fortran's .EQ. is different enough to 
>> draw attention to the two different meanings of `is equal to'.

>What "two different meanings"?  Assignment is _not_ a meaning of
>"is equal to" and never has been.

What, now I have to argue semantics with a guy who uses underscores to
(apparently) emphasize words in English sentences?  (Especially since
they don't need emphasizing in the first place.)  Nobody that wrote to
me had this problem; they all knew what I was talking about (even if 
they didn't agree with me.)  Are you being deliberately obtuse?

>> I am not objecting to constructs like:
>> 	if((fd=open(path,flags,mode)) != NULL)

>You _should_.  Assuming POSIX for open() and ANSI C for NULL,... [ complains,
> gives example ]

There you go again.  Since I did not define any of the identifiers and
I specifically mentioned the construct (in the context of the rest of
this discussion), you don't have any business assuming anything except 
that the example is written in C.  Just because it looks like the standard 
library open() does not mean that it is.  It so happens that open() in the 
example above is defined as `static struct data *open()' and is used within a 
small database library.  Now don't you feel silly?  You should.

>Heuer's Law:  Any feature is a bug unless it can be turned off.

Hmmmm, looks like a case of Heuer worship.

--------------------------------------------------------------------------
C. Bruce Worden                            bruce@seismo.gps.caltech.edu
252-21 Seismological Laboratory, Caltech, Pasadena, CA 91125

darcy@druid.uucp (D'Arcy J.M. Cain) (09/14/90)

In article <57945@iuvax.cs.indiana.edu> bomgard@iuvax.cs.indiana.edu (Tim Bomgardner) writes:
>In article <3836@se-sd.SanDiego.NCR.COM> rns@se-sd.SanDiego.NCR.COM (Rick Schubert) writes:
>}In <1990Sep7.042759.3804@ux1.cso.uiuc.edu> gordon@osiris.cso.uiuc.edu (John Gordon) writes:
>}>	One way to avoid the =/== pitfall is to write your code like this:
>}>	if(7 == x) rather than if(x == 7).
>}    If you remember to put the constant on the left, won't you also remember
>}to use `==' rather than `='?
>conditionals all look like Fortran: 'if (x EQ 7 OR y LT 3)'.  Guess you can
>tell where *I* grew up.  Haven't had a problem in years, except once from
>someone who was reusing some of my code.

Which is the problem with that sort of code.  You can't give C code disguised
as FORTRAN to a C programmer and expect them to be comfortable with it.  I
like to do the following;

    if ((x = 7) != 0)

It makes the intention perfectly obvious to any other C programmer and most
compilers will optimize it anyway.  The Borland compiler has settings that
flag the 'if (x = 7)' construct as a warning and I use this on the DOS side.
It has caught a few typos for me.

-- 
D'Arcy J.M. Cain (darcy@druid)     |
D'Arcy Cain Consulting             |   MS-DOS:  The Andrew Dice Clay
West Hill, Ontario, Canada         |   of operating systems.
+ 416 281 6094                     |

darcy@druid.uucp (D'Arcy J.M. Cain) (09/14/90)

In article <18326@ultima.socs.uts.edu.au> jeremy@sinope.socs.uts.edu.au (Jeremy Fitzhardinge) writes:
>this is quite a useful construct.  How many would prefer
>	if (thing != NULL)
>	{
>		fp = fopen(thing, "r");
>		if (fp == NULL)
>			barf();
>	}
>to
>	if (thing && (fp = fopen(thing, "r"))
>		barf();
>?
I think I prefer the former since the second version has a bug.  I think you
meant to say:
    if (thing && ((fp = fopen(thing, "r")) == NULL)
and just as a matter of style I would use:
    if ((thing != NULL) && ((fp = fopen(thing, "r")) == NULL)

And that solves the =/== problem as well.

I suppose you may also have meant
    if ((thing == NULL) || ((fp = fopen(thing, "r")) == NULL)
unless the 'file not named' error is handled elsewhere.

-- 
D'Arcy J.M. Cain (darcy@druid)     |
D'Arcy Cain Consulting             |   MS-DOS:  The Andrew Dice Clay
West Hill, Ontario, Canada         |   of operating systems.
+ 416 281 6094                     |

gaynor@sparky.rutgers.edu (Silver) (09/14/90)

I don't have any problems with the concept of performing assignments and other
destructive things in conditionals.  The only reason why people question the
practice in C is because the stupid equality and assignment operators appear so
similar.  If I had my way, assignment would be `<-' and equality, `='.  Hmm...
Given the relationships between &/&&/&= and |/||/|=, `=' should probably be
bitwise equality (i.e., `a == b' would be equivalent to `~(a ^ b)'), `=='
should probably be logical equality, and `=<-' should probably apply to the
bitwise version.  But I could imagine people messing up that even worse than
the current set-up.

Regards, [Ag]

robert@isgtec.uucp (Robert Osborne) (09/14/90)

In article <928@hls0.hls.oz> george@hls0.hls.oz (George Turczynski) writes:
> [complains that Saber shouldn't warn about if( x = y ) that's what
>  lint is for.]
> Does Saber warn you that you might have mispelt a variable name ?  I doubt
> it.  It should only bother you with DEFINITE problems or things that it is
> unsure about.  Lint is for finding out more detailed, obscure and discrete
> problems.
One of the biggest advantages of Saber as a debugger is that you can modify
source and reload ONLY that source file (reloading a source file takes about
a second) and immediately start debugging again.  Since the first step of
any debug session should be to lint the source, the fact that Saber does
this is a HUGH advantage.

I don't understand why you don't like a debugging tool
with a built in lint?

Rob.
--
Robert A. Osborne   ...uunet!utai!lsuc!isgtec!robert or robert@isgtec.uucp

brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (09/15/90)

As I understand the argument here, Bruce is saying that := vs. == is no
better than = vs. ==, for if C's = had been := instead, people would
have the same confusion. := does have the definite advantage that you
can't mistype it in place of an == so easily, and = does have the
disadvantage that if (a = b) reads well as ``if a equals b''
mathematically.

To some extent, though, Bruce is right: once people think of symbol X as
meaning equality, they'll try writing ``if (a X b)''. The language must
catch this, no matter what X is. The symbol that people use most of the
time in assignments must not return a value. As long as it does, this
problem will remain.

Splitting off := for assignments that do return a value is enough.
People will use = except in situations like a = b := c := d, so they'll
be used to = for equality. When they write if (a = b), the compiler will
catch the mistake.

Bruce, am I right in thinking that =/:=/== would satisfy you?

---Dan

bruce@seismo.gps.caltech.edu (Bruce Worden) (09/18/90)

In article <14316:Sep1511:00:2390@kramden.acf.nyu.edu> brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes:

> [ material deleted ]
>Bruce, am I right in thinking that =/:=/== would satisfy you?

Well, not really, though it is an interesting idea.  I think that it might 
just add to the confusion that some people already seem to be experiencing 
on this issue.  On that note, I was assuming that people writing `if(x = y)' 
and meaning `if(x == y)' were just making some mechanical error.  It has 
been brought to my attention, however, that the problem may be caused by a 
confusion of the `=' symbol in C with that of some other language, by 
someone who regularly programs in multiple languages.  In such a case the 
bug would be much harder to find.  While I could take a hard line and say 
that anyone programming in C should know what the operators are, I will ask 
a question instead: For those of you who regularly program in several 
languages, how big a problem is this, and would changing `=' to `:=' really 
fix it?  If it turns out to be a significant problem, maybe it could be 
changed.  I think there is a newsgroup `cfutures' that could discuss the 
change.  Mr. Bernstein's suggestion could be considered as well. 
--------------------------------------------------------------------------
C. Bruce Worden                            bruce@seismo.gps.caltech.edu
252-21 Seismological Laboratory, Caltech, Pasadena, CA 91125

steve@taumet.com (Stephen Clamage) (09/18/90)

bruce@seismo.gps.caltech.edu (Bruce Worden) writes:

>In article <14316:Sep1511:00:2390@kramden.acf.nyu.edu> brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes:

>... I was assuming that people writing `if(x = y)' 
>and meaning `if(x == y)' were just making some mechanical error.  It has 
>been brought to my attention, however, that the problem may be caused by a 
>confusion of the `=' symbol in C with that of some other language, by 
>someone who regularly programs in multiple languages.

I sometimes switch between Pascal and C/C++ several times in one day, and
it is a bit confusing.  It isn't that I don't "know" (or that I "forget")
the different versions of assignment and comparison operators.  It is
more a question of "shifting gears" fully.  I find it is like switching
between text editors, or between similar musical instruments.  Habits
carry over, and it takes a little time (minutes or hours) to fully
move into the new mode.  The problem is worse if I am tired or
distracted.
-- 

Steve Clamage, TauMetric Corp, steve@taumet.com

karl@haddock.ima.isc.com (Karl Heuer) (09/19/90)

I suppose that using `:=' would resolve% the problem, in much the same way
that the key-jamming problem was resolved by inventing the pessimal QWERTY.

Karl W. Z. Heuer (karl@kelp.ima.isc.com or ima!kelp!karl), The Walking Lint
________
% I can hardly call it a `fix'.  For me, typing `=' for `==' is no more likely
  than typing `==' for `=' (which I *have* done at least once), and the cure
  would be worse than the disease.  `:=' is almost as clumsy to type as that
  stupid regexp notation `\( \)'.

brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (09/19/90)

In article <18063@haddock.ima.isc.com> karl@kelp.ima.isc.com (Karl Heuer) writes:
> `:=' is almost as clumsy to type as that
>   stupid regexp notation `\( \)'.

I agree! That's why Q lets you use = in 99% of the cases where you'd use
it in C. You only have to resort to := when you want to use the assigned
value in an expression.

---Dan

news@macuni.mqcc.mq.oz (USENET News System) (09/19/90)

In article <Sep.14.10.39.43.1990.17114@sparky.rutgers.edu> gaynor@sparky.rutgers.edu (Silver) writes:
>similar.  If I had my way, assignment would be `<-' and equality, `='.  Hmm...

So 
	if (a<-1) {
		...
	}
takes on a whole new meaning ... (and always succeeds!) IMHO this is even
more confusing than the =/== debate.
Regards
JamesPW

subbarao@phoenix.Princeton.EDU (Kartik Subbarao) (09/19/90)

>In article <Sep.14.10.39.43.1990.17114@sparky.rutgers.edu> gaynor@sparky.rutgers.edu (Silver) writes:
>>similar.  If I had my way, assignment would be `<-' and equality, `='.  Hmm...
>
>So 
>	if (a<-1) {
>		...
>	}
>takes on a whole new meaning ... (and always succeeds!) IMHO this is even
>more confusing than the =/== debate.


My My -- You must be an S programmer, where <- IS the assignment operator.
But now how do I say ``If a is less then -1''? 


			-Kartik




subbarao@{phoenix,bogey or gauguin}.Princeton.EDU -|Internet
kartik@silvertone.Princeton.EDU (NeXT mail)       -|	
subbarao@pucc.Princeton.EDU		          - Bitnet

robert@cs.arizona.edu (Robert J. Drabek) (09/19/90)

Kartik Subbarao writes:
> 
> But now how do I say ``If a is less then -1''? 
> 

You would write

    if (a < )
      -1;

Of course, you've forgotten to specify what you want to compare `a' with.
English can be as unforgiving as C.  8-)

-- 
Robert J. Drabek                            robert@cs.Arizona.EDU
Department of Computer Science              uunet!arizona!robert
The University of Arizona                   602 621 4326
Tucson, AZ  85721

jon@jonlab.UUCP (Jon H. LaBadie) (09/19/90)

In article <14316:Sep1511:00:2390@kramden.acf.nyu.edu>, brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes:
> 
> Splitting off := for assignments that do return a value is enough.
> People will use = except in situations like a = b := c := d, so they'll
> be used to = for equality. When they write if (a = b), the compiler will
> catch the mistake.
> 
> Bruce, am I right in thinking that =/:=/== would satisfy you?

How long will this continue?
Now we should think "gee, do I want THIS assignment to yield a value
or simply do an assignment?".

BTW Dan, I think it should be yield, or evaluate to, a value, not
         return a value.

One of the many virtues of C is that assignment IS an operator and
DOES yield a value.

If you spend countless hours debugging code because of mistyping the
assignment operator when you meant the equality comparison operator,
then get a copy of "ccheck".  I think it was posted to c.s.m.  It
reports (does not say it is wrong) instances of assignments in
contexts where comparison is expected.  Use it as religously as
you do lint.  It will reduce your debugging dramatically.

This part of the language is not broken, don't try to fix it.

Jon


-- 
Jon LaBadie
{att, princeton, bcr, attmail!auxnj}!jonlab!jon

henry@zoo.toronto.edu (Henry Spencer) (09/19/90)

In article <1335:Sep1901:50:0490@kramden.acf.nyu.edu> brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes:
>> `:=' is almost as clumsy to type as that
>>   stupid regexp notation `\( \)'.
>
>I agree! That's why Q lets you use = in 99% of the cases where you'd use
>it in C. You only have to resort to := when you want to use the assigned
>value in an expression.

So why not just insist on proper parenthesization and testing of the value
in an expression -- that is, the clean and readable

	if ((c = getchar()) != '\0')

rather than the cryptic and confusing

	if (c = getchar())

and leave the operator alone?  Then you have the further bonus that it's
not a new language, just a fussier compiler.
-- 
TCP/IP: handling tomorrow's loads today| Henry Spencer at U of Toronto Zoology
OSI: handling yesterday's loads someday|  henry@zoo.toronto.edu   utzoo!henry

brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (09/20/90)

In article <859@jonlab.UUCP> jon@jonlab.UUCP (Jon H. LaBadie) writes:
> BTW Dan, I think it should be yield, or evaluate to, a value, not
>          return a value.

Not if you don't distinguish between operators and functions.

> One of the many virtues of C is that assignment IS an operator and
> DOES yield a value.

Right. That's why you need to preserve that function, as :=. But
changing the common = to not return a value will not affect 99% of the
lines in a typical program, and it will catch the beginner's if (a = b).

> This part of the language is not broken, don't try to fix it.

You're taking entirely the wrong attitude. If beginners slip up
regularly on a language feature, and there's a straightforward way to
change the feature, then the feature should be changed (at least in
future languages). Just because you and I don't make a particular
mistake doesn't mean the language shouldn't prevent the mistake.

Furthermore, =/:=/== has an important benefit: The code-checker no
longer needs to special-case a = b when it's looking for ignored values.

The distinction between = and := is entirely logical, would eliminate
one source of frustration everywhere, and helps the compiler. What more
do you want?

---Dan

gaynor@sparky.rutgers.edu (Silver) (09/20/90)

gaynor@sparky.rutgers.edu (Silver, Moi) wrote:
> If I had my way, assignment would be `<-' and equality, `='.

news@macuni.mqcc.mq.oz (JamesPW) responds:
> So 
>	if (a<-1) {
>		...
>	}
> takes on a whole new meaning ... (and always succeeds!)

Yeah, longest token matched.  I kind of ignored syntactic ambiguity for the
purposes of the discussion.  Personally, I seperate operators of lower
precedences from their arguments, which would make your example would read "if
(a <- 1) ..." if assignment had been intended, and "if (a < -1) ..." if
less-than had been intended.  `<-' so much better connotes assignment than `='
that I'll stick to me guns here.  It's more important to me to get the
appearance of a left arrow; that the characters `<' and `-' happen to give this
appearance when the former immediately preceds the latter is a convenience.
(It's damn unfortunate that left- and right-arrows are not part of the ascii
character set.  They have enough meaning beyond any other graphical
connotations that a good case could be made for them.  But that's life.)

Not that ansi committees and compiler writers are not going to trip over
themselves in a flurry to accommodate a minority preference, hee hee!  But on a
more serious note, simple ol' cpp doesn't accommodate this user's preference
either.  Many'll say that it's not a good idea to modify the language with cpp.
Well, by writing functions and creating data types, one is enhancing (read
"modifying") the language.  I would take this further if I could without a
severe amount of effort.

subbarao@phoenix.Princeton.EDU (Kartik Subbarao) responds:
> My My -- You must be an S programmer, where <- IS the assignment operator.
> But now how do I say ``If a is less then -1''?

Above.

Yes, I've programmed in S.  However, I've held this opinion long before my
escapades with S.  I feel that S is a woof in many respects, but at least the
authors picked my preferred assignment operator appearance.

Regards, [Ag] gaynor@paul.rutgers.edu

gaynor@sparky.rutgers.edu (Silver) (09/20/90)

gaynor@sparky.rutgers.edu (Silver, Moi) wrote:
> If I had my way, assignment would be `<-' and equality, `='.

newc@macuni.mqcc.mq.oz (JamesPW) responds:
> So 
>	if (a<-1) {
>		...
>	}
> takes on a whole new meaning ... (and always succeeds!)

Yeah, longest token matched.  I kind of ignored syntactic ambiguity for the
purposes of the discussion.  Personally, I seperate operators of lower
precedences from their arguments, which would make your example would read "if
(a <- 1) ..." if assignment had been intended, and "if (a < -1) ..." if
less-than had been intended.  `<-' so much better connotes assignment than `='
that I'll stick to me guns here.  It'c more important to me to get the
appearance of a left arrow; that the characters `<' and `-' hap`en to give this
appearance when the former immediately preceds the latter is a convenience.
(It's damn unfortunate that left- and right-arrows are not part of the ascii
character set.  They have enough meaning beyond any other graphical
connotations that a good case could be made for them.  But that's life.)

Not that ansi committees and compiler writers are not going to trip over
themselves in a flurry to accommodate a minority preference, hee hee!  But on a
more serious note, simple ol' cpp doesn't accommodate this user's preference
either.  Many'll say that it's not a good idea to modify the language with cpp.
Well, by writing functions and creating data types, one is enhancing (read
"modifiing") the language.  I would take this further if I could without a
severe amount of effort.

subbarao@phoenix.Princeton.EDU (Kartik Subbarao) responds:
> My My -- You must be an S programmer, where <- IS the assignment operator.
> But now how do I say ``If a is less then -1''?

Above.

Yes, I've programmed in S.  However, I've held this opinion long before my
escapades with S.  I feel that S is a woof in many respects, but at least the
authors picked my preferred assignment operator appearance.

Regards, [Ag] gaynor@paul.rutgers.edu

trt@rti.rti.org (Thomas Truscott) (09/20/90)

> ... changing the common = to not return a value will not affect 99% of the
> lines in a typical program, and it will catch the beginner's if (a = b).

But it will not catch the beginner's (or my) if (a := b).
Will it catch if (c := getchar() != EOF)?
Adding ":=" introduces new opportunities for typographical mayhem.

It will not catch:
	if (a == b && c == d)
		a == b + 3;
I have made that mistake more than once, and the last time it happened
I spent a long time hunting it down.  (Yes, lint would have caught it.)
If the compiler had just said "null effect", I could have fixed
the problem as trivially as if I had misspelled a variable name.

I guess people think this problem is a syntactic one because:
(a) Most other language compilers they have used do not have this problem
(b) The C "==" syntax for comparison is different from the usual "="
But the omitted details are:
(c) Most other language compilers do not support assignment as an operator
(d) Most other language compilers have decent diagnostics

	Tom Truscott

APPENDIX: A MORE SERIOUS SYNTAX PROBLEM THAN =/==
Let's look at a serious "flaw" in C syntax that no one complains about.
Why not?  Because compiler diagnostics keep problems from occurring!
In C, to index a two dimensional array one uses
	n = x[i][j];
This is "gratuitously" different than other languages.
Look at how horrible the following plausible C mistake is:
	n = x[i,j];
Oh no, the dreaded comma operator!  The effect is identical to:
	n = x[j];
And C compilers will gladly generate executable code for it.
What a mess it would be tracking down the bug.
You may claim "but no one makes that mistake".  Untrue!
As a C instructor I routinely notice people fixing that mistake.
I never have to help them, thanks to a little compiler message:
	... Warning ... illegal combination of pointer and integer
I claim that if that compiler message were not printed,
the "comma operator botch" would be the favorite
complaint of FORTRAN-oriented C bashers,
even more popular than complaints of "no variable sized arrays"
or "no complex data type".  Can you prove me wrong?

brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (09/21/90)

In article <4089@rtifs1.UUCP> trt@rti.rti.org (Thomas Truscott) writes:
> > ... changing the common = to not return a value will not affect 99% of the
> > lines in a typical program, and it will catch the beginner's if (a = b).
> But it will not catch the beginner's (or my) if (a := b).

But you and the beginner will both use = almost all the time. := will
always stand out as a rare case.

> It will not catch:
> 	if (a == b && c == d)
> 		a == b + 3;

Gee. My q2c translator spews out ``q2c: warning: foo.q(5): value ignored''
for a mistake like that. Your point is?

You're right that a problem isn't really a problem if the compiler can
reasonably warn you about it. But how do you suppose a C compiler should
detect whether if (a = b) was intentional or not? If a programmer is used
to that style, he'll be flooded with pointless warnings and eventually
learn to ignore them entirely. In contrast, he'd use := consciously, and
never fall into the pschological trap of thinking ``if a equals b'' and
writing ``if (a = b)''.

> APPENDIX: A MORE SERIOUS SYNTAX PROBLEM THAN =/==
> 	n = x[i,j];

q2c: warning: foo.q(6): value ignored. (Note that Q's arrays are
quite different from C's.)

The point is that ``value ignored'' warnings should be right almost all
the time. The compiler shouldn't have to play this guessing game where
sometimes a value is used and sometimes it isn't.

To put it differently, the language should support enough features that
an ignored value could reasonably be fatal. (Language design principles
for the '90s.) With = alone, the programmer can't express the logical
distinction between a used x = y and an unused x = y. This lack of
expressiveness can be expected to cause problems.

---Dan

ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) (09/21/90)

In article <4641:Sep1919:49:5990@kramden.acf.nyu.edu>, brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes:
> Right. That's why you need to preserve that function, as :=. But
> changing the common = to not return a value will not affect 99% of the
> lines in a typical program, and it will catch the beginner's if (a = b).
...
> Furthermore, =/:=/== has an important benefit: The code-checker no
> longer needs to special-case a = b when it's looking for ignored values.

I'm getting sick of this.  If you want a language which has no = / ==
problem, Scheme, with its
	(set variable value)		;; assignment
	(eq? thing1 thing2)		;; object identity
is hard to beat.  And there's a free compiler from DEC that turns it into
C.  (Best of all, none of those nasty malloc/free errors.)  But it doesn't
look like C?  Neither it does.  Wasn't that the point?

There's a _lot_ that C compilers could usefully warn about (like
uninitialised variables, dead code, *ptr - *ptr++, and so on).  = -vs- ==
is just one case among many.
-- 
Heuer's Law:  Any feature is a bug unless it can be turned off.

burley@world.std.com (James C Burley) (09/21/90)

trt@rti.rti.org (Thomas Truscott) writes:

   APPENDIX: A MORE SERIOUS SYNTAX PROBLEM THAN =/==
   Let's look at a serious "flaw" in C syntax that no one complains about.
   Why not?  Because compiler diagnostics keep problems from occurring!
   In C, to index a two dimensional array one uses
	   n = x[i][j];
   This is "gratuitously" different than other languages.
   Look at how horrible the following plausible C mistake is:
	   n = x[i,j];
   Oh no, the dreaded comma operator!  The effect is identical to:
	   n = x[j];
   And C compilers will gladly generate executable code for it.
   What a mess it would be tracking down the bug.

Oooh, another good example, and one I ran into when I first started writing
C code.  I was writing a text-to-Postscript converter for VMS and I had set
up an array to specify the XY offset of a particular graphic so I could
fine-tune it later.  It looked something like this:

   int adjust[4] = [ 1 4 6 3 ];

I had just typed in these semi-random values based on my initial guesses for
the adjustments.  After several compile/link/test passes, I had the code
working and decided it was time to focus on the actual adjustment needed, so
I pulled out a ruler, determined the actual number of points I wanted for
the adjustment rectangle, and modified the numbers accordingly:

   int adjust[4] = [ 1 -3 2 -1 ];

I tried this, and strangely, the graphic moved too far.  Remeasure, readjust:

   int adjust[4] = [ 1 2 1 -1 ];

Hmmm, moved too far again.

Finally, after a couple more attempts, I decided I had to interactively
debug it because I assumed my offsetting code was mysteriously wrong.  Had to
learn VMS debugger etc.  Everything looks ok but STILL doesn't work -- even
though the code paths work fine.  Finally I look at the actual values for
the offset rect as they get pulled out of the structure, and notice that
the last one or two are zero!  Then I look at the earlier ones and they're not
quite right -- though close.

Turns out, as most readers know by know I expect, that I had not used commas
to separate the items in the initialization list.  When there were four
distinct positive numbers, the compiler just inserted commas gratis, with no
message.  When a couple of the initializers were changed to negative values,
the four values turned into two expressions with two operands each!  So
[ 1 -3 2 -1 ] would become [ -2 1 ] (with two zeros added to compensate,
again automatically, but I believe this is correct C and hence shouldn't be
complained about).

Ultimately, even a "complaining" compiler (such as one that complains about
seeing foo[i,j] because i is an unused value) isn't going to catch all such
errors in all situations -- for example, foo[func(i),j] probably shouldn't
produce an error -- perhaps it was intentional, or was it?  But in my case
I think I finally checked the standard and found that it did supposedly
require commas between expressions in an initialization list.  For a compiler
to insert them for one is -- well, arggghhh!  (-:

In doing other language/little-language/whatever designs, I've often thought
back to this problem and avoided making the following general mistake
whenever possible:

    A syntax that allows an item, call it X, in a particular context, should
    always allow another item, Y, that is closely related and likely to
    directly replace it during an edit session and yet is not syntactically
    identical to X.  (E.g. 4 is syntactically identical to 5 but not to -4;
    yet they are all closely related in most user's minds, as might be
    4 and the expression 2+2.)  If replacement of X with Y would change the
    meaning or validity of the overall construct, strongly lean towards
    disallowing X in that context if there can be a form that provides for
    both X and Y meaning the same thing -- in other words, don't allow X
    in a supposedly "convenient" form for "most cases" if it is at all likely
    someone will change X to a Y and get a different result.  (Lean more if
    the result is valid but different than would be expected by direct
    replacement; lean less if the result is an invalid construct resulting
    in a message).

So the compiler I was using violated the rule by permitting one to omit
commas between initializers without considering what happens if one of those
values is directly changed to a negative value.

Other example: c=4;, change the 4 to -2, and you get c=-2;, which in older
Cs used to mean c-=2; (they took a better and more general approach to
fixing it than my limited suggestion -- given no alternative, my rule would
have suggested requiring at least one space following the =).

James Craig Burley, Software Craftsperson    burley@world.std.com

mark@DRD.Com (Mark Lawrence) (09/26/90)

jh4o+@andrew.cmu.edu (Jeffrey T. Hutzelman) wrote:
} [...] However, I think the intent of the original code was to
} perform an assignment and then do a test on the result (look carefully;
} there's a > or < in there somewhere), similar to the following, which I
} use all the time:
} 
} if ( ( file_ptr = fopen (filename, mode) ) == NULL )
} 	{
} 	/* print a message and exit */
} 	}

right.  I posted the original article.  The most severe caution I got
was about readability.  My concern was that Saber C would give a warning
on code just like the above and I've learned to take Saber's warnings
seriously.  In this case, I'll just suppress the warning.  Thanks, all,
for an illuminating thread of discussion.
-- 
mark@DRD.Com uunet!apctrc!drd!mark$B!J%^!<%/!!!&%m!<%l%s%9!K(B

rsalz@bbn.com (Rich Salz) (09/28/90)

In <1990Sep26.124155.9856@DRD.Com> mark@DRD.Com (Mark Lawrence) writes:
[Saber "complains" about the following]
>} if ( ( file_ptr = fopen (filename, mode) ) == NULL )
>} 	{
>} 	/* print a message and exit */
>} 	}

>  My concern was that Saber C would give a warning
>on code just like the above and I've learned to take Saber's warnings
>seriously.

Gee, I'm confused.  The following fragment generated no warnings
whatsoever:
    #include <stdio.h>
    main()
    {
	FILE *F;

	if ((F = fopen("t.out", "w")) == NULL)
	    printf("Open failure");
	else {
	    printf("Open fine\n");
	    (void)fclose(F);
	}
    }

Perhaps something else is going on in your code?  This is with version 2.1,
and with suppressesion 357,358 (using result of ?: or cast as an lvalue)
turned OFF.
	/r$
-- 
Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.
Use a domain-based address or give alternate paths, or you may lose out.