www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Can someone explain why i can change this immutable variable please?

reply "Gary Willoughby" <dev nomad.so> writes:
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.
Oct 09 2013
next sibling parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
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
Oct 09 2013
next sibling parent reply "Gary Willoughby" <dev nomad.so> writes:
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(); }
Oct 09 2013
next sibling parent "Dicebot" <public dicebot.lv> writes:
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.
Oct 09 2013
prev sibling parent reply "Daniel Davidson" <nospam spam.com> writes:
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
Oct 09 2013
parent "Gary Willoughby" <dev nomad.so> writes:
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.
Oct 09 2013
prev sibling parent "Daniel Davidson" <nospam spam.com> writes:
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.
Oct 09 2013
prev sibling parent "Orvid King" <blah38621 gmail.com> writes:
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.
Oct 09 2013