Thread overview
Can someone explain why i can change this immutable variable please?
Oct 09, 2013
Gary Willoughby
Oct 09, 2013
Ali Çehreli
Oct 09, 2013
Gary Willoughby
Oct 09, 2013
Dicebot
Oct 09, 2013
Daniel Davidson
Oct 09, 2013
Gary Willoughby
Oct 09, 2013
Daniel Davidson
Oct 09, 2013
Orvid King
October 09, 2013
Can someone explain why i can change Bar's immutable name member please?

	import std.stdio;

	class Foo
	{
		public void change(string name)
		{
			name = "tess";
			writeln(name);
		}
	}

	class Bar
	{
		private static immutable string name = "gary";

		public void test()
		{
			auto foo = new Foo();
			foo.change(this.name);
		}
	}

	void main(string[] args)
	{
		auto bar = new Bar();
		bar.test();
	}

I thought an error would inform me that the `Foo.change` function is being called with the wrong parameter type.
October 09, 2013
On 10/09/2013 08:26 AM, Gary Willoughby wrote:
> Can someone explain why i can change Bar's immutable name member please?
>
>      import std.stdio;
>
>      class Foo
>      {
>          public void change(string name)
>          {
>              name = "tess";
>              writeln(name);
>          }
>      }
>
>      class Bar
>      {
>          private static immutable string name = "gary";
>
>          public void test()
>          {
>              auto foo = new Foo();
>              foo.change(this.name);
>          }
>      }
>
>      void main(string[] args)
>      {
>          auto bar = new Bar();
>          bar.test();
>      }
>
> I thought an error would inform me that the `Foo.change` function is
> being called with the wrong parameter type.

Foo.Change receives a string:

    public void change(string name)
    {
        name = "tess";
        writeln(name);
    }

That string is independent from the argument (i.e. Bar.name). They initially share the same characters. Either of those strings can leave this sharing at will, and that is exactly what name="tess" does. 'name' now refers  to different immutable chars.

Ali

October 09, 2013
On Wednesday, 9 October 2013 at 15:26:35 UTC, Gary Willoughby wrote:
> Can someone explain why i can change Bar's immutable name member please?
>
> 	import std.stdio;
>
> 	class Foo
> 	{
> 		public void change(string name)
> 		{
> 			name = "tess";
> 			writeln(name);
> 		}
> 	}
>
> 	class Bar
> 	{
> 		private static immutable string name = "gary";
>
> 		public void test()
> 		{
> 			auto foo = new Foo();
> 			foo.change(this.name);
> 		}
> 	}
>
> 	void main(string[] args)
> 	{
> 		auto bar = new Bar();
> 		bar.test();
> 	}
>
> I thought an error would inform me that the `Foo.change` function is being called with the wrong parameter type.

This would fail if you were to declare `change` as `void change(ref string name)`. This is valid because you are passing the value of a reference to a string. `Bar.name` is an immutable reference to a string, but your only passing a copy of that reference to `Foo.change`, that copy is mutable by default.
October 09, 2013
On Wednesday, 9 October 2013 at 15:33:23 UTC, Ali Çehreli wrote:
> On 10/09/2013 08:26 AM, Gary Willoughby wrote:
>> Can someone explain why i can change Bar's immutable name member please?
>>
>>     import std.stdio;
>>
>>     class Foo
>>     {
>>         public void change(string name)
>>         {
>>             name = "tess";
>>             writeln(name);
>>         }
>>     }
>>
>>     class Bar
>>     {
>>         private static immutable string name = "gary";
>>
>>         public void test()
>>         {
>>             auto foo = new Foo();
>>             foo.change(this.name);
>>         }
>>     }
>>
>>     void main(string[] args)
>>     {
>>         auto bar = new Bar();
>>         bar.test();
>>     }
>>
>> I thought an error would inform me that the `Foo.change` function is
>> being called with the wrong parameter type.
>
> Foo.Change receives a string:
>
>     public void change(string name)
>     {
>         name = "tess";
>         writeln(name);
>     }
>
> That string is independent from the argument (i.e. Bar.name). They initially share the same characters. Either of those strings can leave this sharing at will, and that is exactly what name="tess" does. 'name' now refers  to different immutable chars.
>
> Ali

So why does this give me an error i expect:

	import std.stdio;

	class Foo
	{
		public void change(string[] name)
		{
			name[0] = "tess";
			writeln(name);
		}
	}

	class Bar
	{
		private static immutable string name[] = ["gary"];

		public void test()
		{
			auto foo = new Foo();
			foo.change(this.name);
		}
	}

	void main(string[] args)
	{
		auto bar = new Bar();
		bar.test();
	}
October 09, 2013
D does stripping of qualifiers from top level when creating a copy which allows to pass immutable stuff as mutable parameter by value. Adding any single level of immutable indirection will make this impossible and result in compile-time error.
October 09, 2013
On Wednesday, 9 October 2013 at 15:46:29 UTC, Gary Willoughby wrote:
>
> So why does this give me an error i expect:
>
> 	import std.stdio;
>
> 	class Foo
> 	{
> 		public void change(string[] name)
> 		{
> 			name[0] = "tess";
> 			writeln(name);
> 		}
> 	}
>
> 	class Bar
> 	{
> 		private static immutable string name[] = ["gary"];
>
> 		public void test()
> 		{
> 			auto foo = new Foo();
> 			foo.change(this.name);
> 		}
> 	}
>
> 	void main(string[] args)
> 	{
> 		auto bar = new Bar();
> 		bar.test();
> 	}

Maybe this will help explain it:
void main() {
  pragma(msg, typeof(Bar.name));
  pragma(msg, typeof(Foo.change));
}
will print:

immutable(char[][])
void(string[] name)

The latter is really:

void(immutable(char)[] name)

The former is really:
immutable(immutable(immutable(char)[])[])

So for name the whole kit and kaboodle is immutable and you can not pass the whole immutable thing into something that is only immutable at one level.

Thanks
Dan
October 09, 2013
On Wednesday, 9 October 2013 at 16:02:43 UTC, Daniel Davidson wrote:
> Maybe this will help explain it:
> void main() {
>   pragma(msg, typeof(Bar.name));
>   pragma(msg, typeof(Foo.change));
> }
> will print:
>
> immutable(char[][])
> void(string[] name)
>
> The latter is really:
>
> void(immutable(char)[] name)
>
> The former is really:
> immutable(immutable(immutable(char)[])[])
>
> So for name the whole kit and kaboodle is immutable and you can not pass the whole immutable thing into something that is only immutable at one level.
>
> Thanks
> Dan

Ah right, of course. Thanks.
October 09, 2013
On Wednesday, 9 October 2013 at 15:33:23 UTC, Ali Çehreli wrote:
>
> That string is independent from the argument (i.e. Bar.name). They initially share the same characters. Either of those strings can leave this sharing at will, and that is exactly what name="tess" does. 'name' now refers  to different immutable chars.
>

And to prove it - change main to:

void main(string[] args)
{
    auto bar = new Bar();
    bar.test();
    writeln(Bar.name);
}

and as much as you may want to become tess, you will still be gary.