www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Embarrassed to ask this question because it seems so trivial but

reply WhatMeWorry <kheaser gmail.com> writes:
While studying Ali's book at chapter "Constructor and Other 
Special Functions" and the below code snippet:


import std.stdio;

     struct S {
         this(int i) { writeln("an object"); }

         // Original
         //this(int i) const { writeln("a const object"); }
         //this(int i) immutable { writeln("an immutable object"); 
}
         //this(int i) shared { writeln("a shared object"); }

         const this(int i) { writeln("a const object"); }
         immutable this(int i) { writeln("an immutable object"); }
         shared this(int i) { writeln("a shared object"); }
     }

     void main() {
         auto m = S(1);
         auto c = const(S)(2);
         auto i = immutable(S)(3);
         auto s = shared(S)(4);
     }

Assuming I can speak in correct programmer-ese: I was wondering 
why the qualifiers were placed after the function parameter list 
(int i).  Just for fun, I moved to type qualifiers before the 
function definitions "this" (like a return type?) and the output 
was  exactly identical.  So I guess my question is, is this just 
a matter of esthetics or is some more nuanced goal at work here?
Jan 27 2022
next sibling parent Dennis <dkorpel gmail.com> writes:
On Thursday, 27 January 2022 at 17:42:09 UTC, WhatMeWorry wrote:
 So I guess my question is, is this just a matter of esthetics 
 or is some more nuanced goal at work here?
It doesn't matter much for constructors, but in general, the problem with placing qualifiers in front is that it looks confusing: ```D struct S { immutable int[] f() { return []; } } ``` This reads as if it returns an `immutable(int[])`, but it doesn't, the `immutable` means that it can only be called on `immutable` instances of `S`.
Jan 27 2022
prev sibling next sibling parent Steven Schveighoffer <schveiguy gmail.com> writes:
On 1/27/22 12:42 PM, WhatMeWorry wrote:

 Assuming I can speak in correct programmer-ese: I was wondering why the 
 qualifiers were placed after the function parameter list (int i).  Just 
 for fun, I moved to type qualifiers before the function definitions 
 "this" (like a return type?) and the output was  exactly identical.  So 
 I guess my question is, is this just a matter of esthetics or is some 
 more nuanced goal at work here?
For constructors, being on the front is not misleading. But for a member function that returns a value, take a look: ```d struct S { int * x; const int *foo() { return x; } } ``` What do you think happens here? The answer, is that this is a compiler error. The error is that the `const` applies to the `this` parameter and *not* the return value. So you are accepting a `const S`, and trying to return its member `x` as a plain `int *`. This is why we always recommend putting the `this` modifiers at the end of the function to make it visually clear that they don't apply to the return value. -Steve
Jan 27 2022
prev sibling parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Thu, Jan 27, 2022 at 05:42:09PM +0000, WhatMeWorry via Digitalmars-d-learn
wrote:
 While studying Ali's book at chapter "Constructor and Other Special
 Functions" and the below code snippet:
[...]
         // Original
         //this(int i) const { writeln("a const object"); }
         //this(int i) immutable { writeln("an immutable object"); }
         //this(int i) shared { writeln("a shared object"); }
 
         const this(int i) { writeln("a const object"); }
         immutable this(int i) { writeln("an immutable object"); }
         shared this(int i) { writeln("a shared object"); }
[...]
 Assuming I can speak in correct programmer-ese: I was wondering why
 the qualifiers were placed after the function parameter list (int i).
 Just for fun, I moved to type qualifiers before the function
 definitions "this" (like a return type?) and the output was  exactly
 identical.  So I guess my question is, is this just a matter of
 esthetics or is some more nuanced goal at work here?
In method declarations, modifiers like const/immutable/shared play two distinct roles: 1) Qualifying the return type of the method; 2) Qualifying the implicit `this` parameter of the method. Historically, D has been rather lax about where qualifiers in the sense of (2) can go, so that's why: const this() is the same as this() const They both mean that the implicit `this` parameter (not to be confused with `this` as the name of the ctor) is const. Personally, though, I prefer the 2nd form, because the first form could potentially be ambiguous in non-ctor member functions: struct S { const int method(); } Does the const apply to `int` or to the implicit `this` parameter? It's not obvious. Better to write it this way: int method() const; // const applied to `this` const(int) method(); // const applied to return type N.B. the parentheses in `const(int)` -- while D is lax in allowing you to write `const int`, that leads to the ambiguous situation above. My personal recommendation is to always parenthesize qualified types so that they are never ambiguous. T -- Mediocrity has been pushed to extremes.
Jan 27 2022