November 01, 2005
Sean Kelly wrote:
> In article <djq9pn$1jo5$1@digitaldaemon.com>, Ivan Senji says...
> 
>>But this works :)
>>
>>template digittostr(int n)
>>{
>>  const char[] digittostr;
>>  static this()
>>  {
>>    digittostr = "0123456789"[n..n+1];
>>  }
>>}
> 
> 
> Another surprise.  So constants can be initialized at run time via static this?
> I thought the format always had to be:
> 
> const T t = val;
> 
> Interesting.

Colour me surprised, this is an actual intended feature - if a const value isn't given an initialiser, it can be given one in a static constructor.  It can also be used for write-once fields in a class:

http://www.digitalmars.com/d/attribute.html#const
November 01, 2005
On Tue, 01 Nov 2005 14:26:49 +0000, Burton Radons wrote:

> Colour me surprised, this is an actual intended feature - if a const value isn't given an initialiser, it can be given one in a static constructor.  It can also be used for write-once fields in a class:
> 
> http://www.digitalmars.com/d/attribute.html#const

Yeah! I really wanted this feature and I didn't realize it existed either.

Sample code:
---------------------------
import std.stdio;
const int
    code_A,
    code_B,
    code_C,
    code_D,
    code_E;

static this()
{
    int v = 1;

    code_A = v++;
    code_B = v++;
    code_C = v++;
    code_D = v++;
    code_E = v++;

}

void main()
{
    writefln("%d %d %d %d %d ",
    code_A,
    code_B,
    code_C,
    code_D,
    code_E
    );
}

-- 
Derek
(skype: derek.j.parnell)
Melbourne, Australia
2/11/2005 10:39:21 AM
November 01, 2005
Nice! Now if only we could make the assigment at the declaration site, rather than just within static-ctors (the compiler could create an implicit static-ctor in the same way that it creates module-ctors :-)

e.g. const Foo f = new Foo;

Also new to me was this little nugget at the bottom of the page: "Functions declared as abstract can still have function bodies. This is so that even though they must be overridden, they can still provide 'base class functionality.' " ...  Suuweeeet! When did that happen?

Hats' off to Walter for these two.



"Burton Radons" <burton-radons@smocky.com> wrote in message news:dk8q3b$136s$1@digitaldaemon.com...
> Sean Kelly wrote:
>> In article <djq9pn$1jo5$1@digitaldaemon.com>, Ivan Senji says...
>>
>>>But this works :)
>>>
>>>template digittostr(int n)
>>>{
>>>  const char[] digittostr;
>>>  static this()
>>>  {
>>>    digittostr = "0123456789"[n..n+1];
>>>  }
>>>}
>>
>>
>> Another surprise.  So constants can be initialized at run time via static
>> this?
>> I thought the format always had to be:
>>
>> const T t = val;
>>
>> Interesting.
>
> Colour me surprised, this is an actual intended feature - if a const value isn't given an initialiser, it can be given one in a static constructor. It can also be used for write-once fields in a class:
>
> http://www.digitalmars.com/d/attribute.html#const


November 02, 2005
On Tue, 1 Nov 2005 15:49:22 -0800, Kris wrote:


> Also new to me was this little nugget at the bottom of the page: "Functions declared as abstract can still have function bodies. This is so that even though they must be overridden, they can still provide 'base class functionality.' " ...  Suuweeeet! When did that happen?

Huh? If they *must* be overridden, how does their function body get executed? In fact, I've tried a few tests and it seems that they do not have to be overridden anyway. Also, it seems that the only thing that 'abstract' does is allow the compiler to issue an error rather than catch it at link time.

Sample without 'abstract':
---------------------
import std.stdio;
class CC_base
{
    void funcX();
}

class myClass : CC_base
{
}

void main()
{
    myClass cc = new myClass;
    cc.funcX();
}
------------------
This compiles okay but crashes at link time " Error 42: Symbol Undefined _D4test7CC_base5funcXFZv".

If I put the 'abstract' on the class declaration it has no effect. The linker still aborts.

If I put it on the member function "abstract void funcX();" then the compiler detects a problem "cannot create instance of abstract class myClass".

If I give the function a body ...

    abstract void funcX()
    {
        writefln("Base functionality");
    }

it compiles, links and runs okay. The 'abstract' function which is *not* overridden gets run.

If I remove the 'abstract' but retain the body there is no change. The 'abstract' doesn't seem to do anything with regards to forcing the function to be overridden.

So it seems that if you give an abstract function a body then the 'abstract' is ignored.

-- 
Derek
(skype: derek.j.parnell)
Melbourne, Australia
2/11/2005 10:52:14 AM
November 02, 2005
I haven't tried compiling or running any of these, so please take these comments with a grain of salt:

1) In the cases without a function body, the linker is doing the right thing. That "no body" syntax states the symbol will be resolved elsewhere. You must add "abstract" to the method declaration to get the desired behaviour, as you did in the third case.

2) The way I read the abstract documentation is thus: "an abstract method can provide basic implementation, which may or may not be taken advantage of by an overriding implementation". Hence, a subclass must provide a matching & overriding method (upon the superclass abstract method). However, said subclass method can simply invoke super.functionName(args) to get the default behavior.

If, as you indicate, an abstract method with a body does not actually /require/ subclass implementation, then the use of "abstract" on the superclass method is entirely superfluous ~ and the documentation claims would thus be bogus (since the compiler would behave the same with & without the superclass "abstract" method modifer). I sincerely hope this indicates a bug in the compiler as opposed to a waft of hot air from the documentation ;-)

- Kris



"Derek Parnell" <derek@psych.ward> wrote in message news:nvxauw987u1e$.h217vqke1lia$.dlg@40tude.net...
> On Tue, 1 Nov 2005 15:49:22 -0800, Kris wrote:
>
>
>> Also new to me was this little nugget at the bottom of the page:
>> "Functions
>> declared as abstract can still have function bodies. This is so that even
>> though they must be overridden, they can still provide 'base class
>> functionality.' " ...  Suuweeeet! When did that happen?
>
> Huh? If they *must* be overridden, how does their function body get executed? In fact, I've tried a few tests and it seems that they do not have to be overridden anyway. Also, it seems that the only thing that 'abstract' does is allow the compiler to issue an error rather than catch it at link time.
>
> Sample without 'abstract':
> ---------------------
> import std.stdio;
> class CC_base
> {
>    void funcX();
> }
>
> class myClass : CC_base
> {
> }
>
> void main()
> {
>    myClass cc = new myClass;
>    cc.funcX();
> }
> ------------------
> This compiles okay but crashes at link time " Error 42: Symbol Undefined _D4test7CC_base5funcXFZv".
>
> If I put the 'abstract' on the class declaration it has no effect. The linker still aborts.
>
> If I put it on the member function "abstract void funcX();" then the compiler detects a problem "cannot create instance of abstract class myClass".
>
> If I give the function a body ...
>
>    abstract void funcX()
>    {
>        writefln("Base functionality");
>    }
>
> it compiles, links and runs okay. The 'abstract' function which is *not* overridden gets run.
>
> If I remove the 'abstract' but retain the body there is no change. The
> 'abstract' doesn't seem to do anything with regards to forcing the
> function
> to be overridden.
>
> So it seems that if you give an abstract function a body then the 'abstract' is ignored.
>
> -- 
> Derek
> (skype: derek.j.parnell)
> Melbourne, Australia
> 2/11/2005 10:52:14 AM


November 02, 2005
Derek Parnell wrote:
> On Tue, 1 Nov 2005 15:49:22 -0800, Kris wrote:
> 
> 
> 
>>Also new to me was this little nugget at the bottom of the page: "Functions declared as abstract can still have function bodies. This is so that even though they must be overridden, they can still provide 'base class functionality.' " ...  Suuweeeet! When did that happen?

Awesome!

> Huh? If they *must* be overridden, how does their function body get
> executed?

It's similar to this in C++:

class C {
    virtual void fn() = 0 { /* default behavior */ }
};

class D : C {
    virtual void fn() { C::fn(); }
};

> In fact, I've tried a few tests and it seems that they do not
> have to be overridden anyway. Also, it seems that the only thing that
> 'abstract' does is allow the compiler to issue an error rather than catch
> it at link time.

Perhaps this bit isn't finished yet.  It would be nice if this were enforced as per the spec.


Sean
November 02, 2005
Derek Parnell wrote:
> On Sun, 30 Oct 2005 01:38:17 +0300, Georg Wrede wrote:
> 
> 
>>Walter Bright wrote:
>>
>>>"Don Clugston" <dac@nospam.com.au> wrote in message news:djput7$1822$1@digitaldaemon.com...
>>>
>>>
>>>>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.
>>>
>>>This is perfect stuff for a magazine article. If you want to prepare
>>>one, I can get you in with the publisher(s).
>>
>>Guys, this is just awesome!
>>
>>It took Don to show us what Walter has created!
>>
>>I'm getting the impression it's time to throw my meta stuff out the window. ;-(
> 
> 
> Ok, I'll expose my ignorance here, but why is this such a fanfare item? Its
> just a fancy way to declare literals, no? And who needs PI calculated at
> compile time anyway - just hard code the literal - it ain't changing
> anytime soon. What am I missing?

Yes, calculating PI is largely useless, the only reason for using PI is that everyone knows what it should be.
But in general, the feature allows you to replace most 'magic numbers' with the program which was used to create them.
Even more interesting to me is the possibility of creating lookup tables at compile time. Examples:
* the table which is used for isalpha(), ispunct(), etc.
* the table of primes in the BigInt library of Deimos.

In both these cases, it's obvious that another program was written to generate those tables. Where is it now? Is it bug-free? What if you decide you need a bigger lookup table?

With the metaprogramming possibilities in D, we don't need another program.

Caveat: right now, lookup tables can only be created using strings to store the data, because ~ is evaluated early only for strings, and []
is never evaluated early. But I think both those limitations are emminently fixable.

It's interesting also because it gives most of the capability of languages like LISP, but with syntax that is closer to C, and consequently much more intelligible for C/C++ programmers.
It's a case where D is venturing into unexplored territority.
November 02, 2005
Burton Radons wrote:
>...
> It can also be used for write-once fields in a class:
> 
> http://www.digitalmars.com/d/attribute.html#const

Hum... thus, that's a case where it's not true that "The const attribute declares constants that can be evaluated at compile time", right?


-- 
Bruno Medeiros - CS/E student
"Certain aspects of D are a pathway to many abilities some consider to be... unnatural."
November 02, 2005
Kris wrote:
> I haven't tried compiling or running any of these, so please take these comments with a grain of salt:
> 
> 1) In the cases without a function body, the linker is doing the right thing. That "no body" syntax states the symbol will be resolved elsewhere. You must add "abstract" to the method declaration to get the desired behaviour, as you did in the third case.
> 
Hum, should this be allowed? Is it even possible (at source code level) to declare a class method *outside* of the class declaration itself? (à la C++)


-- 
Bruno Medeiros - CS/E student
"Certain aspects of D are a pathway to many abilities some consider to be... unnatural."
November 02, 2005
Don Clugston wrote:
> 
> It's interesting also because it gives most of the capability of languages like LISP, but with syntax that is closer to C, and consequently much more intelligible for C/C++ programmers.
> It's a case where D is venturing into unexplored territority.

Agreed.  Blitz++ is a good example of some practical uses for this sort of thing (http://www.oonumerics.org/blitz/), but this sort of code generation is difficult to impossible with C++.  All we need now is built-in support for lists and we'll practically have a real LISP front-end on D :)


Sean