Enforced immutability: Difference between revisions

From Rosetta Code
Content added Content deleted
m (→‎{{header|Java}}: Added note about "unmodifiable" Collections)
Line 121: Line 121:


=={{header|Java}}==
=={{header|Java}}==
Primitive types in Java can be made immutable by using the <code>final</code> modifier (works on any primitive type):
Variables in Java can be made immutable by using the <code>final</code> modifier (works on any type, primitive or reference):
<lang java>final int immutableInt = 4;
<lang java>final int immutableInt = 4;
int mutableInt = 4;
int mutableInt = 4;
mutableInt = 6; //this is fine
mutableInt = 6; //this is fine
immutableInt = 6; //this is an error</lang>
immutableInt = 6; //this is an error</lang>
Using final on an object type does not necessarily mean that it can't be changed. It means that the "pointer" cannot be reassigned:
Using final on a reference type means the reference cannot be reassigned, but does not necessarily mean that the object that it points to can't be changed:
<lang java>final String immutableString = "test";
<lang java>final String immutableString = "test";
immutableString = new String("anotherTest"); //this is an error
immutableString = new String("anotherTest"); //this is an error

Revision as of 03:41, 3 January 2011

Enforced immutability is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.

Demonstrate any means your language has to prevent the modification of values, or to create objects that cannot be modified after they have been created.

C

You can create simple constants using the C preprocessor: <lang c>#define PI 3.14159265358979323

  1. define MINSIZE 10
  2. define MAXSIZE 100</lang>

Alternatively, you can modify parameters and variables with the const keyword to make them immutable: <lang c>const char foo = 'a'; const double pi = 3.14159; const double minsize = 10; const double maxsize = 10;

// On pointers int const * ptrToConst; int * const constPtr; int const * const constPtrToConst;

// On parameters int main(const int argc,

        const char** argv)

{

   /* ... */

}</lang>

C++

In C++ you can also use the const keyword on methods to indicate that they can be applied to immutable objects: <lang cpp>class MyClass { private:

   int x;
 

public:

   int getX() const
   {
       return x;
   }

};</lang>

You can also create a class whose instances contain instance-specific const members, by initializing them in the class's constructor. <lang cpp>#include <iostream>

class MyOtherClass { public:

 const int m_x;
 MyOtherClass(const int initX = 0) : m_x(initX) { }

};

int main() {

 MyOtherClass mocA, mocB(7);
 std::cout << mocA.m_x << std::endl; // displays 0, the default value given for MyOtherClass's constructor.
 std::cout << mocB.m_x << std::endl; // displays 7, the value we provided for the constructor for mocB.
 // Uncomment this, and the compile will fail; m_x is a const member.
 // mocB.m_x = 99;
 return 0;

}</lang>

D

<lang d>immutable double pi = 3.1415;</lang> An immutable storage class variable that not explicitly initialized can be initialized by its constructor, otherwise it's value is the default initializer during its life-time. <lang d>import std.random ; immutable uint SEED ; static this() {

   SEED = uniform(0,100) ;

} class SeedTest {

   immutable uint seedNum ;
   this() {
       seedNum = uniform(0,100) ;
   }

}</lang>

E

Whether an object can be modified is entirely up to whether the object provides methods for mutation — objects cannot be affected except by using their methods. It is conventional in E to provide immutable objects when it is natural to do so (e.g. immutable and mutable collections).

Variables are immutable unless declared with the 'var' keyword.

<lang e>def x := 1

x := 2 # this is an error</lang>

Below the surface, each variable name is bound to a Slot object, which can be thought of as a one-element collection. If the var keyword is used, then the slot object is mutable; else, immutable. It is never possible to change the slot a name is bound to.

Any object which is immutable and contains no immutable parts has the property DeepFrozen.

<lang e>var y := 1

def things :DeepFrozen := [&x, 2, 3] # This is OK

def funnyThings :DeepFrozen := [&y, 2, 3] # Error: y's slot is not immutable</lang>

(The unary & operator gets the slot of a variable, and can be thought of almost exactly like C's &.)

Haskell

Since Haskell is purely functional everything is immutable by default. <lang haskell>pi = 3.14159 msg = "Hello World"</lang>

J

In J, all values are immutable, except those contained in memory mapped files (which may optionally set to readonly).

The values associated with a J name can be modified, but that is a modification of the association, and (except for mapped files) the original value remains.

<lang j> B=: A=: 'this is a test'

 A=: '*' 2 3 5 7} A
  A

th** *s*a test

  B

this is a test</lang>

Java

Variables in Java can be made immutable by using the final modifier (works on any type, primitive or reference): <lang java>final int immutableInt = 4; int mutableInt = 4; mutableInt = 6; //this is fine immutableInt = 6; //this is an error</lang> Using final on a reference type means the reference cannot be reassigned, but does not necessarily mean that the object that it points to can't be changed: <lang java>final String immutableString = "test"; immutableString = new String("anotherTest"); //this is an error final StringBuffer immutableBuffer = new StringBuffer(); immutableBuffer.append("a"); //this is fine and it changes the state of the object immutableBuffer = new StringBuffer("a"); //this is an error</lang> Objects can be made immutable (in a sense that is more appropriate for this task) by using final and private together to restrict access to instance variables and to ensure that only one assignment is done: <lang java>public class Immute{

   private final int num;
   private final String word;
   private final StringBuffer buff; //still mutable inside this class, but there is no access outside this class
   public Immute(int num){
       this.num = num;
       word = num + "";
       buff = new StringBuffer("test" + word);
   }
   public int getNum(){
       return num;
   }
   public String getWord(){
       return word; //String objects are immutable so passing the object back directly won't harm anything
   }
   public StringBuffer getBuff(){
       return new StringBuffer(buff);
       //using "return buff" here compromises immutability, but copying the object via the constructor makes it ok
   }
   //no "set" methods are given

}</lang> In the Immute class above, the "buff" variable is still technically mutable, since its internal values can still be changed. The private modifier ensures that no other classes can access that variable. The final modifier ensures that it can't be reassigned. Some trickery needed to be done to ensure that no pointers to the actual mutable objects are passed out. Programmers should be aware of which objects that they use are mutable (usually noted in javadocs).

The Collections class also has methods that will create "unmodifiable" Collections out of existing Collections instances.

JavaScript

You can create constants with the Mozilla-specific extension const. This is not supported by IE and it only works on simple scalars and not on arrays, objects, or parameters. <lang javascript>const pi = 3.1415; const msg = "Hello World";</lang>

Perl

The constant pragma allows you to create subroutines that always return the same value and that cannot be modified: <lang perl>use constant PI => 3.14159; use constant MSG => "Hello World";</lang>

The module Readonly.pm provides a means of enforcing immutablity upon scalars and arrays, however, this imposes a considerable performance penalty:

<lang perl>use Readonly;

Readonly::Scalar my $pi => 3.14159; Readonly::Scalar my $msg => "Hello World";

Readonly::Array my @arr => (1, 2, 3, 4, 5); Readonly::Hash my %hash => (

   "a" => 1,
   "b" => 2,
   "c" => 3

);</lang>

Perl 6

You can create constants in Perl 6 with constant: <lang perl6>constant $pi = 3.14159; constant $msg = "Hello World";

constant @arr = (1, 2, 3, 4, 5);</lang>

Unlike variables, parameters are immutable by default. You can directly specify that you want them to be immutable with the readonly trait:

<lang perl6>sub sum (Num $x is readonly, Num $y is readonly) { $x + $y; }</lang>

PHP

You can create constants using the define function. This only works with scalars. <lang php>define("PI", 3.14159265358); define("MSG", "Hello World");</lang>

PureBasic

PureBasic does not natively use immutable variables, only constants. <lang PureBasic>#i_Const1 = 11

  1. i_Const2 = 3.1415
  2. i_Const3 = "A'm a string"</lang>

However using an OO approach, PureBasic allows for creation of new variable classes such as immutable ones. <lang PureBasic>;Enforced immutability Variable-Class

Interface PBVariable  ; Interface for any value of this type

 Get()         ; Get the current value
 Set(Value.i)  ; Set (if allowed) a new value in this variable 
 ToString.s()  ; Transferee the value to a string.
 Destroy()     ; Destructor

EndInterface

Structure PBV_Structure ; The *VTable structure

 Get.i
 Set.i
 ToString.i
 Destroy.i

EndStructure

Structure PBVar

 *VirtualTable.PBV_Structure
 Value.i 

EndStructure

- Functions for any PBVariable

Procedure immutable_get(*Self.PBVar)

 ProcedureReturn *Self\Value

EndProcedure

Procedure immutable_set(*Self.PBVar, N.i)

 ProcedureReturn #False

EndProcedure

Procedure.s immutable_ToString(*Self.PBVar)

 ProcedureReturn Str(*Self\Value)

EndProcedure

Procedure DestroyImmutabe(*Self.PBVar)

 FreeMemory(*Self)

EndProcedure

- Init an OO-Table

DataSection

 VTable:
 Data.i @immutable_get()
 Data.i @immutable_set()
 Data.i @immutable_ToString()
 Data.i @DestroyImmutabe()

EndDataSection

- Create-Class

Procedure CreateImmutabe(Init.i=0)

 Define *p.PBVar
 *p=AllocateMemory(SizeOf(PBVar))
 *p\VirtualTable = ?VTable
 *p\Value = Init
 ProcedureReturn *p

EndProcedure

- **************
- Test the Code
- Initiate two Immutabe variables
  • v1.PBVariable = CreateImmutabe()
  • v2.PBVariable = CreateImmutabe(24)
- Present therir content

Debug *v1\ToString() ; = 0 Debug *v2\ToString() ; = 24

- Try to change the variables
  • v1\Set(314)  ; Try to change the value, which is not permitted
  • v2\Set(7)
Present the values again

Debug Str(*v1\Get()) ; = 0 Debug Str(*v2\Get()) ; = 24

- And clean up
  • v1\Destroy()
  • v2\Destroy()</lang>

Ruby

You can make things immutable at run-time with Ruby using the built-in freeze method: <lang ruby>msg = "Hello World" msg.freeze</lang>

Scala

<lang scala>val pi = 3.14159 val msg = "Hello World"</lang>

Tcl

Although there is no built-in support for constants, it is trivial to construct on top of Tcl's variable tracing facility: <lang tcl>proc constant {varName {value ""}} {

   upvar 1 $varName var
   # Allow application of immutability to an existing variable, e.g., a procedure argument
   if {[llength [info frame 0]] == 2} {set value $var} else {set var $value}
   trace add variable var write [list apply {{val v1 v2 op} {
       upvar 1 $v1 var
       set var $val; # Restore to what it should be
       return -code error "immutable"
   }} $value]

}</lang> Interactive demonstration: <lang tcl>% constant pi 3.14159 % puts "pi=$pi" pi=3.14159 % set pi 3; # Only in Indiana :-) can't set "pi": immutable % puts "pi is still $pi" pi is still 3.14159</lang>