digitalmars.D - const as default for variables
- Walter Bright (23/23) Mar 14 2015 I've often thought, as do many others here, that immutability should be ...
- Douglas Peterson (6/33) Mar 14 2015 Seriously: http://giphy.com/gifs/KmrpxSVxTB9Ty ?
- weaselcat (4/5) Mar 14 2015 safety, the same reason @safe should be the default.
- extrawurst (4/31) Mar 14 2015 I like it! In fact I thought a lot of people asked to take the
- Xinok (13/40) Mar 14 2015 My two and a half cents, I think this is going to lead to all
- Walter Bright (6/12) Mar 14 2015 Not really.
- Almighty Bob (6/8) Mar 14 2015 There should be "constants" and "variables" but no such thing
- Orvid King (3/30) Mar 14 2015 Why would this be even slightly useful? If a value is constant,
- weaselcat (2/44) Mar 14 2015 C heritage.
- deadalnix (2/2) Mar 14 2015 Const is the inconvenience of immutability without its benefit.
- Walter Bright (3/5) Mar 14 2015 It's utility is in self-documenting encapsulation.
- deadalnix (4/11) Mar 14 2015 You'll have to explain yourself, as there is nothing obvious here.
- Walter Bright (3/14) Mar 15 2015 "const ref" can tell the optimizer that that path for a ref counted obje...
- =?UTF-8?B?U8O2bmtlIEx1ZHdpZw==?= (12/31) Mar 15 2015 My proposal would be to make "scope" (with strong recursive guarantees)
- "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> (6/14) Mar 15 2015 Please see my newest scope proposal, which I just posted here:
- =?UTF-8?B?U8O2bmtlIEx1ZHdpZw==?= (7/20) Mar 15 2015 My idea was to make the change explicit first, but module wide (e.g.
- Dicebot (5/9) Mar 16 2015 This can be an interesting approach to breaking change that don't
- deadalnix (3/5) Mar 15 2015 That is not clear why. const ref is supposed to protect against
- Walter Bright (3/8) Mar 15 2015 Passing rc objects by const ref, for example, precludes the disastrous c...
- deadalnix (2/13) Mar 16 2015 That is true.
- Zach the Mystic (10/15) Mar 16 2015 There are two cases here. One is when the reference is copied to
- deadalnix (3/14) Mar 16 2015 I think we should provide library solution for this kind of
- Zach the Mystic (4/19) Mar 16 2015 Changing the reference count is a very low-level operation. I'm
- Dicebot (5/5) Mar 14 2015 I like it but would prefer to have it as part of combined "strict
- Jonathan M Davis via Digitalmars-d (26/49) Mar 15 2015 Given how restricted const in D is and how many things don't work well w...
- "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> (11/56) Mar 15 2015 I concur with Jonathan. There might be an argument for const-ness
- Dejan Lekic (4/31) Mar 17 2015 I definitely think this is a good idea. And if someone wants
- deadalnix (12/15) Mar 17 2015 This is going to break pretty much all the code that use auto.
- Zach the Mystic (7/19) Mar 17 2015 The real devil against safe reference counting is in the
- deadalnix (4/10) Mar 17 2015 That is the wrong approach. This is a know problem and there is a
- Zach the Mystic (34/46) Mar 17 2015 Just so we're clear, there are two problems. One is making
- deadalnix (30/33) Mar 18 2015 It is not the language's problem. If the language defines
- Zach the Mystic (33/69) Mar 18 2015 So let's go through the steps. Question: What parts of borrowing
- Moritz Maxeiner (76/81) Mar 19 2015 The following is just my point of view, so take it with a grain
I've often thought, as do many others here, that immutability should be the default for variables. [This is a long term issue. Just thought maybe it's time for a conversation about it.] Because immutable is transitive, declaring variables as immutable by default would be problematic. A more practical way would be to make them const. As it is now: 1. int x = 1; // mutable 2. auto x = 1; // mutable 3. const x = 1; // const 4. immutable x = 1; // immutable Case (1) is what I'm talking about here. If it is made const, then there are a couple ways forward in declaring a mutable variable: a) Introduce a new storage class, called 'var' or 'mut'. (Please, no bikeshedding on names at the moment. Let's stay on topic.) b) Use 'auto' as meaning 'mutable' if the initializer is also mutable. Extend 'auto' to allow an optional type, auto T t = initializer; There may be some ambiguity issues with 'auto ref', haven't thought it through. Once there is a non-default way to declare variables as mutable, a compiler switch can be added to change the default to be const. Eventually, the language can default to them being const, with a legacy switch to support the mutable default.
Mar 14 2015
On Saturday, 14 March 2015 at 20:15:30 UTC, Walter Bright wrote:I've often thought, as do many others here, that immutability should be the default for variables. [This is a long term issue. Just thought maybe it's time for a conversation about it.] Because immutable is transitive, declaring variables as immutable by default would be problematic. A more practical way would be to make them const. As it is now: 1. int x = 1; // mutable 2. auto x = 1; // mutable 3. const x = 1; // const 4. immutable x = 1; // immutable Case (1) is what I'm talking about here. If it is made const, then there are a couple ways forward in declaring a mutable variable: a) Introduce a new storage class, called 'var' or 'mut'. (Please, no bikeshedding on names at the moment. Let's stay on topic.) b) Use 'auto' as meaning 'mutable' if the initializer is also mutable. Extend 'auto' to allow an optional type, auto T t = initializer; There may be some ambiguity issues with 'auto ref', haven't thought it through. Once there is a non-default way to declare variables as mutable, a compiler switch can be added to change the default to be const. Eventually, the language can default to them being const, with a legacy switch to support the mutable default.Seriously: http://giphy.com/gifs/KmrpxSVxTB9Ty ? It sounds a bit like the bad idea of the month (not totally because at least a bad idea initially sounds good). What would be the rationale for such a change ? In fact, this would imply a huge breakage on any existing code, right ?
Mar 14 2015
On Saturday, 14 March 2015 at 21:18:33 UTC, Douglas Peterson wrote:What would be the rationale for such a change ?safety, the same reason safe should be the default. see: const correctness, virtually any ML-inspired language.
Mar 14 2015
On Saturday, 14 March 2015 at 20:15:30 UTC, Walter Bright wrote:I've often thought, as do many others here, that immutability should be the default for variables. [This is a long term issue. Just thought maybe it's time for a conversation about it.] Because immutable is transitive, declaring variables as immutable by default would be problematic. A more practical way would be to make them const. As it is now: 1. int x = 1; // mutable 2. auto x = 1; // mutable 3. const x = 1; // const 4. immutable x = 1; // immutable Case (1) is what I'm talking about here. If it is made const, then there are a couple ways forward in declaring a mutable variable: a) Introduce a new storage class, called 'var' or 'mut'. (Please, no bikeshedding on names at the moment. Let's stay on topic.) b) Use 'auto' as meaning 'mutable' if the initializer is also mutable. Extend 'auto' to allow an optional type, auto T t = initializer; There may be some ambiguity issues with 'auto ref', haven't thought it through. Once there is a non-default way to declare variables as mutable, a compiler switch can be added to change the default to be const. Eventually, the language can default to them being const, with a legacy switch to support the mutable default.I like it! In fact I thought a lot of people asked to take the const-by-default route when D2 introduced it? ~S
Mar 14 2015
On Saturday, 14 March 2015 at 20:15:30 UTC, Walter Bright wrote:I've often thought, as do many others here, that immutability should be the default for variables. [This is a long term issue. Just thought maybe it's time for a conversation about it.] Because immutable is transitive, declaring variables as immutable by default would be problematic. A more practical way would be to make them const. As it is now: 1. int x = 1; // mutable 2. auto x = 1; // mutable 3. const x = 1; // const 4. immutable x = 1; // immutable Case (1) is what I'm talking about here. If it is made const, then there are a couple ways forward in declaring a mutable variable: a) Introduce a new storage class, called 'var' or 'mut'. (Please, no bikeshedding on names at the moment. Let's stay on topic.) b) Use 'auto' as meaning 'mutable' if the initializer is also mutable. Extend 'auto' to allow an optional type, auto T t = initializer; There may be some ambiguity issues with 'auto ref', haven't thought it through. Once there is a non-default way to declare variables as mutable, a compiler switch can be added to change the default to be const. Eventually, the language can default to them being const, with a legacy switch to support the mutable default.My two and a half cents, I think this is going to lead to all sorts of complications and simply wouldn't be worth the hassle. While I believe that immutable by default is a fine choice for any new language, D was designed with "mutable by default" in mind and it's simply too late to try and change that now. For example, this could be an issue for generic functions: void foo(T)(T[] arr){ T value = arr[0]; // Mutable or immutable? } Also, you forgot a fifth case where only part of the type is const/immutable: 5. const(T)[] x = ...
Mar 14 2015
On 3/14/2015 3:06 PM, Xinok wrote:For example, this could be an issue for generic functions: void foo(T)(T[] arr){ T value = arr[0]; // Mutable or immutable? }Not really. const T value = arr[0]; means that value isn't going to be subsequently reassigned or anything mutated through it.Also, you forgot a fifth case where only part of the type is const/immutable: 5. const(T)[] x = ...The default const'ness would apply to the [] part.
Mar 14 2015
On Saturday, 14 March 2015 at 20:15:30 UTC, Walter Bright wrote:I've often thought, as do many others here, that immutability should be the default for variables.There should be "constants" and "variables" but no such thing as... a constant variable or an immutable variable. It's either constant/immutable or it's variable, it cant be both.
Mar 14 2015
On Saturday, 14 March 2015 at 20:15:30 UTC, Walter Bright wrote:I've often thought, as do many others here, that immutability should be the default for variables. [This is a long term issue. Just thought maybe it's time for a conversation about it.] Because immutable is transitive, declaring variables as immutable by default would be problematic. A more practical way would be to make them const. As it is now: 1. int x = 1; // mutable 2. auto x = 1; // mutable 3. const x = 1; // const 4. immutable x = 1; // immutable Case (1) is what I'm talking about here. If it is made const, then there are a couple ways forward in declaring a mutable variable: a) Introduce a new storage class, called 'var' or 'mut'. (Please, no bikeshedding on names at the moment. Let's stay on topic.) b) Use 'auto' as meaning 'mutable' if the initializer is also mutable. Extend 'auto' to allow an optional type, auto T t = initializer; There may be some ambiguity issues with 'auto ref', haven't thought it through. Once there is a non-default way to declare variables as mutable, a compiler switch can be added to change the default to be const. Eventually, the language can default to them being const, with a legacy switch to support the mutable default.Why would this be even slightly useful? If a value is constant, it _should not_ be a variable.
Mar 14 2015
On Sunday, 15 March 2015 at 00:03:37 UTC, Orvid King wrote:On Saturday, 14 March 2015 at 20:15:30 UTC, Walter Bright wrote:C heritage.I've often thought, as do many others here, that immutability should be the default for variables. [This is a long term issue. Just thought maybe it's time for a conversation about it.] Because immutable is transitive, declaring variables as immutable by default would be problematic. A more practical way would be to make them const. As it is now: 1. int x = 1; // mutable 2. auto x = 1; // mutable 3. const x = 1; // const 4. immutable x = 1; // immutable Case (1) is what I'm talking about here. If it is made const, then there are a couple ways forward in declaring a mutable variable: a) Introduce a new storage class, called 'var' or 'mut'. (Please, no bikeshedding on names at the moment. Let's stay on topic.) b) Use 'auto' as meaning 'mutable' if the initializer is also mutable. Extend 'auto' to allow an optional type, auto T t = initializer; There may be some ambiguity issues with 'auto ref', haven't thought it through. Once there is a non-default way to declare variables as mutable, a compiler switch can be added to change the default to be const. Eventually, the language can default to them being const, with a legacy switch to support the mutable default.Why would this be even slightly useful? If a value is constant, it _should not_ be a variable.
Mar 14 2015
Const is the inconvenience of immutability without its benefit. That would be a poor default, IMO.
Mar 14 2015
On 3/14/2015 8:50 PM, deadalnix wrote:Const is the inconvenience of immutability without its benefit. That would be a poor default, IMO.It's utility is in self-documenting encapsulation. It also turns out that it offers optimization possibilities for ARC systems.
Mar 14 2015
On Sunday, 15 March 2015 at 05:08:54 UTC, Walter Bright wrote:On 3/14/2015 8:50 PM, deadalnix wrote:You'll have to explain yourself, as there is nothing obvious here. I see how immutable can be leveraged to optimize, but I don't think const offers the same capabilities.Const is the inconvenience of immutability without its benefit. That would be a poor default, IMO.It's utility is in self-documenting encapsulation. It also turns out that it offers optimization possibilities for ARC systems.
Mar 14 2015
On 3/14/2015 10:23 PM, deadalnix wrote:On Sunday, 15 March 2015 at 05:08:54 UTC, Walter Bright wrote:"const ref" can tell the optimizer that that path for a ref counted object cannot alter its ref count.On 3/14/2015 8:50 PM, deadalnix wrote:You'll have to explain yourself, as there is nothing obvious here. I see how immutable can be leveraged to optimize, but I don't think const offers the same capabilities.Const is the inconvenience of immutability without its benefit. That would be a poor default, IMO.It's utility is in self-documenting encapsulation. It also turns out that it offers optimization possibilities for ARC systems.
Mar 15 2015
Am 15.03.2015 um 08:44 schrieb Walter Bright:On 3/14/2015 10:23 PM, deadalnix wrote:My proposal would be to make "scope" (with strong recursive guarantees) the default instead to achieve that goal. That would give the compiler a lot of optimization potential (much more than just for RC), and would at the same time most probably be a lot less limiting. It would also be a nice documentation trait to see where references are stored for later use. And it could even be used to implement checked safety for calling C/C++ functions with GC references. I agree with Dicebot that any such change should ideally be done as a single big step for all attributes at once. However, instead of a major version bump, we could have a normal deprecation path à la "opt-in only" -> "opt-in + opt-out" -> "opt-out only" -> remove old defaults.On Sunday, 15 March 2015 at 05:08:54 UTC, Walter Bright wrote:"const ref" can tell the optimizer that that path for a ref counted object cannot alter its ref count.On 3/14/2015 8:50 PM, deadalnix wrote:You'll have to explain yourself, as there is nothing obvious here. I see how immutable can be leveraged to optimize, but I don't think const offers the same capabilities.Const is the inconvenience of immutability without its benefit. That would be a poor default, IMO.It's utility is in self-documenting encapsulation. It also turns out that it offers optimization possibilities for ARC systems.
Mar 15 2015
On Sunday, 15 March 2015 at 13:21:11 UTC, Sönke Ludwig wrote:My proposal would be to make "scope" (with strong recursive guarantees) the default instead to achieve that goal. That would give the compiler a lot of optimization potential (much more than just for RC), and would at the same time most probably be a lot less limiting. It would also be a nice documentation trait to see where references are stored for later use. And it could even be used to implement checked safety for calling C/C++ functions with GC references.Please see my newest scope proposal, which I just posted here: http://forum.dlang.org/thread/tlupkiiarrabqaxtayci forum.dlang.org#post-tlupkiiarrabqaxtayci:40forum.dlang.org It does almost what you suggest, but only for safe functions, to avoid breaking too many things. A change à la " safe by default" would then have the same effect.
Mar 15 2015
Am 15.03.2015 um 15:16 schrieb "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net>":On Sunday, 15 March 2015 at 13:21:11 UTC, Sönke Ludwig wrote:My idea was to make the change explicit first, but module wide (e.g. using a pragma or similar), so that there is no immediate breakage at all. Only the last stage of the deprecation plan would finally switch over the defaults for unannotated modules. I'll make sure to have a look at the proposal later!My proposal would be to make "scope" (with strong recursive guarantees) the default instead to achieve that goal. That would give the compiler a lot of optimization potential (much more than just for RC), and would at the same time most probably be a lot less limiting. It would also be a nice documentation trait to see where references are stored for later use. And it could even be used to implement checked safety for calling C/C++ functions with GC references.Please see my newest scope proposal, which I just posted here: http://forum.dlang.org/thread/tlupkiiarrabqaxtayci forum.dlang.org#post-tlupkiiarrabqaxtayci:40forum.dlang.org It does almost what you suggest, but only for safe functions, to avoid breaking too many things. A change à la " safe by default" would then have the same effect.
Mar 15 2015
On Sunday, 15 March 2015 at 22:48:18 UTC, Sönke Ludwig wrote:My idea was to make the change explicit first, but module wide (e.g. using a pragma or similar), so that there is no immediate breakage at all. Only the last stage of the deprecation plan would finally switch over the defaults for unannotated modules.This can be an interesting approach to breaking change that don't introduce new concepts but it can become tricky with mixins and mixin templates because semantic context is different from declaration context.
Mar 16 2015
On Sunday, 15 March 2015 at 07:44:50 UTC, Walter Bright wrote:"const ref" can tell the optimizer that that path for a ref counted object cannot alter its ref count.That is not clear why. const ref is supposed to protect against escaping when ref does not ?
Mar 15 2015
On 3/15/2015 1:09 PM, deadalnix wrote:On Sunday, 15 March 2015 at 07:44:50 UTC, Walter Bright wrote:Passing rc objects by const ref, for example, precludes the disastrous cases enumerated in the "RCArray is unsafe" thread."const ref" can tell the optimizer that that path for a ref counted object cannot alter its ref count.That is not clear why. const ref is supposed to protect against escaping when ref does not ?
Mar 15 2015
On Monday, 16 March 2015 at 00:07:32 UTC, Walter Bright wrote:On 3/15/2015 1:09 PM, deadalnix wrote:That is true.On Sunday, 15 March 2015 at 07:44:50 UTC, Walter Bright wrote:Passing rc objects by const ref, for example, precludes the disastrous cases enumerated in the "RCArray is unsafe" thread."const ref" can tell the optimizer that that path for a ref counted object cannot alter its ref count.That is not clear why. const ref is supposed to protect against escaping when ref does not ?
Mar 16 2015
On Sunday, 15 March 2015 at 20:09:56 UTC, deadalnix wrote:On Sunday, 15 March 2015 at 07:44:50 UTC, Walter Bright wrote:There are two cases here. One is when the reference is copied to new variable, which would actually break const because the reference count of the original data would have to be incremented (which is a separate issue). But the other case is where the original is reassigned, in which the counter for the data it used to point to gets decremented, possibly to zero. `const` would guarantee against this. But even this is a blunt force weapon, because it would also stop you from mutating the original data, even though that wouldn't change the reference count."const ref" can tell the optimizer that that path for a ref counted object cannot alter its ref count.That is not clear why. const ref is supposed to protect against escaping when ref does not ?
Mar 16 2015
On Monday, 16 March 2015 at 14:40:51 UTC, Zach the Mystic wrote:On Sunday, 15 March 2015 at 20:09:56 UTC, deadalnix wrote:I think we should provide library solution for this kind of things.On Sunday, 15 March 2015 at 07:44:50 UTC, Walter Bright wrote:There are two cases here. One is when the reference is copied to new variable, which would actually break const because the reference count of the original data would have to be incremented (which is a separate issue)."const ref" can tell the optimizer that that path for a ref counted object cannot alter its ref count.That is not clear why. const ref is supposed to protect against escaping when ref does not ?
Mar 16 2015
On Monday, 16 March 2015 at 19:52:00 UTC, deadalnix wrote:On Monday, 16 March 2015 at 14:40:51 UTC, Zach the Mystic wrote:Changing the reference count is a very low-level operation. I'm not sure how to go about breaking the type system in order to support `const` variations on it.On Sunday, 15 March 2015 at 20:09:56 UTC, deadalnix wrote:I think we should provide library solution for this kind of things.On Sunday, 15 March 2015 at 07:44:50 UTC, Walter Bright wrote:There are two cases here. One is when the reference is copied to new variable, which would actually break const because the reference count of the original data would have to be incremented (which is a separate issue)."const ref" can tell the optimizer that that path for a ref counted object cannot alter its ref count.That is not clear why. const ref is supposed to protect against escaping when ref does not ?
Mar 16 2015
I like it but would prefer to have it as part of combined "strict attribute as default" major version bump. It is likely to require lot of attention during upgrade (really lot) even with dfix automation, better to spend that time and get something polished than have many similar but separate breaking steps.
Mar 14 2015
On Saturday, March 14, 2015 13:14:50 Walter Bright via Digitalmars-d wrote:I've often thought, as do many others here, that immutability should be the default for variables. [This is a long term issue. Just thought maybe it's time for a conversation about it.] Because immutable is transitive, declaring variables as immutable by default would be problematic. A more practical way would be to make them const. As it is now: 1. int x = 1; // mutable 2. auto x = 1; // mutable 3. const x = 1; // const 4. immutable x = 1; // immutable Case (1) is what I'm talking about here. If it is made const, then there are a couple ways forward in declaring a mutable variable: a) Introduce a new storage class, called 'var' or 'mut'. (Please, no bikeshedding on names at the moment. Let's stay on topic.) b) Use 'auto' as meaning 'mutable' if the initializer is also mutable. Extend 'auto' to allow an optional type, auto T t = initializer; There may be some ambiguity issues with 'auto ref', haven't thought it through. Once there is a non-default way to declare variables as mutable, a compiler switch can be added to change the default to be const. Eventually, the language can default to them being const, with a legacy switch to support the mutable default.Given how restricted const in D is and how many things don't work well with it (e.g. it is a royal pain to make ranges work when const is involved), I seriously question that this is a good idea. And I agree with deadalnix that if we were to change the default, immutabale would make more sense. const has all of the negatives of immutable without providing many of its benefits. Yes, const provides _some_ benefit, but it's pretty limited and very limiting. So, if we're considering something like this, why not just go straight to immutable and actually get the full benefits rather than get the pain with very few benefits? But really, given how limiting const and immutable are, I seriously question that making either of them the default is a good idea - _especially_ when you consider how abysmally they interact with ranges and how big ranges are for us. Also, if we're thinking about making a change like this, it would be _way_ more beneficial to do something like make safe and pure the default for functions rather than make const the default for variables. At least in that case we'd be reducing the amount of attribute clutter in the language, whereas what you're suggesting would probably make code more verbose in general rather than less (due to having to mark so much as explicitly mutable), and even if it didn't generally make code any more verbose, it certainly wouldn't make it _less_ verbose. Making safe and pure the default would actually help reduce one of the major issues that we have - attribute proliferation, whereas this suggestion pushes one of the more limiting features as the default. - Jonathan M Davis
Mar 15 2015
On Sunday, 15 March 2015 at 08:29:36 UTC, Jonathan M Davis wrote:Given how restricted const in D is and how many things don't work well with it (e.g. it is a royal pain to make ranges work when const is involved), I seriously question that this is a good idea. And I agree with deadalnix that if we were to change the default, immutabale would make more sense. const has all of the negatives of immutable without providing many of its benefits. Yes, const provides _some_ benefit, but it's pretty limited and very limiting. So, if we're considering something like this, why not just go straight to immutable and actually get the full benefits rather than get the pain with very few benefits? But really, given how limiting const and immutable are, I seriously question that making either of them the default is a good idea - _especially_ when you consider how abysmally they interact with ranges and how big ranges are for us. Also, if we're thinking about making a change like this, it would be _way_ more beneficial to do something like make safe and pure the default for functions rather than make const the default for variables. At least in that case we'd be reducing the amount of attribute clutter in the language, whereas what you're suggesting would probably make code more verbose in general rather than less (due to having to mark so much as explicitly mutable), and even if it didn't generally make code any more verbose, it certainly wouldn't make it _less_ verbose. Making safe and pure the default would actually help reduce one of the major issues that we have - attribute proliferation, whereas this suggestion pushes one of the more limiting features as the default.I concur with Jonathan. There might be an argument for const-ness of foreach variables by default, but seeing how that still would require additional syntax to opt out, and would be just another special case, it's probably not a good idea either. ` safe` on the other hand looks promising, and is anyway a good direction to go. About `pure`, I'm not sure. That's very limiting wrt I/O. If `pure` only implied no access to globals/static locals, it would be less restrictive, while still providing useful guarantees. But full purity is still worth considering, of course.
Mar 15 2015
On Saturday, 14 March 2015 at 20:15:30 UTC, Walter Bright wrote:I've often thought, as do many others here, that immutability should be the default for variables. [This is a long term issue. Just thought maybe it's time for a conversation about it.] Because immutable is transitive, declaring variables as immutable by default would be problematic. A more practical way would be to make them const. As it is now: 1. int x = 1; // mutable 2. auto x = 1; // mutable 3. const x = 1; // const 4. immutable x = 1; // immutable Case (1) is what I'm talking about here. If it is made const, then there are a couple ways forward in declaring a mutable variable: a) Introduce a new storage class, called 'var' or 'mut'. (Please, no bikeshedding on names at the moment. Let's stay on topic.) b) Use 'auto' as meaning 'mutable' if the initializer is also mutable. Extend 'auto' to allow an optional type, auto T t = initializer; There may be some ambiguity issues with 'auto ref', haven't thought it through. Once there is a non-default way to declare variables as mutable, a compiler switch can be added to change the default to be const. Eventually, the language can default to them being const, with a legacy switch to support the mutable default.I definitely think this is a good idea. And if someone wants mutable variable, we simply use proposed 'var' storage class. Brilliant!
Mar 17 2015
On Tuesday, 17 March 2015 at 13:55:36 UTC, Dejan Lekic wrote:I definitely think this is a good idea. And if someone wants mutable variable, we simply use proposed 'var' storage class. Brilliant!This is going to break pretty much all the code that use auto. The benefice for the compiler is hypothetical. Walter is right when mentioning that is can remove some refcount boilerplate, which is right but, we have no idea how much, and how good the compiler would be at recognizing them. With existing languag feature, the compiler CANNOT leverage this change for optimization. I'd consider this if it was from scratch, but in the current state of affair, it is a change that does not pay for itself. Switching to safe by default for instance will break less code while providing more.
Mar 17 2015
On Tuesday, 17 March 2015 at 19:53:14 UTC, deadalnix wrote:On Tuesday, 17 March 2015 at 13:55:36 UTC, Dejan Lekic wrote:The real devil against safe reference counting is in the assignment operators, when they do destructive moves. I think those have to be the focus of any effort here. I'm trying to imagine a parameter attribute ` destroy`, for example, indicating that its reference may get destroyed. Not sure if it will work, or even help, but it's a start.I definitely think this is a good idea. And if someone wants mutable variable, we simply use proposed 'var' storage class. Brilliant!This is going to break pretty much all the code that use auto. The benefice for the compiler is hypothetical. Walter is right when mentioning that is can remove some refcount boilerplate, which is right but, we have no idea how much, and how good the compiler would be at recognizing them. With existing languag feature, the compiler CANNOT leverage this change for optimization.
Mar 17 2015
On Tuesday, 17 March 2015 at 22:25:30 UTC, Zach the Mystic wrote:The real devil against safe reference counting is in the assignment operators, when they do destructive moves. I think those have to be the focus of any effort here. I'm trying to imagine a parameter attribute ` destroy`, for example, indicating that its reference may get destroyed. Not sure if it will work, or even help, but it's a start.That is the wrong approach. This is a know problem and there is a known solution: ownership. If we are going to add something in the language to handle it, then it has to be ownership.
Mar 17 2015
On Tuesday, 17 March 2015 at 22:53:20 UTC, deadalnix wrote:On Tuesday, 17 March 2015 at 22:25:30 UTC, Zach the Mystic wrote:Just so we're clear, there are two problems. One is making ref-counting safe. The other is making it fast, by eliding unnecessary operations. The issue I'm worried about is when you pass an RC'd type as an argument by value, for example, you make a copy. To be safe the compiler should wrap the original in an inc/dec cycle for the duration of the call. But this is a waste if there's no risk of reassignment, if you're just mutating the original data, or if the type isn't even an RC'd type but has some other kind of destructor. My guess was that ` destroy` could help the compiler elide unnecessary cycles this way. If you always pass by reference (e.g. `ref`), you're sending the original, rather than copying it. This needs no wrapping therefore, since any reassignment will affect the original. What good would ownership do in that case? Any normal copying will increase the refcount anyway. I'm starting to think that refcounting is precisely the opposite of ownership, useful only for when its *impossible* to track ownership easily. Otherwise why would you need a refcount? What would be really interesting is a combined system, where the compiler detects the ownership properties of any given variable, and automatically decides whether it needs to be refcounted or not. There could be a built-in template in the runtime, e.g. a `_refCounted(T)`, which must be a perfect drop-in replacement for a regular `T` in all cases -- difficult, yes, but interesting to imagine at least -- which the compiler would swap in at its discretion. Obviously a huge flight of fancy, given that D is not in the habit of altering the basic type of a variable based on how it used... but it would be very efficient if it worked. Do you agree that refcounting and ownership oppose each other, that refcounting only makes sense when ownership is impossible? That refcounting is a runtime mechanism for tracking precisely what a compile time ownership system can't? In other words, what problems does ownership solve, and how?The real devil against safe reference counting is in the assignment operators, when they do destructive moves. I think those have to be the focus of any effort here. I'm trying to imagine a parameter attribute ` destroy`, for example, indicating that its reference may get destroyed. Not sure if it will work, or even help, but it's a start.That is the wrong approach. This is a know problem and there is a known solution: ownership. If we are going to add something in the language to handle it, then it has to be ownership.
Mar 17 2015
On Wednesday, 18 March 2015 at 06:24:38 UTC, Zach the Mystic wrote:I'm starting to think that refcounting is precisely the opposite of ownership, useful only for when its *impossible* to track ownership easily. Otherwise why would you need a refcount?It is not the language's problem. If the language defines ownership, the you can define all kind of RC systems as library type by deferring the ownership of things to the RC library. The good thing about it is that it doesn't limit the library solution to be ref counting, but it can be anything else, or any refcounting strategy. Indeed, internally, the RC system have to play unsafe, but as long as it has to free, it has to play unsafe anyway. The important point is that it can provides a safe interface to the outside world. The inc/dec elision problem is simply a copy optimization problem. Framing it as a refcounting problem is the wrong way to think about it. You would like to elide copy as much as possible. The first element for this is borrowing. You can pass borrowed things around without needing to have copies. The general problem of the assignation comes up when something is borrowed several time and assigned. const is obviously a situation where we can elide when borrowing, but that is not the only one. In that situation, only borrowing the RC wrapper require a copy (borrowing the wrapped do not). Note that borrowing the wrapped is most likely what you want in the first place in most situation (so the code manipulating the borrowed do not need to rely on a specific memory management scheme, which allow for versatile libraries) so copy elision is what you'll in most situation as well. Solid core constructs are much better that attribute proliferation.
Mar 18 2015
On Wednesday, 18 March 2015 at 09:28:35 UTC, deadalnix wrote:On Wednesday, 18 March 2015 at 06:24:38 UTC, Zach the Mystic wrote:So let's go through the steps. Question: What parts of borrowing are internally kept track of by the compiler, and what parts are made manifest in code? For what is made manifest, how do they appear -- as type qualifiers, i.e. `borrowed`, `owned` -- or built-in properties, e.g. `fun(x.borrowed)`? For things kept hidden, we need to find potential sources of ambiguity, and derive reliable algorithms to resolve them. For me, a big issue is passing variables as arguments, because the compiler can't read into the function to see what it does, and the function can only tell the caller what the attribute system allows. What if the caller takes a wrapped type and you only have an unwrapped version, or a different wrapped version, to pass to it? Should there be any way to pass it transparently (i.e for the called type to automatically receive the passed type of the argument), or does it have to be created manually? (I was thinking about this when Andrei was trying to create smart pointers, and wondered what it would take to create a`Ref!` type to entirely replace the `ref` storage class.) This may or may not be related to a fully effective ownership system.I'm starting to think that refcounting is precisely the opposite of ownership, useful only for when its *impossible* to track ownership easily. Otherwise why would you need a refcount?It is not the language's problem. If the language defines ownership, the you can define all kind of RC systems as library type by deferring the ownership of things to the RC library. The good thing about it is that it doesn't limit the library solution to be ref counting, but it can be anything else, or any refcounting strategy. Indeed, internally, the RC system have to play unsafe, but as long as it has to free, it has to play unsafe anyway. The important point is that it can provides a safe interface to the outside world. The inc/dec elision problem is simply a copy optimization problem. Framing it as a refcounting problem is the wrong way to think about it. You would like to elide copy as much as possible. The first element for this is borrowing. You can pass borrowed things around without needing to have copies.The general problem of the assignation comes up when something is borrowed several time and assigned. const is obviously a situation where we can elide when borrowing, but that is not the only one. In that situation, only borrowing the RC wrapper require a copy (borrowing the wrapped do not). Note that borrowing the wrapped is most likely what you want in the first place in most situation (so the code manipulating the borrowed do not need to rely on a specific memory management scheme, which allow for versatile libraries) so copy elision is what you'll in most situation as well.I guess this will most often be accomplished with `alias this` when passing to an argument? I guess what you're suggesting is that if a function may delete a reference, you can detect this because it accepts only a fully RC'd type rather than the unwrapped version.Solid core constructs are much better that attribute proliferation.I totally agree, but at this point, we must figure out precisely which constructs to ask for, and then convince everyone else of their worth. How did you become convinced of the value of built-in ownership? Is there a good article you could point me to? Secondly, what do you suggest it would look like in D? Type qualifiers, a storage class, function/parameter attributes? How much just takes place invisibly to the programmer?
Mar 18 2015
On Saturday, 14 March 2015 at 20:15:30 UTC, Walter Bright wrote:I've often thought, as do many others here, that immutability should be the default for variables. Case (1) is what I'm talking about here. If it is made const, then there are a couple ways forward in declaring a mutable variable:The following is just my point of view, so take it with a grain of salt and correct me if I state/understand something wrong: I usually abstain from participating in discussions here, because more often than not someone else will already more or less write what I would, so there is little point in my writing what has already been posted. This issue, however, I consider fairly important, as what you propose would make me classify D as "don't touch", which I really don't want considering that I've been following and using D for the better part of ten years; let me explain why: There exists an abstract amount of data that I want to store somewhere and access within my program. I shall call one instance of something I put my data into "storage entity" (SE for short). Now depending on what properties my data inherently has (or I may additionally attribute to it) I may want or need a SE to - allow any data within it to be changed ([wholly] mutable) - prohibit any data within it to be changed ([wholly] immutable) - allow some of the data within it to be changed (partially mutable) [Here and unless otherwise stated I do not use immutable in the transitive meaning that D currently applies to it, instead it is only applied to one SE] The first of the three is what is generally in computer science (CS) called a variable, the second a constant. SEs of the third type are also mostly referred to as variables, as they are usually implemented as an extension to the first. I know that from a mathematical standpoint, a variable is only a symbol with an attributed value without any associated notion about (im)mutability, so even a contant would be a variable, but this is not how the terminology is used in CS. In CS a variable must allow some kind of mutability; not necessarily wholly, but without mutability it would be a constant, not a variable. As such, should D's SEs default to being wholly immutable (which you seem to propose), it should not call them variables anymore (since they aren't), but instead clearly state that "D's SE default to being constants and if you want a variable, do [...]". With only primitives (no pointers), there can be no partial mutability, you are either allowed to assign a new (primitive) value or you are not. Partial mutability becomes a serious concern, however, once pointers/references are involved, e.g. if you want to reference an SE that is wholly immutable. Does your reference automatically also become immutable (as I understand if - and please correct me if I am wrong here - this is what D's transitive "immutable" means)? I understand that with this extremely complex issue, it may seem desirably to instead default to whole non-transtitive immutability and make people explicitly state when they want their SEs to be mutable. One might argue that it would make a lot of things simpler for everyone involved. However, D is a systems programming language and I would counter-argue that I believe the amount of partially mutable SEs to far outweight the amount of wholly immutable ones and having something like int foo = 5; [...] foo = 6; produce a compile-error because "foo" is by default non-transitive immutable [D terminology would be "const" I think] is something I can only call absurd for the following reason: It breaks with the convention systems programming languages have been using for a very long time. While I'm not generally against cutting off traditions no longer needed, I believe this would have a serious negative impact on people coming form C/C++ who are expecting new cool stuff (which D definitely has) without ground-breaking changes. The longer the list of core differences to the way you code you have to remind yourself about when switching to D, the less likely you will switch to D, I think. What I would propose is the following: Have the compiler-frontend track for all SE whether they are assigned to more than once (counting the initial assignment). Any SE that isn't can safely be marked "const" (or non-transitive immutable) the way to described in your opening post. However, is an SE assigned to at least twice is must not be marked as const. This should - in my opinion - give about the same level of safety as marking everything as "const" by default while not breaking with any long-standing conventions.
Mar 19 2015