Thread overview
Declare a variable in an expression?
Aug 26, 2005
Chuck Esterbrook
Aug 26, 2005
Regan Heath
Aug 26, 2005
Derek Parnell
Aug 26, 2005
Regan Heath
Aug 26, 2005
Derek Parnell
Aug 26, 2005
Walter
Aug 26, 2005
Sean Kelly
August 26, 2005
gcc offers a little trick where you can declare a variable in an expression:

http://gcc.gnu.org/onlinedocs/gcc-3.2.3/gcc/Typeof.html
"""
...a safe "maximum" macro that operates on any arithmetic type and
evaluates each of its arguments exactly once:

     #define max(a,b) \
       ({ typeof (a) _a = (a); \
           typeof (b) _b = (b); \
         _a > _b ? _a : _b; })
"""

Of course, we don't have macros for D, but I'm interested in generating D code and having this capability would make life easier.

Is there any such capability in D?


-Chuck
August 26, 2005
On Thu, 25 Aug 2005 17:11:06 -0700, Chuck Esterbrook <Chuck.Esterbrook@gmail.antispam.com> wrote:
> gcc offers a little trick where you can declare a variable in an
> expression:
>
> http://gcc.gnu.org/onlinedocs/gcc-3.2.3/gcc/Typeof.html
> """
> ...a safe "maximum" macro that operates on any arithmetic type and
> evaluates each of its arguments exactly once:
>
>      #define max(a,b) \
>        ({ typeof (a) _a = (a); \
>            typeof (b) _b = (b); \
>          _a > _b ? _a : _b; })
> """
>
> Of course, we don't have macros for D, but I'm interested in
> generating D code and having this capability would make life easier.
>
> Is there any such capability in D?

I think "almost" is the answer. I have frequently run into the restrictions shown below..

import std.stdio;

/**/
template max(Type) { Type max(Type a, Type b) {
	return (a > b)?a:b;
}}

//This makes the calls look nicer, however it's not a typeless call like the macro
alias max!(byte)   maxByte;
alias max!(short)  maxShort;
alias max!(int)    maxInt;
alias max!(long)   maxLong;
alias max!(float)  maxFloat;
alias max!(double) maxDouble;
/**/

/**
template max(Type) { Type max(Type a, Type b) {
	return (a > b)?a:b;
}}

//If only we could do this, then it could be a typeless call.
alias max!(byte)   max;
alias max!(short)  max;
alias max!(int)    max;
alias max!(long)   max;
alias max!(float)  max;
alias max!(double) max;
/**/

//This would also give a typeless call.
/**
template maxT(Type) { Type max(Type a, Type b) {
	return (a > b)?a:b;
}}
mixin maxT!(byte);
mixin maxT!(short);
mixin maxT!(int);
mixin maxT!(long);
mixin maxT!(float);
mixin maxT!(double);
/**/

void main()
{
	byte   ba = 3, bb = 5;
	short  sa = 2, sb = 9;
	int    ia = 5, ib = 8;
	long   la = 7, lb = 2;
	float  fa = 3.8, fb = 9.2;
	double da = 2.6, db = 1.1;

	writefln(maxByte(ba,bb));
	writefln(maxShort(sa,sb));
	writefln(maxInt(ia,ib));
	writefln(maxLong(la,lb));
	writefln(maxFloat(fa,fb));
	writefln(maxDouble(da,db));

	/**
	writefln(max(ba,bb));
	writefln(max(sa,sb));
	writefln(max(ia,ib));
	writefln(max(la,lb));
	writefln(max(fa,fb));
	writefln(max(da,db));
	/**/
}

Regan
August 26, 2005
On Thu, 25 Aug 2005 17:11:06 -0700, Chuck Esterbrook wrote:

> gcc offers a little trick where you can declare a variable in an expression:

This has been requested. I think its even in the WishList poll somewhere. Basically, the enhancement would be to extend the ability to declare variables in such a way that they only have statement scope. We can already for this for 'for' and 'foreach' statements and this enhancement would extend that concept to all statements.

> http://gcc.gnu.org/onlinedocs/gcc-3.2.3/gcc/Typeof.html
> """
> ...a safe "maximum" macro that operates on any arithmetic type and
> evaluates each of its arguments exactly once:
> 
>      #define max(a,b) \
>        ({ typeof (a) _a = (a); \
>            typeof (b) _b = (b); \
>          _a > _b ? _a : _b; })
> """
> 
> Of course, we don't have macros for D, but I'm interested in generating D code and having this capability would make life easier.

The D template system might be what you are looking for to help with most of these situations.

 -------------------------
import std.stdio;

template maxmin(T)
{
    T maxT(T a, T b)
    {
        return a > b ? a : b;
    }
    T minT(T a, T b)
    {
        return a < b ? a : b;
    }
}
alias maxmin!(int).maxT     max;
alias maxmin!(real).maxT    max;
alias maxmin!(char[]).maxT  max;
alias maxmin!(int).minT     min;
alias maxmin!(real).minT    min;
alias maxmin!(char[]).minT  min;

void main()
{
    writefln("%s", max(3, 6));
    writefln("%s", max(3.1, 6.1));
    writefln("%s", max("three", "six"));
    writefln("%s", min(3, 6));
    writefln("%s", min(3.1, 6.1));
    writefln("%s", min("three", "six"));
}
 --------------------

-- 
Derek
(skype: derek.j.parnell)
Melbourne, Australia
26/08/2005 10:32:19 AM
August 26, 2005
On Fri, 26 Aug 2005 12:49:37 +1200, Regan Heath wrote:

> On Thu, 25 Aug 2005 17:11:06 -0700, Chuck Esterbrook <Chuck.Esterbrook@gmail.antispam.com> wrote:
>> gcc offers a little trick where you can declare a variable in an expression:
>>
>> http://gcc.gnu.org/onlinedocs/gcc-3.2.3/gcc/Typeof.html
>> """
>> ...a safe "maximum" macro that operates on any arithmetic type and
>> evaluates each of its arguments exactly once:
>>
>>      #define max(a,b) \
>>        ({ typeof (a) _a = (a); \
>>            typeof (b) _b = (b); \
>>          _a > _b ? _a : _b; })
>> """
>>
>> Of course, we don't have macros for D, but I'm interested in generating D code and having this capability would make life easier.
>>
>> Is there any such capability in D?
> 
> I think "almost" is the answer. I have frequently run into the restrictions shown below..
> 
> import std.stdio;
> 
> /**/
> template max(Type) { Type max(Type a, Type b) {
> 	return (a > b)?a:b;
> }}
> 
> //This makes the calls look nicer, however it's not a typeless call like
> the macro
> alias max!(byte)   maxByte;
> alias max!(short)  maxShort;
> alias max!(int)    maxInt;
> alias max!(long)   maxLong;
> alias max!(float)  maxFloat;
> alias max!(double) maxDouble;
> /**/
> 
> /**
> template max(Type) { Type max(Type a, Type b) {
> 	return (a > b)?a:b;
> }}
> 
> //If only we could do this, then it could be a typeless call.
> alias max!(byte)   max;
> alias max!(short)  max;
> alias max!(int)    max;
> alias max!(long)   max;
> alias max!(float)  max;
> alias max!(double) max;
> /**/

But we can! The trick is to make sure the template name is not the same as the alias name. That is, you can't have 'template max ...' and 'alias ... max;' in the same scope.

 -------------------------
import std.stdio;

template maxT(T)
{
    T max(T a, T b)
    {
        return a > b ? a : b;
    }
}
alias maxT!(int).max     max;
alias maxT!(real).max    max;
alias maxT!(char[]).max  max;

void main()
{
    writefln("%s", max(3, 6));
    writefln("%s", max(3.1, 6.1));
    writefln("%s", max("three", "six"));
}
  ------------------------


-- 
Derek
(skype: derek.j.parnell)
Melbourne, Australia
26/08/2005 10:54:50 AM
August 26, 2005
On Fri, 26 Aug 2005 10:57:55 +1000, Derek Parnell <derek@psych.ward> wrote:
> But we can! The trick is to make sure the template name is not the same as the alias name. That is, you can't have 'template max ...' and 'alias ...
> max;' in the same scope.

Ahh. Of course. I thought I had tried that, obviously not! :)
I would still like the mixin method to work.

Regan
August 26, 2005
"Chuck Esterbrook" <Chuck.Esterbrook@gmail.antispam.com> wrote in message news:lcnsg1tas4n09ccc2pdk0h5j9ips8h2d9a@4ax.com...
> gcc offers a little trick where you can declare a variable in an expression:

The problem with such a syntax is the following statement:

   if  (int a || int c) { is a in scope here? is c? }

So here we have c being conditionally declared. It makes for a bit of confusing semantics.


August 26, 2005
In article <denmf2$1na3$1@digitaldaemon.com>, Walter says...
>
>
>"Chuck Esterbrook" <Chuck.Esterbrook@gmail.antispam.com> wrote in message news:lcnsg1tas4n09ccc2pdk0h5j9ips8h2d9a@4ax.com...
>> gcc offers a little trick where you can declare a variable in an expression:
>
>The problem with such a syntax is the following statement:
>
>   if  (int a || int c) { is a in scope here? is c? }
>
>So here we have c being conditionally declared. It makes for a bit of confusing semantics.

The spec isn't particularly clear on this point, but declaring a variable in a selection statement is legal in C++ (6.4.3):

"A name introduced by a declaration in a condition (either introduced by the type-specifier-seq or the declarator of the condition) is in scope from its point of declaration until the end of the substatements controlled by the condition."

Oddly, it means this is legal:

# void fn( int v ) {
#     if( int x = v )
#         cout << "yes: " << x;
#     else
#         cout << "no: " << x;
# }


Sean