Created
May 4, 2016 17:42
-
-
Save vik-y/ed62065c9d15717686043116f5897d97 to your computer and use it in GitHub Desktop.
Ocaml Basics
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(* | |
* This document contains code written to learn Ocaml before the | |
* Ocaml quiz. | |
* Let's do this in a hope to learn Ocaml properly. | |
* Author: Vikas Yadav | |
* Email: [email protected] | |
*) | |
(* Definition of Union/Record Types *) | |
type number = Integer of int | Rational of int * int ;; | |
(* Record can also be defined as following *) | |
type student = { name: string; age: int};; | |
(* Here initialization of number and student will be different *) | |
(* | |
Integer(5);; // Number type | |
let vikas = {name="vikas"; age="20";};; // Different kind of record | |
definitions | |
*) | |
let a = Rational(5,2);; | |
let b = Integer(10);; | |
(* Output of both a and b should be number *) | |
let add n1 n2 = | |
match(n1, n2) with | |
Integer(i1), Integer(i2)-> Integer(i1+i2) | |
| Rational(m1, d1), Rational(m2,d2) -> Rational(m1*d2 + m2*d1, d1*d2) | |
| Rational(m1, d1), Integer i -> Rational(m1 + i*d1, d1) | |
| Integer i, Rational(m1, d1) -> Rational(m1 + i*d1, d1) | |
(* Adds two numbers and returns a number. Can take both integer or rational number*) | |
type shape = { | |
length: int; | |
breadth: int; | |
} | |
let square = {length = 10; breadth = 20;};; | |
type anothershape = { | |
length: int; | |
breadth: int; | |
} | |
let testshape = {length = 10; breadth=50};; | |
let square = {length = 10; breadth = 20;};; | |
(* The above demo of Shape, and AnotherShape shows us that we can't create two record types with same attribute names | |
* Even if the name of record types are different. So this concept is not similar to the concept of classes and structures | |
* in C | |
*) | |
(* Understand Tail Recursion in Ocaml *) | |
(* Gist of it | |
* One recursion does not depend on another. For example parent won't depend on child at all. | |
* And hence wont' wait for any data and hence the stack entry for parent can be freed as soon | |
* as its done. | |
*) | |
(* An Example of tail Recursion *) | |
let rec make_list n = if n = 0 then [] else n :: make_list (n - 1);; (* Without tail recursion it gives error for large values of n *) | |
let rec make_list n l = if n = 0 then l else make_list (n - 1) (n :: l);; (* Now we made this tail recursive by adding an accumulator *) | |
let rec tailmap f l a = match l with | |
| [] -> a | |
| h :: t -> tailmap f t (f h :: a);; (* Example of map function with tail recursion *) | |
(* tail map generates an output which is in reversed order | |
* to correct that we can use another function to reverse the list in a tail recursive way | |
*) | |
let rev l = | |
let rec helper l a = match l with | |
| [] -> a | |
| h :: t -> helper t (h :: a) | |
in | |
helper l [];; | |
(* | |
* Refs and Arrays in Ocaml | |
* Ocaml doesn't have side effects since it is a functional programming language | |
* But there are some mutable data structures present in ocaml too which mide lead | |
* to side effects but are still there to give some ease to the programmers and | |
* should be used only if absolutely necessary | |
*) | |
let x = ref 1;; (* Referencing *) | |
!x;; (* Dereferencing *) | |
let f() = !x;; (* function binds with pointer *) | |
f();; (* This should print 1*) | |
x:=30;; | |
f();; (* This should print 30 *) | |
let f x = | |
let i = ref x in | |
while !i> 0 do | |
Printf.printf "%d\n" !i; | |
i:=!i-1; | |
done;; | |
(* An exampleof programming with side effects. *) | |
(* If you wanted to do same thing in Ocaml then you would do somethign like this *) | |
let rec print_all x = | |
match x with | |
l -> if l > 0 then (Printf.printf "%d\n" l; print_all (l-1) )else print_int 0;; | |
print_all 0; | |
type name = {fn: string; sn: string};; | |
let sujit = { fn = "sujit"; sn="chak"};; | |
(* Immutable Record declaration *) | |
type name = {mutable fn: string; sn: string};; | |
let sujit = { fn = "sujit"; sn="chak"};; | |
sujit.fn <- "Vigyan";; | |
(* Same declaration made mutable *) | |
let place = "Mill";; | |
place.[1] <- 'a';; (* We can see here that String is by default a mutable data type *) | |
place;; | |
(* Same way arrays are also mutable and can be modified with the same syntax as above *) | |
List.map (fun x -> x* x) [1;2;3];; (* Example how a function can be directly passed without writing a separate function *) | |
let add1 x y = x + y ;; | |
let add2 x = fun y -> x+y;; (* Here 2nd argument to add2 will automatically become y *) | |
(* | |
val add2 : int -> int -> int = <fun> | |
# add1 1 2;; | |
- : int = 3 | |
# add2 1 2;; | |
- : int = 3 | |
The way arguments gets passed automatically here, it's called currying style of programming | |
*) | |
(* Streams *) | |
type 'a mystream = | |
End | |
| Cons of 'a * (unit -> 'a mystream) | |
let hd = function | |
End -> failwith "emtpy" | |
| Cons(h,_) -> h | |
let tl = function | |
End -> failwith "emtpy" | |
| Cons(_,t) -> t | |
let string_stream s = | |
let rec iter n = | |
if n >= String.length s then End | |
else Cons(s.[n], fun()-> iter(n+1)) | |
in | |
iter 0; | |
;; | |
let rec ns n = Cons(n,fun() -> ns (n + 1)) | |
(* hd of object gives the number | |
* Tl of object points to the next object. | |
Please note that tl stream will just return you a function. | |
You have to run that function to take another stream. | |
E.g. | |
let temp = string_stream "Hey this is vikas";; | |
let t = tl temp;; | |
Note that t is right now a function. | |
Execute t();; and this will return you a mystream object. | |
Now if you do hd(t());; then this will give you the next character in the stream. | |
type state = | |
Terminate of bool | |
| State of (char mystream -> state);; | |
(* Some Generic questions which might be useful for tomorrow's exam | |
* Difference between mutablea and immutable data types | |
*) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment