Variables: Difference between revisions
Content added Content deleted
(added ocaml) |
(Added Oz. (Oops, that was longer than expected.)) |
||
Line 370: | Line 370: | ||
(a + b)</lang> |
(a + b)</lang> |
||
=={{header|Oz}}== |
|||
Variable names in Oz always start with an uppercase letter. |
|||
Oz variables are dataflow variables. A dataflow variable can basically be free (unbound) or determined (has a value). Once a value has been assigned, it can not be changed. If we assign the same value again, nothing happens. If we assign a different value to an already determined variable, an exception is raised: |
|||
<lang oz>declare |
|||
Var %% new variable Var, initially free |
|||
{Show Var} |
|||
Var = 42 %% now Var has the value 42 |
|||
{Show Var} |
|||
Var = 42 %% the same value is assigned again: ok |
|||
Var = 43 %% a different value is assigned: exception</lang> |
|||
In the Emacs-based <em>interactive environment</em>, <code>declare</code> creates a new open scope in which variables can be declared. The variables are visible for the entire rest of the session. |
|||
(Most operations on free variables block until the variables has been bound. <code>Show</code> on the other hand always proceeds.) |
|||
Assignment to dataflow variables is also called unification. It is actually a symmetric operation, e.g. the following binds B to 3: |
|||
<lang oz>declare |
|||
A = 3 |
|||
B |
|||
in |
|||
A = B |
|||
{Show B}</lang> |
|||
However, variables can only be introduced at the left side of the <code>=</code> operator. So this is a syntax error: |
|||
<lang oz>declare |
|||
A = 3 |
|||
A = B %% Error: variable B not introduced |
|||
in |
|||
{Show B}</lang> |
|||
It is possible to introduce multiple variables in a single statement: |
|||
<lang oz>declare |
|||
[A B C D] = [1 2 3 4] %% unification of two lists</lang> |
|||
In a <em>module definition</em>, toplevel variables can be introduced between the keywords <code>define</code> and <code>end</code> without the need for <code>declare</code>. The range between these two keywords is also their scope. Toplevel variables can optionally be exported. |
|||
<lang oz>functor |
|||
export Function |
|||
define |
|||
ToplevelVariable = 42 |
|||
fun {Function} |
|||
42 |
|||
end |
|||
end</lang> |
|||
Function and class definitions introduce a new variable with the name of the function/class and assign the new function/class to this variable. |
|||
Most Oz statement introduce a new scope and it is possible to introduce local variables at the top of this scope with the <code>in</code> keyword. |
|||
<lang oz>fun {Function Arg} |
|||
LocalVar1 |
|||
in |
|||
LocalVar1 = if Arg == 42 then |
|||
LocalVar2 |
|||
in |
|||
LocalVar2 = yes |
|||
LocalVar2 |
|||
else |
|||
LocalVar3 = no %% variables can be initialized when declared |
|||
in |
|||
LocalVar3 |
|||
end |
|||
LocalVar1 |
|||
end</lang> |
|||
Here, <code>LocalVar1</code> is visible in the whole body of <code>Function</code> while <code>LocalVar2</code> is only visible in the <code>then</code> branch and <code>LocalVar3</code> is only visible in the <code>else</code> branch. |
|||
Additionally, new local variables can be introduced everywhere using the keyword <code>local</code>. |
|||
<lang oz>if {IsEven 42} then |
|||
{System.showInfo "Here, LocalVar is not visible."} |
|||
local |
|||
LocalVar = "Here, LocalVar IS visible" |
|||
in |
|||
{System.showInfo LocalVar} |
|||
end |
|||
end</lang> |
|||
New variables are also introduced in pattern matching. |
|||
<lang oz>case "Rosetta code" of First|_ then {Show First} end %% prints "R"</lang> |
|||
<code>_</code> creates a new nameless variable that is initially unbound. It is usually pronounced "don't care". |
|||
It is possible to create a read-only view of a variable with the <code>!!</code> operator. This is called a "future". We can wait for such a variable to become bound by another thread and we can read its value, but we can never set it. |
|||
<lang oz>declare |
|||
A |
|||
B = !!A %% B is a read-only view of A |
|||
in |
|||
thread |
|||
B = 43 %% this blocks until A is known; then it fails because 43 \= 42 |
|||
end |
|||
A = 42</lang> |
|||
Additional operations on variables: |
|||
<lang oz>declare |
|||
V = 42 |
|||
in |
|||
{Wait V} %% explicitly wait for V to become determined |
|||
if {IsDet V} then %% check whether V is determined; not recommended |
|||
{Show determined} |
|||
elseif {IsFree V} then %% check whether V is free; not recommended |
|||
{Show free} |
|||
end</lang> |
|||
<code>IsFree</code> and <code>IsDet</code> are low-level functions. If you use them, you code is no longer declarative and prone to race conditions when used in a multi-threaded context. |
|||
To have mutable references like in imperative languages, use cells: |
|||
<lang oz>declare |
|||
A = {NewCell 42} |
|||
OldVal |
|||
in |
|||
{Show @A} %% read a cell with @ |
|||
A := 43 %% change its value |
|||
OldVal = A := 44 %% read and write at the same time (atomically)</lang> |
|||
<code>A</code> is an immutable dataflow variable that is bound to a mutable reference. |
|||
=={{header|Perl}}== |
=={{header|Perl}}== |