View mode: basic / threaded / horizontal-split · Log in · Help
October 26, 2005
The power of static if! (A bit of fun)
I really think the docs for "static if" don't do it justice. Since I'm 
new to D templates, I've been trying to come up with a more interesting 
example than the one in the docs. Here's my first attempt. This program 
prints a nicely-formatted list of the first 30 Fibonnacci numbers _at 
compile time_.
Note that except for the clunky 'inttostr' template (which is a general 
utility template, could be quite useful in other contexts), it's not 
much longer than a straightforward implementation in a functional 
programming language.

Enjoy!

-----------------------------
template inttostr(int n)
{
   template digittostr(int n)
   {
	  static if (n==0) const char [] s="0";
	  else static if (n==1) const char [] s="1";
	  else static if (n==2) const char [] s="2";
	  else static if (n==3) const char [] s="3";
	  else static if (n==4) const char [] s="4";
	  else static if (n==5) const char [] s="5";
	  else static if (n==6) const char [] s="6";
	  else static if (n==7) const char [] s="7";
	  else static if (n==8) const char [] s="8";
	  else const char [] s="9";
   }
   static if (n<0) const char [] s = "-" ~ inttostr!(-n).s;
   else static if (n<10) const char [] s = digittostr!(n).s;
   else const char [] s = inttostr!(n/10).s ~ digittostr!(n%10).s;
}

template ordinal(int n)
{
  static if (n==1) const char [] ordinal = inttostr!(n).s ~"st";
  else static if (n==2) const char [] ordinal = inttostr!(n).s ~"nd";
  else static if (n==3) const char [] ordinal = inttostr!(n).s ~"rd";
  else const char [] ordinal = inttostr!(n).s ~"th";
}

template fib(int n)
{
    static if (n==0)      const int f=0;
    else static if (n==1) const int f=1;
    else                  const int f = fib!(n-1).f + fib!(n-2).f;
    static if (n>0) {
       pragma(msg, "The " ~ ordinal!(n).ordinal ~
          " Fibonnacci number is "~ inttostr!(fib!(n-1).f).s);
    }
}

int main()
{
   return fib!(30).f;
   ButItWontActuallyCompile;
}
October 26, 2005
Re: The power of static if! (A bit of fun)
Here's an improved version, which generates all Fibonnacci numbers which 
are small enough to fit in the given integral type. Try changing the 
last line to short, uint, ulong, etc.
This is something that would be *extremely* hard to do in C++.
I just wish I could improve the digittostr function.

Tested on DMD-Windows 0.136 and 0.137.
-------------------
// Works for any integral type.
template inttostr(Type, Type n)
{
   template digittostr(int n)
   {
      static if (n==0) const char [] s="0";
      else static if (n==1) const char [] s="1";
      else static if (n==2) const char [] s="2";
      else static if (n==3) const char [] s="3";
      else static if (n==4) const char [] s="4";
      else static if (n==5) const char [] s="5";
      else static if (n==6) const char [] s="6";
      else static if (n==7) const char [] s="7";
      else static if (n==8) const char [] s="8";
      else const char [] s="9";
   }
   static if (Type.min<0 && n<0) const char [] s = "-" ~ inttostr!(-n).s;
   else static if (n<10) const char [] s = digittostr!(n).s;
   else const char [] s = inttostr!(Type, n/10).s ~ digittostr!(n%10).s;
}

template ordinal(int n)
{
  static if (n%10==1 && n!=11) const char [] ordinal = inttostr!(int, 
n).s ~"st";
  else static if (n%10==2 && n!=12) const char [] ordinal = 
inttostr!(int, n).s ~"nd";
  else static if (n%10==3 && n!=13) const char [] ordinal = 
inttostr!(int, n).s ~"rd";
  else const char [] ordinal = inttostr!(int, n).s ~"th";
}

// Calculate the nth Fibonnacci number
template fib(Type, int n)
{
    static if (n==1)      const Type f=0;
    else static if (n==2) const Type f=1;
    else                  const Type f = fib!(Type, n-1).f + fib!(Type, 
n-2).f;
}

template showallfibs(Type)
{
	template showfibs(Type, int n)
	{
	   pragma(msg, "The " ~ ordinal!(n).ordinal ~
		  " Fibonnacci number is "~ inttostr!(Type, fib!(Type, n).f).s);
	   static if (fib!(Type, n).f < Type.max/2) {
		   const int show = showfibs!(Type,n+1).show;
	   } else {
		 const int show = 0;
		 pragma(msg, "The " ~ ordinal!(n+1).ordinal ~
		  " Fibonnacci number is greater than " ~ inttostr!(Type, Type.max).s);
	   }
	}
	const int notfinished = showfibs!(Type, 1).show;
}

static assert(showallfibs!(long).notfinished);
October 26, 2005
Re: The power of static if! (A bit of fun)
In article <djn8dp$93g$1@digitaldaemon.com>, Don Clugston says...
>
>I really think the docs for "static if" don't do it justice. Since I'm 
>new to D templates, I've been trying to come up with a more interesting 
>example than the one in the docs. Here's my first attempt. This program 
>prints a nicely-formatted list of the first 30 Fibonnacci numbers _at 
>compile time_.

Very cool.  I hadn't thought to use pragma(msg) in that way :-)  Nor had I
realized that the concatenate operator worked on const declarations.  This is
probably the most template-oriented thing I've done in D so far:

http://svn.dsource.org/projects/ares/trunk/src/ares/std/atomic.d

Not as fancy, but it's far more compact and readable than it would have been in
C++ (note that the unsigned versions don't work because of a compiler bug).


Sean
October 27, 2005
Re: The power of static if! (A bit of fun)
Sean Kelly wrote:
> In article <djn8dp$93g$1@digitaldaemon.com>, Don Clugston says...
> 
>>I really think the docs for "static if" don't do it justice. Since I'm 
>>new to D templates, I've been trying to come up with a more interesting 
>>example than the one in the docs. Here's my first attempt. This program 
>>prints a nicely-formatted list of the first 30 Fibonnacci numbers _at 
>>compile time_.
> 
> 
> Very cool.  I hadn't thought to use pragma(msg) in that way :-)  Nor had I
> realized that the concatenate operator worked on const declarations.

It was pure speculation on my part. I did not expect either of those 
things to work. I haven't yet worked out what a 'literal' is in D, but 
it is much more generous than C++. For example, casts are permitted.

  This is
> probably the most template-oriented thing I've done in D so far:
> 
> http://svn.dsource.org/projects/ares/trunk/src/ares/std/atomic.d
> 
> Not as fancy, but it's far more compact and readable than it would have been in
> C++ (note that the unsigned versions don't work because of a compiler bug).

Nice. I haven't used the 'is' operator yet, I think it has enormous 
potential too. And now we have 'auto' typing...

I've also made a template that calculates pi at compile time by summing 
a power series. I have hopes that I can make it work to arbitrary 
precision (it only does reals right now).

Seriously, this compiler is *far* more advanced than the programming 
techniques we've developed to use it. Now that we know that a 
compile-time itoa() is possible, and even a basic compile-time printf, 
I can imagine a whole compile-time library.
October 27, 2005
Re: The power of static if! (A bit of fun)
Don Clugston wrote:
> I really think the docs for "static if" don't do it justice. Since I'm 
> new to D templates, I've been trying to come up with a more interesting 
> example than the one in the docs. Here's my first attempt. This program 
> prints a nicely-formatted list of the first 30 Fibonnacci numbers _at 
> compile time_.
> Note that except for the clunky 'inttostr' template (which is a general 
> utility template, could be quite useful in other contexts), it's not 
> much longer than a straightforward implementation in a functional 
> programming language.
> 
> Enjoy!
> 


really nice work. And when that promotion bug is fixed so things can be 
writen this way:

template inttostr(int n)
{
   static if (n<0) const char [] inttostr = "-" ~ .inttostr!(-n);
   else static if (n<10) const char [] inttostr = digittostr!(n);
   else const char [] inttostr  = .inttostr!(n/10) ~ digittostr!(n%10);
}

it will be even nicer and easier!
October 27, 2005
Re: The power of static if! (A bit of fun)
Ivan Senji wrote:
> Don Clugston wrote:
> 
>> I really think the docs for "static if" don't do it justice. Since I'm 
>> new to D templates, I've been trying to come up with a more 
>> interesting example than the one in the docs. Here's my first attempt. 
>> This program prints a nicely-formatted list of the first 30 Fibonnacci 
>> numbers _at compile time_.
>> Note that except for the clunky 'inttostr' template (which is a 
>> general utility template, could be quite useful in other contexts), 
>> it's not much longer than a straightforward implementation in a 
>> functional programming language.
>>
>> Enjoy!
>>
> 
> 
> really nice work. And when that promotion bug is fixed so things can be 
> writen this way:
> 
> template inttostr(int n)
> {
>    static if (n<0) const char [] inttostr = "-" ~ .inttostr!(-n);
>    else static if (n<10) const char [] inttostr = digittostr!(n);
>    else const char [] inttostr  = .inttostr!(n/10) ~ digittostr!(n%10);
> }
> 
> it will be even nicer and easier!

Indeed. Even better would be if a constant index of an array of 
constants, was a literal.
Then digittostr would just be

template digittostr(int n) {
  const char [] digittostr="0123456789"[n];
}

at which point it becomes a genuine functional programming language, 
because you can manipulate lists. (Right now I've shown you can create 
an arbitrary list, but AFAIK you can't peek inside it).
But maybe there's some syntax it will accept right now.

Walter's created a monster. Who knows what it can do!
October 27, 2005
Re: The power of static if! (A bit of fun)
Don Clugston wrote:
> Indeed. Even better would be if a constant index of an array of 
> constants, was a literal.
> Then digittostr would just be
> 
> template digittostr(int n) {
>   const char [] digittostr="0123456789"[n];
> }
> 

I would expect this to work instead of getting the odd "non-constant 
expression "0123456789"[5]" error.

But this works :)

template digittostr(int n)
{
  const char[] digittostr;
  static this()
  {
    digittostr = "0123456789"[n..n+1];
  }
}

But unfortunately this way we can't have implicit promotion.


> at which point it becomes a genuine functional programming language, 
> because you can manipulate lists. (Right now I've shown you can create 
> an arbitrary list, but AFAIK you can't peek inside it).
> But maybe there's some syntax it will accept right now.
> 
> Walter's created a monster. Who knows what it can do!

Indeed!
October 27, 2005
Re: The power of static if! (A bit of fun)
Ivan Senji wrote:
> 
> But this works :)
> 

Correction: it works in
  writefln(digittostr!(0).digittostr);

but not at compile time with
  pragma(msg,digittostr!(0).digittostr);

Strange. What does "string expected for message, not 'digittostr'"
mean anyway??

> template digittostr(int n)
> {
>   const char[] digittostr;
>   static this()
>   {
>     digittostr = "0123456789"[n..n+1];
>   }
> }
> 
> But unfortunately this way we can't have implicit promotion.
October 27, 2005
Re: The power of static if! (A bit of fun)
Ivan Senji wrote:
> Ivan Senji wrote:
> 
>>
>> But this works :)
>>
> 
> Correction: it works in
>   writefln(digittostr!(0).digittostr);
> 
> but not at compile time with
>   pragma(msg,digittostr!(0).digittostr);
> 
> Strange. What does "string expected for message, not 'digittostr'"
> mean anyway??

It means it didn't evaluate it at compile time.

We're so close!

I've also tried this way:

   const char q[][] = ["0", "1", "2", "3","4","5","6","7","8","9"];
   const char[] digittostr = q[n];

but it gives the string as q[3], not "3".

It seems that [] is never evaluated at compile time, but it's 
fascinating that ~ is.
October 27, 2005
Re: The power of static if! (A bit of fun)
Don Clugston wrote:
> Ivan Senji wrote:
>> Strange. What does "string expected for message, not 'digittostr'"
>> mean anyway??
> 
> 
> It means it didn't evaluate it at compile time.
> 

Yes, i figured out this was the problem.

> We're so close!
> 

I hope so.

> I've also tried this way:
> 
>    const char q[][] = ["0", "1", "2", "3","4","5","6","7","8","9"];
>    const char[] digittostr = q[n];
> 
> but it gives the string as q[3], not "3".
> 
> It seems that [] is never evaluated at compile time, but it's 
> fascinating that ~ is.

Yes it is fascinating, i hope this is a bug and not by spec.
Maybe to solve this problem a little Walter-intervention is needed?
« First   ‹ Prev
1 2 3 4
Top | Discussion index | About this forum | D home