Enforced immutability

From Rosetta Code
Revision as of 12:13, 2 January 2011 by rosettacode>Dkf (whitespace)
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>

D

<lang d>immutable double pi = 3.1415;</lang>

Haskell

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

Java

Primitive types in Java can be made immutable by using the final modifier (works on any primitive type): <lang java>final int immutableInt = 4; int mutableInt = 4; mutableInt = 6; //this is fine 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: <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).

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.PBVariable
 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>