Programming C, C++, Java, PHP, Ruby, Turing, VB
Computer Science Canada 
Programming C, C++, Java, PHP, Ruby, Turing, VB  

Username:   Password: 
 RegisterRegister   
 O'Caml Lesson #2
Index -> Programming, General Programming -> Functional Programming
View previous topic Printable versionDownload TopicSubscribe to this topicPrivate MessagesRefresh page View next topic
Author Message
wtd




PostPosted: Tue Mar 14, 2006 11:53 am   Post subject: O'Caml Lesson #2

O'Caml Lesson #2

Understanding functions

Functions are vital to functional programming, as the moniker should immediately suggest. Therefore understanding them is crucial to having some understanding of the language.

What is a function?

A function simply maps one value to another value. A very simple function that maps its argument to double that value would, in fairly standard mathematical notation look like:

code:
f(x) = 2x


In O'Caml we express this as:

code:
let f x = x * 2


The quandry

One of the most important things to realize about functions is that they map a single value to some new value. The quandry here is that we "know" some fucntions take more than one value. Consider the above mentioned multiplication. The multiplication operator (operators are functions too) takes two numbers and returns some other number.

The solution

Functions are values.

A function can easily return some new function. So, let's define multiplication.

code:
let mul a =
   fun b -> a * b


The "mul" function is now a function which takes one argument and returns a new function which only takes one argument. The rules about functions only taking one argument are strictly adhered to.

We can then call this like so:

code:
(mul 4) 3


And get the value 12 in return.

Just as we could give a name to that value:

code:
let c = (mul 4) 3


We can give a name to the function that results from calling "mul 4".

code:
let f = mul 4 in (f 4, f 3)


Gives us:

code:
(16, 12)


Which is exactly what we'd expect.

Is it always so difficult?

Heck no.

O'Caml lets us easily define functions which accept more than one argument.

So, why did I spend so much time talking about functions that only accept one argument? Well, because it's important.

Understanding that functions work that way under the surface makes it much easier to understand the powerful concept of partial function application.

Let's say we have:

code:
let mul a b = a * b


We can still write:

code:
let f = mul 4 in (f 4, f 3)


And get:

code:
(16, 12)


How is this possible?

The "mul" function we're currently working with takes two arguments. But here I've provided it with only the first of those two arguments. By doing this I get a new function which takes the remaining argument and gives me the expected result.

In this case O'Caml has done the hard work for me.

Exercise

In O'Caml, int and float math involve two different sets of operators. The * operator is use for integer multiplication, for instance, and the *. operator is used for float multiplication.

Given a variant data type num_type:

code:
type num_type = Int_number of int | Float_number of float


Rewrite the following function in the form where any given function only takes one argument.

code:
let mul a b =
   match (a, b) with
   | (Int_number i1, Int_number i2) -> Int_number (i1 * i2)
   | (Float_number f1, Float_number f2) -> Float_number (f1 *. f2)
   | _ -> raise (Invalid_argument "Type mismatch")


Extra information

When we defined:

code:
let mul a =
   fun b -> a * b


We called it like so:

code:
(mul 4) 3


However, it is also quite possiblke to call it in the manner any function that takes multiple arguments is called.

code:
mul 4 3


Procedures

Praxtically speaking, we often need functions whose sole purpose is to do some action, rather than calculating some new value. So we make a first try.

code:
let say_hello = print_endline "Hello!"


But this takes no arguments, and thus is a simple binding. The print operatiohn is immediately executed and the result bound to the "say_hello" name.

So we need this to take some kind of value that we really don't care about. The value we use here is "unit", represented by an empty set of parentheses.

code:
let say_hello () = print_endline "Hello!"


We then call this as:

code:
say_hello ()


This bears a passing resemblenace to other programming languages' syntax, where parens are used to surround the argument list, but here serves an entirely different purpose. I highly suggest you treat this as a superficial similarity.

Such functions such as "say_hello", which also returns unit, can be said to map unit to unit. This is a useless mapping, but it keeps such functions consistent with the rest of the language.
Sponsor
Sponsor
Sponsor
sponsor
Display posts from previous:   
   Index -> Programming, General Programming -> Functional Programming
View previous topic Tell A FriendPrintable versionDownload TopicSubscribe to this topicPrivate MessagesRefresh page View next topic

Page 1 of 1  [ 1 Posts ]
Jump to:   


Style:  
Search: