Programming Assignment 0(not turned in or graded)The purpose of this document is to give you a few pointers about using OCaml as you begin to dive into the material from lectures and in subsequent programming assignments. OCaml in the browserOCamlPro offers an OCaml REPL that you can try in the browser. You may want to play around with this until the course accounts get set up properly, or any time if you need to try something quickly. OCaml interpreter (ocaml)
The OCaml interpreter ocaml is a read-eval-print-loop (REPL) loop
that is particularly helpful when learning the language and experimenting
with features.
We use % ocaml Objective Caml version 3.12.0 # 3 + 5 ;; - : int = 8 # let hello () = "Hello!" ;; val hello : unit -> string = <fun> # hello () ;; - : string = "Hello!"
Hit Ctrl-D or type # exit 0;; % OCaml Source Files
To avoid typing the same expressions into the REPL repeatedly,
you can save code in an .ml source file and then load
it into the REPL with the # #use "foo.ml";; (* file defining hello *) - : unit = () val hello : unit -> string = <fun> # hello ();; - : string = "Hello!"
This has the same effect as typing out the file at the prompt.
However, it is far more convenient to type and edit the file with
Vim/Emacs/GEdit and load it with A source file can also be run through the interpreter from the command-line: % ocaml foo.mlIn .ml source files, you may denote the end of “top-level expressions” with ;; , but these are optional.
Saving REPL History with rlwrapThe ordinary interpreter does not allow you to “scroll through” previous expressions that you have entered. Fortunately, there is a terrific utility called rlwrap that can help. Running % rlwrap ocamlwill run the ocaml interpreter such that you can use the up and down keys at the REPL to recall your previous interactions. You will likely want to run ocaml like this every time, so you can modify your shell settings to avoid typing this every time you launch the REPL. For example, if you are running the bash shell, you can add alias ocaml="rlwrap ocaml"to your ~/.bashrc or ~/.bash_profile so that you can simply type % ocaml from the shell.
(Note: this will take effect in all newly-opened terminals. To
have an effect on the current session, you would have to run
something like % source ~/.bashrc ).
OCaml compiler (ocamlc or ocamlopt)OCaml also comes with mature byte-code and native-code and compilers. Feel free to learn more about these, but for most assignments we will stick to the interpreter for simplicity. OCaml core library
We say that the built-in, or native, constructs of OCaml are
those that are defined in the
Pervasives module.
All of the values defined in
Notice that even operators, such as # (||);; - : bool -> bool -> bool = <fun> # let identityBool = (||) false;; val identityBool : bool -> bool = <fun> # identityBool true;; - : bool = true # identityBool false;; - : bool = false The core library provides functions for printing to standard output and reading from standard input. For example: # let _ = print_string "What’s your name? " in let s = read_line () in print_string ("Hello, " ^ s ^ "!\n");; What’s your name? Ravi Hello, Ravi! - : unit = () OCaml standard libraryThe so-called standard library of OCaml has many modules that provide useful functions, including Printf and String . # Printf.printf "Hello, %s!\n" "Ravi";; Hello, Ravi! - : unit = () In some of the assignments, you may be asked to write functions that implement similar functionality to functions provided by the standard library. The assignments will make clear which library functions, if any, you are allowed to use in your solutions. You are encouraged to become familiar with the standard library, however, because they are essential resources once you become familiar with OCaml and start to build larger projects. syntactic sugar for functionsFunctions in OCaml are first-class values that can be bound to variables, supplied as arguments, etc, and all functions take a single argument. Because function definitions and “multi-argument” (so-called curried) function definitions are so common, OCaml provides several forms of syntactic sugar to make common patterns more readable. For example, each of the following sets of functions is equivalent: let foo x = x + 1 let foo = fun x -> x + 1 let bar x y = x + y let bar x = fun y -> x + y let bar = fun x -> fun y -> x + y let baz (x,y) = x + y let baz = fun (x,y) -> x + y The OCaml compiler does a terrific job in automatically inferring types, so that no annotations need to be manually written. It is often useful, however, to write down types (at least for top-level functions) for documentation purposes, or for checking that a type holds when trying to debug type error messages. OCaml allows optional type annotations for expressions. For example, the above functions can be annotated in several different ways: let foo (x:int) : int = x + 1 let foo : int -> int = fun x -> x + 1 let bar (x:int) (y:int) : int = x + y let bar : int -> int -> int = fun x y -> x + y let baz ((x,y):(int*int)) : int = x + y let baz ((x:int),(y:int)) : int = x + y;; let baz : (int*int) -> int = fun (x,y) -> x + y syntactic sugar for pattern matchingPattern matching is used all the time, so OCaml provides several syntactic sugar mechanisms that allow common situations to be written more succinctly.
For example, patterns for cases that have the same expression body can
separated with
Furthermore, because many functions immediately pattern match their
arguments, the syntactic sugar
In particular, all of the following are equivalent: let isOneOrTwo i = match i with 1 -> true | 2 -> true | _ -> false let isOneOrTwo i = match i with 1 | 2 -> true | _ -> false let isOneOrTwo = function 1 | 2 -> true | _ -> false let isOneOrTwo = function | 1 | 2 -> true | _ -> false This same syntactic sugar applies to pattern matching against datatypes, rather than base types, in just the same way: type stuff = A of int | B of bool let lookAtStuff x = match x with | A i -> () | B b -> () let lookAtStuff = function | A i -> () | B b -> () imperative features (gasp!)Finally, lest you find out the truth from some stranger, it is true that OCaml does have imperative programming constructs, such as mutable variables and loops. For example:# for i=1 to 10 do print_int i; print_string " " done; print_newline() ;; 1 2 3 4 5 6 7 8 9 10 - : unit = ()However, you must strike this from your memory, and you are most certainly not allowed to use such features unless explicitly instructed to. Besides, for all of the programming we will be doing in OCaml, solutions that avoid these features are much more likely to be readable, elegant, and correct. |