www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Template return values?

reply "Era Scarecrow" <rtcvb32 yahoo.com> writes:
  A thought's been going through my head for a while now. I wonder 
about template return values. Function signatures are usually the 
inputs and NOT the return type. However for writing a variant 
type could be so very useful. So unless I've misunderstood, this 
doesn't work (but it would be cool if it did).

struct Variant {
   enum ValueType {Long, Float, Double}

   ValueType vt;
   union {
     long lng;
     float fl;
     double dbl;
   }

   T getValue(T)()  property
   if (T == long || T == float || T == double) { //allowable types
     static if (T == long) { //only long case written for brevity
       switch(vt) {
         //entries would likely be mixed in and not written 
manually...
         case Long: return lng;
         case Float:
           assert(lng >= float.min && lng <= float.max);
           return cast(float) lng;
         case Float:
           assert(lng >= double.min && lng <= double.max);
           return cast(double) lng;
       }
     }

     assert(0, "Fell through, should never get here");
   }
}


  So then in theory

  Variant v;
  int i = v.getValue; //calls getValue!int()
Dec 03 2012
next sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2012-12-04 08:48, Era Scarecrow wrote:
   A thought's been going through my head for a while now. I wonder about
 template return values. Function signatures are usually the inputs and
 NOT the return type. However for writing a variant type could be so very
 useful. So unless I've misunderstood, this doesn't work (but it would be
 cool if it did).

 struct Variant {
    enum ValueType {Long, Float, Double}

    ValueType vt;
    union {
      long lng;
      float fl;
      double dbl;
    }

    T getValue(T)()  property
    if (T == long || T == float || T == double) { //allowable types
      static if (T == long) { //only long case written for brevity
        switch(vt) {
          //entries would likely be mixed in and not written manually...
          case Long: return lng;
          case Float:
            assert(lng >= float.min && lng <= float.max);
            return cast(float) lng;
          case Float:
            assert(lng >= double.min && lng <= double.max);
            return cast(double) lng;
        }
      }

      assert(0, "Fell through, should never get here");
    }
 }


   So then in theory

   Variant v;
   int i = v.getValue; //calls getValue!int()

You can use "alias this", but that only works for one type. http://dlang.org/class.html#AliasThis -- /Jacob Carlborg
Dec 04 2012
parent reply Dmitry Olshansky <dmitry.olsh gmail.com> writes:
12/4/2012 4:08 PM, Jacob Carlborg пишет:
 On 2012-12-04 08:48, Era Scarecrow wrote:
   A thought's been going through my head for a while now. I wonder about
 template return values. Function signatures are usually the inputs and
 NOT the return type. However for writing a variant type could be so very
 useful. So unless I've misunderstood, this doesn't work (but it would be
 cool if it did).

 struct Variant {
    enum ValueType {Long, Float, Double}

    ValueType vt;
    union {
      long lng;
      float fl;
      double dbl;
    }

    T getValue(T)()  property
    if (T == long || T == float || T == double) { //allowable types
      static if (T == long) { //only long case written for brevity
        switch(vt) {
          //entries would likely be mixed in and not written manually...
          case Long: return lng;
          case Float:
            assert(lng >= float.min && lng <= float.max);
            return cast(float) lng;
          case Float:
            assert(lng >= double.min && lng <= double.max);
            return cast(double) lng;
        }
      }

      assert(0, "Fell through, should never get here");
    }
 }


   So then in theory

   Variant v;
   int i = v.getValue; //calls getValue!int()

You can use "alias this", but that only works for one type. http://dlang.org/class.html#AliasThis

Well TDPL claims multiple alias this is allowed so in some distant future it maybe possible for Varaint to alias this to all built-in types. -- Dmitry Olshansky
Dec 04 2012
parent reply Dmitry Olshansky <dmitry.olsh gmail.com> writes:
12/4/2012 10:40 PM, Jonathan M Davis пишет:
 On Tuesday, December 04, 2012 21:43:09 Dmitry Olshansky wrote:
 Well TDPL claims multiple alias this is allowed so in some distant
 future it maybe possible for Varaint to alias this to all built-in types.

That would be pretty hideous IMHO. There's a reason that D eschews implicit conversions in general. And in this case, you'd very quickly end up with accidental conversions which resulted in exceptions being thrown by Variant.

Examples?
 I think that it's _much_ better to require explicit conversions from Variant.

Nope. The point of Variant is to feel natural. Keep in mind that alias this is highly customizable. I'd expect it to do safe narrowing conversions and being only r-value so it will work just fine. auto x = someVaraint; //NP: x is Varaint ushort a = x; // implicit conversion that throws on narrowing x = 32; //is fine x is int ubyte b = x; //ok, narrowed x = -1; b = x; //ConvException As for exceptions VS compile-time errors - well, there got to be a reason to use Varaint, namely having dynamic script-like typing. And once there the only way to signal problem is to throw an error, so it is a typical situation in dynamic typing world. -- Dmitry Olshansky
Dec 04 2012
parent reply Dmitry Olshansky <dmitry.olsh gmail.com> writes:
12/5/2012 5:40 AM, Jonathan M Davis пишет:
 On Tuesday, December 04, 2012 23:28:25 Dmitry Olshansky wrote:
 12/4/2012 10:40 PM, Jonathan M Davis пишет:
 On Tuesday, December 04, 2012 21:43:09 Dmitry Olshansky wrote:
 Well TDPL claims multiple alias this is allowed so in some distant
 future it maybe possible for Varaint to alias this to all built-in types.

That would be pretty hideous IMHO. There's a reason that D eschews implicit conversions in general. And in this case, you'd very quickly end up with accidental conversions which resulted in exceptions being thrown by Variant.


Unlike C++, no implicit conversion occurs via constructors. In C++, you get up to three implicit conversions when matching function parameters. In D, without alias this, you get 0. C++ has way more places where it allows implicit conversions than D does. D has very few. If you start letting Variants implicitly convert, then you get problems like int i = v; throwing an exception because v holds a string - or a user defined type which can't convert to int.

So what? I hardly see it as a problem. In the spirit of being dynamic Variant ought to use to! function inside. Thus string can be converted to an int. I'm not big fun of such scripty way of doing things but it has uses. The problematic thing are overloads: void func(double d); void func(int); func(Varaint(3.14)); ---> ambiguous
 I think that it's _much_ better to require explicit conversions from
 Variant.


There's nothing natural about Variant. It's attempting to add dynamic typing to a statically typed language.

Bleh that smells religious. There are cases where one may just go for it to simplify matters. Spreadsheets, Db rows and whatnot often operate in Variants. Simply because one can't know ahead of time what the content is in a arbitrary DB.
 And as you can't know what it's type really is
 at compile time, all conversions require type checking at runtime. And
 implicit conversions must be determined at compile time. So really, the
 implicit conversions make no sense at all.

 And I would generally expect that
 code would have to check the type of a Variant before doing a conversion -

to do what? throw an Exception?? :) Another case would be doing a type-switch but there is little amount of code that deals with many types. Most commonly they assume type or kind of type.
 otherwise it's bound to throw an exception a good portion of the time - so
 implicit conversions make that much less sense.

I just think that for majority of cases it's going to be check and throw on bad conversion. -- Dmitry Olshansky
Dec 05 2012
parent Dmitry Olshansky <dmitry.olsh gmail.com> writes:
12/5/2012 11:31 PM, Jonathan M Davis пишет:
 On Wednesday, December 05, 2012 22:07:48 Dmitry Olshansky wrote:
 12/5/2012 5:40 AM, Jonathan M Davis пишет:
 There's nothing natural about Variant. It's attempting to add dynamic
 typing to a statically typed language.

Bleh that smells religious. There are cases where one may just go for it to simplify matters. Spreadsheets, Db rows and whatnot often operate in Variants. Simply because one can't know ahead of time what the content is in a arbitrary DB.

Yes, but that inevitably forces you to check the type in order to handle it correctly, which means that implicit conversion just doesn't work. In order for implicit conversion to work, you have to be able to assume that you're dealing with a particular type, and if you can do that, why are you using a Variant in the first place? Just use a common type.

Simply put it's the API that is more flexible the your concrete code. But there is a point in forcing the expected types as soon as possible. In other words it's a sugar for calling Varaint.get for the type on the right. That's where the point that you don't like it while I think it could be handy.
 And as you can't know what it's type really is
 at compile time, all conversions require type checking at runtime. And
 implicit conversions must be determined at compile time. So really, the
 implicit conversions make no sense at all.

 And I would generally expect that
 code would have to check the type of a Variant before doing a conversion -

to do what? throw an Exception?? :)

To know what on earth you're suposed to do with the variable. If it's a type that you can't handle, then yes, you'd probably have to throw an exception, but you generally use a Variant because you need to be able to return multiple types from the same function, and each is going to be treated differently, otherwise you could have just used a common type to begin with.

This is a sort of case against Varaint at large.
 I just don't see how it makes any sense to implicitly convert a Variant when
 the only reason to use a Variant is if the types involved have no common type.
 Since if they no common type, you're going to have to check what it is to know
 what you can validly do with it.

It's not. If the only reason was that I'd use an opaque "box" type. -- Dmitry Olshansky
Dec 05 2012
prev sibling next sibling parent reply "bearophile" <bearophileHUGS lycos.com> writes:
Era Scarecrow:

  So then in theory

  Variant v;
  int i = v.getValue; //calls getValue!int()

I think this is not possible in D. This seems possible: auto i = v.getValue!int; Bye, bearophile
Dec 04 2012
parent Jacob Carlborg <doob me.com> writes:
On 2012-12-04 13:59, Era Scarecrow wrote:

   It also doesn't seem like it would be difficult to add, only 'auto'
 would cause any real errors (as it's not a known type it can return).

It has been suggested before, overriding on the return type. I has more problems that one might think first. -- /Jacob Carlborg
Dec 04 2012
prev sibling next sibling parent "Era Scarecrow" <rtcvb32 yahoo.com> writes:
On Tuesday, 4 December 2012 at 12:48:57 UTC, bearophile wrote:
 Era Scarecrow:

 So then in theory

 Variant v;
 int i = v.getValue; //calls getValue!int()


Meant it to be long i, but the idea is the same.
 I think this is not possible in D.

 This seems possible:
 auto i = v.getValue!int;

Indeed... it was just a thought, with that you could remove certain requirements for overriding opCast, and might handle implicit casting... actually that makes sense, allowing for a limited number of types you want it to automatically change to rather than using 'alias this' to subtype it. It also doesn't seem like it would be difficult to add, only 'auto' would cause any real errors (as it's not a known type it can return).
Dec 04 2012
prev sibling next sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Tuesday, December 04, 2012 21:43:09 Dmitry Olshansky wrote:
 Well TDPL claims multiple alias this is allowed so in some distant
 future it maybe possible for Varaint to alias this to all built-in types.

That would be pretty hideous IMHO. There's a reason that D eschews implicit conversions in general. And in this case, you'd very quickly end up with accidental conversions which resulted in exceptions being thrown by Variant. I think that it's _much_ better to require explicit conversions from Variant. - Jonathan M Davis
Dec 04 2012
prev sibling next sibling parent "Era Scarecrow" <rtcvb32 yahoo.com> writes:
On Tuesday, 4 December 2012 at 17:43:21 UTC, Dmitry Olshansky 
wrote:
 Well TDPL claims multiple alias this is allowed so in some 
 distant future it maybe possible for Varaint to alias this to 
 all built-in types.

Maybe.... I remember back when i was originally reading about C++ and overloading how the signature would let you overload a function multiple times (C++ Primer 5th I think); I was going to try making a few classes to get a good understanding only to find it. class Something { long value; long operator+(Something& rhs) { return value + rhs.value; } Something operator+(Something& rhs) { value += rhs.value; return this; } } The above would refuse to compile (and likely still does) although it has a minorly different signature; Then I came to realize the return type wasn't part of the signature, and never was part of the identifying/overload-able part of OO. It makes sense to some limited degree but it's annoying... In certain unique cases I wonder if having a template return type would be an answer to certain problems... We know that sometimes the compiler can rewrite 'a.func(b,c)' to 'func(a,b,c)' , it's just syntactical sugar. Why couldn't it also try (when appropriately identifiable in the signature) 't = a.func(b,c)' to 't = a.func!(typeof(t))(b, c)'? Mind you full template functions (where ! is required) this wouldn't apply for or even work for.
Dec 04 2012
prev sibling next sibling parent "Era Scarecrow" <rtcvb32 yahoo.com> writes:
On Tuesday, 4 December 2012 at 17:43:21 UTC, Dmitry Olshansky 
wrote:
 Well TDPL claims multiple alias this is allowed so in some 
 distant future it maybe possible for Varaint to alias this to 
 all built-in types.

Maybe.... I remember back when I was originally reading about C++ and overloading how the signature would let you overload a function multiple times (C++ Primer 5th I think); I was going to try making a few classes to get a good understanding only to find it. class Something { long value; long operator+(Something& rhs) { return value + rhs.value; } Something operator+(Something& rhs) { value += rhs.value; return this; } } The above would refuse to compile (and likely still does) although it has a minorly different signature; Then I came to realize the return type wasn't part of the signature, and never was part of the identifying/overload-able part of OO. It makes sense to some limited degree but it's annoying... In certain unique cases I wonder if having a template return type would be an answer to certain problems... We know that sometimes the compiler can rewrite 'a.func(b,c)' to 'func(a,b,c)' , it's just syntactical sugar. Why couldn't it also try (when appropriately identifiable in the signature) 't = a.func(b,c)' to 't = a.func!(typeof(t))(b, c)'? Mind you full template functions (where ! is required) this wouldn't apply for or even work for.
Dec 04 2012
prev sibling next sibling parent "Era Scarecrow" <rtcvb32 yahoo.com> writes:
On Tuesday, 4 December 2012 at 17:43:21 UTC, Dmitry Olshansky 
wrote:
 Well TDPL claims multiple alias this is allowed so in some 
 distant future it maybe possible for Varaint to alias this to 
 all built-in types.

Maybe.... I remember back when I was originally reading about C++ and overloading how the signature would let you overload a function multiple times (C++ Primer 5th I think); I was going to try making a few classes to get a good understanding only to find it. class Something { long value; long operator+(Something& rhs) { return value + rhs.value; } Something operator+(Something& rhs) { value += rhs.value; return this; } } The above would refuse to compile (and likely still does) although it has a minorly different signature; Then I came to realize the return type wasn't part of the signature, and never was part of the identifying/overload-able part of OO. It makes sense to some limited degree but it's annoying... In certain unique cases I wonder if having a template return type would be an answer to certain problems... We know that sometimes the compiler can rewrite 'a.func(b,c)' to 'func(a,b,c)' , it's just syntactical sugar. Why couldn't it also try (when appropriately identifiable in the signature) 't = a.func(b,c)' to 't = a.func!(typeof(t))(b, c)'? Mind you full template functions (where ! is required) this wouldn't apply for or even work for.
Dec 04 2012
prev sibling next sibling parent "Era Scarecrow" <rtcvb32 yahoo.com> writes:
On Tuesday, 4 December 2012 at 17:43:21 UTC, Dmitry Olshansky 
wrote:
 Well TDPL claims multiple alias this is allowed so in some 
 distant future it maybe possible for Varaint to alias this to 
 all built-in types.

Maybe.... I remember back when I was originally reading about C++ and overloading how the signature would let you overload a function multiple times (C++ Primer 5th I think); I was going to try making a few classes to get a good understanding only to find it. class Something { long value; long operator+(Something& rhs) { return value + rhs.value; } Something operator+(Something& rhs) { value += rhs.value; return this; } } The above would refuse to compile (and likely still does) although it has a minorly different signature; Then I came to realize the return type wasn't part of the signature, and never was part of the identifying/overload-able part of OO. It makes sense to some limited degree but it's annoying... In certain unique cases I wonder if having a template return type would be an answer to certain problems... We know that sometimes the compiler can rewrite 'a.func(b,c)' to 'func(a,b,c)' , it's just syntactical sugar. Why couldn't it also try (when appropriately identifiable in the signature) 't = a.func(b,c)' to 't = a.func!(typeof(t))(b, c)'? Mind you full template functions (where ! is required) this wouldn't apply for or even work for.
Dec 04 2012
prev sibling next sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Tuesday, December 04, 2012 23:28:25 Dmitry Olshansky wrote:
 12/4/2012 10:40 PM, Jonathan M Davis пишет:
 On Tuesday, December 04, 2012 21:43:09 Dmitry Olshansky wrote:
 Well TDPL claims multiple alias this is allowed so in some distant
 future it maybe possible for Varaint to alias this to all built-in types.

That would be pretty hideous IMHO. There's a reason that D eschews implicit conversions in general. And in this case, you'd very quickly end up with accidental conversions which resulted in exceptions being thrown by Variant.


Unlike C++, no implicit conversion occurs via constructors. In C++, you get up to three implicit conversions when matching function parameters. In D, without alias this, you get 0. C++ has way more places where it allows implicit conversions than D does. D has very few. If you start letting Variants implicitly convert, then you get problems like int i = v; throwing an exception because v holds a string - or a user defined type which can't convert to int.
 I think that it's _much_ better to require explicit conversions from
 Variant.


There's nothing natural about Variant. It's attempting to add dynamic typing to a statically typed language. And as you can't know what it's type really is at compile time, all conversions require type checking at runtime. And implicit conversions must be determined at compile time. So really, the implicit conversions make no sense at all. And I would generally expect that code would have to check the type of a Variant before doing a conversion - otherwise it's bound to throw an exception a good portion of the time - so implicit conversions make that much less sense. - Jonathan M Davis
Dec 04 2012
prev sibling next sibling parent "Era Scarecrow" <rtcvb32 yahoo.com> writes:
On Tuesday, 4 December 2012 at 17:43:21 UTC, Dmitry Olshansky 
wrote:
 Well TDPL claims multiple alias this is allowed so in some 
 distant future it maybe possible for Varaint to alias this to 
 all built-in types.

Maybe.... I remember back when I was originally reading about C++ and overloading how the signature would let you overload a function multiple times (C++ Primer 5th I think); I was going to try making a few classes to get a good understanding only to find it. Went something like: class Something { long value; long operator+(Something& rhs) { return value + rhs.value; } Something operator+(Something& rhs) { value += rhs.value; return this; } } The above would refuse to compile (and likely still does) although it has a different signature (or so I thought); Then I came to realize the return type wasn't part of the signature, and never was part of the identifying/overload-able part of OO. It makes sense to some limited degree but it's annoying... In certain unique cases I wonder if having a template return type would be an answer to certain problems... We know that sometimes the compiler can rewrite 'a.func(b,c)' to 'func(a,b,c)' , it's just syntactical sugar. Why couldn't it also try (when appropriately identifiable in the signature) 't = a.func(b,c)' to 't = a.func!(typeof(t))(b, c)'? Mind you full template functions (where ! is required) this wouldn't apply for or even work for.
Dec 04 2012
prev sibling next sibling parent "Era Scarecrow" <rtcvb32 yahoo.com> writes:
On Tuesday, 4 December 2012 at 17:43:21 UTC, Dmitry Olshansky 
wrote:
 Well TDPL claims multiple alias this is allowed so in some 
 distant future it maybe possible for Varaint to alias this to 
 all built-in types.

Maybe.... I remember back when I was originally reading about C++ and overloading how the signature would let you overload a function multiple times (C++ Primer 5th I think); I was going to try making a few classes to get a good understanding only to find it. Went something like: class Something { long value; long operator+(Something& rhs) { return value + rhs.value; } Something operator+(Something& rhs) { value += rhs.value; return this; } } The above would refuse to compile (and likely still does) although it has a different signature (or so I thought); Then I came to realize the return type wasn't part of the signature, and never was part of the identifying/overload-able part of OO. It makes sense to some limited degree but it's annoying... In certain unique cases I wonder if having a template return type would be an answer to certain problems... We know that sometimes the compiler can rewrite 'a.func(b,c)' to 'func(a,b,c)' , it's just syntactical sugar. Why couldn't it also try (when appropriately identifiable in the signature) 't = a.func(b,c)' to 't = a.func!(typeof(t))(b, c)'? Mind you full template functions (where ! is required) this wouldn't apply for or even work for.
Dec 05 2012
prev sibling next sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Wednesday, December 05, 2012 22:07:48 Dmitry Olshansky wrote:
 12/5/2012 5:40 AM, Jonathan M Davis пишет:
 There's nothing natural about Variant. It's attempting to add dynamic
 typing to a statically typed language.

Bleh that smells religious. There are cases where one may just go for it to simplify matters. Spreadsheets, Db rows and whatnot often operate in Variants. Simply because one can't know ahead of time what the content is in a arbitrary DB.

Yes, but that inevitably forces you to check the type in order to handle it correctly, which means that implicit conversion just doesn't work. In order for implicit conversion to work, you have to be able to assume that you're dealing with a particular type, and if you can do that, why are you using a Variant in the first place? Just use a common type.
 And as you can't know what it's type really is
 at compile time, all conversions require type checking at runtime. And
 implicit conversions must be determined at compile time. So really, the
 implicit conversions make no sense at all.
 
 And I would generally expect that
 code would have to check the type of a Variant before doing a conversion -

to do what? throw an Exception?? :)

To know what on earth you're suposed to do with the variable. If it's a type that you can't handle, then yes, you'd probably have to throw an exception, but you generally use a Variant because you need to be able to return multiple types from the same function, and each is going to be treated differently, otherwise you could have just used a common type to begin with. I just don't see how it makes any sense to implicitly convert a Variant when the only reason to use a Variant is if the types involved have no common type. Since if they no common type, you're going to have to check what it is to know what you can validly do with it. - Jonathan M Davis
Dec 05 2012
prev sibling next sibling parent "Era Scarecrow" <rtcvb32 yahoo.com> writes:
On Tuesday, 4 December 2012 at 17:43:21 UTC, Dmitry Olshansky 
wrote:
 Well TDPL claims multiple alias this is allowed so in some 
 distant future it maybe possible for Varaint to alias this to 
 all built-in types.

Maybe.... I remember back when I was originally reading about C++ and overloading how the signature would let you overload a function multiple times (C++ Primer 5th I think); I was going to try making a few classes to get a good understanding only to find it. Went something like: class Something { long value; long operator+(Something& rhs) { return value + rhs.value; } Something operator+(Something& rhs) { value += rhs.value; return this; } } The above would refuse to compile (and likely still does) although it has a different signature (or so I thought); Then I came to realize the return type wasn't part of the signature, and never was part of the identifying/overload-able part of OO. It makes sense to some limited degree but it's annoying... In certain unique cases I wonder if having a template return type would be an answer to certain problems... We know that sometimes the compiler can rewrite 'a.func(b,c)' to 'func(a,b,c)' , it's just syntactical sugar. Why couldn't it also try (when appropriately identifiable in the signature) 't = a.func(b,c)' to 't = a.func!(typeof(t))(b, c)'? Mind you full template functions (where ! is required) this wouldn't apply for or even work for.
Dec 05 2012
prev sibling next sibling parent "Era Scarecrow" <rtcvb32 yahoo.com> writes:
On Wednesday, 5 December 2012 at 21:39:31 UTC, Era Scarecrow 
wrote:

  My god did it finally post? Sorry if it repeated a few times... 
Left it on easily overnight and it still didn't say it posted any 
of it. :(
Dec 05 2012
prev sibling next sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Thursday, December 06, 2012 01:06:33 Dmitry Olshansky wrote:
 To know what on earth you're suposed to do with the variable. If it's a
 type that you can't handle, then yes, you'd probably have to throw an
 exception, but you generally use a Variant because you need to be able to
 return multiple types from the same function, and each is going to be
 treated differently, otherwise you could have just used a common type to
 begin with.

This is a sort of case against Varaint at large.

Honestly, the only use cases for Variant that I would consider valid would be those where you _can't_ use static typing in any sane way - the places where you're effectively forced to use a union (where a Variant is a better union). If you can reasonably solve the problem by using a common type, then I'm completely against using Variant for it. Pretty much the only kind of situation that I remember running into where I would consider Variant to be a good solution is one where you literally have to return a type from a function where you can't know that type at compile time, and there is no common type to use. And the only time that I recall running into that recently was in writing a lexer (the values of literals ended up having to be put in a variant type). There are obviously other use cases besides that (database-related stuff and spreadsheets like you mentioned are other possibilities), but they are extremely rare in my experience. In almost all cases, you can and should know the type at compile time, in which case, using Variant makes no sense. - Jonathan M Davis
Dec 05 2012
prev sibling next sibling parent "Era Scarecrow" <rtcvb32 yahoo.com> writes:
On Wednesday, 5 December 2012 at 19:32:03 UTC, Jonathan M Davis 
wrote:
 Yes, but that inevitably forces you to check the type in order 
 to handle it correctly, which means that implicit conversion 
 just doesn't work. In order for implicit conversion to work, 
 you have to be able to assume that you're dealing with a 
 particular type, and if you can do that, why are you using a 
 Variant in the first place? Just use a common type.

I know for my own project a common type isn't possible (It's a block of raw memory most of the time), but i do know at certain points if it's one type or another just because of where it's at. In order to handle all the types it ends up either being a pointer (union for all) or use long and double and string, but you I have to call them manually (geti, gets, getf). Also implicit conversion only makes sense if it's a type that can be converted to. Any user type can't be converted without alias this or classes/interfaces.
Dec 05 2012
prev sibling parent "Jesse Phillips" <Jessekphillips+D gmail.com> writes:
On Thursday, 6 December 2012 at 00:31:53 UTC, Jonathan M Davis 
wrote:

 Pretty much the only kind of situation that I remember running 
 into where I
 would consider Variant to be a good solution is one where you 
 literally have
 to return a type from a function where you can't know that type 
 at compile
 time, and there is no common type to use. And the only time 
 that I recall
 running into that recently was in writing a lexer (the values 
 of literals
 ended up having to be put in a variant type). There are 
 obviously other use
 cases besides that (database-related stuff and spreadsheets 
 like you mentioned
 are other possibilities), but they are extremely rare in my 
 experience. In
 almost all cases, you can and should know the type at compile 
 time, in which
 case, using Variant makes no sense.

 - Jonathan M Davis

My experience with Variant has come from integration in LuaD (Probably like what I'd want from JSON). My main use has been an Algebraic type of string, string[], and string[][string]. (Lua does not have arrays or dictionaries, it has a table). In general when I request data I know which of these it is, however I do have some generic code to operate on any of these types, thus: if(myVar.peek!(string[][string])) ... myVar.get!(string[][string]) Does get repetitive and messy to read. On another note, it is sad I can't have that defined as MyType[MyType].
Dec 10 2012