digitalmars.D - clear()
- Marco Leise (22/22) Sep 11 2011 Can someone clarify things for me? So I use .clear() as usual to clear m...
- Michel Fortin (23/29) Sep 12 2011 http://www.digitalmars.com/d/archives/digitalmars/D/bugs/Issue_5683_New_...
- Steven Schveighoffer (9/22) Sep 12 2011 While I share your sentiment that clear is too useful a term to be
- Michel Fortin (32/56) Sep 12 2011 It can "blow up" when the destructor is called twice and the destructor
- Steven Schveighoffer (46/95) Sep 12 2011 d:
- Michel Fortin (23/30) Sep 12 2011 struct S
- Andrei Alexandrescu (11/21) Sep 12 2011 Nope, the way Walter designed the feature, when such a struct is a
- Steven Schveighoffer (41/69) Sep 13 2011 That is a brand new feature that was added after clear was implemented, ...
- sclytrack (4/4) Sep 13 2011 Rename "clear" to "blank" in D version 3.
- Alix Pexton (3/7) Sep 13 2011 wipe(); //??
- Dmitry Olshansky (6/17) Sep 13 2011 my favorite still:
- Simen Kjaeraas (7/25) Sep 14 2011 That's actually kinda nice. Unlikely to be used for much else,
Can someone clarify things for me? So I use .clear() as usual to clear my arrays and associative arrays. But a post by Jonathan M Davis in D.learn made me realize that same name is used to call a destructor on an object and now I wonder if clear() was ever supposed to be called on associative arrays and what the official way is to reset the contents of an associative array (except for solutions containing null and foreach :) ). clear() is well established and known to set the container length to 0 (releasing references and destroying owned objects, often keeping the capacity) as seen in these references of container types in various languages: (C++ STL) http://www.cplusplus.com/reference/stl/vector/clear/ (.NET) http://msdn.microsoft.com/en-us/library/dwb5h52a.aspx (Pascal) http://www.freepascal.org/docs-html/rtl/classes/tlist.clear.html (Ruby) http://www.ruby-doc.org/core/classes/Array.html#M000263 Is there a reason why the method that calls the destructor hasn't been called 'deinit', 'destruct', 'invalidate' or 'destroy' instead? And are these bug reports in fact invalid as per specification of clear() ? http://www.digitalmars.com/d/archives/digitalmars/D/bugs/Issue_5816_New_clear_breaks_associative_array_29122.html http://www.digitalmars.com/d/archives/digitalmars/D/bugs/Issue_5683_New_Calling_.clear_on_a_fresh_associative_array_causes_subsequent_segfault_28632.html I'm confused :p - Marco
Sep 11 2011
On 2011-09-11 10:23:21 +0000, "Marco Leise" <Marco.Leise gmx.de> said:Is there a reason why the method that calls the destructor hasn't been called 'deinit', 'destruct', 'invalidate' or 'destroy' instead?Probably to confuse people.And are these bug reports in fact invalid as per specification of clear() ? http://www.digitalmars.com/d/archives/digitalmars/D/bugs/Issue_5816_New_clear_breaks_associative_array_29122.htmlhttp://www.digitalmars.com/d/archives/digitalmars/D/bugs/Issue_5683_New_Calling_.clear_on_a_fresh_associative_array_causes_subsequent_segfault_28632.html Seemslike they are indeed invalid. Clear is working as intended, and is confusing people.I'm confused :pSee, it works! Enough sarcasm. If I recall, Andrei liked the name 'clear' and was unsympathetic to the arguments that it'd be confusing. 'clear' is explained in TDPL and Andrei doesn't like to break his book, so we might be stuck with that mess for while. But I think it's clear by now that that 'clear' is confusing and dangerous: it will work with certain types and completely blow up with others depending on implementation details of the type (calling the destructor twice, it's insane!). And the name just make it sounds like it's something pretty normal to do, which is probably the worse part of it. Actually no, the worse part is probably that it's inside module 'object', the only module imported by default everywhere, so you can't even escape the confusion by not importing its module. :-( -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Sep 12 2011
On Mon, 12 Sep 2011 07:12:19 -0400, Michel Fortin <michel.fortin michelf.com> wrote:On 2011-09-11 10:23:21 +0000, "Marco Leise" <Marco.Leise gmx.de> said: Enough sarcasm. If I recall, Andrei liked the name 'clear' and was unsympathetic to the arguments that it'd be confusing. 'clear' is explained in TDPL and Andrei doesn't like to break his book, so we might be stuck with that mess for while. But I think it's clear by now that that 'clear' is confusing and dangerous: it will work with certain types and completely blow up with others depending on implementation details of the type (calling the destructor twice, it's insane!). And the name just make it sounds like it's something pretty normal to do, which is probably the worse part of it. Actually no, the worse part is probably that it's inside module 'object', the only module imported by default everywhere, so you can't even escape the confusion by not importing its module. :-(While I share your sentiment that clear is too useful a term to be relegated to only be "call the destructor" (in fact, I use clear as a member function in my dcollections library, which probably adds to the confusion), I still think that the function should work. What types does it "blow up" on? What types does it call the destructor twice? I'd like to fix these. -Steve
Sep 12 2011
On 2011-09-12 11:37:20 +0000, "Steven Schveighoffer" <schveiguy yahoo.com> said:On Mon, 12 Sep 2011 07:12:19 -0400, Michel Fortin <michel.fortin michelf.com> wrote:It can "blow up" when the destructor is called twice and the destructor doesn't expect this. The destructor will be called twice when you use it on a struct variable on the stack. You'll probably say it shouldn't be used on stack variables, but if something work, especially if it looks pretty and appropriate like 'clear' does, people will use it anyway and write programs that'll break later when the implementation behind an API changes. Remember that this problem couldn't happen with 'delete'… 'clear' conflates two things: restoring the object to its pristine state, and releasing resources. It does succeed at releasing resources, but only because it reaches half of the former goal. I think it'd be much wiser to have two different functions for these two concepts. I think 'delete' is the one that should be tasked with releasing resources. Just change 'delete' so it calls the destructor, wipes all the bits, but keep the memory block alive so it gets collected later by the GC, keeping things memory-safe. There's absolutely no point in reinstating the original 'init' bits if what you want is to destroy the object. 'delete' only works with memory allocated on the heap, not stack variables, not memory allocated elsewhere, so it's easy to make sure destructors don't get called twice because that's a bit in the GC's block flags. Then you can make 'clear' a function that actually does what people expects it to do: restore the object to its pristine state: calling the destructor, reinstating the 'init' bits, then calling constructor again if necessary. It could be safe to call on stack variables, and it could fail if the default constructor is disabled (like in NotNull!T). -- Michel Fortin michel.fortin michelf.com http://michelf.com/On 2011-09-11 10:23:21 +0000, "Marco Leise" <Marco.Leise gmx.de> said: Enough sarcasm. If I recall, Andrei liked the name 'clear' and was unsympathetic to the arguments that it'd be confusing. 'clear' is explained in TDPL and Andrei doesn't like to break his book, so we might be stuck with that mess for while. But I think it's clear by now that that 'clear' is confusing and dangerous: it will work with certain types and completely blow up with others depending on implementation details of the type (calling the destructor twice, it's insane!). And the name just make it sounds like it's something pretty normal to do, which is probably the worse part of it. Actually no, the worse part is probably that it's inside module 'object', the only module imported by default everywhere, so you can't even escape the confusion by not importing its module. :-(While I share your sentiment that clear is too useful a term to be relegated to only be "call the destructor" (in fact, I use clear as a member function in my dcollections library, which probably adds to the confusion), I still think that the function should work. What types does it "blow up" on? What types does it call the destructor twice? I'd like to fix these.
Sep 12 2011
On Mon, 12 Sep 2011 15:43:13 -0400, Michel Fortin = <michel.fortin michelf.com> wrote:On 2011-09-12 11:37:20 +0000, "Steven Schveighoffer" =<schveiguy yahoo.com> said:On Mon, 12 Sep 2011 07:12:19 -0400, Michel Fortin =d:<michel.fortin michelf.com> wrote:On 2011-09-11 10:23:21 +0000, "Marco Leise" <Marco.Leise gmx.de> sai==Enough sarcasm. If I recall, Andrei liked the name 'clear' and was =unsympathetic to the arguments that it'd be confusing. 'clear' is =explained in TDPL and Andrei doesn't like to break his book, so we ==might be stuck with that mess for while. But I think it's clear by ==now that that 'clear' is confusing and dangerous: it will work with=certain types and completely blow up with others depending on =implementation details of the type (calling the destructor twice, ==it's insane!). And the name just make it sounds like it's something=ly =pretty normal to do, which is probably the worse part of it. Actual=e =no, the worse part is probably that it's inside module 'object', th=e =only module imported by default everywhere, so you can't even escap==the confusion by not importing its module. :-(While I share your sentiment that clear is too useful a term to be ==relegated to only be "call the destructor" (in fact, I use clear as a=e =member function in my dcollections library, which probably adds to th==confusion), I still think that the function should work. What types ==does it "blow up" on? What types does it call the destructor twice? =r =I'd like to fix these.It can "blow up" when the destructor is called twice and the destructo=doesn't expect this. The destructor will be called twice when you use =it =on a struct variable on the stack. You'll probably say it shouldn't be==used on stack variables, but if something work, especially if it looks==pretty and appropriate like 'clear' does, people will use it anyway an=d =write programs that'll break later when the implementation behind an A=PI =changes. Remember that this problem couldn't happen with 'delete'=E2=80==A6 I'm not sure that's valid. If you can declare a struct, you can declare= = an uninitialized struct, whose destructor *will* be called when the scop= e = exits. How does an author of a struct "not expect" the destructor to be called = on = an .init version of itself? Isn't that an error? Do you have a = counter-case?'clear' conflates two things: restoring the object to its pristine =state, and releasing resources. It does succeed at releasing resources=, =but only because it reaches half of the former goal. I think it'd be =much wiser to have two different functions for these two concepts. I think 'delete' is the one that should be tasked with releasing =resources. Just change 'delete' so it calls the destructor, wipes all ==the bits, but keep the memory block alive so it gets collected later =by =the GC, keeping things memory-safe. There's absolutely no point in =reinstating the original 'init' bits if what you want is to destroy th=e =object. 'delete' only works with memory allocated on the heap, not sta=ck =variables, not memory allocated elsewhere, so it's easy to make sure =destructors don't get called twice because that's a bit in the GC's =block flags. Then you can make 'clear' a function that actually does what people =expects it to do: restore the object to its pristine state: calling th=e =destructor, reinstating the 'init' bits, then calling constructor agai=n =if necessary. It could be safe to call on stack variables, and it coul=d =fail if the default constructor is disabled (like in NotNull!T).I hated having clear call the default constructor. I think that's = entirely the wrong thing to do. clear + deallocate replaces delete, wit= h = clear being the finalization of the data. If you want to reallocate, yo= u = can always reassign the reference to a default-constructed object. -Steve
Sep 12 2011
On 2011-09-12 20:04:05 +0000, "Steven Schveighoffer" <schveiguy yahoo.com> said:How does an author of a struct "not expect" the destructor to be called on an .init version of itself? Isn't that an error? Do you have a counter-case?struct S { disable this(); }I hated having clear call the default constructor.… because you use 'clear' to release resources. Which makes sense, but goes contrary to expectations for something called 'clear'. What I am saying is that 'clear' shouldn't be used to release resources, something else should be used for that.I think that's entirely the wrong thing to do. clear + deallocate replaces delete, wit h clear being the finalization of the data.Well, if you really wanted clear + deallocate to replace delete (regardless of the suitability of the name), don't make it so it looks like you can reuse the object/struct afterward. Saying it is assigning the 'init' state makes people believe the object will still be in a usable state although actually there is no guaranty of that, and that's true for a struct too (as shown above). Also, if 'clear' is meant to replace 'delete', it should give an error when called on non-GC memory because there's no way you can prevent the destructor from being called a second time otherwise. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Sep 12 2011
On 09/12/2011 04:36 PM, Michel Fortin wrote:On 2011-09-12 20:04:05 +0000, "Steven Schveighoffer" <schveiguy yahoo.com> said:Nope, the way Walter designed the feature, when such a struct is a member, it will have opAssign called against an object initialized with .init. Generally I find this discussion difficult to get into. So you don't like the name clear() and you don't like the behavior of clear(). (Also, you seem to consider calling the destructor several times an impossibility. Why?) Anyhow, any chance to post a condensed list of issues as you see them along with proposed fixes? Thanks, AndreiHow does an author of a struct "not expect" the destructor to be called on an .init version of itself? Isn't that an error? Do you have a counter-case?struct S { disable this(); }
Sep 12 2011
On Mon, 12 Sep 2011 17:36:09 -0400, Michel Fortin = <michel.fortin michelf.com> wrote:On 2011-09-12 20:04:05 +0000, "Steven Schveighoffer" =<schveiguy yahoo.com> said:How does an author of a struct "not expect" the destructor to be =That is a brand new feature that was added after clear was implemented, = = and I'm not sure of the semantics yet. I'd suspect that clear probably = = should be statically disallowed if no default ctor is allowed. If what Andrei says is true, however, then assigning to .init is still = feasible, and should be able to be destructed.called on an .init version of itself? Isn't that an error? Do you have a counter-case?struct S { disable this(); }nse, but =I hated having clear call the default constructor.=E2=80=A6 because you use 'clear' to release resources. Which makes se=goes contrary to expectations for something called 'clear'. What I am ==saying is that 'clear' shouldn't be used to release resources, somethi=ng =else should be used for that.I agree the name clear isn't ideal. I don't think we can change it now,= = though. But we need *something* that releases resources without reacquiring them= . = The case for reinitializing resources after releasing them is pretty = uncommon. And in those cases, the object itself can support that, we = don't need a language solution.=I think that's entirely the wrong thing to do. clear + deallocate replaces delete, =wit h clear being the finalization of the data.Well, if you really wanted clear + deallocate to replace delete =(regardless of the suitability of the name), don't make it so it looks==like you can reuse the object/struct afterward. Saying it is assigning==the 'init' state makes people believe the object will still be in a =usable state although actually there is no guaranty of that, and that'=s =true for a struct too (as shown above).You can only reuse the object after if it's a struct. If it's an object= , = you cannot. I think that's pretty much universal (does not depend on th= e = implementation of the struct/class). I think the point of clear is, you are deallocating, and no longer using= = that item. Using it afterwards is not supported without reinitializatio= n.Also, if 'clear' is meant to replace 'delete', it should give an error==when called on non-GC memory because there's no way you can prevent th=e =destructor from being called a second time otherwise.Clear is not meant to replace delete, clear + deallocate is. The notion that the library provides a mechanism to do what clear does = *without* deallocation is a new concept. That concept extends very well= = into non-heap-based types. -Steve
Sep 13 2011
Rename "clear" to "blank" in D version 3. Like blank a CD it is ready for writing but not ready for use. It is ready for use after you have burned something on it. Unless you consider burning a CD using it. blank();
Sep 13 2011
On 13/09/2011 17:05, sclytrack wrote:Rename "clear" to "blank" in D version 3. Like blank a CD it is ready for writing but not ready for use. It is ready for use after you have burned something on it. Unless you consider burning a CD using it. blank();wipe(); //?? A...
Sep 13 2011
On 14.09.2011 1:12, Alix Pexton wrote:On 13/09/2011 17:05, sclytrack wrote:my favorite still: nuke(x); //now it's obvious x is not valid ;) -- Dmitry OlshanskyRename "clear" to "blank" in D version 3. Like blank a CD it is ready for writing but not ready for use. It is ready for use after you have burned something on it. Unless you consider burning a CD using it. blank();wipe(); //?? A...
Sep 13 2011
On Tue, 13 Sep 2011 23:18:57 +0200, Dmitry Olshansky <dmitry.olsh gmail.com> wrote:On 14.09.2011 1:12, Alix Pexton wrote:That's actually kinda nice. Unlikely to be used for much else, intention very clear, and the name is short and easy to remember. Not to mention, it's a crowd-pleaser. -- SimenOn 13/09/2011 17:05, sclytrack wrote:my favorite still: nuke(x); //now it's obvious x is not valid ;)Rename "clear" to "blank" in D version 3. Like blank a CD it is ready for writing but not ready for use. It is ready for use after you have burned something on it. Unless you consider burning a CD using it. blank();wipe(); //?? A...
Sep 14 2011