Re: Bug or feature? iota has different semantics for integer and float arguments
On Saturday, 7 January 2023 at 02:31:14 UTC, Ali Çehreli wrote: On 1/6/23 17:50, Arredondo wrote: > Would anyone volunteer to file a bug report? Me! Me! :) https://issues.dlang.org/show_bug.cgi?id=23604 Ali Thanks a lot :D Arredondo.
Re: Bug or feature? iota has different semantics for integer and float arguments
On 1/6/23 17:50, Arredondo wrote: > Would anyone volunteer to file a bug report? Me! Me! :) https://issues.dlang.org/show_bug.cgi?id=23604 Ali
Re: Bug or feature? iota has different semantics for integer and float arguments
On Saturday, 7 January 2023 at 00:52:20 UTC, Ali Çehreli wrote: Although that difference is a bug, iota does have a special floating point implementation to prevent the accumulation of floating point errors. Thank you for this clarification Ali. I appreciate the fact that there is a specialized implementation for float types in an attempt to mitigate error accumulation. After posting my previous message I became convinced that the behavior I was seeing was indeed a bug. The specialized fp implementation simply does not conform to the semantics specified in the documentation: "If begin < end && step < 0 or begin > end && step > 0 or begin == end, then an empty range is returned." The culprit is this assert in the `in` block of the fp implementation: ``` assert((end - begin) / step >= 0, "iota: incorrect startup parameters"); ``` This effectively prevents iota from ever returning an empty range. Git blame points to a commit from March 2015. It's unbelievable to me this hasn't been fixed in almost 8 years. Would anyone volunteer to file a bug report? I attempted to do it myself but I would need to create an account in the Issue Tracking System, and apparently it doesn't accept gmail addresses anymore? (facepalm). Arredondo.
Re: Bug or feature? iota has different semantics for integer and float arguments
On 1/6/23 15:23, Arredondo wrote: > then you get an exception (incorrect startup parameters). Although that difference is a bug, iota does have a special floating point implementation to prevent the accumulation of floating point errors. I mention it as item 4 here: https://www.youtube.com/watch?v=gwUcngTmKhg=634s Briefly, iota's regular popFront() is a trivial front += step but it is ++n for floating types so that front can be begin + (n * step) for them. The iota discussion starts at an earlier point in the video here: https://www.youtube.com/watch?v=gwUcngTmKhg=558s Ali
Bug or feature? iota has different semantics for integer and float arguments
Consider: ``` import std.range.iota; auto r = iota(5, 0); ``` `r` is an empty range, as it should be. But if you call: ``` auto r = iota(5.0, 0); ``` then you get an exception (incorrect startup parameters). This was unexpected, and a pain to debug. What is the rationale behind iota having different semantics depending on whether the arguments are floats or not? Arredondo.
Re: Create alias of same name in inner scope, bug or feature?
On Saturday, 14 August 2021 at 08:23:20 UTC, user1234 wrote: On Saturday, 14 August 2021 at 04:09:34 UTC, Tejas wrote: [...] Oh right, the ```.``` operator will reference variable in the _module_ scope, not just the _immediate outer scope_, you can use the module name to disambiguate as well. To extend Mike answer, the general rule is that if you can distinguish two names there's no shadowing. Understood
Re: Create alias of same name in inner scope, bug or feature?
On Saturday, 14 August 2021 at 04:09:34 UTC, Tejas wrote: [...] Oh right, the ```.``` operator will reference variable in the _module_ scope, not just the _immediate outer scope_, you can use the module name to disambiguate as well. To extend Mike answer, the general rule is that if you can distinguish two names there's no shadowing.
Re: Create alias of same name in inner scope, bug or feature?
On Saturday, 14 August 2021 at 04:01:31 UTC, Mike Parker wrote: On Saturday, 14 August 2021 at 03:47:05 UTC, Tejas wrote: ```d import std; auto abc(T)(auto ref T a, auto ref T b){ return a+b; } auto def(T)(auto ref T a, auto ref T b){ return a*b; } alias macro_1 = abc; void main() { writeln(macro_1(15, 20)); alias macro_1 = def;// is this NOT considered variable shadowing? writeln(macro_1(100, 20)); } ``` Shadowing local symbols is illegal. But it's okay for local symbols to have the same name as module-scope symbols. You can disambigbuate with [the module scope operator][1]: ```d void main() macro_1(); // the local symbol .macro_1(); // the external symbol } ``` [1]: https://dlang.org/spec/module.html#module_scope_operators Oh right, the ```.``` operator will reference variable in the _module_ scope, not just the _immediate outer scope_, that's why it is not considered shadowing in that case. Thank you very much!
Re: Create alias of same name in inner scope, bug or feature?
On Saturday, 14 August 2021 at 03:47:05 UTC, Tejas wrote: ```d import std; auto abc(T)(auto ref T a, auto ref T b){ return a+b; } auto def(T)(auto ref T a, auto ref T b){ return a*b; } alias macro_1 = abc; void main() { writeln(macro_1(15, 20)); alias macro_1 = def;// is this NOT considered variable shadowing? writeln(macro_1(100, 20)); } ``` Shadowing local symbols is illegal. But it's okay for local symbols to have the same name as module-scope symbols. You can disambigbuate with [the module scope operator][1]: ```d void main() macro_1(); // the local symbol .macro_1(); // the external symbol } ``` [1]: https://dlang.org/spec/module.html#module_scope_operators
Create alias of same name in inner scope, bug or feature?
```d import std; auto abc(T)(auto ref T a, auto ref T b){ return a+b; } auto def(T)(auto ref T a, auto ref T b){ return a*b; } alias macro_1 = abc; void main() { writeln(macro_1(15, 20)); alias macro_1 = def;// is this NOT considered variable shadowing? writeln(macro_1(100, 20)); } ```
Re: Bug or Feature: unsigned integer overflow
On Saturday, 14 December 2019 at 10:32:10 UTC, berni44 wrote: On Saturday, 14 December 2019 at 09:33:13 UTC, Tobias Pankrath wrote: See: https://dlang.org/spec/lex.html#integerliteral What I am aiming at: Is the spec wrong or am I misunderstanding it and did this change recently? You are right. The implementation does not do what the specs tell here. I filed a bug report: https://issues.dlang.org/show_bug.cgi?id=20449 Thank you!
Re: Bug or Feature: unsigned integer overflow
On Saturday, 14 December 2019 at 09:33:13 UTC, Tobias Pankrath wrote: See: https://dlang.org/spec/lex.html#integerliteral What I am aiming at: Is the spec wrong or am I misunderstanding it and did this change recently? You are right. The implementation does not do what the specs tell here. I filed a bug report: https://issues.dlang.org/show_bug.cgi?id=20449
Re: Bug or Feature: unsigned integer overflow
On Saturday, 14 December 2019 at 07:44:37 UTC, berni44 wrote: On Saturday, 14 December 2019 at 07:09:30 UTC, Tobias Pankrath wrote: void main() { auto x = 9223372036854775808; // long.max + 1 } You need to tell, that this is an unsigned long literal, else the compiler treats it as an int: void main() { auto x = 9223372036854775808UL; // long.max + 1 } As far as I understand the spec, the type is inferred from the value range: Literal Type Usual decimal notation 0 .. 2_147_483_647 int 2_147_483_648 .. 9_223_372_036_854_775_807 long 9_223_372_036_854_775_808 .. 18_446_744_073_709_551_615 ulong See: https://dlang.org/spec/lex.html#integerliteral What I am aiming at: Is the spec wrong or am I misunderstanding it and did this change recently?
Re: Bug or Feature: unsigned integer overflow
On Saturday, 14 December 2019 at 07:09:30 UTC, Tobias Pankrath wrote: void main() { auto x = 9223372036854775808; // long.max + 1 } You need to tell, that this is an unsigned long literal, else the compiler treats it as an int: void main() { auto x = 9223372036854775808UL; // long.max + 1 }
Bug or Feature: unsigned integer overflow
void main() { auto x = 9223372036854775808; // long.max + 1 } onlineapp.d(3): Error: signed integer overflow According to spec x should be of type ulong and this should compile? It indeed compiles if I add the uL postfix. Is this a bug or indented behaviour?
Re: Bug or Feature: `this` necessary to call function with template this parameter
On Wednesday, 30 October 2019 at 20:22:25 UTC, Q. Schroll wrote: struct Example { private void helper(int i, this X)() { } void funcTempl(T, this X)(T value) { this.helper!0(); // ^ Why do I need this? } } void main() { auto ex = Example(); ex.funcTempl(1); } The question is in the comment in the code. Is that intentional or a bug? It's a bug - filed as https://issues.dlang.org/show_bug.cgi?id=20341. However, note that typeof(this) inside funcTempl() is different from X, so that inside helper(), X will not be the same as in funcTempl(). To fix this, you will need to pass X on to helper as helper!(0, X). When you do this, you no longer need 'this.' in front of the instantiation. -- Simen
Bug or Feature: `this` necessary to call function with template this parameter
struct Example { private void helper(int i, this X)() { } void funcTempl(T, this X)(T value) { this.helper!0(); // ^ Why do I need this? } } void main() { auto ex = Example(); ex.funcTempl(1); } The question is in the comment in the code. Is that intentional or a bug?
Re: Can't add ubytes together to make a ubyte... bug or feature?
On 03/17/2018 11:36 AM, Jonathan wrote: `(a+b)&0xff` What is this syntax?! Could you give a link to this in the D documentation? Here is my description of bitwise AND: http://ddili.org/ders/d.en/bit_operations.html#ix_bit_operations.&,%20bitwise%20and The section titled "Masking" on the same page explains what &0xff part means. I am not even sure how to look it up... I hope my index section is useful in such cases. Just search for the & character there: http://ddili.org/ders/d.en/ix.html Yes, there are many meanings of the & character but I think it's still useful. :) Ali
Re: Can't add ubytes together to make a ubyte... bug or feature?
On Saturday, 17 March 2018 at 18:56:55 UTC, Dominikus Dittes Scherkl wrote: On Saturday, 17 March 2018 at 18:36:35 UTC, Jonathan wrote: On Tuesday, 19 January 2016 at 23:36:14 UTC, Adam D. Ruppe wrote: On Tuesday, 19 January 2016 at 22:12:06 UTC, Soviet Friend wrote: I don't care if my computer needs to do math on a 4 byte basis, I'm not writing assembly. x86 actually doesn't need to do math that way, if you were writing assembly, it would just work. This is just an annoying rule brought over by C. Can I prevent the initial implicit casts? Nope, though you can help tell the compiler that you want it to fit there by doing stuff like ubyte a = 200; ubyte b = 100; ubyte c = (a+b)&0xff; or something like that, so the expression is specifically proven to fit in the byte with compile time facts. `(a+b)&0xff` What is this syntax?! Could you give a link to this in the D documentation? I am not even sure how to look it up... & is the normal binary and operation, same in C, C++, Java, ... 0xFF is a hexadecimal constant (255), which the compiler knows fit in an ubyte So what do you not understand about this syntax? I guess he doesn't understand bitwise operations. Also don't you mean bitwise and?
Re: Can't add ubytes together to make a ubyte... bug or feature?
On Saturday, 17 March 2018 at 18:36:35 UTC, Jonathan wrote: On Tuesday, 19 January 2016 at 23:36:14 UTC, Adam D. Ruppe wrote: On Tuesday, 19 January 2016 at 22:12:06 UTC, Soviet Friend wrote: I don't care if my computer needs to do math on a 4 byte basis, I'm not writing assembly. x86 actually doesn't need to do math that way, if you were writing assembly, it would just work. This is just an annoying rule brought over by C. Can I prevent the initial implicit casts? Nope, though you can help tell the compiler that you want it to fit there by doing stuff like ubyte a = 200; ubyte b = 100; ubyte c = (a+b)&0xff; or something like that, so the expression is specifically proven to fit in the byte with compile time facts. `(a+b)&0xff` What is this syntax?! Could you give a link to this in the D documentation? I am not even sure how to look it up... & is the normal binary and operation, same in C, C++, Java, ... 0xFF is a hexadecimal constant (255), which the compiler knows fit in an ubyte So what do you not understand about this syntax?
Re: Can't add ubytes together to make a ubyte... bug or feature?
On Tuesday, 19 January 2016 at 23:36:14 UTC, Adam D. Ruppe wrote: On Tuesday, 19 January 2016 at 22:12:06 UTC, Soviet Friend wrote: I don't care if my computer needs to do math on a 4 byte basis, I'm not writing assembly. x86 actually doesn't need to do math that way, if you were writing assembly, it would just work. This is just an annoying rule brought over by C. Can I prevent the initial implicit casts? Nope, though you can help tell the compiler that you want it to fit there by doing stuff like ubyte a = 200; ubyte b = 100; ubyte c = (a+b)&0xff; or something like that, so the expression is specifically proven to fit in the byte with compile time facts. `(a+b)&0xff` What is this syntax?! Could you give a link to this in the D documentation? I am not even sure how to look it up...
Re: Needed return type in static method? bug or feature?
On Tuesday, March 08, 2016 14:56:06 Antonio Corbi via Digitalmars-d-learn wrote: > On Tuesday, 8 March 2016 at 14:13:17 UTC, Adam D. Ruppe wrote: > > On Tuesday, 8 March 2016 at 13:40:06 UTC, Antonio Corbi wrote: > >> Is it a feature or a bug? > > > > It is allowed because the "auto" keyword doesn't actually > > required for auto functions (or variables), what you need is > > any one of the storage classes. > > > > Those include static, auto, const, immutable, even pure. > > > > If any of them are present, the compiler knows you are writing > > a function or declaring a variable and will infer the type. > > Thank's Adam!. > > I had figured out something like this but I couldn't find > anything in the docs > (http://dlang.org/spec/attribute.html#static), moreover, the > example there: > --8><- > class Foo > { > static int bar() { return 6; } > ... > --8><- > > does mention the return type, that's what confused me. The return type is optional so long as one of the keywords that indicates that it's a variable or a function is there, so you can choose to put it or not. In most cases, I think that folks put the return type on functions or use auto, but it's up to you. Where it usually comes up is enums and variable declarations. - Jonathan M Davis
Re: Needed return type in static method? bug or feature?
On Tuesday, 8 March 2016 at 14:13:17 UTC, Adam D. Ruppe wrote: On Tuesday, 8 March 2016 at 13:40:06 UTC, Antonio Corbi wrote: Is it a feature or a bug? It is allowed because the "auto" keyword doesn't actually required for auto functions (or variables), what you need is any one of the storage classes. Those include static, auto, const, immutable, even pure. If any of them are present, the compiler knows you are writing a function or declaring a variable and will infer the type. Thank's Adam!. I had figured out something like this but I couldn't find anything in the docs (http://dlang.org/spec/attribute.html#static), moreover, the example there: --8><- class Foo { static int bar() { return 6; } ... --8><- does mention the return type, that's what confused me.
Re: Needed return type in static method? bug or feature?
On Tuesday, 8 March 2016 at 13:40:06 UTC, Antonio Corbi wrote: Is it a feature or a bug? It is allowed because the "auto" keyword doesn't actually required for auto functions (or variables), what you need is any one of the storage classes. Those include static, auto, const, immutable, even pure. If any of them are present, the compiler knows you are writing a function or declaring a variable and will infer the type.
Needed return type in static method? bug or feature?
Hi all! The following code compiles and works, but the static methods do not have a return type. It also compiles and works if the appropiate (or auto) return type is added to them. -8>< import std.stdio; class B { int foo () { return 1; } static sbar () { return "hi!"; } static ibar () { return 0; } } void main () { auto b = new B; writeln (B.sbar); writeln (B.ibar); } -8><-------- Is it a feature or a bug? I've seen it being used in https://github.com/gecko0307/dlib/blob/master/dlib/math/matrix.d Thank's for your help!
Can't add ubytes together to make a ubyte... bug or feature?
I just attempted to add one ubyte to another and store the result in a ubyte but apparently ubytes get converted to ints when being added... and converting what becomes an int becomes impossible to store in a ubyte without an explicit cast... ubyte a, b; ubyte c = a + b; // Error: cannot implicitly convert expression (cast(int)a + cast(int)b) of type int to ubyte On principal I'm not casting to fix this. I don't care if my computer needs to do math on a 4 byte basis, I'm not writing assembly. I'm really hoping this is a bug because trying to use any type other than ints is going to make for some really ugly code otherwise... Can I prevent the initial implicit casts? On the topic of complaining about casting... array lengths as ulongs is painful... any chance of an array[].lengthi being a thing?
Re: Can't add ubytes together to make a ubyte... bug or feature?
Soviet Friend píše v Út 19. 01. 2016 v 22:12 +: > I just attempted to add one ubyte to another and store the result > in a ubyte but apparently ubytes get converted to ints when being > added... and converting what becomes an int becomes impossible to > store in a ubyte without an explicit cast... > > ubyte a, b; > ubyte c = a + b; // Error: cannot implicitly convert expression > (cast(int)a + cast(int)b) of type int to ubyte > Problem is that compiler does not know that a + b would fit in ubyte. For example if a would be 200 and b would be 100 it would not fit in ubyte. But if compiler can verify it will fit it makes cast implicit. immutable ubyte a = 0; ubyte b = 0; ubyte c = a + b; or ubyte a = 0; ubyte c = a + 0; or immutable ubyte a = 1; immutable ubyte b = 5; ubyte c = a + b; works ok but immutable ubyte a = 1; ubyte b = 0; ubyte c = a + b; can't works because b could be 255 and 255 + 1 does not fit to ubyte > On principal I'm not casting to fix this. I don't care if my > computer needs to do math on a 4 byte basis, I'm not writing > assembly. I'm really hoping this is a bug because trying to use > any type other than ints is going to make for some really ugly > code otherwise... > > Can I prevent the initial implicit casts? > > > On the topic of complaining about casting... array lengths as > ulongs is painful... any chance of an array[].lengthi being a > thing? array.length is not ulong is it size_t and I do not see any problem with that, can you be more specific.
Re: Can't add ubytes together to make a ubyte... bug or feature?
On Tue, 19 Jan 2016 23:32:57 +0100, Daniel Kozak wrote: > Soviet Friend píše v Út 19. 01. 2016 v 22:12 +: >> I just attempted to add one ubyte to another and store the result in a >> ubyte but apparently ubytes get converted to ints when being added... >> and converting what becomes an int becomes impossible to store in a >> ubyte without an explicit cast... >> >> ubyte a, b; >> ubyte c = a + b; // Error: cannot implicitly convert expression >> (cast(int)a + cast(int)b) of type int to ubyte >> >> > Problem is that compiler does not know that a + b would fit in ubyte. > For example if a would be 200 and b would be 100 it would not fit in > ubyte. But if compiler can verify it will fit it makes cast implicit. This is true for all integer types. The reason this isn't in effect for other types is that most values are small (eg array lengths), and most integer types can hold the sum of two small values. But there are plenty of small values where a [u]byte can't hold their sum.
Re: Can't add ubytes together to make a ubyte... bug or feature?
On 01/19/2016 02:12 PM, Soviet Friend wrote: > ubytes get converted to ints when being added... It's a common feature involving all integral type in languages like C, C++, and D: https://dlang.org/spec/type.html#integer-promotions > On the topic of complaining about casting... array lengths as ulongs is > painful... any chance of an array[].lengthi being a thing? That is a topic sometimes with hot debate without any resolution. Chances of it being changed in D is zero. :) Luckily, it's pretty easy in :D ;) long lengthi(T)(T[] arr) { import std.exception : enforce; import std.conv : to; // No overflow here because this comparison is performed in 'ulong' enforce(arr.length.to!ulong < long.max); return arr.length.to!long; } unittest { import std.traits; auto arr = [ 1, 2 ]; static assert(isSigned!(typeof(arr.lengthi))); assert(arr.lengthi == 2); } void main() { } Ali
Re: Can't add ubytes together to make a ubyte... bug or feature?
On Tuesday, 19 January 2016 at 22:12:06 UTC, Soviet Friend wrote: I don't care if my computer needs to do math on a 4 byte basis, I'm not writing assembly. x86 actually doesn't need to do math that way, if you were writing assembly, it would just work. This is just an annoying rule brought over by C. Can I prevent the initial implicit casts? Nope, though you can help tell the compiler that you want it to fit there by doing stuff like ubyte a = 200; ubyte b = 100; ubyte c = (a+b)&0xff; or something like that, so the expression is specifically proven to fit in the byte with compile time facts.
Re: SysTime bug or feature?
On Tuesday, 6 October 2015 at 05:54:44 UTC, Jonathan M Davis wrote: It is by design, albeit undesirable. When SysTime was originally written, it was impossible to have a default value for a class reference other than null. So, unless SysTime was going to take the performance hit of constantly checking whether its TimeZone was null, SysTime.init was going to segfault if you did anything with it that required its TimeZone. And I wasn't about to have it constantly checking for null. In the vast majority of cases, the value of a SysTime comes from Clock.currTime() or from parsing a string, and if code is trying to do anything but assign to a SysTime which is SysTime.init, then that means that it failed to initialize it like it should have. Thanks for thorough explanation. I found the problem using vibe and REST API with SysTime argument with default value (which didn't work due to the bug there) when I tried to print out the passed value and ended up with the segfault. So I guess it doesn't bite devs often as it is mostly used as you wrote.
SysTime bug or feature?
This code: import std.stdio; import std.datetime; void main() { SysTime t = SysTime.init; writeln(t); } results in segfault with dmd-2.068.2 Is it ok? Backtrace: #0 0x004733f3 in std.datetime.SysTime.adjTime() const () #1 0x004730b9 in std.datetime.SysTime.toSimpleString() const () #2 0x00473339 in std.datetime.SysTime.toString() const () #3 0x00463dc4 in std.format.formatObject!(std.stdio.File.LockingTextWriter, std.datetime.SysTime, char).formatObject(ref std.stdio.File.LockingTextWriter, ref std.datetime.SysTime, ref std.format.FormatSpec!(char).FormatSpec) () #4 0x00463cb7 in std.format.formatValue!(std.stdio.File.LockingTextWriter, std.datetime.SysTime, char).formatValue(std.stdio.File.LockingTextWriter, ref std.datetime.SysTime, ref std.format.FormatSpec!(char).FormatSpec) () #5 0x00463c5a in std.format.formatGeneric!(std.stdio.File.LockingTextWriter, std.datetime.SysTime, char).formatGeneric(std.stdio.File.LockingTextWriter, const(void)*, ref std.format.FormatSpec!(char).FormatSpec)---Type to continue, or q to quit--- () #6 0x00463b63 in std.format.formattedWrite!(std.stdio.File.LockingTextWriter, char, std.datetime.SysTime).formattedWrite(std.stdio.File.LockingTextWriter, const(char[]), std.datetime.SysTime) () #7 0x00463675 in std.stdio.File.write!(std.datetime.SysTime, char).write(std.datetime.SysTime, char) () #8 0x00463591 in std.stdio.writeln!(std.datetime.SysTime).writeln(std.datetime.SysTime) () #9 0x00461b38 in D main ()
Re: SysTime bug or feature?
On Monday, October 05, 2015 18:12:06 tchaloupka via Digitalmars-d-learn wrote: > This code: > > import std.stdio; > import std.datetime; > > void main() > { > SysTime t = SysTime.init; > writeln(t); > } > > results in segfault with dmd-2.068.2 > > Is it ok? It is by design, albeit undesirable. When SysTime was originally written, it was impossible to have a default value for a class reference other than null. So, unless SysTime was going to take the performance hit of constantly checking whether its TimeZone was null, SysTime.init was going to segfault if you did anything with it that required its TimeZone. And I wasn't about to have it constantly checking for null. In the vast majority of cases, the value of a SysTime comes from Clock.currTime() or from parsing a string, and if code is trying to do anything but assign to a SysTime which is SysTime.init, then that means that it failed to initialize it like it should have. At some point in the last couple of years, it became possible to directly initialize a class reference that was a member variable (or static, or at module level, etc.) with an immutable class object. So, when the issue that you're bringing up was brought up last year, I tried to create a new TimeZone class that would specifically be for SysTime.init so that SysTime.init would still be unique (so that st is SysTime.init would still work properly), and it would print out "SysTime.init" for toString and be treated as 1-01-01T00:00:00+00:00 for most everything else, but a compiler bugs with regards to Rebindable made it so that it didn't work. I need to take another stab at it and see if it works now, but until the compiler issue is resolved, SysTime.init will continue to segfault if you do anything with it which requires its TimeZone to be used (which includes toString). - Jonathan M Davis
Re: Bug or feature?
fix - https://github.com/D-Programming-Language/phobos/pull/3524
Re: Bug or feature?
On Monday, 29 June 2015 at 14:28:06 UTC, anonymous wrote: On Monday, 29 June 2015 at 12:04:46 UTC, Jonathan M Davis wrote: You haven't declared an immutable constructor, so you can't construct an immutable Foo. That's not what's happening. Constructing an immutable Foo works just fine. Then I stand corrected. - Jonathan M Davis
Re: Bug or feature?
On Sunday, June 28, 2015 11:37:59 Jack Applegame via Digitalmars-d-learn wrote: I don't see any reason why it should not compile. import std.array; import std.range; import std.algorithm; class Foo { } void main() { auto result = iota(3).map!(i = new immutable Foo).array(); } /usr/include/dmd/phobos/std/conv.d(4028): Error: cannot implicitly convert expression (arg) of type immutable(Foo) to test.Foo /usr/include/dmd/phobos/std/conv.d(3931): Error: template instance std.conv.emplaceImpl!(immutable(Foo)).emplaceImpl!(immutable(Foo)) error instantiating /usr/include/dmd/phobos/std/array.d(115):instantiated from here: emplaceRef!(immutable(Foo), Foo, immutable(Foo)) test.d(9):instantiated from here: array!(MapResult!(__lambda1, Result)) You haven't declared an immutable constructor, so you can't construct an immutable Foo. If the default constructor were pure, then it could be used to construct immutable objects even if it weren't immutable, but the default constructor is neither pure nor immutable, and purity isn't inferred for normal functions. It might make sense as a feature request to request that a class' default constructor be pure (assuming that its base class constructor is pure), since theoretically, it should be able to be pure, but that would be a change in the language. What you're seeing is not a bug. It's how the current design works. - Jonathan M Davis
Re: Bug or feature?
On Monday, 29 June 2015 at 12:04:46 UTC, Jonathan M Davis wrote: You haven't declared an immutable constructor, so you can't construct an immutable Foo. That's not what's happening. Constructing an immutable Foo works just fine.
Re: Bug or feature?
https://issues.dlang.org/show_bug.cgi?id=14751
Re: Bug or feature?
I'd say bug, I think the array function is trying an optimization it shouldn't be trying for immutable classes.
Re: Bug or feature?
On Mon, 29 Jun 2015 05:04:36 -0700 Jonathan M Davis via Digitalmars-d-learn digitalmars-d-learn@puremagic.com wrote: On Sunday, June 28, 2015 11:37:59 Jack Applegame via Digitalmars-d-learn wrote: I don't see any reason why it should not compile. import std.array; import std.range; import std.algorithm; class Foo { } void main() { auto result = iota(3).map!(i = new immutable Foo).array(); } /usr/include/dmd/phobos/std/conv.d(4028): Error: cannot implicitly convert expression (arg) of type immutable(Foo) to test.Foo /usr/include/dmd/phobos/std/conv.d(3931): Error: template instance std.conv.emplaceImpl!(immutable(Foo)).emplaceImpl!(immutable(Foo)) error instantiating /usr/include/dmd/phobos/std/array.d(115): instantiated from here: emplaceRef!(immutable(Foo), Foo, immutable(Foo)) test.d(9):instantiated from here: array!(MapResult!(__lambda1, Result)) You haven't declared an immutable constructor, so you can't construct an immutable Foo. If the default constructor were pure, then it could be used to construct immutable objects even if it weren't immutable, but the default constructor is neither pure nor immutable, and purity isn't inferred for normal functions. It might make sense as a feature request to request that a class' default constructor be pure (assuming that its base class constructor is pure), since theoretically, it should be able to be pure, but that would be a change in the language. What you're seeing is not a bug. It's how the current design works. - Jonathan M Davis No it is a bug in std.conv.emplaceRef or more probably in std.array.
Bug or feature?
I don't see any reason why it should not compile. import std.array; import std.range; import std.algorithm; class Foo { } void main() { auto result = iota(3).map!(i = new immutable Foo).array(); } /usr/include/dmd/phobos/std/conv.d(4028): Error: cannot implicitly convert expression (arg) of type immutable(Foo) to test.Foo /usr/include/dmd/phobos/std/conv.d(3931): Error: template instance std.conv.emplaceImpl!(immutable(Foo)).emplaceImpl!(immutable(Foo)) error instantiating /usr/include/dmd/phobos/std/array.d(115):instantiated from here: emplaceRef!(immutable(Foo), Foo, immutable(Foo)) test.d(9):instantiated from here: array!(MapResult!(__lambda1, Result))
Re: Bug or feature?
On 05/10/2015 10:18 AM, Jack Applegame wrote: code: class A { void test(int) {} } class B : A { void test() { super.test(1); // compiles test(10); // error } } Error: function B.test () is not callable using argument types (int) It is a concept called name hiding. It is intentional to prevent at least function hijacking. Ali
Re: Bug or feature?
On Sunday, May 10, 2015 10:48:33 Ali Çehreli via Digitalmars-d-learn wrote: On 05/10/2015 10:18 AM, Jack Applegame wrote: code: class A { void test(int) {} } class B : A { void test() { super.test(1); // compiles test(10); // error } } Error: function B.test () is not callable using argument types (int) It is a concept called name hiding. It is intentional to prevent at least function hijacking. Yeah. You have to alias A's overloads inside of B or explicitly declare them as overrides and call the A versions from inside them. So, something like alias A.test test; or alias test = A.test; inside of B should work (though I haven't done it recently, so the syntax might be slightly off), or you can just do override void test(int i) { super.test(i); } - Jonathan M Davis
Re: Bug or feature?
Jack Applegame wrote: test(10); // error One can import the declaration by using an alias: class A { void test(int) {} } class B : A { alias test= super.test; void test() { super.test(1); // compiles test(10); // compiles } } -manfred
Bug or feature?
code: class A { void test(int) {} } class B : A { void test() { super.test(1); // compiles test(10); // error } } Error: function B.test () is not callable using argument types (int)
Re: Bug or feature?
Ok, it's a feature. Thanks.
bug or feature? shared objects and tuples
It is impossible to pack a structure with shared object into tuple. ``` import std.concurrency; import std.typecons; class Foo {} struct A { shared Foo foo; } void main() { auto a = tuple(new shared Foo); // ОК auto b = tuple(A());// Error: static assert unable to format shared objects } ```
Re: bug or feature? shared objects and tuples
On 8/27/13, Jack Applegame jappleg...@gmail.com wrote: It is impossible to pack a structure with shared object into tuple. Bug. Please file it to bugzilla: http://d.puremagic.com/issues/enter_bug.cgi?product=D Thanks!
Re: bug or feature? shared objects and tuples
On Monday, 26 August 2013 at 23:04:24 UTC, Andrej Mitrovic wrote: Bug. Please file it to bugzilla: http://d.puremagic.com/issues/enter_bug.cgi?product=D Thanks! http://d.puremagic.com/issues/show_bug.cgi?id=10907
Re: Bug or feature?
Well, how you can reduce the long ugly name in this case? In the real function I mentioned it so many times.
Re: Bug or feature?
void foo( S s ) { auto local = this.bigUglyName; auto b = s.bigUglyName; writeln( bigUglyName (AKA local)=, local, b=, b ); } :P
Re: Bug or feature?
On Monday, 27 May 2013 at 10:17:01 UTC, Namespace wrote: void foo( S s ) { auto local = this.bigUglyName; auto b = s.bigUglyName; writeln( bigUglyName (AKA local)=, local, b=, b ); } :P By the way, yes. Thanks for that, I'm stupid today.
Re: Bug or feature?
On Monday, 27 May 2013 at 10:07:49 UTC, mimi wrote: Well, how you can reduce the long ugly name in this case? In the real function I mentioned it so many times. By not making the name ugly big.
Re: Bug or feature?
On Monday, 27 May 2013 at 11:32:46 UTC, Maxim Fomin wrote: On Monday, 27 May 2013 at 10:07:49 UTC, mimi wrote: Well, how you can reduce the long ugly name in this case? In the real function I mentioned it so many times. By not making the name ugly big. Other people do. In addition, sometimes you want to cut long nested queries such as: auto numOfPixelsDisplayed = Table.getItems( Scene.getObjectsArray() ).prepareForDisplay( type.GL ).showScene();
Bug or feature?
import std.stdio; struct S { int bigUglyName; void foo( S s ) { alias bigUglyName local; alias s.bigUglyName b; writeln( bigUglyName (AKA local)=, local, b=, b ); } } void main() { S s1; S s2; s1.bigUglyName = 1; s2.bigUglyName = 2; s1.foo( s2 ); } returns to console: bigUglyName (AKA local)=1 b=1 Why? I am expected that b=2
Re: Bug or feature?
On Sunday, 26 May 2013 at 23:35:43 UTC, mimi wrote: import std.stdio; struct S { int bigUglyName; void foo( S s ) { alias bigUglyName local; alias s.bigUglyName b; writeln( bigUglyName (AKA local)=, local, b=, b ); } } void main() { S s1; S s2; s1.bigUglyName = 1; s2.bigUglyName = 2; s1.foo( s2 ); } returns to console: bigUglyName (AKA local)=1 b=1 Why? I am expected that b=2 alias does not capture this pointer, it is rewritten as S.bigUglyName and you can refer to non-static fields as Type.member which is this.member in member functions (in D semantic differences of accessing static and non-static members are diluted)
Re: Appending immutable char implicit cast to int, bug or feature?
I don't know where that cast occurs but I wanted to state the obvious: Operator ~ is defined only for arrays. Would having it also work for individual units to make an array be a plausible enhancement request? It would seem like a natural use of the operator.
Appending immutable char implicit cast to int, bug or feature?
This is simple code to create all genetic combinations from two organisms. string[] mixGenes(string a, string b) { string[] result; foreach(i;0..2) foreach(j;0..2) foreach(k;2..4) foreach(m;2..4) result ~= [a[i]] ~ [b[j]] ~ [a[k]] ~ [b[m]]; return result; } This works, however when I remove the brackets: result ~= a[i] ~ b[j] ~ a[k] ~ b[m]; I get the error: Error: incompatible types for ((cast(int)a[cast(uint)i]) ~ (cast(int)b[cast(uint)j])): 'int' and 'int' Why, when trying to append immutable chars to make a string, has it decided to implicitly cast them to int?
Appending immutable char implicit cast to int, bug or feature?
This is simple code to create all genetic combinations from two organisms. string[] mixGenes(string a, string b) { string[] result; foreach(i;0..2) foreach(j;0..2) foreach(k;2..4) foreach(m;2..4) result ~= [a[i]] ~ [b[j]] ~ [a[k]] ~ [b[m]]; return result; } This works, however when I remove the brackets: result ~= a[i] ~ b[j] ~ a[k] ~ b[m]; I get the error: Error: incompatible types for ((cast(int)a[cast(uint)i]) ~ (cast(int)b[cast(uint)j])): 'int' and 'int' Why, when trying to append immutable chars to make a string, has it decided to implicitly cast them to int?
Re: Appending immutable char implicit cast to int, bug or feature?
On 12/05/2012 09:30 AM, ixid wrote: This is simple code to create all genetic combinations from two organisms. string[] mixGenes(string a, string b) { string[] result; foreach(i;0..2) foreach(j;0..2) foreach(k;2..4) foreach(m;2..4) result ~= [a[i]] ~ [b[j]] ~ [a[k]] ~ [b[m]]; return result; } This works, however when I remove the brackets: result ~= a[i] ~ b[j] ~ a[k] ~ b[m]; I get the error: Error: incompatible types for ((cast(int)a[cast(uint)i]) ~ (cast(int)b[cast(uint)j])): 'int' and 'int' Why, when trying to append immutable chars to make a string, has it decided to implicitly cast them to int? I don't know where that cast occurs but I wanted to state the obvious: Operator ~ is defined only for arrays. Ali
Re: Bug or feature? std.c.stdlib.exit() breaks RAII
On 29/12/2011 19:09, Jacob Carlborg wrote: snip excessive quote Could druntime hook up on the atexit function to run destructors and similar when the program exits? I'm not sure. Maybe it could be called upon to run static destructors and destruct heap-allocated objects. But in order to call scope guards and RAII, it would need to unwind the call stack, which could get complicated if you're trying to do it from within a function. It's much simpler not to use exit() and throw a custom exception instead. Stewart.
Re: Bug or feature? std.c.stdlib.exit() breaks RAII
That should have been int main.
Re: Bug or feature? std.c.stdlib.exit() breaks RAII
On Thursday, December 29, 2011 23:03:23 Ashish Myles wrote: Since D could conceivably implement a very safe exit() without an explicit use of Exceptions to get around the catch Exception() {} problem you mentioned above, does it make sense to request a safer exit() feature for D? And how would it do that? The only way in the language to properly unwind the stack without returning from each and every function is to throw an Exception. If you wanted to do an exit function, it would somehow have to do the exact same thing that happens when you throw an Exception except that it's not an Exception and isn't caught by catch(Exception) {}. That may not be impossible, but I expect that it would complicate things quite a bit. And scope statements are designed around exceptions such that if you didn't throw an Exception, they wouldn't work properly. The same goes for finally blocks. Also, what is the correct thing to do in a situation like this try { //code } catch(Exception e) { //do stuff } The code in the catch block assumes that it's always going to be run when the code in the try block is not properly completed. If an exit call were made from within the try block (be it directly in it or in a function that was called inside it), how would the catch block be handled? Without an Exception, it would be skipped, what's in that catch block wouldn't be run, and there would be no proper cleanup. The very concept of exit violates how the language functions with regards to stack unwinding. Stack unwinding is built around how exceptions function. exit, on the other hand, tries to avoid the whole exception thing and just kill your program. But ultimately, you _can't_ ignore the fact that in order to ensure proper stack unwinding, you either need to return from each function on the stack, or throw an Exception from them. Anything else is going to fail to unwind the stack properly. And honestly, I would generally consider it bad practice to use an exit function. It violates the proper flow of the program - as the issues with stack unwinding illustrate. If you want to do the equivalent of an exit function and have proper cleanup occur, you really need to be throw an Exception designated for that and have your code let it pass all the way through to main so that it can exit properly after having unwound the stack. - Jonathan M Davis
Re: Bug or feature? std.c.stdlib.exit() breaks RAII
On Fri, Dec 30, 2011 at 5:43 AM, Jonathan M Davis jmdavisp...@gmx.com wrote: On Thursday, December 29, 2011 23:03:23 Ashish Myles wrote: Since D could conceivably implement a very safe exit() without an explicit use of Exceptions to get around the catch Exception() {} problem you mentioned above, does it make sense to request a safer exit() feature for D? And how would it do that? The only way in the language to properly unwind the stack without returning from each and every function is to throw an Exception. If you wanted to do an exit function, it would somehow have to do the exact same thing that happens when you throw an Exception except that it's not an Exception and isn't caught by catch(Exception) {}. That may not be impossible, but I expect that it would complicate things quite a bit. And scope statements are designed around exceptions such that if you didn't throw an Exception, they wouldn't work properly. The same goes for finally blocks. Also, what is the correct thing to do in a situation like this Ok, now there are two issues here: IMPLEMENTATION: Implementation of a safe_exit() without an explicit Exception seems to be easy to do at the language level for a single-threaded program -- you simply have a hidden/system class like, say, __SystemException from which Exception derives that be comes the base class of all throwable objects. __ExitException could then derive from __SystemException and store the exit value. But it is not clear how this would work for multithreaded programs, with which I have little experience in the context of C++ exceptions. Presumably, the __ExitException would have to be thrown in all threads and could interrupt functions that would otherwise not throw exceptions -- I can't say I understand all the implications. try { //code } catch(Exception e) { //do stuff } The code in the catch block assumes that it's always going to be run when the code in the try block is not properly completed. If an exit call were made from within the try block (be it directly in it or in a function that was called inside it), how would the catch block be handled? Without an Exception, it would be skipped, what's in that catch block wouldn't be run, and there would be no proper cleanup. For cleanup that needs to be done no matter what the exception, I would just use a finally{} block. UTILITY: Now, the actual utility of having a safe exit seems to be in question here. A common use of this is in OpenGL programs (that may be implicitly multithreaded) where the keyboard handler exit()s when I hit 'q' or ESC (which is quite common). Moreover, the underlying GUI framework or other APIs being used may conceivably have multiple threads and abstract this out for the user. Is this an unreasonable use case for a safe exit? Or would this be too difficult to implement cleanly?
Re: Bug or feature? std.c.stdlib.exit() breaks RAII
On Friday, December 30, 2011 10:45:43 Ashish Myles wrote: Ok, now there are two issues here: IMPLEMENTATION: Implementation of a safe_exit() without an explicit Exception seems to be easy to do at the language level for a single-threaded program -- you simply have a hidden/system class like, say, __SystemException from which Exception derives that be comes the base class of all throwable objects. __ExitException could then derive from __SystemException and store the exit value. But it is not clear how this would work for multithreaded programs, with which I have little experience in the context of C++ exceptions. Presumably, the __ExitException would have to be thrown in all threads and could interrupt functions that would otherwise not throw exceptions -- I can't say I understand all the implications. It's more complicate than that. The base class of all throwable objects is Throwable. Error and Exception are derived from Throwable. Destructors, finally blocks, and scope statements are all skipped when a Throwable is thrown unless it is derived from Exception. So, there is no proper cleanup unless an Exception is thrown. Right now, the compiler, the runtime, and programmers can all assume that try { //code //1 } catch(Exception e) { //2 } either #1 or #2 will be hit in that code if proper cleanup is occuring. In fact nothrow relies on this. If you wrap a function call in a try-catch block which catches Exception, then the function it's called in can be nothrow even if the function being called throws an exception. If we tried to have another exception type which was for exiting, then you'd get this weird situation where nothrow functions _can_ throw when the program is being shutdown properly, and that could be a big problem. Functions in D are set up around the idea that the only way to exit a function and have proper cleanup occur is to either return from it or have an Exception thrown from it. You're trying to have another way added. It's not that it's necessarily impossible, but it would likely require the redesign of several features and would break the assumptions made by a lot of code. For cleanup that needs to be done no matter what the exception, I would just use a finally{} block. Yes and no. finally gets hit whether an Exception is thrown or the try block is exited normally, but it isn't run when a non-Exception Throwable (generally an Error) is thrown, so it gurantees nothing on unsafe shutdown. And if you were using exit, what would be the proper behavior? Neither the remainder of the try block nor the catch block would be run (since exit would skip the rest of the try block and skip the catch block entirely), which would likely break the assumptions made by a lot of code. It would certainly break scope. All of a sudden, you have something other than Error which won't hit scope(success) or scope(failure) but _will_ hit scope(exit), and that something is trying to be exiting _cleanly_ - unlike Error. UTILITY: Now, the actual utility of having a safe exit seems to be in question here. A common use of this is in OpenGL programs (that may be implicitly multithreaded) where the keyboard handler exit()s when I hit 'q' or ESC (which is quite common). Moreover, the underlying GUI framework or other APIs being used may conceivably have multiple threads and abstract this out for the user. Is this an unreasonable use case for a safe exit? Or would this be too difficult to implement cleanly? Exceptions only affect a single thread, so they're not going to help you terminate a multi-threaded program regardless. And to terminate another thread, you need a way to terminate it. The only ways to do that are to tell them to terminate themselves or to kill them. There is no way that I'm aware of built into threads to tell them that it's time to shutdown and then let them do it cleanly (which is what you'd need for a clean shutdown). You could use std.concurrency to inform them to shutdown or have a shared flag which indicates that it's time for all threads to shutdown, but you couldn't use pthreads or the Windows equivalent to tell a thread to shutdown cleanly. So, the only means generally available to terminate a thread is to forcibly kill it (as C's exit does), making automatic cleanup impossible. _Some_ cleanup can be done when exit is called using atexit and on_exit, but the stack won't be unwound properly, so RAII, scope statements, and finally blocks aren't going to be run properly. So, critical, global stuff can be potentially cleaned up, but you can't get a fully clean shutdown without actually returning or having an Exception thrown from every function in every thread. So, in general, the best way to handle taking down a multi-threaded application cleanly is to message each thread (be it via std.concurrency or a flag or whatever) which isn't going to shutdown on its own (e.g. after finishing some calculation)
Re: Bug or feature? std.c.stdlib.exit() breaks RAII
Thanks, Jonathan, for your detailed answer. Ashish On Fri, Dec 30, 2011 at 1:41 PM, Jonathan M Davis jmdavisp...@gmx.com wrote: On Friday, December 30, 2011 10:45:43 Ashish Myles wrote: Ok, now there are two issues here: IMPLEMENTATION: Implementation of a safe_exit() without an explicit Exception seems to be easy to do at the language level for a single-threaded program -- you simply have a hidden/system class like, say, __SystemException from which Exception derives that be comes the base class of all throwable objects. __ExitException could then derive from __SystemException and store the exit value. But it is not clear how this would work for multithreaded programs, with which I have little experience in the context of C++ exceptions. Presumably, the __ExitException would have to be thrown in all threads and could interrupt functions that would otherwise not throw exceptions -- I can't say I understand all the implications. It's more complicate than that. The base class of all throwable objects is Throwable. Error and Exception are derived from Throwable. Destructors, finally blocks, and scope statements are all skipped when a Throwable is thrown unless it is derived from Exception. So, there is no proper cleanup unless an Exception is thrown. Right now, the compiler, the runtime, and programmers can all assume that try { //code //1 } catch(Exception e) { //2 } either #1 or #2 will be hit in that code if proper cleanup is occuring. In fact nothrow relies on this. If you wrap a function call in a try-catch block which catches Exception, then the function it's called in can be nothrow even if the function being called throws an exception. If we tried to have another exception type which was for exiting, then you'd get this weird situation where nothrow functions _can_ throw when the program is being shutdown properly, and that could be a big problem. Functions in D are set up around the idea that the only way to exit a function and have proper cleanup occur is to either return from it or have an Exception thrown from it. You're trying to have another way added. It's not that it's necessarily impossible, but it would likely require the redesign of several features and would break the assumptions made by a lot of code. For cleanup that needs to be done no matter what the exception, I would just use a finally{} block. Yes and no. finally gets hit whether an Exception is thrown or the try block is exited normally, but it isn't run when a non-Exception Throwable (generally an Error) is thrown, so it gurantees nothing on unsafe shutdown. And if you were using exit, what would be the proper behavior? Neither the remainder of the try block nor the catch block would be run (since exit would skip the rest of the try block and skip the catch block entirely), which would likely break the assumptions made by a lot of code. It would certainly break scope. All of a sudden, you have something other than Error which won't hit scope(success) or scope(failure) but _will_ hit scope(exit), and that something is trying to be exiting _cleanly_ - unlike Error. UTILITY: Now, the actual utility of having a safe exit seems to be in question here. A common use of this is in OpenGL programs (that may be implicitly multithreaded) where the keyboard handler exit()s when I hit 'q' or ESC (which is quite common). Moreover, the underlying GUI framework or other APIs being used may conceivably have multiple threads and abstract this out for the user. Is this an unreasonable use case for a safe exit? Or would this be too difficult to implement cleanly? Exceptions only affect a single thread, so they're not going to help you terminate a multi-threaded program regardless. And to terminate another thread, you need a way to terminate it. The only ways to do that are to tell them to terminate themselves or to kill them. There is no way that I'm aware of built into threads to tell them that it's time to shutdown and then let them do it cleanly (which is what you'd need for a clean shutdown). You could use std.concurrency to inform them to shutdown or have a shared flag which indicates that it's time for all threads to shutdown, but you couldn't use pthreads or the Windows equivalent to tell a thread to shutdown cleanly. So, the only means generally available to terminate a thread is to forcibly kill it (as C's exit does), making automatic cleanup impossible. _Some_ cleanup can be done when exit is called using atexit and on_exit, but the stack won't be unwound properly, so RAII, scope statements, and finally blocks aren't going to be run properly. So, critical, global stuff can be potentially cleaned up, but you can't get a fully clean shutdown without actually returning or having an Exception thrown from every function in every thread. So, in general, the best way to handle taking down a multi-threaded application cleanly is to message
Re: Bug or feature? std.c.stdlib.exit() breaks RAII
On 2011-12-29 18:22, Jakob Ovrum wrote: On Thursday, 29 December 2011 at 16:27:33 UTC, Ashish Myles wrote: std.c.stdlib.exit() seems to break RAII. The code below tests this both using a struct destructor and an explicit scope(exit) {}. Is this an intentional feature or a bug? import std.stdio; import std.c.stdlib; void main() { struct SafeExit { ~this() { writeln(Safely exit with destructor.); } } SafeExit safeExit; scope(exit) { writeln(Safely exit with scope(exit).); } scope(failure) { writeln(Safely exit with scope(failure).); } writeln(Test if std.c.stdlib.exit() breaks RAII.); writeln(Pre-exit!); std.c.stdlib.exit(0); writeln(Post-exit! Should not get here!); } The C runtime is beyond D's immediate control. You would have to replace C's exit function with a custom one or make the compiler recognize calls to it. Calling 'exit' doesn't properly shut down the D runtime either, it's not just constructors. It's neither a bug or a feature. The bug is arguably in your program. Could druntime hook up on the atexit function to run destructors and similar when the program exits? -- /Jacob Carlborg
Re: Bug or feature? std.c.stdlib.exit() breaks RAII
Probably the easiest thing to do is to throw a custom exception and catch it somewhere in main() to return your status code. Unlike exit(), throwing will take care of RAII stuff.
Re: Bug or feature? std.c.stdlib.exit() breaks RAII
On Thu, Dec 29, 2011 at 1:26 PM, Andrej Mitrovic andrej.mitrov...@gmail.com wrote: Probably the easiest thing to do is to throw a custom exception and catch it somewhere in main() to return your status code. Unlike exit(), throwing will take care of RAII stuff. Thanks, Andrej. That option had occurred to me, but I figured that shouldn't be the way to do things given that most other languages have a native exit function. Given that this code transformation isn't particularly difficult (put main in a try/catch, have a custom exception storing exit code, return the exit code in the catch block), would it be reasonable to do a feature request for a D-language-supported exit()?
Re: Bug or feature? std.c.stdlib.exit() breaks RAII
On Thursday, 29 December 2011 at 16:27:33 UTC, Ashish Myles wrote: std.c.stdlib.exit() seems to break RAII. The code below tests this both using a struct destructor and an explicit scope(exit) {}. Is this an intentional feature or a bug? import std.stdio; import std.c.stdlib; void main() { struct SafeExit { ~this() { writeln(Safely exit with destructor.); } } SafeExit safeExit; scope(exit) { writeln(Safely exit with scope(exit).); } scope(failure) { writeln(Safely exit with scope(failure).); } writeln(Test if std.c.stdlib.exit() breaks RAII.); writeln(Pre-exit!); std.c.stdlib.exit(0); writeln(Post-exit! Should not get here!); } The C runtime is beyond D's immediate control. You would have to replace C's exit function with a custom one or make the compiler recognize calls to it. Calling 'exit' doesn't properly shut down the D runtime either, it's not just constructors. It's neither a bug or a feature. The bug is arguably in your program.
Re: Bug or feature? std.c.stdlib.exit() breaks RAII
On Thursday, 29 December 2011 at 17:22:33 UTC, Jakob Ovrum wrote: Calling 'exit' doesn't properly shut down the D runtime either, it's not just constructors. I mean destructors*.
Re: Bug or feature? std.c.stdlib.exit() breaks RAII
On 12/29/2011 12:43 PM, Ashish Myles wrote: On Thu, Dec 29, 2011 at 1:26 PM, Andrej Mitrovic andrej.mitrov...@gmail.com wrote: Probably the easiest thing to do is to throw a custom exception and catch it somewhere in main() to return your status code. Unlike exit(), throwing will take care of RAII stuff. Thanks, Andrej. That option had occurred to me, but I figured that shouldn't be the way to do things given that most other languages have a native exit function. Given that this code transformation isn't particularly difficult (put main in a try/catch, have a custom exception storing exit code, return the exit code in the catch block), would it be reasonable to do a feature request for a D-language-supported exit()? Yeah, really. I'd been using the C exit() as well. Seems like a pretty fundamental feature. :O
Re: Bug or feature? std.c.stdlib.exit() breaks RAII
On Thursday, December 29, 2011 13:43:36 Ashish Myles wrote: On Thu, Dec 29, 2011 at 1:26 PM, Andrej Mitrovic andrej.mitrov...@gmail.com wrote: Probably the easiest thing to do is to throw a custom exception and catch it somewhere in main() to return your status code. Unlike exit(), throwing will take care of RAII stuff. Thanks, Andrej. That option had occurred to me, but I figured that shouldn't be the way to do things given that most other languages have a native exit function. Given that this code transformation isn't particularly difficult (put main in a try/catch, have a custom exception storing exit code, return the exit code in the catch block), would it be reasonable to do a feature request for a D-language-supported exit()? A D exit function would have to do essentially the same thing as throw an exception and catch it in main anyway. The only way that the stack is going to be unwound properly is if you actually unwind it. The only way in the language to do that without actually returning from each and every function on the stack is to throw an exception. How many modern languages do you know of with an exit function that cleans everything up properly? C++ won't for the same reasons that D won't. Java gets away with it because it doesn't have destructors or scope statements or anything else that would actually require unwinding the stack. All a D exit function _could_ do would be to throw an exception and then have the runtime catch it - which still wouldn't work if the programmer was foolish enough to do something like catch(Exception) {} in their code. So, throwing an exception and catching it _is_ the way to do it, and it really makes more sense if you're doing it yourself, since then you're less likely to make that mistake and catch all Exceptions somewhere in your code and eat the one which is supposed to exit the program. - Jonathan M Davis
Re: Bug or feature? std.c.stdlib.exit() breaks RAII
On Thu, Dec 29, 2011 at 7:16 PM, Jonathan M Davis jmdavisp...@gmx.com wrote: A D exit function would have to do essentially the same thing as throw an exception and catch it in main anyway. The only way that the stack is going to be unwound properly is if you actually unwind it. The only way in the language to do that without actually returning from each and every function on the stack is to throw an exception. How many modern languages do you know of with an exit function that cleans everything up properly? C++ won't for the same reasons that D won't. Java gets away with it because it doesn't have destructors or scope statements or anything else that would actually require unwinding the stack. All a D exit function _could_ do would be to throw an exception and then have the runtime catch it - which still wouldn't work if the programmer was foolish enough to do something like catch(Exception) {} in their code. So, throwing an exception and catching it _is_ the way to do it, and it really makes more sense if you're doing it yourself, since then you're less likely to make that mistake and catch all Exceptions somewhere in your code and eat the one which is supposed to exit the program. - Jonathan M Davis Hm...embarassingly, it didn't occur to me that C++ didn't clean up either; but sure enough, the following code shows that exit() breaks C++ RAII. #include iostream #include cstdlib struct SafeExit { ~SafeExit() { std::cout Safely exit with destructor. std::endl; } }; int main(int argc, char** argv) { SafeExit safeExit; std::cout Test if std.c.stdlib.exit() breaks RAII. std::endl; std::cout Pre-exit! std::endl; exit(0); std::cout Post-exit! Should not get here! std::endl; return 0; } On the other hand, ruby happily *does* unwind the stack properly on exit(). def safe_exit begin yield ensure puts Safely exit with ensure. end end safe_exit do puts Test if std.c.stdlib.exit() breaks RAII. puts Pre-exit! exit(0); puts Post-exit! Should not get here! end Honestly, I would rather have the latter robustness. While I have always thought of abort() as being a dirty exit, I had, until now, always thought of exit() as being very safe. Violating RAII on a safely-intended exit() is a really Bad Thing, I would think. Since D could conceivably implement a very safe exit() without an explicit use of Exceptions to get around the catch Exception() {} problem you mentioned above, does it make sense to request a safer exit() feature for D? Ashish
struct opEquals does not work with parameter of same type - bug or feature?
I am trying to build a struct with equality testing, using this code: struct Foo { const bool opEquals(Foo f) { return true; } } This gives me the error that the parameter should be of type ref const Foo. Fine. struct Foo { const bool opEquals(ref const Foo f) { return true; } } This, however, does not work with code like: Foo bar() { return Foo(); } assert(Foo() == bar()); function Foo.opEquals(ref const const(Foo) f) const is not callable using argument types (Foo) and bar() is not an lvalue. How can I do this?
Re: struct opEquals does not work with parameter of same type - bug or feature?
On Monday, August 29, 2011 22:41:26 Sean Eskapp wrote: I am trying to build a struct with equality testing, using this code: struct Foo { const bool opEquals(Foo f) { return true; } } This gives me the error that the parameter should be of type ref const Foo. Fine. struct Foo { const bool opEquals(ref const Foo f) { return true; } } This, however, does not work with code like: Foo bar() { return Foo(); } assert(Foo() == bar()); function Foo.opEquals(ref const const(Foo) f) const is not callable using argument types (Foo) and bar() is not an lvalue. How can I do this? http://d.puremagic.com/issues/show_bug.cgi?id=3659 http://stackoverflow.com/questions/6986175/const-ref-and-rvalue-in-d - Jonathan M Davis
Re: struct opEquals does not work with parameter of same type - bug or feature?
== Quote from Jonathan M Davis (jmdavisp...@gmx.com)'s article On Monday, August 29, 2011 22:41:26 Sean Eskapp wrote: I am trying to build a struct with equality testing, using this code: struct Foo { const bool opEquals(Foo f) { return true; } } This gives me the error that the parameter should be of type ref const Foo. Fine. struct Foo { const bool opEquals(ref const Foo f) { return true; } } This, however, does not work with code like: Foo bar() { return Foo(); } assert(Foo() == bar()); function Foo.opEquals(ref const const(Foo) f) const is not callable using argument types (Foo) and bar() is not an lvalue. How can I do this? http://d.puremagic.com/issues/show_bug.cgi?id=3659 http://stackoverflow.com/questions/6986175/const-ref-and-rvalue-in-d - Jonathan M Davis Ah, thanks!