From c8d00f319cda729b0e91e48fe489c6961681610f Mon Sep 17 00:00:00 2001 From: Parashurama Date: Thu, 19 Jan 2017 11:13:26 +0100 Subject: [PATCH] Updated NEP 2 Catching up with C and Rust: Ownership, destructors, unique pointers (markdown) --- ...--and-Rust:-Ownership,-destructors,-unique-pointers.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/NEP-2-Catching-up-with-C---and-Rust:-Ownership,-destructors,-unique-pointers.md b/NEP-2-Catching-up-with-C---and-Rust:-Ownership,-destructors,-unique-pointers.md index 7646ac4..4a2bdd0 100644 --- a/NEP-2-Catching-up-with-C---and-Rust:-Ownership,-destructors,-unique-pointers.md +++ b/NEP-2-Catching-up-with-C---and-Rust:-Ownership,-destructors,-unique-pointers.md @@ -39,7 +39,7 @@ echo "end of program" The obvious problem is, that the discarded value is not deinitialized at all. This should not be possible so easily. The less obvious problem is, that there are two initializations for v. One is with the values (1,2) and the other one is with the values (5,6), but there is only one deinitialization. -My suggestion would be to trigger deinitialization of the left operand of the assignment operator, before assignment takes place. Meaning that `v = MyType(a:5, b:6)` compiles to something equivalent to this pseudocode: `destroy(v); init(v, MyType(...))`. This would also solve the problem, that current implementors of the `=` operator have to implement some logic that needs to determine weather the left operand is already initialized or not, because the compiler would ensure that the left operand is not initialized. +My suggestion would be to trigger deinitialization of the left operand of the assignment operator, before assignment takes place. Meaning that `v = MyType(a:5, b:6)` compiles to something equivalent to this pseudocode: `destroy(v); init(v, MyType(...))`. This would also solve the problem, that current implementors of the `=` operator have to implement some logic that needs to determine whether the left operand is already initialized or not, because the compiler would ensure that the left operand is not initialized. ```Nim type @@ -52,7 +52,7 @@ proc `=`(dst: var MyType; src: MyType) = dst.resources = src ``` -I just heard, that self assignment on types that have deinitialization would not work anymore. This can be handled by implementing some logic that checks weather it is self assignment, or by simply declaring self assignment illegal. One version that works with self assignment is the following (again in pseudocode), but it still needs to explain what move semantics are. +I just heard, that self assignment on types that have deinitialization would not work anymore. This can be handled by implementing some logic that checks whether it is self assignment, or by simply declaring self assignment illegal. One version that works with self assignment is the following (again in pseudocode), but it still needs to explain what move semantics are. ```Nim proc `=`(dst: var MyType; src: MyType) = @@ -63,13 +63,13 @@ proc `=`(dst: var MyType; src: MyType) = # move semantics -Move semantics mere introduced into c++ as a new way to construct objects. A move to `a` from `b` means that `a` get's contructed from `b`, but `a` may exploit `b` to do so. To support this feature C++ added two entirely new kinds of references to the language, to move reference, and the forward reference. One reference is marked as `&&T` and the other one `&&T`, but here T is a templated type. And then there is move initialization and move assignment. +Move semantics mere introduced into c++ as a new way to construct objects. A move to `a` from `b` means that `a` gets constructed from `b`, but `a` may exploit `b` to do so. To support this feature C++ added two entirely new kinds of references to the language, to move reference, and the forward reference. One reference is marked as `&&T` and the other one `&&T`, but here T is a templated type. And then there is move initialization and move assignment. Nim also needs some sort of move semantics, when it doesn't want to have everything garbage collected, but I do think that the c++ way of doing this is just too complicated, and for most cases unnecessary. The most important context for move optimization is the return value, because nobody wants create a complex copy operation that keeps the source object alive, just to delete this objects instantly after that. And to have move optimizations for return values, the language does not need to have additional move operations. # My Suggestion to the problem -My proposition is, to use swap, for things that are solved with move in other languages (C++). The idea to do is, comes from the fact, that Nim does not have the concept of a contructor, and therefore is not able to introduce a new kind of constructor. Neither does it have a state to describe a variable as _is moved from_ (ivalid to read). +My proposition is, to use swap, for things that are solved with move in other languages (C++). The idea to do is, comes from the fact, that Nim does not have the concept of a constructor, and therefore is not able to introduce a new kind of constructor. Neither does it have a state to describe a variable as _is moved from_ (ivalid to read). Swap has the advantage, that it never introduces new entities, it just swaps two objects of the same type. Therefore the operation contains two move operations, but without destroying any other variable