Re: Embarrassed to ask this question because it seems so trivial but genuinely curious...

2022-01-27 Thread H. S. Teoh via Digitalmars-d-learn
On Thu, Jan 27, 2022 at 05:42:09PM +, 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.


Re: Embarrassed to ask this question because it seems so trivial but genuinely curious...

2022-01-27 Thread Steven Schveighoffer via Digitalmars-d-learn

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


Re: Embarrassed to ask this question because it seems so trivial but genuinely curious...

2022-01-27 Thread Dennis via Digitalmars-d-learn

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`.





Embarrassed to ask this question because it seems so trivial but genuinely curious...

2022-01-27 Thread WhatMeWorry via Digitalmars-d-learn
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?