November 02, 2005
Sean Kelly wrote:
> 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 :)

I just saw your post in the other forum.  That would cover everything but typelists, which would be quite useful for template specialization and such:

template fn(T : [int,long]) { void fn() {} }

I suppose the declarative form might be:

const type t = [int,long];

Though I'm not sure whether being able to declare a typelist makes sense as it would allow things like this:

static if( ... ) t[0] var;
else char var;

Thoughts?


Sean
November 02, 2005
Sean Kelly wrote:
> Sean Kelly wrote:
> 
>> 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 :)
> 
> 
> I just saw your post in the other forum.  That would cover everything but typelists, which would be quite useful for template specialization and such:
> 
> template fn(T : [int,long]) { void fn() {} }
> 
> I suppose the declarative form might be:
> 
> const type t = [int,long];
> 
> Though I'm not sure whether being able to declare a typelist makes sense as it would allow things like this:
> 
> static if( ... ) t[0] var;
> else char var;
> 
> Thoughts?

> Sean

Hmmm. That's a definite possible direction. I suspect, though, that it's not as important for D as for Lisp. We already have normal template type
parameters, structs, and indexed arrays. I'm a bit worried about painting ourselves into a corner when we don't even know how big the room is yet :-)

Another radical possibility:
Imagine that itoa!(int) was an allowable overload for itoa(int).

The rationale is, the function itoa!(int) is not a template at all. Instead, it's a function that operates on compile-time constants, turning them into other compile-time constants. It should never result in any code being generated in the executable.

The minimal syntax change to allow this would be by creating const aliases.

const alias itoa!(long n).s   char[] itoa(long n);

This means: if you see a call to itoa() where the parameter n is known at compile time, you should use the template instead of the normal itoa() function. But the ideal would be to have (say) const int as a
type which is distinct from int, having a value which is known at compile time, and potentially treated differently. (This is completely
different to const in C++, which doesn't seem to mean much at all).
Any such function could be used in compile-time expressions like static assert and static if.

So when you write
writef( itoa(x) );
and if at compile time x is known to be 7, then this compiles to
writef(itoa!(7).s);  ----> writef("7");
but if the value of x is unknown (either because it reaches that line at different times with more than one value, or because the compiler can't work it out what the single value is), it just uses itoa(x).

I'm sure there are lots of problems with this idea -- I'm just beginning to think about it. I can't see how it could be done with D's simple function overloading.

November 02, 2005
How about a function attribute of "state"? It would mean that the return value of the function is only a function of it's arguments (and it's only side effect is it's return). This would mean that if a function has the state attribute and it's arguments are known at compile time, then it's return can also be found at compile time (more or less what Don Clugston suggested under a different name). The important aspect of this is that the compiler would only allow code in such a function that it knows can be evaluated and removed at compile time. This would also eliminate the use of a template and a function doing the same thing.



In article <dkarbt$2j3$1@digitaldaemon.com>, Don Clugston says...
>
>Sean Kelly wrote:
>> Sean Kelly wrote:
>> 
>>> 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 :)
>> 
>> 
>> I just saw your post in the other forum.  That would cover everything but typelists, which would be quite useful for template specialization and such:
>> 
>> template fn(T : [int,long]) { void fn() {} }
>> 
>> I suppose the declarative form might be:
>> 
>> const type t = [int,long];
>> 
>> Though I'm not sure whether being able to declare a typelist makes sense as it would allow things like this:
>> 
>> static if( ... ) t[0] var;
>> else char var;
>> 
>> Thoughts?
>
>> Sean
>
>Hmmm. That's a definite possible direction. I suspect, though, that it's not as important for D as for Lisp. We already have normal template type parameters, structs, and indexed arrays. I'm a bit worried about painting ourselves into a corner when we don't even know how big the room is yet :-)
>
>Another radical possibility:
>Imagine that itoa!(int) was an allowable overload for itoa(int).
>
>The rationale is, the function itoa!(int) is not a template at all. Instead, it's a function that operates on compile-time constants, turning them into other compile-time constants. It should never result in any code being generated in the executable.
>
>The minimal syntax change to allow this would be by creating const aliases.
>
>const alias itoa!(long n).s   char[] itoa(long n);
>
>This means: if you see a call to itoa() where the parameter n is known at compile time, you should use the template instead of the normal itoa() function. But the ideal would be to have (say) const int as a type which is distinct from int, having a value which is known at compile time, and potentially treated differently. (This is completely different to const in C++, which doesn't seem to mean much at all). Any such function could be used in compile-time expressions like static assert and static if.
>
>So when you write
>writef( itoa(x) );
>and if at compile time x is known to be 7, then this compiles to
>writef(itoa!(7).s);  ----> writef("7");
>but if the value of x is unknown (either because it reaches that line at
>different times with more than one value, or because the compiler can't
>work it out what the single value is), it just uses itoa(x).
>
>I'm sure there are lots of problems with this idea -- I'm just beginning to think about it. I can't see how it could be done with D's simple function overloading.
>


November 06, 2005
"Bruno Medeiros" <daiphoenixNO@SPAMlycos.com> wrote in message news:4368A9E1.5050003@SPAMlycos.com...
> 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?

Yes, it makes it possible to provide the implementation of a class function in another language, such as assembly, C, or even Fortran!

> Is it even possible (at source code level)
> to declare a class method *outside* of the class declaration itself? (à
> la C++)

Not in D, but in another language, yes.


November 06, 2005
In article <dkjhqm$2hg2$1@digitaldaemon.com>, Walter Bright says...
>
>
>"Bruno Medeiros" <daiphoenixNO@SPAMlycos.com> wrote in message
>> Is it even possible (at source code level)
>> to declare a class method *outside* of the class declaration itself? (à
>> la C++)
>
>Not in D, but in another language, yes.
>

NOTE: Please, for the love of all that's sane, do not use the following in production code, unless someone puts a gun to your head.  Otherwise, Cuthulu himself will awake from his ancient slumber and devour all of mankind, starting with you. :)

In the spirit of this thread, I took walter's words here as a direct challenge, as I felt pretty sure D could be put to task here.

Technically, Walter is correct.  D wasn't designed with partial classes, from within D, in mind.  His hint above, that other languages could be used for this facility, got me thinking that this could be done.  It is possible to work around this by clever use of the compiler, and tricking the linker.

So here is the hack:

//////////////////
module test_a;
private import std.stdio;
class Foobar{
extern(C) uint add(uint a,uint b); // here is your 'empty' method
}
void main(){
Foobar f = new Foobar();
writefln("test: %d",f.add(42,69));
}

///////////////////
module test_b;
import test_a;
// here is the body of the method (that's not a typeo)
extern(C) uint _D6test_a6Foobar3addUkkZk(Foobar _this,uint a,uint b){
return a+b;
}

//////////////////
Compile: dmd test_a.d test_b.d
Run: test_a.exe
Output: "test: 111"

The trick here is is to use extern(C) as to specify the call-spec on the class-definition (test_a) side, *and* circumvent name-mangling on the method-definition side (test_b).  The horribly named symbol you see in test_b is a perfect match for the symbol in test_a, so the linker is satisified and the program runs perfectly.

The reason why this works at all is because D does not name-mangle if the symbol defined is at the module level, and does not use the D calling convention. By this, extern(C) has two distinct behaviors, depending on context; this makes sense from a C-programming point of view.

Note: I did try using extern(C) *only* on the test_b side (being careful to fetch the last parameter from EAX), but this somehow generates an access violation once main() exits; differences in stack-management between C and D perhaps?  Also, you can link the modules one at a time, and ignore the linker errors you get (even when using '-c'); for reasons unknown, these do not interfere with the creation of .obj files one bit.

- EricAnderton at yahoo
November 06, 2005
On Sat, 5 Nov 2005 15:49:02 -0800, Walter Bright wrote:

> "Bruno Medeiros" <daiphoenixNO@SPAMlycos.com> wrote in message news:4368A9E1.5050003@SPAMlycos.com...
>> 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?
> 
> Yes, it makes it possible to provide the implementation of a class function in another language, such as assembly, C, or even Fortran!
> 
>> Is it even possible (at source code level)
>> to declare a class method *outside* of the class declaration itself? (à
>> la C++)
> 
> Not in D, but in another language, yes.

Walter, you did not answer my issue with this. I repeat it from my earlier post...

It seems that the only thing that 'abstract' does is allow the compiler to issue an error rather than catch it at link time.

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.

This is *not* what the documentation seems to be saying.

-- 
Derek Parnell
Melbourne, Australia
6/11/2005 6:00:19 PM
1 2 3 4
Next ›   Last »