Re: Question on Immutability

2021-09-01 Thread Merlin Diavova via Digitalmars-d-learn

Goal achieved! Thanks all, really appreciate the assistance.


Re: Question on Immutability

2021-08-31 Thread Mike Parker via Digitalmars-d-learn

On Tuesday, 31 August 2021 at 06:15:07 UTC, jfondren wrote:

On Tuesday, 31 August 2021 at 05:42:22 UTC, ag0aep6g wrote:

On 31.08.21 02:50, Mike Parker wrote:
Member functions marked as immutable can be called on both 
mutable and immutable instances.


That's not true.


Demonstrated:


Well I'm really on my A game lately.


Re: Question on Immutability

2021-08-31 Thread jfondren via Digitalmars-d-learn

On Tuesday, 31 August 2021 at 05:42:22 UTC, ag0aep6g wrote:

On 31.08.21 02:50, Mike Parker wrote:
Member functions marked as immutable can be called on both 
mutable and immutable instances.


That's not true.


Demonstrated:

```d
struct S {
int x;
int get() immutable { return x; }
}

unittest {
auto s1 = S(1);
const s2 = S(2);
immutable s3 = S(3);
assert(s1.get == 1); // Error: is not callable using a 
mutable object
assert(s2.get == 2); // Error: is not callable using a 
`const` object

assert(s3.get == 3);
}
```

s/immutable/const/ and all those uses are acceptable.


Re: Question on Immutability

2021-08-30 Thread ag0aep6g via Digitalmars-d-learn

On 31.08.21 02:50, Mike Parker wrote:
Member functions marked as immutable can be called on both mutable and 
immutable instances.


That's not true.


Re: Question on Immutability

2021-08-30 Thread Mike Parker via Digitalmars-d-learn

On Monday, 30 August 2021 at 23:27:07 UTC, Merlin Diavova wrote:


```
After playing around the above works, Great! However I have 
some questions


First, why do the interfaces have to be defined as `immutable 
interface`?

The interfaces cannot be changed at runtime or instantiated.


It isn't required. And that's related to the answer to the next 
question.




Secondly, why does defining the return type for withName as 
`Project` give the `Error: 'immutable' method 
'winry.project.Project.name' is not callable using a mutable 
object`. However changing it to `immutable(Project)` works as 
expected.




Applying immutable to a class or interface does not make 
instances immutable. It makes member functions callable on 
immutable instances. Example:


```d
import std.stdio;

interface Foo {
void bar() immutable;
}

class Baz : Foo {
void bar() immutable { writeln("Boo!"); }
}

void main()
{
immutable(Baz) b = new Baz;
b.bar();

}
```

Notice my application of immutable on the declarations of the 
member functions. This means that the `bar` function is callable 
through immutable instances of `Foo`.


When you apply immutable to the interface declaration, it has the 
effect of applying it to every member function. You can see that 
from the compilation error output when we modify the above to 
this:


```d
import std;

immutable interface Foo {
void bar();
}

class Baz : Foo {
void bar() { writeln("Boo!"); }
}

void main()
{
immutable(Baz) b = new Baz;
b.bar();

}
```

```d
onlineapp.d(7): Error: class `onlineapp.Baz` interface function 
`void bar() immutable` is not implemented

```

Member functions marked as immutable can be called on both 
mutable and immutable instances. Member functions without it can 
only be called on mutable instances.


This applies to const as well.


Re: Question on Immutability

2021-08-30 Thread H. S. Teoh via Digitalmars-d-learn
On Mon, Aug 30, 2021 at 11:27:07PM +, Merlin Diavova via 
Digitalmars-d-learn wrote:
> Hi All,
> 
> I'm trying to understand immutability in D and it seems a bit odd.
> I'm coming from dynamic languages so please forgive my ignorance and
> dynamic language-isms.
> 
> I want to have a base `Project interface` and then extend other more
> specific interfaces from that such as `DockerEnabledProject
> interface`, `NetworkEnabledProject interface` etc.
> 
> The interface implementations are immutable. I have defined some
> methods that allows one to change specific properties and return a new
> instance of the implementation.

> 
> ```d
> immutable interface Project
> {
> string name();
> immutable(Project) withName(string name); // Returns a new instance
> }
> 
> immutable class ShellScriptCLI : Project
> {
> private string _name, _slug;
> private DirectoryPath _directory;
> 
> string name()
> {
> return this._name;
> }
> 
> immutable(Project) withName(string name)
> {
> return new immutable ShellScriptCLI(name, this._slug,
> this._directory);
> }
> }
> 
> ...
> 
> auto project = new immutable ShellScriptCLI("Project One", "project-one",
> projectPath);
> auto modifiedProject = project.withName("G2 Project");
> assert(modifiedProject.name == "G2 Project");
> ```
> After playing around the above works, Great! However I have some questions
> 
> First, why do the interfaces have to be defined as `immutable interface`?
> The interfaces cannot be changed at runtime or instantiated.
>
> Secondly, why does defining the return type for withName as `Project`
> give the `Error: 'immutable' method 'winry.project.Project.name' is
> not callable using a mutable object`. However changing it to
> `immutable(Project)` works as expected.

You need to declare Project.name and Project.withName with either
`const` or `immutable`, like this:

 string name() const;
 immutable(Project) withName(string name) immutable;

The second `immutable` in .withName applies to the implicit `this`
parameter received by every method.  Without this qualifier you cannot
invoke it with an immutable object.

The interface itself does not need to be immutable; putting `immutable`
on it merely makes `immutable` the default attributes in member
declarations, which is likely not what you want if you will be defining
mutable data fields later on.  It happens to fix your compile error
because you forgot to put `const` or `immutable` on .name and .withName.

//

The best way to understand const/mutable/immutable in D is this little
diagram (forgive the ASCII art):

   const
  / \
mutable immutable

Think of it as analogous to a class hierarchy diagram (a "type
hierarchy" if you will): both mutable and immutable implicit convert to
const, but const does not convert to either.

Basically, `const` means the holder of the reference is not allowed to
modify it.  So it doesn't matter whether the original data was mutable
or immutable: as far as the recipient is concerned, it cannot modify the
data, so everything is good.

`immutable` means that ALL references to the data cannot modify it (this
applies across threads too).  Const data *could* be modified by somebody
who happens to hold a mutable reference to it; immutable data cannot be
modified, period.  This means immutable can be freely shared across
threads (there are no mutable references to it, so the data never
changes and any thread can read it without needing to synchronize).

Furthermore, const/immutable in D is transitive, i.e., if a reference is
const, then any data it references is also implicitly const, and the
data referenced by said data, etc., is also const. Ditto with immutable.
We call it "turtles all the way down". :-)  In D you cannot have an
immutable reference to immutable data, and if you have a const reference
to something, you cannot modify anything it may refer to recursively.


T

-- 
The most powerful one-line C program: #include "/dev/tty" -- IOCCC


Question on Immutability

2021-08-30 Thread Merlin Diavova via Digitalmars-d-learn

Hi All,

I'm trying to understand immutability in D and it seems a bit odd.
I'm coming from dynamic languages so please forgive my ignorance 
and dynamic language-isms.


I want to have a base `Project interface` and then extend other 
more specific interfaces from that such as `DockerEnabledProject 
interface`, `NetworkEnabledProject interface` etc.


The interface implementations are immutable. I have defined some 
methods that allows one to change specific properties and return 
a new instance of the implementation.


```d
immutable interface Project
{
string name();
immutable(Project) withName(string name); // Returns a new 
instance

}

immutable class ShellScriptCLI : Project
{
private string _name, _slug;
private DirectoryPath _directory;

string name()
{
return this._name;
}

immutable(Project) withName(string name)
{
return new immutable ShellScriptCLI(name, this._slug, 
this._directory);

}
}

...

auto project = new immutable ShellScriptCLI("Project One", 
"project-one", projectPath);

auto modifiedProject = project.withName("G2 Project");
assert(modifiedProject.name == "G2 Project");
```
After playing around the above works, Great! However I have some 
questions


First, why do the interfaces have to be defined as `immutable 
interface`?

The interfaces cannot be changed at runtime or instantiated.

Secondly, why does defining the return type for withName as 
`Project` give the `Error: 'immutable' method 
'winry.project.Project.name' is not callable using a mutable 
object`. However changing it to `immutable(Project)` works as 
expected.


Look forward to your help.

Thanks
Merlin