ok;
true;
99;
'c';
"hello world";
tuple 1 "hello world" end;
tuple let fst = 1 let snd = "hello world" end;
{tuple let fst = 1 let snd = "hello world" end}.snd;
array 1 2 3 end;
99 + 2;
99 + 2 * 3;
{99 + 2} * 3;
99 + {2 * 3};
fun(i :Int) :Int i;
{fun(i :Int) :Int i}(99);
b) The above values are typed:
:Ok; :Bool; :Int; :Char; :String; :Tuple :Int :String end; :Tuple fst :Int snd :String end; :Array(Int); :Fun(i :Int) :Int; :Fun(:Int) :Int;c) Create bindings of identifiers to the values and types above, e.g. 'let i = 99' or 'Let T = Int'
d) Naming and scoping:
let a = 99; a; let b = "hello world"; a + b; let c = a; a + c; let a = 1; (* does the value of c change? *) a + c; let b = 2; (* note binding of b above! *) a + b;e) Block structured scoping:
begin "hello" end;
let a = 10;
begin let a = "hello" end;
a; (* which binding of a is used? *)
let a = begin "hello" end;
a;
let c =
begin
let a = 1
let b = a + a
a
end;
(* what's the value of a and what's the value of c? *)
a; c;
let x =
tuple
let fst = 1
let snd =
tuple
let a = "hello"
let b = fst
end
end;
x.fst;
x.snd;
x.snd.a;
x.a;
x.snd.b;
x.fst.a;
b) Arrays:
let a = array 2001 101 x.fst end;
a[0];
a[1];
a[3];
extent(a); (* size of an array *)
x[0];
extent(x);
let b = array
array 1 2 3 end
array end
array 2002 102 6 end
end;
extent(b);
extent(b[0]);
extent(b[1]);
b[0][1];
b[1];
let c = array 1 'z' end;
let c = array
array 1 2 3 end
array 'x' 'y' 'z' end
end;
let c = array end;
c) Booleans:
let a = true;
let b = not(true);
(* strict and non-strict and/or: *)
a /\ b;
a \/ b;
let x = array 'x' end;
let i = 1;
{i < extent(x)} /\ {x[i] == 'x'};
{i < extent(x)} andif {x[i] == 'x'};
{i <= extent(x)} andif {x[i] == 'x'};
i < extent(x) andif x[i] == 'x';
not(i >= extent(x) orif x[i] != 'x');
(* -- Equality: *)
1 == 1;
true != false;
'x' == 'x';
"xyz" == "xyz";
let a = 'x';
a != 'x';
tuple 1 end == tuple 2 end;
tuple 1 end == tuple 1 end; (* !!! *)
array 1 end == array 1 end;
d) Functions:
fun() 1;
{fun() 1}();
fun() :String 1;
let f() = 1;
f;
f();
(* different syntactical possibilities to define a function: *)
let f() = 1;
let f = fun() 1;
let f() :Int = 1;
let f = fun() :Int 1;
let f :Fun() :Int = fun() 1;
let f() :Int = 'c';
let f :Fun() :Int = fun() 'c';
f()();
(* higher order functions: *)
let f() = fun() 1;
f;
f();
f()();
let f()() = 1;
let id(i :Int) = i;
let add1(i :Int) = i+1;
let g(h(:Int) :Int x :Int) = h(x);
g(id 4);
g(add1 4);
g(id 4 5);
g(id 'z');
(* currying: *)
let add(x :Int)(y :Int) :Int = x + y;
add(1);
add(1)(2);
let add1 = add(1);
add1;
add1(2);
if true then "then" else "else" end;
let a = 99;
if true then let a = 1 else let b = 2 end;
(* what is the value of a? *)
a; b;
if false then "then" end;
if true then 1 else "hello" end;
if 1 then true end;
if 1 == 2 then 1 elsif 1 == {2-1} then 2 else 3 end;
b) Loops:
loop if true then exit end end;
let var a = 1;
loop
a:= a+1
if a == 100 then
exit
end
end;
let x = loop exit end;
x;
for i = 1 upto 10 do
i * i
end;
for i = 10 downto 1 do
i * i
end;
c) Mutable bindings:
let var a = 99; a; let b = a; let var c = a; a:= 100; a; b; c; c:= 200; a; b; c; b:= 300;d) Variable parameters:
let f(var x :Int) = x:= x+1; let var a = 99; f(a); a; let b = 1; f(b); f(let var x = 100);e) Variant tuples:
Let Color =
Tuple
name :String
case redCase
case greenCase with
intensity :Int
end;
let redObject =
tuple_case redCase of Color with
let name = "red color"
end;
let greenObject =
tuple_case greenCase of Color with
"green color"
10
end;
redObject.name;
redObject.intensity;
greenObject.intensity;
redObject?redCase;
redObject?greenCase;
greenObject!greenCase.intensity;
redObject!redCase.intensity;
redObject!greenCase.intensity;
case redObject
when redCase then "red"
when greenCase then "green"
end;
case red
when greenCase then "green"
end;
case redObject
when greenCase then "green"
else "else"
end;
case of redObject
when redCase then "red"
end;
case of redObject
when redCase then "red"
when greenCase then "green"
end;
case of redObject
when redCase then "red"
else "else"
end;
case greenObject
when greenCase with x then
x.intensity
else ~1
end;
f) Exceptions:
let newExc = exception "new Exc" end;
raise newExc end;
try
raise newExc end
"normal"
else
"else"
end;
try
raise newExc end
"normal"
when newExc then
"newExc"
else
"else"
end;
try
raise newExc end
"normal"
when newExc then
"newExc"
reraise
end;
if true then "then" else raise newExc end end;
if false then "then" else raise newExc end end;
let rec fac(n :Int) :Int =
if n == 0 then 0
elsif n == 1 then 1
else n * fac(n-1)
end;
fac(0);
fac(1);
fac(6);
let rec even(x :Int) :Bool =
if x == 0 then true else odd(x-1) end
and odd(x :Int) :Bool =
if x == 0 then false else even(x-1) end;
even(2);
odd(2);
b) Recursive tuples:
let rec lonelyJohn =
tuple
let name = "John"
let bestFriend = lonelyJohn
end;
Let Rec Person <:Ok = Tuple
name :String
bestFriend :Person
end;
let rec lonelyJohn :Person =
tuple
let name = "John"
let bestFriend = lonelyJohn
end;
lonelyJohn.bestFriend.name;
let rec john :Person =
tuple
let name = "John"
let bestFriend = mary
end
and mary :Person =
tuple
let name = "Mary"
let bestFriend = john
end;
john.bestFriend.bestFriend.name;
c) Recursive variant tuples:
Let Rec IntList <:Ok =
Tuple
case nil
case cons with head :Int tail :IntList
end;
let nil = tuple_case nil of IntList end;
let single =
tuple_case cons of IntList with
let head = 100
let tail = nil
end;
single!cons.tail?cons;
let rec ring :IntList =
tuple_case cons of IntList with
let head = 99
let tail = ring
end;
ring!cons.tail?cons;
let name = "John"; do exit; tycoon -restart name; let name = "John"; do saveSystem; let name = "Mary"; do exit; tycoon -restart name;