Re: auto limitation?

2012-09-12 Thread Namespace

Done, thank you. :)


Re: auto limitation?

2012-09-11 Thread Ali Çehreli

On 09/11/2012 11:10 AM, Namespace wrote:
 I have this code, but it works not as expected:
 http://dpaste.dzfl.pl/6ce5b4dd

 I get 0 instead of 42 if my type is Int.
 My value is correct (as you can see) but writeln prints still 0
 instead of 42.
 I think auto compiles first to float and cannot handle then integers.
 Am I right? And could you explain me how this could work?

Here is a reduced code:

import std.stdio;

enum Type { Int, Float }

auto foo(Type t)
{
final switch (t) {
case Type.Int:
return 42;
case Type.Float:
return 1.5;
}
}

void main()
{
writeln(foo(Type.Int));
writeln(foo(Type.Float));
}

The return type of foo() is double. (It's float in your code but it 
doesn't matter.)


I think this is a bug. I guess that 'return 42' is still placing an int 
onto the program stack instead of a float. A workarounds are returning 
to!float(this._num.ivalue).


But I think this is a compiler bug.

Ali


Re: auto limitation?

2012-09-11 Thread Ali Çehreli

On 09/11/2012 11:40 AM, Namespace wrote:
 Here is a reduced code:

 import std.stdio;

 enum Type { Int, Float }

 auto foo(Type t)
 {
 final switch (t) {
 case Type.Int:
 return 42;
 case Type.Float:
 return 1.5;
 }
 }

 void main()
 {
 writeln(foo(Type.Int));
 writeln(foo(Type.Float));
 }

 The return type of foo() is double. (It's float in your code but it
 doesn't matter.)

 I think this is a bug. I guess that 'return 42' is still placing an
 int onto the program stack instead of a float. A workarounds are
 returning to!float(this._num.ivalue).

 But I think this is a compiler bug.

 Ali

 I should begin to count the bugs I find with stuff like this. :)

Please create a bug about this one:

  http://d.puremagic.com/issues/

But wait until someone else confirms that it really is a bug. :)

 So no correct workaround, hm?

You have to cast the types to the largest one. The following does not 
work because foo() is not defined yet:


import std.traits;
// ...
auto foo(Type t)
{
final switch (t) {
case Type.Int:
return to!(ReturnType!(typeof(foo)))(42);
case Type.Float:
return 1.5;
}
}

  Error: forward reference to foo

Explicitly casting is a way:

return to!double(42);

Or you can write or find a template that produces the largest type among 
the members of a union.


Ali



Re: auto limitation?

2012-09-11 Thread Namespace

That's not what i want. I would avoid casting if it's possible.
I hope it is a bug and will fixed in 2.061.


Re: auto limitation?

2012-09-11 Thread Maxim Fomin

On Tuesday, 11 September 2012 at 18:32:47 UTC, Ali Çehreli wrote:


Here is a reduced code:



I guess it may be reduced to:

auto foo(bool val)
{
   if (val)
  return 42;
   else
  return 1.5;
}

void main()
{
   assert(foo(true) == 42); // assertion failure
   assert(foo(false) == 1.5);
}




The return type of foo() is double. (It's float in your code 
but it doesn't matter.)


I think this is a bug. I guess that 'return 42' is still 
placing an int onto the program stack instead of a float. A 
workarounds are returning to!float(this._num.ivalue).


But I think this is a compiler bug.

Ali


I think it is UB rather than a bug. The spec says that return 
types must match exactly. AFAIK auto is a feature to infer return 
type, not to magically adjust to multiple incompatible types.




Re: auto limitation?

2012-09-11 Thread Simen Kjaeraas

On Tue, 11 Sep 2012 20:48:25 +0200, Ali Çehreli acehr...@yahoo.com wrote:

Or you can write or find a template that produces the largest type among  
the members of a union.


std.traits.CommonType.

--
Simen


Re: auto limitation?

2012-09-11 Thread Namespace
I think it is UB rather than a bug. The spec says that return 
types must match exactly. AFAIK auto is a feature to infer 
return type, not to magically adjust to multiple incompatible 
types.


But i thought Variant is one. ;)


Re: auto limitation?

2012-09-11 Thread Maxim Fomin

On Tuesday, 11 September 2012 at 19:03:56 UTC, Namespace wrote:
I think it is UB rather than a bug. The spec says that return 
types must match exactly. AFAIK auto is a feature to infer 
return type, not to magically adjust to multiple incompatible 
types.


But i thought Variant is one. ;)


I guess (never used Variant) that it uses templated getter which 
correctly returns value. Float values are returned in %xmm 
registers and integer values are returned in %eax. Without 
knowing return type a caller doesn't know where to take return 
value. For example in this case foo function correctly places 
return values, but main takes in both cases return value from 
%xmm.





Re: auto limitation?

2012-09-11 Thread Namespace

With multiple alias this this should work.

int getInt() const { return this.ivalue; }
alias getInt this;
float getFloat() const { return this.fvalue; }
alias getFloat this;

Or with a class method for implicit conversion.


Re: auto limitation?

2012-09-11 Thread Maxim Fomin
On Tuesday, 11 September 2012 at 19:07:52 UTC, Simen Kjaeraas 
wrote:
On Tue, 11 Sep 2012 20:57:07 +0200, Maxim Fomin 
ma...@maxim-fomin.ru wrote:


I think it is UB rather than a bug. The spec says that return 
types must match exactly. AFAIK auto is a feature to infer 
return type, not to magically adjust to multiple incompatible 
types.


I'd be surprised if this were not a bug. My expectation would 
be that the
types be combined as with the ?: operator, just like 
std.traits.CommonType.


If this is not a bug, it's certainly worth filing as an 
enhancement request.


It can do, but in compile time. At runtime it cannot know what 
type is returned (I suppose, but I am not expert in such things). 
Variant works because it does it in compile time, but buggy 
examples published so far do it at runtime.


Re: auto limitation?

2012-09-11 Thread Timon Gehr

On 09/11/2012 08:57 PM, Maxim Fomin wrote:


I think it is UB rather than a bug.


No, this is a bug.


The spec says that return types must match exactly.


Exactly. If it was UB, the spec would say the behaviour is undefined if 
they don't match exactly.




AFAIK auto is a feature to infer return type, not to
magically adjust to multiple incompatible types.



Re: auto limitation?

2012-09-11 Thread Timon Gehr

On 09/11/2012 09:29 PM, Namespace wrote:

On Tuesday, 11 September 2012 at 19:27:40 UTC, Timon Gehr wrote:

On 09/11/2012 08:57 PM, Maxim Fomin wrote:


I think it is UB rather than a bug.


No, this is a bug.


The spec says that return types must match exactly.


Exactly. If it was UB, the spec would say the behaviour is undefined
if they don't match exactly.



AFAIK auto is a feature to infer return type, not to
magically adjust to multiple incompatible types.


So what? Should my code work or not?


According to the spec it should fail compilation.


Re: auto limitation?

2012-09-11 Thread Namespace

Ah ok. That's sad.


Re: auto limitation?

2012-09-11 Thread Maxim Fomin

On Tuesday, 11 September 2012 at 19:35:58 UTC, Timon Gehr wrote:

According to the spec it should fail compilation.


After rethinking it I agree that bug is in faulty compilation 
(assuming spec is correct), not in returning zero at runtime, 
which was thought previously.





Re: auto limitation?

2012-09-11 Thread Namespace

My final implementation:
http://dpaste.dzfl.pl/4d2a045a

Any suggestions?


Re: auto limitation?

2012-09-11 Thread bearophile

Namespace:


I have this code, but it works not as expected:
http://dpaste.dzfl.pl/6ce5b4dd


I suggest to file a bug:


auto foo(bool b) {
final switch (b) {
case true:
return 10;
case false:
return 20.0;
}
}
void main() {
import std.stdio: writeln;
writeln(foo(true));
writeln(foo(false));
}


The acceptable results are a compile-time error for type 
mismatch, or a conversion of both literals to double. Probably 
the second is better. But a silent bit-level cast is not 
acceptable.


Bye,
bearophile


Re: auto limitation?

2012-09-11 Thread Namespace

On Tuesday, 11 September 2012 at 21:13:02 UTC, bearophile wrote:

Namespace:


I have this code, but it works not as expected:
http://dpaste.dzfl.pl/6ce5b4dd


I suggest to file a bug:


auto foo(bool b) {
final switch (b) {
case true:
return 10;
case false:
return 20.0;
}
}
void main() {
import std.stdio: writeln;
writeln(foo(true));
writeln(foo(false));
}


The acceptable results are a compile-time error for type 
mismatch, or a conversion of both literals to double. Probably 
the second is better. But a silent bit-level cast is not 
acceptable.


Bye,
bearophile


Sure that is the first i will do tomorrow.
But so far no suggestions?



Re: auto limitation?

2012-09-11 Thread Denis Shelomovskij

11.09.2012 22:48, Ali Çehreli пишет:

 return to!(ReturnType!(typeof(foo)))(42);


typeof(return)
See http://dlang.org/declaration.html#typeof

Anyway don't use it as a type of the first return. You will get:
---
Error: cannot use typeof(return) inside function foo with inferred 
return type

---


--
Денис В. Шеломовский
Denis V. Shelomovskij


Re: auto limitation?

2012-09-11 Thread Jonathan M Davis
On Tuesday, September 11, 2012 23:31:43 Namespace wrote:
 Sure that is the first i will do tomorrow.
 But so far no suggestions?

Use a cast. auto _cannot_ be different types depending on what you return. It 
must always resolve to the same type. So, in this case, either it needs to 
resolve to double (in which case the compiler should case) or fail to compile.

If you really want the type of the return type to be different depending on 
what you return, you need to use Variant (in which case it _still_ won't 
really be different, it'll just always be Variant, but Variant will hold a 
different value in its internal union, and you'll be able to get that value out 
as its original type later, because the Variant knows what it was). But D is 
statically typed, so all types must be known at compile time, and you can't 
have types changing based on the path of execution.

- Jonathan M Davis


Re: auto limitation?

2012-09-11 Thread bearophile

Namespace:


But so far no suggestions?


This seems to work, but solutions that use cast() are sometimes 
fragile (and dangerous):



auto foo(bool b) {
final switch (b) {
case false:
return 20.0;
case true:
return cast(typeof(return))10;
}
}
void main() {
import std.stdio: writeln;
writeln(foo(false));
writeln(foo(true));
}


Bye,
bearophile


Re: auto limitation?

2012-09-11 Thread Jonathan M Davis
On Tuesday, September 11, 2012 23:55:40 bearophile wrote:
 Namespace:
  But so far no suggestions?
 
 This seems to work, but solutions that use cast() are sometimes
 fragile (and dangerous):
 
 
 auto foo(bool b) {
  final switch (b) {
  case false:
  return 20.0;
  case true:
  return cast(typeof(return))10;
  }
 }
 void main() {
  import std.stdio: writeln;
  writeln(foo(false));
  writeln(foo(true));
 }

If you're going to use a cast, then use one where you give the type 
explicitly. Using typeof(return) is just asking for it when the compiler is 
clearly already having issues with the return type.

- Jonathan M Davis


Re: auto limitation?

2012-09-11 Thread Jonathan M Davis
On Tuesday, September 11, 2012 15:14:43 Jonathan M Davis wrote:
 If you're going to use a cast, then use one where you give the type
 explicitly. Using typeof(return) is just asking for it when the compiler is
 clearly already having issues with the return type.

And actually, in all honesty, I see no reason to use auto here. If you know 
what the return type is supposed to be (e.g. double), then just use double. 
Casting where it's unnecessary is just begging for bugs.

Based on Namespace's posts in this thread, I get the impression that what he 
wanted was that the return type would be either int or double depending on the 
value returned - i.e. he was trying to get dynamic typing - which doesn't 
work, because D is a static language. If that's what he wants, he needs to use 
Variant, and casting and the like is going to do him no good. auto was the 
wrong choice in the first place.

- Jonathan M Davis


Re: auto limitation?

2012-09-11 Thread Namespace

You mean so?
ref Variant get() {
return this._num; // with Variant _num;
}

alias get this;

and then:
int i = zahl.get!int?
No. Then I use my solution as you can see on DPaste. If Variant 
works only this way I can also set float to the return type an 
cast if I need to int.
And with my solution I have in calculation a numeric value and 
doesn't have to cast with Variant's get method.




Re: auto limitation?

2012-09-11 Thread Jonathan M Davis
On Wednesday, September 12, 2012 00:29:32 Namespace wrote:
 You mean so?
 ref Variant get() {
  return this._num; // with Variant _num;
 }
 
 alias get this;
 
 and then:
 int i = zahl.get!int?
 No. Then I use my solution as you can see on DPaste. If Variant
 works only this way I can also set float to the return type an
 cast if I need to int.
 And with my solution I have in calculation a numeric value and
 doesn't have to cast with Variant's get method.

If want the result to always be the same type, then either use the explicit 
type or auto (though clearly auto is having some issues right now, so it might 
be best to avoid it if you're returning stuff that differs in type and needs to 
be converted). If you want the result to differ in type depending on the value 
returned, then you need Variant in order to simulate dynamic typing.

I'm not quite sure what you're trying to do with your code, but if you use 
Variant, you'll need to use get or coerce to get its value from it, which it 
doesn't sound like what you want to do. If that's the case, then your get 
function needs to always return the same type - be it int or float or double or 
whatever, and you might as well just use the explicit type rather than auto, 
since it's a primitive type, not a complicated, templated one (which is the 
main reason to use auto for the return type of a function).

- Jonathan M Davis


Re: auto limitation?

2012-09-11 Thread Graham Fawcett

On Tuesday, 11 September 2012 at 21:31:17 UTC, Namespace wrote:

On Tuesday, 11 September 2012 at 21:13:02 UTC, bearophile wrote:

Namespace:


I have this code, but it works not as expected:
http://dpaste.dzfl.pl/6ce5b4dd


I suggest to file a bug:


auto foo(bool b) {
   final switch (b) {
   case true:
   return 10;
   case false:
   return 20.0;
   }
}
void main() {
   import std.stdio: writeln;
   writeln(foo(true));
   writeln(foo(false));
}


The acceptable results are a compile-time error for type 
mismatch, or a conversion of both literals to double. Probably 
the second is better. But a silent bit-level cast is not 
acceptable.


Bye,
bearophile


Sure that is the first i will do tomorrow.
But so far no suggestions?


Just this one. You can use an anonymous union in your Num struct, 
so you can write obj.ivalue rather than obj._num.ivalue:


struct Num {
private:

  final enum Type {
None,
Float,
Int
  }

  union {
float fvalue;
int ivalue;
  }

  Type _type;

  

Graham