[comp.lang.c] What I'd really like to see in an if-statement...

spl@mcnc.org (Steve Lamont) (08/05/89)

All this discussion about arithmetic ifs has goaded me into posting my own
particular pet construct.

Since I do a lot of programming that involves mathematical expressions of one
sort of another I often find myself wishing for an if construct that looks
like

	if ( foo < bar < baz )
	  do_something();
	else
	  do_something_else();

which is, of course, equivalent to

	if ( ( foo < bar ) && ( bar < baz ) )
	  do_something();
	else
	  do_something_else();

Is there any reason why such a construction is not practical?  If not, why has
no language (that I am aware of or can program in) implemented such a
construction?  Good idea or bad idea?

-- 
							spl
Steve Lamont, sciViGuy			EMail:	spl@ncsc.org
North Carolina Supercomputing Center	Phone: (919) 248-1120
Box 12732/RTP, NC 27709

hascall@atanasoff.cs.iastate.edu (John Hascall) (08/06/89)

In article <5024@alvin.mcnc.org> spl@mcnc.org.UUCP (Steve Lamont) writes:
}Since I do a lot of programming that involves mathematical expressions of one
}sort of another I often find myself wishing for an if construct that looks
}like
 
}	if ( foo < bar < baz )  ...
 
}Is there any reason why such a construction is not practical?  If not, why has
}no language (that I am aware of or can program in) implemented such a
}construction?  Good idea or bad idea?
 

     It's in COBOL (along with everything else).

     To answer your other question, COBOL is a bad idea.


John Hascall
ISU COmp Center

spl@mcnc.org (Steve Lamont) (08/06/89)

In article <1300@atanasoff.cs.iastate.edu> hascall@atanasoff.cs.iastate.edu.UUCP (John Hascall) writes:
@In article <5024@alvin.mcnc.org> spl@mcnc.org.UUCP (Steve Lamont) writes:
@}sort of another I often find myself wishing for an if construct that looks
@}like
@ 
@}	if ( foo < bar < baz )  ...
@ 
@}Is there any reason why such a construction is not practical?  If not, why has
@}no language (that I am aware of or can program in) implemented such a
@}construction?  Good idea or bad idea?
@ 
@
@     It's in COBOL (along with everything else).
@
@     To answer your other question, COBOL is a bad idea.

That really doesn't address the question:  is the mathematical inequality test
shown in my example a *bad* idea?

-- 
							spl
Steve Lamont, sciViGuy			EMail:	spl@ncsc.org
North Carolina Supercomputing Center	Phone: (919) 248-1120
Box 12732/RTP, NC 27709

ath@helios.prosys.se (Anders Thulin) (08/06/89)

In article <1300@atanasoff.cs.iastate.edu> hascall@atanasoff.cs.iastate.edu.UUCP (John Hascall) writes:
-In article <5024@alvin.mcnc.org> spl@mcnc.org.UUCP (Steve Lamont) writes:
-
-}	if ( foo < bar < baz )  ...
-}Is there any reason why such a construction is not practical?  If not, why has
-}no language (that I am aware of or can program in) implemented such a
-}construction?  Good idea or bad idea?
-
-     It's in COBOL (along with everything else).
-     To answer your other question, COBOL is a bad idea.

It's also in BCPL (with the semantics of foo < bar && bar < baz).
BCPL isn't.

-- 
Anders Thulin, Programsystem AB, Teknikringen 2A, S-583 30 Linkoping, Sweden
ath@prosys.se   {uunet,mcvax}!sunic!prosys!ath

hascall@atanasoff.cs.iastate.edu (John Hascall) (08/06/89)

In article <5027> spl@mcnc.org.UUCP (Steve Lamont) writes:
}In article <1300> hascall@atanasoff.cs.iastate.edu.UUCP (John Hascall) writes:
}@In article <5024> spl@mcnc.org.UUCP (Steve Lamont) writes:
  
}@}	if ( foo < bar < baz )  ...
}@} Good idea or bad idea?
}@ 
}@     It's in COBOL (along with everything else).
}@     To answer your other question, COBOL is a bad idea.
 
}That really doesn't address the question:  is the mathematical inequality test
}shown in my example a *bad* idea?
 
   Sorry, I should have followed that last bit with a smiley :-)

   I can see no reason why it is a bad idea (from a programming standpoint).
   And I can come up with a reason why it is a good idea (side effects):

	 while (min < *ptr++ < max) ...

   I can see no way to do this sort of thing as cleanly with ``< && <''.
   I compiler writer might have other opinions though!

John

leichter@CS.YALE.EDU (Jerry Leichter) (08/06/89)

In article <5024@alvin.mcnc.org>, spl@mcnc.org (Steve Lamont) writes...
>...Since I do a lot of programming that involves mathematical expressions of
>one sort of another I often find myself wishing for an if construct that
>looks like
> 
>	if ( foo < bar < baz )
>	  do_something();
>	else
>	  do_something_else();
> 
>...Is there any reason why such a construction is not practical?  If not, why
>has no language (that I am aware of or can program in) implemented such a
>construction?  Good idea or bad idea?

This construct exists, and has the meaning you would expect, in Icon.  Someone
else has pointed out that it is also allowed in COBOL.

The reason most languages don't allow such contructs is a side-effect of a
great unifying idea that sometimes ends up getting in the way:  The idea that
relational symbols are really binary operators with Boolean values.  Having
decided that "<" is a binary operator returning a Boolean, there is no possi-
ble parse of

		foo < bar < baz

which can give you the interpretation you want:  You need a context-sensitive
parse (perhaps not a context-sensitive grammer - let's keep the technicalities
out of this) that interprets the "<" symbols differently when they are adja-
cent.

COBOL avoids this problem because it was designed before the great unifica-
tion.  It has no Booleans - its relational operators are part of the syntax
of conditionals.  (My COBOL is almost non-existent, so this may not be an
accurate rendering.)

Icon avoids this problem by taking an entirely different approach.  There are
deep reasons for the alternative approach, which I will not try to justify
here; it was not taken to make expressions like this work right, that was a
nice side-effect.

In Icon, any expression can either produce a result, or fail to produce a
result.  In an if, the controlling expression is considered true if it
produces a result, false otherwise.  Expression evaluation has an explicitly
defined order (left to right, except inside parentheses outward first), and
"failing to produce a result" is "sticky":  Once any component of an
expression fails to produce a result, the entire expression immediately
terminates, having failed to produce a result.

The "<" operation in Icon is defined so that:

	a < b	is	if a is less then b, then produce the result b,
				else fail to produce a result.

Further, "<"'s associates to the left.  Hence:

	a < b < c

is evaluated as follows:

	1.  First, we evaluate a < b.
	2.  If a is greater than or equal to b, then a < b produces no result,
		so the whole expression produces no result (is false, in the
		context of an if).

		If a is less than b, then a < b produces b.
	3.  If a < b produced a result (b), we have reduced our expression to

			b < c

		which we proceed to evalutate.

VERY clever idea!
							-- Jerry

tneff@bfmny0.UUCP (Tom Neff) (08/06/89)

The complex expression

	val1 < x < val2

(and by extension, the 24 other forms possible with <, <=, ==, >= and >)
really has nothing to do with the 'if' statement, so the subject name
of this thread is inaccurate.  What's wished for is a triadic comparison
operator, which could then be used in any of the boolean contexts that
a simple binary comparison can be used now.

It would be fun to have such a thing, it would make expressing lots of
conditions more concise and everyone would use it.  However it would
break a lot of things in "C" (the expression above IS VALID C right now,
for instance, with a totally different meaning) and parsing would be a
nightmare.  I wouldn't hold my breath.
-- 
"We walked on the moon --	((	Tom Neff
	you be polite"		 )) 	tneff@bfmny0.UU.NET

drs@bnlux0.bnl.gov (David R. Stampf) (08/07/89)

In article <14521@bfmny0.UUCP> tneff@bfmny0.UUCP (Tom Neff) writes:
>The complex expression
>
>	val1 < x < val2
>
>(and by extension, the 24 other forms possible with <, <=, ==, >= and >)
>really has nothing to do with the 'if' statement, so the subject name
>of this thread is inaccurate.  What's wished for is a triadic comparison
>operator, ...
>...
>"We walked on the moon --	((	Tom Neff
>	you be polite"		 )) 	tneff@bfmny0.UU.NET


How true.  One of my *favorite* features of smallTalk is how one can compare
a number (actually a magnitude) for inclusion in an interval, and how SmallTalk
does C one better by making "if" an operator as well!  For example, one can
write:

	(x between: val1 and: val2) ifTrue: [ "do this block if true"]
				    ifFalse: [ "do this block otherwise"].

Pretty neat stuff.  I would imagine that C++ could handle such a construct.
One of these days I'll have a C++ compiler to try it.

	< dave

dworkin@Solbourne.COM (Dieter Muller) (08/07/89)

In article <14521@bfmny0.UUCP> tneff@bfmny0.UUCP (Tom Neff) writes:
>What's wished for is a triadic comparison
>operator, which could then be used in any of the boolean contexts that
>a simple binary comparison can be used now.

I'd say what's wanted is more of an n-adic comparison operator, since
it is occassionally nice to say ``if (a < b < c < d)'', etc.  If you're
going to generalize, do it all the way.

>It would be fun to have such a thing, it would make expressing lots of
>conditions more concise and everyone would use it.  However it would
>break a lot of things in "C" (the expression above IS VALID C right now,
>for instance, with a totally different meaning) and parsing would be a
>nightmare.

Unfortunately quite correct.  Looks like another one of those ``in the
successor of C'' sorts of things (please, let's not get *that* started
again).  'Course, if someone felt ambitious, they could provide
both interpretations, selected by a #pragma.  If the construct appears
before the compiler sees one of the appropriate #pragma's, it generates
a warning and applies the "normal" interpretation.

Dieter
-- 
"Your spatial laws are ok, but God, the choices you give us." -- Deborah Blau
boulder!stan!dworkin  dworkin%stan@boulder.colorado.edu  dworkin@solbourne.com
Flamer's Hotline: (303) 678-4624 (1000 - 1800 Mountain Time)

bengsig@oracle.nl (Bjorn Engsig) (08/07/89)

Article <14521@bfmny0.UUCP> by tneff@bfmny0.UUCP (Tom Neff) says:
|	val1 < x < val2
|
|What's wished for is a triadic comparison operator ...
|
|... and parsing would be a nightmare.
As an example, have a look at the database language SQL, where you can write

  <expr1> <= <expr2> AND <expr2> <= <expr3>

or
  
  <expr2> BETWEEN <expr1> AND <expr3>

The two semantically equal (no side effects) have to be syntactically different
for the parser to resolve it.  

-- 
Bjorn Engsig, ORACLE Europe         \ /    "Hofstadter's Law:  It always takes
Path:   mcvax!orcenl!bengsig         X      longer than you expect, even if you
Domain: bengsig@oracle.nl           / \     take into account Hofstadter's Law"

peter@ficc.uu.net (Peter da Silva) (08/07/89)

In article <5024@alvin.mcnc.org>, spl@mcnc.org (Steve Lamont) writes:
> 	if ( foo < bar < baz )

> Is there any reason why such a construction is not practical?

It complicates the language design for the sake of adding syntactic
sugar, but otherwise it's eminently practical.

> If not, why has
> no language (that I am aware of or can program in) implemented such a
> construction?  Good idea or bad idea?

Well, languages don't implement constructs, but semantic quibbling aside
the real-time control language Bob Pearson designed and I implemented at
Hydril Control Systems (for a product that was later dropped) had such
a construct. It was fairly easy to implement, at least in the Forth-based
recursive-descent parser I wrote.
-- 
Peter da Silva, Xenix Support, Ferranti International Controls Corporation.
Business: peter@ficc.uu.net, +1 713 274 5180. | "The sentence I am now
Personal: peter@sugar.hackercorp.com.   `-_-' |  writing is the sentence
Quote: Have you hugged your wolf today?  'U`  |  you are now reading"

peter@ficc.uu.net (Peter da Silva) (08/07/89)

In article <456@helios.prosys.se>, ath@helios.prosys.se (Anders Thulin) writes:
> In article <1300@atanasoff.cs.iastate.edu> hascall@atanasoff.cs.iastate.edu.UUCP (John Hascall) writes:
> -     To answer your other question, COBOL is a bad idea.

> BCPL isn't.

BCPL wasn't, once upon a time. At this late date, BCPL is. If you really
WANT a typeless C, the Ron Cain small-C is much more regular, and avoids
stuff like the global vector.
-- 
Peter da Silva, Xenix Support, Ferranti International Controls Corporation.
Business: peter@ficc.uu.net, +1 713 274 5180. | "The sentence I am now
Personal: peter@sugar.hackercorp.com.   `-_-' |  writing is the sentence
Quote: Have you hugged your wolf today?  'U`  |  you are now reading"

ethan@esosun.UUCP (Ethan Brown) (08/07/89)

[Regarding the if ( x < y < z ) evaluation]

LisP has it!  All comparison operators work on N arguments.

(if ( > x y z a b c)
  (foo)
 (bar))

--
--Ethan Brown			
--Science Applications International Corp.
--Geophysics Division 
--San Diego, CA 92121 (619) 458-2676

tneff@bfmny0.UUCP (Tom Neff) (08/07/89)

I suppose I might as well point out that if speed is not crucial,
you could always code a C function to do the triadic compare:

	if (triadc(min, '<', thisval, '<=', max)) ...

note using char for the two "operators" as above only works if type
int will accomodate two characters, which is usually but not universally
true.  You could also define special symbols for <= and >= and thus
express them in one character, or you could use string pointers or
enum constants like

	if (triadc(min, LESS_THAN, thisval, LESS_OR_EQUAL, max)) ...
-- 
"We walked on the moon --	((	Tom Neff
	you be polite"		 )) 	tneff@bfmny0.UU.NET

karl@haddock.ima.isc.com (Karl Heuer) (08/08/89)

In article <14521@bfmny0.UUCP> tneff@bfmny0.UUCP (Tom Neff) writes:
>It would be fun to have such a thing, it would make expressing lots of
>conditions more concise and everyone would use it.  However it would
>break a lot of things in "C" (the expression above IS VALID C right now,
>for instance, with a totally different meaning) and parsing would be a
>nightmare.  I wouldn't hold my breath.

It would "break a lot of things in C"?  I admit that "x<y<z" is currently
valid C, but I seriously doubt that it gets used heavily!  (Outside the
Obfuscated C Contest, anyway.)  And I doubt that the parse is any more
difficult than the dangling-else problem.

But still, it would be a new wart in a language that already has too many.  If
it could be defined in such a way that the language became *simpler*, I'd like
it a lot more.  (The ICON semantics come to mind.)

Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint

karl@haddock.ima.isc.com (Karl Heuer) (08/08/89)

Btw, one of my own pet ideas for "D" is the same notation in a loop construct:
	for (lo <= var < hi) ...
which would mean the same thing as C's
	for (var = lo; var < hi; ++var) ...
except that hi would be evaluated only once, and it would be illegal to change
the value of var within the loop.  (I.e., it would be your standard for-loop
as in BASIC/FORTRAN/PASCAL.)  All eight sensible combinations of relational
operators would be allowed.  (The construct
	for (hi > var >= lo) ...
would step through the same values via a decrementing loop.)

The only other proposal I've seen for such a feature uses notation like
	for (var in [lo, hi)) ...
but the syntax for the half-open interval is ugly.  (And "[lo, hi[" is worse.)

Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint

spl@mcnc.org (Steve Lamont) (08/08/89)

In article <14522@bfmny0.UUCP> tneff@bfmny0.UUCP (Tom Neff) writes:
>I suppose I might as well point out that if speed is not crucial,
>you could always code a C function to do the triadic compare:
>
>	if (triadc(min, '<', thisval, '<=', max)) ...
>

Though the following isn't exactly what I intended (generating even more
keystrokes than the simpler and, to the mathematical among us, more
straightforward

		( a < b < c )

you don't need to code triadc() as a function.  You could indeed code it as a
macro, to wit

	#define triadc(a,b,c,d,e) ( ( a b c ) && ( c d e ) )

	...

	if ( triadc( 0.0, <, x, <, 1.0 ) )
	...

which will expand to

	if ( ( ( 0.0 < x ) && ( x < 1.0 ) ) )
	...

or at least it does on my IRIS.  Haven't tested it on other versions of CPP,
so I can't say whether it is a general solution or one unique to the
preprocessor on the IRIS 4D series of machines.

Note that while this effectively does more or less what I want, it is a kludge
at best and I don't know how one would go about implementing 

		( a < b < c )

in C without either overloading the inequality operators, breaking currently
working programs [does anyone really code something like the above to mean

		( a < b ) < c
		
in a useful, working C program???  I'd be curious to see an example where such
a construction would be meaningful.]

Perhaps in ANSI C II (K&R Strike Back?? :-) ) we could add operators .<., .>.,
.<=., and .>=. (big :-) here ).  Wouldn't you just love to code

		( a .<. b .<. c ) ?????


-- 
							spl
Steve Lamont, sciViGuy			EMail:	spl@ncsc.org
North Carolina Supercomputing Center	Phone: (919) 248-1120
Box 12732/RTP, NC 27709

cjc@ulysses.homer.nj.att.com (Chris Calabrese[mav]) (08/08/89)

In article <5040@alvin.mcnc.org>, spl@mcnc.org (Steve Lamont) writes:
> Perhaps in ANSI C II (K&R Strike Back?? :-) ) we could add operators .<., .>.,
> .<=., and .>=. (big :-) here ).  Wouldn't you just love to code
> 
> 		( a .<. b .<. c ) ?????

Why do this when we can take advantage of another language which is
an international standard and use the following:
	( a .LE. b .LE. c ) ???

Insert biggest smiley you ever saw here...
-- 
Name:			Christopher J. Calabrese
Brain loaned to:	AT&T Bell Laboratories, Murray Hill, NJ
att!ulysses!cjc		cjc@ulysses.att.com
Obligatory Quote:	``Anyone who would tell you that would also try and sell you the Brooklyn Bridge.''

lacey@batcomputer.tn.cornell.edu (John Lacey) (08/09/89)

On Aug 8,  1:46am, Karl Heuer wrote:
} Subject: Re: What I'd really like to see in an if-statement...
} 
} In article <14521@bfmny0.UUCP> tneff@bfmny0.UUCP (Tom Neff) writes:
} >It would be fun to have such a thing, it would make expressing lots of
} >conditions more concise and everyone would use it.  However it would
} >break a lot of things in "C" (the expression above IS VALID C right now,
} >for instance, with a totally different meaning) and parsing would be a
} >nightmare.  I wouldn't hold my breath.
} 
} It would "break a lot of things in C"?  I admit that "x<y<z" is currently
} valid C, but I seriously doubt that it gets used heavily!  (Outside the
} Obfuscated C Contest, anyway.)  And I doubt that the parse is any more
} difficult than the dangling-else problem.

The parse would be more difficult.  The problems aren't analogous.  The 
dangling-else problem is one of ambiguity.  Parsing a general relational
expression is difficult because the same string will be used for multiple
tokens.  For example, in (a < x < b), x has to be associated separately
to its left and right.

} But still, it would be a new wart in a language that already has too many.  If
} it could be defined in such a way that the language became *simpler*, I'd like
} it a lot more.  (The ICON semantics come to mind.)

I agree that it doesn't belong in C.  However, I also happen to think that 
Icon's semantics are horrible.  The idea that (a < b) either fails to produce
a result or evaluates to b is completely unintuitive.  

} Btw, one of my own pet ideas for "D" is the same notation in a loop construct:
} 	for (lo <= var < hi) ...
} which would mean the same thing as C's
} 	for (var = lo; var < hi; ++var) ...
} except that hi would be evaluated only once, and it would be illegal to change
} the value of var within the loop.  (I.e., it would be your standard for-loop
} as in BASIC/FORTRAN/PASCAL.)  All eight sensible combinations of relational
} operators would be allowed.  (The construct
} 	for (hi > var >= lo) ...
} would step through the same values via a decrementing loop.)

This is a nice idea.  Also, parsing is simplified here, because the var
need not be split into 2 tokens.

} The only other proposal I've seen for such a feature uses notation like
} 	for (var in [lo, hi)) ...
} but the syntax for the half-open interval is ugly.  (And "[lo, hi[" is worse.)

Well, _I_ don't think it's ugly.  And it could be made less so, by removing
the redundant parentheses.  Simply say

	for var in [a, b) ...

as the shell languages do.  The difficulty of this construct, or perhaps
the beauty, is that the syntax cries out for non-determinism.  That is, 
this construct should not be required to let var be a, a+1, ..., b-1
in that order, but should be free to bind var to every value in the 
interval in any order.  Hence, it would still be nice to keep your 
previous pet idea around, for times when sequence really matters.

} Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint
} 
}-- End of excerpt from Karl Heuer

It seems that SETL may already have both of these constructs.

Sequential:           for var in {a..b-1} do <stmts> end for;

Non-deterministic:    for var in [a..b-1] do <stmts> end for;

where {...} is a set, and [...] is a tuple.


As I think we have all agreed that C is not the place for these extended
constructs, I have directed follow-ups to comp.lang.misc.

Cheers,

-- 
John Lacey     lacey@tcgould.tn.cornell.edu    cornell!batcomputer!lacey

After August 16:  jjlacey@owucomcn.bitnet
If you have to, try  mdl@sppy00.UUCP or maybe {...}!osu-cis!sppy00!mdl

henseler@uniol.UUCP (Herwig Henseler) (08/11/89)

Hello, world.

karl@haddock.ima.isc.com (Karl Heuer) writes:
> In article <14521@bfmny0.UUCP> tneff@bfmny0.UUCP (Tom Neff) writes:
> >It would be fun to have such a thing, it would make expressing lots of
	       ^^^
Oh, boy! I think when ADA was created, everyone said something like
"Wouldn't it be fun if ADA has ..". The results is a heavily overloaded
language which is *very* hard to learn because of the many ways to express
the same thing. A programmer must not only learn how to write a language,
but also to *read* programs from others. Therefore you have to know all
statements/functions/predicates it offers.

> It would "break a lot of things in C"?  I admit that "x<y<z" is currently
> valid C, but I seriously doubt that it gets used heavily!

That's my opinion. The famous #define makes almost every syntactic sugar
possible if *you* want it.

> But still, it would be a new wart in a language that already has too many.  If
> it could be defined in such a way that the language became *simpler*, I'd like
> it a lot more.  (The ICON semantics come to mind.)

Absolute correct. The simpler, the better. (But I've never heard of ICON.
What is it?)

	bye, Herwig
--
** Herwig Henseler (CS-Student) D-2930 Varel, Tweehoernweg 69 | Brain error- **
** EMail: henseler@uniol.UUCP (..!uunet!unido!uniol!henseler) | core dumped  **

flaps@gpu.utcs.utoronto.ca (Alan J Rosenthal) (08/12/89)

People seem to be wondering what use operators such as `<' have as applied to
boolean-valued operands.  For example, would (a < b < c) always be a mistake?
In fact, it would not, and I would like to point out the meaning of relational
operators as applied to boolean-valued operands.

If `a' and `b' are boolean-valued values (i.e. normalized, i.e. `!!' is the
boolean normalize operator in C), then `a < b' means "a is weaker than b", in
other words `a' is false and `b' is true.  `a <= b' means "a implies b".

Similarly the other boolean-valued operators in C can be used on boolean
values.  Another example:  `!=' means xor, and so (a != b != c) is the parity
of the three bits a, b, and c.

[ Followup avoidance tactics: I know that there is no boolean type in C, and
that relational operators return ints.  In fact, if I did not know this, I
would not have come up with the above. ]