**OCaml** (ent. **Objective Caml**) on funktionaalista ja olio-ohjelmointia tukeva ohjelmointikieli. OCaml on laajennettu versio Caml-kielestä ja on sen pääasiallinen implementaatio.

Historiaa
---------

OCamlin ensiversio julkaistiin vuonna 1996 *Objective Caml* -nimisenä, kun *Caml special light* -kieleen yhdistettiin tyypitetty olio- ja luokkamalli. OCaml nimitys otettiin käyttöön vuonna 2011.

Ominaispiirteet
---------------

OCaml:ssa on korkeatasoinen tulkki ja optimoiva kääntäjä sekä laaja standardikirjasto, joka tekee siitä käyttökelpoisen myös laajojen ohjelmistojen kehitykseen.

OCaml sisältää täysiverisen olio-mallin, vahvan moduulijärjestelmän sekä polymorfisen tyyppijärjestelmän tyypinpäättelyllä. *OCaml System* sisältää teollisuustasoisen toteutuksen, natiivikääntäjät yhdeksälle eri prosessoriarkkitehtuurille, tavukoodikääntäjän, sekä komentorivitulkin (read-eval-loop).

OCamlin jakelu sisältää laajan standardikirjaston, debuggerin, lekseri- ja parseri-generaattorit sekä koodin tulostamiseen ja dokumentointiin tarvittavat osat. OCaml ja sen kirjastot on julkaistu avoimen lähdekoodin lisensseillä (QPL ja GGPL).

OCamlia ei ole standardoitu, vaan kuten esimerkiksi Python, OCamlilla on kielen määrittelevä toteutus, INRIA:n OCaml.

Esimerkki OCamlin käytöstä
--------------------------

Tyypillinen esimerkkiohjelma *hello.ml* tulostaa sanat "Hello World":

```
  print\_endline "Hello world!";;

```

  

OCamlissa ohjelma käännetään komennolla:

```
  $ ocamlc -o hello\_ocaml hello.ml

```

  

Ohjelman ajaminen:

```
  $ ./hello\_ocaml

  Hello world!

```

OCaml kielenä
-------------

OCaml on kypsä ML-sukuinen funktionaalinen olio-ohjelmointikieli. Se on kirjoitettu OCamlilla itsellään lukuun ottamatta joitakin C-kielellä kirjoitettuja ajonaikaisia osia. OCaml perii paljon vuosikymmenien funktionaalisten kieliin, kielentutkimukseen ja tyyppiteoriaan liittyvästä akateemisesta tutkimustyöstä. OCamlia käytetään sekä opetuskielenä, että teollisuudessa.

OCaml on staattisesti tyypitetty kieli, joka käyttää *implisiittistä* tyypitystä. Kääntäjä päättelee muuttujien tyypit sen sijaan että ne määriteltäisiin lähdekoodissa.

Tästä seuraten OCaml syntaksi on hälytön, sen kääntäjä poimii virheet tehokkaasti ja tuloksena syntyvä koodi on nopeaa.

### Syntaksi

OCamlissa on ML:stä periytynyt suoraviivainen syntaksi. Sen ytimekäs syntaksi ilmaisee lambda-kalkyylia kolmella tavalla: tunnistimet (esim. *x*), funktiot (*λ x. a*) ja sovelmat (*a1 a2*). Lisäksi löytyy *let* -lause (esim *let x = a1 in a2*), jota käytetään sitomaan ilmaisu *a1* tunnistimeen *x* ilmaisussa *a2*.

### Fraasit

Ocamlissa yksittäinen lauseke on muodoltaan Caml-fraasi. Fraasit ovat joko ilmaisuja tai tunnistimien *let*-määritelmiä. Komentotulkkia käytettäessä ne päättyvät ';;' merkkeihin, jotka eivät ole välttämättömiä kieltä käännettäessä.

```
  1 + 2 \* 4;;

  let piiarvo = 4.0 \*. atan 1.0;; (\* huomaa oma kertomaoperaattori liukuluvuille \*)

```

Kullekin fraasille lasketaan kääntäjässä arvo ja tyyppi, eikä tyyppiä tarvitse erikseen määritellä.

Tyyppien päättely mahdollistaa *polymorfisuuden* funktioille.

### Tyyppijärjestelmä

OCamlin tyyppijärjestelmästä löytyvät tyypit totuusarvo (boolean), kokonaisluku, liukuluku, merkki ja merkkijono.

### Tietorakenteet

Ennaltamääritellyt tietorakenteet ovat monikko (*tuple*), taulukko (*array*) ja lista (*list*). Useimmat OCamlin tietorakenteet ovat muuttumattomia, mutta taulukko on muuttuva - sen kokoa voi muuttaa sen määrittelemisen jälkeenkin. Monikot ja listat voivat sisältää tyypeiltään eriäviä arvoja, kun taulukko sisältää samantyyppisiä arvoja.

OCamlissa ei ole muuttujan käsitettä. OCaml Standard library -kirjasto sisältää viitteet (*references*), yhden alkion taulut joita *let*illä tunnistimiin sitomalla voi viitata vaihteleviin arvoihin.

Käyttäjän määrittelemät tietorakenteet ovat taltiot (*records*) ja variantit (*variants*). Taltiot kuvaavat tietorakenteen osaset ja niiden tyypit.

```
(\* taltio eli record määritellään murtoluvuille näin: \*)

type ratio = {num: int; denum: int};;

```

  

Variantit taasen luettelevat kaikki mahdolliset tyypit määrittelemälleen tietorakenteelle:

```
(\* variant määritellään numeroille näin: \*)

  type number = Int of int | Float of float | Error;;

```

### OCaml ja funktiot

OCaml on funktionaalinen ohjelmointikieli – se tukee funktioita matemaattisen määritelmän mukaisesti täysin. Tästä seuraten funktioita voi vapaasti antaa parametreinä ja käyttää kuten muitakin tietotyyppejä. OCaml tukee myös korkeamman asteen funktioita (*higher order functions*), eli funktioita joihin annetaan toisia funktioita argumentteina.

```
  List.map (function n -> n \* 2 + 2) [0;1;2;3;4];;
  - : int list = [2; 4; 6; 8; 10]

```

### Funktiot ja rekursio

OCaml tukee rekursiota. Rekursio ilmaistaan käyttäen *rec*-sanaa. Rekursion käyttö on rajoitettu funktioihin, koska sen todistus ei ole eheä mielivaltaisille ilmaisuille.

```
 let  rec  f = λ x. a1  in  a2

 (\*\* tai esimerkiksi \*\*)

 let  rec  f1 = λ x. a1  and  f2 = λ x. a2  in  a

```

### Imperatiiviset piirteet

OCamlin imperatiivisiin ominaisuuksiin kuuluvat *for* ja *while* -silmukat, sekä muuntuvat tietorakenteet kuten taulukot (*array*). Myös taltiot voivat olla muuntuvia, jos ne määritellään käyttämällä avainsanaa *mutable*.

### Poikkeukset

OCaml tukee ohjelmien poikkeustilaa ja niiden käsittelyä. Poikkeuskäsittelijä määritellään *exception* avainsanalla.

### Muistinhallinta

OCamlin muistinhallinta on täysin automaattinen - kääntäjä osaa käyttää osoittimia (*pointers*) ja ajaa roskienkeräyksen tarvittaessa.

OCamlin moduulijärjestelmä
--------------------------

OCaml käyttää moduuleita johdonmukaisen rakenteen ja yhtenäisen nimikäytännön aikaansaamiseksi. OCamlissa tällaisia rakenteita (*structure*) määritellään lauseella *struct ... end*, jonka sisäpuolella voi olla mielivaltaisia lausekesarjoja. Rakenteelle annetaan yleensä myös nimi sitomalla se tunnistimeen *module* -avainsanalla. Näin estetään nimien loppuminen ja törmäily nimiavaruudessa.

```
 module PrioQueue =  
   struct
     type priority = int
     (\*\* jne... \*\*)
     let extract = function
         Empty -> raise Queue\_is\_empty
       | Node(prio, elt, \_, \_) as queue -> (prio, elt, remove\_top queue)
   end;;

```

  

Moduulijärjestelmä mahdollistaa myös tyyppiabstraktion (*abstract types*). Määritellyn tietorakenteen osien näkyvyyttä voi määritellä kuvaajalla*(sic)* (*signature*), joka määritellään avainsanoilla *sig ... end*.

OCamlin moduulijärjestelmän avulla voi myös määritellä funktoreita. Funktorit ovat yksinkertaisesti yhden rakenteen avulla parametrisoituja rakenteita; rakenne A joka määritellään rakenteen B:n avulla voidaan sanoa olevan funktori F parametrillä B joka palauttaa rakenteen A. Myös funktoreihin voi soveltaa kuvaajaa (*signature*).

OCamlin moduuliominaisuudet mahdollistavat myös monista moduuleista koostuvan ohjelman osien kääntämisen eri aikaan *.ml* rakennetiedostojen ja *.mli* kuvaajien lähdekoodista *.cmo*-objekti- ja *.cmi*-rajapintatiedostoiksi, jotka lopulta yhdistetään konekielikäännökseksi.

OCamlin oliomalli
-----------------

OCamlin oliomalli on omintakeinen. OCamlin luokat (*class*) määrittelevät olioita (*object*) käyttäen periytyvyyttä ja metodeita.

### Oliot

Olioiden tyypitys on tavallinen, ja niillä voi lisäksi olla alatyyppejä. Oliot eivät tunne periytymistä.

Oliot luodaan yleensä luokista, käyttäen *new* -avainsanaa. Oliot voidaan myös luoda kloonaamalla (metodilla *Oo.copy*) tai kaappaamalla (*overriding*) toisia olioita.

Olioita voidaan myös määritellä ilman luokkia, välittöminä objekteina (*immediate objects*). Tällöin oliota kuvaus (*object ... end*) voi esiintyä missä vain ekspressiossa, mutta tuloksena syntyvä olio ei omaa luokkien ominaisuuksia, kuten periytyvyys.

Olioiden sisältämät, niiden luokissa määritellyt tietorakenteet ovat saatavilla vain olioiden metodien kautta (enkapsulaatio). OCaml ei tunne luokkamuuttujia, eli kullakin oliolla on omat yksittäiset tietorakennejoukkonsa. Tässä mielessä OCamlin oliomalli noudattaa klassista olio-ohjelmointi-mallia.

### Luokat

Luokat ovat OCamlissa yleisen olio-ohjelmointi-paradigman mukaisesti määritelmiä olioiden rakentamista varten. OCaml -luokilla on oma, tavallisista tyypeistä poikkeava tyyppijärjestelmänsä, ja luokat voivat periytyä toisista luokista. Luokat määritellään OCamlissa sitomalla luokka ja sen nimi oliorakenteeseen *class NN object ... end* -rakenteella.

#### Periytyvyys

Luokkia voidaan periyttää toisista luokista lisäämällä *object ... end*-rakenteen sisään *inherit NN* -viittaus. OCaml tukee moninperiytyvyyttä.

Luokkien metodit määritellään puolestaan samaisen object-rakenteen sisällä *method nn = ...* ilmaisuilla. Luokkien metodimääritelmät ovat varjostavia, eli jälkeläisen metodi korvaa vanhemmalta perityn metodin. Tätä kutsutaan OCamlissa nimellä *late binding*. Esi-isä-luokan metodeita voidaan kuitenkin sitoa vaihtoehtoisiin metodinimiin käyttäen avainsanaa *super*.

#### Alustus, näkyvyyden rajoittaminen ja virtuaaliluokat

OCaml luokat tukevat niistä olioita luotaessa kutsuttavia alustusmetodeita. Alustusmetodit ovat avainsanalla *initializer* määriteltäviä anonyymejä metodeita, joita ei voi varjostaa tai uudelleenmääritellä. Periytetyissä luokissa alustusmetodit ajetaan määrittelyjärjestyksessä.

OCaml-luokkien metodit voivat olla yksityisiä, jolloin ne eivät näy olion ulkopuolella, ja niitä voidaan kutsua vain toisista saman olion metodeista. Yksityiset metodit määritellään ilmaisulla *method private*. OCamlin yksityiset metodit ovat vain saman olio-instanssin käytettävissä, joten ne eroavat tässä suhteessa C++:n yksityisistä metodeista, jotka ovat saman luokan olio-instanssien käytettävissä.

OCaml luokat voivat myös olla virtuaalisia; luokkia joissa määritellään virtuaalisia, sisällöttömiä metodeita ja instanssimuuttujia (*virtual*). Virtuaalisien luokkien virtuaaliset metodit ja muuttujat täytyy määritellä aliluokassa ennen kuin niistä voidaan instantioida olioita.

Virtuaaliset metodit voivat olla yksityisiä, syntaksissa tämä tapaus ilmaistaan *method private virtual*.

#### Muut luokkaominaisuudet

Tavallisten olio-ohjelmointimallien lisäksi OCaml tukee myös parametrisoituja luokkamääritelmiä, polymorfisia metodeita, tyypinpakotusta (*coercion*), funktionaalisia objekteja (syntaksissa *{< ... >}*) ja rekursiivisiä luokkia.

Katso myös
----------

* Haskell
* Lisp

Lähteet
-------

1. ↑  The Caml language (html) © INRIA 1995-2011. All rights reserved.. Viitattu 23.2.2012.
2. ↑  A History of Caml (html) © INRIA 1995-2011. All rights reserved.. Viitattu 23.2.2012.
3. 1 2  Ocaml (html) © INRIA 1995-2011. All rights reserved.. Viitattu 23.2.2012.
4. ↑  Didier Rémy: First steps in OCaml – Using, Understanding, and Unraveling The OCaml Language (html) *Lectures Notes in Computer Science*. Copyright © 2000, 2001 by Didier Rémy. Viitattu 23.2.2012. (englanniksi)
5. ↑  Type Inference *cs.cornell.edu*. Viitattu 19.2.2020. (englanniksi)
6. ↑
7. ↑  Didier Rémy: Core ML – Using, Understanding, and Unraveling The OCaml Language (html) *Lectures Notes in Computer Science*. Copyright © 2000, 2001 by Didier Rémy. Viitattu 23.2.2012. (englanniksi)
8. 1 2 3 4 5 6 7 8 9 10 11 12  Xavier Leroy, Damien Doligez, Alain Frisch, Jacques Garrigue, Didier Rémy and Jérôme Vouillon: Standalone Caml programs, The OCaml system release 3.12  29.7.2011. Copyright © 2008 Institut National de Recherche en Informatique et en Automatique.  Arkistoitu 20.12.2008. Viitattu 23.2.2012. (englanniksi)
9. ↑  Didier Rémy: 1.5. Recursion, Core ML – Using, Understanding, and Unraveling The OCaml Language (html) *Lectures Notes in Computer Science*. Copyright © 2000, 2001 by Didier Rémy. Viitattu 27.2.2012. (englanniksi)
10. 1 2 3 4  Didier Rémy: First steps in OCaml – Using, Understanding, and Unraveling The OCaml Language (html) *Lectures Notes in Computer Science*. Copyright © 2000, 2001 by Didier Rémy. Viitattu 23.2.2012.
11. ↑  Didier Rémy: The object layer – Using, Understanding, and Unraveling The OCaml Language (html) *Lectures Notes in Computer Science*. Copyright © 2000, 2001 by Didier Rémy. Viitattu 29.2.2012.


|  |  |  |  |  |  |  |  |  |  |  |  |  |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| 

| * n
* k
* m
Yleisimmät ohjelmointikielet |
| --- |
|  |
| Tuotantokäytössä | 
* Ada
* APL
* Assembly
* AWK
* C
* C++
* C#
* COBOL
* Dart
* Delphi
* Eiffel
* Erlang
* Forth
* Fortran
* Go
* Java
* JavaScript
* Kotlin
* Lisp
* Lua
* Objective-C
* Pascal
* Perl
* PHP
* PostScript
* Python
* R
* Ruby
* Rust
* Smalltalk
* Swift
* Tcl
* TypeScript
* Visual Basic

 |
|  |
| Akateemiset | 
* CLU
* Haskell
* Logo
* ML
* OCaml
* Prolog
* Scheme

 |
|  |
| Historialliset | 
* ALGOL
* BASIC
* Modula-3
* MUMPS
* Plankalkül
* PL/I
* Simula

 |
|  |
| Luettelo yleisimmistä ohjelmointikielistä |

 |