Introduction to Objective Caml
General comments ML is a purely functional language--there are (almost) no side effects There are two basic dialects of ML –Standard ML –Caml (including Objective Caml, or OCaml) ML is interactive ML is case-sensitive ML is strongly typed
Using Objective Caml
Programs on files Save your program file with a.ml extension –As always, use a decent text editor To load a program: –Choose File -> Open... –Click OK (to clear the input pane) –Navigate to your file and open it –Hit the Return key in the terminal input window
Two kinds of Enter! The Enter key on the main keyboard sends your expression to Ocaml to be executed The Enter key on the numeric keypad just gives you a new line in the input pane If you copy and paste code from another source, you may get mysterious errors –Replace each newline with the keypad kind!
Comments Comments are enclosed in (* and *) Comments can be nested Nested comments are useful for commenting out a block of code that may itself contain comments
Identifiers Identifiers are composed of letters, digits, underscores ( _ ), and primes ( ' ) –Normal variables must start with a lowercase letter –"prime" = "apostrophe" = "single quote" = "tick" –Only "type variables" can start with a prime –An underscore all by itself, _, is a wildcard
Primitive types int 0, 5, 42, -17, 0x00FF –Negative int s often need to be parenthized: (-1) float 0.0, -5.3, 1.7e14, 1e-10 –Cannot start with a decimal point bool true, false string "", "One\nTwo\nThree" char 'a', '\n'
Trying things at the prompt End expressions with a double semicolon, ;; # 2 + 2;; - : int = 4 # let five = 5;; val five : int = 5 # 2 + five;; - : int = 7 Caml shows you the type because it's important
Operations on bool s Comparisons give a bool result >= > Standard operators are not, &&, || # (1 < 3) && (3 <= 5);; - : bool = true && and || are short-circuit operators There is an and, but it's something else entirely
Arithmetic Arithmetic on integers: + - * / 2 + 2;; # - : int = 4 Arithmetic on floats: *. /. # ;; - : float = # ;; # Characters 6-9: This expression has type float but is here used with type int
No mixed-mode arithmetic # ;; # Characters 4-7: This expression has type float but is here used with type int # ;; # Characters 0-1: This expression has type int but is here used with type float
Numeric coercions #float 5;; - : float = # truncate 3.8;; - : int = 3 # floor 3.8;; - : float = # ceil 3.8;; - : float =
Comparisons Comparisions >= > can be applied to any type –Comparisons have their usual meanings for primitive types ( int, float, bool, string, char ) –Their meaning is undefined for more complex types The comparisons == and != test whether two things occupy the same storage locations
Operations on strings and chars ^ is string concatenation String.length s returns the size of string s String.index s c finds character c in string s String.sub s p n returns a substring of s of length n starting from p String.uppercase s uppercases all letters in s String.capitalize s uppercases the first character in s
Lists Lists are semicolon-separated and enclosed in brackets # [3; 5; 7];; - : int list = [3; 5; 7] All elements of a list must be the same type –Note that the type above is given as int list
The empty list The empty list is represented by [ ] The empty list has a type When Caml doesn't know the type, it represents it with a type variable 'a, 'b, 'c,... # [ ];; - : 'a list = [] Sometimes Caml does know the type of [ ] !
Operations on lists hd returns the head ( CAR ) of a list tl returns the tail ( CDR ) of a list :: adds an element to a list ( CONS ) –Example: 1 :: [3; 5; 7] gives [1; 3; 5; appends two lists ( APPEND ) List.length l returns the length of l List.nth l n returns the n th element of l
Tuples Elements of a tuple are separated by commas Tuples are usually enclosed in parentheses # ("pi", , [1;2;3]);; - : string * float * int list = "pi", , [1; 2; 3] Notice the type: (string * float * int list) [(3, 5.0); (3.0, 5)] isn't legal--why not?
Tuples of different sizes Notice the types in the following: # (1, 2, 3);; - : int * int * int = 1, 2, 3 # (1, 2);; - : int * int = 1, 2 # (1);; - : int = 1 (* Why is this an int? *) For x of any type, (x) is the same as x
Operations on tuples A pair is a tuple of two elements fst t is the first element of a pair t snd t is the second element of a pair t That's all! You can define additional operations on tuples by using pattern matching (more about that later)
The unit The empty tuple is represented as ( ) The empty tuple is called the "unit" There is (obviously) only one value of this type, but it is a value There are a (very) few places where we use the unit because we need to provide a value but don't care what it is.
Defining a simple function # let add (x, y) = x + y;; val add : int * int -> int = # add (3, 5);; - : int = 8 Notice the type of add: int * int -> int = The -> indicates that this is a function The value (function body) is abbreviated to
The End