Velocity Reviews > Two expression variant of ()

# Two expression variant of ()

mathog
Guest
Posts: n/a

 03-30-2012
C has two () constructs which return a value:

( expr1 ? expr2 : expr3)
( expr )

As far as I can tell the language does not define a two expression
variant. Is there some way to concoct a two expression variant that
acts like this (whatever the solution is, it has to go within () ):

( expr1 ?? expr2 ) // ?? isn't legal. used to show approx. syntax

Where
the value returned is expr1
expr2 is always evaluated
expr2 is evaluated after expr1
The value of expr2 is not used for the () logic, it is just
evaluated for side effects.

Or described another way:

in any if() or while(), within the parens
val=expression1
do some other stuff (at least one expression, more would be better)
the test is applied to val

Here is a simple example of its use with the approx. syntax in a while loop:

while( *ptr ?? {ptr+=1;val--;} ){

Notice that at the moment there seems to be no place to put the val--,
other than with a lot of extra logic, and the +=1 is only possible
because of the way ++ works:

didval=0;
while(*ptr++){
val--;
/* code */
if(whatever){didval=1; break;}
/* more code */
}
if(!didval)val--;

If we give up on putting everything within the while parens the logic is
at least easier to understand:

while(1){
tval=*ptr;
ptr+=1;
val--;
if(!tval)break;
/* code */
}

This can be accomplished by calling a function within the parens.

Can it be done without calling a function and with all implementing code
within the parens???

Thanks,

David Mathog

Kaz Kylheku
Guest
Posts: n/a

 03-30-2012
On 2012-03-30, mathog <(E-Mail Removed)> wrote:
> C has two () constructs which return a value:
>
> ( expr1 ? expr2 : expr3)
> ( expr )

This is not a () construct. It's just

expr1 ? expr2 : expr3

> while( *ptr ?? {ptr+=1;val--;} ){

Comma operator:

while (ptr += 1, val --, *ptr) ...

You really should read a C tutorial and reference manual.

Ben Pfaff
Guest
Posts: n/a

 03-30-2012
mathog <(E-Mail Removed)> writes:

> As far as I can tell the language does not define a two expression
> variant. Is there some way to concoct a two expression variant that
> acts like this (whatever the solution is, it has to go within () ):
>
> ( expr1 ?? expr2 ) // ?? isn't legal. used to show approx. syntax
>
> Where
> the value returned is expr1
> expr2 is always evaluated
> expr2 is evaluated after expr1
> The value of expr2 is not used for the () logic, it is just
> evaluated for side effects.

I don't think so.

I think that you can come close, at least, with the GCC ({})
extension:
({ typeof(expr1) e1 = expr1; expr2; e1 })
--
char a[]="\n .CJacehknorstu";int putchar(int);int main(void){unsigned long b[]
={0x67dffdff,0x9aa9aa6a,0xa77ffda9,0x7da6aa6a,0xa6 7f6aaa,0xaa9aa9f6,0x11f6},*p
=b,i=24;for(;p+=!*p;*p/=4)switch(0[p]&3)case 0:{return 0;for(p--;i--;i--)case+
2:{i++;if(i)break;else default:continue;if(0)case 1utchar(a[i&15]);break;}}}

Tim Rentsch
Guest
Posts: n/a

 03-30-2012
mathog <(E-Mail Removed)> writes:

> C has two () constructs which return a value:
>
> ( expr1 ? expr2 : expr3)
> ( expr )
>
> As far as I can tell the language does not define a two expression
> variant. Is there some way to concoct a two expression variant that
> acts like this (whatever the solution is, it has to go within () ):
>
> ( expr1 ?? expr2 ) // ?? isn't legal. used to show approx. syntax
>
> Where
> the value returned is expr1
> expr2 is always evaluated
> expr2 is evaluated after expr1
> The value of expr2 is not used for the () logic, it is just
> evaluated for side effects.
>
> Or described another way:
>
> in any if() or while(), within the parens
> val=expression1
> do some other stuff (at least one expression, more would be better)
> the test is applied to val
>
> Here is a simple example of its use with the approx. syntax in a while loop:
>
> while( *ptr ?? {ptr+=1;val--;} ){
>
> [snip elaboration]

This use case isn't very compelling, because it has
been doable easily in standard C since K&R, to wit:

while( *ptr && (ptr++, val--, 1) ){ ... }

(This assumes of course that writing such code has
been judged acceptable style, as to which I am
expressing no opinion; I'm just pointing out that
it's possible.)

Tim Rentsch
Guest
Posts: n/a

 03-30-2012
Tim Rentsch <(E-Mail Removed)> writes:

> mathog <(E-Mail Removed)> writes:
>
>> C has two () constructs which return a value:
>>
>> ( expr1 ? expr2 : expr3)
>> ( expr )
>>
>> As far as I can tell the language does not define a two expression
>> variant. Is there some way to concoct a two expression variant that
>> acts like this (whatever the solution is, it has to go within () ):
>>
>> ( expr1 ?? expr2 ) // ?? isn't legal. used to show approx. syntax
>>
>> Where
>> the value returned is expr1
>> expr2 is always evaluated
>> expr2 is evaluated after expr1
>> The value of expr2 is not used for the () logic, it is just
>> evaluated for side effects.
>>
>> Or described another way:
>>
>> in any if() or while(), within the parens
>> val=expression1
>> do some other stuff (at least one expression, more would be better)
>> the test is applied to val
>>
>> Here is a simple example of its use with the approx. syntax in a while loop:
>>
>> while( *ptr ?? {ptr+=1;val--;} ){
>>
>> [snip elaboration]

>
> This use case isn't very compelling, because it has
> been doable easily in standard C since K&R, to wit:
>
> while( *ptr && (ptr++, val--, 1) ){ ... }
>
> (This assumes of course that writing such code has
> been judged acceptable style, as to which I am
> expressing no opinion; I'm just pointing out that
> it's possible.)

What was I thinking??? This isn't the same as your
proposed construct at all. In fact now I don't see the
point of your example; presumably 'val' and 'ptr' are
independent, so this example could be written just as

while( val--, *ptr++ ){

Ben Bacarisse
Guest
Posts: n/a

 03-30-2012
Kaz Kylheku <(E-Mail Removed)> writes:

> On 2012-03-30, mathog <(E-Mail Removed)> wrote:
>> C has two () constructs which return a value:
>>
>> ( expr1 ? expr2 : expr3)
>> ( expr )

>
> This is not a () construct. It's just
>
> expr1 ? expr2 : expr3
>
> that you added parentheses around.
>
>> while( *ptr ?? {ptr+=1;val--;} ){

>
> Comma operator:
>
> while (ptr += 1, val --, *ptr) ...

The result was intended to be the value of the first expression.
Following the rules as they were specified, the literal translation
would seem to be

while (*ptr, ptr += 1, val--, ptr[-1]) ...

from which we can get

while (ptr += 1, val--, ptr[-1]) ...

and finally

while (val--, *ptr++) ...

which is Tim's translation.

FWIW, Algol 68C had "displacement operators" that are to assignment
operators what x++ is to ++x. E.g. x :=:= y assigns y to x but returns
the prior value. This can be combined with an operator, so that
x +:=:= 1 is the same as x++ in C. (I may be misremembering the syntax.)

<snip>
--
Ben.

Paul N
Guest
Posts: n/a

 03-30-2012
On Mar 30, 6:37*pm, mathog <(E-Mail Removed)> wrote:
> Is there some way to concoct a two expression variant that
> acts like this (whatever the solution is, it has to go within () ):
>
> * *( expr1 ?? expr2 ) *// ?? isn't legal. used to show approx. syntax
>
> Where
> * *the value returned is expr1
> * *expr2 is always evaluated
> * *expr2 is evaluated after expr1
> * *The value of expr2 is not used for the () logic, it is just
> * * * evaluated for side effects.

Funnily enough, I suggested this a bit ago. See my thread of August
10, 2009 entitled "Reverse comma operator?" at
.. It wasn't popular.

Regards.
Paul.

mathog
Guest
Posts: n/a

 03-30-2012
Tim Rentsch wrote:
> This use case isn't very compelling, because it has
> been doable easily in standard C since K&R, to wit:
>
> while( *ptr && (ptr++, val--, 1) ){ ... }

No cigar - if *ptr is false expr2 is not evaluated.

Hard to see how to make this work with logic statements because
the outcome of () must only depend on expr1, and if it does expr2
will not be evaluated in some instances, but the requirement was that
expr2 must always be evaluated.

A comma list will work if a temporary variable is allowed:

while (tmp=*ptr, ptr++, val--, tmp)

Can it be done without an explicit temporary variable? I'm thinking no,
unless there is some way to coerce the compiler into creating one
implicitly.

Ben Bacarisse gave this:

while (ptr += 1, val--, ptr[-1]) ...

which does not use a temporary variable, and works for the toy example,
but isn't a general solution since it depends on the value of expr1 not
being changed by evaluating expr2. That isn't guaranteed.

BartC
Guest
Posts: n/a

 03-30-2012
"Ben Bacarisse" <(E-Mail Removed)> wrote in message
news:0.eacf61bb4569bc150c57.20120330212838BST.87d3 (E-Mail Removed)...

> FWIW, Algol 68C had "displacement operators" that are to assignment
> operators what x++ is to ++x. E.g. x :=:= y assigns y to x but returns
> the prior value. This can be combined with an operator, so that
> x +:=:= 1 is the same as x++ in C. (I may be misremembering the syntax.)

It sounds a useful construct, although I've never come across it before. And
it sounds like it can be implemented efficiently too, using machine exchange
instructions, at least for the plain assignment version.

That's a hell of a syntax though..

But applied to the OP's problem, I don't think it can help avoid using a
temporary variable:

(t=expr1, t:=expr2)

where ":=" represents the displacement operator. In this case it doesn't buy
much.

Although if we're using imaginary operators, then we might as well go with
the OP's ?? operator, which ticks all the boxes..

--
Bartc

Kaz Kylheku
Guest
Posts: n/a

 03-30-2012
On 2012-03-30, mathog <(E-Mail Removed)> wrote:
> Tim Rentsch wrote:
>> This use case isn't very compelling, because it has
>> been doable easily in standard C since K&R, to wit:
>>
>> while( *ptr && (ptr++, val--, 1) ){ ... }

>
> No cigar - if *ptr is false expr2 is not evaluated.

What you're after is similar to the Lisp PROG1 operator: evaluate
some forms left to right, and then return the value that the leftmost one
returned:

(prog1 x (incf x)) ;; simulate x++, but two evaluations of x

I posed a similar question in another newsgroup. Lisp has an (or ...)
which returns the first argument which is true, and does not evaluate
the rest. This is useful for choosing a default value:

(let ((ice-cream (or (have? :chocolate) ;; prefer chocolate
(have? :strawberry) ;; not available, try strawberry
:vanilla))) ;; fall back on vanilla
...)

There is no clean way to write an OR macro in C even just with two arguments.

I.e.: or(a, b): evaluate a, and return a if it is non-zero, otherwise
evaluate b and return that value.

But you can do this with some temporary variables.

In the program I was working on, all values are of type "val", so no
GCC-specific typeof required. A hidden temporary of type val
covers all uses.

I hacked it with a declarator:

{
uses_or2;

/* ... */

foo(or2(a, b), ...)
}

To use or2, you have to put a uses_or2 somewhere in the lexical scope.

This allows or2 to expand into an expression (not a block that declares
local variables, which cannot return a value, without GCC-specific features).

It's only practical because of the generic typing; otherwise the hack
would have to be even uglier.

uses_or2(int); /* pass in type specifier for the temporary */

Ideally, we could script the compiler so that it realizes that or2 is being
used and adds the equivalent of users_or2 to the lexical scope via an
abstract syntax tree manipulation.

> Hard to see how to make this work with logic statements because
> the outcome of () must only depend on expr1, and if it does expr2
> will not be evaluated in some instances, but the requirement was that
> expr2 must always be evaluated.

PROG1 is impossible in C without temporary variables. There is no evaluation
control construct that evaluates two expressions left to right (with or without
a sequence point) but then yields the remembered value of the left one.

> A comma list will work if a temporary variable is allowed:
>
> while (tmp=*ptr, ptr++, val--, tmp)
>
> Can it be done without an explicit temporary variable? I'm thinking no,
> unless there is some way to coerce the compiler into creating one
> implicitly.

Your only tools there are preprocessor macros.

#define uses_prog1(type) \
type prog1_TeMp_stack[8]; \
int prog1_TeMp_ptr = 0

#define prog1(A, B) (prog1_TeMp_stack[prog1_TeMp_ptr++] = (A), \
(B), \
prog1_TeMp_stack[--prog1_TeMp_ptr])

{
uses_prog1(int); /* declare support necessary for prog1 */

while (prog1(*ptr, (ptr++, val--))) {

}
}

The stack allows for to eight levels of safe nesting (with no overrun check).
left-associative nesting (the kind you would usually have) is no problem even
with just a single temporary variable, but this won't work:

prog1(a, prog1(b, c))

With the stack mechanism, the inner prog1(b, c) will use its the [1] stack
location for the temporary and not disturb the saved value of a at the at the
[0] location.