Re: auto limitation?
My final implementation: http://dpaste.dzfl.pl/4d2a045a Any suggestions?
Re: auto limitation?
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?
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?
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?
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?
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?
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?
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?
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?
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?
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?
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?
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?
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?
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?
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?
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?
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?
There is no compiler bug. You cannot pass immutable/rvalue by reference to mutable.
Re: Optional extra return value? Multiple return values with auto?
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?
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?
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?
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?
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?
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?
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...
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...
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...
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...
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...
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
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
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
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?
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?
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?
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?
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?
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
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
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
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
The type has to be deduced anyway for type checking the assignment/initialization. Makes sense. Overseen that.
Re: auto
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
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
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?
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?
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?
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?
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?
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?
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?
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?
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?
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?
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?
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?
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?
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?
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?
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?
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?
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?
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?
Req'd: http://d.puremagic.com/issues/show_bug.cgi?id=6550
Re: Why no (auto foo = bar) in while loops?
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?
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?
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?
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?
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?
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?
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?
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?
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?
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?
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?
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];
is there any different b/w: auto arr = new int[10]; and int[10] arr; ?
Re: auto arr = new int[10];
%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
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
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
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
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
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
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
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
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?
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?
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?
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?
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?
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?
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
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
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?