www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - immutable, const, enum

reply bearophile <bearophileHUGS lycos.com> writes:
I am about one year late for such comments or more. I also have some
suggestions and questions.

I suggest to perform a serch & replace in all the D2 documentation to replace
all "invariant" with "immutable". Some versions of D2 from now "invariant" can
be removed from DMD itself.

-----------------

From the examples of the docs. I hope to not see this code, it's not easy to
understand:
immutable(char*)** p = ...;

-----------------

The const and immutable function attributes can also appear after the closing
parenthesis of the parameter list: <

I think this doesn't produce much damage, but why? ----------------- Mutable and transitive-immutable data types are easy to understand. But "const" is less easy to understand for me:
Const types are like immutable types, except that const forms a read-only view
of data. Other aliases to that same data may change it at any time.<

Regarding its purpose the docs say just:
const finds applications in passing data through interfaces that promise not to
modify them.<

I suggest to add more examples of "const" usage, to show where it can be useful, because I am not much able to understand where to use it. It may also be better to rename "const" of D2 as "constview" or "cview" then (and the meaning of const can be kept from D1). The semantic overloading of the "enum" keyword doesn't look nice, but it's not too much bad. ----------------- The following things are written about constview/immutable member functions: immutable member functions are guaranteed that the object and anything referred to by the this reference is immutable. They are declared as: struct S { int x; immutable void foo() { x = 4; // error, x is immutable this.x = 4; // error, x is immutable } } constview member functions are functions that are not allowed to change any part of the object through the member function's this reference. I don't understand such explanations, and I'd like to see a bit wider example(s) about it. ----------------- Immutable structs/classes can be quite useful, they are safer, remove some complexity from a program, they can be sometimes the right thing you want (think about a Date object that keeps one day of the year), help paralellism, and they may allow for other optimizations (for example there's no need to copy them (so you can save memory and/or allocations, just like for immutable strings), or on the opposite you can have a copy of them on each CPU cache, and you are sure they will not go out of sync, this allows for a program more scalable on multi-cores). So I have tried to write a very simple program that uses immutable structs and classes: immutable struct S { int x; this(int xx) { this.x = x; } } immutable class C { int x; this(int xx) { this.x = x; } } void main() { auto s = S(10); auto c = new C(10); } But the compiler outputs: Error: cannot implicitly convert expression (this) of type immutable(C) to test.C test.d(8): Error: constructor test.C.this missing initializer for final field x test.d(12): Error: constructor test.S.this (int xx) does not match parameter types (int) test.d(12): Error: ((immutable immutable(S) __ctmp1 = 0; ) , __ctmp1).this can only be called on a mutable object, not immutable(S) I don't understand such errors much. What is that I am doing wrong? Note that if you remove the "immutable" that program works, and if you replace "immutable" with "invariant" the compiler gives thye same errors (internally it keeps using immutable(C)). Thank you, bye, bearophile
Apr 28 2009
next sibling parent reply Steve Teale <steve.teale britseyeview.com> writes:
bearophile Wrote:

 I am about one year late for such comments or more. I also have some
suggestions and questions.
 
 I suggest to perform a serch & replace in all the D2 documentation to replace
all "invariant" with "immutable". Some versions of D2 from now "invariant" can
be removed from DMD itself.
 
 -----------------
 
 From the examples of the docs. I hope to not see this code, it's not easy to
understand:
 immutable(char*)** p = ...;
 
 -----------------
 
The const and immutable function attributes can also appear after the closing
parenthesis of the parameter list: <

I think this doesn't produce much damage, but why? ----------------- Mutable and transitive-immutable data types are easy to understand. But "const" is less easy to understand for me:
Const types are like immutable types, except that const forms a read-only view
of data. Other aliases to that same data may change it at any time.<

Regarding its purpose the docs say just:
const finds applications in passing data through interfaces that promise not to
modify them.<

I suggest to add more examples of "const" usage, to show where it can be useful, because I am not much able to understand where to use it. It may also be better to rename "const" of D2 as "constview" or "cview" then (and the meaning of const can be kept from D1). The semantic overloading of the "enum" keyword doesn't look nice, but it's not too much bad. ----------------- The following things are written about constview/immutable member functions: immutable member functions are guaranteed that the object and anything referred to by the this reference is immutable. They are declared as: struct S { int x; immutable void foo() { x = 4; // error, x is immutable this.x = 4; // error, x is immutable } } constview member functions are functions that are not allowed to change any part of the object through the member function's this reference. I don't understand such explanations, and I'd like to see a bit wider example(s) about it. ----------------- Immutable structs/classes can be quite useful, they are safer, remove some complexity from a program, they can be sometimes the right thing you want (think about a Date object that keeps one day of the year), help paralellism, and they may allow for other optimizations (for example there's no need to copy them (so you can save memory and/or allocations, just like for immutable strings), or on the opposite you can have a copy of them on each CPU cache, and you are sure they will not go out of sync, this allows for a program more scalable on multi-cores). So I have tried to write a very simple program that uses immutable structs and classes: immutable struct S { int x; this(int xx) { this.x = x; } } immutable class C { int x; this(int xx) { this.x = x; } } void main() { auto s = S(10); auto c = new C(10); } But the compiler outputs: Error: cannot implicitly convert expression (this) of type immutable(C) to test.C test.d(8): Error: constructor test.C.this missing initializer for final field x test.d(12): Error: constructor test.S.this (int xx) does not match parameter types (int) test.d(12): Error: ((immutable immutable(S) __ctmp1 = 0; ) , __ctmp1).this can only be called on a mutable object, not immutable(S) I don't understand such errors much. What is that I am doing wrong? Note that if you remove the "immutable" that program works, and if you replace "immutable" with "invariant" the compiler gives thye same errors (internally it keeps using immutable(C)). Thank you, bye, bearophile

Well, I'm glad it's just not me! Anytime I've used the keyword 'invariant' what I get just won't compile. So I remove it, which suggests that from a practical point of view, it is not much use. Const for me should mean pretty much what it means in C++ If I write: foo(const Bar b) { // I mean that if in my implementation of the function, I try to alter // b, then the compiler should flag it as an error. } foo(invariant Bar b) { // Does not seem to offer anything else that I need! }
Apr 28 2009
parent reply Derek Parnell <derek psych.ward> writes:
On Tue, 28 Apr 2009 14:08:58 -0400, Steve Teale wrote:

 bearophile Wrote:
 
 I am about one year late for such comments or more. I also have some
suggestions and questions.
 
 I suggest to perform a serch & replace in all the D2 documentation to replace
all "invariant" with "immutable". Some versions of D2 from now "invariant" can
be removed from DMD itself.
 
 -----------------
 
 From the examples of the docs. I hope to not see this code, it's not easy to
understand:
 immutable(char*)** p = ...;
 
 -----------------
 
The const and immutable function attributes can also appear after the closing
parenthesis of the parameter list: <

I think this doesn't produce much damage, but why? ----------------- Mutable and transitive-immutable data types are easy to understand. But "const" is less easy to understand for me:
Const types are like immutable types, except that const forms a read-only view
of data. Other aliases to that same data may change it at any time.<

Regarding its purpose the docs say just:
const finds applications in passing data through interfaces that promise not to
modify them.<

I suggest to add more examples of "const" usage, to show where it can be useful, because I am not much able to understand where to use it. It may also be better to rename "const" of D2 as "constview" or "cview" then (and the meaning of const can be kept from D1). The semantic overloading of the "enum" keyword doesn't look nice, but it's not too much bad. ----------------- The following things are written about constview/immutable member functions: immutable member functions are guaranteed that the object and anything referred to by the this reference is immutable. They are declared as: struct S { int x; immutable void foo() { x = 4; // error, x is immutable this.x = 4; // error, x is immutable } } constview member functions are functions that are not allowed to change any part of the object through the member function's this reference. I don't understand such explanations, and I'd like to see a bit wider example(s) about it. ----------------- Immutable structs/classes can be quite useful, they are safer, remove some complexity from a program, they can be sometimes the right thing you want (think about a Date object that keeps one day of the year), help paralellism, and they may allow for other optimizations (for example there's no need to copy them (so you can save memory and/or allocations, just like for immutable strings), or on the opposite you can have a copy of them on each CPU cache, and you are sure they will not go out of sync, this allows for a program more scalable on multi-cores). So I have tried to write a very simple program that uses immutable structs and classes: immutable struct S { int x; this(int xx) { this.x = x; } } immutable class C { int x; this(int xx) { this.x = x; } } void main() { auto s = S(10); auto c = new C(10); } But the compiler outputs: Error: cannot implicitly convert expression (this) of type immutable(C) to test.C test.d(8): Error: constructor test.C.this missing initializer for final field x test.d(12): Error: constructor test.S.this (int xx) does not match parameter types (int) test.d(12): Error: ((immutable immutable(S) __ctmp1 = 0; ) , __ctmp1).this can only be called on a mutable object, not immutable(S) I don't understand such errors much. What is that I am doing wrong? Note that if you remove the "immutable" that program works, and if you replace "immutable" with "invariant" the compiler gives thye same errors (internally it keeps using immutable(C)). Thank you, bye, bearophile

Well, I'm glad it's just not me! Anytime I've used the keyword 'invariant' what I get just won't compile. So I remove it, which suggests that from a practical point of view, it is not much use. Const for me should mean pretty much what it means in C++ If I write: foo(const Bar b) { // I mean that if in my implementation of the function, I try to alter // b, then the compiler should flag it as an error. } foo(invariant Bar b) { // Does not seem to offer anything else that I need! }

The difference between immutable and const, in my understanding, is that 'immutable' means that nothing in the program will change it, and 'const' means that this function won't change it but it might be changed by other functions in the program. What has surprised me is that immutability is *not* guaranteed. It is also just a promise that the coder makes to the compiler. You can declare something as immutable and have the program change it. The compiler does not actually prevent that happening, it only makes it difficult to do. Same with const. -- Derek Parnell Melbourne, Australia skype: derek.j.parnell
Apr 28 2009
next sibling parent reply BCS <ao pathlink.com> writes:
Reply to Derek,

 What has surprised me is that immutability is *not* guaranteed. It is
 also just a promise that the coder makes to the compiler. You can
 declare something as immutable and have the program change it. The
 compiler does not actually prevent that happening, it only makes it
 difficult to do. Same with const.
 

The language has asm blocks can can call C. The only things it can guarantee are the same things the OS can guarantee. If the the language can get at sprintf and sscanf, you can get around any const system ever made.
Apr 28 2009
parent reply Derek Parnell <derek psych.ward> writes:
On Tue, 28 Apr 2009 23:39:14 +0000 (UTC), BCS wrote:

 Reply to Derek,
 
 What has surprised me is that immutability is *not* guaranteed.


 The language has asm blocks can can call C. The only things it can guarantee 
 are the same things the OS can guarantee.

Oh, I agree. It is just that the documentation is pretty adamant that "immutability" means that the data WILL NOT change. It gives the impression that there is compiler support to ensure that this is axiomatic rather than just a convention. -- Derek Parnell Melbourne, Australia skype: derek.j.parnell
Apr 28 2009
next sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Derek Parnell wrote:
 On Tue, 28 Apr 2009 23:39:14 +0000 (UTC), BCS wrote:
 
 Reply to Derek,

 What has surprised me is that immutability is *not* guaranteed.


 The language has asm blocks can can call C. The only things it can guarantee 
 are the same things the OS can guarantee.

Oh, I agree. It is just that the documentation is pretty adamant that "immutability" means that the data WILL NOT change. It gives the impression that there is compiler support to ensure that this is axiomatic rather than just a convention.

IMHO it's more than a convention. Andrei
Apr 28 2009
prev sibling next sibling parent Robert Fraser <fraserofthenight gmail.com> writes:
Derek Parnell wrote:
 On Tue, 28 Apr 2009 23:39:14 +0000 (UTC), BCS wrote:
 
 Reply to Derek,

 What has surprised me is that immutability is *not* guaranteed.


 The language has asm blocks can can call C. The only things it can guarantee 
 are the same things the OS can guarantee.

Oh, I agree. It is just that the documentation is pretty adamant that "immutability" means that the data WILL NOT change. It gives the impression that there is compiler support to ensure that this is axiomatic rather than just a convention.

It's supposed to give the impression that if you DO change it, undefined behavior (including crashes, if the value was stored in ROM) could result.
Apr 29 2009
prev sibling parent reply Walter Bright <newshound1 digitalmars.com> writes:
Derek Parnell wrote:
 Oh, I agree. It is just that the documentation is pretty adamant that
 "immutability" means that the data WILL NOT change. It gives the impression
 that there is compiler support to ensure that this is axiomatic rather than
 just a convention.

D is a systems programming language. By that I mean that there are mechanisms to defeat the type system, for those that know what they're doing. If you defeat the type system, and mutate immutably-typed data, the onus is on you. It's like if you pop the carburetor off and put a supercharger on, you void the warranty <g>.
Apr 29 2009
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Steven Schveighoffer wrote:
 On Wed, 29 Apr 2009 03:35:32 -0400, Walter Bright 
 <newshound1 digitalmars.com> wrote:
 
 Derek Parnell wrote:
 Oh, I agree. It is just that the documentation is pretty adamant that
 "immutability" means that the data WILL NOT change. It gives the 
 impression
 that there is compiler support to ensure that this is axiomatic 
 rather than
 just a convention.

D is a systems programming language. By that I mean that there are mechanisms to defeat the type system, for those that know what they're doing. If you defeat the type system, and mutate immutably-typed data, the onus is on you. It's like if you pop the carburetor off and put a supercharger on, you void the warranty <g>.

I hate having to keep argue this, but you keep forgetting. You cannot create immutable data without circumventing the type system (except strings which have special treatment).

Yes, this is a bug, and one not easy to fix (requires a bit of flow control in constructors), but we know how to fix it. It's just a matter of time. Andrei
Apr 29 2009
prev sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Wed, 29 Apr 2009 03:35:32 -0400, Walter Bright  
<newshound1 digitalmars.com> wrote:

 Derek Parnell wrote:
 Oh, I agree. It is just that the documentation is pretty adamant that
 "immutability" means that the data WILL NOT change. It gives the  
 impression
 that there is compiler support to ensure that this is axiomatic rather  
 than
 just a convention.

D is a systems programming language. By that I mean that there are mechanisms to defeat the type system, for those that know what they're doing. If you defeat the type system, and mutate immutably-typed data, the onus is on you. It's like if you pop the carburetor off and put a supercharger on, you void the warranty <g>.

I hate having to keep argue this, but you keep forgetting. You cannot create immutable data without circumventing the type system (except strings which have special treatment). Only way to make an immutable class: auto c = cast(immutable(C))new C; You have just circumvented the type system, and it's on you as a programmer to guarantee that C's constructor didn't store mutable references to itself somewhere, NOT the compiler. Until this is fixed, immutability is far less useful (except for strings). It's like you are buying a car where the dealer says you void the warranty if you put gas in it. -Steve
Apr 29 2009
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 28 Apr 2009 13:43:48 -0400, bearophile <bearophileHUGS lycos.com>  
wrote:

 The const and immutable function attributes can also appear after the  
 closing parenthesis of the parameter list: <

I think this doesn't produce much damage, but why?

First, C++ does it this way: int foo() const { } Second, because const/immutable is a type constructor, it can be applied to the return type as well as the function. So what looks less confusing to you: const A foo() // const function which returns a mutable A A foo() const // same thing, clearly const can't apply to A const const A foo() // const function which returns a const A const A foo() const // ditto There have been proposals to change const to const(this), so it is clear what you are applying const to (in fact, that is what a const function does, just mark the hidden "this" parameter as const): const(this) A foo() const A foo() // would either be syntax error or mean a normal fn that returns a const A I'd be in favor of such a change.
 -----------------

 The following things are written about constview/immutable member  
 functions:

 immutable member functions are guaranteed that the object and anything  
 referred to by the this reference is immutable. They are declared as:

 struct S {
     int x;

     immutable void foo() {
         x = 4;	    // error, x is immutable
         this.x = 4; // error, x is immutable
     }
 }

 constview member functions are functions that are not allowed to change  
 any part of the object through the member function's this reference.

 I don't understand such explanations, and I'd like to see a bit wider  
 example(s) about it.

The detail you are missing is that anything is implicitly castable to const, but nothing else implicitly casts. Think about it this way: const means "I cannot change this, but something else might be able to." So mutable can implicitly be cast to const if I don't want to change it, and immutable can implicitly cast to const. Mutable and immutable cannot implicitly be cast to eachother because that would violate immutability. So since something that is const could potentially be immutable OR mutable, it can't be implicitly cast to immutable or mutable because that would violate immutability. Many functions want the contract "I won't change this, but I don't care what anybody else does to it", so those are perfect candidates for const. The benefit is you can pass in mutable, const, or immutable data without an explicit cast. Immutable functions can add extra optimizations to their code. For example, you don't need to lock an immutable object to access its data. This kind of thing is very important for statically provable purity.
 -----------------

 Immutable structs/classes can be quite useful, they are safer, remove  
 some complexity from a program, they can be sometimes the right thing  
 you want (think about a Date object that keeps one day of the year),  
 help paralellism, and they may allow for other optimizations (for  
 example there's no need to copy them (so you can save memory and/or  
 allocations, just like for immutable strings), or on the opposite you  
 can have a copy of them on each CPU cache, and you are sure they will  
 not go out of sync, this allows for a program more scalable on  
 multi-cores).

 So I have tried to write a very simple program that uses immutable  
 structs and classes:

 immutable struct S {
     int x;
     this(int xx) { this.x = x; }
 }

 immutable class C {
     int x;
     this(int xx) { this.x = x; }
 }

 void main() {
     auto s = S(10);
     auto c = new C(10);
 }


 But the compiler outputs:


 Error: cannot implicitly convert expression (this) of type immutable(C)  
 to test.C
 test.d(8): Error: constructor test.C.this missing initializer for final  
 field x
 test.d(12): Error: constructor test.S.this (int xx) does not match  
 parameter types (int)
 test.d(12): Error: ((immutable immutable(S) __ctmp1 = 0;

 ) , __ctmp1).this can only be called on a mutable object, not  
 immutable(S)


 I don't understand such errors much. What is that I am doing wrong?
 Note that if you remove the "immutable" that program works, and if you  
 replace "immutable" with "invariant" the compiler gives thye same errors  
 (internally it keeps using immutable(C)).

Unfortunately, the whole thing is not completely fleshed out. currently, the only way to make an immutable class instance is to make a mutable class instance, and cast it to immutable once you have constructed it. Therefore, saying all instances of a class are immutable renders it useless. I don't really like the way this works, as the compiler is depending on the developer to ensure something marked as immutable really doesn't have any other mutable references to it. This can be difficult if you don't know the contents of the class. -Steve
Apr 28 2009
prev sibling parent reply Christian Kamm <kamm-incasoftware removethis.de> writes:
 immutable struct S {
     int x;
     this(int xx) { this.x = x; }
 }

As far as I know, immutable has no effect on class declarations, so what your code says is struct S { immutable int x; this(int xx) immutable { this.x = x; } } and that's causing problems. If you want an immutable instance, you can say: auto c = new immutable(C)(10); or cast an existing instance to immutable.
Apr 28 2009
next sibling parent Jarrett Billingsley <jarrett.billingsley gmail.com> writes:
On Tue, Apr 28, 2009 at 5:17 PM, Christian Kamm
<kamm-incasoftware removethis.de> wrote:
 As far as I know, immutable has no effect on class declarations

It does. http://www.digitalmars.com/d/2.0/class.html At the very bottom it describes const and invariant (i.e. immutable) classes.
Apr 28 2009
prev sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
Many thanks Steven Schveighoffer for the good explanations. Now I think I have
understood what's one of the purposes of const. const arguments of a function
just states that you aren't going to change the data inside a function/method,
more or less like in C++, but in a transitive way.

But wasn't "in" before an argument type already doing that? I presume "in"
isn't transitive. I have tried this:

import std.stdio: writeln;
void foo(in int* x) {
    (*x) = (*x) * 10;
    writeln(*x);
}
void main() {
    int y = 10;
    foo(&y);
}

But it doesn't work, so maybe in and const are the same thing now. Is "in"
going to be removed then? Or maybe it's better to remove const and keep just a
transitive "in". And I have seen "immutable ref" too is allowed, I guess it's
mostly for performance reasons. Maybe "immutable in" is just for show, this
works:

import std.stdio: writeln;

void foo(immutable in int x) {
    writeln(x * 2);
}
void main() {
    int y = 10;
    foo(y);
}

I want a simpler language -.-

While this doesn't work:

import std.stdio: writeln;

void foo(const in int x) {
    writeln(x * 2);
}
void main() {
    int y = 10;
    foo(y);
}

it prints: "redundant storage class in". So const and "in" seem really the same
thing. But then what does it mean "immutable in"? I guess it just means
transitive-immutable.

"immutable out" and "const out" are thankfully disallowed. So I guess "in" is
now deprecated, it's just an alias of "const. But this idea seems wrong because
"in ref" is disalloed but "const ref" is allowed, so they aren't just an alias
of each other.

So the available ones are ("in" not listed to keep a bit of my sanity):
 immutable type
 const type
 out type
 immutable ref type
 const ref type
 type
 type*
 type**
 etc

-----------------------------

Christian Kamm:

 immutable struct S {
     int x;
     this(int xx) { this.x = x; }
 }

As far as I know, immutable has no effect on class declarations, so what your code says is struct S { immutable int x; this(int xx) immutable { this.x = x; } } and that's causing problems. If you want an immutable instance, you can say: auto c = new immutable(C)(10);

Sorry, the constructor was: this(int xx) { this.x = xx; } The following code works, and x can't be modified from outside the constructor: import std.stdio: writeln; immutable struct S { int x; this(int xx) { this.x = xx * 2; } } void main() { auto s = new S(10); writeln(s.x); // 20 } I think it works because s is a mutable pointer to an immutable struct. If you do this: auto s = S(10); The assignment doesn't work because s too is immutable. Well, this idea may be false because a line of code just like this doesn't work: S(10); I don't see ways yet to create an immutable struct on the stack. Well... you can do: S s = { 10 }; But then the constructor isn't called. The following too works: import std.stdio: writeln; struct S { int x; this(int xx) { this.x = xx * 2; } } void main() { auto s = new immutable(S)(10); writeln(s.x); } I don't repeat similar experiments with immutable classes because they seem to never work to me. I think I have already understood about 5% of this topic :-) Bye, bearophile
Apr 28 2009
next sibling parent Paul D. Anderson <paul.d.removethis.anderson comcast.andthis.net> writes:
bearophile Wrote:

 Many thanks Steven Schveighoffer for the good explanations. Now I think I have
understood what's one of the purposes of const. const arguments of a function
just states that you aren't going to change the data inside a function/method,
more or less like in C++, but in a transitive way.
 

 But it doesn't work, so maybe in and const are the same thing now. Is "in"
going to be removed then? Or maybe it's better to remove const and keep just a
transitive "in". And I have seen "immutable ref" too is allowed, I guess it's
mostly for performance reasons. Maybe "immutable in" is just for show, this
works:
 
 So the available ones are ("in" not listed to keep a bit of my sanity):
  immutable type
  const type
  out type
  immutable ref type
  const ref type
  type
  type*
  type**
  etc
 

On the language/functions page: "The in storage class is equivalent to const scope." I hope that clears everything up for you! :-) Paul
Apr 28 2009
prev sibling parent reply Paul D. Anderson <paul.d.removethis.anderson comcast.andthis.net> writes:
bearophile Wrote:

<snip> 

 it prints: "redundant storage class in". So const and "in" seem really the
same thing. But then what does it mean "immutable in"? I guess it just means
transitive-immutable.
 
 "immutable out" and "const out" are thankfully disallowed. So I guess "in" is
now deprecated, it's just an alias of "const. But this idea seems wrong because
"in ref" is disalloed but "const ref" is allowed, so they aren't just an alias
of each other.
 
 So the available ones are ("in" not listed to keep a bit of my sanity):
  immutable type
  const type
  out type
  immutable ref type
  const ref type
  type
  type*
  type**
  etc
 

From the D2.0/Language/Functions page, under Function Parameters: "The in storage class is equivalent to const scope." That's why the "const in" combination doesn't work. Paul "I can't tell a lie -- not even when I hear one." John Kendrik Bangs, A House-Boat on the Styx.
Apr 28 2009
parent reply bearophile <bearophileHUGS lycos.com> writes:
Paul D. Anderson:
 From the D2.0/Language/Functions page, under Function Parameters:
 "The in storage class is equivalent to const scope."
 That's why the "const in" combination doesn't work.

Why is this working then, and printing 100? import std.stdio: writeln; void foo(const ref int x) { writeln(x * 10); } void main() { int y = 10; foo(y); } Note that the following doesn't compile: void foo(in ref int x) { Bye, bearophile
Apr 28 2009
parent Georg Wrede <georg.wrede iki.fi> writes:
bearophile wrote:
 Paul D. Anderson:
 From the D2.0/Language/Functions page, under Function Parameters:
 "The in storage class is equivalent to const scope."
 That's why the "const in" combination doesn't work.

Why is this working then, and printing 100? import std.stdio: writeln; void foo(const ref int x) { writeln(x * 10); }

You are not changig x here. The x*10 just multiplies and returns its result to writeln.
 void main() {
     int y = 10;
     foo(y);
 }
 
 Note that the following doesn't compile:
 void foo(in ref int x) {
 
 Bye,
 bearophile

Apr 29 2009