Enforced immutability: Difference between revisions
Content added Content deleted
m (→{{header|J}}) |
Thundergnat (talk | contribs) m (syntax highlighting fixup automation) |
||
Line 8: | Line 8: | ||
Prepend V/var keyword with minus sign to make variable immutable: |
Prepend V/var keyword with minus sign to make variable immutable: |
||
< |
<syntaxhighlight lang="11l">-V min_size = 10</syntaxhighlight> |
||
=={{header|6502 Assembly}}== |
=={{header|6502 Assembly}}== |
||
Line 15: | Line 15: | ||
Side note: Trying to write to ROM at runtime will typically have no effect, but can also interact with memory-mapped ports resulting in undesired operation. (Some NES/Famicom cartridges would access mapper hardware by writing values to ROM) |
Side note: Trying to write to ROM at runtime will typically have no effect, but can also interact with memory-mapped ports resulting in undesired operation. (Some NES/Famicom cartridges would access mapper hardware by writing values to ROM) |
||
< |
<syntaxhighlight lang="6502asm">List: |
||
byte $01,$02,$03,$04,$05</ |
byte $01,$02,$03,$04,$05</syntaxhighlight> |
||
Labeled constants are also immutable, as the assembler replaces them with their equivalent values during the assembly process. The 6502 isn't aware those labels ever existed. |
Labeled constants are also immutable, as the assembler replaces them with their equivalent values during the assembly process. The 6502 isn't aware those labels ever existed. |
||
< |
<syntaxhighlight lang="6502asm">bit_7 equ $80 ;every instance of "bit_7" in your source code is swapped with hexadecimal 80 during assembly</syntaxhighlight> |
||
=={{header|68000 Assembly}}== |
=={{header|68000 Assembly}}== |
||
Most assemblers allow you to define labels which can refer to constant values for clarity. |
Most assemblers allow you to define labels which can refer to constant values for clarity. |
||
< |
<syntaxhighlight lang="68000devpac">bit7 equ %10000000 |
||
bit6 equ %01000000 |
bit6 equ %01000000 |
||
MOVE.B (A0),D0 |
MOVE.B (A0),D0 |
||
AND.B #bit7,D0 |
AND.B #bit7,D0 |
||
;D0.B contains either $00 or $80</ |
;D0.B contains either $00 or $80</syntaxhighlight> |
||
When the program is being assembled, the assembler dereferences the labels and replaces them in-line with the labeled constants. They cannot be altered at runtime (except with self-modifying code). |
When the program is being assembled, the assembler dereferences the labels and replaces them in-line with the labeled constants. They cannot be altered at runtime (except with self-modifying code). |
||
Line 34: | Line 34: | ||
=={{header|8th}}== |
=={{header|8th}}== |
||
Items in 8th are constants if they are declared inside a word (function). Otherwise, they are mutable, unless the "const" word is used: |
Items in 8th are constants if they are declared inside a word (function). Otherwise, they are mutable, unless the "const" word is used: |
||
< |
<syntaxhighlight lang="forth"> |
||
123 const var, one-two-three |
123 const var, one-two-three |
||
</syntaxhighlight> |
|||
</lang> |
|||
That declares that the number 123 is constant and may not be modified (not that the variable named 'one-two-three' is constant) |
That declares that the number 123 is constant and may not be modified (not that the variable named 'one-two-three' is constant) |
||
Line 44: | Line 44: | ||
To declare a global constant, use: |
To declare a global constant, use: |
||
< |
<syntaxhighlight lang="lisp">(defconst *pi-approx* 22/7)</syntaxhighlight> |
||
Subsequent attempts to redefine the constant give an error: |
Subsequent attempts to redefine the constant give an error: |
||
Line 54: | Line 54: | ||
=={{header|Ada}}== |
=={{header|Ada}}== |
||
Ada provides the <code>constant</code> keyword: |
Ada provides the <code>constant</code> keyword: |
||
< |
<syntaxhighlight lang="ada">Foo : constant := 42; |
||
Foo : constant Blahtype := Blahvalue;</ |
Foo : constant Blahtype := Blahvalue;</syntaxhighlight> |
||
Types can be declared as limited: Objects of these types cannot be changed and also not compared nor copied: |
Types can be declared as limited: Objects of these types cannot be changed and also not compared nor copied: |
||
< |
<syntaxhighlight lang="ada">type T is limited private; -- inner structure is hidden |
||
X, Y: T; |
X, Y: T; |
||
B: Boolean; |
B: Boolean; |
||
Line 63: | Line 63: | ||
X := Y; -- illegal (cannot be compiled |
X := Y; -- illegal (cannot be compiled |
||
B := X = Y; -- illegal |
B := X = Y; -- illegal |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|ALGOL 68}}== |
=={{header|ALGOL 68}}== |
||
When a ''name'' is defined it can be identified as a constant value with an equality, eg pi = 355/113. |
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; |
For a variable an assignment ":=" would be used instead, eg pi := 355/113; |
||
< |
<syntaxhighlight lang="algol 68">INT max allowed = 20; |
||
REAL pi = 3.1415 9265; # pi is constant that the compiler will enforce # |
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 # |
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 #</ |
var := pi # constant pointer var has the REAL value referenced assigned pi #</syntaxhighlight> |
||
=={{header|AutoHotkey}}== |
=={{header|AutoHotkey}}== |
||
{{works with|AutoHotkey_L}} |
{{works with|AutoHotkey_L}} |
||
It should be noted that Enforced immutability goes against the nature of AHK. However, it can be achieved using objects: |
It should be noted that Enforced immutability goes against the nature of AHK. However, it can be achieved using objects: |
||
< |
<syntaxhighlight lang="autohotkey">MyData := new FinalBox("Immutable data") |
||
MsgBox % "MyData.Data = " MyData.Data |
MsgBox % "MyData.Data = " MyData.Data |
||
MyData.Data := "This will fail to set" |
MyData.Data := "This will fail to set" |
||
Line 98: | Line 98: | ||
return |
return |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
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. |
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. |
||
=={{header|BASIC}}== |
=={{header|BASIC}}== |
||
Many BASICs support the <code>CONST</code> keyword: |
Many BASICs support the <code>CONST</code> keyword: |
||
< |
<syntaxhighlight lang="qbasic">CONST x = 1</syntaxhighlight> |
||
Some flavors of BASIC support other methods of declaring constants. For example, [[FreeBASIC]] supports C-style defines: |
Some flavors of BASIC support other methods of declaring constants. For example, [[FreeBASIC]] supports C-style defines: |
||
<lang |
<syntaxhighlight lang="freebasic">#define x 1</syntaxhighlight> |
||
=={{header|BBC BASIC}}== |
=={{header|BBC BASIC}}== |
||
BBC BASIC doesn't have named constants. The closest you can get is to use a function: |
BBC BASIC doesn't have named constants. The closest you can get is to use a function: |
||
< |
<syntaxhighlight lang="bbcbasic"> DEF FNconst = 2.71828182845905 |
||
PRINT FNconst |
PRINT FNconst |
||
FNconst = 1.234 : REM Reports 'Syntax error'</ |
FNconst = 1.234 : REM Reports 'Syntax error'</syntaxhighlight> |
||
=={{header|Bracmat}}== |
=={{header|Bracmat}}== |
||
All values (expressions) in Bracmat are immutable, except those that contain <code>=</code> operators. |
All values (expressions) in Bracmat are immutable, except those that contain <code>=</code> operators. |
||
< |
<syntaxhighlight lang="bracmat">myVar=immutable (m=mutable) immutable; |
||
changed:?(myVar.m); |
changed:?(myVar.m); |
||
lst$myVar |
lst$myVar |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}} |
{{out}} |
||
<pre>(myVar= |
<pre>(myVar= |
||
Line 126: | Line 126: | ||
=={{header|C}}== |
=={{header|C}}== |
||
You can create simple constants using the C preprocessor: |
You can create simple constants using the C preprocessor: |
||
< |
<syntaxhighlight lang="c">#define PI 3.14159265358979323 |
||
#define MINSIZE 10 |
#define MINSIZE 10 |
||
#define MAXSIZE 100</ |
#define MAXSIZE 100</syntaxhighlight> |
||
Alternatively, you can modify parameters and variables with the const keyword to make them immutable: |
Alternatively, you can modify parameters and variables with the const keyword to make them immutable: |
||
< |
<syntaxhighlight lang="c">const char foo = 'a'; |
||
const double pi = 3.14159; |
const double pi = 3.14159; |
||
const double minsize = 10; |
const double minsize = 10; |
||
Line 149: | Line 149: | ||
{ |
{ |
||
/* ... */ |
/* ... */ |
||
}</ |
}</syntaxhighlight> |
||
It is possible to remove the <tt>const</tt> qualifier of the type a pointer points to through a cast, but doing so will result in undefined behavior. |
It is possible to remove the <tt>const</tt> qualifier of the type a pointer points to through a cast, but doing so will result in undefined behavior. |
||
Line 155: | Line 155: | ||
=={{header|C sharp|C#}}== |
=={{header|C sharp|C#}}== |
||
Fields can be made read-only (a runtime constant) with the '''readonly''' keyword. |
Fields can be made read-only (a runtime constant) with the '''readonly''' keyword. |
||
< |
<syntaxhighlight lang="csharp">readonly DateTime now = DateTime.Now;</syntaxhighlight> |
||
When used on reference types, it just means the reference cannot be reassigned. It does not make the object itself immutable.<br/> |
When used on reference types, it just means the reference cannot be reassigned. It does not make the object itself immutable.<br/> |
||
Primitive types can be declared as a compile-time constant with the '''const''' keyword. |
Primitive types can be declared as a compile-time constant with the '''const''' keyword. |
||
< |
<syntaxhighlight lang="csharp">const int Max = 100;</syntaxhighlight> |
||
Parameters can be made readonly by preceding them with the '''in''' keyword. Again, when used on reference types, it just means the reference cannot be reassigned. |
Parameters can be made readonly by preceding them with the '''in''' keyword. Again, when used on reference types, it just means the reference cannot be reassigned. |
||
< |
<syntaxhighlight lang="csharp">public void Method(in int x) { |
||
x = 5; //Compile error |
x = 5; //Compile error |
||
}</ |
}</syntaxhighlight> |
||
Local variables of primitive types can be declared as a compile-time constant with the '''const''' keyword. |
Local variables of primitive types can be declared as a compile-time constant with the '''const''' keyword. |
||
< |
<syntaxhighlight lang="csharp">public void Method() { |
||
const double sqrt5 = 2.236; |
const double sqrt5 = 2.236; |
||
... |
... |
||
}</ |
}</syntaxhighlight> |
||
To make a type immutable, the programmer must write it in such a way that mutation is not possible. One important way to this is to use readonly properties. By not providing a setter, the property can only be assigned within the constructor. |
To make a type immutable, the programmer must write it in such a way that mutation is not possible. One important way to this is to use readonly properties. By not providing a setter, the property can only be assigned within the constructor. |
||
< |
<syntaxhighlight lang="csharp">public string Key { get; }</syntaxhighlight> |
||
On value types (which usually should be immutable from a design perspective), immutability can be enforced by applying the '''readonly''' modifier on the type. It will fail to compile if it contains any members that are not read-only. |
On value types (which usually should be immutable from a design perspective), immutability can be enforced by applying the '''readonly''' modifier on the type. It will fail to compile if it contains any members that are not read-only. |
||
< |
<syntaxhighlight lang="csharp">public readonly struct Point |
||
{ |
{ |
||
public Point(int x, int y) => (X, Y) = (x, y); |
public Point(int x, int y) => (X, Y) = (x, y); |
||
Line 180: | Line 180: | ||
public int X { get; } |
public int X { get; } |
||
public int Y { get; } |
public int Y { get; } |
||
}</ |
}</syntaxhighlight> |
||
On a struct that is not made readonly, individual methods or properties can be made readonly by applying the '''readonly''' modifier on that member. |
On a struct that is not made readonly, individual methods or properties can be made readonly by applying the '''readonly''' modifier on that member. |
||
< |
<syntaxhighlight lang="csharp">public struct Vector |
||
{ |
{ |
||
public readonly int Length => 3; |
public readonly int Length => 3; |
||
}</ |
}</syntaxhighlight> |
||
=={{header|C++}}== |
=={{header|C++}}== |
||
In addition to the examples shown in [[#C|C]], you can create a class whose instances contain instance-specific const members, by initializing them in the class's constructor. |
In addition to the examples shown in [[#C|C]], you can create a class whose instances contain instance-specific const members, by initializing them in the class's constructor. |
||
< |
<syntaxhighlight lang="cpp">#include <iostream> |
||
class MyOtherClass |
class MyOtherClass |
||
Line 211: | Line 211: | ||
return 0; |
return 0; |
||
}</ |
}</syntaxhighlight> |
||
You can also use the const keyword on methods to indicate that they can be applied to immutable objects: |
You can also use the const keyword on methods to indicate that they can be applied to immutable objects: |
||
< |
<syntaxhighlight lang="cpp">class MyClass |
||
{ |
{ |
||
private: |
private: |
||
Line 224: | Line 224: | ||
return x; |
return x; |
||
} |
} |
||
};</ |
};</syntaxhighlight> |
||
=={{header|Clojure}}== |
=={{header|Clojure}}== |
||
Everything in Clojure except for Java interop are immutable. |
Everything in Clojure except for Java interop are immutable. |
||
< |
<syntaxhighlight lang="clojure">user> (def d [1 2 3 4 5]) ; immutable vector |
||
#'user/d |
#'user/d |
||
user> (assoc d 3 7) |
user> (assoc d 3 7) |
||
[1 2 3 7 5] |
[1 2 3 7 5] |
||
user> d |
user> d |
||
[1 2 3 4 5]</ |
[1 2 3 4 5]</syntaxhighlight> |
||
=={{header|COBOL}}== |
=={{header|COBOL}}== |
||
Constants in COBOL are not stored in memory, but are closer to C's macros, by associating a literal with a name. |
Constants in COBOL are not stored in memory, but are closer to C's macros, by associating a literal with a name. |
||
Prior to COBOL 2002, you could define figurative literals for characters only: |
Prior to COBOL 2002, you could define figurative literals for characters only: |
||
< |
<syntaxhighlight lang="cobol">ENVIRONMENT DIVISION. |
||
CONFIGURATION SECTION. |
CONFIGURATION SECTION. |
||
SPECIAL-NAMES. |
SPECIAL-NAMES. |
||
SYMBOLIC CHARACTERS NUL IS 0, TAB IS 9.</ |
SYMBOLIC CHARACTERS NUL IS 0, TAB IS 9.</syntaxhighlight> |
||
A new syntax was introduced in COBOL 2002 which allowed defining constants for other types. |
A new syntax was introduced in COBOL 2002 which allowed defining constants for other types. |
||
< |
<syntaxhighlight lang="cobol">01 Foo CONSTANT AS "Foo".</syntaxhighlight> |
||
Prior to COBOL 2002, there were non-standard extensions available that also implemented constants. One extension was the the 78 level-number: |
Prior to COBOL 2002, there were non-standard extensions available that also implemented constants. One extension was the the 78 level-number: |
||
< |
<syntaxhighlight lang="cobol">78 Foo VALUE "Foo".</syntaxhighlight> |
||
Another was the <code>CONSTANT SECTION</code>: |
Another was the <code>CONSTANT SECTION</code>: |
||
< |
<syntaxhighlight lang="cobol">CONSTANT SECTION. |
||
01 Foo VALUE "Foo".</ |
01 Foo VALUE "Foo".</syntaxhighlight> |
||
=={{header|D}}== |
=={{header|D}}== |
||
< |
<syntaxhighlight lang="d">import std.random; |
||
// enum allows to define manifest (compile-time) constants: |
// enum allows to define manifest (compile-time) constants: |
||
Line 320: | Line 320: | ||
// Not allowed, the setter property is missing: |
// Not allowed, the setter property is missing: |
||
// t.x = 10; // Error: not a property t.x |
// t.x = 10; // Error: not a property t.x |
||
}</ |
}</syntaxhighlight> |
||
=={{header|Delphi}}== |
=={{header|Delphi}}== |
||
Typed constants can be assigned to using the {$WRITABLECONST ON} or {J+} compiler directives (off by default). |
Typed constants can be assigned to using the {$WRITABLECONST ON} or {J+} compiler directives (off by default). |
||
< |
<syntaxhighlight lang="delphi">const |
||
STR1 = 'abc'; // regular constant |
STR1 = 'abc'; // regular constant |
||
STR2: string = 'def'; // typed constant</ |
STR2: string = 'def'; // typed constant</syntaxhighlight> |
||
=={{header|Dyalect}}== |
=={{header|Dyalect}}== |
||
Line 333: | Line 333: | ||
Dyalect supports creation of constants using "let" keyword: |
Dyalect supports creation of constants using "let" keyword: |
||
< |
<syntaxhighlight lang="dyalect">let pi = 3.14 |
||
let helloWorld = "Hello, world!"</ |
let helloWorld = "Hello, world!"</syntaxhighlight> |
||
A constant can contain a value of any type: |
A constant can contain a value of any type: |
||
< |
<syntaxhighlight lang="dyalect">let sequence = [1,2,3,4,5]</syntaxhighlight> |
||
=={{header|E}}== |
=={{header|E}}== |
||
Line 346: | Line 346: | ||
Variables are immutable unless declared with the '<code>var</code>' keyword. |
Variables are immutable unless declared with the '<code>var</code>' keyword. |
||
< |
<syntaxhighlight lang="e">def x := 1 |
||
x := 2 # this is an error</ |
x := 2 # this is an error</syntaxhighlight> |
||
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. |
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. |
||
Line 354: | Line 354: | ||
Any object which is immutable and contains no immutable parts has the property DeepFrozen. |
Any object which is immutable and contains no immutable parts has the property DeepFrozen. |
||
< |
<syntaxhighlight lang="e">var y := 1 |
||
def things :DeepFrozen := [&x, 2, 3] # This is OK |
def things :DeepFrozen := [&x, 2, 3] # This is OK |
||
def funnyThings :DeepFrozen := [&y, 2, 3] # Error: y's slot is not immutable</ |
def funnyThings :DeepFrozen := [&y, 2, 3] # Error: y's slot is not immutable</syntaxhighlight> |
||
(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>.) |
||
Line 366: | Line 366: | ||
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 an unsafe module "cell", that implements reference cells in Ocaml style: |
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 an unsafe module "cell", that implements reference cells in Ocaml style: |
||
< |
<syntaxhighlight lang="ela">open unsafe.cell |
||
r = ref 0</ |
r = ref 0</syntaxhighlight> |
||
Function mutate can be used to mutate a reference cell: |
Function mutate can be used to mutate a reference cell: |
||
<lang |
<syntaxhighlight lang="ela">mutate r 1</syntaxhighlight> |
||
In order to unwrap a value from a cell one can use a valueof function: |
In order to unwrap a value from a cell one can use a valueof function: |
||
<lang |
<syntaxhighlight lang="ela">valueof r</syntaxhighlight> |
||
=={{header|Elixir}}== |
=={{header|Elixir}}== |
||
Line 394: | Line 394: | ||
Erlang variables are immutable by nature. The following would be an error: |
Erlang variables are immutable by nature. The following would be an error: |
||
< |
<syntaxhighlight lang="erlang">X = 10, |
||
X = 20.</ |
X = 20.</syntaxhighlight> |
||
However, since = actually performs pattern matching, the following is permissible: |
However, since = actually performs pattern matching, the following is permissible: |
||
< |
<syntaxhighlight lang="erlang">X = 10, |
||
X = 10.</ |
X = 10.</syntaxhighlight> |
||
=={{header|Euphoria}}== |
=={{header|Euphoria}}== |
||
< |
<syntaxhighlight lang="euphoria">constant n = 1 |
||
constant s = {1,2,3} |
constant s = {1,2,3} |
||
constant str = "immutable string"</ |
constant str = "immutable string"</syntaxhighlight> |
||
=={{header|F_Sharp|F#}}== |
=={{header|F_Sharp|F#}}== |
||
As a functional language, everything in F# is immutable by default. Interestingly, <code>const</code> is a reserved word but is non-functional. |
As a functional language, everything in F# is immutable by default. Interestingly, <code>const</code> is a reserved word but is non-functional. |
||
< |
<syntaxhighlight lang="fsharp">let hello = "Hello!"</syntaxhighlight> |
||
=={{header|Factor}}== |
=={{header|Factor}}== |
||
Tuple slots may be declared <code>read-only</code>. For example, the <code>range</code> tuple declares its slots <code>read-only</code>: |
Tuple slots may be declared <code>read-only</code>. For example, the <code>range</code> tuple declares its slots <code>read-only</code>: |
||
< |
<syntaxhighlight lang="factor">TUPLE: range |
||
{ from read-only } { length read-only } { step read-only } ;</ |
{ from read-only } { length read-only } { step read-only } ;</syntaxhighlight> |
||
Note that the <code>CONSTANT:</code> word does nothing to enforce immutability on the object it places on the stack, as it is functionally equivalent to a standard word definition with stack effect <code>( -- obj )</code>. |
Note that the <code>CONSTANT:</code> word does nothing to enforce immutability on the object it places on the stack, as it is functionally equivalent to a standard word definition with stack effect <code>( -- obj )</code>. |
||
Line 419: | Line 419: | ||
=={{header|Forth}}== |
=={{header|Forth}}== |
||
Forth has constant, 2constant and fconstant for creating named constants. This can only be done for global scoped objects, not for function parameters. |
Forth has constant, 2constant and fconstant for creating named constants. This can only be done for global scoped objects, not for function parameters. |
||
<syntaxhighlight lang="forth"> |
|||
<lang Forth> |
|||
256 constant one-hex-dollar |
256 constant one-hex-dollar |
||
s" Hello world" 2constant hello \ "hello" holds the address and length of an anonymous string. |
s" Hello world" 2constant hello \ "hello" holds the address and length of an anonymous string. |
||
355 119 2constant ratio-pi \ 2constant can also define ratios (e.g. pi) |
355 119 2constant ratio-pi \ 2constant can also define ratios (e.g. pi) |
||
3.14159265e fconstant pi |
3.14159265e fconstant pi |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Fortran}}== |
=={{header|Fortran}}== |
||
{{works with|Fortran|90 and later}} |
{{works with|Fortran|90 and later}} |
||
In type declaration statements a PARAMETER attribute can be specified turning the data object into a named constant. |
In type declaration statements a PARAMETER attribute can be specified turning the data object into a named constant. |
||
< |
<syntaxhighlight lang="fortran">real, parameter :: pi = 3.141593</syntaxhighlight> |
||
Dummy arguments of procedures can be given an INTENT attribute. An argument with INTENT(IN) cannot be changed by the procedure |
Dummy arguments of procedures can be given an INTENT attribute. An argument with INTENT(IN) cannot be changed by the procedure |
||
< |
<syntaxhighlight lang="fortran">subroutine sub1(n) |
||
real, intent(in) :: n</ |
real, intent(in) :: n</syntaxhighlight> |
||
=={{header|FreeBASIC}}== |
=={{header|FreeBASIC}}== |
||
< |
<syntaxhighlight lang="freebasic">#define IMMUT1 32767 'constants can be created in the preprocessor |
||
dim as const uinteger IMMUT2 = 2222 'or explicitly declared as constants |
dim as const uinteger IMMUT2 = 2222 'or explicitly declared as constants |
||
</syntaxhighlight> |
|||
</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: |
||
< |
<syntaxhighlight lang="go">package main |
||
func main() { |
func main() { |
||
s := "immutable" |
s := "immutable" |
||
s[0] = 'a' |
s[0] = 'a' |
||
}</ |
}</syntaxhighlight> |
||
<pre> |
<pre> |
||
test.go:5: cannot assign to s[0] |
test.go:5: cannot assign to s[0] |
||
Line 454: | Line 454: | ||
=={{header|Haskell}}== |
=={{header|Haskell}}== |
||
Since Haskell is purely functional everything is immutable by default. |
Since Haskell is purely functional everything is immutable by default. |
||
< |
<syntaxhighlight lang="haskell">pi = 3.14159 |
||
msg = "Hello World"</ |
msg = "Hello World"</syntaxhighlight> |
||
=={{header|Icon}} and {{header|Unicon}}== |
=={{header|Icon}} and {{header|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 [[Icon%2BUnicon/Intro#Mutable_and_Immutable_Types|Mutable and Immutable Types]]. |
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 [[Icon%2BUnicon/Intro#Mutable_and_Immutable_Types|Mutable and Immutable Types]]. |
||
< |
<syntaxhighlight lang="icon">$define "1234"</syntaxhighlight> |
||
=={{header|J}}== |
=={{header|J}}== |
||
Line 470: | Line 470: | ||
(Tangentially: note that J has a rich language for defining numeric constants. For example, 2*pi represented as a floating point number would be 2p1. These are analogous to names but can never be modified.) |
(Tangentially: note that J has a rich language for defining numeric constants. For example, 2*pi represented as a floating point number would be 2p1. These are analogous to names but can never be modified.) |
||
< |
<syntaxhighlight lang="j"> B=: A=: 'this is a test' |
||
A=: '*' 2 3 5 7} A |
A=: '*' 2 3 5 7} A |
||
A |
A |
||
th** *s*a test |
th** *s*a test |
||
B |
B |
||
this is a test</ |
this is a test</syntaxhighlight> |
||
Names can also be made constant (that is, have their referent fixed), so that name, value, and association between name and value are immutable:< |
Names can also be made constant (that is, have their referent fixed), so that name, value, and association between name and value are immutable:<syntaxhighlight lang="j"> require'jmf' |
||
C=: 'this is a test' |
C=: 'this is a test' |
||
1 readonly_jmf_ 'C' |
1 readonly_jmf_ 'C' |
||
Line 485: | Line 485: | ||
| C =:'some new value' |
| C =:'some new value' |
||
C |
C |
||
this is a test</ |
this is a test</syntaxhighlight> |
||
=={{header|Java}}== |
=={{header|Java}}== |
||
Variables in Java can be made immutable by using the <code>final</code> modifier (works on any type, primitive or reference): |
Variables in Java can be made immutable by using the <code>final</code> modifier (works on any type, primitive or reference): |
||
< |
<syntaxhighlight 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</ |
immutableInt = 6; //this is an error</syntaxhighlight> |
||
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: |
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: |
||
< |
<syntaxhighlight lang="java">final String immutableString = "test"; |
||
immutableString = new String("anotherTest"); //this is an error |
immutableString = new String("anotherTest"); //this is an error |
||
final StringBuffer immutableBuffer = new StringBuffer(); |
final StringBuffer immutableBuffer = new StringBuffer(); |
||
immutableBuffer.append("a"); //this is fine and it changes the state of the object |
immutableBuffer.append("a"); //this is fine and it changes the state of the object |
||
immutableBuffer = new StringBuffer("a"); //this is an error</ |
immutableBuffer = new StringBuffer("a"); //this is an error</syntaxhighlight> |
||
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 <code>final</code> or <code>private</code>, and making sure that no methods modify the fields: |
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 <code>final</code> or <code>private</code>, and making sure that no methods modify the fields: |
||
< |
<syntaxhighlight lang="java">public class Immute{ |
||
private final int num; |
private final int num; |
||
private final String word; |
private final String word; |
||
Line 527: | Line 527: | ||
} |
} |
||
//no "set" methods are given |
//no "set" methods are given |
||
}</ |
}</syntaxhighlight> |
||
In the <code>Immute</code> class above, the object pointed to by "buff" is still technically mutable, since its internal values can still be changed. The <code>private</code> 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). |
In the <code>Immute</code> class above, the object pointed to by "buff" is still technically mutable, since its internal values can still be changed. The <code>private</code> 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). |
||
Line 536: | Line 536: | ||
'''Update''': const is now a standard part of ES6 JavaScript, and works with all data types, including arrays, objects, and parameters. It is not, however, included in the ES5 standard. |
'''Update''': const is now a standard part of ES6 JavaScript, and works with all data types, including arrays, objects, and parameters. It is not, however, included in the ES5 standard. |
||
< |
<syntaxhighlight lang="javascript">const pi = 3.1415; |
||
const msg = "Hello World";</ |
const msg = "Hello World";</syntaxhighlight> |
||
=={{header|jq}}== |
=={{header|jq}}== |
||
All values in jq are immutable. Sometimes the syntax may make it appear as though a value is being altered, but that is never the case. For example, consider the following pipeline:< |
All values in jq are immutable. Sometimes the syntax may make it appear as though a value is being altered, but that is never the case. For example, consider the following pipeline:<syntaxhighlight lang="jq"> |
||
["a", "b"] as $a | $a[0] = 1 as $b | $a</ |
["a", "b"] as $a | $a[0] = 1 as $b | $a</syntaxhighlight> |
||
Here, the result is ["a", "b"]. |
Here, the result is ["a", "b"]. |
||
Line 548: | Line 548: | ||
{{works with|Julia|0.6}} |
{{works with|Julia|0.6}} |
||
< |
<syntaxhighlight lang="julia">const x = 1 |
||
x = π # ERROR: invalid ridefinition of constant x</ |
x = π # ERROR: invalid ridefinition of constant x</syntaxhighlight> |
||
=={{header|Kotlin}}== |
=={{header|Kotlin}}== |
||
Line 563: | Line 563: | ||
Here are some examples: |
Here are some examples: |
||
< |
<syntaxhighlight lang="scala">// version 1.1.0 |
||
// constant top level property |
// constant top level property |
||
Line 589: | Line 589: | ||
println(mc.myInt) |
println(mc.myInt) |
||
mc.myFunc(0) |
mc.myFunc(0) |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 599: | Line 599: | ||
=={{header|Logtalk}}== |
=={{header|Logtalk}}== |
||
Logtalk supports both static and dynamic objects. Static objects are usually defined in source files. Object predicates are static by default. These objects can be defined locked against runtime modifications. For simplicity, the following example uses a prototype: |
Logtalk supports both static and dynamic objects. Static objects are usually defined in source files. Object predicates are static by default. These objects can be defined locked against runtime modifications. For simplicity, the following example uses a prototype: |
||
< |
<syntaxhighlight lang="logtalk"> |
||
:- object(immutable). |
:- object(immutable). |
||
Line 615: | Line 615: | ||
:- end_object. |
:- end_object. |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Lua}}== |
=={{header|Lua}}== |
||
{{works with|lua|5.4}} |
{{works with|lua|5.4}} |
||
< |
<syntaxhighlight lang="lua">local pi <const> = 3.14159265359</syntaxhighlight> |
||
=={{header|Mathematica}} / {{header|Wolfram Language}}== |
=={{header|Mathematica}} / {{header|Wolfram Language}}== |
||
< |
<syntaxhighlight lang="mathematica">Tau = 2*Pi;Protect[Tau] |
||
{"Tau"} |
{"Tau"} |
||
Tau = 2 |
Tau = 2 |
||
->Set::wrsym: Symbol Tau is Protected. </ |
->Set::wrsym: Symbol Tau is Protected. </syntaxhighlight> |
||
=={{header|MBS}}== |
=={{header|MBS}}== |
||
< |
<syntaxhighlight lang="mbs">CONSTANT INT foo=640;</syntaxhighlight> |
||
=={{header|Nemerle}}== |
=={{header|Nemerle}}== |
||
Everything is immutable by default. |
Everything is immutable by default. |
||
< |
<syntaxhighlight lang="nemerle">def foo = 42; // immutable by default |
||
mutable bar = "O'Malleys"; // mutable because you asked it to be</ |
mutable bar = "O'Malleys"; // mutable because you asked it to be</syntaxhighlight> |
||
=={{header|Nim}}== |
=={{header|Nim}}== |
||
< |
<syntaxhighlight lang="nim">var x = "mutablefoo" # Mutable variable |
||
let y = "immutablefoo" # Immutable variable, at runtime |
let y = "immutablefoo" # Immutable variable, at runtime |
||
const z = "constantfoo" # Immutable constant, at compile time |
const z = "constantfoo" # Immutable constant, at compile time |
||
Line 644: | Line 644: | ||
x[0] = 'M' |
x[0] = 'M' |
||
y[0] = 'I' # Compile error: 'y[0]' cannot be assigned to |
y[0] = 'I' # Compile error: 'y[0]' cannot be assigned to |
||
z[0] = 'C' # Compile error: 'z[0]' cannot be assigned to</ |
z[0] = 'C' # Compile error: 'z[0]' cannot be assigned to</syntaxhighlight> |
||
=={{header|OCaml}}== |
=={{header|OCaml}}== |
||
Line 660: | Line 660: | ||
File <code>ImString.mli</code> containing the interface: |
File <code>ImString.mli</code> containing the interface: |
||
< |
<syntaxhighlight lang="ocaml">type im_string |
||
val create : int -> im_string |
val create : int -> im_string |
||
Line 674: | Line 674: | ||
val index : im_string -> char -> int |
val index : im_string -> char -> int |
||
val contains : im_string -> char -> bool |
val contains : im_string -> char -> bool |
||
val print : im_string -> unit</ |
val print : im_string -> unit</syntaxhighlight> |
||
File <code>ImString.ml</code> containing the "implementation": |
File <code>ImString.ml</code> containing the "implementation": |
||
< |
<syntaxhighlight lang="ocaml">type im_string = string |
||
let create = String.create |
let create = String.create |
||
Line 693: | Line 693: | ||
let of_string s = s |
let of_string s = s |
||
let to_string s = s |
let to_string s = s |
||
let print = print_string</ |
let print = print_string</syntaxhighlight> |
||
Here we can see that in the implementation the new type for immutable strings is defined with <code>type im_string = string</code>, and the definition of this type is hidden in the interface with <code>type im_string</code>. |
Here we can see that in the implementation the new type for immutable strings is defined with <code>type im_string = string</code>, and the definition of this type is hidden in the interface with <code>type im_string</code>. |
||
Line 717: | Line 717: | ||
All these rules are checked at runtime and exceptions are raised if a piece of code breaks those immutability rules. |
All these rules are checked at runtime and exceptions are raised if a piece of code breaks those immutability rules. |
||
< |
<syntaxhighlight lang="oforth">Object Class new: MyClass(a, b) |
||
MyClass method: setA(value) value := a ; |
MyClass method: setA(value) value := a ; |
||
Line 728: | Line 728: | ||
MyClass new(ListBuffer new, 12) // KO : Not an immutable value. |
MyClass new(ListBuffer new, 12) // KO : Not an immutable value. |
||
ListBuffer new Constant new: T // KO : A constant cannot be mutable. |
ListBuffer new Constant new: T // KO : A constant cannot be mutable. |
||
Channel new send(ListBuffer new) // KO : A mutable object can't be sent into a channel.</ |
Channel new send(ListBuffer new) // KO : A mutable object can't be sent into a channel.</syntaxhighlight> |
||
=={{header|PARI/GP}}== |
=={{header|PARI/GP}}== |
||
Line 738: | Line 738: | ||
=={{header|Perl}}== |
=={{header|Perl}}== |
||
The constant pragma allows you to create subroutines that always return the same value and that cannot be modified: |
The constant pragma allows you to create subroutines that always return the same value and that cannot be modified: |
||
< |
<syntaxhighlight lang="perl">use constant PI => 3.14159; |
||
use constant MSG => "Hello World";</ |
use constant MSG => "Hello World";</syntaxhighlight> |
||
The module Readonly.pm provides a means of enforcing immutablity upon scalars and arrays, however, this imposes a considerable performance penalty: |
The module Readonly.pm provides a means of enforcing immutablity upon scalars and arrays, however, this imposes a considerable performance penalty: |
||
< |
<syntaxhighlight lang="perl">use Readonly; |
||
Readonly::Scalar my $pi => 3.14159; |
Readonly::Scalar my $pi => 3.14159; |
||
Line 753: | Line 753: | ||
"b" => 2, |
"b" => 2, |
||
"c" => 3 |
"c" => 3 |
||
);</ |
);</syntaxhighlight> |
||
=={{header|Phix}}== |
=={{header|Phix}}== |
||
<!--< |
<!--<syntaxhighlight lang="phix">(phixonline)--> |
||
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span> |
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span> |
||
<span style="color: #008080;">constant</span> <span style="color: #000000;">n</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span> |
<span style="color: #008080;">constant</span> <span style="color: #000000;">n</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span> |
||
<span style="color: #008080;">constant</span> <span style="color: #000000;">s</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">3</span><span style="color: #0000FF;">}</span> |
<span style="color: #008080;">constant</span> <span style="color: #000000;">s</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">3</span><span style="color: #0000FF;">}</span> |
||
<span style="color: #008080;">constant</span> <span style="color: #000000;">str</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"immutable string"</span> |
<span style="color: #008080;">constant</span> <span style="color: #000000;">str</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"immutable string"</span> |
||
<!--</ |
<!--</syntaxhighlight>--> |
||
You can also optionally enforce one-off initial typechecks. In the following the compiler may infer the types and optimise away the typecheck, however for more complex initialisations this may lead to performance improvements later on, assuming eg a fatal `typecheck error, n is "no such directory"` is acceptable/wanted. |
You can also optionally enforce one-off initial typechecks. In the following the compiler may infer the types and optimise away the typecheck, however for more complex initialisations this may lead to performance improvements later on, assuming eg a fatal `typecheck error, n is "no such directory"` is acceptable/wanted. |
||
<!--< |
<!--<syntaxhighlight lang="phix">(phixonline)--> |
||
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span> |
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span> |
||
<span style="color: #008080;">constant</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">n</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span> |
<span style="color: #008080;">constant</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">n</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span> |
||
<span style="color: #008080;">constant</span> <span style="color: #004080;">sequence</span> <span style="color: #000000;">s</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">3</span><span style="color: #0000FF;">}</span> |
<span style="color: #008080;">constant</span> <span style="color: #004080;">sequence</span> <span style="color: #000000;">s</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">3</span><span style="color: #0000FF;">}</span> |
||
<span style="color: #008080;">constant</span> <span style="color: #004080;">string</span> <span style="color: #000000;">str</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"immutable string"</span> |
<span style="color: #008080;">constant</span> <span style="color: #004080;">string</span> <span style="color: #000000;">str</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"immutable string"</span> |
||
<!--</ |
<!--</syntaxhighlight>--> |
||
=={{header|PHP}}== |
=={{header|PHP}}== |
||
You can create constants using the define function. This only works with scalars. |
You can create constants using the define function. This only works with scalars. |
||
< |
<syntaxhighlight lang="php">define("PI", 3.14159265358); |
||
define("MSG", "Hello World");</ |
define("MSG", "Hello World");</syntaxhighlight> |
||
Or: {{works with|PHP|5.3+}} |
Or: {{works with|PHP|5.3+}} |
||
< |
<syntaxhighlight lang="php">const PI = 3.14159265358; |
||
const MSG = "Hello World";</ |
const MSG = "Hello World";</syntaxhighlight> |
||
http://us.php.net/manual/en/language.constants.syntax.php |
http://us.php.net/manual/en/language.constants.syntax.php |
||
Line 784: | Line 784: | ||
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. |
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. |
The nearest thing would be to define a function, e.g. |
||
< |
<syntaxhighlight lang="picolisp">: (de pi () 4) |
||
-> pi |
-> pi |
||
: (pi) |
: (pi) |
||
-> 4</ |
-> 4</syntaxhighlight> |
||
but even this could be modified, e.g.: |
but even this could be modified, e.g.: |
||
< |
<syntaxhighlight lang="picolisp">: (set (cdr pi) 3) |
||
-> 3 |
-> 3 |
||
: (pi) |
: (pi) |
||
-> 3</ |
-> 3</syntaxhighlight> |
||
=={{header|PL/I}}== |
=={{header|PL/I}}== |
||
PL/I supports Named Constants. This avoids the default data attributes used when writing ''simple'' constants (such as 3). |
PL/I supports Named Constants. This avoids the default data attributes used when writing ''simple'' constants (such as 3). |
||
< |
<syntaxhighlight lang="pli">*process source attributes xref; |
||
constants: Proc Options(main); |
constants: Proc Options(main); |
||
Dcl three Bin Fixed(15) Value(3); |
Dcl three Bin Fixed(15) Value(3); |
||
Put Skip List(1/three); |
Put Skip List(1/three); |
||
Put Skip List(1/3); |
Put Skip List(1/3); |
||
End;</ |
End;</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> 0.33333332 |
<pre> 0.33333332 |
||
Line 810: | Line 810: | ||
=={{header|PowerBASIC}}== |
=={{header|PowerBASIC}}== |
||
Constants are declared by prefacing the variable name with <code>$</code> for strings and <code>%</code> for numeric variables: |
Constants are declared by prefacing the variable name with <code>$</code> for strings and <code>%</code> for numeric variables: |
||
< |
<syntaxhighlight lang="powerbasic">$me = "myname" |
||
%age = 35</ |
%age = 35</syntaxhighlight> |
||
=={{header|PureBasic}}== |
=={{header|PureBasic}}== |
||
PureBasic does not natively use immutable variables, only constants. |
PureBasic does not natively use immutable variables, only constants. |
||
< |
<syntaxhighlight lang="purebasic">#i_Const1 = 11 |
||
#i_Const2 = 3.1415 |
#i_Const2 = 3.1415 |
||
#i_Const3 = "A'm a string"</ |
#i_Const3 = "A'm a string"</syntaxhighlight> |
||
However using an OO approach, PureBasic allows for creation of new variable classes such as immutable ones. |
However using an OO approach, PureBasic allows for creation of new variable classes such as immutable ones. |
||
< |
<syntaxhighlight lang="purebasic">;Enforced immutability Variable-Class |
||
Interface PBVariable ; Interface for any value of this type |
Interface PBVariable ; Interface for any value of this type |
||
Line 897: | Line 897: | ||
;- And clean up |
;- And clean up |
||
*v1\Destroy() |
*v1\Destroy() |
||
*v2\Destroy()</ |
*v2\Destroy()</syntaxhighlight> |
||
=={{header|Python}}== |
=={{header|Python}}== |
||
Some datatypes such as strings are immutable: |
Some datatypes such as strings are immutable: |
||
< |
<syntaxhighlight lang="python">>>> s = "Hello" |
||
>>> s[0] = "h" |
>>> s[0] = "h" |
||
Line 907: | Line 907: | ||
File "<pyshell#1>", line 1, in <module> |
File "<pyshell#1>", line 1, in <module> |
||
s[0] = "h" |
s[0] = "h" |
||
TypeError: 'str' object does not support item assignment</ |
TypeError: 'str' object does not support item assignment</syntaxhighlight> |
||
While classes are generally mutable, you can define immutability by overriding __setattr__: |
While classes are generally mutable, you can define immutability by overriding __setattr__: |
||
< |
<syntaxhighlight lang="python">>>> class Immut(object): |
||
def __setattr__(self, *args): |
def __setattr__(self, *args): |
||
raise TypeError( |
raise TypeError( |
||
Line 935: | Line 935: | ||
"'Immut' object does not support item assignment") |
"'Immut' object does not support item assignment") |
||
TypeError: 'Immut' object does not support item assignment |
TypeError: 'Immut' object does not support item assignment |
||
>>></ |
>>></syntaxhighlight> |
||
=={{header|Racket}}== |
=={{header|Racket}}== |
||
Line 946: | Line 946: | ||
In addition, new type definitions using <tt>struct</tt> are immutable by default: |
In addition, new type definitions using <tt>struct</tt> are immutable by default: |
||
< |
<syntaxhighlight lang="racket">(struct coordinate (x y)) ; immutable struct</syntaxhighlight> |
||
mutable struct definitions need to explicitly use a <tt>#:mutable</tt>, keyword next to a field to specify it as mutable, or as an option to the whole struct to make all fields mutable. |
mutable struct definitions need to explicitly use a <tt>#:mutable</tt>, keyword next to a field to specify it as mutable, or as an option to the whole struct to make all fields mutable. |
||
Line 952: | Line 952: | ||
(formerly Perl 6) |
(formerly Perl 6) |
||
You can create constants in Raku with <code>constant</code>: |
You can create constants in Raku with <code>constant</code>: |
||
<lang |
<syntaxhighlight lang="raku" line>constant $pi = 3.14159; |
||
constant $msg = "Hello World"; |
constant $msg = "Hello World"; |
||
constant @arr = (1, 2, 3, 4, 5);</ |
constant @arr = (1, 2, 3, 4, 5);</syntaxhighlight> |
||
Immutability is abstract enough that you can define an infinite constant lazily: |
Immutability is abstract enough that you can define an infinite constant lazily: |
||
<lang |
<syntaxhighlight lang="raku" line>constant fibonacci = 0, 1, *+* ... *;</syntaxhighlight> |
||
Variables are considered mutable by default, but may be marked as readonly after initialization: |
Variables are considered mutable by default, but may be marked as readonly after initialization: |
||
<lang |
<syntaxhighlight lang="raku" line>my $pi := 3 + rand;</syntaxhighlight> |
||
Unlike variables, formal parameters are considered readonly by default even if bound to a mutable container. |
Unlike variables, formal parameters are considered readonly by default even if bound to a mutable container. |
||
<lang |
<syntaxhighlight lang="raku" line>sub sum (Num $x, Num $y) { |
||
$x += $y; # ERROR |
$x += $y; # ERROR |
||
} |
} |
||
Line 976: | Line 976: | ||
$x += $y; # ok, but NOT propagated back to caller |
$x += $y; # ok, but NOT propagated back to caller |
||
$x; |
$x; |
||
}</ |
}</syntaxhighlight> |
||
A number of built-in types are considered immutable value types, including: |
A number of built-in types are considered immutable value types, including: |
||
<pre>Str String (finite sequence of Unicode characters) |
<pre>Str String (finite sequence of Unicode characters) |
||
Line 1,005: | Line 1,005: | ||
=={{header|REXX}}== |
=={{header|REXX}}== |
||
Programming note: The REXX language doesn't have immutable variables as such, but the method can be emulated with a simple subroutine. Immutable variables are set via a REXX subroutine which makes a shadow copy of the variable. Later, the same subroutine can be invoked (mutiple times if wanted) to check if any immutable variables have been altered (compromised). Three REXX variables are preempted: '''immutable.''', '''_''', and '''__''' (the last two are just used for temporary variables and any unused variable names can be used). |
Programming note: The REXX language doesn't have immutable variables as such, but the method can be emulated with a simple subroutine. Immutable variables are set via a REXX subroutine which makes a shadow copy of the variable. Later, the same subroutine can be invoked (mutiple times if wanted) to check if any immutable variables have been altered (compromised). Three REXX variables are preempted: '''immutable.''', '''_''', and '''__''' (the last two are just used for temporary variables and any unused variable names can be used). |
||
< |
<syntaxhighlight lang="rexx">/*REXX program emulates immutable variables (as a post-computational check). */ |
||
call immutable '$=1' /* ◄─── assigns an immutable variable. */ |
call immutable '$=1' /* ◄─── assigns an immutable variable. */ |
||
call immutable ' pi = 3.14159' /* ◄─── " " " " */ |
call immutable ' pi = 3.14159' /* ◄─── " " " " */ |
||
Line 1,041: | Line 1,041: | ||
return words(immutable.0) /*return number immutables. */ |
return words(immutable.0) /*return number immutables. */ |
||
/*──────────────────────────────────────────────────────────────────────────────────────*/ |
/*──────────────────────────────────────────────────────────────────────────────────────*/ |
||
ser: say; say '***error***' arg(2); say; exit arg(1) /*error msg.*/</ |
ser: say; say '***error***' arg(2); say; exit arg(1) /*error msg.*/</syntaxhighlight> |
||
'''output''' |
'''output''' |
||
<pre> |
<pre> |
||
Line 1,054: | Line 1,054: | ||
=={{header|Ring}}== |
=={{header|Ring}}== |
||
< |
<syntaxhighlight lang="ring"> |
||
# Project : Enforced immutability |
# Project : Enforced immutability |
||
Line 1,060: | Line 1,060: | ||
assert( x = 10) |
assert( x = 10) |
||
assert( x = 100 ) |
assert( x = 100 ) |
||
</syntaxhighlight> |
|||
</lang> |
|||
Output: |
Output: |
||
<pre> |
<pre> |
||
Line 1,068: | Line 1,068: | ||
=={{header|Ruby}}== |
=={{header|Ruby}}== |
||
You can make things immutable at run-time with Ruby using the built-in Object#freeze method: |
You can make things immutable at run-time with Ruby using the built-in Object#freeze method: |
||
< |
<syntaxhighlight lang="ruby">msg = "Hello World" |
||
msg << "!" |
msg << "!" |
||
puts msg #=> Hello World! |
puts msg #=> Hello World! |
||
Line 1,088: | Line 1,088: | ||
puts msg.frozen? #=> false |
puts msg.frozen? #=> false |
||
puts msg2.frozen? #=> true</ |
puts msg2.frozen? #=> true</syntaxhighlight> |
||
Since Ruby version 2.1 freezing strings can give a performance boost. |
Since Ruby version 2.1 freezing strings can give a performance boost. |
||
There is no way to unfreeze a frozen object. |
There is no way to unfreeze a frozen object. |
||
The freeze can not be canceled but the object of approximately the same contents not to freeze up can be gotten if using Object#dup. |
The freeze can not be canceled but the object of approximately the same contents not to freeze up can be gotten if using Object#dup. |
||
< |
<syntaxhighlight lang="ruby"># There are two methods in the copy of the object. |
||
msg = "Hello World!".freeze |
msg = "Hello World!".freeze |
||
msg2 = msg.clone # Copies the frozen and tainted state of obj. |
msg2 = msg.clone # Copies the frozen and tainted state of obj. |
||
Line 1,099: | Line 1,099: | ||
puts msg3 #=> Hello World! |
puts msg3 #=> Hello World! |
||
puts msg2.frozen? #=> true |
puts msg2.frozen? #=> true |
||
puts msg3.frozen? #=> false</ |
puts msg3.frozen? #=> false</syntaxhighlight> |
||
=={{header|Rust}}== |
=={{header|Rust}}== |
||
Line 1,105: | Line 1,105: | ||
Rust <tt>let</tt> bindings are immutable by default. This will raise a compiler error: |
Rust <tt>let</tt> bindings are immutable by default. This will raise a compiler error: |
||
< |
<syntaxhighlight lang="rust">let x = 3; |
||
x += 2;</ |
x += 2;</syntaxhighlight> |
||
You must declare a variable mutable explicitly: |
You must declare a variable mutable explicitly: |
||
< |
<syntaxhighlight lang="rust">let mut x = 3;</syntaxhighlight> |
||
Similarly, references are immutable by default e.g. |
Similarly, references are immutable by default e.g. |
||
< |
<syntaxhighlight lang="rust">let mut x = 4; |
||
let y = &x; |
let y = &x; |
||
*y += 2 // Raises compiler error. Even though x is mutable, y is an immutable reference. |
*y += 2 // Raises compiler error. Even though x is mutable, y is an immutable reference. |
||
Line 1,119: | Line 1,119: | ||
// Note that though y is now a mutable reference, y itself is still immutable e.g. |
// Note that though y is now a mutable reference, y itself is still immutable e.g. |
||
let mut z = 5; |
let mut z = 5; |
||
let y = &mut z; // Raises compiler error because y is already assigned to '&mut x'</ |
let y = &mut z; // Raises compiler error because y is already assigned to '&mut x'</syntaxhighlight> |
||
=={{header|Scala}}== |
=={{header|Scala}}== |
||
< |
<syntaxhighlight lang="scala">val pi = 3.14159 |
||
val msg = "Hello World"</ |
val msg = "Hello World"</syntaxhighlight> |
||
=={{header|Scheme}}== |
=={{header|Scheme}}== |
||
Line 1,134: | Line 1,134: | ||
This R6RS macro can be effortlessly ported to [[Racket]] by replacing <tt>make-variable-transformer</tt> with <tt>make-set!-transformer</tt> and <tt>(raise (syntax-violation ...))</tt> with <tt>(raise-syntax-error ...)</tt>. |
This R6RS macro can be effortlessly ported to [[Racket]] by replacing <tt>make-variable-transformer</tt> with <tt>make-set!-transformer</tt> and <tt>(raise (syntax-violation ...))</tt> with <tt>(raise-syntax-error ...)</tt>. |
||
< |
<syntaxhighlight lang="scheme">(define-syntax define-constant |
||
(syntax-rules () |
(syntax-rules () |
||
((_ id v) |
((_ id v) |
||
Line 1,148: | Line 1,148: | ||
'set! "Cannot redefine constant" stx #'id))) |
'set! "Cannot redefine constant" stx #'id))) |
||
((id . args) #'(_id . args)) |
((id . args) #'(_id . args)) |
||
(id #'_id)))))))))</ |
(id #'_id)))))))))</syntaxhighlight> |
||
Example use case: |
Example use case: |
||
< |
<syntaxhighlight lang="scheme">(define-constant fnord 23) |
||
;; |
;; |
||
fnord |
fnord |
||
Line 1,157: | Line 1,157: | ||
;; => 28 |
;; => 28 |
||
(set! fnord 42) |
(set! fnord 42) |
||
;; => Syntax error: set!: Cannot redefine constant in subform fnord of (set! fnord 42)</ |
;; => Syntax error: set!: Cannot redefine constant in subform fnord of (set! fnord 42)</syntaxhighlight> |
||
It works with procedures as well: |
It works with procedures as well: |
||
< |
<syntaxhighlight lang="scheme">(define-constant square (lambda (n) (* n n))) |
||
;; |
;; |
||
square |
square |
||
Line 1,166: | Line 1,166: | ||
;; => 25 |
;; => 25 |
||
(set! square (lambda (n) (* n n n))) |
(set! square (lambda (n) (* n n n))) |
||
;; => Syntax error: set!: Cannot redefine constant in subform square of (set! square (lambda (n) (* n n n)))</ |
;; => Syntax error: set!: Cannot redefine constant in subform square of (set! square (lambda (n) (* n n n)))</syntaxhighlight> |
||
=={{header|Seed7}}== |
=={{header|Seed7}}== |
||
Seed7 provides <code>const</code> definitons. |
Seed7 provides <code>const</code> definitons. |
||
Constants can have any type: |
Constants can have any type: |
||
< |
<syntaxhighlight lang="seed7">const integer: foo is 42; |
||
const string: bar is "bar"; |
const string: bar is "bar"; |
||
const blahtype: blah is blahvalue;</ |
const blahtype: blah is blahvalue;</syntaxhighlight> |
||
Constants can be initialized with expressions: |
Constants can be initialized with expressions: |
||
< |
<syntaxhighlight lang="seed7">const integer: foobar is 2 * length(bar) * (foo - 35);</syntaxhighlight> |
||
Any function, even user defined functions can be used to initialize a constant: |
Any function, even user defined functions can be used to initialize a constant: |
||
< |
<syntaxhighlight lang="seed7">const func float: deg2rad (in float: degree) is # User defined function |
||
return degree * PI / 180.0; |
return degree * PI / 180.0; |
||
const float: rightAngle is deg2rad(90.0);</ |
const float: rightAngle is deg2rad(90.0);</syntaxhighlight> |
||
The initialisation expression is evaluated at compile-time. |
The initialisation expression is evaluated at compile-time. |
||
It is possible to initialize a constant with data from the file system: |
It is possible to initialize a constant with data from the file system: |
||
< |
<syntaxhighlight lang="seed7">const string: fileData is getf("some_file.txt");</syntaxhighlight> |
||
The compiler can even get initialisation data from the internet: |
The compiler can even get initialisation data from the internet: |
||
< |
<syntaxhighlight lang="seed7">const string: unixDict is getHttp("www.puzzlers.org/pub/wordlists/unixdict.txt");</syntaxhighlight> |
||
Types are also defined as constants (in other languages this is called a ''typedef''): |
Types are also defined as constants (in other languages this is called a ''typedef''): |
||
< |
<syntaxhighlight lang="seed7">const type: blahtype is integer;</syntaxhighlight> |
||
Function definitions (see above for the definition of ''deg2rad'') have also the form of a <code>const</code> definition. |
Function definitions (see above for the definition of ''deg2rad'') have also the form of a <code>const</code> definition. |
||
=={{header|Sidef}}== |
=={{header|Sidef}}== |
||
< |
<syntaxhighlight lang="ruby">define PI = 3.14159; # compile-time defined constant |
||
const MSG = "Hello world!"; # run-time defined constant</ |
const MSG = "Hello world!"; # run-time defined constant</syntaxhighlight> |
||
=={{header|SuperCollider}}== |
=={{header|SuperCollider}}== |
||
< |
<syntaxhighlight lang="supercollider">// you can freeze any object. |
||
b = [1, 2, 3]; |
b = [1, 2, 3]; |
||
b[1] = 100; // returns [1, 100, 3] |
b[1] = 100; // returns [1, 100, 3] |
||
b.freeze; // make b immutable |
b.freeze; // make b immutable |
||
b[1] = 2; // throws an error ("Attempted write to immutable object.")</ |
b[1] = 2; // throws an error ("Attempted write to immutable object.")</syntaxhighlight> |
||
=={{header|Swift}}== |
=={{header|Swift}}== |
||
Swift has a notion of immutable values built into the language. |
Swift has a notion of immutable values built into the language. |
||
< |
<syntaxhighlight lang="swift">let a = 1 |
||
a = 1 // error: a is immutable |
a = 1 // error: a is immutable |
||
var b = 1 |
var b = 1 |
||
b = 1</ |
b = 1</syntaxhighlight> |
||
It also extends this to higher level data structures. For example Swift has a notion of value types vs reference types. |
It also extends this to higher level data structures. For example Swift has a notion of value types vs reference types. |
||
< |
<syntaxhighlight lang="swift">/// Value types are denoted by `struct`s |
||
struct Point { |
struct Point { |
||
var x: Int |
var x: Int |
||
Line 1,231: | Line 1,231: | ||
let pClass = ClassPoint(x: 1, y: 1) |
let pClass = ClassPoint(x: 1, y: 1) |
||
pClass.x = 2 // Fine because reference types can be mutated, as long as you are not replacing the reference</ |
pClass.x = 2 // Fine because reference types can be mutated, as long as you are not replacing the reference</syntaxhighlight> |
||
Value types are always passed by value. This applies to collections in Swift. |
Value types are always passed by value. This applies to collections in Swift. |
||
< |
<syntaxhighlight lang="swift"> |
||
// A common Swift beginner trap |
// A common Swift beginner trap |
||
func addToArray(_ arr: [Int]) { |
func addToArray(_ arr: [Int]) { |
||
Line 1,244: | Line 1,244: | ||
let array = [1] |
let array = [1] |
||
addToArray(array) |
addToArray(array) |
||
print(array) // [1], because value types are pass by copy, array is immutable</ |
print(array) // [1], because value types are pass by copy, array is immutable</syntaxhighlight> |
||
=={{header|Tcl}}== |
=={{header|Tcl}}== |
||
Although there is no built-in support for constants, it is trivial to construct on top of Tcl's variable tracing facility: |
Although there is no built-in support for constants, it is trivial to construct on top of Tcl's variable tracing facility: |
||
< |
<syntaxhighlight lang="tcl">proc constant {varName {value ""}} { |
||
upvar 1 $varName var |
upvar 1 $varName var |
||
# Allow application of immutability to an existing variable, e.g., a procedure argument |
# Allow application of immutability to an existing variable, e.g., a procedure argument |
||
Line 1,257: | Line 1,257: | ||
return -code error "immutable" |
return -code error "immutable" |
||
}} $value] |
}} $value] |
||
}</ |
}</syntaxhighlight> |
||
Interactive demonstration: |
Interactive demonstration: |
||
< |
<syntaxhighlight lang="tcl">% constant pi 3.14159 |
||
% puts "pi=$pi" |
% puts "pi=$pi" |
||
pi=3.14159 |
pi=3.14159 |
||
Line 1,265: | Line 1,265: | ||
can't set "pi": immutable |
can't set "pi": immutable |
||
% puts "pi is still $pi" |
% puts "pi is still $pi" |
||
pi is still 3.14159</ |
pi is still 3.14159</syntaxhighlight> |
||
=={{header|UNIX Shell}}== |
=={{header|UNIX Shell}}== |
||
Line 1,271: | Line 1,271: | ||
{{works with|Bourne Shell}} |
{{works with|Bourne Shell}} |
||
< |
<syntaxhighlight lang="sh">PIE=APPLE |
||
readonly PIE</ |
readonly PIE</syntaxhighlight> |
||
==={{header|C Shell}}=== |
==={{header|C Shell}}=== |
||
< |
<syntaxhighlight lang="csh">set -r PIE = APPLE</syntaxhighlight> |
||
=={{header|XPL0}}== |
=={{header|XPL0}}== |
||
< |
<syntaxhighlight lang="xpl0">define Pi=3.14; |
||
Pi:= 3.15; \causes a compile error: statement starting with a constant |
Pi:= 3.15; \causes a compile error: statement starting with a constant |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Vlang}}== |
=={{header|Vlang}}== |
||
Line 1,294: | Line 1,294: | ||
To change the values of variables, arguments, and struct fields the keyword "mut" is used. |
To change the values of variables, arguments, and struct fields the keyword "mut" is used. |
||
< |
<syntaxhighlight lang="vlang">// To change the value of the variable, after making it mutable with "mut", use "=". |
||
mut age := 20 |
mut age := 20 |
||
Line 1,326: | Line 1,326: | ||
mut s := 'hello' |
mut s := 'hello' |
||
s[0] = m // not allowed</ |
s[0] = m // not allowed</syntaxhighlight> |
||
=={{header|Wren}}== |
=={{header|Wren}}== |
||
Line 1,338: | Line 1,338: | ||
Note though that if fields are reference types (lists, maps, user-defined classes etc.) even a 'getter' method may enable their internal state to be mutated unless you copy them first. |
Note though that if fields are reference types (lists, maps, user-defined classes etc.) even a 'getter' method may enable their internal state to be mutated unless you copy them first. |
||
< |
<syntaxhighlight lang="ecmascript">class A { |
||
construct new(f) { |
construct new(f) { |
||
_f = f // sets field _f to the argument f |
_f = f // sets field _f to the argument f |
||
Line 1,353: | Line 1,353: | ||
System.print(a.f) |
System.print(a.f) |
||
a.f = 8 |
a.f = 8 |
||
System.print(a.f)</ |
System.print(a.f)</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 1,366: | Line 1,366: | ||
Side note: Trying to write to ROM at runtime will simply have no effect, and will not raise any kind of hardware exception or segfault. |
Side note: Trying to write to ROM at runtime will simply have no effect, and will not raise any kind of hardware exception or segfault. |
||
< |
<syntaxhighlight lang="z80">List: |
||
byte 2,3,4,5,6 ;this could be either mutable or immutable, it depends on the hardware.</ |
byte 2,3,4,5,6 ;this could be either mutable or immutable, it depends on the hardware.</syntaxhighlight> |
||
=={{header|zkl}}== |
=={{header|zkl}}== |
||
Mutability is up to each object. Strings, numbers are immutable. Lists can be either. Dictionaries can switch. |
Mutability is up to each object. Strings, numbers are immutable. Lists can be either. Dictionaries can switch. |
||
< |
<syntaxhighlight lang="zkl">List(1,2,3).del(0) //--> L(2,3) |
||
ROList(1,2,3).del(0) //-->SyntaxError : Can't find del, which means you can't call it |
ROList(1,2,3).del(0) //-->SyntaxError : Can't find del, which means you can't call it |
||
d:=Dictionary(); d.add("one",1) |
d:=Dictionary(); d.add("one",1) |
||
D(one:1) |
D(one:1) |
||
d.makeReadOnly(); d.add("2",2) //-->AccessError(This Dictionary is read only)</ |
d.makeReadOnly(); d.add("2",2) //-->AccessError(This Dictionary is read only)</syntaxhighlight> |
||