views:

103

answers:

4

This doesn't work in D:

void doSomething(auto a, auto b){
    // ...
}

I'm just curious, will this ever work? Or is this just technically impossible? (Or just plain stupid?)

In anyway, can this be accomplished in any other way? I suppose I could use the ... and look through the argument list, but I'm kinda making a library for lazy newbie people and want them to be able to create functions easily without really caring about data types. I'm playing with the idea of creating a struct called var like

struct var{
   byte type;
   void* data
   // ...
}

// and overload like all operators so that a lazy devver can do

var doSomething(var a, var b){
   if(a == "hello")
       b = 8;
   var c = "No.:" ~ b ~ " says:" ~ a; 
   return c;
}

But my head is already starting to hurt right there. And, I'm kinda feeling I'm missing something. I'm also painfully aware that this is probably what templates are for... Are they? From the little I know, a template would look like this (?)

void doSomething(T, U)( T a, U b){
   // ...
}

But now it doesn't look so clean anymore. Maybe I'm getting all this backwards. Maybe my confusion stems from my belief that auto is a dynamic type, comparable to var i javascript, but when in reality, it's something else?

And if it isn't a dynamic type, and this is probably a whole other topic, is it possible to create one? Or is there maybe even an open source lib available? A liblazy maybe?

(PS. Yeah, maybe the lazy devver is me : )

+11  A: 

If doSomething is generic over any type of a and b, then the template version is the right thing to do:

void doSomething(T, U)(T a, U b) {
    // etc.
}

The compiler will detect the types represented by T and U at compile time and generate the proper code.

JSBangs
+6  A: 

I'll just add that something close to your idea of runtime type polymorphism (the var structure) is already implemented in the std.variant module (D2 only).

Also, technically auto is really a keyword that does nothing - it's used where you need a type modifier without a type. If you don't specify a type, D will infer it for you from the initialization expression. For example, all of these work:

auto i = 5;
const j = 5;
static k = 5;
CyberShadow
+2  A: 

Stop, don't do that! I fear that if you ignore types early on it will be harder to grasp them, especially since D is not dynamically typed. I believe types are important even in dynamic languages.

You can ignore the type in D2 by using std.variant and it can make the code look like the language is dynamically typed.

You are correct on you Template usage, but not auto. D allows you the use of this word in many circumstances, such as the return type, since D has a very good system for inferring a type. Parameters are something that doesn't come with duplicate information for the type to be inferred with.

Additional info on std.variant: Looking into this more, this is still more complicated than what you desire. For example, to assign the value to a typed variable requires a method call. and you can't access class methods from the reference.

int b = a.get!(int);
a.goFish() // Error Variant type doesn't have goFish method
he_the_great
+1  A: 

Maybe my confusion stems from my belief that auto is a dynamic type, comparable to var i javascript, but when in reality, it's something else?

auto is a storage class. In fact, it's the default storage class; it doesn't mean anything beyond 'this has a storage class'.

Now if the compiler can infer the type unambiguously, then everything is fine. Otherwise, it's an error:

auto i = 42;  // An integer literal is inferred to be of type 'int'.
auto j;       // Error!

So auto isn't a type at all. Remember that this all has to happen at compile time, not run time. So let's look at a function:

auto add(auto a, auto b)
{
    return a + b;
}

Can the compiler automatically infer the types of a, b, or the return value? Nope. In addition to the primitives that work with the add operator (int, byte, double, and so on), user defined types could overload it, and so on. Because the compiler cannot unambiguously infer any of these types, it is an error. Types must be specified in parameters because in general, they cannot be inferred (unlike declarations, for example).

Bernard

related questions