Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #11331 > unrolled thread

is the < operator transitive?

Started byFrancois Grieu <fgrieu@gmail.com>
First post2011-10-07 19:10 +0200
Last post2012-01-24 16:14 -0800
Articles 20 on this page of 57 — 16 participants

Back to article view | Back to comp.lang.c


Contents

  is the < operator transitive? Francois Grieu <fgrieu@gmail.com> - 2011-10-07 19:10 +0200
    Re: is the < operator transitive? Robert Wessel <robertwessel2@yahoo.com> - 2011-10-07 13:44 -0500
    Re: is the < operator transitive? Edward Rutherford <edward.p.rutherford79@REMOVETHIS.gmail.com> - 2011-10-07 18:50 +0000
      Re: is the < operator transitive? Keith Thompson <kst-u@mib.org> - 2011-10-07 12:42 -0700
        Re: is the < operator transitive? Edward Rutherford <edward.p.rutherford79@REMOVETHIS.gmail.com> - 2011-10-07 20:23 +0000
          Re: is the < operator transitive? Patrick Scheible <kkt@zipcon.net> - 2011-10-07 14:29 -0700
          Re: is the < operator transitive? Keith Thompson <kst-u@mib.org> - 2011-10-07 16:49 -0700
            Re: is the < operator transitive? Patrick Scheible <kkt@zipcon.net> - 2011-10-07 19:19 -0700
          Re: is the < operator transitive? Eric Sosman <esosman@ieee-dot-org.invalid> - 2011-10-08 09:57 -0400
      Re: is the < operator transitive? "BartC" <bc@freeuk.com> - 2011-10-08 13:17 +0100
        Re: is the < operator transitive? Harald van Dijk <truedfx@gmail.com> - 2011-10-08 06:06 -0700
          Re: is the < operator transitive? "BartC" <bc@freeuk.com> - 2011-10-08 14:48 +0100
            Re: is the < operator transitive? Harald van Dijk <truedfx@gmail.com> - 2011-10-08 07:18 -0700
            Re: is the < operator transitive? "BartC" <bc@freeuk.com> - 2011-10-08 15:19 +0100
    Re: is the < operator transitive? Edward Rutherford <edward.p.rutherford79@REMOVETHIS.gmail.com> - 2011-10-07 18:50 +0000
      Re: is the < operator transitive? jacob navia <jacob@spamsink.net> - 2011-10-07 21:23 +0200
        Re: is the < operator transitive? Edward Rutherford <edward.p.rutherford79@REMOVETHIS.gmail.com> - 2011-10-07 20:24 +0000
          Re: is the < operator transitive? James Kuyper <jameskuyper@verizon.net> - 2011-10-07 16:40 -0400
            Re: is the < operator transitive? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2011-10-07 23:12 +0100
              Re: is the < operator transitive? Harald van Dijk <truedfx@gmail.com> - 2011-10-07 15:28 -0700
                Re: is the < operator transitive? Harald van Dijk <truedfx@gmail.com> - 2011-10-07 15:31 -0700
                Re: is the < operator transitive? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2011-10-07 23:36 +0100
                  Re: is the < operator transitive? Patrick Scheible <kkt@zipcon.net> - 2011-10-07 16:18 -0700
                    Re: is the < operator transitive? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2011-10-08 10:32 +0100
              Re: is the < operator transitive? James Kuyper <jameskuyper@verizon.net> - 2011-10-07 18:30 -0400
                Re: is the < operator transitive? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2011-10-08 00:21 +0100
                  Re: is the < operator transitive? James Kuyper <jameskuyper@verizon.net> - 2011-10-07 21:33 -0400
                    Re: is the < operator transitive? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2011-10-08 10:45 +0100
                      Re: is the < operator transitive? James Kuyper <jameskuyper@verizon.net> - 2011-10-08 14:02 -0400
                        Re: is the < operator transitive? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2011-10-08 21:49 +0100
                          Re: is the < operator transitive? James Kuyper <jameskuyper@verizon.net> - 2011-10-08 17:17 -0400
                            Re: is the < operator transitive? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2011-10-08 22:59 +0100
                              Re: is the < operator transitive? James Kuyper <jameskuyper@verizon.net> - 2011-10-08 21:33 -0400
                                Re: is the < operator transitive? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2011-10-09 09:09 +0100
                                  Re: is the < operator transitive? James Kuyper <jameskuyper@verizon.net> - 2011-10-09 07:00 -0400
                      Re: is the < operator transitive? "BartC" <bc@freeuk.com> - 2011-10-09 01:12 +0100
                        Re: is the < operator transitive? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2011-10-09 08:55 +0100
              Re: is the < operator transitive? Robert Wessel <robertwessel2@yahoo.com> - 2011-10-07 18:16 -0500
                Re: is the < operator transitive? David Thompson <dave.thompson2@verizon.net> - 2011-10-18 02:03 -0400
                  Re: is the < operator transitive? Robert Wessel <robertwessel2@yahoo.com> - 2011-10-20 18:03 -0500
          Re: is the < operator transitive? Keith Thompson <kst-u@mib.org> - 2011-10-07 16:50 -0700
      Re: is the < operator transitive? "io_x" <a@b.c.invalid> - 2011-10-09 11:00 +0200
        Re: is the < operator transitive? Willem <willem@toad.stack.nl> - 2011-10-09 09:42 +0000
          Re: is the < operator transitive? Ike Naar <ike@sverige.freeshell.org> - 2011-10-09 12:20 +0000
            Re: is the < operator transitive? Willem <willem@toad.stack.nl> - 2011-10-09 12:40 +0000
              Re: is the < operator transitive? Ike Naar <ike@sverige.freeshell.org> - 2011-10-09 12:54 +0000
                Re: is the < operator transitive? Willem <willem@toad.stack.nl> - 2011-10-09 13:04 +0000
              Re: is the < operator transitive? "BartC" <bc@freeuk.com> - 2011-10-09 15:34 +0100
                Re: is the < operator transitive? Willem <willem@toad.stack.nl> - 2011-10-09 15:08 +0000
              Re: is the < operator transitive? Robert Wessel <robertwessel2@yahoo.com> - 2011-10-09 12:14 -0500
    Re: is the < operator transitive? James Kuyper <jameskuyper@verizon.net> - 2011-10-07 15:36 -0400
      Re: is the < operator transitive? Eric Sosman <esosman@ieee-dot-org.invalid> - 2011-10-07 20:00 -0400
        Re: is the < operator transitive? James Kuyper <jameskuyper@verizon.net> - 2011-10-07 21:38 -0400
        Re: is the < operator transitive? Francois Grieu <fgrieu@gmail.com> - 2011-10-09 21:40 +0200
          Re: is the < operator transitive? Eric Sosman <esosman@ieee-dot-org.invalid> - 2011-10-09 16:34 -0400
            Re: is the < operator transitive? Francois Grieu <fgrieu@gmail.com> - 2011-10-11 14:08 +0200
            Re: is the < operator transitive? Tim Rentsch <txr@alumni.caltech.edu> - 2012-01-24 16:14 -0800

Page 2 of 3 — ← Prev page 1 [2] 3  Next page →


#11357

FromHarald van Dijk <truedfx@gmail.com>
Date2011-10-07 15:31 -0700
Message-ID<17e038ac-ebf2-484d-ab67-643d76b788ae@h10g2000yqd.googlegroups.com>
In reply to#11355
On Oct 8, 12:28 am, Harald van Dijk <true...@gmail.com> wrote:
> On Oct 8, 12:12 am, Ben Bacarisse <ben.use...@bsb.me.uk> wrote:
> > If <, >, <=, >=, == and != all have the same priority, you can parse it
> > just like a + b - c + d and simply double the operand you have "in hand"
> > and add &&.  The operators need to be marked as non-associative, but it
> > can be fitted into an operator precedence grammar very simply.
>
> > I've spent the last hour (not exclusively, you understand) trying to
> > remember what language it was that I've worked on that does this, and
> > I've come up with nothing.  But I don't think I'm making it up, honest.
>
> Python does this. Is that what you were trying to think of?

I see Python was already mentioned in the post you replied to, just
not part of the text you quoted.

[toc] | [prev] | [next] | [standalone]


#11358

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2011-10-07 23:36 +0100
Message-ID<0.d84d000fd0f0f2131344.20111007233634BST.87ty7kv37x.fsf@bsb.me.uk>
In reply to#11355
Harald van Dijk <truedfx@gmail.com> writes:

> On Oct 8, 12:12 am, Ben Bacarisse <ben.use...@bsb.me.uk> wrote:
>> If <, >, <=, >=, == and != all have the same priority, you can parse it
>> just like a + b - c + d and simply double the operand you have "in hand"
>> and add &&.  The operators need to be marked as non-associative, but it
>> can be fitted into an operator precedence grammar very simply.
>>
>> I've spent the last hour (not exclusively, you understand) trying to
>> remember what language it was that I've worked on that does this, and
>> I've come up with nothing.  But I don't think I'm making it up, honest.
>
> Python does this. Is that what you were trying to think of?

Thanks, but not what I was thinking of.  It's something depressingly
old.  Maybe Maxima?  Or an extension to Algo68, maybe?

-- 
Ben.

[toc] | [prev] | [next] | [standalone]


#11365

FromPatrick Scheible <kkt@zipcon.net>
Date2011-10-07 16:18 -0700
Message-ID<86pqi875lx.fsf@zipcon.net>
In reply to#11358
Ben Bacarisse <ben.usenet@bsb.me.uk> writes:

> Harald van Dijk <truedfx@gmail.com> writes:
>
>> On Oct 8, 12:12 am, Ben Bacarisse <ben.use...@bsb.me.uk> wrote:
>>> If <, >, <=, >=, == and != all have the same priority, you can parse it
>>> just like a + b - c + d and simply double the operand you have "in hand"
>>> and add &&.  The operators need to be marked as non-associative, but it
>>> can be fitted into an operator precedence grammar very simply.
>>>
>>> I've spent the last hour (not exclusively, you understand) trying to
>>> remember what language it was that I've worked on that does this, and
>>> I've come up with nothing.  But I don't think I'm making it up, honest.
>>
>> Python does this. Is that what you were trying to think of?
>
> Thanks, but not what I was thinking of.  It's something depressingly
> old.  Maybe Maxima?  Or an extension to Algo68, maybe?

The Icon Programming Language does this, and it's not a special case but
a natural consequence of a well-designed set of operators.

Comparison operators are evaluated left to right and produced the value
of their right operand if they are true (succeed, in Icon terminology).
If they fail, the subsequent comparison fails also.

A < B < C is evaluated (A < B); if true, it produces B, which is then
compared to C.

If (A < B) is false, it fails and produces no result.  Comparing to no
result fails in turn.

http://www.cs.arizona.edu/icon/

-- Patrick

[toc] | [prev] | [next] | [standalone]


#11387

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2011-10-08 10:32 +0100
Message-ID<0.9773ec0ec8ffd69ee85a.20111008103202BST.8762jzvnfx.fsf@bsb.me.uk>
In reply to#11365
Patrick Scheible <kkt@zipcon.net> writes:

> Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
>
>> Harald van Dijk <truedfx@gmail.com> writes:
>>
>>> On Oct 8, 12:12 am, Ben Bacarisse <ben.use...@bsb.me.uk> wrote:
>>>> If <, >, <=, >=, == and != all have the same priority, you can parse it
>>>> just like a + b - c + d and simply double the operand you have "in hand"
>>>> and add &&.  The operators need to be marked as non-associative, but it
>>>> can be fitted into an operator precedence grammar very simply.
>>>>
>>>> I've spent the last hour (not exclusively, you understand) trying to
>>>> remember what language it was that I've worked on that does this, and
>>>> I've come up with nothing.  But I don't think I'm making it up, honest.
>>>
>>> Python does this. Is that what you were trying to think of?
>>
>> Thanks, but not what I was thinking of.  It's something depressingly
>> old.  Maybe Maxima?  Or an extension to Algo68, maybe?
>
> The Icon Programming Language does this, and it's not a special case but
> a natural consequence of a well-designed set of operators.

Ah, yes, I'd forgotten that.  It wasn't Icon I was thinking about, but
it does indeed do this naturally.

<snip>
-- 
Ben.

[toc] | [prev] | [next] | [standalone]


#11356

FromJames Kuyper <jameskuyper@verizon.net>
Date2011-10-07 18:30 -0400
Message-ID<4E8F7D9A.70405@verizon.net>
In reply to#11353
On 10/07/2011 06:12 PM, Ben Bacarisse wrote:
...
> If <, >, <=, >=, == and != all have the same priority, you can parse it
> just like a + b - c + d and simply double the operand you have "in hand"
> and add &&.  The operators need to be marked as non-associative, but it
> can be fitted into an operator precedence grammar very simply.

I'd like to see that explained more clearly. In particular I'd like to
see an explanation of how, with that modification, each of the following
expressions would be handled:

	2 < 1 < 3
	0 < 3
	(2 < 1) < 3

[toc] | [prev] | [next] | [standalone]


#11363

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2011-10-08 00:21 +0100
Message-ID<0.8ddcdfed841f725b51f7.20111008002123BST.87d3e8v158.fsf@bsb.me.uk>
In reply to#11356
James Kuyper <jameskuyper@verizon.net> writes:

> On 10/07/2011 06:12 PM, Ben Bacarisse wrote:
> ...
>> If <, >, <=, >=, == and != all have the same priority, you can parse it
>> just like a + b - c + d and simply double the operand you have "in hand"
>> and add &&.  The operators need to be marked as non-associative, but it
>> can be fitted into an operator precedence grammar very simply.
>
> I'd like to see that explained more clearly. In particular I'd like to
> see an explanation of how, with that modification, each of the following
> expressions would be handled:
>
> 	2 < 1 < 3
> 	0 < 3
> 	(2 < 1) < 3

I'll try.  I should go find some code probably but I am a bit short of
time right now...

Operators are marked with a precedence and an associativity.  This
latter can be "left", "right" or "none".  The heart of the parser deals
with operators with left or no associativity and a priority that is
passed as an argument:

  exp = parse_exp_with_prio(priority + 1);
  last_right = null;
  while (next_token.prio == priority) {
      op = next_token;
      advance_token();
      right = parse_exp_with_prio(priority + 1);
      if (last_right != null && op.assoc == none) {
          e = make_exp(last_right, op, right);
          exp = make_exp(exp, '&&', e);
      }
      else exp = make_exp(exp, op, right);
      last_right = right;
  }
  return exp;

When called with maximum priority, parse_exp_with_prio matches only
constansts, names, and expressions in brackets.  This nested case is
handled by calling parse_exp_with_prio(0).

So "0 < 3" goes round this loop once and builds one expression node
with a < operator.

"2 < 1 < 3" goes round twice.  In the second iteration we notice that we
have seen a previous "right operand" of this priority (it will be the
constant 1) and we build (2 < 1) && (1 < 3) while setting last_right to
3 in case there are non-associative operators of the same priority.

"(2 < 1) < 3" parses as normal.   The request for exp on the left will
eventually be matched by a call to parse_exp_with_prio with maximum
priority.  That will return 2 < 1 after calling parse_exp_with_prio(0)
and matching the closing bracket.  This nested call goes round the loop
once.  Having get exp on the left, we loop once to build (2 < 1) < 3.

I am sure I've messed up some detail (writing in haste here) and the big
picture is missing.  But if you've seen other recursive descent parsers
where expressions are handled by one parameterised parser function
(rather than one for each operator priority) it won't look too odd.

-- 
Ben.

[toc] | [prev] | [next] | [standalone]


#11375

FromJames Kuyper <jameskuyper@verizon.net>
Date2011-10-07 21:33 -0400
Message-ID<j6o99i$aa6$1@dont-email.me>
In reply to#11363
On 10/07/2011 07:21 PM, Ben Bacarisse wrote:
> James Kuyper <jameskuyper@verizon.net> writes:
> 
>> On 10/07/2011 06:12 PM, Ben Bacarisse wrote:
>> ...
>>> If <, >, <=, >=, == and != all have the same priority, you can parse it
>>> just like a + b - c + d and simply double the operand you have "in hand"
>>> and add &&.  The operators need to be marked as non-associative, but it
>>> can be fitted into an operator precedence grammar very simply.
>>
>> I'd like to see that explained more clearly. In particular I'd like to
>> see an explanation of how, with that modification, each of the following
>> expressions would be handled:
>>
>> 	2 < 1 < 3
>> 	0 < 3
>> 	(2 < 1) < 3
> 
> I'll try.  I should go find some code probably but I am a bit short of
> time right now...
> 
> Operators are marked with a precedence and an associativity.  This
> latter can be "left", "right" or "none".  The heart of the parser deals
> with operators with left or no associativity and a priority that is
> passed as an argument:
> 
>   exp = parse_exp_with_prio(priority + 1);
>   last_right = null;
>   while (next_token.prio == priority) {
>       op = next_token;
>       advance_token();
>       right = parse_exp_with_prio(priority + 1);
>       if (last_right != null && op.assoc == none) {
>           e = make_exp(last_right, op, right);
>           exp = make_exp(exp, '&&', e);
>       }
>       else exp = make_exp(exp, op, right);
>       last_right = right;
>   }
>   return exp;
> 
> When called with maximum priority, parse_exp_with_prio matches only
> constansts, names, and expressions in brackets.  This nested case is
> handled by calling parse_exp_with_prio(0).
> 
> So "0 < 3" goes round this loop once and builds one expression node
> with a < operator.
> 
> "2 < 1 < 3" goes round twice.  In the second iteration we notice that we
> have seen a previous "right operand" of this priority (it will be the
> constant 1) and we build (2 < 1) && (1 < 3) while setting last_right to
> 3 in case there are non-associative operators of the same priority.
> 
> "(2 < 1) < 3" parses as normal.   The request for exp on the left will
> eventually be matched by a call to parse_exp_with_prio with maximum
> priority.  That will return 2 < 1 after calling parse_exp_with_prio(0)
> and matching the closing bracket.  This nested call goes round the loop
> once.  Having get exp on the left, we loop once to build (2 < 1) < 3.

So 2 < 1 < 3  would be different from (2 < 1) < 3. That would bother me;
not because it's so important to allow the current meaning of 2<1<3 to
survive, but because it would be inconsistent with the way parentheses
work in most other C contexts.
-- 
James Kuyper

[toc] | [prev] | [next] | [standalone]


#11388

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2011-10-08 10:45 +0100
Message-ID<0.9c297e0e5b9ae67129fd.20111008104538BST.87zkhbu88t.fsf@bsb.me.uk>
In reply to#11375
James Kuyper <jameskuyper@verizon.net> writes:

> On 10/07/2011 07:21 PM, Ben Bacarisse wrote:
>> James Kuyper <jameskuyper@verizon.net> writes:
>> 
>>> On 10/07/2011 06:12 PM, Ben Bacarisse wrote:
>>> ...
>>>> If <, >, <=, >=, == and != all have the same priority, you can parse it
>>>> just like a + b - c + d and simply double the operand you have "in hand"
>>>> and add &&.  The operators need to be marked as non-associative, but it
>>>> can be fitted into an operator precedence grammar very simply.
>>>
>>> I'd like to see that explained more clearly. In particular I'd like to
>>> see an explanation of how, with that modification, each of the following
>>> expressions would be handled:
>>>
>>> 	2 < 1 < 3
>>> 	0 < 3
>>> 	(2 < 1) < 3
>> 
>> I'll try.  I should go find some code probably but I am a bit short of
>> time right now...
>> 
>> Operators are marked with a precedence and an associativity.  This
>> latter can be "left", "right" or "none".  The heart of the parser deals
>> with operators with left or no associativity and a priority that is
>> passed as an argument:
>> 
>>   exp = parse_exp_with_prio(priority + 1);
>>   last_right = null;
>>   while (next_token.prio == priority) {
>>       op = next_token;
>>       advance_token();
>>       right = parse_exp_with_prio(priority + 1);
>>       if (last_right != null && op.assoc == none) {
>>           e = make_exp(last_right, op, right);
>>           exp = make_exp(exp, '&&', e);
>>       }
>>       else exp = make_exp(exp, op, right);
>>       last_right = right;
>>   }
>>   return exp;
>> 
>> When called with maximum priority, parse_exp_with_prio matches only
>> constansts, names, and expressions in brackets.  This nested case is
>> handled by calling parse_exp_with_prio(0).
>> 
>> So "0 < 3" goes round this loop once and builds one expression node
>> with a < operator.
>> 
>> "2 < 1 < 3" goes round twice.  In the second iteration we notice that we
>> have seen a previous "right operand" of this priority (it will be the
>> constant 1) and we build (2 < 1) && (1 < 3) while setting last_right to
>> 3 in case there are non-associative operators of the same priority.
>> 
>> "(2 < 1) < 3" parses as normal.   The request for exp on the left will
>> eventually be matched by a call to parse_exp_with_prio with maximum
>> priority.  That will return 2 < 1 after calling parse_exp_with_prio(0)
>> and matching the closing bracket.  This nested call goes round the loop
>> once.  Having get exp on the left, we loop once to build (2 < 1) < 3.
>
> So 2 < 1 < 3  would be different from (2 < 1) < 3. That would bother me;
> not because it's so important to allow the current meaning of 2<1<3 to
> survive, but because it would be inconsistent with the way parentheses
> work in most other C contexts.

Well, that's an example, and I aimed to make it different deliberately
because I thought your point was that it would be hard to distinguish
between those two.

A simpler solution is to parse without creating the extra && nodes and
have the code generator (or some later parse tree re-writing) handle it.
Then (2 < 1) < 1 and 2 < (1 < 3) can easily mean the same as 2 < 1 < 3.

But none of this can be about C, surely, not even as an extension.  In
that case (a < b) < c does not have to mean the same as a < b < c.  The
relational operators (in this scheme) are non-associative, so the
programmer will know that the parentheses can change the meaning.

-- 
Ben.

[toc] | [prev] | [next] | [standalone]


#11400

FromJames Kuyper <jameskuyper@verizon.net>
Date2011-10-08 14:02 -0400
Message-ID<j6q379$56l$1@dont-email.me>
In reply to#11388
On 10/08/2011 05:45 AM, Ben Bacarisse wrote:
> James Kuyper <jameskuyper@verizon.net> writes:
> 
>> On 10/07/2011 07:21 PM, Ben Bacarisse wrote:
...
>>> I'll try.  I should go find some code probably but I am a bit short of
>>> time right now...
>>>
>>> Operators are marked with a precedence and an associativity.  This
>>> latter can be "left", "right" or "none".  The heart of the parser deals
>>> with operators with left or no associativity and a priority that is
>>> passed as an argument:
>>>
>>>   exp = parse_exp_with_prio(priority + 1);
>>>   last_right = null;
>>>   while (next_token.prio == priority) {
>>>       op = next_token;
>>>       advance_token();
>>>       right = parse_exp_with_prio(priority + 1);
>>>       if (last_right != null && op.assoc == none) {
>>>           e = make_exp(last_right, op, right);
>>>           exp = make_exp(exp, '&&', e);
>>>       }
>>>       else exp = make_exp(exp, op, right);
>>>       last_right = right;
>>>   }
>>>   return exp;
>>>
>>> When called with maximum priority, parse_exp_with_prio matches only
>>> constansts, names, and expressions in brackets.  This nested case is
>>> handled by calling parse_exp_with_prio(0).
>>>
>>> So "0 < 3" goes round this loop once and builds one expression node
>>> with a < operator.
>>>
>>> "2 < 1 < 3" goes round twice.  In the second iteration we notice that we
>>> have seen a previous "right operand" of this priority (it will be the
>>> constant 1) and we build (2 < 1) && (1 < 3) while setting last_right to
>>> 3 in case there are non-associative operators of the same priority.
>>>
>>> "(2 < 1) < 3" parses as normal.   The request for exp on the left will
>>> eventually be matched by a call to parse_exp_with_prio with maximum
>>> priority.  That will return 2 < 1 after calling parse_exp_with_prio(0)
>>> and matching the closing bracket.  This nested call goes round the loop
>>> once.  Having get exp on the left, we loop once to build (2 < 1) < 3.
>>
>> So 2 < 1 < 3  would be different from (2 < 1) < 3. That would bother me;
>> not because it's so important to allow the current meaning of 2<1<3 to
>> survive, but because it would be inconsistent with the way parentheses
>> work in most other C contexts.
> 
> Well, that's an example, and I aimed to make it different deliberately
> because I thought your point was that it would be hard to distinguish
> between those two.

Not quite. I gave three expressions for an important reason. After I
sent that message, I've since realized that it would have been less
confusing to use an expression which would have a different value under
the current standard than it would have if the suggested change were made:

A:	3 < 2 < 1
B:	(3 < 2) < 1
C:	0 < 1

Under the current standard, the first two statements have the same
meaning, and all three expressions have the same value. The fact that A
and B have the same meaning is needed for consistency with the rest of
the C language. The fact that B and C have the same value is needed for
consistency with the rest of the C language. You can change the meaning
of a < b < c to be (a<b) && (b<c), but only at the cost of breaking one
of those relationships. I don't care which one is broken, they're both
important, and I wouldn't like to see either one change.

In a new language that was otherwise similar to C, I'd favor having a
boolean type that was
a) Not treated as special kind of integer type
b) incapable of conversion to or from any other type.
c) the only type that could be used as a condition in #if preprocessing
directives; if(), while(), do while(), or for() statements; or ?:
expressions.

In such a language, the connection between B and C above would be
broken; and I wouldn't mind, but such a language could not be backward
compatible with existing C code, so I cannot favor any such change to C
itself.

> But none of this can be about C, surely, not even as an extension.  In

I'm in agreement about that, but Edward Rutherford said:
> IMO it would be great if this could be backported to C.

And my comments have all been in the context of that comment.
-- 
James Kuyper

[toc] | [prev] | [next] | [standalone]


#11408

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2011-10-08 21:49 +0100
Message-ID<0.5dc2ca7041c5610fa99e.20111008214949BST.87ty7jtdhu.fsf@bsb.me.uk>
In reply to#11400
James Kuyper <jameskuyper@verizon.net> writes:
<snip>
> A:	3 < 2 < 1
> B:	(3 < 2) < 1
> C:	0 < 1
<snip>
> In a new language that was otherwise similar to C, I'd favor having a
> boolean type that was
> a) Not treated as special kind of integer type
> b) incapable of conversion to or from any other type.
> c) the only type that could be used as a condition in #if preprocessing
> directives; if(), while(), do while(), or for() statements; or ?:
> expressions.
>
> In such a language, the connection between B and C above would be
> broken; and I wouldn't mind, but such a language could not be backward
> compatible with existing C code, so I cannot favor any such change to C
> itself.

I think your conditions are not quite enough.  I'd say that the boolean
type must not be ordered.  If it is ordered, (false is usually < true)
there is a reasonable (C-like) meaning to A -- it means the same as B
and C.  To fully break the connection between these expressions,
booleans should be unordered.

That's a step too far for lots of languages.  For example, Haskell will
sort a list of bool values as happily as it will any type with an
ordering.  It meets your conditions (a), (b) and (c) but the designers
chose to make < non-associative so that 3 < 2 < 1 is a parse error
rather than a type error.

<snip>
-- 
Ben.

[toc] | [prev] | [next] | [standalone]


#11413

FromJames Kuyper <jameskuyper@verizon.net>
Date2011-10-08 17:17 -0400
Message-ID<j6qeku$e4p$1@dont-email.me>
In reply to#11408
On 10/08/2011 04:49 PM, Ben Bacarisse wrote:
> James Kuyper <jameskuyper@verizon.net> writes:
> <snip>
>> A:	3 < 2 < 1
>> B:	(3 < 2) < 1
>> C:	0 < 1
> <snip>
>> In a new language that was otherwise similar to C, I'd favor having a
>> boolean type that was
>> a) Not treated as special kind of integer type
>> b) incapable of conversion to or from any other type.
>> c) the only type that could be used as a condition in #if preprocessing
>> directives; if(), while(), do while(), or for() statements; or ?:
>> expressions.
>>
>> In such a language, the connection between B and C above would be
>> broken; and I wouldn't mind, but such a language could not be backward
>> compatible with existing C code, so I cannot favor any such change to C
>> itself.
> 
> I think your conditions are not quite enough.  I'd say that the boolean
> type must not be ordered.  If it is ordered, (false is usually < true)
> there is a reasonable (C-like) meaning to A -- it means the same as B
> and C.  To fully break the connection between these expressions,
> booleans should be unordered.

I forgot a few additional item:
d) expressions containing the defined operator in #if directives, and
all relational, equality, and logical expressions have values of boolean
type.
e) Logical operators (&&, ||) require operands of boolean type.

There's no need to prohibit comparisons of boolean values with each
other for relative order, so long as they cannot be compared with
anything else. In the hypothetical language that I was describing, 1
cannot be converted to a boolean type, and the boolean value of 3<2
cannot be converted to an integer type; without a common type that both
can be converted to, "false < 1" would have to be a constraint violation.
-- 
James Kuyper

[toc] | [prev] | [next] | [standalone]


#11417

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2011-10-08 22:59 +0100
Message-ID<0.05da23b1f25502367918.20111008225930BST.87zkhbrvp9.fsf@bsb.me.uk>
In reply to#11413
James Kuyper <jameskuyper@verizon.net> writes:

> On 10/08/2011 04:49 PM, Ben Bacarisse wrote:
>> James Kuyper <jameskuyper@verizon.net> writes:
>> <snip>
>>> A:	3 < 2 < 1
>>> B:	(3 < 2) < 1
>>> C:	0 < 1
>> <snip>
>>> In a new language that was otherwise similar to C, I'd favor having a
>>> boolean type that was
>>> a) Not treated as special kind of integer type
>>> b) incapable of conversion to or from any other type.
>>> c) the only type that could be used as a condition in #if preprocessing
>>> directives; if(), while(), do while(), or for() statements; or ?:
>>> expressions.
>>>
>>> In such a language, the connection between B and C above would be
>>> broken; and I wouldn't mind, but such a language could not be backward
>>> compatible with existing C code, so I cannot favor any such change to C
>>> itself.
>> 
>> I think your conditions are not quite enough.  I'd say that the boolean
>> type must not be ordered.  If it is ordered, (false is usually < true)
>> there is a reasonable (C-like) meaning to A -- it means the same as B
>> and C.  To fully break the connection between these expressions,
>> booleans should be unordered.
>
> I forgot a few additional item:
> d) expressions containing the defined operator in #if directives, and
> all relational, equality, and logical expressions have values of boolean
> type.
> e) Logical operators (&&, ||) require operands of boolean type.
>
> There's no need to prohibit comparisons of boolean values with each
> other for relative order, so long as they cannot be compared with
> anything else. In the hypothetical language that I was describing, 1
> cannot be converted to a boolean type, and the boolean value of 3<2
> cannot be converted to an integer type; without a common type that both
> can be converted to, "false < 1" would have to be a constraint
> violation.

Maybe I've missed your point, but it seems to be that

 a < b < c

is perfectly valid when a, b and c are of type bool (not C bool -- this
hypothetical language's bool) provided that bool is an ordered type.  I
was not saying that an ordered bool type somehow effected 3 < 2 < 1,
just that it affects some syntactically similar expressions.

-- 
Ben.

[toc] | [prev] | [next] | [standalone]


#11422

FromJames Kuyper <jameskuyper@verizon.net>
Date2011-10-08 21:33 -0400
Message-ID<j6qtl9$1v0$1@dont-email.me>
In reply to#11417
On 10/08/2011 05:59 PM, Ben Bacarisse wrote:
> James Kuyper <jameskuyper@verizon.net> writes:
...
>> There's no need to prohibit comparisons of boolean values with each
>> other for relative order, so long as they cannot be compared with
>> anything else. In the hypothetical language that I was describing, 1
>> cannot be converted to a boolean type, and the boolean value of 3<2
>> cannot be converted to an integer type; without a common type that both
>> can be converted to, "false < 1" would have to be a constraint
>> violation.
> 
> Maybe I've missed your point, but it seems to be that
> 
>  a < b < c
> 
> is perfectly valid when a, b and c are of type bool (not C bool -- this
> hypothetical language's bool) provided that bool is an ordered type.  I
> was not saying that an ordered bool type somehow effected 3 < 2 < 1,
> just that it affects some syntactically similar expressions.

You're right, I'd forgotten to cover that possibility. It seems we must
sacrifice either sortability of boolean values, or the proposed new
meaning for a<b<c. Given those options, I favor sortability.
-- 
James Kuyper

[toc] | [prev] | [next] | [standalone]


#11432

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2011-10-09 09:09 +0100
Message-ID<0.2dfc50b72ffcd236185f.20111009090921BST.87ipnysi1a.fsf@bsb.me.uk>
In reply to#11422
James Kuyper <jameskuyper@verizon.net> writes:

> On 10/08/2011 05:59 PM, Ben Bacarisse wrote:
>> James Kuyper <jameskuyper@verizon.net> writes:
> ...
>>> There's no need to prohibit comparisons of boolean values with each
>>> other for relative order, so long as they cannot be compared with
>>> anything else. In the hypothetical language that I was describing, 1
>>> cannot be converted to a boolean type, and the boolean value of 3<2
>>> cannot be converted to an integer type; without a common type that both
>>> can be converted to, "false < 1" would have to be a constraint
>>> violation.
>> 
>> Maybe I've missed your point, but it seems to be that
>> 
>>  a < b < c
>> 
>> is perfectly valid when a, b and c are of type bool (not C bool -- this
>> hypothetical language's bool) provided that bool is an ordered type.  I
>> was not saying that an ordered bool type somehow effected 3 < 2 < 1,
>> just that it affects some syntactically similar expressions.
>
> You're right, I'd forgotten to cover that possibility. It seems we must
> sacrifice either sortability of boolean values, or the proposed new
> meaning for a<b<c. Given those options, I favor sortability.

The "problem" (I am not sure i remember what it is) may be worse in the
I used < following your example, but the general idea would be to do
this for all relations operators, so

  a == b == c

would be permitted to mean a == b && b == c (with b evaluated only
once).  It would be a bog step to outlaw equality testing for bool.

Again, unless I'm missing the main point, I don't see the problem.  If
this hypothetical language clearly states all the relational operators
and non-associative, chains of them must mean something other the usual
default pair-wise bracketing that associativity implies.  Given that in
mathematics, (a < b) < c is at the very least odd, or rare, compared to
a < b < c, I'd be happy for it to have it's obvious meaning distinct
from the unbracketed version.  In many non-C-like languages, things like
(3 < 2) < 1 will be type error anyway, so the only "silent" cases would
be the very rare examples of bracketed comparisons of booleans.

-- 
Ben.

[toc] | [prev] | [next] | [standalone]


#11441

FromJames Kuyper <jameskuyper@verizon.net>
Date2011-10-09 07:00 -0400
Message-ID<j6rutc$sc0$1@dont-email.me>
In reply to#11432
On 10/09/2011 04:09 AM, Ben Bacarisse wrote:
...
> The "problem" (I am not sure i remember what it is) may be worse in the
> I used < following your example, but the general idea would be to do
> this for all relations operators, so
> 
>   a == b == c
> 
> would be permitted to mean a == b && b == c (with b evaluated only
> once).  It would be a bog step to outlaw equality testing for bool.
> 
> Again, unless I'm missing the main point, I don't see the problem.  If
> this hypothetical language clearly states all the relational operators
> and non-associative, chains of them must mean something other the usual
> default pair-wise bracketing that associativity implies.

Associativity isn't the relevant characteristic. Associativity is about
how an expression's meaning can be rearranged, while still having the
same value; my issue with this proposal doesn't have anything to do with
an expression's possible rearrangements. In the hypothetical language I
was discussing, chains of relational or equality operators would
necessarily be constraint violations - unless all values being compared
after the first two were of boolean type - and that's the problem.
There's no way to handle that case which is consistent with the proposed
chain rule for relational and equality operators without violating a key
feature that the hypothetical language was intended to share with C.

The relevant feature of C is that every complex expression can be broken
down recursively into a top-level operator operating on the value of
it's sub-expressions. The value and meaning of the sub-expressions
depends only upon the sub-expression itself, not on the context in which
it occurs. What the top-level operation does depends only upon the
values of it's operands, and not upon how they were calculated. I can
think of a few special exceptions (for instance, the fact that &*p can
have a well-defined meaning in contexts where *p does not), but in
general this is a fundamental feature of the structure of C. The
proposed new interpretation of

	x = a == b == c;

would make it quite different from

	auto temp = a == b;
	x = temp == c;

I've borrowed here a new feature of C++, where the 'auto' keyword causes
'temp' to be declared with precisely the type of it's initializer. That
type would be 'int' in C; and 'bool' in the hypothetical language I've
been referring to, but the issue is the same in both cases.
-- 
James Kuyper

[toc] | [prev] | [next] | [standalone]


#11420

From"BartC" <bc@freeuk.com>
Date2011-10-09 01:12 +0100
Message-ID<j6qp25$c5s$1@dont-email.me>
In reply to#11388
"Ben Bacarisse" <ben.usenet@bsb.me.uk> wrote in message 
news:0.9c297e0e5b9ae67129fd.20111008104538BST.87zkhbu88t.fsf@bsb.me.uk...

> A simpler solution is to parse without creating the extra && nodes and
> have the code generator (or some later parse tree re-writing) handle it.
> Then (2 < 1) < 1 and 2 < (1 < 3) can easily mean the same as 2 < 1 < 3.
>
> But none of this can be about C, surely, not even as an extension.  In
> that case (a < b) < c does not have to mean the same as a < b < c.  The
> relational operators (in this scheme) are non-associative, so the
> programmer will know that the parentheses can change the meaning.

I've had a go at implementing a<b<c for one of my language projects.

The expression is modified in a subsequent pass, after already being parsed 
as (< (< a b) c). When the left operand of a compare op is also a compare 
op, the whole thing gets changed to (and (< a b) (< b c)).

('b' gets evaluated twice, but I don't care; not at this time of night 
anyway.)

This works fine (also for long chains of relational and equality ops).

But I thought that by writing (a<b)<c, I could also turn a<b into a bool 
result, and compare that against c (this is more useful when written as 
(a<b)==c), but it doesn't work! The parentheses disappear. Which in fact is 
as it should be:

If a<b<c is usually evaluated as (a<b)<c, then actually writing (a<b)<c 
should do the same. (So some dummy op is needed to isolate the a<b bit - in 
C that might be something like !!(a<b) - so that the conversion above is not 
triggered.)

(Then I tried a<(b<c), which does compare a against the bool result of b<c; 
that's OK, as there is no other meaning for that. The only niggle is that it 
doesn't match the behaviour of a+b+c and a+(b+c), which are more or less the 
same.)

-- 
Bartc 

[toc] | [prev] | [next] | [standalone]


#11431

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2011-10-09 08:55 +0100
Message-ID<0.e63445836250346188d0.20111009085536BST.87obxqsio7.fsf@bsb.me.uk>
In reply to#11420
"BartC" <bc@freeuk.com> writes:

> "Ben Bacarisse" <ben.usenet@bsb.me.uk> wrote in message
> news:0.9c297e0e5b9ae67129fd.20111008104538BST.87zkhbu88t.fsf@bsb.me.uk...
>
>> A simpler solution is to parse without creating the extra && nodes and
>> have the code generator (or some later parse tree re-writing) handle it.
>> Then (2 < 1) < 1 and 2 < (1 < 3) can easily mean the same as 2 < 1 < 3.
>>
>> But none of this can be about C, surely, not even as an extension.  In
>> that case (a < b) < c does not have to mean the same as a < b < c.  The
>> relational operators (in this scheme) are non-associative, so the
>> programmer will know that the parentheses can change the meaning.
>
> I've had a go at implementing a<b<c for one of my language projects.
>
> The expression is modified in a subsequent pass, after already being
> parsed as (< (< a b) c). When the left operand of a compare op is also
> a compare op, the whole thing gets changed to (and (< a b) (< b c)).
>
> ('b' gets evaluated twice, but I don't care; not at this time of night
> anyway.)

That should be fixed but I can see it's not a priority in an experiment.

> This works fine (also for long chains of relational and equality ops).
>
> But I thought that by writing (a<b)<c, I could also turn a<b into a
> bool result, and compare that against c (this is more useful when
> written as (a<b)==c), but it doesn't work! The parentheses
> disappear. Which in fact is as it should be:

The simples options is to parse are I originally described, and then,
because the operators are non-associative, adding brackets to the left
or to the right will produce something new.

Once you have a parse tree of (< (< a b) c) there is no way to know if
it's from (a < b) < c or a plain a < b < c.  There might be a kludge in
that could use a spare bit in the operator to indicate if it was
originally in parentheses, but that's, well, a kludge!

> If a<b<c is usually evaluated as (a<b)<c, then actually writing
> (a<b)<c should do the same. (So some dummy op is needed to isolate the
> a<b bit - in C that might be something like !!(a<b) - so that the
> conversion above is not triggered.)

I don't follow this.  If a<b<c is usually evaluated as (a<b)<c that's
what you should do, and a<b<c can't have it's special meaning.

> (Then I tried a<(b<c), which does compare a against the bool result of
> b<c; that's OK, as there is no other meaning for that. The only niggle
> is that it doesn't match the behaviour of a+b+c and a+(b+c), which are
> more or less the same.)

Id say it's not a niggle at all -- it perfect.  < is not symmetric, so a
better comparison is with a-b-c which changes meaning with brackets:
a-(b-c).

-- 
Ben.

[toc] | [prev] | [next] | [standalone]


#11362

FromRobert Wessel <robertwessel2@yahoo.com>
Date2011-10-07 18:16 -0500
Message-ID<rj1v871u15fpmnp1b8avt7gvun3769tc69@4ax.com>
In reply to#11353
On Fri, 07 Oct 2011 23:12:51 +0100, Ben Bacarisse
<ben.usenet@bsb.me.uk> wrote:

>James Kuyper <jameskuyper@verizon.net> writes:
><snip>
>> You could define '< <' as a special trinary operator like "?:". But then
>> you'd have to define a<b<c<d as a quaternary operator, etc. That way
>> lies madness.
>
>The madness can be avoided.  There's no need define tertiary or
>quaternary (and so on) versions.  In fact doing so either rules out a <
>b <= c or it means you need < <= as yet another operator (and so on for
>dozens of combinations).
>
>If <, >, <=, >=, == and != all have the same priority, you can parse it
>just like a + b - c + d and simply double the operand you have "in hand"
>and add &&.  The operators need to be marked as non-associative, but it
>can be fitted into an operator precedence grammar very simply.
>
>I've spent the last hour (not exclusively, you understand) trying to
>remember what language it was that I've worked on that does this, and
>I've come up with nothing.  But I don't think I'm making it up, honest.


Cobol 68 did something like that.  You could write:

  IF A IS GREATER THAN B OR C

(or equivalently)

  IF A > B OR C

You could also do things like:

  IF A IS EQUAL TO B AND NOT C

(and yes, the second term(?) is "A IS NOT EQUAL TO C")

My history on this is a bit fuzzy, but I think that form was removed
in Cobol 7x.  Or maybe that was pre-68 and it was removed in '68.

That and a related syntactical oddity introduced some *really*
confusing logical statements when the conditions became complex.

[toc] | [prev] | [next] | [standalone]


#11850

FromDavid Thompson <dave.thompson2@verizon.net>
Date2011-10-18 02:03 -0400
Message-ID<195q97lp8gqkc4kf23g2oo574d8cpie9ct@4ax.com>
In reply to#11362
On Fri, 07 Oct 2011 18:16:40 -0500, Robert Wessel
<robertwessel2@yahoo.com> wrote:

> On Fri, 07 Oct 2011 23:12:51 +0100, Ben Bacarisse
> <ben.usenet@bsb.me.uk> wrote:
<snip: a<b<c etc.>
> >If <, >, <=, >=, == and != all have the same priority, you can parse it
> >just like a + b - c + d and simply double the operand you have "in hand"
> >and add &&.  The operators need to be marked as non-associative, but it
> >can be fitted into an operator precedence grammar very simply.
> >
> >I've spent the last hour (not exclusively, you understand) trying to
> >remember what language it was that I've worked on that does this, and
> >I've come up with nothing.  But I don't think I'm making it up, honest.
> 
> 
> Cobol 68 did something like that.  You could write:
> 
>   IF A IS GREATER THAN B OR C
> 
> (or equivalently)
> 
>   IF A > B OR C
> 
> You could also do things like:
> 
>   IF A IS EQUAL TO B AND NOT C
> 
> (and yes, the second term(?) is "A IS NOT EQUAL TO C")
> 
> My history on this is a bit fuzzy, but I think that form was removed
> in Cobol 7x.  Or maybe that was pre-68 and it was removed in '68.
> 
Still in -74 and -85. And still in the last draft I looked at for -03;
I didn't follow to completion, but I would be astonished if they
dropped a longstanding feature that is trivial to implement.

Of course this repeats the _left_ comparand (and possibly the
operator), not the right which as elsethread Icon does.

FWIW in (Common)Lisp all operators are syntactically function calls,
allowing variable number of arguments e.g. (< 3 4) and (< 3 4 5 6 7).
These do have the 'obvious' semantics, except maybe /= notequal which
per standard checks all pairs not just adjacent pairs (as the C syntax
presumably would); I don't recall ever wanting /= with more than 2
operands for any real purpose, and thus exercising that case.

[toc] | [prev] | [next] | [standalone]


#11927

FromRobert Wessel <robertwessel2@yahoo.com>
Date2011-10-20 18:03 -0500
Message-ID<r591a7hfugnq0vcmrtsh38q0q8nke7qpkg@4ax.com>
In reply to#11850
On Tue, 18 Oct 2011 02:03:54 -0400, David Thompson
<dave.thompson2@verizon.net> wrote:

>On Fri, 07 Oct 2011 18:16:40 -0500, Robert Wessel
><robertwessel2@yahoo.com> wrote:
>
>> On Fri, 07 Oct 2011 23:12:51 +0100, Ben Bacarisse
>> <ben.usenet@bsb.me.uk> wrote:
><snip: a<b<c etc.>
>> >If <, >, <=, >=, == and != all have the same priority, you can parse it
>> >just like a + b - c + d and simply double the operand you have "in hand"
>> >and add &&.  The operators need to be marked as non-associative, but it
>> >can be fitted into an operator precedence grammar very simply.
>> >
>> >I've spent the last hour (not exclusively, you understand) trying to
>> >remember what language it was that I've worked on that does this, and
>> >I've come up with nothing.  But I don't think I'm making it up, honest.
>> 
>> 
>> Cobol 68 did something like that.  You could write:
>> 
>>   IF A IS GREATER THAN B OR C
>> 
>> (or equivalently)
>> 
>>   IF A > B OR C
>> 
>> You could also do things like:
>> 
>>   IF A IS EQUAL TO B AND NOT C
>> 
>> (and yes, the second term(?) is "A IS NOT EQUAL TO C")
>> 
>> My history on this is a bit fuzzy, but I think that form was removed
>> in Cobol 7x.  Or maybe that was pre-68 and it was removed in '68.
>> 
>Still in -74 and -85. And still in the last draft I looked at for -03;
>I didn't follow to completion, but I would be astonished if they
>dropped a longstanding feature that is trivial to implement.
>
>Of course this repeats the _left_ comparand (and possibly the
>operator), not the right which as elsethread Icon does.
>
>FWIW in (Common)Lisp all operators are syntactically function calls,
>allowing variable number of arguments e.g. (< 3 4) and (< 3 4 5 6 7).
>These do have the 'obvious' semantics, except maybe /= notequal which
>per standard checks all pairs not just adjacent pairs (as the C syntax
>presumably would); I don't recall ever wanting /= with more than 2
>operands for any real purpose, and thus exercising that case.


I blame age and fading memories...

True enough, implied subjects and relations still exist, but they did
change the rules in Cobol-74.  Notably the binding of NOT in
conditionals with implied relationals changed.  In Cobol 68:

IF A > B AND NOT < C AND D

parsed as:

IF (A > B) AND (NOT A < C) AND (A < D)

In Cobol-74, the NOT binds to the less than instead, changing that to:

IF (A > B) AND (A NOT < C) AND (A NOT < D)

Which doesn't change the practical meaning of the middle term (in
approximate C* terms it goes from (!(a<c)) to ((a!<c)) ), but it
certainly changes the meaning of the third term.


*Ignoring that C doesn't actually have a "!<" (not less than) operator

[toc] | [prev] | [next] | [standalone]


Page 2 of 3 — ← Prev page 1 [2] 3  Next page →

Back to top | Article view | comp.lang.c


csiph-web