Enforced immutability: Difference between revisions

From Rosetta Code
Content added Content deleted
No edit summary
Line 193: Line 193:
=={{header|Ela}}==
=={{header|Ela}}==


Normally there is no need to enforce immutability in Ela - everything is immutable by default. Ela doesn't support mutable variables like imperative languages. Most of built-in data structures are immutable as well. The only way to create a mutable data structure is to use a record with a mutable field like so:
Normally there is no need to enforce immutability in Ela - everything is immutable by default. Ela doesn't support mutable variables like imperative languages. All built-in data structures are immutable as well. The only way to create a mutable data structure is to use a Cell module that implements reference cells in Ocaml style:


<lang ela>let rec = {!val=0}</lang>
<lang ela>open Cell
let r = cell 0</lang>


Function mutate can be used to mutate a reference cell:
An operator (!) is used to mark a field as mutable. You can update this field value using assignment operator:


<lang ela>rec.val <- 1</lang>
<lang ela>mutate r 1</lang>

In order to unwrap a value from a cell one can use a valueof function:

<lang ela>valueof r</lang>


=={{header|Euphoria}}==
=={{header|Euphoria}}==

Revision as of 15:43, 28 May 2012

Task
Enforced immutability
You are encouraged to solve this task according to the task description, using any language you may know.

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.

ACL2

All variables in ACL2 are constants, with the exception of those accessed using (assign ...) and accessed using (@ ...)

To declare a global constant, use:

<lang Lisp>(defconst *pi-approx* 22/7)</lang>

Subsequent attempts to redefine the constant give an error:

ACL2 Error in ( DEFCONST *PI* ...):  The name *PI* is in use as a constant.
The redefinition feature is currently off.  See :DOC ld-redefinition-
action.

Ada

Ada provides the constant keyword: <lang Ada>Foo : constant := 42; Foo : constant Blahtype := Blahvalue;</lang>

ALGOL 68

When a name is defined it can be identified as a constant value with an equality, eg pi = 355/113. For a variable an assignment ":=" would be used instead, eg pi := 355/113; <lang ALGOL 68>INT max allowed = 20; REAL pi = 3.1415 9265; # pi is constant that the compiler will enforce # REF REAL var = LOC REAL; # var is a constant pointer to a local REAL address # var := pi # constant pointer var has the REAL value referenced assigned pi #</lang>

AutoHotkey

Works with: AutoHotkey_L

It should be noted that Enforced immutability goes against the nature of AHK. However, it can be achieved using objects: <lang AutoHotkey>MyData := new FinalBox("Immutable data") MsgBox % "MyData.Data = " MyData.Data MyData.Data := "This will fail to set" MsgBox % "MyData.Data = " MyData.Data

Class FinalBox {

  __New(FinalValue) {
     ObjInsert(this, "proxy",{Data:FinalValue})
  }
override the built-in methods
  __Get(k) {
     return, this["proxy",k]
  }
  __Set(p*) {
     return
  }
  Insert(p*) {
     return
  }
  Remove(p*) {
     return
  }

}</lang> You could still use ObjInsert/ObjRemove functions, since they are designed to bypass any custom behaviour implemented by the object. Also, technically you could still use the SetCapacity method to truncate the object, or the GetAddress method to modify the object using memory addresses.

BASIC

Many BASICs support the CONST keyword: <lang qbasic>CONST x = 1</lang>

Some flavors of BASIC support other methods of declaring constants. For example, FreeBASIC supports C-style defines: <lang freebasic>#define x 1</lang>

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 const int * ptrToConst; // The value is constant, but the pointer may change. int const * ptrToConst; // The value is constant, but the pointer may change. (Identical to the above.) int * const constPtr; // The pointer is constant, but the value may change. int const * const constPtrToConst; // Both the pointer and value are constant.

// On parameters int main(const int argc, // note that here, the "const", applied to the integer argument itself,

                           // is kind of pointless, as arguments are passed by value, so 
                           // it does not affect any code outside of the function
        const char** argv)

{

   /* ... */

}</lang>

It is possible to remove the const qualifier of the type a pointer points to through a cast, but doing so will result in undefined behavior.

C++

In addition to the examples shown in C, you can 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>

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>


Clojure

Everything in Clojure except for Java interop are immutable.

<lang Clojure>user> (def d [1 2 3 4 5]) ; immutable vector

  1. 'user/d

user> (assoc d 3 7) [1 2 3 7 5] user> d [1 2 3 4 5]</lang>

D

<lang d>immutable double pi = 3.1415; enum int X = 5; // Compile-time constant</lang> An immutable storage class variable that's not explicitly initialized can be initialized by its constructor, otherwise its value is the default initializer during its life-time. enum allows to define compile-time constants. <lang d>import std.random: uniform;

immutable uint SEED;

static this() {

   SEED = uniform(0, 100);

}

class SeedTest {

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

}</lang>

Delphi

Typed constants can be assigned to using the {$WRITABLECONST ON} or {J+} compiler directives (off by default). <lang Delphi>const

 STR1 = 'abc';         // regular constant
 STR2: string = 'def'; // typed constant</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 &.)

Ela

Normally there is no need to enforce immutability in Ela - everything is immutable by default. Ela doesn't support mutable variables like imperative languages. All built-in data structures are immutable as well. The only way to create a mutable data structure is to use a Cell module that implements reference cells in Ocaml style:

<lang ela>open Cell let r = cell 0</lang>

Function mutate can be used to mutate a reference cell:

<lang ela>mutate r 1</lang>

In order to unwrap a value from a cell one can use a valueof function:

<lang ela>valueof r</lang>

Euphoria

<lang euphoria>constant n = 1 constant s = {1,2,3} constant str = "immutable string"</lang>

Go

Strings in Go are immutable. Attempts to modify them fail to compile: <lang go>package main

func main() {

   s := "immutable"
   s[0] = 'a'

}</lang>

test.go:5: cannot assign to s[0]

Go has const declarations, but they concern compile-time expression evaluation, and not run-time immutability.

Haskell

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

Icon and Unicon

In Icon and Unicon pretty much everything can be changed. There really isn't an easy way to protect a variable from being changed. There are compile time constants created by $define (as shown); although, they can be explicitly undefined. String values themselves are immutable; however, manipulating them creates new string values. The effect is that the value assigned to a variable will change even though the value itself won't. For more see Mutable and Immutable Types.

<lang Icon>$define "1234"</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. Names are not constant unless they are delegated to the operating system (mapped files) and made read-only by the operating system.

Note that J has a rich language for defining numeric constants. For example, 2*pi represented as a floating point number would be 2p1.

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

Whether an object can be modified is entirely up to whether the object provides either methods or non-final public/protected fields for mutation. Objects can be made immutable (in a sense that is more appropriate for this task) by making all fields final or private, and making sure that no methods modify the fields: <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 object pointed to by "buff" is still technically mutable, since its internal values can still be changed. The private modifier ensures that no other classes can access that variable. 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>

Mathematica

<lang Mathematica>Tau = 2*Pi;Protect[Tau] {"Tau"}

Tau = 2 ->Set::wrsym: Symbol Tau is Protected. </lang>


MBS

<lang mbs>CONSTANT INT foo=640;</lang>

Nemerle

Everything is immutable by default. <lang Nemerle>def foo = 42; // immutable by default mutable bar = "O'Malleys"; // mutable because you asked it to be</lang>

OCaml

By default integers, floats, characters, booleans are immutable. Tuples, lists and variants are also immutable as long as they only contain immutable elements. Records are immutable as long as none of its elements are declared with the keyword "mutable" and also as long as none of its fields contain a mutable element (an array or a string for example).

Objects are immutable as long as none of its variables are declared with the keyword "mutable" or is a mutable type (an array or a string for example).

Arrays and strings are mutable.

In order to use immutable strings or immutable arrays, we would create new modules and aliasing the functions for creating and access, but not those for modifying. Here is below an example of this.

File ImString.mli containing the interface:

<lang ocaml>type im_string

val create : int -> im_string val make : int -> char -> im_string val of_string : string -> im_string val to_string : im_string -> string val copy : im_string -> im_string val sub : im_string -> int -> int -> im_string val length : im_string -> int val get : im_string -> int -> char val iter : (char -> unit) -> im_string -> unit val escaped : im_string -> im_string val index : im_string -> char -> int val contains : im_string -> char -> bool val print : im_string -> unit</lang>

File ImString.ml containing the "implementation":

<lang ocaml>type im_string = string

let create = String.create let make = String.make let copy = String.copy let sub = String.sub let length = String.length let get = String.get let iter = String.iter let escaped = String.escaped let index = String.index let contains = String.contains

let of_string s = s let to_string s = s let print = print_string</lang>

Here we can see that in the implementation the new type for immutable strings is defined with type im_string = string, and the definition of this type is hidden in the interface with type im_string.

PARI/GP

GP cannot enforce immutability on its functions or variables. PARI can do so through the usual C methods.

Pascal

See Delphi

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>

Immutability is abstract enough that you can define an infinite constant lazily: <lang perl6>constant fibonacci = 0, 1, *+* ... *;</lang>

Variables are considered mutable by default, but may be marked as readonly after initialization: <lang perl6>my $pi is readonly = 3 + rand; my $pi ::= 3 + rand; # same thing, SSA-ish form</lang> Unlike variables, formal parameters are considered readonly by default even if bound to a mutable container. <lang perl6>sub sum (Num $x, Num $y) { $x += $y; # ERROR }

  1. Explicitly ask for pass-by-reference semantics

sub addto (Num $x is rw, Num $y) {

   $x += $y;  # ok, propagated back to caller

}

  1. Explicitly ask for pass-by-value semantics

sub sum (Num $x is copy, Num $y) {

   $x += $y;  # ok, but NOT propagated back to caller
   $x;

}</lang> A number of built-in types are considered immutable value types, including:

Str         Perl string (finite sequence of Unicode characters)
Bit         Perl single bit (allows traits, aliasing, undefinedness, etc.)
Int         Perl integer (allows Inf/NaN, arbitrary precision, etc.)
Num         Perl number (approximate Real, generally via floating point)
Rat         Perl rational (exact Real, limited denominator)
FatRat      Perl rational (unlimited precision in both parts)
Complex     Perl complex number
Bool        Perl boolean
Exception   Perl exception
Block       Executable objects that have lexical scopes
Seq         A list of values (can be generated lazily)
Range       A pair of Ordered endpoints
Set         Unordered collection of values that allows no duplicates
Bag         Unordered collection of values that allows duplicates
Enum        An immutable Pair
EnumMap     A mapping of Enums with no duplicate keys
Signature   Function parameters (left-hand side of a binding)
Parcel      Arguments in a comma list
LoL         Arguments in a semicolon list
Capture     Function call arguments (right-hand side of a binding)
Blob        An undifferentiated mass of ints, an immutable Buf
Instant     A point on the continuous atomic timeline
Duration    The difference between two Instants
HardRoutine A routine that is committed to not changing

These values, though objects, can't mutate; they may only be "changed" by modifying a mutable container holding one of them to hold a different value instead. (In the abstract, that is. In the interests of efficiency, a string or list implementation would be allowed to cheat as long as it doesn't get caught cheating.) Some of these types have corresponding "unboxed" native representations, where the container itself must carry the type information since the value can't. In this case, it's still the container that might be considered mutable as an lvalue location, not the value stored in that location.

By default, object attributes are not modifiable from outside a class, though this is usually viewed more as encapsulation than as mutability control.

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>

Or:

Works with: PHP version 5.3+

<lang php>const PI = 3.14159265358; const MSG = "Hello World";</lang>

http://us.php.net/manual/en/language.constants.syntax.php

PicoLisp

In PicoLisp it is a central design issue that the programmer is in control of everything, and thus can modify any value. Even program parts written in C or assembly can be changed on the fly. The nearest thing would be to define a function, e.g. <lang PicoLisp>: (de pi () 4) -> pi

(pi)

-> 4</lang> but even this could be modified, e.g.: <lang PicoLisp>: (set (cdr pi) 3) -> 3

(pi)

-> 3</lang>

PowerBASIC

Constants are declared by prefacing the variable name with $ for strings and % for numeric variables: <lang powerbasic>$me = "myname" %age = 35</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>

Python

Some datatypes such as strings are immutable: <lang python>>>> s = "Hello" >>> s[0] = "h"

Traceback (most recent call last):

 File "<pyshell#1>", line 1, in <module>
   s[0] = "h"

TypeError: 'str' object does not support item assignment</lang>

While classes are generally mutable, you can define immutability by overriding __setattr__: <lang python>>>> class Immut(object): def __setattr__(self, *args): raise TypeError( "'Immut' object does not support item assignment")

       __delattr__ = __setattr__
       def __repr__(self):

return str(self.value)

       def __init__(self, value):
               # assign to the un-assignable the hard way.

super(Immut, self).__setattr__("value", value)

>>> im = Immut(123) >>> im 123 >>> im.value = 124

Traceback (most recent call last):

 File "<pyshell#27>", line 1, in <module>
   del a.value
 File "<pyshell#23>", line 4, in __setattr__
   "'Immut' object does not support item assignment")

TypeError: 'Immut' object does not support item assignment >>></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>

Seed7

Seed7 provides const declarations. Constants can have any type: <lang seed7>const integer: foo is 42; const string: bar is "bar"; const blahtype: blah is blahvalue;</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>

UNIX Shell

The Unix shell does not support constants, but variables can be marked as readonly for the same effect.

<lang sh>PIE=APPLE readonly PIE</lang>

XPL0

<lang XPL0>define Pi=3.14; Pi:= 3.15; \causes a compile error: statement starting with a constant </lang>