Skip to content
Bart Jacobs edited this page Feb 14, 2018 · 41 revisions

beOI'18-krokuscursus

In deze cursus gaan we de programmeertaal OCaml gebruiken. (F# is een uitbreiding van OCaml.)

We gaan de online programmeeromgeving Ocsigen gebruiken.

Waarden en bewerkingen

OCaml ondersteunt verschillende soorten waarden.

Opdracht:

  • Tik 2 + 2 in.
  • OCaml antwoordt met - : int = 4. OCaml geeft aan dat de opgegeven uitdrukking van het type int is (het type van de gehele getallen, integers in het Engels) en evalueert tot de waarde 4.

Opdracht:

  • Tik "Hello, " ^ "world!" in.
  • OCaml antwoordt met - : string = "Hello, world!". De opgegeven uitdrukking is van het type string (het type van de stukken tekst) en evalueert tot de waarde "Hello, world!". Het bewerkingsteken ^ dient om stukken tekst aan elkaar te plakken (string concatenation in het Engels).

Opdracht:

  • Tik 1 / 2 in.
  • OCaml antwoordt met - : int = 0. Het bewerkingsteken / staat voor gehele deling.

Opdracht:

  • Tik 1.0 /. 2.0 in.
  • OCaml antwoordt met - : float = 0.5. De opgegeven uitdrukking is van het type float (het type van de vlottende-kommagetallen, floating-point numbers in het Engels). Het bewerkingsteken /. staat voor reële deling.

Opdracht:

  • Tik 1 /. 2 in.
  • OCaml onderlijnt de uitdrukking 1 in het rood en zegt erover Error: This expression has type int but an expression was expected of type float. OCaml is heel streng qua het correct gebruik van types: de reële deling mag enkel gebruikt worden met kommagetallen, en de gehele deling enkel met gehele getallen.

Opdracht:

  • Tik 1 < 2 in.
  • OCaml antwoordt met - : bool = true. De ongelijkheid is waar (true in Engels). true en false zijn de waarheidswaarden, ook Booleaanse waarden genoemd. Ze zijn van het type bool.

Opdracht:

  • Tik true && false in.
  • OCaml antwoordt met - : bool = false. Het bewerkingsteken && staat voor de logische EN-operatie.

Andere opdrachten zijn: aftrekking - en vermenigvuldiging * van gehele getallen, optelling +., aftrekking -., en vermenigvuldiging *. van kommagetallen, en de logische OF-operatie || op Booleaanse waarden.

Variabelen

Opdracht:

  • Tik let x = 3 in.
  • Tik dan x + 5 in.
  • OCaml antwoordt met - : int = 8. De opdracht let x = 3 bindt de waarde 3 aan de variabele x.

Functies

Opdracht:

  • Tik let f x = x + 1 in.
  • Tik dan f 3 in.
  • OCaml antwoordt met - : int = 4. De opdracht let f x = x + 1 definieert de functie f met parameter x en lichaam x + 1. De uitdrukking f 3 staat voor de toepassing van de functie f op het argument 3. De waarde van zo'n functietoepassing is de waarde van het lichaam van de functie, waarbij de parameter gebonden wordt aan het opgegeven argument. Dus, de waarde van f 3 is de waarde van x + 1 waarbij x gebonden wordt aan 3.

Oefening:

  • Definieer een functie begroeting zodanig dat begroeting "Jan" evalueert tot "Hallo, Jan!" en begroeting "Piet" evalueert tot "Hallo, Piet!".

Oefening:

  • Definieer een functie positief zodanig dat positief 1 en positief 10 evalueren tot true en positief 0 en positief (-7) tot false.

Opdracht:

  • Tik let dubbel x = x + x in.
  • Tik dan dubbel 5 in.
  • OCaml antwoordt met - : int = 10.

Opdracht:

  • Tik let viervoud y = dubbel y + dubbel y in.
  • Tik dan viervoud 7 in.
  • OCaml antwoordt met - : int = 28. Je kan een functie gebruiken in het lichaam van een andere functie.

Oefening:

  • Definieer de functie citeer, zodanig dat citeer "Hallo" evalueert tot "'Hallo'".

Opdracht:

  • Tik let spreuk x = citeer x ^ ", dat is de vraag." in.
  • Tik dan spreuk "Zijn of niet zijn?" in.
  • OCaml antwoordt met - : string = "'Zijn of niet zijn?', dat is de vraag.".

Opdracht:

  • Tik let f x y = x + y in.
  • Tik dan f 10 30 in.
  • OCaml antwoordt met - : int = 40. Functies kunnen meerdere parameters hebben. Je scheidt ze gewoon met een spatie.
  • Tik dan f 100 (f 10 30) in.
  • OCaml antwoordt met - : int = 140. Je moet haakjes gebruiken als je een complexe uitdrukking wilt gebruiken als argument voor een functie-oproep.

Opdracht:

  • Tik let volledige_naam voornaam achternaam = voornaam ^ " " ^ achternaam in.
  • Tik dan volledige_naam "Jan" "Janssens" in.
  • OCaml antwoordt met "Jan Janssens".
  • Tik dan volledige_naam "Piet" "Pieters" in.
  • OCaml antwoordt met "Piet Pieters".

Opdracht:

  • Tik let adres naam straat nummer postcode gemeente = naam ^ ", " ^ straat ^ " " ^ nummer ^ ", " ^ postcode ^ " " ^ gemeente in.
  • Tik dan let adres2 voornaam achternaam straat nummer postcode gemeente = adres (volledige_naam voornaam achternaam) straat nummer postcode gemeente in.
  • Tik dan adres2 "Jan" "Janssens" "Dorpsstraat" "10" "1000" "Brussel" in.
  • OCaml antwoordt met "Jan Janssens, Dorpsstraat 10, 1000 Brussel".

Oefening:

  • Definieer een functie gemiddelde zodanig dat gemiddelde 10 20 evalueert tot 15 en gemiddelde 3 7 evalueert tot 5.

Oefening:

  • Definieer een functie tussen zodanig dat tussen x y z evalueert tot true als en slechts als y tussen x en z ligt.

Recursieve functies

Opdracht:

  • Tik let rec macht x n = if n = 0 then 1 else x * macht x (n - 1) in.
  • Tik dan macht 2 3 in.
  • OCaml antwoordt met - : int = 8. Je kan een functie toepassen in haar eigen lichaam, op voorwaarde dat je de let rec-opdracht gebruikt in plaats van de let-opdracht. Zo'n functie noemen we een recursieve functie.

Je kan de evaluatie van deze functie begrijpen als volgt:

macht 2 3
= if 3 = 0 then 1 else 2 * macht 2 (3 - 1)                       (definitie van macht)
= 2 * macht 2 2                                                  (vereenvoudiging)
= 2 * (if 2 = 0 then 1 else 2 * macht 2 (2 - 1))                 (definitie van macht)
= 2 * (2 * macht 2 1)                                            (vereenvoudiging)
= 2 * (2 * (if 1 = 0 then 1 else 2 * macht 2 (1 - 1)))           (definitie van macht)
= 2 * (2 * (2 * macht 2 0))                                      (vereenvoudiging)
= 2 * (2 * (2 * (if 0 = 0 then 1 else 2 * macht 2 (0 - 1))))     (definitie van macht)
= 2 * (2 * (2 * 1))                                              (vereenvoudiging)
= 8                                                              (vereenvoudiging)

Opdracht:

  • Tik let sterren_0 = "" in.
  • OCaml antwoordt met sterren_0 : string = "".
  • Tik let sterren_1 = "*" ^ sterren_0 in.
  • OCaml antwoordt met sterren_1 : string = "*".
  • Tik let sterren_2 = "*" ^ sterren_1 in.
  • OCaml antwoordt met sterren_2 : string = "**".
  • Tik let sterren_3 = "*" ^ sterren_2 in.
  • OCaml antwoordt met sterren_3 : string = "***".

Oefening:

  • Definieer de functie sterren zodanig dat sterren 3 evalueert tot "***" en sterren 5 evalueert tot "*****".

Samengestelde waarden

Opdracht:

  • Tik [10; 20; 30; 40] in.
  • OCaml antwoordt met - : int list = [10; 20; 30; 40]. Het type int list is het type van lijsten van gehele getallen.

Opdracht:

  • Tik 10::20::30::40::[] in.
  • OCaml antwoordt met - : int list = [10; 20; 30; 40]. De uitdrukking e::l betekent: de lijst bestaande uit het element e gevolgd door de lijst l. Het eerste element van een (niet-lege) lijst noemen we het hoofd en de elementen ná het eerste element de staart. De uitdrukking e::l betekent dus: de lijst met hoofd e en staart l.

Opdracht:

  • Tik let aftelling_0 = [0] in.
  • OCaml antwoordt met aftelling_0 : int list = [0].
  • Tik let aftelling_1 = 1::aftelling_0 in.
  • OCaml antwoordt met aftelling_1 : int list = [1; 0].
  • Tik let aftelling_2 = 2::aftelling_1 in.
  • OCaml antwoordt met aftelling_2 : int list = [2; 1; 0].
  • Tik let aftelling_3 = 3::aftelling_2 in.
  • OCaml antwoordt met aftelling_3 : int list = [3; 2; 1; 0].

Oefening:

  • Definieer een functie aftelling zodanig dat aftelling 2 evalueert tot [2; 1; 0] en aftelling 4 evalueert tot [4; 3; 2; 1; 0].

Opdracht:

  • Tik let leeg xs = match xs with [] -> true | hoofd::staart -> false in.
  • Tik dan leeg [] in.
  • OCaml antwoordt met - : bool = true.
  • Tik dan leeg [10] in.
  • OCaml antwoordt met - : bool = false. Je kan een match-uitdrukking gebruiken om verschillende berekeningen te doen afhankelijk van de vorm van een lijst. Meer bepaald: de uitdrukking match xs with [] -> U1 | hoofd::staart -> U2 evalueert tot de waarde van U1 als xs een lege lijst is, en tot de waarde van U2, waarbij hoofd gebonden wordt aan het hoofd (eerste element) van xs en staart aan de staart van xs (de lijst die je krijgt door het eerste element van xs weg te laten), als xs niet leeg is.

Opdracht:

  • Tik let som_eerste_twee xs = match xs with eerste::tweede::_ -> eerste + tweede in.
  • Tik dan som_eerste_twee [10; 20; 30] in.
  • OCaml antwoordt met - : int = 30.
  • Tik dan som_eerste_twee [10] in.
  • OCaml antwoordt met Exception: Match_failure. Als je in een match-uitdrukking niet alle gevallen behandelt, krijg je een waarschuwing. Als je dan de uitdrukking evalueert voor een geval dat niet behandeld wordt, krijg je een uitzondering (exception in het Engels).

Opdracht:

  • Tik let hoofd_van xs = match xs with hoofd::staart -> hoofd in.
  • Tik dan hoofd_van [1;2;3] in.
  • OCaml antwoordt met - : int = 1.
  • Tik dan hoofd_van [10;20] in.
  • OCaml antwoordt met - : int = 10.

Opdracht:

  • Tik let staart_van xs = match xs with hoofd::staart -> staart in.
  • Tik dan staart_van [1;2;3] in.
  • OCaml antwoordt met - : int list = [2;3].
  • Tik dan staart_van [10;20] in.
  • OCaml antwoordt met - : int list = [20].

Oefening:

  • Definieer een functie lengte zodanig dat lengte [true; false] evalueert tot 2 en lengte ["Hallo"] evalueert tot 1 en lengte [1.0; 2.0; 3.0] evalueert tot 3.

Merk op:

lengte ["a"; "b"; "c"]
= lengte ("a"::"b"::"c"::[])
= lengte ("a"::("b"::("c"::[])))
= 1 + lengte ("b"::("c"::[]))
= 1 + (1 + lengte ("c"::[]))
= 1 + (1 + (1 + lengte []))
= 1 + (1 + (1 + 0))
= 3

Oefening:

  • Definieer een functie som zodanig dat som [1; 2; 3] evalueert tot 6 en som [7; 3; 11] evalueert tot 21.

Oefening:

  • Definieer een functie filter_pos zodanig dat filter_pos [10; -3; 5] evalueert tot [10; 5] en filter_pos [-7; 0; 8] evalueert tot [8].

Oefening:

  • Definieer een functie negatie zodanig dat negatie [10; -20] evalueert tot [-10; 20].

Oefening:

  • Definieer een functie aan_elkaar zodanig dat aan_elkaar [1; 2] [3; 4] evalueert tot [1; 2; 3; 4].

Oefening:

  • Definieer een functie alles_aan_elkaar zodanig dat alles_aan_elkaar [[10; 20]; [30; 40]; [50]] evalueert tot [10; 20; 30; 40; 50].

Oefening:

  • Definieer een functie voeg_in die, gegeven een geheel getal en een gesorteerde lijst van gehele getallen, de gesorteerde lijst berekent die je bekomt als je het element op de juiste plaats invoegt in de gegeven gesorteerde lijst.

Oefening:

  • Definieer een functie sorteer zodanig dat sorteer [3; 1; 2] evalueert tot [1; 2; 3]. Hint: gebruik de functie voeg_in.

Tuples

Opdracht:

  • Tik ("Jan", 14) in.
  • OCaml antwoordt met - : string * int = ("Jan", 14). Dit is een tuple (een geordend n-tal) bestaande uit een stuk tekst en een geheel getal.
  • Tik let (naam, leeftijd) = ("Jan", 14) in.
  • OCaml antwoordt met naam : string = "Jan" en leeftijd : int = 14.

Oefening:

  • Definieer een functie splits zodanig dat splits [1;2;3;4;5] evalueert tot ([1;3;5], [2;4]), en splits [2;3;4;5;6] evalueert tot ([2;4;6], [3;5]).

Oefening:

  • Definieer een functie merge_sort die een gegeven lijst sorteert door ze eerst te splitsen in twee ongeveer even grote deel-lijsten, door middel van de functie splits, en dan beide deel-lijsten te sorteren.

Associatielijsten

Oefening:

  • Definieer een functie zoek_op, zodanig dat zoek_op "Jan" [("Piet", 14); ("Jan", 16)] evalueert tot 16.

Oefening:

  • Definieer een functie verwijder_associatie, zodanig dat verwijder_associatie "Jan" [("Piet", 14); ("Jan", 16)] evalueert tot [("Piet", 14)].

Arrays

Opdracht:

  • Tik [| 1; 2; 3; 4 |] in.
  • OCaml antwoordt met - : int array = [| 1; 2; 3; 4 |].
  • Tik let xs = [| 1; 2; 3; 4 |] in.
  • Tik dan xs.(0) in.
  • OCaml antwoordt met - : int = 1. Arrays zijn zoals lijsten, behalve dat sommige operaties een andere performantie hebben. Het ophalen van het N-de element gebeurt bij arrays in constante tijd, terwijl de tijd die hiervoor nodig is bij lijsten lineair is in het aantal elementen van de lijst.
  • Tik dan Array.length xs in.
  • OCaml antwoordt met - : int = 4.

Oefening:

  • Definieer de functie positie_van, die, gegeven een getal en een gesorteerde array, de positie van dit getal in de array teruggeeft, ofwel de positie waar dit getal ingevoegd mag worden zodat de array gesorteerd blijft. Bijvoorbeeld: positie_van 4 [| 3; 4; 5 |] evalueert tot 1, en positie_van [| 2; 4; 6 |] 5 evalueert tot 2. Definieer de functie zó dat ze slechts een aantal opzoekingen doet van elementen in de array dat logaritmisch is in de lengte van de array. Dus: in een array van lengte 32 mag je slechts 5 opzoekingen doen.

Wijzigen van array-elementen

Opdracht:

  • Tik let xs = [| 0 |] in.
  • Tik dan xs.(0) <- 3 in.
  • Tik dan xs.(0) in.
  • OCaml antwoordt met - : int = 3.

Oefening:

  • Definieer een functie sorteer die, gegeven een array, de elementen van deze array verplaatst zodat de array gesorteerd wordt.
Clone this wiki locally