Upload
clinton-cox
View
16
Download
2
Embed Size (px)
DESCRIPTION
Writing functions in ML. Defining a simple function. MLWorks> fun add (x, y) = x + y; val add : (int * int) -> int = fn Notice what this says: add is a value the type of add is (int * int) -> int the -> denotes a function Therefore, a function is a kind of value! - PowerPoint PPT Presentation
Citation preview
Writing functions in ML
Defining a simple function
• MLWorks> fun add (x, y) = x + y;– val add : (int * int) -> int = fn
• Notice what this says:– add is a value– the type of add is (int * int) -> int – the -> denotes a function– Therefore, a function is a kind of value!– The actual value is abbreviated to fn
Another function definition
• MLWorks> fun double x = 2 * x;– val double : int -> int = fn
• Why don't we need parentheses around the parameter x?
• Every function in ML takes one parameter and returns one result.– The parameter may be a tuple– The result may be a tuple
add again
• MLWorks> fun add (x, y) = x + y;– val add : (int * int) -> int = fn
• MLWorks> add (7, 3);– val it : int = 10
• MLWorks> add(3.0, 5.0);– Gives a type error; why?– ML is strongly typed, but it can deduce types– If expression could be real or int, default is int
Statements in ML
• There are no statements in ML– ML is a purely functional language; it has no
side effects*...but ML does have expressions
• Every expression has a value
* Except for output "statements"--we won't be doing output
The if...then...else expression
• if boolean-expression then expression1 else expression2
• The else part is required (why?)– because the if expression must have a value
• expression1 and expression2 must have the same type– because ML is strongly typed– it needs to know the type of the expression
Using if...then...else
• MLWorks> fun max(x, y) = if x > y then x else y;– val max : (int * int) -> int = fn
• MLWorks> max (7, 5);– val it : int = 7
Integer division, with remainder
• MLWorks> fun divide(x, y) = (x div y, x mod y);– val divide : (int * int) -> (int * int) = fn
• MLWorks> divide (20, 3);– val it : (int * int) = (6, 2)
• We aren't returning two results, just one--but it's a tuple
• Similarly, we're only providing one parameter
Adding vectors
• MLWorks> fun addVec ((x1, y1), (x2, y2)) = ((x1 + x2), (y1 + y2));– val addVec : ((int * int) * (int * int)) -> (int
* int) = fn
• MLWorks> addVec ((3, 5), (10, 20));– val it : (int * int) = (13, 25)
LISP-like operations
• Recall that ML has the following operations:– hd returns the head of a list
– tl returns the tail of a list
– :: adds an element to a list
• These are essentially the same as CAR, CDR, and CONS in LISP
• Can we define CAR, CDR, and CONS in ML?
Redefining LISP
• MLWorks> fun car x = hd x;– val car : 'a list -> 'a = fn
• MLWorks> fun cdr x = tl x;– val cdr : 'a list -> 'a list = fn
• MLWorks> fun cons (x, y) = x :: y;– val cons : ('a * 'a list) -> 'a list = fn
• MLWorks> car (cdr [1,2,3,4]);– val it : int = 2
Testing our LISP functions
• MLWorks> cons([1,2], [3,4]);– Function applied to argument of wrong type
Near: cons (1 :: 2 :: nil, 3 :: 4 :: nil) Required argument type: (int list * int list list) Actual argument type: (int list * int list) Type clash between int and int list
• Elements of list must be same type!• There is no solution (with the ML we know so far)
Trapped in time
• MLWorks> val age = 20;• MLWorks> fun older ( ) = age + 1;• MLWorks> older ( );
– val it : int = 21
• MLWorks> val age = 35;• MLWorks> older ( );
– val it : int = 21
ML adds to state, doesn't change it
• ML has no "assignment"
• val age = 21; associates age with 21• This age is then used in function older• val age = 35; associates a new age with
35• The old age goes out of scope
• ...but older still refers to the old one
Functions are values, too
• MLWorks> fun f x = 2 * x;• MLWorks> fun g x = f (f x);• MLWorks> g 5;
– val it : int = 20
• MLWorks> fun f x = 3 * x;• MLWorks> g 5;
– val it : int = 20
Debugging functions
• You saw that redefining a function does not affect prior uses of that function
• Therefore, you can't change a function by changing something it calls
• Everything should work OK if you compile all your functions from a file every time
• Sometimes you just have to restart ML
It's all in the binding times
• ML's approach seems strange, but you have seen it before
• x = 5;y = 2 * x;x = x + 1;print "y = ", y;
• Would you expect y = 12 to be printed?
• Remember, functions are values too!
The End