digitalmars.D.learn - Why I could not cast string to int?
- xancorreu (26/26) Feb 02 2012 Hi,
- David Nadlinger (4/6) Feb 02 2012 std.conv.to!int(…) or parse().
- xancorreu (7/13) Feb 02 2012 to!int gives me this error:
- Adam D. Ruppe (7/10) Feb 02 2012 args[0] is the name of your program.
- xancorreu (3/13) Feb 02 2012 Why cast(int) does not work and I have to call another function?
- =?UTF-8?B?QWxleCBSw7hubmUgUGV0ZXJzZW4=?= (5/24) Feb 02 2012 Because D is a strongly typed language. Casting a string to an int
- bearophile (1/30) Feb 02 2012
- bearophile (6/8) Feb 02 2012 I think that D being strongly typed is not significant here. When you ca...
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (22/31) Feb 02 2012 I first read it as if you were saying that dynamic cast is the only one
- Jonathan M Davis (10/29) Feb 02 2012 Very true. However, std.conv.to will use a user-defined opCast if there ...
- Jonathan M Davis (17/38) Feb 02 2012 Casts generally reintrepret what they're converting on some level (thoug...
- xancorreu (14/22) Feb 02 2012 Okay, very useful answer!
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (13/27) Feb 02 2012 I haven't used it but there is Orange:
- Jonathan M Davis (56/92) Feb 02 2012 I'd be very surprised if Orange could help here (though I've never used ...
- xancorreu (4/34) Feb 03 2012 For my it could be put in a outside library, not in the class of the
- xancorreu (6/13) Feb 03 2012 I think it as a tool, not solve-everything-thing, it just a tool for
- xancorreu (21/21) Feb 02 2012 I get "segment violation" error with ./factorial 400000
- bearophile (28/30) Feb 02 2012 You are having a stack overflow. DMD currently doesn't print a good mess...
- xancorreu (7/37) Feb 02 2012 Thank you very much for recode this. But you "only" put a "in" in
- Timon Gehr (7/61) Feb 02 2012 It is not. He just added some stylistic changes that don't change the
- H. S. Teoh (14/22) Feb 02 2012 [...]
- Timon Gehr (12/33) Feb 02 2012 This is not a tail-recursive function. And neither is recFactorial, my
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (3/9) Feb 02 2012 Sorry, wrong newsgroup. alt.comp.lang.perl is around the corner. :p
- H. S. Teoh (6/17) Feb 02 2012 [...]
- H. S. Teoh (9/15) Feb 02 2012 Whoa. A caching recursive definition of fibonacci. Impressive!
- H. S. Teoh (8/11) Feb 02 2012 [...]
- bearophile (4/7) Feb 02 2012 It wasn't meant to improve performance. "in" turns a function argument t...
- Jonathan M Davis (12/25) Feb 02 2012 in is pointless on value types. All it does is make the function paramet...
- bearophile (14/21) Feb 03 2012 Having const value types is useful because you can't change them later i...
- Artur Skawina (11/21) Feb 03 2012 BTW, scope should have been the default for *all* reference type functio...
- =?UTF-8?B?QWxleCBSw7hubmUgUGV0ZXJzZW4=?= (7/28) Feb 03 2012 It is not that simple.
- Artur Skawina (8/37) Feb 03 2012 It's about enabling the optimization for as much code as possible. And p...
- =?UTF-8?B?QWxleCBSw7hubmUgUGV0ZXJzZW4=?= (6/43) Feb 03 2012 Well, you would have to mark methods as scope too, as they could be
- bearophile (4/7) Feb 03 2012 Maybe this is a topic worth discussing in the main D newsgroup (and mayb...
- Artur Skawina (10/48) Feb 03 2012 Actually, passing 'this' to some "some arbitrary code" isn't a problem, ...
- Timon Gehr (5/26) Feb 03 2012 I totally agree. Most function arguments are not escaped. However, it is...
- bearophile (6/8) Feb 03 2012 I'd like to ask this to be valid, to shorten my code:
- Daniel Murphy (8/11) Feb 03 2012 Yes =)
- Artur Skawina (44/64) Feb 04 2012 There are currently two problems with using "in": a) the one mentioned, ...
- Timon Gehr (6/66) Feb 04 2012 I think this is covered in this issue:
- Artur Skawina (23/109) Feb 04 2012 Apparently, there's already a bug open for everything.
- Timon Gehr (8/117) Feb 04 2012 Well, string = string ~ const(char)[] and char[] = string ~
- Artur Skawina (4/45) Feb 04 2012 Please do; i've been avoiding filing dmd bugs, because i'm only using gd...
- xancorreu (3/10) Feb 03 2012 Mmm. Thanks. It remembers me val in scala ;-)
- Timon Gehr (17/38) Feb 02 2012 import std.stdio, std.bigint, std.conv;
- bearophile (4/7) Feb 02 2012 Is it possible to create a function attribute like @tail_recursive that ...
- Jonathan M Davis (5/13) Feb 02 2012 I suspect that Walter would feel the same way about that that he feels a...
- xancorreu (3/9) Feb 02 2012 Sorry, if condition was wrong. conv.to!int is perfect!
- Tobias Pankrath (1/9) Feb 02 2012
- Jonathan M Davis (4/9) Feb 03 2012 That would destroy slicing. I'm firmly of the opinion that scope should ...
- Timon Gehr (2/11) Feb 03 2012 It could be enabled on by type basis.
- Artur Skawina (36/45) Feb 03 2012 Well, not doing it destroys performance. [1] It's a trade-off. Also, i d...
- Jonathan M Davis (11/23) Feb 03 2012 Fastest and easiest would be to simply do
Hi, In this code, how can I cast the args[0] string to int for computing factorial(args[0])? import std.stdio, std.bigint, std.string, std.conv, std.stream; BigInt recFactorial(int n) { if (n == 0) return BigInt(1); else return (BigInt(n) * recFactorial(n - 1)); } void main(string[] args) { if (args.length == 2) writeln("Factorial requires a number"); else try { writeln(recFactorial(cast(int) args[1])); } catch { writeln("Error"); } } I receive: $ gdmd-4.6 factorial.d factorial.d: In function ‘main’: factorial.d:15:0: error: cannot cast expression of type string to int Thanks in advance, Xan.
Feb 02 2012
On 2/2/12 1:35 PM, xancorreu wrote:In this code, how can I cast the args[0] string to int for computing factorial(args[0])?std.conv.to!int(…) or parse(). Hope this helps, David
Feb 02 2012
Al 02/02/12 16:58, En/na David Nadlinger ha escrit:On 2/2/12 1:35 PM, xancorreu wrote:to!int gives me this error: $ ./factorial 222 Factorial requires a number parse() where is the doc? Thanks in advance, Xan.In this code, how can I cast the args[0] string to int for computing factorial(args[0])?std.conv.to!int(…) or parse().Hope this helps, David
Feb 02 2012
On Thursday, 2 February 2012 at 16:21:39 UTC, xancorreu wrote:$ ./factorial 222 Factorial requires a numberargs[0] is the name of your program. (The first thing you typed on the command line.) Use args[1] to get that number.parse() where is the doc?http://www.d-programming-language.org/phobos/std_conv.html#parse to!int(args[1]) is probably what you want here though.
Feb 02 2012
Why cast(int) does not work and I have to call another function? Thanks, Al 02/02/12 17:24, En/na Adam D. Ruppe ha escrit:On Thursday, 2 February 2012 at 16:21:39 UTC, xancorreu wrote:$ ./factorial 222 Factorial requires a numberargs[0] is the name of your program. (The first thing you typed on the command line.) Use args[1] to get that number.parse() where is the doc?http://www.d-programming-language.org/phobos/std_conv.html#parse to!int(args[1]) is probably what you want here though.
Feb 02 2012
On 02-02-2012 17:26, xancorreu wrote:Why cast(int) does not work and I have to call another function? Thanks, Al 02/02/12 17:24, En/na Adam D. Ruppe ha escrit:Because D is a strongly typed language. Casting a string to an int doesn't make sense from a type system perspective. -- - AlexOn Thursday, 2 February 2012 at 16:21:39 UTC, xancorreu wrote:$ ./factorial 222 Factorial requires a numberargs[0] is the name of your program. (The first thing you typed on the command line.) Use args[1] to get that number.parse() where is the doc?http://www.d-programming-language.org/phobos/std_conv.html#parse to!int(args[1]) is probably what you want here though.
Feb 02 2012
Alex Rønne Petersen Wrote:On 02-02-2012 17:26, xancorreu wrote:Why cast(int) does not work and I have to call another function? Thanks, Al 02/02/12 17:24, En/na Adam D. Ruppe ha escrit:Because D is a strongly typed language. Casting a string to an int doesn't make sense from a type system perspective. -- - AlexOn Thursday, 2 February 2012 at 16:21:39 UTC, xancorreu wrote:$ ./factorial 222 Factorial requires a numberargs[0] is the name of your program. (The first thing you typed on the command line.) Use args[1] to get that number.parse() where is the doc?http://www.d-programming-language.org/phobos/std_conv.html#parse to!int(args[1]) is probably what you want here though.
Feb 02 2012
Alex R. Petersen: (Sorry for my last blank answer.)Because D is a strongly typed language. Casting a string to an int doesn't make sense from a type system perspective.I think that D being strongly typed is not significant here. When you cast a string to char* you are casting a 2 words struct to a single pointer, when you cast a char* to long on a 32 bit system you are changing type and size, etc. The purpose of cast() is right to break the strongly typed nature of the D type system. So I think a better answer is that D designers have decided to give different purposes to to!X(y) and cast(X)x. The cast() is meant to be a light and very quick conversion, usually done at compile-time (unless it's a dynamic cast), to throw no exceptions, and generally unsafe. to!() is meant to be safer, to throw exceptions if the conversion fails, and it uses library code, so it's more flexible, and often performs some work at run-time too. Given such design a string->int conversion is better left to to!(). Bye, bearophile
Feb 02 2012
On 02/02/2012 10:18 AM, bearophile wrote:The cast() is meant to be a light and very quick conversion, usually done at compile-time (unless it's a dynamic cast),I first read it as if you were saying that dynamic cast is the only one that is done at runtime. Actually many casts are done at runtime even for fundamental types.to throw no exceptions, and generally unsafe.Just to be complete: You mean it for fundamental types. Of course user types' opCast operators may throw: import std.exception; class C { int opCast(T : int)() const { enforce(false, "Not good."); return 42; } } void main() { auto c = new C; auto i = cast(int)c; }to!() is meant to be safer, to throw exceptions if the conversion fails, and it uses library code, so it's more flexible, and often performs some work at run-time too. Given such design a string->int conversion is better left to to!().Agreed.Bye, bearophileAli
Feb 02 2012
On Thursday, February 02, 2012 10:36:06 Ali Çehreli wrote:Just to be complete: You mean it for fundamental types. Of course user types' opCast operators may throw: import std.exception; class C { int opCast(T : int)() const { enforce(false, "Not good."); return 42; } } void main() { auto c = new C; auto i = cast(int)c; }Very true. However, std.conv.to will use a user-defined opCast if there is one, and so it's generally better to use std.conv.to with user-defined opCasts than to cast explicitly. The risk of screwing it up is lower too, since then you don't have to worry about the built-in cast accidentally being used instead of your user-defined opCast if you screwed up - e.g. by declaring int opcast(T : int)() const { .. } Though in many cases, the compiler will still catch that for you (not all though). - Jonathan M Davis
Feb 02 2012
On Thursday, February 02, 2012 13:18:17 bearophile wrote:Alex R. Petersen: (Sorry for my last blank answer.)Casts generally reintrepret what they're converting on some level (though not necessarily as exactly as C++'s reinterpret_cast does). The types involved are always similar and any converting that takes place is incredibly straightforward. They don't really convert in the sense of creating one type from another. It's closer to treating a type like another type than actually converting it. Strings are not at all similar to ints. One is an array. The other is a single integral value. So, it makes no sense to treat one like the other. std.conv.to, on the other hand, outright converts. It does what makes the most sense when trying to take a value of one type and create a value of another type from it. The two types may have absolutely nothing to do with each other. It's closer to constructing a value of one type from a value of another type than treating one like the other. So, as Bearophile says, the purposes of casting and std.conv.to are very different. - Jonathan M DavisBecause D is a strongly typed language. Casting a string to an int doesn't make sense from a type system perspective.I think that D being strongly typed is not significant here. When you cast a string to char* you are casting a 2 words struct to a single pointer, when you cast a char* to long on a 32 bit system you are changing type and size, etc. The purpose of cast() is right to break the strongly typed nature of the D type system. So I think a better answer is that D designers have decided to give different purposes to to!X(y) and cast(X)x. The cast() is meant to be a light and very quick conversion, usually done at compile-time (unless it's a dynamic cast), to throw no exceptions, and generally unsafe. to!() is meant to be safer, to throw exceptions if the conversion fails, and it uses library code, so it's more flexible, and often performs some work at run-time too. Given such design a string->int conversion is better left to to!().
Feb 02 2012
Al 02/02/12 19:18, En/na bearophile ha escrit:Alex R. Petersen: (Sorry for my last blank answer.)Okay, very useful answer! Can I say "serialize the first, second and third arguments as Class Person"? I mean, if you define a class Person like: class Person { string name uint age dead bool } could you serialize the input from console, like Std.in.serialize(Person, args(0), args(1), args(2))? You could do that "manually" checking each paramm, but it's a tedious task. Thanks, Xan.Because D is a strongly typed language. Casting a string to an int doesn't make sense from a type system perspective.I think that D being strongly typed is not significant here. When you cast a string to char* you are casting a 2 words struct to a single pointer, when you cast a char* to long on a 32 bit system you are changing type and size, etc. The purpose of cast() is right to break the strongly typed nature of the D type system. So I think a better answer is that D designers have decided to give different purposes to to!X(y) and cast(X)x. The cast() is meant to be a light and very quick conversion, usually done at compile-time (unless it's a dynamic cast), to throw no exceptions, and generally unsafe. to!() is meant to be safer, to throw exceptions if the conversion fails, and it uses library code, so it's more flexible, and often performs some work at run-time too. Given such design a string->int conversion is better left to to!(). Bye, bearophile
Feb 02 2012
On 02/02/2012 11:00 AM, xancorreu wrote:Al 02/02/12 19:18, En/na bearophile ha escrit:Can I say "serialize the first, second and third arguments as Class Person"? I mean, if you define a class Person like: class Person { string name uint age dead bool } could you serialize the input from console, like Std.in.serialize(Person, args(0), args(1), args(2))?I haven't used it but there is Orange: https://github.com/jacob-carlborg/orange I think it will be included in Phobos.You could do that "manually" checking each paramm, but it's a tedioustask. If the input is exactly in the format that a library like Orange expects, then it's easy. To me, constructing an object from user input is conceptually outside of OO, because there is no object at that point yet. It makes sense to me to read the input and then make an object from the input. Depending on the design, the input may be rejected by the function that reads the input, by the constructor of the type, or by both.Thanks, Xan.Ali
Feb 02 2012
On Thursday, February 02, 2012 11:11:28 Ali Çehreli wrote:On 02/02/2012 11:00 AM, xancorreu wrote:I'd be very surprised if Orange could help here (though I've never used it, so I don't know exactly what it can it). Normally, when you talk about serialization, you talk about serializing an object to another format (generally a binary format of some kind) and restoring it later, not creating an object. It's pretty much expected that if you're going to create an object from user input, you're going to have to do it yourself. That's perfectly normal. What makes the most sense for each application varies too much to really standardize it - especially when you consider error handling. What happens when not enough arguments were passed to the application? What if the values given can't be converted to the desired types? etc. If you have class Person { string name; uint age; bool dead; } I'd expect something like: int main(string[] args) { if(args.length != 4) { stderr.writeln("Not enough arguments."); return -1; } auto name = args[1]; uint age; try age = to!uint(args[2]); catch(ConvException ce) { stderr.writefln("[%s] is not a valid age.", args[2]); return -1; } bool dead; try dead = to!bool(args[3]); catch(ConvException ce) { stderr.writefln("[%s] is not a valid boolean value. It must be true or false.", args[3]); return -1; } auto person = Person(name, age, dead); //... return 0; } And whether that's the best way to handle it depends on what you're trying to do in terms of user input and error messages. How on earth is all of that going to be handled generically? It all depends on what the programmer is trying to do. Switching to use command-line switches and getopt would help some, but you still have to deal with the error messages yourself. Creating the Person is the easy part. - Jonathan M DavisAl 02/02/12 19:18, En/na bearophile ha escrit: Can I say "serialize the first, second and third arguments as Class Person"? I mean, if you define a class Person like: class Person { string name uint age dead bool } could you serialize the input from console, like Std.in.serialize(Person, args(0), args(1), args(2))?I haven't used it but there is Orange: https://github.com/jacob-carlborg/orange I think it will be included in Phobos.You could do that "manually" checking each paramm, but it's a tedioustask. If the input is exactly in the format that a library like Orange expects, then it's easy. To me, constructing an object from user input is conceptually outside of OO, because there is no object at that point yet. It makes sense to me to read the input and then make an object from the input. Depending on the design, the input may be rejected by the function that reads the input, by the constructor of the type, or by both.
Feb 02 2012
Al 02/02/12 20:11, En/na Ali Çehreli ha escrit:On 02/02/2012 11:00 AM, xancorreu wrote:For my it could be put in a outside library, not in the class of the object. And if it's well designed, it could be informed of all exceptions....Al 02/02/12 19:18, En/na bearophile ha escrit:Can I say "serialize the first, second and third arguments as Class Person"? I mean, if you define a class Person like: class Person { string name uint age dead bool } could you serialize the input from console, like Std.in.serialize(Person, args(0), args(1), args(2))?I haven't used it but there is Orange: https://github.com/jacob-carlborg/orange I think it will be included in Phobos.You could do that "manually" checking each paramm, but it's atedious task. If the input is exactly in the format that a library like Orange expects, then it's easy. To me, constructing an object from user input is conceptually outside of OO, because there is no object at that point yet. It makes sense to me to read the input and then make an object from the input.Depending on the design, the input may be rejected by the function that reads the input, by the constructor of the type, or by both.Thanks, Xan.Ali
Feb 03 2012
Al 02/02/12 20:40, En/na Jonathan M Davis ha escrit:And whether that's the best way to handle it depends on what you're trying to do in terms of user input and error messages. How on earth is all of that going to be handled generically? It all depends on what the programmer is trying to do. Switching to use command-line switches and getopt would help some, but you still have to deal with the error messages yourself. Creating the Person is the easy part. - Jonathan M DavisI think it as a tool, not solve-everything-thing, it just a tool for easy your job. Yeah, you could manually do that (thanks for the code) but really you, maybe, want to do it _fastest_ and _easyest_. Thanks, Xan.
Feb 03 2012
I get "segment violation" error with ./factorial 400000 How can I resolve it? My code is: import std.stdio, std.bigint, std.string, std.conv, std.stream; BigInt recFactorial(int n) { if (n == 0) return BigInt(1); else return (BigInt(n) * recFactorial(n - 1)); } void main(string[] args) { if (args.length != 2) writeln("Factorial requires a number"); else try { writeln(recFactorial(std.conv.to!int(args[1]))); } catch { writeln("Error"); } } Thanks a lot,
Feb 02 2012
xancorreu:I get "segment violation" error with ./factorial 400000 How can I resolve it?You are having a stack overflow. DMD currently doesn't print a good message because of this regression that is being worked on: http://d.puremagic.com/issues/show_bug.cgi?id=6088 On Windows with DMD you increase the stack like this: dmd -L/STACK:100000000 -run test2.d 400000 > result.txt If it goes in overflow still, increase the stack some more. But it will take a long time to compute the result even with the latest 2.058head with improved GC because the algorithm you have used to compute the factorial is very bad. I have rewritten your code like this: import std.stdio, std.bigint, std.conv, std.exception; BigInt recFactorial(in int n) { if (n == 0) return BigInt(1); else return BigInt(n) * recFactorial(n - 1); } void main(string[] args) { if (args.length != 2) { writeln("Factorial requires a number."); } else { try { writeln(recFactorial(to!int(args[1]))); } catch (ConvException e) { writeln("Error"); } } } Note the usage of ConvException, it's a very good practice to never use a generic "gotta catch them all" expression, because it leads to hiding other bugs in your code, and this is a source for troubles. Bye, bearophile
Feb 02 2012
Al 02/02/12 19:30, En/na bearophile ha escrit:xancorreu:Thank you very much for recode this. But you "only" put a "in" in recFactorial function argument. What this mean? **Why** this is more efficient than mine? For the other hand, how can increase the stack in linux? Thanks, Xan.I get "segment violation" error with ./factorial 400000 How can I resolve it?You are having a stack overflow. DMD currently doesn't print a good message because of this regression that is being worked on: http://d.puremagic.com/issues/show_bug.cgi?id=6088 On Windows with DMD you increase the stack like this: dmd -L/STACK:100000000 -run test2.d 400000> result.txt If it goes in overflow still, increase the stack some more. But it will take a long time to compute the result even with the latest 2.058head with improved GC because the algorithm you have used to compute the factorial is very bad. I have rewritten your code like this: import std.stdio, std.bigint, std.conv, std.exception; BigInt recFactorial(in int n) { if (n == 0) return BigInt(1); else return BigInt(n) * recFactorial(n - 1); } void main(string[] args) { if (args.length != 2) { writeln("Factorial requires a number."); } else { try { writeln(recFactorial(to!int(args[1]))); } catch (ConvException e) { writeln("Error"); } } } Note the usage of ConvException, it's a very good practice to never use a generic "gotta catch them all" expression, because it leads to hiding other bugs in your code, and this is a source for troubles. Bye, bearophile
Feb 02 2012
On 02/02/2012 08:04 PM, xancorreu wrote:Al 02/02/12 19:30, En/na bearophile ha escrit:It is not. He just added some stylistic changes that don't change the code's semantics in any way.xancorreu:Thank you very much for recode this. But you "only" put a "in" in recFactorial function argument. What this mean? **Why** this is more efficient than mine?I get "segment violation" error with ./factorial 400000 How can I resolve it?You are having a stack overflow. DMD currently doesn't print a good message because of this regression that is being worked on: http://d.puremagic.com/issues/show_bug.cgi?id=6088 On Windows with DMD you increase the stack like this: dmd -L/STACK:100000000 -run test2.d 400000> result.txt If it goes in overflow still, increase the stack some more. But it will take a long time to compute the result even with the latest 2.058head with improved GC because the algorithm you have used to compute the factorial is very bad. I have rewritten your code like this: import std.stdio, std.bigint, std.conv, std.exception; BigInt recFactorial(in int n) { if (n == 0) return BigInt(1); else return BigInt(n) * recFactorial(n - 1); } void main(string[] args) { if (args.length != 2) { writeln("Factorial requires a number."); } else { try { writeln(recFactorial(to!int(args[1]))); } catch (ConvException e) { writeln("Error"); } } } Note the usage of ConvException, it's a very good practice to never use a generic "gotta catch them all" expression, because it leads to hiding other bugs in your code, and this is a source for troubles. Bye, bearophileFor the other hand, how can increase the stack in linux? Thanks, Xan.I don't know, but it is best to just rewrite the code so that it does not use recursion. (This kind of problem is exactly the reason why any language standard should mandate tail call optimization.)
Feb 02 2012
On Thu, Feb 02, 2012 at 10:55:06PM +0100, Timon Gehr wrote:On 02/02/2012 08:04 PM, xancorreu wrote:[...][...]For the other hand, how can increase the stack in linux?I don't know, but it is best to just rewrite the code so that it does not use recursion. (This kind of problem is exactly the reason why any language standard should mandate tail call optimization.)Doesn't help badly-chosen implementations like: int fib(int n) { if (n <= 2) return 1; else return fib(n-2) + fib(n+1); } There's not much the compiler can do to offset programmers choosing the wrong algorithm for the job. It can't replace educating programmers to not implement things a certain way unless they have to. T -- Philosophy: how to make a career out of daydreaming.
Feb 02 2012
On 02/02/2012 11:47 PM, H. S. Teoh wrote:On Thu, Feb 02, 2012 at 10:55:06PM +0100, Timon Gehr wrote:This is not a tail-recursive function. And neither is recFactorial, my bad. Anyway, my point was that the compiler should not generate code that blows up on a (in principle) perfectly sane implementation.On 02/02/2012 08:04 PM, xancorreu wrote:[...][...]For the other hand, how can increase the stack in linux?I don't know, but it is best to just rewrite the code so that it does not use recursion. (This kind of problem is exactly the reason why any language standard should mandate tail call optimization.)Doesn't help badly-chosen implementations like: int fib(int n) { if (n<= 2) return 1; else return fib(n-2) + fib(n+1); }There's not much the compiler can do to offset programmers choosing the wrong algorithm for the job.Agreed.It can't replace educating programmers to not implement things a certain way unless they have to. TOr unless they feel like it. LList!ulong fib(){ LList!ulong r; r=cons(st(1UL),cons(st(1UL),lz(()=>zipWith((Lazy!ulong a, Lazy!ulong b)=>lz(()=>a+b),r,r.tail)()))); return r; }
Feb 02 2012
On 02/02/2012 03:10 PM, Timon Gehr wrote:LList!ulong fib(){ LList!ulong r; r=cons(st(1UL),cons(st(1UL),lz(()=>zipWith((Lazy!ulong a, Lazy!ulong b)=>lz(()=>a+b),r,r.tail)()))); return r; }Sorry, wrong newsgroup. alt.comp.lang.perl is around the corner. :p Ali
Feb 02 2012
On Thu, Feb 02, 2012 at 03:26:52PM -0800, Ali Çehreli wrote:On 02/02/2012 03:10 PM, Timon Gehr wrote:[...] You mean alt.comp.lang.lisp. :-) T -- Why waste time learning, when ignorance is instantaneous? -- Hobbes, from Calvin & HobbesLList!ulong fib(){ LList!ulong r; r=cons(st(1UL),cons(st(1UL),lz(()=>zipWith((Lazy!ulong a, Lazy!ulong b)=>lz(()=>a+b),r,r.tail)()))); return r; }Sorry, wrong newsgroup. alt.comp.lang.perl is around the corner. :p
Feb 02 2012
On Fri, Feb 03, 2012 at 12:10:01AM +0100, Timon Gehr wrote: [...]LList!ulong fib(){ LList!ulong r; r=cons(st(1UL),cons(st(1UL),lz(()=>zipWith((Lazy!ulong a, Lazy!ulong b)=>lz(()=>a+b),r,r.tail)()))); return r; }Whoa. A caching recursive definition of fibonacci. Impressive! Now I wonder if we can do this with the Ackermann function... ;-) T -- "640K ought to be enough" -- Bill G., 1984. "The Internet is not a primary goal for PC usage" -- Bill G., 1995. "Linux has no impact on Microsoft's strategy" -- Bill G., 1999.
Feb 02 2012
On Thu, Feb 02, 2012 at 02:47:22PM -0800, H. S. Teoh wrote: [...]int fib(int n) { if (n <= 2) return 1; else return fib(n-2) + fib(n+1);[...] Ugh. That should be fib(n-1), not fib(n+1). But no matter, such a thing shouldn't ever be actually written and compiled, as Andrei says. :) T -- Change is inevitable, except from a vending machine.
Feb 02 2012
xancorreu:But you "only" put a "in" in recFactorial function argument. What this mean? **Why** this is more efficient than mine?It wasn't meant to improve performance. "in" turns a function argument to "input only" (and eventually scoped too). Generally when you program in D2 it's a good practice to use immutability where you can and where this doesn't cause other performance or typing problems. Immutability avoids bugs, allows a stronger purity (and I have seen DMD is often able to compiler a little more efficient program if you use immutability/constants everywhere they are a good fit). So 95% of the arguments of your program are better tagged with "in". Bye, bearophile
Feb 02 2012
On Thursday, February 02, 2012 18:14:25 bearophile wrote:xancorreu:in is pointless on value types. All it does is make the function parameter const, which really doesn't do much for you, and in some instances, is really annoying. Personally, I see no point in using in unless the parameter is a reference type, and even then, it's often a bad idea with reference types, because in is really const scope, and the scope is problematic if you want to return anything from that variable. It's particularly problematic with arrays, since it's frequently desirable to return slices of them, and scope (and therefore in) would prevent that. It's useful in some instances (particularly with delegates), but I'd use in _very_ sparingly. It's almost always more trouble than it's worth IMHO. - Jonathan M DavisBut you "only" put a "in" in recFactorial function argument. What this mean? **Why** this is more efficient than mine?It wasn't meant to improve performance. "in" turns a function argument to "input only" (and eventually scoped too). Generally when you program in D2 it's a good practice to use immutability where you can and where this doesn't cause other performance or typing problems. Immutability avoids bugs, allows a stronger purity (and I have seen DMD is often able to compiler a little more efficient program if you use immutability/constants everywhere they are a good fit). So 95% of the arguments of your program are better tagged with "in".
Feb 02 2012
Jonathan M Davis:in is pointless on value types. All it does is make the function parameter const, which really doesn't do much for you, and in some instances, is really annoying.Having const value types is useful because you can't change them later inside the method. This helps you avoid bugs like: void foo(int n) { // uses n here // modifies n here by mistake // uses n here again, assuming it's the 'real' n argument } When you program you think of arguments as the inputs of your algorithm, so if you mutate them by mistake, this sometimes causes bugs if later you think they are the real inputs of your algorithm still. Generally in D code all variables that can be const/immutable should be const/immutable, unless this causes problems or is impossible or it causes signficant performance troubles. This avoids some bugs, helps DMD optimize better (I have seen this), and helps the person that reads the code to understand the code better (because he/she/shi is free to focus on just the mutable variables). It's better to have const function arguments, unless this is not possible, or for not common situations where a mutable input helps you optimize your algorithm better (especially if the profiler has told you so).Personally, I see no point in using in unless the parameter is a reference type, and even then, it's often a bad idea with reference types, because in is really const scope, and the scope is problematic if you want to return anything from that variable.Think of returning a part of a mutable input argument as an optimization, to be used when you know you need the extra speed. Otherwise where performance is not a problem it's often safer to return a const value or to return something new created inside the function/method. This programming style avoids many mistakes (it's useful in Java coding too). From what I've seen, in my D code only a small percentage of the program lines need to be optimized and use C-style coding. For most of the lines of code a more functional D style is enough, and safer. The idea is "mutability where needed, and a bit more functional-style everywhere else" :-) Bye, bearophile
Feb 03 2012
On 02/03/12 00:20, Jonathan M Davis wrote:in is pointless on value types. All it does is make the function parameter const, which really doesn't do much for you, and in some instances, is really annoying. Personally, I see no point in using in unless the parameter is a reference type, and even then, it's often a bad idea with reference types, because in is really const scope, and the scope is problematic if you want to return anything from that variable. It's particularly problematic with arrays, since it's frequently desirable to return slices of them, and scope (and therefore in) would prevent that. It's useful in some instances (particularly with delegates), but I'd use in _very_ sparingly. It's almost always more trouble than it's worth IMHO.BTW, scope should have been the default for *all* reference type function arguments, with an explicit modifier, say "esc", required to let the thing escape. It's an all-or-nothing thing, just like immutable strings - not using it everywhere is painful, but once you switch everything over you get the benefits. If it isn't obvious why - GC. The compiler can optimize the cases where it knows a newly allocated object can't escape and reduce or omit the GC overhead. And yes, it can also do this automatically - but that requires analyzing the whole call chain, which is a) not always possible and b) much more expensive. artur
Feb 03 2012
On 03-02-2012 11:08, Artur Skawina wrote:On 02/03/12 00:20, Jonathan M Davis wrote:It is not that simple. If the class's constructor passes 'this' off to some arbitrary code, this optimization breaks completely. You would need whole-program analysis to have the slightest hope of doing this optimization correctly. -- - Alexin is pointless on value types. All it does is make the function parameter const, which really doesn't do much for you, and in some instances, is really annoying. Personally, I see no point in using in unless the parameter is a reference type, and even then, it's often a bad idea with reference types, because in is really const scope, and the scope is problematic if you want to return anything from that variable. It's particularly problematic with arrays, since it's frequently desirable to return slices of them, and scope (and therefore in) would prevent that. It's useful in some instances (particularly with delegates), but I'd use in _very_ sparingly. It's almost always more trouble than it's worth IMHO.BTW, scope should have been the default for *all* reference type function arguments, with an explicit modifier, say "esc", required to let the thing escape. It's an all-or-nothing thing, just like immutable strings - not using it everywhere is painful, but once you switch everything over you get the benefits. If it isn't obvious why - GC. The compiler can optimize the cases where it knows a newly allocated object can't escape and reduce or omit the GC overhead. And yes, it can also do this automatically - but that requires analyzing the whole call chain, which is a) not always possible and b) much more expensive. artur
Feb 03 2012
On 02/03/12 11:21, Alex Rønne Petersen wrote:On 03-02-2012 11:08, Artur Skawina wrote:It's about enabling the optimization for as much code as possible. And probably the most interesting cases are strings/arrays - the GC overhead can be huge if you do a lot of concatenation etc. Would marking the ctor as "scope" (similarly to "const" or "pure") work for your case? (it is reasonable to expect that the compiler checks this by itself; it's per-type, so not nearly as expensive as analyzing the flow) arturOn 02/03/12 00:20, Jonathan M Davis wrote:It is not that simple. If the class's constructor passes 'this' off to some arbitrary code, this optimization breaks completely. You would need whole-program analysis to have the slightest hope of doing this optimization correctly.in is pointless on value types. All it does is make the function parameter const, which really doesn't do much for you, and in some instances, is really annoying. Personally, I see no point in using in unless the parameter is a reference type, and even then, it's often a bad idea with reference types, because in is really const scope, and the scope is problematic if you want to return anything from that variable. It's particularly problematic with arrays, since it's frequently desirable to return slices of them, and scope (and therefore in) would prevent that. It's useful in some instances (particularly with delegates), but I'd use in _very_ sparingly. It's almost always more trouble than it's worth IMHO.BTW, scope should have been the default for *all* reference type function arguments, with an explicit modifier, say "esc", required to let the thing escape. It's an all-or-nothing thing, just like immutable strings - not using it everywhere is painful, but once you switch everything over you get the benefits. If it isn't obvious why - GC. The compiler can optimize the cases where it knows a newly allocated object can't escape and reduce or omit the GC overhead. And yes, it can also do this automatically - but that requires analyzing the whole call chain, which is a) not always possible and b) much more expensive. artur
Feb 03 2012
On 03-02-2012 11:41, Artur Skawina wrote:On 02/03/12 11:21, Alex Rønne Petersen wrote:Well, you would have to mark methods as scope too, as they could be passing off 'this' as well. It's probably doable that way, but explicit annotations kind of suck. :( -- - AlexOn 03-02-2012 11:08, Artur Skawina wrote:It's about enabling the optimization for as much code as possible. And probably the most interesting cases are strings/arrays - the GC overhead can be huge if you do a lot of concatenation etc. Would marking the ctor as "scope" (similarly to "const" or "pure") work for your case? (it is reasonable to expect that the compiler checks this by itself; it's per-type, so not nearly as expensive as analyzing the flow) arturOn 02/03/12 00:20, Jonathan M Davis wrote:It is not that simple. If the class's constructor passes 'this' off to some arbitrary code, this optimization breaks completely. You would need whole-program analysis to have the slightest hope of doing this optimization correctly.in is pointless on value types. All it does is make the function parameter const, which really doesn't do much for you, and in some instances, is really annoying. Personally, I see no point in using in unless the parameter is a reference type, and even then, it's often a bad idea with reference types, because in is really const scope, and the scope is problematic if you want to return anything from that variable. It's particularly problematic with arrays, since it's frequently desirable to return slices of them, and scope (and therefore in) would prevent that. It's useful in some instances (particularly with delegates), but I'd use in _very_ sparingly. It's almost always more trouble than it's worth IMHO.BTW, scope should have been the default for *all* reference type function arguments, with an explicit modifier, say "esc", required to let the thing escape. It's an all-or-nothing thing, just like immutable strings - not using it everywhere is painful, but once you switch everything over you get the benefits. If it isn't obvious why - GC. The compiler can optimize the cases where it knows a newly allocated object can't escape and reduce or omit the GC overhead. And yes, it can also do this automatically - but that requires analyzing the whole call chain, which is a) not always possible and b) much more expensive. artur
Feb 03 2012
Artur Skawina:Would marking the ctor as "scope" (similarly to "const" or "pure") work for your case? (it is reasonable to expect that the compiler checks this by itself; it's per-type, so not nearly as expensive as analyzing the flow)Maybe this is a topic worth discussing in the main D newsgroup (and maybe later worth an enhancement request). Bye, bearophile
Feb 03 2012
On 02/03/12 11:41, Artur Skawina wrote:On 02/03/12 11:21, Alex Rønne Petersen wrote:Actually, passing 'this' to some "some arbitrary code" isn't a problem, unless the code in question has the "esc" annotation, in which case you need to mark the ctor (or any other method) as "esq" too; that will turn off the optimization, for this struct/class, obviously. That's why "scope" needs to be the default - mixing it with code that does not guarantee that the object does not escape does not really work - you cannot call anything not marked with "scope" with an already scoped object. Which means you need to mark practically every function argument as scope - this doesn't scale well. arturOn 03-02-2012 11:08, Artur Skawina wrote:It's about enabling the optimization for as much code as possible. And probably the most interesting cases are strings/arrays - the GC overhead can be huge if you do a lot of concatenation etc. Would marking the ctor as "scope" (similarly to "const" or "pure") work for your case? (it is reasonable to expect that the compiler checks this by itself; it's per-type, so not nearly as expensive as analyzing the flow)On 02/03/12 00:20, Jonathan M Davis wrote:It is not that simple. If the class's constructor passes 'this' off to some arbitrary code, this optimization breaks completely. You would need whole-program analysis to have the slightest hope of doing this optimization correctly.in is pointless on value types. All it does is make the function parameter const, which really doesn't do much for you, and in some instances, is really annoying. Personally, I see no point in using in unless the parameter is a reference type, and even then, it's often a bad idea with reference types, because in is really const scope, and the scope is problematic if you want to return anything from that variable. It's particularly problematic with arrays, since it's frequently desirable to return slices of them, and scope (and therefore in) would prevent that. It's useful in some instances (particularly with delegates), but I'd use in _very_ sparingly. It's almost always more trouble than it's worth IMHO.BTW, scope should have been the default for *all* reference type function arguments, with an explicit modifier, say "esc", required to let the thing escape. It's an all-or-nothing thing, just like immutable strings - not using it everywhere is painful, but once you switch everything over you get the benefits. If it isn't obvious why - GC. The compiler can optimize the cases where it knows a newly allocated object can't escape and reduce or omit the GC overhead. And yes, it can also do this automatically - but that requires analyzing the whole call chain, which is a) not always possible and b) much more expensive. artur
Feb 03 2012
On 02/03/2012 11:08 AM, Artur Skawina wrote:On 02/03/12 00:20, Jonathan M Davis wrote:I totally agree. Most function arguments are not escaped. However, it is nice that the shortest storage class, 'in', implies scope.in is pointless on value types. All it does is make the function parameter const, which really doesn't do much for you, and in some instances, is really annoying. Personally, I see no point in using in unless the parameter is a reference type, and even then, it's often a bad idea with reference types, because in is really const scope, and the scope is problematic if you want to return anything from that variable. It's particularly problematic with arrays, since it's frequently desirable to return slices of them, and scope (and therefore in) would prevent that. It's useful in some instances (particularly with delegates), but I'd use in _very_ sparingly. It's almost always more trouble than it's worth IMHO.BTW, scope should have been the default for *all* reference type function arguments, with an explicit modifier, say "esc", required to let the thing escape. It's an all-or-nothing thing, just like immutable strings - not using it everywhere is painful, but once you switch everything over you get the benefits.If it isn't obvious why - GC. The compiler can optimize the cases where it knows a newly allocated object can't escape and reduce or omit the GC overhead. And yes, it can also do this automatically - but that requires analyzing the whole call chain, which is a) not always possible and b) much more expensive. arturAny optimization that relies on alias analysis potentially benefits from 'scope'.
Feb 03 2012
Timon Gehr:However, it is nice that the shortest storage class, 'in', implies scope.I'd like to ask this to be valid, to shorten my code: alias immutable imm; Is this silly? Bye, bearophile
Feb 03 2012
"bearophile" <bearophileHUGS lycos.com> wrote in message news:jgi3jn$2o6p$1 digitalmars.com...I'd like to ask this to be valid, to shorten my code: alias immutable imm; Is this silly?Yes =) immutable might be more characters than you want to type, but at this point it's extremely unlikely it will be changed or a synonym will be added. You can always define something like this: template imm(T) { alias immutable T imm; } imm!int cantchangethis = ...;
Feb 03 2012
On 02/04/12 02:03, Timon Gehr wrote:On 02/03/2012 11:08 AM, Artur Skawina wrote:There are currently two problems with using "in": a) the one mentioned, where using in/scope means you can't (or shouldn't be able to) pass the thing to another function w/o scope marked args, and b) "in" implies "const", which is a problem because you may want to reassign the argument - a perfectly safe thing to do. With "const" itself you can use parentheses to limit its scope to not include the reference itself; the problematic case is the builtin "string" alias, ie "int f(in string s);" would have to allow reassigning 's' inside the function. Semi-related quiz: immutable(char)[] a = "a"; const (char)[] b = "b"; auto aa = a ~ a; auto bb = b ~ b; auto ab = a ~ b; writeln("aa: ", typeid(aa), " bb: ", typeid(bb), " ab: ", typeid(ab)); And the question is: How many people, who have not already been bitten by this, will give the correct answer to: "What will this program print?"? There should have been another class, in addition to immutable/const, say "uniq". For cases where an expression results in new unique objects. This class implicitly converts to any of const/immutable and mutates to the new type. IOW string a = "a"; char[] b = "b"; auto c = a ~ b; // typeid(c) == (uniq(char)[]) string d = c; // Fine, "c" is unique and can be safely treated as a string. // But, from now on, "c" is (immutable(char)[]) so: char[] e = c; // Fails. // And the other way: auto f = a ~ b; char[] g = f; // OK string h = f // Fails, as f is now a (char[]) No need for unsafe-looking casts, just so that the compiler accepts perfectly safe code, like: "string c = ab;", which would currently fail if used in the above quiz, and has to be written as "string c = cast(string)ab;". [1] artur [1] Using a helper template is not different from adding a comment, it only serves to document /why/ the programmer had to something, which is only a workaround for a language/compiler limitation. "Compiler" because at least the simple cases could be silently fixed in a backward compatible way (by not disallowing safe conversions). "Language" because "uniq" would also be useful when the programmer knows it applies, but the compiler can't figure it out by itself.On 02/03/12 00:20, Jonathan M Davis wrote:I totally agree. Most function arguments are not escaped. However, it is nice that the shortest storage class, 'in', implies scope.in is pointless on value types. All it does is make the function parameter const, which really doesn't do much for you, and in some instances, is really annoying. Personally, I see no point in using in unless the parameter is a reference type, and even then, it's often a bad idea with reference types, because in is really const scope, and the scope is problematic if you want to return anything from that variable. It's particularly problematic with arrays, since it's frequently desirable to return slices of them, and scope (and therefore in) would prevent that. It's useful in some instances (particularly with delegates), but I'd use in _very_ sparingly. It's almost always more trouble than it's worth IMHO.BTW, scope should have been the default for *all* reference type function arguments, with an explicit modifier, say "esc", required to let the thing escape. It's an all-or-nothing thing, just like immutable strings - not using it everywhere is painful, but once you switch everything over you get the benefits.
Feb 04 2012
On 02/04/2012 06:55 PM, Artur Skawina wrote:On 02/04/12 02:03, Timon Gehr wrote:I think this is covered in this issue: http://d.puremagic.com/issues/show_bug.cgi?id=7311 But feel free to open a more specific enhancement/bug report.On 02/03/2012 11:08 AM, Artur Skawina wrote:There are currently two problems with using "in": a) the one mentioned, where using in/scope means you can't (or shouldn't be able to) pass the thing to another function w/o scope marked args, and b) "in" implies "const", which is a problem because you may want to reassign the argument - a perfectly safe thing to do. With "const" itself you can use parentheses to limit its scope to not include the reference itself; the problematic case is the builtin "string" alias, ie "int f(in string s);" would have to allow reassigning 's' inside the function. Semi-related quiz: immutable(char)[] a = "a"; const (char)[] b = "b"; auto aa = a ~ a; auto bb = b ~ b; auto ab = a ~ b; writeln("aa: ", typeid(aa), " bb: ", typeid(bb), " ab: ", typeid(ab)); And the question is: How many people, who have not already been bitten by this, will give the correct answer to: "What will this program print?"?On 02/03/12 00:20, Jonathan M Davis wrote:I totally agree. Most function arguments are not escaped. However, it is nice that the shortest storage class, 'in', implies scope.in is pointless on value types. All it does is make the function parameter const, which really doesn't do much for you, and in some instances, is really annoying. Personally, I see no point in using in unless the parameter is a reference type, and even then, it's often a bad idea with reference types, because in is really const scope, and the scope is problematic if you want to return anything from that variable. It's particularly problematic with arrays, since it's frequently desirable to return slices of them, and scope (and therefore in) would prevent that. It's useful in some instances (particularly with delegates), but I'd use in _very_ sparingly. It's almost always more trouble than it's worth IMHO.BTW, scope should have been the default for *all* reference type function arguments, with an explicit modifier, say "esc", required to let the thing escape. It's an all-or-nothing thing, just like immutable strings - not using it everywhere is painful, but once you switch everything over you get the benefits.There should have been another class, in addition to immutable/const, say "uniq". For cases where an expression results in new unique objects. This class implicitly converts to any of const/immutable and mutates to the new type. IOW string a = "a"; char[] b = "b"; auto c = a ~ b; // typeid(c) == (uniq(char)[]) string d = c; // Fine, "c" is unique and can be safely treated as a string. // But, from now on, "c" is (immutable(char)[]) so: char[] e = c; // Fails. // And the other way: auto f = a ~ b; char[] g = f; // OK string h = f // Fails, as f is now a (char[]) No need for unsafe-looking casts, just so that the compiler accepts perfectly safe code, like: "string c = ab;", which would currently fail if used in the above quiz, and has to be written as "string c = cast(string)ab;". [1] artur [1] Using a helper template is not different from adding a comment, it only serves to document /why/ the programmer had to something, which is only a workaround for a language/compiler limitation. "Compiler" because at least the simple cases could be silently fixed in a backward compatible way (by not disallowing safe conversions). "Language" because "uniq" would also be useful when the programmer knows it applies, but the compiler can't figure it out by itself.I am certain we'll get something like this eventually, once the compiler bug count has shrunk sufficiently. It is a natural thing to add.
Feb 04 2012
On 02/04/12 22:20, Timon Gehr wrote:On 02/04/2012 06:55 PM, Artur Skawina wrote:Apparently, there's already a bug open for everything. I'm not sure if it's a good or bad thing. :) I don't think there's one correct answer here - you're right that unique const does not really make sense. But is mutable (non-const) really better than immutable? It depends, sometimes you will want one, sometimes the other. I first ran into this while doing a custom string class - there it was the cause of the one and only cast - (string ~ const(char)[]) can obviously still be a string, but the compiler won't accept it without a cast. I'm not sure how often you'll want the result of concatenation to be mutable, compared to immutable. Anyway, the result really is "unique", not mutable, const or immutable, at least until it is converted to one of those, hence the solution described below.On 02/04/12 02:03, Timon Gehr wrote:I think this is covered in this issue: http://d.puremagic.com/issues/show_bug.cgi?id=7311 But feel free to open a more specific enhancement/bug report.On 02/03/2012 11:08 AM, Artur Skawina wrote:There are currently two problems with using "in": a) the one mentioned, where using in/scope means you can't (or shouldn't be able to) pass the thing to another function w/o scope marked args, and b) "in" implies "const", which is a problem because you may want to reassign the argument - a perfectly safe thing to do. With "const" itself you can use parentheses to limit its scope to not include the reference itself; the problematic case is the builtin "string" alias, ie "int f(in string s);" would have to allow reassigning 's' inside the function. Semi-related quiz: immutable(char)[] a = "a"; const (char)[] b = "b"; auto aa = a ~ a; auto bb = b ~ b; auto ab = a ~ b; writeln("aa: ", typeid(aa), " bb: ", typeid(bb), " ab: ", typeid(ab)); And the question is: How many people, who have not already been bitten by this, will give the correct answer to: "What will this program print?"?On 02/03/12 00:20, Jonathan M Davis wrote:I totally agree. Most function arguments are not escaped. However, it is nice that the shortest storage class, 'in', implies scope.in is pointless on value types. All it does is make the function parameter const, which really doesn't do much for you, and in some instances, is really annoying. Personally, I see no point in using in unless the parameter is a reference type, and even then, it's often a bad idea with reference types, because in is really const scope, and the scope is problematic if you want to return anything from that variable. It's particularly problematic with arrays, since it's frequently desirable to return slices of them, and scope (and therefore in) would prevent that. It's useful in some instances (particularly with delegates), but I'd use in _very_ sparingly. It's almost always more trouble than it's worth IMHO.BTW, scope should have been the default for *all* reference type function arguments, with an explicit modifier, say "esc", required to let the thing escape. It's an all-or-nothing thing, just like immutable strings - not using it everywhere is painful, but once you switch everything over you get the benefits.It would be great if as many of the /language/ issues were fixed and documented as soon as possible. They don't even have to be implemented. What i'm afraid of is what will happen once dmd no longer is the normative compiler... Walter did a very good job with D, i wouldn't expect others to get even a small part of it right; it would be best if by the time the committee hordes start to "fix" things there was not much left to fix. [Changes such as defaulting to scoped args are obviously D3 material, i'm only mentioning them so that they're already out there to consider/discuss. But some things *can* still be fixed in D2 in a mostly backward compatible way] arturThere should have been another class, in addition to immutable/const, say "uniq". For cases where an expression results in new unique objects. This class implicitly converts to any of const/immutable and mutates to the new type. IOW string a = "a"; char[] b = "b"; auto c = a ~ b; // typeid(c) == (uniq(char)[]) string d = c; // Fine, "c" is unique and can be safely treated as a string. // But, from now on, "c" is (immutable(char)[]) so: char[] e = c; // Fails. // And the other way: auto f = a ~ b; char[] g = f; // OK string h = f // Fails, as f is now a (char[]) No need for unsafe-looking casts, just so that the compiler accepts perfectly safe code, like: "string c = ab;", which would currently fail if used in the above quiz, and has to be written as "string c = cast(string)ab;". [1] artur [1] Using a helper template is not different from adding a comment, it only serves to document /why/ the programmer had to something, which is only a workaround for a language/compiler limitation. "Compiler" because at least the simple cases could be silently fixed in a backward compatible way (by not disallowing safe conversions). "Language" because "uniq" would also be useful when the programmer knows it applies, but the compiler can't figure it out by itself.I am certain we'll get something like this eventually, once the compiler bug count has shrunk sufficiently. It is a natural thing to add.
Feb 04 2012
On 02/04/2012 11:23 PM, Artur Skawina wrote:On 02/04/12 22:20, Timon Gehr wrote:Well, string = string ~ const(char)[] and char[] = string ~ const(char)[] should work, regardless of the type of immutable[] ~ const[]. The compiler can track the uniqueness of the data at the expression level without actually introducing a type modifier. There is precedent: Array literals are covariant, because it is safe. Do you want to open the enhancement or should I do it? (I really thought I already had an issue open for this...)On 02/04/2012 06:55 PM, Artur Skawina wrote:Apparently, there's already a bug open for everything. I'm not sure if it's a good or bad thing. :) I don't think there's one correct answer here - you're right that unique const does not really make sense. But is mutable (non-const) really better than immutable? It depends, sometimes you will want one, sometimes the other. I first ran into this while doing a custom string class - there it was the cause of the one and only cast - (string ~ const(char)[]) can obviously still be a string, but the compiler won't accept it without a cast. I'm not sure how often you'll want the result of concatenation to be mutable, compared to immutable. Anyway, the result really is "unique", not mutable, const or immutable, at least until it is converted to one of those, hence the solution described below.On 02/04/12 02:03, Timon Gehr wrote:I think this is covered in this issue: http://d.puremagic.com/issues/show_bug.cgi?id=7311 But feel free to open a more specific enhancement/bug report.On 02/03/2012 11:08 AM, Artur Skawina wrote:There are currently two problems with using "in": a) the one mentioned, where using in/scope means you can't (or shouldn't be able to) pass the thing to another function w/o scope marked args, and b) "in" implies "const", which is a problem because you may want to reassign the argument - a perfectly safe thing to do. With "const" itself you can use parentheses to limit its scope to not include the reference itself; the problematic case is the builtin "string" alias, ie "int f(in string s);" would have to allow reassigning 's' inside the function. Semi-related quiz: immutable(char)[] a = "a"; const (char)[] b = "b"; auto aa = a ~ a; auto bb = b ~ b; auto ab = a ~ b; writeln("aa: ", typeid(aa), " bb: ", typeid(bb), " ab: ", typeid(ab)); And the question is: How many people, who have not already been bitten by this, will give the correct answer to: "What will this program print?"?On 02/03/12 00:20, Jonathan M Davis wrote:I totally agree. Most function arguments are not escaped. However, it is nice that the shortest storage class, 'in', implies scope.in is pointless on value types. All it does is make the function parameter const, which really doesn't do much for you, and in some instances, is really annoying. Personally, I see no point in using in unless the parameter is a reference type, and even then, it's often a bad idea with reference types, because in is really const scope, and the scope is problematic if you want to return anything from that variable. It's particularly problematic with arrays, since it's frequently desirable to return slices of them, and scope (and therefore in) would prevent that. It's useful in some instances (particularly with delegates), but I'd use in _very_ sparingly. It's almost always more trouble than it's worth IMHO.BTW, scope should have been the default for *all* reference type function arguments, with an explicit modifier, say "esc", required to let the thing escape. It's an all-or-nothing thing, just like immutable strings - not using it everywhere is painful, but once you switch everything over you get the benefits.It would be great if as many of the /language/ issues were fixed and documented as soon as possible. They don't even have to be implemented. What i'm afraid of is what will happen once dmd no longer is the normative compiler... Walter did a very good job with D, i wouldn't expect others to get even a small part of it right; it would be best if by the time the committee hordes start to "fix" things there was not much left to fix. [Changes such as defaulting to scoped args are obviously D3 material, i'm only mentioning them so that they're already out there to consider/discuss. But some things *can* still be fixed in D2 in a mostly backward compatible way] arturThere should have been another class, in addition to immutable/const, say "uniq". For cases where an expression results in new unique objects. This class implicitly converts to any of const/immutable and mutates to the new type. IOW string a = "a"; char[] b = "b"; auto c = a ~ b; // typeid(c) == (uniq(char)[]) string d = c; // Fine, "c" is unique and can be safely treated as a string. // But, from now on, "c" is (immutable(char)[]) so: char[] e = c; // Fails. // And the other way: auto f = a ~ b; char[] g = f; // OK string h = f // Fails, as f is now a (char[]) No need for unsafe-looking casts, just so that the compiler accepts perfectly safe code, like: "string c = ab;", which would currently fail if used in the above quiz, and has to be written as "string c = cast(string)ab;". [1] artur [1] Using a helper template is not different from adding a comment, it only serves to document /why/ the programmer had to something, which is only a workaround for a language/compiler limitation. "Compiler" because at least the simple cases could be silently fixed in a backward compatible way (by not disallowing safe conversions). "Language" because "uniq" would also be useful when the programmer knows it applies, but the compiler can't figure it out by itself.I am certain we'll get something like this eventually, once the compiler bug count has shrunk sufficiently. It is a natural thing to add.
Feb 04 2012
On 02/04/12 23:44, Timon Gehr wrote:On 02/04/2012 11:23 PM, Artur Skawina wrote:Please do; i've been avoiding filing dmd bugs, because i'm only using gdc, not dmd. (so i can't even easily check if the issue still exists in the current tree) arturOn 02/04/12 22:20, Timon Gehr wrote:Well, string = string ~ const(char)[] and char[] = string ~ const(char)[] should work, regardless of the type of immutable[] ~ const[]. The compiler can track the uniqueness of the data at the expression level without actually introducing a type modifier. There is precedent: Array literals are covariant, because it is safe. Do you want to open the enhancement or should I do it? (I really thought I already had an issue open for this...)On 02/04/2012 06:55 PM, Artur Skawina wrote:Apparently, there's already a bug open for everything. I'm not sure if it's a good or bad thing. :) I don't think there's one correct answer here - you're right that unique const does not really make sense. But is mutable (non-const) really better than immutable? It depends, sometimes you will want one, sometimes the other. I first ran into this while doing a custom string class - there it was the cause of the one and only cast - (string ~ const(char)[]) can obviously still be a string, but the compiler won't accept it without a cast. I'm not sure how often you'll want the result of concatenation to be mutable, compared to immutable. Anyway, the result really is "unique", not mutable, const or immutable, at least until it is converted to one of those, hence the solution described below.Semi-related quiz: immutable(char)[] a = "a"; const (char)[] b = "b"; auto aa = a ~ a; auto bb = b ~ b; auto ab = a ~ b; writeln("aa: ", typeid(aa), " bb: ", typeid(bb), " ab: ", typeid(ab)); And the question is: How many people, who have not already been bitten by this, will give the correct answer to: "What will this program print?"?I think this is covered in this issue: http://d.puremagic.com/issues/show_bug.cgi?id=7311 But feel free to open a more specific enhancement/bug report.
Feb 04 2012
Al 03/02/12 00:14, En/na bearophile ha escrit:xancorreu:Mmm. Thanks. It remembers me val in scala ;-) I note it for optimizations.But you "only" put a "in" in recFactorial function argument. What this mean? **Why** this is more efficient than mine?It wasn't meant to improve performance. "in" turns a function argument to "input only" (and eventually scoped too). Generally when you program in D2 it's a good practice to use immutability where you can and where this doesn't cause other performance or typing problems. Immutability avoids bugs, allows a stronger purity (and I have seen DMD is often able to compiler a little more efficient program if you use immutability/constants everywhere they are a good fit). So 95% of the arguments of your program are better tagged with "in".Bye, bearophile
Feb 03 2012
On 02/02/2012 05:28 PM, xancorreu wrote:I get "segment violation" error with ./factorial 400000 How can I resolve it? My code is: import std.stdio, std.bigint, std.string, std.conv, std.stream; BigInt recFactorial(int n) { if (n == 0) return BigInt(1); else return (BigInt(n) * recFactorial(n - 1)); } void main(string[] args) { if (args.length != 2) writeln("Factorial requires a number"); else try { writeln(recFactorial(std.conv.to!int(args[1]))); } catch { writeln("Error"); } } Thanks a lot,import std.stdio, std.bigint, std.conv; BigInt factorial(int n) { BigInt result=1; foreach(i;1..n) result*=i; return result; } void main(string[] args) { if (args.length != 2) writeln("Factorial requires a number"); else try { writeln(factorial(std.conv.to!int(args[1]))); } catch { writeln("Error"); } }
Feb 02 2012
Timon Gehr:This is not a tail-recursive function. And neither is recFactorial, my bad. Anyway, my point was that the compiler should not generate code that blows up on a (in principle) perfectly sane implementation.Is it possible to create a function attribute like tail_recursive that produces a compile error if you apply it to a function that's not tail-recursive? Bye, bearophile
Feb 02 2012
On Thursday, February 02, 2012 18:17:36 bearophile wrote:Timon Gehr:I suspect that Walter would feel the same way about that that he feels about something like marking functions as inline - i.e. that sort of thing should be left up to the compiler to optimize or not as it sees appropriate. - Jonathan M DavisThis is not a tail-recursive function. And neither is recFactorial, my bad. Anyway, my point was that the compiler should not generate code that blows up on a (in principle) perfectly sane implementation.Is it possible to create a function attribute like tail_recursive that produces a compile error if you apply it to a function that's not tail-recursive?
Feb 02 2012
Al 02/02/12 16:58, En/na David Nadlinger ha escrit:On 2/2/12 1:35 PM, xancorreu wrote:Sorry, if condition was wrong. conv.to!int is perfect! Thanks,In this code, how can I cast the args[0] string to int for computing factorial(args[0])?std.conv.to!int(…) or parse().Hope this helps, David
Feb 02 2012
Use to!int(args[1])I receive: $ gdmd-4.6 factorial.d factorial.d: In function ‘main’: factorial.d:15:0: error: cannot cast expression of type string to int Thanks in advance, Xan.
Feb 02 2012
On Friday, February 03, 2012 11:08:54 Artur Skawina wrote:BTW, scope should have been the default for *all* reference type function arguments, with an explicit modifier, say "esc", required to let the thing escape. It's an all-or-nothing thing, just like immutable strings - not using it everywhere is painful, but once you switch everything over you get the benefits.That would destroy slicing. I'm firmly of the opinion that scope should be used sparingly. - Jonathan M Davis
Feb 03 2012
On 02/03/2012 01:06 PM, Jonathan M Davis wrote:On Friday, February 03, 2012 11:08:54 Artur Skawina wrote:It could be enabled on by type basis.BTW, scope should have been the default for *all* reference type function arguments, with an explicit modifier, say "esc", required to let the thing escape. It's an all-or-nothing thing, just like immutable strings - not using it everywhere is painful, but once you switch everything over you get the benefits.That would destroy slicing. I'm firmly of the opinion that scope should be used sparingly. - Jonathan M Davis
Feb 03 2012
On 02/03/12 13:06, Jonathan M Davis wrote:On Friday, February 03, 2012 11:08:54 Artur Skawina wrote:Well, not doing it destroys performance. [1] It's a trade-off. Also, i don't know if "destroy slicing" is accurate. Things like 'string f(string s) { return s[1..$]; }' needs to continue to work; the object does not really "escape" from the POV of f(), but the caller has to assume it's not dead after returning from the function. Doing this by default for any functions returning refs that could potentially hold on to the passed object would make things work. For the cases that where the called function knows that it will always return unique objects the signature could look like 'new string f(string s);', but that's only an optimization. Any other problematic slicing use, that i'm not thinking of right now? artur [1] I had a case, where turning on logging in some code made the program unusable, because instead of IIRC ~40s it took 40+ minutes, at which point i gave up and killed it... The profile looked like this: 37.62% uint gc.gcx.Gcx.fullcollect(void*) 20.47% uint gc.gcbits.GCBits.test(uint) 13.80% uint gc.gcbits.GCBits.testSet(uint) 10.15% pure nothrow safe bool std.uni.isGraphical(dchar) 3.33% _D3std5array17__T8AppenderTAyaZ8Appender10__T3putTwZ3putMF 2.78% 0x11025a 2.13% _D3std6format65__T13formatElementTS3std5array17__T8Appende 1.64% _D3std6format56__T10formatCharTS3std5array17__T8AppenderTA 1.37% pure safe uint std.utf.encode(ref char[4], dchar) 0.88% void* gc.gcx.GC.malloc(uint, uint, uint*) 0.50% pure nothrow safe bool std.uni.binarySearch2(dchar, immutable(dchar[2][])) 0.45% void gc.gcbits.GCBits.set(uint) 0.37% void gc.gcbits.GCBits.clear(uint) 0.34% __divdi3 That shows several problems, but even after fixing the obvious ones (inlining GCBits, making std.uni.isGraphical sane (this, btw, reduced its cost to ~1%)) GC still takes up most of time (not remembering the details, but certainly >50%, it could have been >80%). Some slowdown from the IO and formatting is expected, but spending most cycles on GC is not reasonable, when most objects never leave the scope (in this case it was just strings passed to writeln etc IIRC).BTW, scope should have been the default for *all* reference type function arguments, with an explicit modifier, say "esc", required to let the thing escape. It's an all-or-nothing thing, just like immutable strings - not using it everywhere is painful, but once you switch everything over you get the benefits.That would destroy slicing. I'm firmly of the opinion that scope should be used sparingly.
Feb 03 2012
On Friday, February 03, 2012 15:40:34 xancorreu wrote:Al 02/02/12 20:40, En/na Jonathan M Davis ha escrit:Fastest and easiest would be to simply do auto person = person(args[1], to!uint(args[2]), to!bool(args[3])); but that's going to blow up in your face in all sorts of entertaining ways if you didn't do verify the arguments that the user gave you (both in terms of number and their values). And it's so easy to do, that I don't see much point in trying to have some sort of function or library for automatically generating your object from the program's arguments - especially when you really should be doing argument validation, which no one else can do for you, since the correct way to do it is completely dependent on your application. - Jonathan M DavisAnd whether that's the best way to handle it depends on what you're trying to do in terms of user input and error messages. How on earth is all of that going to be handled generically? It all depends on what the programmer is trying to do. Switching to use command-line switches and getopt would help some, but you still have to deal with the error messages yourself. Creating the Person is the easy part. - Jonathan M DavisI think it as a tool, not solve-everything-thing, it just a tool for easy your job. Yeah, you could manually do that (thanks for the code) but really you, maybe, want to do it _fastest_ and _easyest_.
Feb 03 2012