OCaml

Versiunea actuală a paginii nu a fost încă examinată de colaboratori experimentați și poate diferi semnificativ de versiunea revizuită pe 28 octombrie 2021; verificările necesită 3 modificări .
OCaml
Semantică multi- paradigma : funcțional , orientat pe obiecte , imperativ
Clasa de limba limbaj de programare orientat pe obiecte , limbaj de programare funcțional ,de programare multi-paradigma , limbaj de programare imperativ, limbaj de programare șisoftware gratuit și open source
Aparut in 1996
Autor Leroy, Xavier și Damien Doligez [d]
Dezvoltator INRIA
Extensie de fișier .ml, .mli
Eliberare 4.14.0 ( 28 martie 2022 )
Tip sistem strict , static
Dialectele F# , JoCaml , MetaOCaml, OcamlP3l
A fost influențat Standard ML , Caml Light
Licență LGPL
Site-ul web ocaml.org
OS Sistem de operare asemănător Unix [1]
 Fișiere media la Wikimedia Commons

OCaml ( Obiective Caml ) este un limbaj de programare funcțional orientat pe obiecte de uz general . A fost proiectat având în vedere siguranța execuției și fiabilitatea programelor. Suportă paradigme de programare funcționale, imperative și orientate pe obiecte. Cel mai comun dialect al limbajului ML în lucrările practice .

A apărut în 1996 sub numele de Objective Caml, când Didier Rémy (Didier Rémy) și Jérôme Vouillon (Jérôme Vouillon) au implementat suport pentru programarea orientată pe obiecte pentru limbajul Caml, dezvoltat inițial la Institutul Francez INRIA . Oficial redenumit în OCaml în 2011 [2] .

Setul de instrumente OCaml include un interpret , un compilator la bytecode și un compilator de optimizare la codul nativ, comparabil ca eficiență cu Java și doar puțin inferior ca performanță cu C și C++ [3] .

În special, redarea formulelor Wikipedia folosind eticheta <math>, clientul de schimb de fișiere MLDonkey , stiva de control al hipervizorului Xen xapi (parte a Xen Server / Xen Cloud Platform) și limbajul de programare Haxe sunt scrise în OCaml limbaj .

Despre limba

Locul și rolul în informatică

Limbajul OCaml este un limbaj de programare de uz general, dar are propriile sale domenii de aplicare stabilite [4] .

În primul rând, este crearea de aplicații „sigure” (nu numai în sensul securității informațiilor). Limbajul folosește colectarea gunoiului, iar majoritatea tipurilor de date sunt de referință ( cutie în engleză  ), ceea ce înseamnă prevenirea depășirilor de buffer în timpul execuției programului. În plus, tastarea statică și verificările la timp de compilare fac imposibile anumite alte clase de erori, cum ar fi erorile de turnare , din cauza lipsei de turnare automată a tipului. În plus, codul poate fi verificat oficial . Există utilitare pentru demonstrarea automată a corectitudinii tipului codului, superioare celor pentru majoritatea limbajelor de programare. Și, important, măsurile de securitate nu afectează eficiența codului executabil [4] .

Un alt domeniu de succes cu OCaml este în aplicațiile bazate pe date . Această zonă include procesarea textului, precum și compilatoarele de scriere. OCaml are nu numai instrumente pentru procesarea textului (pentru care, de exemplu, Perl sau AWK sunt renumite ), ci și instrumente pentru analiză semantică profundă și transformare a textului, ceea ce face ca OCaml să fie aplicabil în sarcinile de data mining [ 4 ] . 

Desigur, OCaml, ca și alte dialecte ale ML, este folosit în sarcini de cercetare și verificare, în care codul principal este scris într-un limbaj de programare, iar apoi verificat și analizat formal de un program OCaml [4] . De exemplu, sistemul interactiv de demonstrare a teoremei Coq este scris în OCaml .

Proprietăți de bază

OCaml deține un loc special printre limbajele de programare datorită combinației sale de eficiență, expresivitate și caracter practic. Printre caracteristicile limbajului care au evoluat de-a lungul a peste 40 de ani de la crearea ML se numără [5] :

Istorie

OCaml își are originile în ML ( eng.  meta language ), care a fost implementat în dialectul Lisp de Robin Milner în 1972 ca instrument software pentru demonstrarea teoremelor, ca metalimbaj pentru logica funcțiilor calculabile (LCF, eng.  logic for calculable ). funcții ). Mai târziu, a fost creat un compilator , iar până în 1980, ML a devenit un sistem de programare cu drepturi depline [6] .

Guy Cousineau a adăugat tipuri de date algebrice și potrivire a modelelor la limbaj și a definit ML ca o mașină abstractă categorială (CAM). Astfel, CAM-ML a putut fi descris, verificat și optimizat, ceea ce a reprezentat un pas înainte pentru ML [7] .

O dezvoltare ulterioară a fost limbajul Caml (reluat de CAM-ML) [6] [7] creat până în 1987 de Ascánder Suárez și continuat de Pierre Weis și Michel Mauny .

În 1990, Xavier Leroy și Damien Doligez au lansat o nouă implementare numită Caml Light . Această implementare C a folosit un interpret de cod de octet și un colector de gunoi rapid. Odată cu scrierea bibliotecilor, limba a început să fie folosită în institutele de educație și cercetare [6] [7] .

Caml Special Light , dezvoltat de C. Leroy , a văzut lumina în 1995 . Sistemul de programare a primit un compilator în coduri de mașină, ceea ce pune eficiența codului executabil la egalitate cu alte limbaje compilate. În același timp, a fost dezvoltat un sistem de module , a cărui idee a fost împrumutată din Standard ML [6] .

Forma modernă a lui OCaml datează din 1996 , când Didier Rémy și Jérôme Vouillon au implementat suport pentru obiecte clar și eficient pentru limbaj . Acest sistem de obiecte vă permite să utilizați idiomuri de programare orientate pe obiect în timpul compilării într-o manieră sigură , fără verificările inerente C++ și Java la timpul de rulare [6] .

În anii 2000, limba a evoluat fără probleme, câștigând în același timp mai multă recunoaștere în proiectele comerciale și educație. Printre cele dezvoltate în acest moment se numără metodele polimorfe și tipurile de variante, parametrii numiți și opționali, modulele de primă clasă , tipurile de date algebrice generalizate (GADT). Limbajul a început să suporte mai multe platforme hardware ( X86 , ARM , SPARC , PowerPC ) [6] [7] .

Semantică de bază

Modelul de calcul al OCaml ca limbaj de programare funcțional se bazează pe trei construcții principale ale calculului lambda : variabile , definițiile funcției și aplicarea unei funcții la argumente [8] .

Variabile

O variabilă este un identificator a cărui valoare este asociată cu o anumită valoare. Numele variabilelor încep cu o literă mică sau liniuță de subliniere. Legarea se face de obicei cu cuvântul cheie let, ca în exemplul următor într-un shell interactiv [9] :

fie v = 1 ;;

Variabilele au un domeniu de aplicare . De exemplu, într-un shell interactiv, o variabilă poate fi utilizată în comenzi care urmează legăturii acesteia. În mod similar, o variabilă definită într-un modul poate fi utilizată după ce a fost definită în acel modul [9] .

Legarea variabilelor se poate face și în domeniul specificat de constructul let-in, ca în exemplul următor pentru calcularea ariei unui cerc de la o rază:

# fie raza zonei = fie pi = 3 . 14 în rază *. raza *. pi ;; val area : float -> float = < distracție > # zonă 2 . 0 ;; - : plutitor = 12 . 56

În OCaml, legăturile variabilelor sunt imuabile (ca și în ecuațiile matematice), adică valoarea unei variabile este „alocată” o singură dată (atribuire unică). Un alt lucru este că în interiorul let-in poate fi un alt let-in, în care se introduce o altă variabilă, care o poate „umbri” pe prima [9] .

Funcții

Există mai multe constructe de sintaxă pentru definirea funcțiilor în OCaml.

Funcțiile pot fi definite folosind function. Expresia pentru funcție arată astfel [10] :

funcția x -> x + 1

În acest caz, funcția este anonimă și poate fi folosită ca parametri pentru alte funcții sau aplicată unui argument, de exemplu:

( funcția x -> x + 1 ) 5

Tipul acestei funcții este int -> int, adică funcția ia un număr întreg și returnează un număr întreg.

O funcție poate avea mai multe argumente [11] :

funcția ( x , y ) -> x - y

În acest exemplu, tipul său este: int * int -> int, adică intrarea funcției este o pereche , iar rezultatul este un întreg.

Există o altă abordare pentru reprezentarea funcțiilor mai multor argumente - conversia unei funcții N-ary în N funcții ale unui argument - currying . Următoarele două notații pentru o funcție care calculează produsul argumentelor întregi sunt echivalente [11] :

funcția x -> funcția y -> x * y fun x y -> x * y

Funcțiile numite pot fi obținute prin asocierea unei variabile cu o funcție [10] . Definiția unei funcții numite este o operație atât de comună încât are suport sintactic separat. Următoarele trei intrări sunt modalități echivalente de a defini o funcție (într-un shell interactiv):

# let prod = function x -> function y -> x * y ;; val prod : int -> int -> int = < fun > # let prod x y = x * y ;; val prod : int -> int -> int = < fun > # let prod = fun x y -> x * y ;; val prod : int -> int -> int = < distracție >

Funcțiile a două argumente pot fi definite pentru a utiliza notația infixă [10] :

# fie (^^) x y = x ** 2 . 0+ . y ** 2 . 0 ;; val ( ^^ ) : float -> float -> float = < distracție > # 2 . 0 ^^ 3 . 0 ;; - : plutitor = 13 . # (^^) 2 . 0 3 . 0 ;; - : plutitor = 13 .

Acest exemplu definește o funcție (^^)care calculează suma pătratelor a două numere în virgulă mobilă . Ultimele două tipuri de notație sunt echivalente.

Funcțiile recursive , adică funcțiile care se referă la propria lor definiție, pot fi specificate folosind let rec[10] :

# let rec fac n = potrivește n cu | 0 -> 1 | x -> x * fac ( x - 1 ) ;;

În același exemplu de calcul factorial , se aplică potrivirea modelului (construct match-with).

Argumentele funcției pot fi definite ca denumite. Argumentele numite pot fi specificate în orice ordine [10] :

# let divmod ~ x ~ y = ( x / y , x mod y ) ;; val divmod : x : int -> y : int -> int * int = < fun > # divmod ~ x : 4 ~ y : 3 ;; - : int * int = ( 1 , 1 ) # divmod ~ y : 3 ~ x : 4 ;; - : int * int = ( 1 , 1 )

În OCaml, puteți omite valori folosind jocul de etichete dacă numele parametrului și numele variabilei sunt aceleași [  10] :

# fie x = 4 în fie y = 3 în divmod ~ x ~ y ;; - : int * int = ( 1 , 1 )

Expresii

Asociativitatea operațiilor din expresiile OCaml este determinată de prefix, extinzându-se astfel la operațiunile definite de utilizator. Semnul -funcționează atât ca prefix, cât și ca operație de infix, iar dacă este necesar, pentru a fi folosit ca prefix împreună cu funcția, parametrul trebuie inclus între paranteze [12] .

Prefixul operațiunii Asociativitatea
! ? ~ Prefix
. .( .[ .{
aplicarea unei funcții, constructor, etichetă, assert,lazy Stânga
- -. Prefix
** lsl lsr asr Dreapta
* / % mod land lor lxor Stânga
+ - Stânga
:: Dreapta
@ ^ Dreapta
& $ != Stânga
& && Dreapta
or || Dreapta
,
<- := Dreapta
if
; Dreapta
let match fun function try

Sistemul de tipuri

Tipuri primitive

Limbajul OCaml are mai multe tipuri primitive : tipuri numerice ( întregi și virgulă mobilă), caractere , șiruri de caractere , boolean [13] .

Tipul întreg reprezintă numere întregi din intervalul [−2 30 , 2 30 − 1] și [−2 62 , 2 62 − 1] pentru arhitecturile pe 32 de biți și, respectiv, pe 64 de biți. Cu numere întregi, puteți efectua operațiile obișnuite de adunare, scădere, înmulțire, împărțire, luând restul împărțirii :+,-,*,/,mod. Dacă rezultatul depășește intervalul admis, nu apare nicio eroare, iar rezultatul este calculat modulo limita intervalului [14] .

Numerele în virgulă mobilă sunt reprezentate de o mantisă de 53 de bițiși un exponent în intervalul [−1022, 1023], urmând standardul IEEE 754 pentru duble. În operațiuni, aceste numere nu pot fi amestecate cu numere întregi. În plus, operațiile pe numere în virgulă mobilă sunt diferite din punct de vedere sintactic de operațiile cu numere întregi:+.,-.,*.,/.. Există și o operație de exponențiere:**. Pentru a converti numerele întregi în numere în virgulă mobilă și invers, sunt disponibile următoarele funcții: float_of_int și int_of_float [14] .

Pentru numerele cu virgulă mobilă, există și alte funcții matematice: trigonometrice (sin, cos, tan, asin, acos, atan), rotunjire (tavan, floor), exponențială (exp), logaritmică (log, log10), precum și luarea rădăcină pătrată (sqrt) [14] . Există și operații de comparare polimorfă pentru tipuri numerice [14] .

Tipul de caracter  - char - corespunde reprezentării unui caracter cu un cod de la 0 la 255 (primele 128 de caractere sunt identice cu ASCII ). Tip  șir - șir - succesiune de caractere (lungime maximă: 2 24  - 6) [15] . Un exemplu folosind funcția de conversie întreg în șir și operația de concatenare :

# "Exemplu" ^ string_of_int ( 2 ) ;; - : șir = „Exemplu 2”

Tipul boolean are două valori:true(adevărat) șifalse(fals). Operații pe valori booleene: unare not (negație), binare:&&(și),||(sau). Operațiile binare evaluează mai întâi argumentul din stânga, iar argumentul din dreapta numai dacă este necesar [16] .

Valorile booleene se obțin în urma comparațiilor: =(egalitatea structurală), ==(identitatea), <>(negarea egalității structurale), !=(negarea identității), <, >, <=, >=. Pentru tipurile primitive, cu excepția șirurilor de caractere și a numerelor în virgulă mobilă, egalitatea structurală și identitatea coincid, pentru alte tipuri, valorile situate la aceeași adresă în memorie sunt considerate identice, iar în comparație structurală, valorile sunt verificate componentă cu componentă [16] .

În plus, OCaml are o unitate de tip special, care are o singură valoare - ()[16] .

Liste

În OCaml , o listă  este o secvență finită, imuabilă de elemente de același tip, implementată ca o listă legată individual. Următorul exemplu demonstrează sintaxa listei [17] :

# [ 'a' ; 'b' ; 'c' ] ;; - : lista de caractere = [ 'a' ; 'b' ; 'c' ] # 'a' :: ( 'b' :: ( 'c' :: [] )) ;; - : lista de caractere = [ 'a' ; 'b' ; 'c' ] # 'a' :: 'b' :: 'c' :: [] ;; - : lista de caractere = [ 'a' ; 'b' ; 'c' ] # [] ;; - : ' o listă = []

Operația ::vă permite să construiți o listă bazată pe elementul nou și coada listei vechi. În acest caz, lista „veche” nu se modifică:

# Let lst = [ 1 ; 2 ] ;; val lst : int list = [ 1 ; 2 ] # let lst1 = 0 :: lst ;; val lst1 : int list = [ 0 ; 1 ; 2 ] # primul ;; - : int list = [ 1 ; 2 ] # lst1 ;; - : int list = [ 0 ; 1 ; 2 ] Exemplu: calcularea sumei elementelor unei liste

List este unul dintre principalele tipuri de date din OCaml. Următorul exemplu de cod definește o funcție recursivă (rețineți cuvântul cheie rec) care iterează peste elementele unei liste date și returnează suma acestora:

fie rec suma xs = potriviți xs cu | [] -> 0 | x :: xs' -> x + suma xs' #sum[1;2;3;4;5];; - : int = 15

O altă modalitate de a calcula suma este să utilizați funcția de acumulare:

fie suma xs = Listă . fold_left (+ ) 0xs # suma [ 1 ; 2 ; 3 ; 4 ; 5 ];; - : int = 15 Intrări

Înregistrările sunt un element important în sistemul de tip OCaml. O înregistrare este un set de valori stocate împreună, unde fiecare element al înregistrării valorii este accesibil prin numele său, numele câmpului înregistrării. Un exemplu de declarație de tip, legând o înregistrare la o variabilă și accesând un câmp de înregistrare [18] :

# tip utilizator = { login : string ; parola : sir _ nick : șir _ };; # let usr = { login = "utilizatorul meu" ; parola = "secret" ; nick = "aka" ; } ;; val usr : utilizator = { login = "utilizatorul meu" ; parola = "secret" ; nick = "aka" } # usr . Nick ;; - : șir = „aka”

Trebuie remarcat faptul că tipul variabilei usr a fost setat automat de către compilator.

Ca și în cazul altor tipuri, un tip poate fi parametrizat. Alte posibilități de înregistrare [18] :

  • potrivirea modelului (de nerefuzat)
  • jocul de cuvinte în câmpul sintactic al înregistrărilor în cazul în care numele câmpurilor și variabilelor se potrivesc
  • reutilizarea câmpului și dezambiguizarea cu module
  • actualizare funcțională a evidenței
  • câmpuri mutabile
  • fieldslib și înregistrarea câmpului ca obiect de primă clasă
  • iteratoare de câmp
Tip varianta

Un tip de variantă reprezintă date care pot lua diferite forme, definite prin etichete explicite. Următorul exemplu definește un tip pentru culorile de bază [19] :

# tip culoarea_principală = Roșu | verde | albastru ;; # albastru ;; - : main_color = Albastru # ( Roșu , Albastru ) ;; - : main_color * main_color = ( Roșu , Albastru )

În exemplul de mai sus, tipul de variantă este utilizat ca tip enumerat . În OCaml, totuși, tipul de variantă este mai bogat, deoarece pe lângă etichete, vă permite și să specificați date, de exemplu:

# tip color_scheme = RGB din int * int * int | CMYK de float * float * float * float ;; tip color_scheme = RGB din int * int * int | CMYK de float * float * float * float

La definirea funcțiilor, tipul de variante se asociază în mod natural cu potrivirea modelului.

Obiecte

În OCaml, obiectele și tipurile lor sunt complet separate de sistemul de clase . Clasele sunt folosite pentru a construi obiecte și pentru a sprijini moștenirea , dar nu sunt tipuri de obiecte. Obiectele au propriile lor tipuri de obiecte și nu trebuie să folosiți clase pentru a lucra cu obiecte. Obiectele nu sunt folosite la fel de des în OCaml (de exemplu, sistemul de module este mai expresiv decât obiectele, deoarece modulele pot include tipuri, dar clasele și obiectele nu). Principalul avantaj al obiectelor față de înregistrări este că nu necesită declarații de tip și sunt mai flexibile datorită polimorfismului rândurilor .  Pe de altă parte, beneficiile obiectelor intră în joc atunci când se utilizează sistemul de clasă. Spre deosebire de module, clasele acceptă legarea tardivă, ceea ce vă permite să vă referiți la metode obiect fără o implementare definită static și să utilizați recursiunea deschisă (în cazul modulelor, puteți utiliza funcții și functori, dar din punct de vedere sintactic, astfel de descrieri necesită scrierea mai multor cod) [20] ] .

Tip inferență

Deși OCaml este un limbaj de programare puternic tipizat , sistemul de inferență de tip ( în engleză  tip inference ) vă permite să determinați tipul unei expresii pe baza informațiilor disponibile despre componentele sale. În următorul exemplu de funcție de paritate, nu este specificată nicio declarație de tip și totuși compilatorul de limbaj are informații complete despre tipul funcției [21] :

# fie impar x = x mod 2 <> 0 ;; val odd : int -> bool = < distracție >

Programare imperativă și funcții cu efecte secundare

Pe lângă cele funcționale, limbajul conține instrumente de programare imperative : funcții cu efecte secundare , date mutabile, construcții sintactice imperative, în special, bucle while explicite și for[22] .

Următorul exemplu va imprima 11 linii la ieșirea standard (acesta este un efect secundar al funcției printf):

pentru i = 0 la 10 face Printf . printf "i =%d \n " am terminat ;;

În următorul exemplu (mai degrabă artificial), elementele unui tablou sunt incrementate într-o buclă de precondiție. Pentru indexul matricei, este utilizată o referință (ref), care este incrementată în corpul buclei:

# let incr_ar ar = let i = ref 0 în while ! i < matrice . lungime ar do ar .(! i ) <- ar .(! i ) + 1 ; incr am terminat ;; val incr_ar : int array -> unit = < fun > # let nums = [| 1 ; 2 ; 3 ; 4 ; 5 |];; val nums : int array = [| 1 ; 2 ; 3 ; 4 ; 5 |] # incr_ar nums ;; - : unitate = () # numere ;; - : int matrice = [| 2 ; 3 ; 4 ; 5 ; 6 |]

Efectele secundare vă permit să optimizați calculele, mai ales când vine vorba de transformări semnificative pe seturi mari de date. Ele sunt, de asemenea, folosite pentru a implementa evaluarea leneșă și memorarea [22] .

Programare la scară largă

Modularitate

OCaml poate fi gândit ca fiind format din două limbi: un limbaj de bază cu valori și tipuri și un limbaj de module și semnături ale acestora . Aceste limbaje formează două straturi în sensul că modulele pot conține tipuri și valori, în timp ce valorile obișnuite nu pot conține module și module de tip. Cu toate acestea, OCaml oferă un mecanism pentru module de primă clasă , care pot fi valori și pot converti în și din module normale după cum este necesar [23] .

Functorii

Sistemul de module OCaml nu se limitează la organizarea codului modular și interfețele. Unul dintre instrumentele importante ale programării generice sunt functorii . Mai simplu spus, functorii sunt o funcție de la un modul la module, care vă permite să implementați următoarele mecanisme [24] :

  • Injecție de dependență _ _  _
  • Autoextensia modulelor _  _
  • Instanciarea unui  modul cu o anumită stare

Exemple de programe

Lansarea interpretului OCaml

Pentru a porni interpretul de limbaj OCaml, introduceți următoarea comandă în consolă:

$ ocaml OCaml versiunea 4.08.1 #

Calculele se pot face interactiv, de exemplu:

# 1 + 2 * 3 ;; - : int = 7

salut lumea

Următorul program „hello.ml”:

print_endline „Bună lume!” ;;

poate fi compilat fie la bytecode :

$ ocamlc salut.ml -o salut

sau în codul mașinii optimizat :

$ ocamlopt hello.ml -o salut

si a lansat:

$ ./bună ziua Salut Lume! $

Sortare rapidă

Următorul exemplu este un algoritm de sortare rapidă care sortează o listă în ordine crescătoare:

lasă rec qsort = funcția | [] -> [] | pivot :: rest -> let is_less x = x < pivot in let left , right = List . partiția is_less rest în qsort stânga @ [ pivot ] @ qsort right

Secvența Fibonacci

fie rec fib_aux n a b = potrivește n cu | 0 -> a | _ -> fib_aux ( n - 1 ) ( a + b ) a let fib n = fib_aux n 0 1

Vezi și

Note

  1. https://ocaml.org/docs/up-and-running
  2. Istoria OCaml . Preluat la 22 aprilie 2019. Arhivat din original la 1 septembrie 2015.
  3. Minsky, 2011 .
  4. 1 2 3 4 Smith, 2006 , p. 2-3.
  5. Minsky, Madhavapeddy, Hickey, 2013 , De ce OCaml?.
  6. 1 2 3 4 5 6 Minsky, Madhavapeddy, Hickey, 2013 , O scurtă istorie.
  7. 1 2 3 4 Smith, 2006 , p. 3-4.
  8. Chailloux, Manoury, Pagano - Dezvoltarea cu OCaml, 2007 , p. 11-12.
  9. 1 2 3 Minsky, Madhavapeddy, Hickey, 2013 , Variabile.
  10. 1 2 3 4 5 6 Minsky, Madhavapeddy, Hickey, 2013 , Funcții.
  11. 1 2 Chailloux, Manoury, Pagano - Dezvoltarea cu OCaml, 2007 , p. 23.
  12. Manual OCaml: 6.7 Expresii . Data accesului: 6 ianuarie 2015. Arhivat din original la 1 ianuarie 2015.
  13. Chailloux, Manoury, Pagano - Dezvoltarea cu OCaml, 2007 , p. 12.
  14. 1 2 3 4 Chailloux, Manoury, Pagano - Dezvoltarea cu OCaml, 2007 , p. 13.
  15. Chailloux, Manoury, Pagano - Dezvoltarea cu OCaml, 2007 , p. cincisprezece.
  16. 1 2 3 Chailloux, Manoury, Pagano - Dezvoltarea cu OCaml, 2007 , p. 15-16.
  17. Minsky, Madhavapeddy, Hickey, 2013 , List Basics.
  18. 1 2 Minsky, Madhavapeddy, Hickey, 2013 , capitolul 5. Înregistrări.
  19. Minsky, Madhavapeddy, Hickey, 2013 , Capitolul 6. Variante.
  20. Minsky, Madhavapeddy, Hickey, 2013 , Obiecte.
  21. Minsky, Madhavapeddy, Hickey, 2013 , Functions and Type Inference.
  22. 1 2 Minsky, Madhavapeddy, Hickey, 2013 , Imperative Programming.
  23. Minsky, Madhavapeddy, Hickey, 2013 , Module de primă clasă.
  24. Minsky, Madhavapeddy, Hickey, 2013 , Functors.

Literatură

Lista cărților disponibile online
  • Minsky, Y. și Madhavapeddy, A. și Hickey, J. Real World OCaml: Functional Programming for the Masses. - O'Reilly Media, 2013. - 510 p. — ISBN 9781449324766 .
    • Traducere în rusă: Minsky, Yaron; Madhavapeddy, Anil; Hickey, Jason. Programare în OCaml = Real World OCaml: Programare funcțională pentru Masse. - DMK, 2014. - 536 p. — (Programare funcțională). - ISBN 978-5-97060-102-0 .
Important: traducere incorectă în ediția rusă

Notă - Cartea folosește traducerea termenului „ funcție de primă clasă ” ca „ funcție de ordinul întâi ”. Dar trebuie avut în vedere că în numeroase surse în limba engleză (despre semantica limbilor în general și despre ML și Hindley-Milner în special), se disting conceptual patru concepte:

  • clasa întâi,
  • clasa a doua,
  • prima comanda,
  • ordine superioară,

în plus, „ prima clasă ” este „ mai bună ” decât „ clasa a doua ” (mai larg ca capabilități, mai aproape de teorie și mai mare în ceea ce privește pragul de intrare ( C. Strachey — Fundamental Concepts in Programming Languages ​​)), dar „ de ordinul întâi „mai primitiv decât „ de ordin înalt ”. În special, extinderea limbajului modulului ML la nivelul de primă clasă prezintă o problemă mult mai mare pentru cercetători decât extinderea lui doar la „ de primă clasă ” sau doar la „ de ordin înalt ” ( Rosberg A. Functors și runtime vs compile time (downlink) Preluat la 25 iunie 2015. Arhivat din original pe 26 iunie 2015  ).

Link -uri