0% found this document useful (0 votes)
159 views1 page

Numbers Pattern Matching: Sentences Are Actually Expressions and Not

A one page printout with a bunch of info on Standard ML Programming, Used as a cheat sheet allowed during a programming language theory exam.

Uploaded by

skiloh1
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
159 views1 page

Numbers Pattern Matching: Sentences Are Actually Expressions and Not

A one page printout with a bunch of info on Standard ML Programming, Used as a cheat sheet allowed during a programming language theory exam.

Uploaded by

skiloh1
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 1

(*Declarations :*)

val rent = 1200


val negative_number = ~15
fun is_large(x : int) = if x > 37 then true else false
(* Floating-point numbers are called "reals". *)
val tau = 2.0 * pi (* You can multiply two reals *)
val twice_rent = 2 * rent (*two ints*)
(* you can't multiply an int and a real *)
(* +, - and * are overloaded so they work for both int
and real.The same cannot be said for division which has
separate operators: *)
val real_division = 14.0 / 4.0 (* gives 3.5 *)
val int_division = 14 div 4 (* rounds to 3 *)
val int_remainder = 14 mod 4(* gives 2 *)
(* ~ is actually sometimes a function (e.g. when put in
front of variables) *)
val negative_rent = ~(rent)

val lots = [ 5, 5, 5, 6, 4, 5, 6, 5, 4, 5, 7, 3 ]
(* Tuples, on the other hand, can contain a fixed
number of different things *)
val person1 = ("Simon", 28, 3.14159)
(* : string * int * real *)
(* You can even have tuples inside lists and lists inside
tuples *)
val likes = [("Alice", "ice cream"),("Bob", "hot dogs"),
("Bob", "Alice")]
(* : (string * string) list *)
val mixup = [ ("Alice", 39),("Bob", 37),("Eve", 41) ]
(* : (string * int) list *)
val good_bad_stuff =
(["ice cream", "hot dogs", "chocolate"],
["liver", "paying the rent" ])
(* : string list * string list *)

val denom = 2.0 * a


in ((~b + sqr) / denom,
(~b - sqr) / denom) end

(* Pattern matching is a funky part of functional


programming. It is an alternative to if-sentences. The
fibonacci function can be rewritten: *)
fun fibonacci 0 = 0 (* Base case *)
| fibonacci 1 = 1 (* Base case *)
| fibonacci n = fibonacci (n - 1) + fibonacci (n - 2) (*
Recursive case *)
(* Pattern matching is also possible on composite types
like tuples, lists and records. Writing "fun solve2 (a, b,
c) = ..." is in fact a pattern match on the one threetuple solve2 takes as argument. Similarly, but less
intuitively, you can match on a list consisting of
elements in it (from the beginning of the list only). *)
fun first_elem (x::xs) = x
fun second_elem (x::y::xs) = y
(* Records are tuples with named slots *)
(* There are also booleans and boolean operators *)
fun evenly_positioned_elems (odd::even::xs) =
val rgb = { r=0.23, g=0.56, b=0.91 }
val got_milk = true
even::evenly_positioned_elems xs
(* : {b:real, g:real, r:real} *)
val got_bread = false
| evenly_positioned_elems [odd] = []
(* You don't need to declare their slots ahead of time.
val has_breakfast = got_milk andalso got_bread
(* Base case: throw away *)
Records with different slot names are considered
val has_something = got_milk orelse got_bread
| evenly_positioned_elems [] = []
different types, even if their slot value types match up.
val is_sad = not(has_something)(*not is a function *)
(* Base case *)
For instance... *)
(* Many values can be compared using equality
(* When matching on records, you must use their slot
val Hsl = { H=310.3, s=0.51, l=0.23 }
operators: = and <> *)
names,
and you must bind every slot in a record. The
(* : {H:real, l:real, s:real} *)
val pays_same_rent = (rent = 1300)
order of the slots doesn't matter though. *)
val Hsv = { H=310.3, s=0.51, v=0.23 }
(* false *)
fun rgbToTup {r, g, b} = (r, g, b)
(* : {H:real, s:real, v:real} *)
val is_wrong_phone_no = (phone_no <> 5551337)
(* ...trying to evaluate `Hsv = Hsl` or `rgb = Hsl` would (* fn : {b:'a, g:'b, r:'c} -> 'c * 'b * 'a *)
(* false *)
fun mixRgbToTup {g, b, r} = (r, g, b)
give a type error. While they're all three-slot records
(* The operator <> is != *)
(* fn : {b:'a, g:'b, r:'c} -> 'c * 'b * 'a *)
composed only of `real`s, they each have different
(* If called with {r=0.1, g=0.2, b=0.3}, either of the
names for at least some slots. *)
(* Actually, most of the parentheses above are
(* You can use hash notation to get values out of tuples. above functions would return (0.1, 0.2, 0.3). But it
unnecessary. Here are some different ways to say some
would be a type error to call them with {r=0.1, g=0.2,
*)
of the things mentioned above: *)
b=0.3, a=0.4} *)
val H = #H Hsv (* : real *)
fun is_large x = x > 37
(* Higher order functions: Functions can take other
val s = #s Hsl (* : real *)
val is_sad = not has_something
functions as arguments.*)
val pays_same_rent = rent = 1300
val is_large = (fn x => x > 37)
(* Functions! *)
val is_wrong_phone_no = phone_no <> 5551337
val add_them = fn (a,b) => a + b
fun add_them (a, b) = a + b
val negative_rent = ~rent
val thermometer =
(* A simple function that adds two numbers *)
(* Parentheses are necessary when grouping things:*)
fn temp => if temp < 37
val test_it = add_them (3, 4) (* gives 7 *)
val some_answer = is_large (5 + 5)
then "Cold"
(* Larger functions are usually broken into several lines
(* Without parens, this would break! *)
else if temp > 37
for readability *)
(* val some_answer = is_large 5 + 5 *)
then "Warm"
fun thermometer temp =
(* Read as: (is_large 5) + 5. Bad! *)
else "Normal"
if temp < 37
then "Cold"
(* Besides booleans, ints and reals, Standard ML also
(* Write a function cube of type int -> int that
else if temp > 37
has Chars and Strings : *)
returns the cube of its parameter. *)
then "Warm"
val foo = "Hello, World!\n"
fun cube x = x * x * x;
else "Normal"
(* The \n is the escape sequence for linebreaks *)
(* Write a function cuber of type real -> real that
val one_letter = #"a"
returns the cube of its parameter. *)
val test_thermo = thermometer 40 (* gives "Warm" *)
(* That funky syntax is just one character, a *)
fun cuber(x:real):real = x*x*x;
(* if-sentences are actually expressions and not
val combined = "Hello " ^ "there, " ^ "fellow!\n"
(* Write a function forth of type 'a list -> 'a
statements/declarations.A function body can only
(* Concatenate strings *)
that returns the fourth element of a list. Your
contain one expression.There are some tricks for
val _ = print foo
function need not behave well on lists with less
making a function do more than just one thing,
val _ = print combined
than four elements. *)
though.A
function
can
call
itself
as
part
of
its
result
(* print things *)
fun fourth (L) = hd (tl (tl (tl L)));
(
Recursion
!)
*)
(* val _ = print one_letter NOPE ONLY STRINGS *)
(* Write a function min3 of type int * int * int -> int that
fun fibonacci n =
returns the smallest of three integers. *)
if
n
=
0
then
0
else
(*
Base
case
*)
(* SML also has Lists! *)
fun min3 (a, b, c) =
if
n
=
1
then
1
else
(*
Base
case
*)
val bar = [ #"H", #"e", #"l", #"l", #"o" ]
if a < b andalso a < c
fibonacci
(n
1)
+
fibonacci
(n
2)
(* Library functs that take strings as argument. *)
then a
(*
Recursive
case
*)
val bob = String.implode bar (* gives "Hello" *)
else if b<a andalso b<c
(*
A
function
cannot
change
the
variables
it
can
refer
val bob_char_count = String.size bob (* gives 5 *)
then b
to. It can only temporarily shadow them with new
val _ = print (bob ^ "\n")
else c;
variables that have the same names. In this sense,
(* You can have lists of any kind *)
(* Write a function red3 of type 'a * 'b * 'c -> 'a * 'c that
variables are really constants and only behave like
val numbers = [1, 3, 3, 7, 229, 230, 248]
converts a tuple with three elements into one with two
variables when dealing with recursion. For this reason, by eliminating the second element.*)
(* : int list *)
variables
are
also
called
value
bindings.
An
example
of
val names = [ "Fred", "Jane", "Alice" ]
fun red3 (a, b, c) = (a, c);
this: *)
(* : string list *)
(*Write a function thirds of type string -> char that
val
x
=
42
(* Even lists of lists of things *)
returns the third character of a string. Your function
fun
answer(question)
=
val groups = [ [ "Alice", "Bob" ],[ "Huey", "Dewey",
need not behave well on strings with lengths less than
if
question
=
"What
is
the
meaning
of
life,
the
"Louie" ],[ "Bonnie", "Clyde" ] ]
3. *)
universe
and
everything?"
(* : string list list *)
fun thirds (s) = hd (tl (tl (explode s) ) );
then x
val number_count = List.length numbers (* gives 7 *)
(* Write a function cycle1 of type 'a list -> 'a list whose
else raise Fail "I'm an exception. Also, I don't know
(* You can put single values in front of lists of the same
output list is the same as the input list, but with the
what the answer is."
kind using the :: operator, called "the cons operator"
first element of the list moved to the end. For example,
val
x
=
43
(known from Lisp). *)
cycle1 [1, 2, 3, 4] should return [2, 3, 4, 1]. *)
val
hmm
=
answer
"What
is
the
meaning
of
life,
the
val more_numbers = 13 :: numbers
fun cycle1(L) =
universe
and
everything?"
(* gives [13, 1, 3, 3, 7, ...] *)
if null L
(*
Now,
hmm
has
the
value
42.
This
is
because
the
val more_groups = ["Batman","Superman"] :: groups
then L
function
answer
refers
to
the
copy
of
x
that
was
visible
(* Lists of the same kind can be appended using the @
else tl(L) @ [ hd (L) ];
before
its
own
function
definition.
*)
("append") operator *)
(*Square Sum*)
(*
Functions
can
take
several
arguments
by
taking
one
val guest_list = ["Mom", "Dad"]@[ "Aunt", "Uncle"]
fun sqsum (x:int, y:int) =
tuples as argument : *)
(* This could have been done with the "cons" operator.
let sum:int = x+y in
fun solve2 (a : real, b : real, c : real) =
It is tricky because the left-hand-side must be an
sum*sum
((~b + Math.sqrt(b*b-4.0*a*c)) / (2.0*a),
element whereas the right-hand-side must be a list of
end
(~b - Math.sqrt(b*b-4.0*a*c)) / (2.0*a))
those elements. *)
(*Max of three*)
(* Sometimes, the same computation is carried out
val guest_list = "Mom" :: "Dad" :: ["Aunt", "Uncle"]
fun max(a,b,c) =
val guest_list = "Mom" :: ("Dad" :: ("Aunt" :: n("Uncle" :: several times. It makes sensento save and re-use the
if a > b then
result the first time. We can use
[])))
if a > c then a
(* If you have many lists of the same kind, you can
else c
"let-bindings ": *)
concatenate them all *)
else
fun solve2 (a : real, b : real, c : real) =
val everyone = List.concat groups
if b < c then c
let val discr = b * b - 4.0*a*c
(* [ "Alice", "Bob", "Huey", ... ] *)
else b;
val sqr = Math.sqrt discr
(* A list can have any number of same type values*)

You might also like