Enforced immutability: Difference between revisions
m (→{{header|PureBasic}}: Clearer pointer type) |
(→Tcl: Added implementation) |
||
Line 225: | Line 225: | ||
<lang scala>val pi = 3.14159 |
<lang scala>val pi = 3.14159 |
||
val msg = "Hello World"</lang> |
val msg = "Hello World"</lang> |
||
=={{header|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> |
Revision as of 12:29, 2 January 2011
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
- 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>
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
- 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>