epita - practical programming 03 - from code to project€¦ · module name is built after file...

38
Modules Marwan Burelle Multi-Files OCaml Standard Library EPITA - Practical Programming 03 - From Code To Project Marwan Burelle [email protected] http://wiki-prog.infoprepa.epita.fr

Upload: others

Post on 02-Nov-2020

2 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: EPITA - Practical Programming 03 - From Code To Project€¦ · Module name is built after file name: smpl_mod.ml defines module Smpl_mod Every definition inside a module is available

Modules

Marwan Burelle

Multi-Files

OCaml StandardLibraryEPITA - Practical Programming

03 - From Code To Project

Marwan Burelle

[email protected]://wiki-prog.infoprepa.epita.fr

Page 2: EPITA - Practical Programming 03 - From Code To Project€¦ · Module name is built after file name: smpl_mod.ml defines module Smpl_mod Every definition inside a module is available

Modules

Marwan Burelle

Multi-Files

OCaml StandardLibrary

Outline

1 Multi-Files Project And Simple ModulesModulesDependencies And OrderModule Interfaces

2 OCaml Standard Library

Page 3: EPITA - Practical Programming 03 - From Code To Project€¦ · Module name is built after file name: smpl_mod.ml defines module Smpl_mod Every definition inside a module is available

Modules

Marwan Burelle

Multi-FilesModules

Dependencies And Order

Module Interfaces

OCaml StandardLibrary

Multi-Files Project And Simple Modules

Multi-Files Project AndSimple Modules

Page 4: EPITA - Practical Programming 03 - From Code To Project€¦ · Module name is built after file name: smpl_mod.ml defines module Smpl_mod Every definition inside a module is available

Modules

Marwan Burelle

Multi-FilesModules

Dependencies And Order

Module Interfaces

OCaml StandardLibrary

Building Real Projects

• Putting all your code in one file is stupid• Projects need organization and structures• OCaml provides a sub-language for modules:

• Modules are autonomous entity providing a set ofsymbols and definitions

• OCaml provides the basic file oriented modules• You can also have embedded modules and parametric

modules (functors.)• Modules have interfaces in order to manage visibility.• Modules’ Interface provides an opaque types

mechanism.

Page 5: EPITA - Practical Programming 03 - From Code To Project€¦ · Module name is built after file name: smpl_mod.ml defines module Smpl_mod Every definition inside a module is available

Modules

Marwan Burelle

Multi-FilesModules

Dependencies And Order

Module Interfaces

OCaml StandardLibrary

Overview

1 Multi-Files Project And Simple ModulesModulesDependencies And OrderModule Interfaces

Page 6: EPITA - Practical Programming 03 - From Code To Project€¦ · Module name is built after file name: smpl_mod.ml defines module Smpl_mod Every definition inside a module is available

Modules

Marwan Burelle

Multi-FilesModules

Dependencies And Order

Module Interfaces

OCaml StandardLibrary

A Simple Example

smpl_mod.ml(* Module: Smpl_mod *)(* File: smpl_mod.ml *)

(* A type def *)type t = Yes | No

(* Some functions *)let tostr = function| Yes -> "yes"| No -> "no"

let rec fact = function| (0|1) as n -> n| n -> n * fact (n-1)

(* A constant *)let cst = 42

main.ml(* Module: Main *)(* File: main.ml *)open Printflet cst = 0

let main () =beginprintf "%s\n"(Smpl_mod.tostr Smpl_mod.Yes);printf "cst: %d\n" cst;printf "Smpl_mod.cst: %d\n"Smpl_mod.cst;printf "Smpl_mod.fact 5: %d\n"(Smpl_mod.fact 5);exit 0;endlet _ = main ()

Page 7: EPITA - Practical Programming 03 - From Code To Project€¦ · Module name is built after file name: smpl_mod.ml defines module Smpl_mod Every definition inside a module is available

Modules

Marwan Burelle

Multi-FilesModules

Dependencies And Order

Module Interfaces

OCaml StandardLibrary

Compiling

Example:

File by file

> ocamlopt -c smpl_mod.ml> ocamlopt -c main.ml> ocamlopt -o main smpl_mod.cmx main.cmx> ./mainyescst: 0Smpl_mod.cst: 42Smpl_mod.fact 5: 120

Using ocamlbuild:

> ocamlbuild main.nativeFinished, 7 targets (0 cached) in 00:00:00.> ./main.native> yes <cst: 0Smpl_mod.cst: 42Smpl_mod.fact 5: 120

Page 8: EPITA - Practical Programming 03 - From Code To Project€¦ · Module name is built after file name: smpl_mod.ml defines module Smpl_mod Every definition inside a module is available

Modules

Marwan Burelle

Multi-FilesModules

Dependencies And Order

Module Interfaces

OCaml StandardLibrary

Using A MakefileMakefile

# Some variablesSRC= smpl_mod.ml main.mlCMX= ${SRC:.ml=.cmx}PRG=mainOCAMLOPT=ocamlopt.optOCFLAGS= # options for modules compilingOCLDFLAG= # options for link time# Main targetall: ${PRG}${PRG}: ${CMX}

${OCAMLOPT} -o $@ ${OCLDFLAG} ${CMX}# Automatic targets.SUFFIXES: .ml .cmx.ml.cmx:

${OCAMLOPT} ${OCFLAGS} -c $<# Usefull targetsclean::

rm -f *.cm[iox] *.o *~rm -f ${PRG}

# END

Page 9: EPITA - Practical Programming 03 - From Code To Project€¦ · Module name is built after file name: smpl_mod.ml defines module Smpl_mod Every definition inside a module is available

Modules

Marwan Burelle

Multi-FilesModules

Dependencies And Order

Module Interfaces

OCaml StandardLibrary

Modules

• Every .ml file is a module• Module name is built after file name: smpl_mod.ml

defines module Smpl_mod• Every definition inside a module is available using the

dot notation: Smpl_mod.fact• Tag names (record fields or sum types’ label) must

also be prefixed with module name: Smpl_mod.Yes• Names’ restrictions (uniqueness of tag names, symbol

masking . . . ) does not cross module boundaries.

Page 10: EPITA - Practical Programming 03 - From Code To Project€¦ · Module name is built after file name: smpl_mod.ml defines module Smpl_mod Every definition inside a module is available

Modules

Marwan Burelle

Multi-FilesModules

Dependencies And Order

Module Interfaces

OCaml StandardLibrary

More Modules Syntax

aa.ml(* module: Aa *)type t = {a: int;b: int;c: int;

}

module P = Printflet print x =P.printf"{a=%d;b=%d;c=%d;}\n"x.a x.b x.c

bb.ml(* Module: Bb *)

let x = {Aa.a = 0;Aa.b = 0;Aa.c = 0;

}

let y =Aa.({a = 0; b = 0; c = 0;

})

Page 11: EPITA - Practical Programming 03 - From Code To Project€¦ · Module name is built after file name: smpl_mod.ml defines module Smpl_mod Every definition inside a module is available

Modules

Marwan Burelle

Multi-FilesModules

Dependencies And Order

Module Interfaces

OCaml StandardLibrary

Overview

1 Multi-Files Project And Simple ModulesModulesDependencies And OrderModule Interfaces

Page 12: EPITA - Practical Programming 03 - From Code To Project€¦ · Module name is built after file name: smpl_mod.ml defines module Smpl_mod Every definition inside a module is available

Modules

Marwan Burelle

Multi-FilesModules

Dependencies And Order

Module Interfaces

OCaml StandardLibrary

Modules Organization

• Splitting code into modules requires someorganization.

• When a piece of code use symbols from anothermodule it creates a dependency.

• Dependencies induce constraints on compilationorder.

• A program with circular dependencies won’t nevercompile.

• The way you split your code is important !

Page 13: EPITA - Practical Programming 03 - From Code To Project€¦ · Module name is built after file name: smpl_mod.ml defines module Smpl_mod Every definition inside a module is available

Modules

Marwan Burelle

Multi-FilesModules

Dependencies And Order

Module Interfaces

OCaml StandardLibrary

Graph And Dependencies

Data_structure File_format

Algorithm

Main is used by

A possible compilation order could be:

Data_structure File_format Algorithm Main

Page 14: EPITA - Practical Programming 03 - From Code To Project€¦ · Module name is built after file name: smpl_mod.ml defines module Smpl_mod Every definition inside a module is available

Modules

Marwan Burelle

Multi-FilesModules

Dependencies And Order

Module Interfaces

OCaml StandardLibrary

Compilation Order

Given the previous example, we should compile our codehas follow:

> ocamlopt -c data_structure.ml> ocamlopt -c file_format.ml> ocamlopt -c algorithm.ml> ocamlopt -c main.ml> ocamlopt -o main data_structure.cmx file_format.cmxalgorithm.cmx main.cmx

Order is important when compiling modules but alsowhen giving .cmx files list !

Page 15: EPITA - Practical Programming 03 - From Code To Project€¦ · Module name is built after file name: smpl_mod.ml defines module Smpl_mod Every definition inside a module is available

Modules

Marwan Burelle

Multi-FilesModules

Dependencies And Order

Module Interfaces

OCaml StandardLibrary

OCaml Link And Execute Schema

• An OCaml program is basically the evaluation of asequence of phrases (most of it being definitions.)

• The old rule is still there: a symbol should definedbefore its first use.

• Unlike most language, link step in OCaml is almost aconcatenation of all modules.

mod1.ml(* Mod1 *)let _ = print_string "Mod1\n"

mod2.ml(* Mod2 *)let _ = print_string "Mod2\n"

mod3.ml(* Mod3 *)let _ = print_string "Mod3\n"

mod4.ml(* Mod4 *)let _ = print_string "Mod4\n"

Page 16: EPITA - Practical Programming 03 - From Code To Project€¦ · Module name is built after file name: smpl_mod.ml defines module Smpl_mod Every definition inside a module is available

Modules

Marwan Burelle

Multi-FilesModules

Dependencies And Order

Module Interfaces

OCaml StandardLibrary

OCaml Link And Execute Schema

Example:

> for f in mod?.ml; doocamlopt -c $fdone> ocamlopt -o v1 mod1.cmx mod2.cmx mod3.cmx mod4.cmx> ocamlopt -o v2 mod4.cmx mod3.cmx mod2.cmx mod1.cmx> ./v1Mod1Mod2Mod3Mod4> ./v2Mod4Mod3Mod2Mod1

Page 17: EPITA - Practical Programming 03 - From Code To Project€¦ · Module name is built after file name: smpl_mod.ml defines module Smpl_mod Every definition inside a module is available

Modules

Marwan Burelle

Multi-FilesModules

Dependencies And Order

Module Interfaces

OCaml StandardLibrary

Good Pratices When Splitting Code

• Each data structure must belongs to its own module.• All operations attached to a data structure must be in

the module defining it.• Each algorithm should have its own module.• Functions and definitions used by only one algorithm

should reside in the module defining it.• When splitting your project you must think of:

• Nature of your data• How information will flow in your program• How modules will talk together

Page 18: EPITA - Practical Programming 03 - From Code To Project€¦ · Module name is built after file name: smpl_mod.ml defines module Smpl_mod Every definition inside a module is available

Modules

Marwan Burelle

Multi-FilesModules

Dependencies And Order

Module Interfaces

OCaml StandardLibrary

Breaking Circular Dependencies ?

• Re-check previous rules: beware of orphan functions• Can you split of your module ? Yes ? Do it !• Build toolboxes: debugging facilities, pretty-printers,

file manipulation functions . . .• When all have failed, use refactoring and genericity:

• Polymorphic data structures can help to separate adata structures and its specific usages.

• First order functions can be used to loose the couplingbetween data operations and specific usages.

• Polymorphic parametric classes and functors can alsohelp.

Page 19: EPITA - Practical Programming 03 - From Code To Project€¦ · Module name is built after file name: smpl_mod.ml defines module Smpl_mod Every definition inside a module is available

Modules

Marwan Burelle

Multi-FilesModules

Dependencies And Order

Module Interfaces

OCaml StandardLibrary

Overview

1 Multi-Files Project And Simple ModulesModulesDependencies And OrderModule Interfaces

Page 20: EPITA - Practical Programming 03 - From Code To Project€¦ · Module name is built after file name: smpl_mod.ml defines module Smpl_mod Every definition inside a module is available

Modules

Marwan Burelle

Multi-FilesModules

Dependencies And Order

Module Interfaces

OCaml StandardLibrary

Interfaces ?

• It can be convenient to hide inner details of a module.• Some data structures are stable only if proper

operations are used on it.1

We can use interfaces for that !

• Interfaces, let you decide which symbols are exportedor not.

• Interfaces, let you define opaque types.• Interfaces can be used to define several

implementations for one API.

Page 21: EPITA - Practical Programming 03 - From Code To Project€¦ · Module name is built after file name: smpl_mod.ml defines module Smpl_mod Every definition inside a module is available

Modules

Marwan Burelle

Multi-FilesModules

Dependencies And Order

Module Interfaces

OCaml StandardLibrary

A Simple Interface

arith.ml(* Module: Arith *)(* Implementation *)

let rec aux_fact a = function| 0 | 1 -> a| n -> aux_fact (a*n) (n-1)let fact n =if n < 0 then assert falseelse aux_fact 1 n

let rec aux_pow a = function| 1 -> a| n -> (aux_pow (a*a) (n/2))* if n mod 2=0 then 1 else alet power a = function| 0 -> 1| b when b<0 -> assert false| b -> aux_pow a b

arith.mli(* Module: Arith *)(* Interface *)(* Only fact and powerare visible. *)

val fact: int -> int(* fact n : returns thefactorial of n, raiseassertion failure ifn is negative.

*)

val power: int -> int -> int(* power a b returnsa powers b, raiseassertion failure ifb is negative.

*)

Page 22: EPITA - Practical Programming 03 - From Code To Project€¦ · Module name is built after file name: smpl_mod.ml defines module Smpl_mod Every definition inside a module is available

Modules

Marwan Burelle

Multi-FilesModules

Dependencies And Order

Module Interfaces

OCaml StandardLibrary

Using Modules With Interface

main.mllet main () =begin(* Working *)Printf.printf "fact 5 = %d\n" (Arith.fact 5);(* aux_fact doesn’t exit here *)Printf.printf "fact 5 = %d\n"(Arith.aux_fact 1 5);

exit 0;endlet _ = main ()

Page 23: EPITA - Practical Programming 03 - From Code To Project€¦ · Module name is built after file name: smpl_mod.ml defines module Smpl_mod Every definition inside a module is available

Modules

Marwan Burelle

Multi-FilesModules

Dependencies And Order

Module Interfaces

OCaml StandardLibrary

Compiling With Interfaces

Example:> lsmymod.ml mymod.mli> ocamlopt -c mymod.mlFile "mymod.ml", line 1, characters 0-1:Error: Could not find the .cmi file for interface mymod.mli.> ocamlopt -c mymod.mli> ocamlopt -c mymod.ml

ocamlopt -c file.mli produces a compiled interface filefile.cmi

Page 24: EPITA - Practical Programming 03 - From Code To Project€¦ · Module name is built after file name: smpl_mod.ml defines module Smpl_mod Every definition inside a module is available

Modules

Marwan Burelle

Multi-FilesModules

Dependencies And Order

Module Interfaces

OCaml StandardLibrary

Interfaces, Dependencies And Order

• When compiling modules, dependencies only appliedto compiled interfaces.

• When linking (program production) you need objectcode (.cmx file) for each module.

• Take the following example:• we got three modules forming a dependency string:A→ B→ Main.

• If all modules have interface we can compile theprogram that way:> ocamlopt -c a.mli> ocamlopt -c b.mli> ocamlopt -c main.mli> ocamlopt -c main.ml> ocamlopt -c b.ml> ocamlopt -c a.ml> ocamlopt -o main a.cmx b.cmx main.cmx

Page 25: EPITA - Practical Programming 03 - From Code To Project€¦ · Module name is built after file name: smpl_mod.ml defines module Smpl_mod Every definition inside a module is available

Modules

Marwan Burelle

Multi-FilesModules

Dependencies And Order

Module Interfaces

OCaml StandardLibrary

Generating Interfaces

> cat mylist.mllet rec len = function| [] -> 0| _::t -> 1 + len t

let rec iter f = function| [] -> ()| h::t -> f h; iter f t

> ocamlopt -i mylist.mlval len : ’a list -> intval iter : (’a -> ’b) -> ’a list -> unit> ocamlopt -i mylist.ml > mylist.mli

Page 26: EPITA - Practical Programming 03 - From Code To Project€¦ · Module name is built after file name: smpl_mod.ml defines module Smpl_mod Every definition inside a module is available

Modules

Marwan Burelle

Multi-FilesModules

Dependencies And Order

Module Interfaces

OCaml StandardLibrary

Interfaces And Project Organization

• An interface describe how someone will use a module• Interfaces are the place for:

• API description• Types and operation specifications• Module documentations.

• You can have modules without comments, but notinterfaces.

• A good project organization should be:1 Analyze and divide your project2 Write interfaces3 Distribute jobs among programmers4 Test and integrate modules.

Page 27: EPITA - Practical Programming 03 - From Code To Project€¦ · Module name is built after file name: smpl_mod.ml defines module Smpl_mod Every definition inside a module is available

Modules

Marwan Burelle

Multi-Files

OCaml StandardLibrary

OCaml Standard Library

OCaml Standard Library

Page 28: EPITA - Practical Programming 03 - From Code To Project€¦ · Module name is built after file name: smpl_mod.ml defines module Smpl_mod Every definition inside a module is available

Modules

Marwan Burelle

Multi-Files

OCaml StandardLibrary

Don’t rewrite code !

• Just like most modern programming languages,OCaml provides a Standard Library.

• This library contains usual tools: I/O, stringsmanipulations, formatted output, containers . . .

• Most data structures you may need are probablyavailable in a stable and efficient form.

• Like any good programmer, when you need adata-structure or a tools, the first thing you must do is:take a look at the standard library.

• The library is organized in modules.

Page 29: EPITA - Practical Programming 03 - From Code To Project€¦ · Module name is built after file name: smpl_mod.ml defines module Smpl_mod Every definition inside a module is available

Modules

Marwan Burelle

Multi-Files

OCaml StandardLibrary

Pervasivesmodule

• Implicitely opens• Contains all basic functions (simple I/O, arithmetic,

types conversions . . . )• Even if the module is implicitely open, you can use

the dot notation (Pervasives.abs for example) toavoid conflicts.

Page 30: EPITA - Practical Programming 03 - From Code To Project€¦ · Module name is built after file name: smpl_mod.ml defines module Smpl_mod Every definition inside a module is available

Modules

Marwan Burelle

Multi-Files

OCaml StandardLibrary

List, Stack and Queue

• These modules provide implementation for thesethree classic data structures.

• While List is pure functional, Stack and Queue areimperative and provides in-place operations.

Most used functions:

List Stack QueueList.map Stack.create Queue.createList.iter Stack.push Queue.push

List.fold_left Stack.pop Queue.takeList.assoc Stack.is_empty Queue.is_empty

Page 31: EPITA - Practical Programming 03 - From Code To Project€¦ · Module name is built after file name: smpl_mod.ml defines module Smpl_mod Every definition inside a module is available

Modules

Marwan Burelle

Multi-Files

OCaml StandardLibrary

List, Stack and Queue

lsq.mllet l = [1;2;3;4;5;]let main () =let s = Stack.create () and q = Queue.create () inbeginList.iter (fun x -> Stack.push x s) l;while not (Stack.is_empty s) doQueue.push (Stack.pop s) q

done;Printf.printf "[";while not (Queue.is_empty q) doPrintf.printf "%d;" (Queue.take q);

done;Printf.printf "]\n";

endlet _ = main ()

> ocamlbuild lsq.nativeFinished, 4 targets (0 cached) in 00:00:00.> ./lsq.native[5;4;3;2;1;]

Page 32: EPITA - Practical Programming 03 - From Code To Project€¦ · Module name is built after file name: smpl_mod.ml defines module Smpl_mod Every definition inside a module is available

Modules

Marwan Burelle

Multi-Files

OCaml StandardLibrary

Hashtbl

• Hash table are simplest kind of map (associativetables.)

• They are very efficient for searching (amortizedconstant time.)

• They’re less usefull when mapping is too dynamic.• The Hashtblmodule provides an imperative

implementation of auto-resizable hash table using ageneric hash function.

Using Hashtbllet ops =let h = Hashtbl.create 13 inList.iter (fun (k,v) -> Hashtbl.add h k v) [("+", (+));("-", (-));("*", ( * ));("/", (/));

]; hlet eval_op op v1 v2 =(Hashtbl.find ops op) v1 v2

Page 33: EPITA - Practical Programming 03 - From Code To Project€¦ · Module name is built after file name: smpl_mod.ml defines module Smpl_mod Every definition inside a module is available

Modules

Marwan Burelle

Multi-Files

OCaml StandardLibrary

Set and Map

• Set provides set of values (without duplicate.)• Map provides another kind (functionnal.)• Both use a functor: a function from modules to

modules.• Functors require an input module respecting an

interface, both Set and Map have the same kind ofinput:

OrderedType(* More on module type later ... *)module type OrderedType =sigtype tval compare : t -> t -> int

end

Page 34: EPITA - Practical Programming 03 - From Code To Project€¦ · Module name is built after file name: smpl_mod.ml defines module Smpl_mod Every definition inside a module is available

Modules

Marwan Burelle

Multi-Files

OCaml StandardLibrary

Using Settestset

module StrSet = Set.Make(String)

let wset = List.fold_left (fun s w -> StrSet.add w s)StrSet.empty [ "hello";"code";"work";"code";"effort" ]

module Int =structtype t = intlet compare = Pervasives.compare

endmodule IntSet = Set.Make(Int)

let iset = List.fold_left (fun s w -> IntSet.add w s)IntSet.empty [ 42; 5; 6; 2; 42; 36; ]

let main () =StrSet.iter (Printf.printf "%S\n") wset;IntSet.iter (Printf.printf "%d\n") iset;exit 0

let _ = main ()

Page 35: EPITA - Practical Programming 03 - From Code To Project€¦ · Module name is built after file name: smpl_mod.ml defines module Smpl_mod Every definition inside a module is available

Modules

Marwan Burelle

Multi-Files

OCaml StandardLibrary

Using Set

> ocamlbuild testset.nativeFinished, 4 targets (0 cached) in 00:00:01.> ./testset.native"code""effort""hello""work"2563642

Page 36: EPITA - Practical Programming 03 - From Code To Project€¦ · Module name is built after file name: smpl_mod.ml defines module Smpl_mod Every definition inside a module is available

Modules

Marwan Burelle

Multi-Files

OCaml StandardLibrary

Using Map

Operators with Mapmodule StrMap = Map.Make(String)

let ops =List.fold_left(fun s (k,v) -> StrMap.add k v s)[("+", (+)); ("-", (-));("*", ( * )); ("/", (/));

]

let eval_op op v1 v2 =(StrMap.find op ops) v1 v2

Page 37: EPITA - Practical Programming 03 - From Code To Project€¦ · Module name is built after file name: smpl_mod.ml defines module Smpl_mod Every definition inside a module is available

Modules

Marwan Burelle

Multi-Files

OCaml StandardLibrary

Managing Command Line: Args

usingarg.mllet switch = ref falselet num = ref 0

let num_fun i = Printf.printf "Called num_fun %d\n" ilet annon s = Printf.printf "Called with: %S\n" slet usage = Sys.argv.(0) ^ " <option>: module Arg demo."

let spec = Arg.align [("-switch", Arg.Set switch, " set the switch on");("-num", Arg.Set_int num, " fix num value (default 0)");("-num_fun", Arg.Int num_fun, " call num_fun");

]

let main () =Arg.parse spec annon usage;if !switch then Printf.printf "Switch is on\n";Printf.printf "num value is: %d\n" !num

let _ = main ()

Page 38: EPITA - Practical Programming 03 - From Code To Project€¦ · Module name is built after file name: smpl_mod.ml defines module Smpl_mod Every definition inside a module is available

Modules

Marwan Burelle

Multi-Files

OCaml StandardLibrary

Managing Command Line: Args

> ./usingarg.native --help./usingarg.native <option>: demo for module Arg.-switch set the switch on-num fix num value (default 0)-num_fun call num_fun-help Display this list of options--help Display this list of options

> ./usingarg.native -switch -num 42 -num_fun 1 annon paramCalled num_fun 1Called with: "annon"Called with: "param"Switch is onnum value is: 42> ./usingarg.native -num_fun 1 -num_fun 2Called num_fun 1Called num_fun 2num value is: 0