digitalmars.D.learn - const in functions
- Salih Dincer (56/61) Mar 12 2023 Hi,
- Hipreme (21/25) Mar 12 2023 Const is used for you not be able to change your values inside
- =?UTF-8?Q?Ali_=c3=87ehreli?= (31/32) Mar 12 2023 You can live without 'const' until your code interacts with other
- Salih Dincer (21/22) Mar 13 2023 In this case, using `ref` will increase performance while
- =?UTF-8?Q?Ali_=c3=87ehreli?= (9/11) Mar 13 2023 I am not sure about that. Unless there is an expensive copy
- FozzieBear (13/14) Mar 12 2023 So I don't agree with part of this comment (made elsewhere in
- =?UTF-8?Q?Ali_=c3=87ehreli?= (27/37) Mar 17 2023 My comment was purely technical. What I meant is, if the code is an
- Salih Dincer (20/42) Mar 18 2023 Let's increase the level one bit...
- Basile B. (12/18) Mar 13 2023 Well you got the great answers to your questions already but I
Hi, As someone who has used const very little in my life, I want to learn and ask: What are consts used in function parameters for; isn't there a copy already? ```d /* * Here's we have a class (Foo is partially simple): */ class Foo(T) { T x; // <----------- Because gonna just an int field! this(T n) { x = n; } override string toString() { import std.conv : text; return x.text; } } alias Int = Foo!int; // more simple... import std.stdio : writeln; import std.traits: isMutable; /* * Let's simply use and test it! */ void main() { auto n = new Int(41); auto r = (new Int(1)).inConst(n);/* auto r = (new Int(1)).outConst(n); assert( r.x == 42 && !isMutable!( typeof(r) ) );//*/ n.writeln; // "41": It still has a value of 41. r.writeln; // "43": Added an extra 1 as expected! } // A, we can get its to guarantee us that parameters // won't change: auto inConst(T)(T a, const T b) // const { // it's not needed --^ but ^-- why can't this be used a.x += 1; /* suppose it happened accidentally! ^-- it's already a new copy, right?//*/ return new T(a.x + b.x); // Foo!int(43) } // B is used to guarantee that the returned result // doesn't change: const(T) outConst(T)(T a, T b) { return new T(a.x + b.x); } ``` In summary, we can use it in several places (in/out data, body, etc.) in a function. Is const needed if the compiler is copying? So why can't at the beginning of the body also be used and we get this error:source_file.d(38): Error: function `source.inConst!(Foo!int).inConst` without `this` cannot be `const` source_file.d(26): Error: template instance `source.inConst!(Foo!int)` error instantiatingI appreciate the answers given because they hold a very important place in my life, thank you. SDB 79
Mar 12 2023
On Sunday, 12 March 2023 at 15:09:45 UTC, Salih Dincer wrote:Hi, As someone who has used const very little in my life, I want to learn and ask: What are consts used in function parameters for; isn't there a copy already?Const is used for you not be able to change your values inside references. This is why we have const methods for example: ```d class Test { private int a; int getA() const {return a;} } ``` By having this property in your method, it says you're guaranteeing that Test won't be changed when this method is called, then, it'll be less time trying to find what mutated the object, so, use it as much as you can, but never overuse it since it is a pain to deal with. Const for value types is also used for not mutating them inside the function also leading to less debugging. Another use case for them is for compiler being able to infer some optimizations. If your variable is `immutable`, it becomes implicitly `__gshared`, which does not uses Thread Local Storage, another good thing for optimization in both memory and access.
Mar 12 2023
On 3/12/23 08:09, Salih Dincer wrote:As someone who has used const very little in my lifeYou can live without 'const' until your code interacts with other people's code. For example, the following program works just fine: struct S { int * p; void foo() {} } void bar(S s) {} void main() { auto s = S(); s.foo(); bar(s); } Now you replace (or a user of your code replaces) 'auto' with 'const' and you will get 2 compilation errors: const s = S(); s.foo(); // ERROR 1 bar(s); // ERROR 2 So, if your code will ever interact with other people's code it must be const-correct. If foo() is not mutating the object (including through the p member), it better be defined as 'const': void foo() const {} And if bar() is not mutating the parameter, it better take as const: void bar(const(S) s) {} Now the code compiles. You can (and should) use 'const' everywhere that you can because it increases the usability of code: Mutable, 'const', and 'immutable' variables can be used with code that takes by 'const'. This is not the same with code taking by 'immutable'. It can only be used with 'immutable' variables. Ali
Mar 12 2023
On Sunday, 12 March 2023 at 19:09:13 UTC, Ali Çehreli wrote:---In this case, using `ref` will increase performance while reducing the number of copies. Would it be wise to use `const ref` to protect the routine from ourselves or someone else? For example: ```d auto inConst( //const ref Int a, const ref Int b) { a.x += 1; return Int(a.x + b.x); } struct Foo(T) { T x; alias x this; this(T n) { x = n; } } alias Int = Foo!int; ``` SDB 79
Mar 13 2023
On 3/13/23 08:17, Salih Dincer wrote:In this case, using `ref` will increase performance while reducing the number of copies.I am not sure about that. Unless there is an expensive copy construction, most objects are simple data copies. To use 'ref' or not should be guided through semantics. Luckily, we have the -preview=in command line switch that removes the cost of copying from the equation: https://dlang.org/spec/function.html#in-params Just marking the input parameters 'in' should be sufficient in most cases. Ali
Mar 13 2023
On Sunday, 12 March 2023 at 15:09:45 UTC, Salih Dincer wrote:...So I don't agree with part of this comment (made elsewhere in this thread): "You can live without 'const' until your code interacts with other people's code." Code interacts with other code. Code should always be clear as to its intent. Who wrote that code, or other code that interacts with that code, is irrelvant. As for the issue of 'const' itelf, I refer you to a thoughtful article on this matter: (I'm not saying I agree with this article, or that I don't agree, I'm just referring it to you to make your own judgements. http://www.jmdavisprog.com/articles/why-const-sucks.html
Mar 12 2023
On 3/12/23 16:14, FozzieBear wrote:On Sunday, 12 March 2023 at 15:09:45 UTC, Salih Dincer wrote:thread):...So I don't agree with part of this comment (made elsewhere in this"You can live without 'const' until your code interacts with other people's code."My comment was purely technical. What I meant is, if the code is an island where there is no single 'const' in sight, then a D programmer can live by ignoring 'const'. At a technical level... This is different from C++ where you have to use references to const in order to take rvalue references as parameters. Since D does not allow binding rvalues even to references to const, this is a moot point. (-preview=in does bind rvalues to references as an optimization but that fact is hidden from the programmer.) So, my comment is correct at a technical level.Code interacts with other code. Code should always be clear as to its intent.Absolutely. That's why I always start with 'const' (what should have been the default but is not for historical reasons): const foo = bar(); I change that 'const' to e.g. 'auto' as needed.Who wrote that code, or other code that interacts with that code, is irrelvant.However, there is always the danger of going too far though. To keep the fun in the game, a programmer should be free to do whatever they want in their own code e.g. in their throw-away script programs. Here is one line I never include in production code but I very frequently use in short programs: import std; Removes mental load, frees the mind, and enables flow of programming. Some code is written for myself, not for people who are not watching over my shoulder. There is pride in caring for every character of the source code but sometimes freedom from all concerns is good too. Luckily, D makes it easy to refactor as requirements change. Ali
Mar 17 2023
On Friday, 17 March 2023 at 22:41:18 UTC, Ali Çehreli wrote:My comment was purely technical. What I meant is, if the code is an island where there is no single 'const' in sight, then a D programmer can live by ignoring 'const'. At a technical level... This is different from C++ where you have to use references to const in order to take rvalue references as parameters. Since D does not allow binding rvalues even to references to const, this is a moot point. (-preview=in does bind rvalues to references as an optimization but that fact is hidden from the programmer.)Let's increase the level one bit... Again we will remain within the boundaries of `-preview=in`, but we will learn other hidden information. Because you get interesting results when you raise the issue to function overloading. Here's what happens when you compile the following example: https://wandbox.org/permlink/XvInUjEtMKOS0CVD 1. I guess none of objects are created copy. Because Apple has already `ref` and Pineapple didn't execute ctor because of `in` keyword. Isn't Quince also a `const` but it was created when it is not a copyible object:ref: Apple in: Pinapple const: Quince 0 copies... [Apple: paid, pinapple, quince]2. If there is no function that takes `ref`, Apple prefers `const`. Please just hide the function under the version block. In this case, ctor will run once:const: Apple in: Pinapple const: Quince 1 copies... [qpple, pinapple, quince]3. If you replace `in` with `scope` (function 3) then pineapple and quince will also select different functions:const: Apple const: Pinapple in: Quince 2 copies... [qpple, qinapple, puince]With this example, it is possible to obtain dozens of results like these. I love D, D is a very powerful language. SDB 79
Mar 18 2023
On Sunday, 12 March 2023 at 15:09:45 UTC, Salih Dincer wrote:Hi, [...] // A, we can get its to guarantee us that parameters // won't change: auto inConst(T)(T a, const T b) // const { // it's not needed --^ but ^-- why can't this be usedWell you got the great answers to your questions already but I like to add a comment that is that **`const` parameters without `ref` are really moot.** I whish at least that they could give the guarantee to be rvalues (i.e have no address) but this is actually not the case. All the D compilers will actually copy `const` parameters to locals, making them lvalues, unless optimizations are requested(1). See codegen : https://godbolt.org/z/vev1PGWh3. This brings the idea that maybe a `rvalue` storage class could be added to the language. (1): Actually DMD does not drop the copy **at all**, even with -O.
Mar 13 2023