December 04, 2012
 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()
December 04, 2012
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
December 04, 2012
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
December 04, 2012
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).
December 04, 2012
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
December 04, 2012
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
December 04, 2012
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
December 04, 2012
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
December 04, 2012
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.
December 04, 2012
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.
« First   ‹ Prev
1 2 3
Top | Discussion index | About this forum | D home