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



Re: Optional extra return value? Multiple return values with auto?

2012-08-15 Thread ReneSac

On Wednesday, 15 August 2012 at 01:22:41 UTC, Era Scarecrow wrote:

On Wednesday, 15 August 2012 at 00:37:32 UTC, ReneSac wrote:
And my last question of my first post: I can't use auto for 
the out values right? An enhancement proposal like this 
would be compatible with D?


 I would say No. Maybe if it was a union, but I don't think 
so;.It still needs to know it's type when it's working with, 
aka statically typed (known at compile-time).


 The auto as an out variable may work in an interpreted or more 
dynamic language.


It was the reverse way (as in my first post):

bool bar(out ulong output){ output = 0 ; return true;}

auto check = bar(auto num); // error

The type of the out parameter is explicit in this case, but, 
right now, I need to declarate num outside the function, and thus 
I can't use the auto keyword.


I'm not sure how this would work for templatized out parameters 
(if they are permitted)...


Re: Optional extra return value? Multiple return values with auto?

2012-08-14 Thread ReneSac
Thanks, this indeed works. One obvious (when your program 
starts to behave weirdly...) down side of this solution: it needs 
a different dummy for each optional out value of a function, or 
else multiple variables will be modifying the same dummy.


And, of course, a different dummy for each type of out value, 
because values after cast() apparently aren't lvalues.


And my last question of my first post: I can't use auto for the 
out values right? An enhancement proposal like this would be 
compatible with D?


Also, the function duplication workaround doesn't works if I 
templatize the function... Is this inconsistency intentional?



On Saturday, 11 August 2012 at 23:23:48 UTC, Ali Çehreli wrote:


I am not a fan of this solution either. To make the code to 
compile, define dummy as static:


static T dummy = T.init;  // -- this works

That way there will be just one copy for the entire type, 
instead of one copy per object.


Ali


Re: Optional extra return value? Multiple return values with auto?

2012-08-14 Thread Era Scarecrow

On Wednesday, 15 August 2012 at 00:37:32 UTC, ReneSac wrote:
And my last question of my first post: I can't use auto for 
the out values right? An enhancement proposal like this would 
be compatible with D?


 I would say No. Maybe if it was a union, but I don't think 
so;.It still needs to know it's type when it's working with, aka 
statically typed (known at compile-time).


 The auto as an out variable may work in an interpreted or more 
dynamic language.


Re: Optional extra return value? Multiple return values with auto?

2012-08-14 Thread Ali Çehreli

On 08/14/2012 06:22 PM, Era Scarecrow wrote:
 On Wednesday, 15 August 2012 at 00:37:32 UTC, ReneSac wrote:
 And my last question of my first post: I can't use auto for the
 out values right? An enhancement proposal like this would be
 compatible with D?

 I would say No. Maybe if it was a union, but I don't think so;.It
 still needs to know it's type when it's working with, aka statically
 typed (known at compile-time).

 The auto as an out variable may work in an interpreted or more dynamic
 language.

Agreed. The function code must be compiled to use certain amount of data 
from the program stack for that particular parameter. That size of that 
parameter must be known at compile time.


The compiler could in theory examine the entire program to determine a 
type for the parameter but the separate compilation model would preclude it.


Ali



Re: Optional extra return value? Multiple return values with auto?

2012-08-14 Thread Era Scarecrow

On Wednesday, 15 August 2012 at 01:42:11 UTC, Ali Çehreli wrote:
Agreed. The function code must be compiled to use certain 
amount of data from the program stack for that particular 
parameter. That size of that parameter must be known at compile 
time.


The compiler could in theory examine the entire program to 
determine a type for the parameter but the separate compilation 
model would preclude it.


 Although if you used a template you could pull it off... I 
think... But you'd need the sources for that.


 void multiOut(T)(out T outType) {
   outType = 100;
 }

 int a;
 char b;

 multiOut(a);
 multiOut(b);

 assert(a == 100);
 assert(b == 100);


Re: Optional extra return value? Multiple return values with auto?

2012-08-11 Thread ReneSac

On Tuesday, 24 July 2012 at 05:30:49 UTC, Ali Çehreli wrote:

The options that I can think of:

- Return a struct (or a class) where one of the members is not 
filled-in


- Similarly, return a tuple


This is awkward, and doesn't look good for performance.



- Use an out parameter, which can have a default lvalue:

int g_default_param;

void foo(ref int i = g_default_param)
{
if (i == g_param) {
// The caller is not interested in 'i'

} else {
// The caller wants 'i'
i = 42;
}
}

void main()
{
foo();

int i;
foo(i);
assert(i == 42);
}


This is not working inside a class. I'm not sure what default 
value I should put when I don't know the type entered:


class a (T) {
T dummy = T.init;
bool foo(int a, out T optional = dummy)
{
return true;
}
}

void main () {
auto c = new a!uint();
c.foo(5);
}

I get the following error:

Error: need 'this' to access member dummy



Re: Optional extra return value? Multiple return values with auto?

2012-08-11 Thread Ali Çehreli

On 08/11/2012 03:48 PM, ReneSac wrote:
 On Tuesday, 24 July 2012 at 05:30:49 UTC, Ali Çehreli wrote:

 - Use an out parameter, which can have a default lvalue:

 int g_default_param;

 void foo(ref int i = g_default_param)
 {
 if (i == g_param) {
 // The caller is not interested in 'i'

 } else {
 // The caller wants 'i'
 i = 42;
 }
 }

 void main()
 {
 foo();

 int i;
 foo(i);
 assert(i == 42);
 }

 This is not working inside a class. I'm not sure what default value I
 should put when I don't know the type entered:

 class a (T) {
 T dummy = T.init;
 bool foo(int a, out T optional = dummy)
 {
 return true;
 }
 }

 void main () {
 auto c = new a!uint();
 c.foo(5);
 }

 I get the following error:

 Error: need 'this' to access member dummy


I am not a fan of this solution either. To make the code to compile, 
define dummy as static:


static T dummy = T.init;  // -- this works

That way there will be just one copy for the entire type, instead of one 
copy per object.


I also tried to define it as immutable but the following line fails to 
compile:


static immutable T dummy = T.init;  // -- compilation error

I thought that a solution would be to define 'static this()':

class a (T){
static immutable T dummy;

static this()
{
dummy = T.init;
}

bool foo(int a, out T optional = dummy)
{ // -- compilation error on this line
return true;
}
}

Still fails to compile:

  Error: cast(uint)dummy is not an lvalue

The error is on the line that I have pointed in the code. I think this 
is a compiler bug. T is not a reference type and 'cast(uint)dummy' not 
being an lvalue should not matter.


I tried an enum too but a different error on the same line:

static enum T dummy = T.init;

  Error: constant 0u is not an lvalue

Ali



Re: Optional extra return value? Multiple return values with auto?

2012-08-11 Thread Timon Gehr

There is no compiler bug. You cannot pass immutable/rvalue by reference
to mutable.


Re: Optional extra return value? Multiple return values with auto?

2012-07-24 Thread Chris NS

On Tuesday, 24 July 2012 at 03:25:55 UTC, ReneSac wrote:


Do I really have to duplicate the function, in order to achieve 
this?




In a nutshell, yes.  Or else resort to bizarre sorcery such as 
may rot the very heart from one's chest (or template ninjitsu, 
whatever).  But is it really so bad?


bool foo ( byte[] data, out int stats ) {
// do a bunch of stuff
}

bool foo ( byte[] data ) {
int dummy;
return foo( data, dummy );
}

One could possibly put together a template that automates this... 
heck, here's a quick and dirty implementation of such:


##
import  std.stdio   ,
std.traits  ;

template DummyLast ( alias Func ) {
ReturnType!Func DummyLast ( ParameterTypeTuple!Func[ 0 .. $ - 
1 ] args ) {

ParameterTypeTuple!Func[ $ - 1 ] dummy;
return Func( args, dummy );
}
}

bool foo ( byte[] data, out int stats ) {
stats = 42;
return true;
}

alias DummyLast!foo foo;

void main () {
byte[] data;
bool result;
int stats;
result = foo( data, stats );
writeln( result, ' ', stats );

result = false;
stats  = 0;
result = foo( data );
writeln( result, ' ', stats );
}
##

-- Chris NS



Re: Optional extra return value? Multiple return values with auto?

2012-07-24 Thread David

Am 24.07.2012 05:25, schrieb ReneSac:

I whish there was:

auto foo() {
return Tuple!(foo, bar, 1, new Custum());
}

void main() {
auto (s1, s2, i, c) = foo();
}


Re: Optional extra return value? Multiple return values with auto?

2012-07-24 Thread bearophile

On Tuesday, 24 July 2012 at 03:25:55 UTC, ReneSac wrote:
How I can return multiple values in D, but one of them being 
optional?


One of the ways to to it is to return a tuple with your 
arguments, where the last item of the tuple is a Nullable of the 
optional element:



import std.stdio, std.typecons;

Tuple!(int, double, Nullable!int) foo(bool b) {
if (b)
return tuple(5, 1.5, Nullable!int(1));
else
return tuple(10, 2.5, Nullable!int());
}

void main() {
writeln(foo(false)[2]); // enforcement failed
}


Bye,
bearophile


Re: Optional extra return value? Multiple return values with auto?

2012-07-24 Thread Chris NS

On Tuesday, 24 July 2012 at 08:56:21 UTC, David wrote:

Am 24.07.2012 05:25, schrieb ReneSac:

I whish there was:

auto foo() {
return Tuple!(foo, bar, 1, new Custum());
}

void main() {
auto (s1, s2, i, c) = foo();
}


I think the main blocker to something like that right now is the 
compiler's ability to detect and guarantee that the returned 
tuple will always be a specific series of types (or at least 
implicitly convertible to a common series).  And in order for 
that, tuples would, I imagine, need to be a part of the language 
proper.  If I'm wrong about that last requirement, then I'm 
honestly not sure what the main obstacle to this is.


-- Chris NS


Re: Optional extra return value? Multiple return values with auto?

2012-07-24 Thread bearophile

It seems forum.dlang.org hides my first answer, I don't know why:

http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D.learnarticle_id=37708

Bye,
bearophile


Optional extra return value? Multiple return values with auto?

2012-07-23 Thread ReneSac
How I can return multiple values in D, but one of them being 
optional? I tried the 'out' hack to achieve multiple return 
values, but it didn't accepted a default argument: it needed a 
lvalue in the calling function.


In Lua, for example, one can do:

function foo(input)

-- calculations --

return result, iterations_needed
end

a, stats = foo()

or, if you are only interested in the result:

a = foo() -- the second return is automatically discarded.

Do I really have to duplicate the function, in order to achieve 
this?


Also, is there some way to use auto with multiple returns? Like:

bool bar(out ulong output){ output = 0 ; return true;}

auto check = bar(auto num); // error

Right now, I need to declarate num outside the function, and thus 
I can't use the auto keyword.


Re: Optional extra return value? Multiple return values with auto?

2012-07-23 Thread Ali Çehreli

On 07/23/2012 08:25 PM, ReneSac wrote:

How I can return multiple values in D, but one of them being optional? I
tried the 'out' hack to achieve multiple return values, but it didn't
accepted a default argument: it needed a lvalue in the calling function.


Like in C and C++, functions in D can also have a single return value. 
The most common workaround in C and C++ has been an out parameter 
(pointer in C and pointer or reference in C++).


The options that I can think of:

- Return a struct (or a class) where one of the members is not filled-in

- Similarly, return a tuple

- Use an out parameter, which can have a default lvalue:

int g_default_param;

void foo(ref int i = g_default_param)
{
if (i == g_param) {
// The caller is not interested in 'i'

} else {
// The caller wants 'i'
i = 42;
}
}

void main()
{
foo();

int i;
foo(i);
assert(i == 42);
}

- Use some template trick where the caller specifies what he wants:

  result = foo();
  complex_result = foo!with_iterations_needed();

Thinking back, perhaps because C and C++ don't provide multiple return 
values, I never missed them. Although they were nice when coding in 
Python. :)


Ali


Re: Bug in Auto Functions and Template? Or Am I Just Crazy...

2012-06-28 Thread Michael

Good I know I spotted something _real_ this time!

On Wednesday, 27 June 2012 at 11:55:11 UTC, Timon Gehr wrote:

On 06/27/2012 01:24 PM, Timon Gehr wrote:

On 06/27/2012 11:07 AM, Michael wrote:

Hello all,
  I came across some weird behaviors yesterday and I can't 
figure out

what it's about.

(1)
auto factorial(int n) {
if (n  2) return 1;
return n * factorial(n-1);
}

The compiler complained about forward declaration of 
factorial. If I
change the return type to int, the problem goes away. I can 
understand
that with the recursion, it might be impossible for the 
compiler to
deduce the type of factorial and so it compile errors, but I 
don't see
anything about that on the Language Reference. Is this the 
intended

behavior?



Apparently the compiler attempts to type combine the types of 
the
return statements. This does not match the language 
documentation. I
think it should just use the type of the first return 
statement.

...


http://d.puremagic.com/issues/show_bug.cgi?id=8307





Bug in Auto Functions and Template? Or Am I Just Crazy...

2012-06-27 Thread Michael

Hello all,
  I came across some weird behaviors yesterday and I can't figure 
out what it's about.


(1)
auto factorial(int n) {
if (n  2) return 1;
return n * factorial(n-1);
}

The compiler complained about forward declaration of factorial. 
If I change the return type to int, the problem goes away. I can 
understand that with the recursion, it might be impossible for 
the compiler to deduce the type of factorial and so it compile 
errors, but I don't see anything about that on the Language 
Reference. Is this the intended behavior?


(2)
auto stuff(T)(T[] arr) {
auto inner(T[] s) {
s[0] = 0;
}
arr.inner();
}
This time the compiler complained about 'inner' not being 
defined. This time I have no idea what is wrong.


Thanks for your help!
Michael


Re: Bug in Auto Functions and Template? Or Am I Just Crazy...

2012-06-27 Thread Tobias Pankrath

On Wednesday, 27 June 2012 at 09:07:57 UTC, Michael wrote:

Hello all,
  I came across some weird behaviors yesterday and I can't 
figure out what it's about.


(1)
auto factorial(int n) {
if (n  2) return 1;
return n * factorial(n-1);
}

The compiler complained about forward declaration of 
factorial. If I change the return type to int, the problem 
goes away. I can understand that with the recursion, it might 
be impossible for the compiler to deduce the type of factorial 
and so it compile errors, but I don't see anything about that 
on the Language Reference. Is this the intended behavior?


(2)
auto stuff(T)(T[] arr) {
auto inner(T[] s) {
s[0] = 0;
}
arr.inner();
}
This time the compiler complained about 'inner' not being 
defined. This time I have no idea what is wrong.


Thanks for your help!
Michael


(1) is intended bahaviour, though I do think that the compiler 
could be smarter. At least the cases, that could be 
tail-call-optimize could also be inferred.


(2) looks like a bug to me



Re: Bug in Auto Functions and Template? Or Am I Just Crazy...

2012-06-27 Thread Timon Gehr

On 06/27/2012 11:07 AM, Michael wrote:

Hello all,
   I came across some weird behaviors yesterday and I can't figure out
what it's about.

(1)
auto factorial(int n) {
 if (n  2) return 1;
 return n * factorial(n-1);
}

The compiler complained about forward declaration of factorial. If I
change the return type to int, the problem goes away. I can understand
that with the recursion, it might be impossible for the compiler to
deduce the type of factorial and so it compile errors, but I don't see
anything about that on the Language Reference. Is this the intended
behavior?



Apparently the compiler attempts to type combine the types of the
return statements. This does not match the language documentation. I
think it should just use the type of the first return statement.


(2)
auto stuff(T)(T[] arr) {
 auto inner(T[] s) {
 s[0] = 0;
 }
 arr.inner();
}
This time the compiler complained about 'inner' not being defined. This
time I have no idea what is wrong.

Thanks for your help!
Michael



This is expected behaviour. UFCS only works with module scope functions.


Re: Bug in Auto Functions and Template? Or Am I Just Crazy...

2012-06-27 Thread Timon Gehr

On 06/27/2012 01:24 PM, Timon Gehr wrote:

On 06/27/2012 11:07 AM, Michael wrote:

Hello all,
   I came across some weird behaviors yesterday and I can't figure out
what it's about.

(1)
auto factorial(int n) {
 if (n  2) return 1;
 return n * factorial(n-1);
}

The compiler complained about forward declaration of factorial. If I
change the return type to int, the problem goes away. I can understand
that with the recursion, it might be impossible for the compiler to
deduce the type of factorial and so it compile errors, but I don't see
anything about that on the Language Reference. Is this the intended
behavior?



Apparently the compiler attempts to type combine the types of the
return statements. This does not match the language documentation. I
think it should just use the type of the first return statement.
...


http://d.puremagic.com/issues/show_bug.cgi?id=8307


Re: Using consistently auto as function return type

2012-06-16 Thread Era Scarecrow

On Saturday, 16 June 2012 at 09:31:35 UTC, Tommi wrote:
Do you consider it to be good or bad style of programming to 
use consistently auto as function return type?


One of the pros is that it saves some redundant typing when the 
function returns some complex templated type:


auto getValue()
{
return MyType!(int, asdf, 64).init;
}

But one of the cons is that you don't see what the function 
returns just by looking at the signature.


Are there some more severe issues that I'm missing?


 I've wondered a bit of this myself. I tend to have all my 
function return types explicit and tend to use auto more for 
values returned when I am going to be using them right away, or 
they vary slightly on type (but not function).


 Being as D is not C++ (with it's template system), it can still 
parse and make sense of a majority of the code but lacking a 
specific return type... I want to say it's a potential pitfall 
and trap for later. If it only returns a basic type then the 
problem isn't as severe since implicit casting can take place to 
fix minor variations of type (real/double, int/long, etc).


 Perhaps a suggestion on use, where auto should be used: As a 
lambda return type, or functions that return simple base types?  
Not to say it would prevent you from from using auto, but then 
the potential damage is lessened. Perhaps a bigger problem is 
that auto would hide type changes and potential problems because 
it was auto, but regarding templates with that I don't know. 
Mmmm... I need more experience.


Re: Using consistently auto as function return type

2012-06-16 Thread Timon Gehr

On 06/16/2012 11:31 AM, Tommi wrote:

Do you consider it to be good or bad style of programming to use
consistently auto as function return type?

One of the pros is that it saves some redundant typing when the function
returns some complex templated type:

auto getValue()
{
 return MyType!(int, asdf, 64).init;
}

But one of the cons is that you don't see what the function returns just
by looking at the signature.

Are there some more severe issues that I'm missing?


auto return types make functions semantically dependent on each other,
eg. the following is illegal code:

auto foo(){bar(); return 0; }
auto bar(){foo(); return 1; }

In order to resolve the return type of foo, the body of foo needs to be
analyzed, which involves resolving the return type of bar, therefore
the body of bar needs to be analyzed, which involves resolving the
return type of foo, therefore the body of foo needs to be analyzed, ...


The current implementation is very conservative, and rejects every
dependency cycle of auto return functions, even if the return types
could be resolved in theory.


Other than that, there are no more severe issues, I see these major
applications for auto return types:

- The body is very short and spells out the type explicitly, auto saves 
redundancy.


- The implementer does not know the exact return type himself, because
  it depends on template arguments.

- The user of the function does not need to know the return type. eg if
  it is a type local to the function.


Re: Using consistently auto as function return type

2012-06-16 Thread bearophile

Tommi:

Do you consider it to be good or bad style of programming to 
use consistently auto as function return type?


In Python programming you don't specify the types of function 
arguments and return values, but while this is possible in 
Haskell too, it's good practice to write down input and output 
types for functions, and let the type inferencer work just inside 
functions.


In D I use auto often inside function, unless I want to change a 
type or unless I want to be sure a certain variable has a desired 
type. But for clarity/readability I prefer to specify 
input/output types of D functions, unless they return a complex 
range. In this case I sometimes add a static assert to be sure it 
yields a range of my desired type:


auto foo(...)
out (result) {
static assert(ForeachType!(typeof(result)) == ushort);
}
body {
...
}


Bye,
bearophile


Auto-conversion in array literals?

2012-06-11 Thread bearophile

This is valid Scala code:

object Main {
def main(args: Array[String]): Unit = {
val a: List[BigInt] = List(1, BigInt(2))
}
}


Is it possible/meaningful to support/allow D code like this?

import std.bigint;
void main() {
BigInt[] a = [1, BigInt(2)];
}

Bye,
bearophile


Re: Auto-conversion in array literals?

2012-06-11 Thread Timon Gehr

On 06/12/2012 12:55 AM, bearophile wrote:

This is valid Scala code:

object Main {
 def main(args: Array[String]): Unit = {
 val a: List[BigInt] = List(1, BigInt(2))
 }
}


Is it possible/meaningful to support/allow D code like this?

import std.bigint;
void main() {
 BigInt[] a = [1, BigInt(2)];
}

Bye,
bearophile


Making it work would require a way to specify an implicit conversion 
from int to BigInt.


Auto-casting in range based functions?

2012-05-13 Thread Andrew Stanton
I have been playing around with D as a scripting tool and have 
been running into the following issue:


---
import std.algorithm;

struct Delim {
char delim;
this(char d) {
delim = d;
}
}

void main() {
char[] d = ['a', 'b', 'c'];
auto delims = map!Delim(d);
}

/*
Compiling gives me the following error:
/usr/include/d/dmd/phobos/std/algorithm.d(382): Error: 
constructor test.Delim.this (char d) is not callable using 
argument types (dchar)
/usr/include/d/dmd/phobos/std/algorithm.d(382): Error: cannot 
implicitly convert expression ('\U') of type dchar to char


*/

---

As someone who most of the time doesn't need to handle unicode, 
is there a way I can convince these functions to not upcast char 
to dchar?  I can't think of a way to make the code more explicit 
in its typing.


Re: Auto-casting in range based functions?

2012-05-13 Thread Artur Skawina
On 05/13/12 19:49, Andrew Stanton wrote:
 I have been playing around with D as a scripting tool and have been running 
 into the following issue:
 
 ---
 import std.algorithm;
 
 struct Delim {
 char delim;
 this(char d) {
 delim = d;
 }
 }
 
 void main() {
 char[] d = ['a', 'b', 'c'];
 auto delims = map!Delim(d);
 }
 
 /*
 Compiling gives me the following error:
 /usr/include/d/dmd/phobos/std/algorithm.d(382): Error: constructor 
 test.Delim.this (char d) is not callable using argument types (dchar)
 /usr/include/d/dmd/phobos/std/algorithm.d(382): Error: cannot implicitly 
 convert expression ('\U') of type dchar to char
 
 */
 
 ---
 
 As someone who most of the time doesn't need to handle unicode, is there a 
 way I can convince these functions to not upcast char to dchar?  I can't 
 think of a way to make the code more explicit in its typing.

Well, if you don't want/need utf8 at all:

   alias ubyte ascii;

   int main() {
   ascii[] d = ['a', 'b', 'c'];
   auto delims = map!Delim(d);
   //...

and if you want to avoid utf8 just for this case (ie you know 'd[]'
contains just ascii) something like this should work:

char[] d = ['a', 'b', 'c'];
auto delims = map!((c){assert(c128); return Delim(cast(char)c);})(d);

(it's probably more efficient when written as

auto delims = map!Delim(cast(ascii[])d);

but you loose the safety checks)

artur


Re: Auto-casting in range based functions?

2012-05-13 Thread Jonathan M Davis
On Sunday, May 13, 2012 19:49:00 Andrew Stanton wrote:
 I have been playing around with D as a scripting tool and have
 been running into the following issue:
 
 ---
 import std.algorithm;
 
 struct Delim {
  char delim;
  this(char d) {
  delim = d;
  }
 }
 
 void main() {
  char[] d = ['a', 'b', 'c'];
  auto delims = map!Delim(d);
 }
 
 /*
 Compiling gives me the following error:
 /usr/include/d/dmd/phobos/std/algorithm.d(382): Error:
 constructor test.Delim.this (char d) is not callable using
 argument types (dchar)
 /usr/include/d/dmd/phobos/std/algorithm.d(382): Error: cannot
 implicitly convert expression ('\U') of type dchar to char
 
 */
 
 ---
 
 As someone who most of the time doesn't need to handle unicode,
 is there a way I can convince these functions to not upcast char
 to dchar?  I can't think of a way to make the code more explicit
 in its typing.

_All_ string types are considered ranges of dchar and treated as such. That 
means that narrow strings (e.g. arrays of char or wchar) are not random-access 
ranges and have no length property as far as range-based functions are 
concerned. So, you can _never_ have char[] treated as a range of char by any 
Phobos functions. char[] is UTF-8 by definition, and range-based functions in 
Phobos operates on code points, not code units.

If you want a char[] to be treated as a range of char, then you're going to 
have to use ubyte[] instead. e.g.

char[] d = ['a', 'b', 'c'];
auto delims = map!Delim(cast(ubyte[])d);

Now, personally, I would argue that you should just use dchar, not char, 
because regadless of what you are or aren't doing with unicode right now, the 
odds are that you'll end up processing unicode at some point, and if you're in 
the habit of using char, you're going to get all kinds of bugs. So, if you 
just did

struct Delim
{
dchar delim;

this(dchar d)
{
delim = d;
}
}

void main()
{
char[] d = ['a', 'b', 'c'];
auto delims = map!Delim(d);
}

then it should work just fine. And if you really need a char instead of dchar 
for some reason, you can always just use std.conv.to - to!char(value) - which 
will then throw if you're trying to convert a code point that won't fit in a 
char.

In general, any code which has a variable of char or wchar as a variable 
rather than an element in an array is a red flag which indicates a likely bug 
or bad design. In specific circumstances, you may need to do so, but in 
general, it's just asking for bugs. And you're going to have to be fighting 
Phobos all the time if you try and use ranges of code units rather than ranges 
of code points.

- Jonathan M Davis


Re: auto

2011-11-26 Thread mta`chrono
Did you know that auto is not auto in the way auto behalfs. it's just a
placeholder so the compiler can determine that a variable follows. but
you can use any other keyword for type interfering, too.

void main()
{
const a = FunctionThatReturnsSomething();
static b = 5.0;
scope c = hey;
}


auto

2011-11-24 Thread RexLen
Just curious:
is there any performance gap using auto instead of int or other
type? For example

int[] ar1 = new int[1000];
auto[] ar2 = new int[1000];

are these equivalent by a perfomance point of view?

Thx


Re: auto

2011-11-24 Thread David Nadlinger

On 11/24/11 10:09 PM, Trass3r wrote:

Well the runtime performance is equal but of course compilation takes
slightly longer since it has to deduce the type first.


Just curious: I would be surprised if there was actually a measurable 
difference between the two – did you ever try to measure it?


David


Re: auto

2011-11-24 Thread Trass3r

The type has to be deduced anyway for type checking the
assignment/initialization.


Makes sense. Overseen that.


Re: auto

2011-11-24 Thread Andrej Mitrovic
But I bet you would waste more memory at compile-time if you had to
type a long template instance name instead of using auto. We're
talkin' bytes here!


Re: Cannot use auto return while using class invariants

2011-10-21 Thread Jonathan M Davis
On Friday, October 21, 2011 16:51 simendsjo wrote:
 Is this a temporary restriction?
 
 class C {
 invariant() { }
 auto f() {
 return 1;
 }
 }
 
 Error: function C.f post conditions are not supported if the return type
 is inferred

http://d.puremagic.com/issues/show_bug.cgi?id=5039


Re: Cannot use auto return while using class invariants

2011-10-21 Thread simendsjo

On 22.10.2011 02:06, Jonathan M Davis wrote:

On Friday, October 21, 2011 16:51 simendsjo wrote:

Is this a temporary restriction?

class C {
invariant() { }
auto f() {
return 1;
}
}

Error: function C.f post conditions are not supported if the return type
is inferred


http://d.puremagic.com/issues/show_bug.cgi?id=5039


Thanks. Doesn't look like it will be fixed for a while.


Re: Why no (auto foo = bar) in while loops?

2011-08-25 Thread Timon Gehr

On 08/25/2011 01:11 PM, Steven Schveighoffer wrote:

On Wed, 24 Aug 2011 19:01:31 -0400, Timon Gehr timon.g...@gmx.ch wrote:


On 08/25/2011 12:47 AM, Mafi wrote:

Am 24.08.2011 21:04, schrieb Timon Gehr:

On 08/24/2011 08:04 PM, Andrej Mitrovic wrote:

Here's some code that iterates through parents of some class object
until it finds an object with no parent (where parent is null):

import std.stdio;

class Foo
{
Foo parent;
int state;

this (int state) { this.state = state; }
}

void main()
{
auto foo = new Foo(0);
foo.parent = new Foo(1);
foo.parent.parent = new Foo(2);

while (true)
{
if (auto par = foo.parent)
{
writeln(par.state);
foo = par;
}
else
{
break;
}
}
}

(syntax-highlighted: http://codepad.org/8yHRmICh)

But I was hoping I could simplify this by doing:

while (auto par = foo.parent)
{
writeln(par.state);
foo = par;
}

However that doesn't work, I get back:
expression expected, not 'auto'

Is there a limitation on why this couldn't work or can this be added
to the language?


Afaics, this could be added just like it could be added for if. In fact
the compiler should be able to simply rewrite it to your first example.
I think it is worth an enhancement request, because there are
situations
where this would be useful, and implementation should be trivial, if
somebody has the time. (I also think it adds to the consistency of the
language, but others may disagree.)


(btw, i always use for(;;) instead of while(true), it is usually faster
in debug mode and faster to type :))


I just have to say that it already works for 'if'. It's a great feature
because in the body of the 'if' you know the value is non-null and
outside, where there could be an segfault, the variable is not visible.
I'm not really sure if it's good for 'while'.
I'm unsure because there are two somewhat natural semantics for such a
construct.

//example
//more to the nature of while
while(auto obj = init) { work(obj); }

//1 (your interpretation)
typeof(init) obj;
while(obj = init) { work(obj); }

//2
/*
seems more natural for me because init runs only once (like any other
init and like in 'for' or 'if')
*/


for(;;){int x=init;} // init runs infinitely many times


if(auto a=init){} is really more trying to solve

if(???){auto a=init;} // correct scoping but cannot refer to it in cond

than

{auto a=init; if(a){}} // correct scoping as long as there is no else

That is why there is the language construct. That it has not been
adopted for while is because it is so much more useful for if, but I
personally think while could/should get the possibility as well.




auto obj = init;
while(obj) { work(obj); }

This could confuse many people, I think. What do you think?



I think that by the same argument, you could say that the fact that
the body of a looping statement is executed multiple times could
confuse many people.

1 is more natural imho. (and 2 would be rather useless)


I disagree -- I think the semantics are confusing.


while(condition) do_this;
while(auto d=condition) do_this_and_use_d;

I still think it is simple, but it is not a feature I miss often.



I'd say just leave the auto x = y for if and for loops, where there is a
clear run once section.

Also, what do you do with a do while loop if the while contains this
construct?



In do while it is useless because the scope ends after the condition.



Re: Why no (auto foo = bar) in while loops?

2011-08-25 Thread Jonathan M Davis
On Thursday, August 25, 2011 07:11:31 Steven Schveighoffer wrote:
 On Wed, 24 Aug 2011 19:01:31 -0400, Timon Gehr timon.g...@gmx.ch wrote:
  On 08/25/2011 12:47 AM, Mafi wrote:
  Am 24.08.2011 21:04, schrieb Timon Gehr:
  On 08/24/2011 08:04 PM, Andrej Mitrovic wrote:
  Here's some code that iterates through parents of some class
  object
  until it finds an object with no parent (where parent is null):
  
  import std.stdio;
  
  class Foo
  {
  Foo parent;
  int state;
  
  this (int state) { this.state = state; }
  }
  
  void main()
  {
  auto foo = new Foo(0);
  foo.parent = new Foo(1);
  foo.parent.parent = new Foo(2);
  
  while (true)
  {
  if (auto par = foo.parent)
  {
  writeln(par.state);
  foo = par;
  }
  else
  {
  break;
  }
  }
  }
  
  (syntax-highlighted: http://codepad.org/8yHRmICh)
  
  But I was hoping I could simplify this by doing:
  
  while (auto par = foo.parent)
  {
  writeln(par.state);
  foo = par;
  }
  
  However that doesn't work, I get back:
  expression expected, not 'auto'
  
  Is there a limitation on why this couldn't work or can this be
  added
  to the language?
  
  Afaics, this could be added just like it could be added for if. In
  fact
  the compiler should be able to simply rewrite it to your first
  example.
  I think it is worth an enhancement request, because there are
  situations
  where this would be useful, and implementation should be trivial, if
  somebody has the time. (I also think it adds to the consistency of
  the
  language, but others may disagree.)
  
  
  (btw, i always use for(;;) instead of while(true), it is usually
  faster
  in debug mode and faster to type :))
  
  I just have to say that it already works for 'if'. It's a great
  feature
  because in the body of the 'if' you know the value is non-null and
  outside, where there could be an segfault, the variable is not
  visible.
  I'm not really sure if it's good for 'while'.
  I'm unsure because there are two somewhat natural semantics for such a
  construct.
  
  //example
  //more to the nature of while
  while(auto obj = init) { work(obj); }
  
  //1 (your interpretation)
  typeof(init) obj;
  while(obj = init) { work(obj); }
  
  //2
  /*
  seems more natural for me because init runs only once (like any other
  init and like in 'for' or 'if')
  */
  
  for(;;){int x=init;} // init runs infinitely many times
  
  
  if(auto a=init){} is really more trying to solve
  
  if(???){auto a=init;} // correct scoping but cannot refer to it in cond
  
  than
  
  {auto a=init; if(a){}} // correct scoping as long as there is no else
  
  That is why there is the language construct. That it has not been
  adopted for while is because it is so much more useful for if, but I
  personally think while could/should get the possibility as well.
  
  auto obj = init;
  while(obj) { work(obj); }
  
  This could confuse many people, I think. What do you think?
  
  I think that by the same argument, you could say that the fact that the
  body of a looping statement is executed multiple times could confuse
  many people.
  
  1 is more natural imho. (and 2 would be rather useless)
 
 I disagree -- I think the semantics are confusing.
 
 I'd say just leave the auto x = y for if and for loops, where there is a
 clear run once section.
 
 Also, what do you do with a do while loop if the while contains this
 construct?
 
 I just find the whole thing confusing.

I don't see why it would be confusing. Because it's unclear whether it's set 
every time or whether it's a new variable every time? It's actually one of 
those things that I do periodically thinking that it works and then get 
frustrated when it doesn't, so I'd love to see it added.

- Jonathan M Davis


Re: Why no (auto foo = bar) in while loops?

2011-08-25 Thread Steven Schveighoffer
On Thu, 25 Aug 2011 11:15:44 -0400, Jonathan M Davis jmdavisp...@gmx.com  
wrote:



On Thursday, August 25, 2011 07:11:31 Steven Schveighoffer wrote:

 On 08/25/2011 12:47 AM, Mafi wrote:



 I'm not really sure if it's good for 'while'.
 I'm unsure because there are two somewhat natural semantics for such  
a

 construct.

 //example
 //more to the nature of while
 while(auto obj = init) { work(obj); }

 //1 (your interpretation)
 typeof(init) obj;
 while(obj = init) { work(obj); }

 //2
 /*
 seems more natural for me because init runs only once (like any other
 init and like in 'for' or 'if')
 */

I'd say just leave the auto x = y for if and for loops, where there is a
clear run once section.

Also, what do you do with a do while loop if the while contains this
construct?

I just find the whole thing confusing.


I don't see why it would be confusing. Because it's unclear whether it's  
set
every time or whether it's a new variable every time? It's actually one  
of

those things that I do periodically thinking that it works and then get
frustrated when it doesn't, so I'd love to see it added.


See Mafi's response above.

What it boils down to is, I usually replace code like this:

auto x = condition;
if(x)
{
   // use x
}

with this:

if(auto x = condition)
{
   // use x.
}

so the logical mapping to while would map this:

auto x = condition;
while(x)
{
   // use x.
}

to this:

while(auto x = condition)
{
   // use x.
}

But it looks like every time through the loop x gets reassigned to  
condition.  That's not what I'd want.  At the very least, it's confusing  
semantics one way or the other.


If you use the construct in the *init* section of a for loop, it reads the  
same as the if statement, since that part is only executed once.


The while loop just doesn't fit the model.

-Steve


Re: Why no (auto foo = bar) in while loops?

2011-08-25 Thread Jonathan M Davis
On Thursday, August 25, 2011 11:31:56 Steven Schveighoffer wrote:
 On Thu, 25 Aug 2011 11:15:44 -0400, Jonathan M Davis jmdavisp...@gmx.com
 
 wrote:
  On Thursday, August 25, 2011 07:11:31 Steven Schveighoffer wrote:
   On 08/25/2011 12:47 AM, Mafi wrote:
   I'm not really sure if it's good for 'while'.
   I'm unsure because there are two somewhat natural semantics for
   such
  
  a
  
   construct.
   
   //example
   //more to the nature of while
   while(auto obj = init) { work(obj); }
   
   //1 (your interpretation)
   typeof(init) obj;
   while(obj = init) { work(obj); }
   
   //2
   /*
   seems more natural for me because init runs only once (like any
   other
   init and like in 'for' or 'if')
   */
  
  I'd say just leave the auto x = y for if and for loops, where there is
  a
  clear run once section.
  
  Also, what do you do with a do while loop if the while contains this
  construct?
  
  I just find the whole thing confusing.
  
  I don't see why it would be confusing. Because it's unclear whether it's
  set
  every time or whether it's a new variable every time? It's actually one
  of
  those things that I do periodically thinking that it works and then get
  frustrated when it doesn't, so I'd love to see it added.
 
 See Mafi's response above.
 
 What it boils down to is, I usually replace code like this:
 
 auto x = condition;
 if(x)
 {
 // use x
 }
 
 with this:
 
 if(auto x = condition)
 {
 // use x.
 }
 
 so the logical mapping to while would map this:
 
 auto x = condition;
 while(x)
 {
 // use x.
 }
 
 to this:
 
 while(auto x = condition)
 {
 // use x.
 }
 
 But it looks like every time through the loop x gets reassigned to
 condition.  That's not what I'd want.  At the very least, it's confusing
 semantics one way or the other.
 
 If you use the construct in the *init* section of a for loop, it reads the
 same as the if statement, since that part is only executed once.
 
 The while loop just doesn't fit the model.

Well, I'd definitely want it so that x is the value of the condition every 
time, and it surprises me that anyone would have thought that that would do 
anything else. The whole point of creating the variable in the if or while 
condition like that IMHO is so that you can save what the exact condition was 
for that run of the if statement or while loop without having to have to run 
the condition twice or have the variable exist outside the scope of the if-
statement or while-loop. If you wanted it to just be the value of the 
condition on the first iteration, then for does that already quite explicitly. 
But then again, assuming that for allows you to assign in the condition as 
well, then at least it's more explicit there, but I would have thought that 
the semantics of the while loop would have been quite clear.

- Jonathan M Davis


Re: Why no (auto foo = bar) in while loops?

2011-08-25 Thread Timon Gehr

On 08/25/2011 05:31 PM, Steven Schveighoffer wrote:
 On Thu, 25 Aug 2011 11:15:44 -0400, Jonathan M Davis
 jmdavisp...@gmx.com wrote:

 On Thursday, August 25, 2011 07:11:31 Steven Schveighoffer wrote:
  On 08/25/2011 12:47 AM, Mafi wrote:

  I'm not really sure if it's good for 'while'.
  I'm unsure because there are two somewhat natural semantics for
 such a
  construct.
 
  //example
  //more to the nature of while
  while(auto obj = init) { work(obj); }
 
  //1 (your interpretation)
  typeof(init) obj;
  while(obj = init) { work(obj); }
 
  //2
  /*
  seems more natural for me because init runs only once (like any 
other

  init and like in 'for' or 'if')
  */
 
 I'd say just leave the auto x = y for if and for loops, where there 
is a

 clear run once section.

 Also, what do you do with a do while loop if the while contains this
 construct?

 I just find the whole thing confusing.

 I don't see why it would be confusing. Because it's unclear whether
 it's set
 every time or whether it's a new variable every time? It's actually
 one of
 those things that I do periodically thinking that it works and then get
 frustrated when it doesn't, so I'd love to see it added.

 See Mafi's response above.

 What it boils down to is, I usually replace code like this:

 auto x = condition;
 if(x)
 {
 // use x
 }

 with this:

 if(auto x = condition)
 {
 // use x.
 }

 so the logical mapping to while would map this:

 auto x = condition;
 while(x)
 {
 // use x.
 }

 to this:

 while(auto x = condition)
 {
 // use x.
 }

 But it looks like every time through the loop x gets reassigned to
 condition. That's not what I'd want. At the very least, it's confusing
 semantics one way or the other.

 If you use the construct in the *init* section of a for loop, it reads
 the same as the if statement, since that part is only executed once.

 The while loop just doesn't fit the model.

 -Steve

I usually replace code like this:

x++;
if(x  100)
{
  // use x
}

with this:

if(++x  100) {
// use x
}

so the logical mapping to while would map this:

x++;
while(x  100)
{
// use x.
}

to this:

while(++x  100) {
// use x.
}


But it looks like every time through the loop x gets incremented.
That's not what I'd want. At the very least, it's confusing
semantics one way or the other.

If you use the construct in the *init* section of a for loop, it reads
the same as the if statement, since that part is only executed once.

The while loop just doesn't fit the model. Let's ditch the while loop.

-Timon


Re: Why no (auto foo = bar) in while loops?

2011-08-25 Thread Steven Schveighoffer

On Thu, 25 Aug 2011 12:21:19 -0400, Timon Gehr timon.g...@gmx.ch wrote:




I usually replace code like this:

x++;
if(x  100)
{
   // use x
}

with this:

if(++x  100) {
 // use x
}

so the logical mapping to while would map this:

x++;
while(x  100)
{
 // use x.
}

to this:

while(++x  100) {
 // use x.
}


But it looks like every time through the loop x gets incremented.
That's not what I'd want. At the very least, it's confusing
semantics one way or the other.

If you use the construct in the *init* section of a for loop, it reads
the same as the if statement, since that part is only executed once.

The while loop just doesn't fit the model. Let's ditch the while loop.


Not relevant, you are not declaring a variable in your example.  The  
benefit of using the auto x = y is that you can move the declaration of  
the variable, which is used only during the loop, into the loop statement.


I have written loops like this:

bool found = false;
while(!found)
{
  // things that might set found to true
}

There is also this construct, which is what you are arguing for:

bool continueloop;
while(continueloop = someComplexFunction())
{
  // use continueloop as rvalue in places
}

So there are legitimate cases for while(auto x = y) being a shortcut for  
both behaviors, hence the confusion.


I agree your case yields more fruit, since I think the above is actually  
invalid (can't use = as a boolean expression), but it doesn't stop me from  
being confused about whether the initialization happens once or every  
time.  It just reads like it happens once to me, even if it happens every  
loop.  That confusion isn't there for if statements or for loops.


-Steve


Re: Why no (auto foo = bar) in while loops?

2011-08-25 Thread Timon Gehr

On 08/25/2011 10:51 PM, Steven Schveighoffer wrote:
 On Thu, 25 Aug 2011 12:21:19 -0400, Timon Gehr timon.g...@gmx.ch wrote:



 I usually replace code like this:

 x++;
 if(x  100)
 {
 // use x
 }

 with this:

 if(++x  100) {
 // use x
 }

 so the logical mapping to while would map this:

 x++;
 while(x  100)
 {
 // use x.
 }

 to this:

 while(++x  100) {
 // use x.
 }


 But it looks like every time through the loop x gets incremented.
 That's not what I'd want. At the very least, it's confusing
 semantics one way or the other.

 If you use the construct in the *init* section of a for loop, it reads
 the same as the if statement, since that part is only executed once.

 The while loop just doesn't fit the model. Let's ditch the while loop.

 Not relevant, you are not declaring a variable in your example.

It was _the whole point_ that I am not declaring a variable in my 
example. Our two examples are equivalent in what they are saying on a 
conceptual level. Whether the condition contains a declaration or an 
increment operation does not matter.


 The
 benefit of using the auto x = y is that you can move the declaration of
 the variable, which is used only during the loop, into the loop 
statement.


The benefit of using the auto x = y is that you can declare a new 
variable inside the condition, plus useful scoping.



 I have written loops like this:

 bool found = false;
 while(!found)
 {
 // things that might set found to true
 }

for(;;) {
... break; ...
}

or even

for(bool found=false;!found;){
// things that might set found to true
}



 There is also this construct, which is what you are arguing for:

 bool continueloop;
 while(continueloop = someComplexFunction())
 {
 // use continueloop as rvalue in places
 }


I am not arguing for this esoteric case, I wouldn't use a boolean flag, 
but a reference or pointer that is then guaranteed to be non-null inside 
each loop body execution. Pragmatic and consistent with how it would 
normally be used in if.


 So there are legitimate cases for while(auto x = y) being a shortcut for
 both behaviors, hence the confusion.

There is really no legitimate reason for while(auto x = y) being a 
shortcut for the first.



 I agree your case yields more fruit, since I think the above is actually
 invalid (can't use = as a boolean expression), but it doesn't stop me
 from being confused about whether the initialization happens once or
 every time. It just reads like it happens once to me, even if it happens
 every loop. That confusion isn't there for if statements or for loops.


Why does the _loop condition_ read like it happens only once to you? I 
don't get that.



for(init; condition; statement){}
while(condition   ){}

The init part of for is irrelevant for this discussion because it does 
not exist in while. conditions work for both kinds of loops in the same 
way: They are executed and checked before the loop body is run. The body 
of an if is only executed once, therefore the condition is only executed 
and checked once. If there is an inline-declaration or not does not 
matter for the execution semantics, and it *WOULD* be confusing if it was.









Re: Why no (auto foo = bar) in while loops?

2011-08-25 Thread Steven Schveighoffer

On Thu, 25 Aug 2011 17:31:26 -0400, Timon Gehr timon.g...@gmx.ch wrote:


On 08/25/2011 10:51 PM, Steven Schveighoffer wrote:
  On Thu, 25 Aug 2011 12:21:19 -0400, Timon Gehr timon.g...@gmx.ch  
wrote:

 
 
 
  I usually replace code like this:
 
  x++;
  if(x  100)
  {
  // use x
  }
 
  with this:
 
  if(++x  100) {
  // use x
  }
 
  so the logical mapping to while would map this:
 
  x++;
  while(x  100)
  {
  // use x.
  }
 
  to this:
 
  while(++x  100) {
  // use x.
  }
 
 
  But it looks like every time through the loop x gets incremented.
  That's not what I'd want. At the very least, it's confusing
  semantics one way or the other.
 
  If you use the construct in the *init* section of a for loop, it  
reads

  the same as the if statement, since that part is only executed once.
 
  The while loop just doesn't fit the model. Let's ditch the while  
loop.

 
  Not relevant, you are not declaring a variable in your example.

It was _the whole point_ that I am not declaring a variable in my  
example. Our two examples are equivalent in what they are saying on a  
conceptual level. Whether the condition contains a declaration or an  
increment operation does not matter.


Except the declaration is not currently allowed in a while-loop
conditional expression.  Nor was it allowed in an if conditional
expression, until it was added.  Prior to that addition, it was necessary
to declare the variable outside the if statement in order to only call the
intializer once.



  The
  benefit of using the auto x = y is that you can move the declaration  
of
  the variable, which is used only during the loop, into the loop  
statement.


The benefit of using the auto x = y is that you can declare a new  
variable inside the condition, plus useful scoping.


I think you just said the same thing I did :)



 
  I have written loops like this:
 
  bool found = false;
  while(!found)
  {
  // things that might set found to true
  }

for(;;) {
 ... break; ...
}


This doesn't always work, you may need to delay exiting the loop.


or even

for(bool found=false;!found;){
 // things that might set found to true
}


This also works in your case too.  You can simply declare your variable,
then assign it in the condition.  Insert whatever case you wish there.




 
  There is also this construct, which is what you are arguing for:
 
  bool continueloop;
  while(continueloop = someComplexFunction())
  {
  // use continueloop as rvalue in places
  }
 

I am not arguing for this esoteric case, I wouldn't use a boolean flag,  
but a reference or pointer that is then guaranteed to be non-null inside  
each loop body execution. Pragmatic and consistent with how it would  
normally be used in if.


Well, it was just a contrived example, not a full-fledged program.



  So there are legitimate cases for while(auto x = y) being a shortcut  
for

  both behaviors, hence the confusion.

There is really no legitimate reason for while(auto x = y) being a  
shortcut for the first.


I disagree, especially since it *reads* that way to me.



 
  I agree your case yields more fruit, since I think the above is  
actually

  invalid (can't use = as a boolean expression), but it doesn't stop me
  from being confused about whether the initialization happens once or
  every time. It just reads like it happens once to me, even if it  
happens

  every loop. That confusion isn't there for if statements or for loops.
 

Why does the _loop condition_ read like it happens only once to you? I  
don't get that.


Because it is a declaration.  Declarations do not typically get executed
more than once, unless it is *inside* a loop.

I'm not saying the functionality you want to create is not useful, or that
it would not help in many cases.  I'm not saying it should be either my
way or your way.  I'm saying, it *reads* like it could be both ways, and
therefore is confusing, and not worth adding to the language.  It will
lead to people expecting one case, even though it means the other, no
matter which way you choose it to mean.  We already have several people
split about evenly on what they expect.

-Steve


Re: Why no (auto foo = bar) in while loops?

2011-08-25 Thread Timon Gehr

On 08/26/2011 12:38 AM, Steven Schveighoffer wrote:

On Thu, 25 Aug 2011 17:31:26 -0400, Timon Gehr timon.g...@gmx.ch wrote:


On 08/25/2011 10:51 PM, Steven Schveighoffer wrote:
 On Thu, 25 Aug 2011 12:21:19 -0400, Timon Gehr timon.g...@gmx.ch
wrote:



 I usually replace code like this:

 x++;
 if(x  100)
 {
 // use x
 }

 with this:

 if(++x  100) {
 // use x
 }

 so the logical mapping to while would map this:

 x++;
 while(x  100)
 {
 // use x.
 }

 to this:

 while(++x  100) {
 // use x.
 }


 But it looks like every time through the loop x gets incremented.
 That's not what I'd want. At the very least, it's confusing
 semantics one way or the other.

 If you use the construct in the *init* section of a for loop, it reads
 the same as the if statement, since that part is only executed once.

 The while loop just doesn't fit the model. Let's ditch the while loop.

 Not relevant, you are not declaring a variable in your example.

It was _the whole point_ that I am not declaring a variable in my
example. Our two examples are equivalent in what they are saying on a
conceptual level. Whether the condition contains a declaration or an
increment operation does not matter.


Except the declaration is not currently allowed in a while-loop
conditional expression. Nor was it allowed in an if conditional
expression, until it was added. Prior to that addition, it was necessary
to declare the variable outside the if statement in order to only call the
intializer once.



 The
 benefit of using the auto x = y is that you can move the declaration of
 the variable, which is used only during the loop, into the loop
statement.

The benefit of using the auto x = y is that you can declare a new
variable inside the condition, plus useful scoping.


I think you just said the same thing I did :)


As an analogy, you said: We have loops so that we can hide gotos. I 
said: We have loops so that we can execute code sequences multiple 
times. :)







 I have written loops like this:

 bool found = false;
 while(!found)
 {
 // things that might set found to true
 }

for(;;) {
... break; ...
}


This doesn't always work, you may need to delay exiting the loop.


or even

for(bool found=false;!found;){
// things that might set found to true
}


This also works in your case too. You can simply declare your variable,
then assign it in the condition. Insert whatever case you wish there.



Yes, but then I don't get type inference, which is not very D-like.





 There is also this construct, which is what you are arguing for:

 bool continueloop;
 while(continueloop = someComplexFunction())
 {
 // use continueloop as rvalue in places
 }


I am not arguing for this esoteric case, I wouldn't use a boolean
flag, but a reference or pointer that is then guaranteed to be
non-null inside each loop body execution. Pragmatic and consistent
with how it would normally be used in if.


Well, it was just a contrived example, not a full-fledged program.



 So there are legitimate cases for while(auto x = y) being a shortcut
for
 both behaviors, hence the confusion.

There is really no legitimate reason for while(auto x = y) being a
shortcut for the first.


I disagree, especially since it *reads* that way to me.



I suggest you reconsider.




 I agree your case yields more fruit, since I think the above is
actually
 invalid (can't use = as a boolean expression), but it doesn't stop me
 from being confused about whether the initialization happens once or
 every time. It just reads like it happens once to me, even if it
happens
 every loop. That confusion isn't there for if statements or for loops.


Why does the _loop condition_ read like it happens only once to you? I
don't get that.


Because it is a declaration. Declarations do not typically get executed
more than once, unless it is *inside* a loop.


while(condition) statement;
 ~~~
  ^- inside loop

How can you say the condition is not part of the loop? It is looped too.


I'm not saying the functionality you want to create is not useful, or that
it would not help in many cases. I'm not saying it should be either my
way or your way. I'm saying, it *reads* like it could be both ways, and
therefore is confusing, and not worth adding to the language. It will
lead to people expecting one case, even though it means the other, no
matter which way you choose it to mean. We already have several people
split about evenly on what they expect.

-Steve


Well, I don't get it. If I ever write a D compiler, this feature will be 
supported. =)


Re: Why no (auto foo = bar) in while loops?

2011-08-25 Thread Ali Çehreli
On Thu, 25 Aug 2011 23:31:26 +0200, Timon Gehr wrote:

 for(init; condition; statement){}
 while(condition   ){}

That's a very interesting way of looking at the question.

I bet that explains the other way around: there can't be a variable 
definition in the 'for' loop's condition clause, because 'while' doesn't 
allow it. :p

The compiler probably uses 'while's implementation. The 'for' loop 
probably becomes this:

{
for_init;
while (for_condition) {
for_body;
for_statement;
}
}

So there is no discrepancy: the condition clauses cannot define a 
variable in either loop. :)

If 'while' gets this enhancement, 'for' could be written as the following:

for (int i = 0; auto c = condition(); ++i) {

// Yes, we know that c doesn't evaluate to 'false', but
// we can use c here when it evaluates to 'true'.
// e.g. if it's a pointer:

writeln(*c);
}

Ali


Re: Why no (auto foo = bar) in while loops?

2011-08-25 Thread Timon Gehr

On 08/26/2011 02:00 AM, Ali Çehreli wrote:

On Thu, 25 Aug 2011 23:31:26 +0200, Timon Gehr wrote:


for(init; condition; statement){}
while(condition   ){}


That's a very interesting way of looking at the question.

I bet that explains the other way around: there can't be a variable
definition in the 'for' loop's condition clause, because 'while' doesn't
allow it. :p

The compiler probably uses 'while's implementation. The 'for' loop
probably becomes this:

{
 for_init;
 while (for_condition) {
 for_body;
 for_statement;
 }
}

So there is no discrepancy: the condition clauses cannot define a
variable in either loop. :)


There is a little discrepancy because 'if' condition clauses can. ;)



If 'while' gets this enhancement, 'for' could be written as the following:

for (int i = 0; auto c = condition(); ++i) {

 // Yes, we know that c doesn't evaluate to 'false', but
 // we can use c here when it evaluates to 'true'.
 // e.g. if it's a pointer:

 writeln(*c);
}



Only if it is specifically enabled. The compiler can only rewrite it to 
the while form if it can successfully parse it. But I think that indeed 
iff while is enhanced, for should be too.




Why no (auto foo = bar) in while loops?

2011-08-24 Thread Andrej Mitrovic
Here's some code that iterates through parents of some class object
until it finds an object with no parent (where parent is null):

import std.stdio;

class Foo
{
Foo parent;
int state;

this (int state) { this.state = state; }
}

void main()
{
auto foo  = new Foo(0);
foo.parent= new Foo(1);
foo.parent.parent = new Foo(2);

while (true)
{
if (auto par = foo.parent)
{
writeln(par.state);
foo = par;
}
else
{
break;
}
}
}

(syntax-highlighted: http://codepad.org/8yHRmICh)

But I was hoping I could simplify this by doing:

while (auto par = foo.parent)
{
writeln(par.state);
foo = par;
}

However that doesn't work, I get back:
expression expected, not 'auto'

Is there a limitation on why this couldn't work or can this be added
to the language?


Re: Why no (auto foo = bar) in while loops?

2011-08-24 Thread Andrej Mitrovic
P.S. I'm aware I'm loosing the reference to the first foo object but
this is just demonstration code.


Re: Why no (auto foo = bar) in while loops?

2011-08-24 Thread Timon Gehr

On 08/24/2011 08:04 PM, Andrej Mitrovic wrote:

Here's some code that iterates through parents of some class object
until it finds an object with no parent (where parent is null):

import std.stdio;

class Foo
{
 Foo parent;
 int state;

 this (int state) { this.state = state; }
}

void main()
{
 auto foo  = new Foo(0);
 foo.parent= new Foo(1);
 foo.parent.parent = new Foo(2);

 while (true)
 {
 if (auto par = foo.parent)
 {
 writeln(par.state);
 foo = par;
 }
 else
 {
 break;
 }
 }
}

(syntax-highlighted: http://codepad.org/8yHRmICh)

But I was hoping I could simplify this by doing:

 while (auto par = foo.parent)
 {
 writeln(par.state);
 foo = par;
 }

However that doesn't work, I get back:
expression expected, not 'auto'

Is there a limitation on why this couldn't work or can this be added
to the language?


Afaics, this could be added just like it could be added for if. In fact 
the compiler should be able to simply rewrite it to your first example.
I think it is worth an enhancement request, because there are situations 
where this would be useful, and implementation should be trivial, if 
somebody has the time. (I also think it adds to the consistency of the 
language, but others may disagree.)



(btw, i always use for(;;) instead of while(true), it is usually faster 
in debug mode and faster to type :))


Re: Why no (auto foo = bar) in while loops?

2011-08-24 Thread Andrej Mitrovic
On 8/24/11, Timon Gehr timon.g...@gmx.ch wrote:
 it is usually faster
 in debug mode

Huh.. How come?


Re: Why no (auto foo = bar) in while loops?

2011-08-24 Thread Timon Gehr

On 08/24/2011 09:21 PM, Andrej Mitrovic wrote:

On 8/24/11, Timon Gehrtimon.g...@gmx.ch  wrote:

it is usually faster
in debug mode


Huh.. How come?


Well, not notably faster, but many compilers will emit something in the 
lines of


mov eax, 1
test eax
jnz beginning_of_loop

if no optimizer is run,

whereas most get

for(;;){}

as

jmp beginning_of_loop

even in debug mode.


Re: Why no (auto foo = bar) in while loops?

2011-08-24 Thread Jonathan M Davis
On Wednesday, August 24, 2011 21:29:23 Timon Gehr wrote:
 On 08/24/2011 09:21 PM, Andrej Mitrovic wrote:
  On 8/24/11, Timon Gehrtimon.g...@gmx.ch  wrote:
  it is usually faster
  in debug mode
  
  Huh.. How come?
 
 Well, not notably faster, but many compilers will emit something in the
 lines of
 
 mov eax, 1
 test eax
 jnz beginning_of_loop
 
 if no optimizer is run,
 
 whereas most get
 
 for(;;){}
 
 as
 
 jmp beginning_of_loop
 
 even in debug mode.

Optimizations aside, I would always argue that while(true) should be used 
rather than for(;;). I find for(;;) to be ugly personally and would argue that 
while(true) better captures what you're actually doing. A loop with no 
condition at all is horrible IMHO. It seems completely inconsistent to me that 
the language would allow you to have a for loop without a condition.

Regardless of that, however, I would fully expect that if there is a difference 
in code between the two in debug mode (which there shouldn't be IMHO, but 
compilers don't always do what makes the most sense - especially in debug 
mode) that the difference would be drowned by the contents of the loop and 
wouldn't matter at all. But even if it did, I'd generally argue that coding in 
a certain way just because it was slightly faster in debug mode but had zero 
impact in release mode is not a good idea unless all of the considerations are 
equal. And I'd definitely argue that while(true) is better than for(;;) from an 
aesthetic point of view at minimum, so they definitely aren't equal.

In any case, that's my take on it.

- Jonathan M Davis


Re: Why no (auto foo = bar) in while loops?

2011-08-24 Thread Timon Gehr

On 08/24/2011 09:36 PM, Jonathan M Davis wrote:

On Wednesday, August 24, 2011 21:29:23 Timon Gehr wrote:

On 08/24/2011 09:21 PM, Andrej Mitrovic wrote:

On 8/24/11, Timon Gehrtimon.g...@gmx.ch   wrote:

it is usually faster
in debug mode


Huh.. How come?


Well, not notably faster, but many compilers will emit something in the
lines of

mov eax, 1
test eax
jnz beginning_of_loop

if no optimizer is run,

whereas most get

for(;;){}

as

jmp beginning_of_loop

even in debug mode.


Optimizations aside, I would always argue that while(true) should be used
rather than for(;;). I find for(;;) to be ugly personally and would argue that
while(true) better captures what you're actually doing. A loop with no
condition at all is horrible IMHO. It seems completely inconsistent to me that
the language would allow you to have a for loop without a condition.

Regardless of that, however, I would fully expect that if there is a difference
in code between the two in debug mode (which there shouldn't be IMHO, but
compilers don't always do what makes the most sense - especially in debug
mode) that the difference would be drowned by the contents of the loop and
wouldn't matter at all. But even if it did, I'd generally argue that coding in
a certain way just because it was slightly faster in debug mode but had zero
impact in release mode is not a good idea unless all of the considerations are
equal. And I'd definitely argue that while(true) is better than for(;;) from an
aesthetic point of view at minimum, so they definitely aren't equal.

In any case, that's my take on it.

- Jonathan M Davis


Well, it is consistent in that you can leave out the other parts in for 
too. (but those are statements, and you can almost everywhere write an 
empty statement, while there exist no empty expressions)


As to while(true) vs for(;;), in my point of view, it is the other way 
round, because how it is compiled in debug mode is really how the 
semantics of the language are: look at the condition, and if it is true, 
loop another time, if it is false, break. If you want an infinite loop, 
why bother having to write a condition to evaluate? Imho for(;;){} 
captures the meaning better than while(true){}. for(;;){} means, loop 
unconditionally (which proves insight in what it is actually doing), and 
while(true){} means 'loop until true is false', which is imo ugly for 
obvious reasons.


That is my way of thinking about aesthetics in programming.



Re: Why no (auto foo = bar) in while loops?

2011-08-24 Thread Andrej Mitrovic
Req'd: http://d.puremagic.com/issues/show_bug.cgi?id=6550


Re: Why no (auto foo = bar) in while loops?

2011-08-24 Thread Mafi

Am 24.08.2011 21:04, schrieb Timon Gehr:

On 08/24/2011 08:04 PM, Andrej Mitrovic wrote:

Here's some code that iterates through parents of some class object
until it finds an object with no parent (where parent is null):

import std.stdio;

class Foo
{
Foo parent;
int state;

this (int state) { this.state = state; }
}

void main()
{
auto foo = new Foo(0);
foo.parent = new Foo(1);
foo.parent.parent = new Foo(2);

while (true)
{
if (auto par = foo.parent)
{
writeln(par.state);
foo = par;
}
else
{
break;
}
}
}

(syntax-highlighted: http://codepad.org/8yHRmICh)

But I was hoping I could simplify this by doing:

while (auto par = foo.parent)
{
writeln(par.state);
foo = par;
}

However that doesn't work, I get back:
expression expected, not 'auto'

Is there a limitation on why this couldn't work or can this be added
to the language?


Afaics, this could be added just like it could be added for if. In fact
the compiler should be able to simply rewrite it to your first example.
I think it is worth an enhancement request, because there are situations
where this would be useful, and implementation should be trivial, if
somebody has the time. (I also think it adds to the consistency of the
language, but others may disagree.)


(btw, i always use for(;;) instead of while(true), it is usually faster
in debug mode and faster to type :))


I just have to say that it already works for 'if'. It's a great feature 
because in the body of the 'if' you know the value is non-null and 
outside,  where there could be an segfault, the variable is not visible.

I'm not really sure if it's good for 'while'.
I'm unsure because there are two somewhat natural semantics for such a 
construct.


//example
//more to the nature of while
while(auto obj = init) { work(obj); }

//1 (your interpretation)
typeof(init) obj;
while(obj = init) { work(obj); }

//2
/*
seems more natural for me because init runs only once (like any other 
init and like in 'for' or 'if')

*/
auto obj = init;
while(obj) { work(obj); }

This could confuse many people, I think. What do you think?

Mafi



Re: Why no (auto foo = bar) in while loops?

2011-08-24 Thread Timon Gehr

On 08/25/2011 12:47 AM, Mafi wrote:

Am 24.08.2011 21:04, schrieb Timon Gehr:

On 08/24/2011 08:04 PM, Andrej Mitrovic wrote:

Here's some code that iterates through parents of some class object
until it finds an object with no parent (where parent is null):

import std.stdio;

class Foo
{
Foo parent;
int state;

this (int state) { this.state = state; }
}

void main()
{
auto foo = new Foo(0);
foo.parent = new Foo(1);
foo.parent.parent = new Foo(2);

while (true)
{
if (auto par = foo.parent)
{
writeln(par.state);
foo = par;
}
else
{
break;
}
}
}

(syntax-highlighted: http://codepad.org/8yHRmICh)

But I was hoping I could simplify this by doing:

while (auto par = foo.parent)
{
writeln(par.state);
foo = par;
}

However that doesn't work, I get back:
expression expected, not 'auto'

Is there a limitation on why this couldn't work or can this be added
to the language?


Afaics, this could be added just like it could be added for if. In fact
the compiler should be able to simply rewrite it to your first example.
I think it is worth an enhancement request, because there are situations
where this would be useful, and implementation should be trivial, if
somebody has the time. (I also think it adds to the consistency of the
language, but others may disagree.)


(btw, i always use for(;;) instead of while(true), it is usually faster
in debug mode and faster to type :))


I just have to say that it already works for 'if'. It's a great feature
because in the body of the 'if' you know the value is non-null and
outside, where there could be an segfault, the variable is not visible.
I'm not really sure if it's good for 'while'.
I'm unsure because there are two somewhat natural semantics for such a
construct.

//example
//more to the nature of while
while(auto obj = init) { work(obj); }

//1 (your interpretation)
typeof(init) obj;
while(obj = init) { work(obj); }

//2
/*
seems more natural for me because init runs only once (like any other
init and like in 'for' or 'if')
*/


for(;;){int x=init;} // init runs infinitely many times


if(auto a=init){} is really more trying to solve

if(???){auto a=init;} // correct scoping but cannot refer to it in cond

than

{auto a=init; if(a){}} // correct scoping as long as there is no else

That is why there is the language construct. That it has not been 
adopted for while is because it is so much more useful for if, but I 
personally think while could/should get the possibility as well.





auto obj = init;
while(obj) { work(obj); }

This could confuse many people, I think. What do you think?



I think that by the same argument, you could say that the fact that the 
body of a looping statement is executed multiple times could confuse 
many people.


1 is more natural imho. (and 2 would be rather useless)




Re: Can we make auto return type inference a little more lax?

2011-05-17 Thread bearophile
Andrej Mitrovic:

 I don't think the compiler can figure that one out unless tuples
 become a standard language feature, not a library one. But maybe I'm
 wrong.

Turning tuples into a a _partial_ language feature will be a good thing [TM] 
for D. Tuples are useful in many situations, and they are easy to use.

Bye,
bearophile


Re: Can we make auto return type inference a little more lax?

2011-05-17 Thread Robert Clipsham

On 17/05/2011 04:40, Andrej Mitrovic wrote:

auto foo()
{
 if (1)
 {
 return [0, 0];
 }
 else
 {
 size_t one;
 size_t two;

 return [one, two];
 }
}

void main(){ }

Error: mismatched function return type inference of
uint[] and int[]

Surely the compiler can figure out a common type for these two when literals 
are involved.


I haven't tested, but make the first array [0u, 0u], that should work, 
as a work around. Make a bug report for this (maybe a patch if you feel 
up to it? :D).


--
Robert
http://octarineparrot.com/


Re: Can we make auto return type inference a little more lax?

2011-05-17 Thread Andrej Mitrovic
Bug is in bugzilla: http://d.puremagic.com/issues/show_bug.cgi?id=6022

I'm not a compiler writer though, sorry. :)


Can we make auto return type inference a little more lax?

2011-05-16 Thread Andrej Mitrovic
auto foo()
{
if (1)
{
return [0, 0];
}
else
{
size_t one;
size_t two;

return [one, two];
}
}

void main(){ }

Error: mismatched function return type inference of
uint[] and int[]

Surely the compiler can figure out a common type for these two when literals 
are involved.


Re: Can we make auto return type inference a little more lax?

2011-05-16 Thread Jonathan M Davis
On 2011-05-16 20:40, Andrej Mitrovic wrote:
 auto foo()
 {
 if (1)
 {
 return [0, 0];
 }
 else
 {
 size_t one;
 size_t two;
 
 return [one, two];
 }
 }
 
 void main(){ }
 
 Error: mismatched function return type inference of
 uint[] and int[]
 
 Surely the compiler can figure out a common type for these two when
 literals are involved.

I'm sure that auto return types are a tricky thing. The compiler also tends to 
have trouble when deducing the proper type for array literals. It's probably a 
similar problem. I believe that the compiler is supposed to take the common 
type but that it currently takes the last type in the literal as the element 
type of the array. auto return types probably have similar problems. In this 
case, it appears to be determining the types of each return value individually 
rather than collectively, and 0 defaults to int. Hence the failure. A cast 
will fix the problem. Still, it would be nice if the compiler were able to 
correctly determine that [0, 0] could be size_t[]. Open a bug report on it. It 
may or may not get fixed, and there's bound to be a limit to how smart the 
type inference can be, but Walter may very well look at improving it so that 
this works. It doesn't hurt to ask.

- Jonathan M Davis


Re: Can we make auto return type inference a little more lax?

2011-05-16 Thread Andrej Mitrovic
Yeah it's low priority, but nice to have.

Note that there's a similar issue with tuples. However since tuples
are a library type and not first-class citizens (when it comes to
return types that is), the compiler probably won't be able to figure
out a common type.

What I mean is this:

auto foo()
{
   if (1)
   {
   tuple(0, 0);
   }
   else
   {
   size_t one;
   size_t two;

   tuple(one, two);
   }
}

I don't think the compiler can figure that one out unless tuples
become a standard language feature, not a library one. But maybe I'm
wrong.


Re: Can we make auto return type inference a little more lax?

2011-05-16 Thread Jonathan M Davis
On 2011-05-16 21:31, Andrej Mitrovic wrote:
 Yeah it's low priority, but nice to have.
 
 Note that there's a similar issue with tuples. However since tuples
 are a library type and not first-class citizens (when it comes to
 return types that is), the compiler probably won't be able to figure
 out a common type.
 
 What I mean is this:
 
 auto foo()
 {
if (1)
{
tuple(0, 0);
}
else
{
size_t one;
size_t two;
 
tuple(one, two);
}
 }
 
 I don't think the compiler can figure that one out unless tuples
 become a standard language feature, not a library one. But maybe I'm
 wrong.

I'm sure that the compiler could be made to do it, but it would likely be very 
hacky to do so. It would have to realize that treating 0 as size_t for both 
arguments to tuple(0, 0) would result in the type Tuple!(size_t, size_t) which 
would be compatible with what's generated by tuple(one, two). I'm sure that it 
could be done without understanding anything about tuples specifically. It 
would just have to better understand templates. But it would likely be very 
complicated to implement for a pretty small gain, and there's a good chance 
that it would require a major redesign of that portion of the compiler. So, I 
wouldn't expect that to ever work. It should technically be possible, however.

- Jonathan M Davis


Is this an auto ref bug?

2011-04-25 Thread Andrej Mitrovic
import std.traits;

void main()
{
const wchar* t;
unqual(t);
}

auto ref unqual(T)(ref T value)
{
return cast(Unqual!T)value;
}

I've attempted to create myself an unqual function which could for example do a 
cast from const char* to char*. The above won't work though:
test.d(14): Error: variable test.unqual!(const(char*)).unqual.value cannot 
modify const

It does work if I only use auto:
auto unqual(T)(ref T value)
{
return cast(Unqual!T)value;
}

But that creates an rvalue. 

I wanted to use such a function to avoid doing explicit casts to get an 
unqualified type. For example a C function might be prototyped as:

foo(char* input);

You can't pass a const char* here, so you would have to either cast the type:
const char* str;
foo(cast(char*)str);

Or you would modify the prototype to:
foo(const(char)* input);
foo(str);  // now ok

The second choice is probably the best, since this specific C function would 
not actually modify the input. But I thought having an unqual function would 
be handy, so I could use:

foo(unqual(str));


Re: Is this an auto ref bug?

2011-04-25 Thread Jonathan M Davis
 import std.traits;
 
 void main()
 {
 const wchar* t;
 unqual(t);
 }
 
 auto ref unqual(T)(ref T value)
 {
 return cast(Unqual!T)value;
 }
 
 I've attempted to create myself an unqual function which could for example
 do a cast from const char* to char*. The above won't work though:
 test.d(14): Error: variable test.unqual!(const(char*)).unqual.value cannot
 modify const
 
 It does work if I only use auto:
 auto unqual(T)(ref T value)
 {
 return cast(Unqual!T)value;
 }
 
 But that creates an rvalue.
 
 I wanted to use such a function to avoid doing explicit casts to get an
 unqualified type. For example a C function might be prototyped as:
 
 foo(char* input);
 
 You can't pass a const char* here, so you would have to either cast the
 type: const char* str;
 foo(cast(char*)str);
 
 Or you would modify the prototype to:
 foo(const(char)* input);
 foo(str);  // now ok
 
 The second choice is probably the best, since this specific C function
 would not actually modify the input. But I thought having an unqual
 function would be handy, so I could use:
 
 foo(unqual(str));

Okay. First off, T does _not_ include the ref. So, Unqual!T is not going to be 
a ref (and it doesn't look like you can cast to ref either, which does make a 
fair bit of sense). So, the result of the cast is a temporary, and you can't 
have a ref to a temporary, so it's illegal to return auto ref from the 
function. auto works because then the return type is just wchar* - there's no 
ref there. I really don't think that it works to change the type of a ref.

- Jonathan M Davis


Re: Is this an auto ref bug?

2011-04-25 Thread Andrej Mitrovic
Oh I've just realized I was being a little silly here. I don't need
ref for pointers. Essentially I was looking to make this:

auto ref unqual(T)(ref T value)
{
   return cast(Unqual!T)value;
}

do this:

char* unqual(const char* value)
{
   return cast(char*)value;
}

Except to make it work for any type. Which is why I thought auto ref
would do it. :)


auto arr = new int[10];

2011-04-16 Thread %u
is there any different b/w:
auto arr = new int[10];
and
int[10] arr;
?


Re: auto arr = new int[10];

2011-04-16 Thread Piotr Szturmaj

%u wrote:

is there any different b/w:
auto arr = new int[10];


arr is dynamic array of int with ten elements


and
int[10] arr;
?


arr is static array of int with ten elements



Re: auto declarations

2011-01-10 Thread Lars T. Kyllingstad
On Fri, 07 Jan 2011 16:30:24 -0800, Jonathan M Davis wrote:

 On Friday, January 07, 2011 13:32:42 Ellery Newcomer wrote:
 auto a = 1, b = null;
 
 int a = 1, *b = null;
 
 
 [...]
 
 [...]
 
 However, I'm vere suprised that the first one succeeds. I think that it
 should be reported as a bug. All variables declared on the same line are
 supposed to have the same type.

If I remember correctly, TDPL explicitly states that you may use 
automatic type inference to declare variables of different types in one 
line.

-Lars


Re: auto declarations

2011-01-10 Thread Jonathan M Davis
On Monday 10 January 2011 01:59:34 Lars T. Kyllingstad wrote:
 On Fri, 07 Jan 2011 16:30:24 -0800, Jonathan M Davis wrote:
  On Friday, January 07, 2011 13:32:42 Ellery Newcomer wrote:
  auto a = 1, b = null;
  
  int a = 1, *b = null;
  
  
  [...]
  
  [...]
  
  However, I'm vere suprised that the first one succeeds. I think that it
  should be reported as a bug. All variables declared on the same line are
  supposed to have the same type.
 
 If I remember correctly, TDPL explicitly states that you may use
 automatic type inference to declare variables of different types in one
 line.

Well, it may. I don't know. I don't really believe in declaring multiple 
variables on one line in normal circumstances anyway. However, it's definitely 
an 
inconsistency in the language, and I would be inclined to argue that it should 
be removed and TDPL errata-ed if it does mention this feature. I don't see 
any 
real benefit of allowing this.

- Jonathan M Davis


Re: auto declarations

2011-01-08 Thread bearophile
Ellery Newcomer:

 int a = 1, *b = null;

Walter has disallowed code like this in D because in C it is a well known 
source of bugs (so much that C style guides strongly suggest to declare only 
each variable in a distinct statement and line of code).


 auto a = 1, b = null;

I have discussed this with other people some time ago. At first I don't like 
this, it's against the D rule of not allowing different types to be initialized 
in the same statement. It may cause some bugs.

Example: if you write a line of code like, meaning it to initialize six double 
variables both you have a bug:
auto x1=1., x2=2., x3=3., x4=4., x5=5, x6=6.;

But you are playing with fire. Better to be safer and write:
double x1=1., x2=2., x3=3., x4=4., x5=5, x6=6.;

Or even:
double x1, x2, x3, x4, x5, x6;
x1 = 1.0;
x2 = 2.0;
x3 = 3.0;
x4 = 4.0;
x5 = 5.0;
x6 = 6.0;

Or:
double[6] x;
foreach (i, ref xi; x)
xi = i + 1;

Or:
double[6] x = array(iota(1.0, 7.0));


 The first is accepted by dmd, and it should result in typeof(a) == int 
 and typeof(b) == void*. It is somewhat contradictory to the error 
 message resulting from the second:
 
 multiple declarations must have the same type, not int and int*

Error messages in DMD are a draft :-) I have opened many bug reports that 
suggest to improve them.

Here the error message is not fully correct, but I think it's acceptable. To 
improve it the D compiler may also give a number of the error, and a manual of 
the errors may explain that indeed the auto is allowed to instantiate 
different types, etc. I don't know why DMD errors are not numbered ad in C#.

Bye,
bearophile


auto declarations

2011-01-07 Thread Ellery Newcomer


auto a = 1, b = null;

int a = 1, *b = null;


The first is accepted by dmd, and it should result in typeof(a) == int 
and typeof(b) == void*. It is somewhat contradictory to the error 
message resulting from the second:


multiple declarations must have the same type, not int and int*

I am skeptical of dmd's permitting the first. Does anyone else see any 
utility in it?


Re: auto declarations

2011-01-07 Thread Piotr Szturmaj

Ellery Newcomer wrote:


auto a = 1, b = null;

int a = 1, *b = null;


The first is accepted by dmd, and it should result in typeof(a) == int
and typeof(b) == void*. It is somewhat contradictory to the error
message resulting from the second:

multiple declarations must have the same type, not int and int*

I am skeptical of dmd's permitting the first. Does anyone else see any
utility in it?


Personally, I like it. In second line you specify int type, and list of 
*int* variables.
In first line you specify list of initialized variables which types 
should be inferred automatically. I see no reason why first line should 
not be permitted.
If one would need several variables of one type, why he wouldn't specify 
exact type instead of using 'auto'?


Re: auto declarations

2011-01-07 Thread Jonathan M Davis
On Friday, January 07, 2011 13:32:42 Ellery Newcomer wrote:
 auto a = 1, b = null;
 
 int a = 1, *b = null;
 
 
 The first is accepted by dmd, and it should result in typeof(a) == int
 and typeof(b) == void*. It is somewhat contradictory to the error
 message resulting from the second:
 
 multiple declarations must have the same type, not int and int*
 
 I am skeptical of dmd's permitting the first. Does anyone else see any
 utility in it? 

The second should definitely _not_ be allowed. * definitely goes with the type 
in 
D (as it should have in C), not the variable. So, the *b = null makes no sense.

However, I'm vere suprised that the first one succeeds. I think that it should 
be 
reported as a bug. All variables declared on the same line are supposed to have 
the same type.

- Jonathan M Davis



Storing auto types in classes

2010-07-02 Thread Rob Adelberg
I'm sure this has come up before, but I want to store something like an
std.array appender in a class.  All of the examples use auto for the type but
you can't put that in a class definition, so what do you put?

Example:
class packet{...}

class A {

   packet []  packetlist;
   appender!(packet) packappender;   // wrong format

   this () {
  packetlist = new packet[0];
  packappender = appender(packetlist);
   }
   :
}

What's the format to store the appender in the class?


Re: Storing auto types in classes

2010-07-02 Thread Jonathan M Davis
On Friday, July 02, 2010 09:46:37 Rob Adelberg wrote:
 I'm sure this has come up before, but I want to store something like an
 std.array appender in a class.  All of the examples use auto for the type
 but you can't put that in a class definition, so what do you put?
 
 Example:
 class packet{...}
 
 class A {
 
packet []  packetlist;
appender!(packet) packappender;   // wrong format
 
this () {
   packetlist = new packet[0];
   packappender = appender(packetlist);
}
 
 }
 
 What's the format to store the appender in the class?

In this case, the type would be Appender!(packet[]). However, if you ever want 
to know the exact type of something, one way to do it is something like this:

writeln(typeid(appender(packelist)));

It will print out the type of the expression for you.

- Jonathan M Davis


Re: auto functions not authorized inside main?

2010-06-28 Thread Rory McGuire
On Sun, 27 Jun 2010 17:17:25 +0200, Philippe Sigaud  
philippe.sig...@gmail.com wrote:


Is it defined somewhere that auto functions are not authorized inside  
main?


void main()
{
auto fun(string s) { return s;} // this does not compile
}

error:

main.d|6|found 's' when expecting ')'|
main.d|6|semicolon expected, not ')'|
main.d|6|found ')' instead of statement|
main.d|7|unrecognized declaration|
||=== Build finished: 4 errors, 0 warnings ===|


So it's not even parsed?

I couldn't find a bugzilla entry for this and I cannot believe no one  
ever

tried to put an auto fun inside main!

Is that part of the spec?

Philippe


Hope this isn't a stupid question, but how would you access this function  
if it did work?

Would it be fun(asdf)?
Is this just shorthand for:
auto fun = function(string s) {return s;};



-Rory


Re: auto functions not authorized inside main?

2010-06-28 Thread BCS

Hello Rory,


On Sun, 27 Jun 2010 17:17:25 +0200, Philippe Sigaud
philippe.sig...@gmail.com wrote:


void main()
{
auto fun(string s) { return s;} // this does not compile
}


Hope this isn't a stupid question, but how would you access this
function
if it did work?
Would it be fun(asdf)?
Is this just shorthand for:
auto fun = function(string s) {return s;};


I would look almost the same to the user but should in fact be a normal local 
function.


--
... IXOYE





Re: auto functions not authorized inside main?

2010-06-28 Thread Rory McGuire



On Mon, 28 Jun 2010 16:07:43 +0200, Philippe Sigaud philippe.sig...@gmail.com wrote:On Mon, Jun 28, 2010 at 15:40, Rory McGuire rmcgu...@neonova.co.za wrote:

void main()
{
    auto fun(string s) { return s;} // this does not compile
}

Hope this isn't a stupid question, but how would you access this function if it did work?
Would it be fun("asdf")?Yes, that's what I had in mind. Basically, just using it as any other auto inner function. void main(){auto fun(string s) { return s;}auto s = fun("abc");
auto t = fun("def");} 
Is this just shorthand for:
auto fun = function(string s) {return s;};That'd be about the same, yes. Fact is, I don't really _need_ this, I was just astonished to be bitten by this.Why can I do
void main(){    string foo(string s) { return s;}}and notvoid main(){    auto foo(string s) { return s;}} ?***OK, I tested it some more, and it seems you cannot define auto function inside any other function. So auto function cannot be inner functions. I'm quite astonished I never did that when using D, but OK.
I filed a bug report, at least to update the docs. It's bug #4401.Philippe
Right! I get what you're saying, didn't realise because it was formatted more how I would format a anon delegate.You're saying "surely the compiler can infer the return type for a inner function just as much as it can infer the return type of a normal function..Must be a compiler bug.-Rory

Re: auto functions not authorized inside main?

2010-06-28 Thread Rory McGuire

On Mon, 28 Jun 2010 16:01:46 +0200, BCS n...@anon.com wrote:


Hello Rory,


On Sun, 27 Jun 2010 17:17:25 +0200, Philippe Sigaud
philippe.sig...@gmail.com wrote:


void main()
{
auto fun(string s) { return s;} // this does not compile
}


Hope this isn't a stupid question, but how would you access this
function
if it did work?
Would it be fun(asdf)?
Is this just shorthand for:
auto fun = function(string s) {return s;};


I would look almost the same to the user but should in fact be a normal  
local function.




Ye I got it now.

My brain was interpreting it as a delegate that wasn't being assigned to  
anything for some reason.


Now I get that it is just return type inferance doesn't work for inner  
functions.


-Rory


auto functions not authorized inside main?

2010-06-27 Thread Philippe Sigaud
Is it defined somewhere that auto functions are not authorized inside main?

void main()
{
auto fun(string s) { return s;} // this does not compile
}

error:

main.d|6|found 's' when expecting ')'|
main.d|6|semicolon expected, not ')'|
main.d|6|found ')' instead of statement|
main.d|7|unrecognized declaration|
||=== Build finished: 4 errors, 0 warnings ===|


So it's not even parsed?

I couldn't find a bugzilla entry for this and I cannot believe no one ever
tried to put an auto fun inside main!

Is that part of the spec?

Philippe


Re: auto functions not authorized inside main?

2010-06-27 Thread bearophile
Philippe Sigaud:
 I couldn't find a bugzilla entry for this and I cannot believe no one ever
 tried to put an auto fun inside main!

Maybe auto funcs are seen as instantiated templates, and templates can't be 
defined inside functions. Anyway, I think you can file this as enhancement 
request.

Bye,
bearophile


Re: Descent eclipse plugin - auto code completion

2009-11-05 Thread Joel Christensen
Do you have something in the Error Log (Window - Show View - Error 
Log)? How is your project configured? Do you have phobos or Tango in the 
include path?


My Eclipse doesn't have a thing called Error Log. I can't see more than 
'D Build Path' to configure.


I've been testing with Tangos 'Stdout'. It's been working in my little 
test programs, but not aways with a proper program, I just get the 
Object class stuff, not Stdouts stuff. Other things work like structs 
and 'this.' and other classes work. Even other Tango class's work (if I 
put the full name).


I'm using 'tango\import' in my include path.

Another note: I couldn't get an external software to compile from 
eclipse either.


Re: Descent eclipse plugin - auto code completion

2009-11-03 Thread Ary Borenszweig

Joel Christensen wrote:
I've got one project working ok, but not another. Things like working at 
the start of the main function but not at the end, and not in other 
functions.


Hi Joel,

Do you have something in the Error Log (Window - Show View - Error 
Log)? How is your project configured? Do you have phobos or Tango in the 
include path?


<    2   3   4   5   6   7