Enforced immutability: Difference between revisions
(Omitting MUMPS) |
No edit summary |
||
Line 127: | Line 127: | ||
(The unary <code>&</code> operator gets the slot of a variable, and can be thought of almost exactly like C's <code>&</code>.) |
(The unary <code>&</code> operator gets the slot of a variable, and can be thought of almost exactly like C's <code>&</code>.) |
||
=={{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: |
|||
<lang ela>let rec = {!val=0}</lang> |
|||
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> |
|||
=={{header|Go}}== |
=={{header|Go}}== |
||
Strings in Go are immutable. Attempts to modify them fail to compile: |
Strings in Go are immutable. Attempts to modify them fail to compile: |
Revision as of 07:40, 2 May 2011
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.
Ada
Ada provides the constant
keyword:
<lang Ada>Foo : constant := 42;
Foo : constant Blahtype := Blahvalue;</lang>
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
- define MINSIZE 10
- 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>
Clojure
Everything in Clojure except for Java interop are immutable.
<lang Clojure>user> (def d [1 2 3 4 5]) ; immutable vector
- '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>
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. 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:
<lang ela>let rec = {!val=0}</lang>
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>
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>
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>
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" Collection
s out of existing Collection
s 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>
Or:
<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
- i_Const2 = 3.1415
- 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>