OCaml (Objective Caml) to obiektowy funkcyjny język programowania, który istnieje w wersji zarówno interpretowanej jak oraz kompilowanej, przy czym kompilowany Ocaml to jeden z najszybszych języków funkcyjnych. OCaml jest tworzony przede wszystkim we francuskim akademickim instytucie badawczym INRIA od 1985 roku. Jest dostępny na licencji LGPL.
Ocaml jest statycznie typizowany z inferencją typów.
Do Ocamla jest nader dużo bibliotek oraz istnieje pokaźna liczba rozszerzeń oraz programów pomocniczych, takich jak:
- ocamldep - generuje zależności pomiędzy modułami dla Makefile'a.
- ocamlcp - front end do ocamlc, dodający informacje profilujące
- ocamlprof - program interpretujący wyniki działania programów skompilowanych za pomocą ocamlcp
- ocamllex - generator lekserów dla ocamla, podobny do lex oraz flex dla C.
- ocamlyacc - generator parserów dla ocamla, podobny do yacc oraz bison dla C.
- ledit - frontend zapewniający edycje linii do ocamla.
- dbforge - program do tworzenia interfejsów do relacyjnych baz danych ODBC, MySQL oraz PostgreSQL
- zoggy - program do generowania interfejsów GTK+
- camlp4 - Pre-Procesor-Pretty-Printer do ocamla, dopuszcza używanie praktycznie dowolnej składni, np. składni Lispowej.
- i wiele innych
Programy napisane w Ocamlu zajmują czołowe miejsca w ICFP Programming Contest.
Ocaml wywodzi się z rodziny języków Meta Language, analogicznie jak Standard ML.
Używanie Ocamla z poziomu powłoki
Uwaga: Informacje te odnoszą się do systemów uniksowych. W innych systemach pewne rzeczy trzeba wykonywać inaczej.
Pliki źródłowe ocamla posiadają rozszerzenie ml, pliki z sygnaturami - odpowiednik plików nagłówkowych w C - rozszerzenie mli. Nie ma tu jednak żadnego preprocesora oraz literalnego włączania nagłówków - pliki sygnaturowe są najzwyczajniej kompilowane. Zwykle nie ma potrzeby tworzenia osobnych plików sygnaturowych oraz Ocaml automatycznie generuje sygnatury na podstawie plików ml.
Istnieją trzy sposoby wykonywania programów ocamlowych:
- za pomocą interpretera - komenda ocaml
- kompilacja do binarnej postaci interpretowanej - komenda ocamlc. Program ten przetwarza zaledwie tekst na struktury interpretera. Uruchomienie takiego programu powoduje uruchomienie interpretera, który wykonuje instrukcje zapisane w pliku wykonywalnym. Podobne rozwiązanie było używane w Visual Basicu. Jest przydatne z reguły podczas programowania, raczej nie winno być stosowane do tworzenia dystrybucji binarnej.
- kompilacja do kodu maszynowej - komenda ocamlopt. Tworzy bardzo szybki program, który nie wymaga żadnych zewnętrznych bibliotek oprócz libc. Kompilacja dużego programu zajmuje nader dużo czasu, więc w trakcie programowania praktyczniejsze bywa korzystanie z ocamlc.
W wyniku działania kompilatorów Ocamla powstają pliki:
- cmi - skompilowane pliki sygnaturowe, takie same w ocamlc oraz ocamlopt
- cmo - pliki modułów dla ocamlc
- o - zwykłe pliki obiektowe, wykonywane przez ocamlopt
- cmx - pliki z dodatkowymi informacjami na temat modułów, wykonywane przez ocamlc
- pliki wykonywalne (bez rozszerzenia):
- pliki skryptowe shebang ocamlrun generowane przez ocamlc
- binarne pliki wykonywalne (na Linuksie typu ELF) generowane przez ocamlopt
System typów
System typów ma za podstawę na typach bazowych takich jak:
int
Czyli liczby całkowite. Operacje na nich to m.in. +, -, *, /.
let x = 2 + 2 * 2;;
print_int x;;
float
Liczby zmiennoprzecinkowe posiadają osobny zestaw operacji, co zmniejsza wydatnie czytelność, ale jest konieczne ze względu na sposób działania systemu inferencji typów.
Operacje te zwykle kończą się kropką, np. +., -., *., /..
let y = 2.0 +. 2.0 *. 2.0;;
print_float y;;
char
Pojedyncze znaki umieszcza się w pojedynczym cudzysłowie:
let c = '\n';;
print_char c;;
Do zamieniania znaków na ich wartości numeryczne oraz na odwrót służą int_of_char oraz char_of_int.
string
Łańcuchy tekstowe umieszcza się w podwójnym cudzysłowie:
let s = "Ala ma kota\n";;
print_string s;;
bool
Wartości logiczne - true oraz false. Operacje to not, ||, && itd.
unit
Typ pusty, wartość tylko ().
Oraz na typach pochodnych takich jak:
Listy elementów danego typu
Lista elementów danego typu to 'a list, np. [1; 2; 3] to lista typu int list, a [2.71; 3.14; 6.28] to lista typu float list.
Krotka
Krotka to zestaw ustalonej liczby wartości o przyporządkowanych im na stałe, lecz niekoniecznie tych samych, typach zmiennych. Krotką jest np. para (2, "napis"), czy trójka (3, 2, 3.14). Branie krotek w nawiasy nie jest konieczne, lecz zwiększa czytelność programu.
Alternatywy
Alternatywa to zestaw konstruktorów, które bywają parametryzowane (wtedy typ ma podwartości równe wszystkim możliwym wartościom parametru) bądź też nie (istnieje tylko jedna wartość z takim konstruktorem). Jeśli potrzebny jest konstruktor, który przyjmuje więcej niż jeden parametr, używa się krotki.
Dla przykładu zdefiniujmy typ foo mający dwa konstruktory - Foo o parametrze int oraz Bar o parametrze string:
type foo = Foo of int | Bar of string;;
let print_foo = function
Foo n -> print_int n
| Bar s -> print_string s
;;
print_foo (Foo 2);;
print_foo (Bar "Napis")
Przykładem predefiniowanej polimorficznej alternatywy jest typ 'a option. Np. dla typu int option poprawnymi wartościami są None oraz Some 4.
Przykładowy kod
(* komentarz *)
let rec fib n =
if n < 2
then n
else fib (n-1) + fib (n-2)
;;
(* odmienny sposób, wykorzystujący dopasowanie do wzorca *)
let rec fibb = function
| 0 -> 0
| 1 -> 1
| n -> fibb (n-1) + fibb(n-2)
;;
print_string "Hello, world !\n";;
print_int (fib (2+2*2));;
print_newline ();;
Sprawdź też
Linki zewnętrzne