## digitalmars.D.announce - template functions, a special case of constant folding?

Hasan Aljudy <hasan.aljudy gmail.com> writes:
```Given the following expression:
#x = 10 * 5 + y;
the compiler will compute 10 * 5 at compile-time and convert the
expression into
#x = 50 + y;

I think that's called constant-folding, am I right?

Why can't this be extended such that for the following function:
# int add( int x, int y ) { return x + y; }

if it's called with constant arguments:
# x = add( 10, 3 );

the compiler shall do the computation at compile time and convert it to:
# x = 13;
is there a particular reason for not doing that?

What I'm trying to say is, why do we need templates to do compile-time
computation of square roots? (as shown on
http://www.digitalmars.com/d/templates-revisited.html)

Why not, instead of calling the templated sqrt
#    x = sqrt!(2);
you just call the regular sqrt
#    x = sqrt(2);
and the compiler, if smart enough, should do the computation at compile
time?

If it's too hard to make the compiler smart enough, then maybe we can
add a keyword to hint to the compiler that if all arguments to this
function are constants then it can be "folded"!
After all, that's essentially what the "template" keyword is doing!
(kinda, not really though, I know).

# fold int add( int x, int y ) { return x + y; }
vs.
# template add( int x, int y ) { const add = x + y; }

The "fold" version of the function can be reused for non-constant
arguments. Where as the templated version can't. (although I'm not
```
Mar 23 2006
Derek Parnell <derek psych.ward> writes:
```On Thu, 23 Mar 2006 16:34:07 -0700, Hasan Aljudy wrote:

Given the following expression:
#x = 10 * 5 + y;
the compiler will compute 10 * 5 at compile-time and convert the
expression into
#x = 50 + y;

I think that's called constant-folding, am I right?

Why can't this be extended such that for the following function:
# int add( int x, int y ) { return x + y; }

if it's called with constant arguments:
# x = add( 10, 3 );

You can almost do this with mixins, except that mixins only allow one to
mixin a complete statement and not just an expression. What would be useful
is to allow mixins (or some other similar thing) to generate expressions at
compile time and not just statements. Something like ...

{
b + c;
}

int main()
{
int q;
return q;
}

Which would generate

int main()
{
int q;
q = 10 + 3;
return q;
}

Which the compiler would constant-fold as normal.

But this is starting to look too much like text macros which Walter is very
concerned not to have.

--
Derek
(skype: derek.j.parnell)
Melbourne, Australia
"Down with mediocracy!"
24/03/2006 10:51:16 AM
```
Mar 23 2006
James Dunne <james.jdunne gmail.com> writes:
```Derek Parnell wrote:
On Thu, 23 Mar 2006 16:34:07 -0700, Hasan Aljudy wrote:

Given the following expression:
#x = 10 * 5 + y;
the compiler will compute 10 * 5 at compile-time and convert the
expression into
#x = 50 + y;

I think that's called constant-folding, am I right?

Why can't this be extended such that for the following function:
# int add( int x, int y ) { return x + y; }

if it's called with constant arguments:
# x = add( 10, 3 );

You can almost do this with mixins, except that mixins only allow one to
mixin a complete statement and not just an expression. What would be useful
is to allow mixins (or some other similar thing) to generate expressions at
compile time and not just statements. Something like ...

{
b + c;
}

int main()
{
int q;
return q;
}

Which would generate

int main()
{
int q;
q = 10 + 3;
return q;
}

Which the compiler would constant-fold as normal.

But this is starting to look too much like text macros which Walter is very
concerned not to have.

Why not reuse alias?  Aliased expressions.

--
Regards,
James Dunne
```
Mar 23 2006
Hasan Aljudy <hasan.aljudy gmail.com> writes:
```Derek Parnell wrote:
On Thu, 23 Mar 2006 16:34:07 -0700, Hasan Aljudy wrote:

Given the following expression:
#x = 10 * 5 + y;
the compiler will compute 10 * 5 at compile-time and convert the
expression into
#x = 50 + y;

I think that's called constant-folding, am I right?

Why can't this be extended such that for the following function:
# int add( int x, int y ) { return x + y; }

if it's called with constant arguments:
# x = add( 10, 3 );

You can almost do this with mixins, except that mixins only allow one to
mixin a complete statement and not just an expression. What would be useful
is to allow mixins (or some other similar thing) to generate expressions at
compile time and not just statements. Something like ...

{
b + c;
}

int main()
{
int q;
return q;
}

Which would generate

int main()
{
int q;
q = 10 + 3;
return q;
}

Which the compiler would constant-fold as normal.

But this is starting to look too much like text macros which Walter is very
concerned not to have.

but you're still using templates. which completely defies my point!
```
Mar 24 2006
=?ISO-8859-1?Q?Jari-Matti_M=E4kel=E4?= <jmjmak utu.fi.invalid> writes:
```Hasan Aljudy wrote:
Derek Parnell wrote:
On Thu, 23 Mar 2006 16:34:07 -0700, Hasan Aljudy wrote:

Given the following expression:
#x = 10 * 5 + y;
the compiler will compute 10 * 5 at compile-time and convert the
expression into
#x = 50 + y;

I think that's called constant-folding, am I right?

Why can't this be extended such that for the following function:
# int add( int x, int y ) { return x + y; }

if it's called with constant arguments:
# x = add( 10, 3 );

You can almost do this with mixins, except that mixins only allow one to
mixin a complete statement and not just an expression. What would be
useful
is to allow mixins (or some other similar thing) to generate
expressions at
compile time and not just statements. Something like ...

{
b + c;
}

int main()
{
int q;
return q;
}

Which would generate
int main()
{
int q;
q = 10 + 3;
return q;
}

Which the compiler would constant-fold as normal.

But this is starting to look too much like text macros which Walter is
very
concerned not to have.

but you're still using templates. which completely defies my point!

Doing this kind of compiler optimization is very expensive (adds
compiling time & optimizer complexity and thus more bugs). If you
already know that the function should be folded / inlined when you're
writing the code, it's a natural way to explicitly say this with
templates. I think the compiler already does some tricks when -inline is
used. I think new M\$ compilers convert stuff like this:

int a = 5, b = 2;
for (int i=0; i<3; i++) a *= b;
int get(int c) { return c+2; }
a = b = get(a);

into:

int a = 42, b = 42;

but IMHO it's a sign of a bad coder not to optimize code on the higher
levels. It's extremely simple to "hint" to compiler by using templates
and lift the burden of implementation to the metaprogramming engine.

--
Jari-Matti
```
Mar 24 2006
```In article <e00jv5\$19h2\$1 digitaldaemon.com>,
=?ISO-8859-1?Q?Jari-Matti_M=E4kel=E4?= says...
Hasan Aljudy wrote:
Derek Parnell wrote:
On Thu, 23 Mar 2006 16:34:07 -0700, Hasan Aljudy wrote:

Given the following expression:
#x = 10 * 5 + y;
the compiler will compute 10 * 5 at compile-time and convert the
expression into
#x = 50 + y;

I think that's called constant-folding, am I right?

Why can't this be extended such that for the following function:
# int add( int x, int y ) { return x + y; }

if it's called with constant arguments:
# x = add( 10, 3 );

You can almost do this with mixins, except that mixins only allow one to
mixin a complete statement and not just an expression. What would be
useful
is to allow mixins (or some other similar thing) to generate
expressions at
compile time and not just statements. Something like ...

{
b + c;
}

int main()
{
int q;
return q;
}

Which would generate
int main()
{
int q;
q = 10 + 3;
return q;
}

Which the compiler would constant-fold as normal.

But this is starting to look too much like text macros which Walter is
very
concerned not to have.

but you're still using templates. which completely defies my point!

Doing this kind of compiler optimization is very expensive (adds
compiling time & optimizer complexity and thus more bugs). If you
already know that the function should be folded / inlined when you're
writing the code, it's a natural way to explicitly say this with
templates. I think the compiler already does some tricks when -inline is
used. I think new M\$ compilers convert stuff like this:

int a = 5, b = 2;
for (int i=0; i<3; i++) a *= b;
int get(int c) { return c+2; }
a = b = get(a);

into:

int a = 42, b = 42;

but IMHO it's a sign of a bad coder not to optimize code on the higher
levels. It's extremely simple to "hint" to compiler by using templates
and lift the burden of implementation to the metaprogramming engine.

--
Jari-Matti

An idiom that I find helpful is static variables.

: int[] BuildLookupTable(...)
: {
:     // computes some complex table or
:     // other data set.
: }
:
: int do_lookup(int i)
: {
:     static int[] s = BuildLookupTable(...);
:     return s[i];
: }

The static int[] gets computed once and stored the first time the code runs,
after this the compiler just checks that it is assigned.  I use this in C++.

I'm not sure if this works in D, if not you can still do this:

: static int[] s;
: if (s.length == 0) {
:    s = BuildLookupTable();
: }

Sometimes a data structure computation is complex and has a lot of data, but the
code to compute it is compact.  This lets you build that code on demand at the
point of use, and only if the program needs it.

Kevin
```
Mar 24 2006
=?iso-8859-1?q?Knud_S=F8rensen?= <12tkvvb02 sneakemail.com> writes:
```What if the compiler automatic inlines functions with
constant arguments.

Then the optimiser could do some real work on it !

Just a trough.

Knud

On Thu, 23 Mar 2006 16:34:07 -0700, Hasan Aljudy wrote:

Given the following expression:
#x = 10 * 5 + y;
the compiler will compute 10 * 5 at compile-time and convert the
expression into
#x = 50 + y;

I think that's called constant-folding, am I right?

Why can't this be extended such that for the following function:
# int add( int x, int y ) { return x + y; }

if it's called with constant arguments:
# x = add( 10, 3 );

the compiler shall do the computation at compile time and convert it to:
# x = 13;
is there a particular reason for not doing that?

What I'm trying to say is, why do we need templates to do compile-time
computation of square roots? (as shown on
http://www.digitalmars.com/d/templates-revisited.html)

Why not, instead of calling the templated sqrt
#    x = sqrt!(2);
you just call the regular sqrt
#    x = sqrt(2);
and the compiler, if smart enough, should do the computation at compile
time?

If it's too hard to make the compiler smart enough, then maybe we can
add a keyword to hint to the compiler that if all arguments to this
function are constants then it can be "folded"!
After all, that's essentially what the "template" keyword is doing!
(kinda, not really though, I know).

# fold int add( int x, int y ) { return x + y; }
vs.
# template add( int x, int y ) { const add = x + y; }

The "fold" version of the function can be reused for non-constant
arguments. Where as the templated version can't. (although I'm not