OCaml Introduction

by "Blag" - Developer Evangelist

Return to Geeky Thursday

What is OCaml?


OCaml is a Multi-Paradigm, Imperative, Functional and Object-Oriented programming language.


OCaml is free and Open Source.


If you have used Haskell or Erlang before...you should be fine with OCaml.


How to install OCaml?


Of course...the best option is to use Linux


apt-get install ocaml


On Mac's shouldn't be that hard either...


brew install ocaml


On Windows...well...I haven't tried it out...Windows's OCaml

Who uses OCaml?


  • Facebook -> Hack, a compiler for a variant of PHP. Flow, Static type checking for JavaScript. Pfff, Set of tools for code analysis, visualizations, and style-preserving source transformation.
  • Bloomberg -> Advanced financial derivatives risk management application.
  • Citrix -> XenServer, a world-class virtualization system.
  • American Museum of Natural History -> Sotware package POY for Phylogenetic inference.
  • Jane Street -> They use OCaml for everything, from research infrastructure to trading systems to operations and accounting systems.

Starting out...


Once OCaml is installed, we can simply call it from the terminal


Package Management


OCaml uses OPAM which is pretty easy to use...


opam list -a --> will list all installed packages


opam install bitcoin --> will install an interface to the official BitCoin API


opam update --> will update the source list


opam upgrade --> will upgrade the installed packages


utop and Core


utop is a better interactive shell for OCaml...

Core is a library that brings more power to OCaml development

opam install core utop




Once utop is up and running...


type open Core.Std


This will save us some time and also will remove the need to specify functions by their classes...

Variables


Like every functional language...variables are immutable...but using "Let" we can assing them new values...

				
let myVar = 5;;

val myVar : int = 5



let myVar = "Hello OCaml";;

val myVar : string = "Hello OCaml"
				

Just keep in mind that this will work only in the interactive shell...

Strings in OCaml are really a list of characters.


So we can easily access each value...


				
let myVar = "Hello OCaml";;

val myVar : string = "Hello OCaml"


myVar.[0];;

- : char = H



myVar.[6];;

- : char = O
				

Variable can change their values after assignment...but that's not a good functional practice


Best thing is to update the value when calling a function...


Its value doesn't really change but it's carried out by the function...


Tuples

Sometimes we need to group values together...for that, we can use Tuples.

Tuples can have any number of values...

				
let myvar = (1,"Blag");;

val myvar : int * string = (1, "Blag")



let myvar = (1,"Blag","SAP");;

val myvar : int * string * string = (1, "Blag", "SAP")
				

We can extract the Tuples values using fst and snd.


				
let myvar = (1,"Blag");;

val myvar : int * string = (1, "Blag")



fst myvar;;

- : int = 1 



snd myvar

"Blag"


- : string = "Blag"
				

When using tuples with more than 2 values...we need to create a function...we'll see that later...

List


Lists are the most common and used variable type in OCaml.


Lists comes with some nice built-in functions...

				
let someNumbers = [1;2;3;4;5];;

val someNumbers : int list = [1; 2; 3; 4; 5]



let someNames = ["Blag","Schmerdy","Rocky"];;

val someNames : string list = ["Blag"; "Schmerdy"; "Rocky"] 
				
				
let someNumbers = [1,2,3,4,5];;

val someNumbers : int list = [1; 2; 3; 4; 5]




List.hd_exn someNumbers;;

- : int = 1



List.hd_exn someNumbers;;

- : int list = [2; 3; 4; 5]



List.last_exn someNumbers;;

- : int = 5


				
				
List.take someNumbers 3;; 

- : int list = [1; 2; 3]



let hello = "Hello";;

val hello : string = "Hello"



hello.[0]

- : char = H



String.sub hello 0 2;;

- : string = "He"
				
				
List.nth_exn [1;2;3;4;5] 0;;

- : int = 1



List.append [1;2;3] [4;5;6]

- : int list = [1; 2; 3; 4; 5; 6]



"Hello " ^ "World!"

- : string = "Hello World!"



1 :: [2;3;4;5]

- : int list = [1; 2; 3; 4; 5]

				

Functions


Function are very important...


Using Pattern Matching we can call the same function and it will perform different actions...


First Application


For our First Application we need to wrote the code on any editor. We need to use the .ml extension


After compilation, an executable will be generated...


On Geany we need to press the button Compile the current file...and then Run or view the current file

On the terminal do corebuild "name_of_file".native

For this example...we don't need to compile it...just call it as an include...


Call your file "triples.ml" (all in lowercase).

				
open Core.Std



let first myTuple = 

	let (x,_,_) = myTuple in

	printf "%d" x



let second myTuple = 

	let (_,x,_) = myTuple in

	printf "%s" x
	


let third myTuple = 

	let (_,_,x) = myTuple in

	printf "%s" x
				

When we run it we're going to see...


Second Application


In this example we're going to use Pattern Matching


Call your file "greetings.hs" (all in lowercase).


Again...there's no need to compile this code...but to include it...

				
open Core.Std



let greet gender name =

	match gender with

		| "male" -> "Good Morning Mr. " ^ name

		| "female" -> "Good Morning Mrs. " ^ name

		| _ -> "Good Morning ??? " ^ name
				

When we run it we're going to see...


List Higher-Order functions


Unlike other Functional languages...OCaml doesn't provide List Comprehensions.


But the same can be achieved by using Higher-Order functions with Lambda functions...


				
List.map (List.range 1 6) (fun x -> x * 10);;

- : int list = [10; 20; 30; 40; 50]



List.filter (List.map (List.range 1 11) (fun x -> x * 10)) 

            (fun x -> if x > 50 then true else false);;

- : int list = [60; 70; 80; 90; 100]



let doubleIt x = x * 2;;

val doubleIt : int -> int = <fun>



List.map [1;2;3;4;5] (doubleIt);;

- : int list = [2; 4; 6; 8; 10]
				

Recursion


Recursion is one of the key points in OCaml...you call a function that calls itself multiple times.


As we can't change the value of a variable, we can pass different values as parameters. This way we can update the variable value without changing the variable value...


Third Application


In this example we're going to create a Fibonacci sequence generator...


Call your file "fibonacci.ml" (all in lowercase).


We will compile this code...


				
open Core.Std



let rec fib num a b = 

	match num with 

	| num when a > 0 && num > 1 -> 
	
	      string_of_int (a + b) ^ " " ^ 
	      
	      fib (num - 1) (a+b) a

	| num when a = 0 -> 
	
	      string_of_int a ^ " " ^ 
	      
	      string_of_int b ^ " " ^ 
	      
	      string_of_int (a + b) ^ " " ^ 
	      
	      fib (num - 1) (a+b) b

	| num -> ""
				
					
let () =

	print_string "Enter a number: "

	let num = read_int() in

	printf "%s" (fib num 0 1)
				

When we run it we're going to see...


Fourth Application


In this example we're going to create an LED Number


Call your file "LED_Numbers.ml" (all in lowercase).


				
open Core.Std



let get_leds number =

let leds = [0, [" _  ";"| | ";"|_| "];

    	    1, ["  ";"| ";"| "];

            2, [" _  ";" _| ";"|_  "];

            3, ["_  ";"_| ";"_| "];

            4, ["    ";"|_| ";"  | "];

            5, [" _  ";"|_  ";" _| "];

            6, [" _  ";"|_  ";"|_| "];

            7, ["_   ";" |  ";" |  "];

            8, [" _  ";"|_| ";"|_| "];

            9, [" _  ";"|_| ";" _| "]] in
				
				
for i = 0 to 2 do
	
    for j = 0 to 
		 
	    String.length(number) - 1 do
		
		let line = List.Assoc.find_exn leds 
			
	           (int_of_string(Char.to_string(
	           
	                          number.[j]))) in
					   
		printf "%s" (List.nth_exn line i)
			
	done;
		
	print_string "\n"
		
done
				
				
let () =

	print_string "Enter a number: "

	let num = read_line() in

	get_leds num
				

When we run it we're going to see...


Fifth Application


In this example we're going to create a Decimals to Romans application


Call your file "DecToRomans.ml" (all in lowercase).


				
open Core.Std



let rec show_romans num ctr =

let romans = [(1000,"M");(900,"CM");(500,"D");

              (90,"XC");(50,"L");(40,"XL");

              (10,"X");(9,"IX");(5,"V");

              (4,"IV");(1,"I")] in

        let roman = List.nth_exn romans ctr in

        if num > fst roman then 
        
        snd roman ^ show_romans (num - fst roman) ctr 

        else if num < fst roman && num > 0 then 
        
        show_romans num (ctr + 1)

        else "" ^ snd roman	        
				
				
let () =
	
	print_string "Enter a number: "
	
	let num = read_int() in
	
	printf "%s\n" (show_romans num 0)
				

When we run it we're going to see...


Sixth Application


In this example we're going to read a file and count how many time a letter appears...


Call your file "countletters.ml" (all in lowercase).


Create a file called "readme.txt" with the following text...


"This is a text file that we're going to read it using OCaml"


				
open Core.Std


		
let rec update_list lst_count lst_file i top = 

	if i < top then

        let file_value = List.nth_exn lst_file i in 

        let value = try List.Assoc.find_exn 
        
        lst_count (file_value) + 1 
        
        with Not_found -> 1 in

        let lst_count = List.Assoc.add 
        
        lst_count (file_value) (value) in

        update_list lst_count lst_file (i+1) top
				
				
   else

        for i = 0 to List.length lst_count - 1 do

            let lst_value = List.nth_exn lst_count i in

            printf "%c-->%d\n" 
            
                   (fst lst_value) (snd lst_value)

        done
        
        
        
let () =
	
	let file = input_line ( open_in "readme.txt") in
	
	let lst_file = String.to_list file in
	
	let lst_count = [] in
	
	update_list lst_count lst_file 0 
	
	            (List.length lst_file - 1)        
				

When we run it we're going to see...


That's it for now...


I hope you had some fun...


Functional languages are very important


because they force you think differently...


and getting the grasp of OCaml is not an easy thing...


Contact Information


Blag --> blag@blagarts.com

@Blag on Twitter

Go back home...