Start to program – Programmeertalen

print

Inhoud


Over bits en bytes

Elektronica is in zijn essentie een verhaal van: er is stroom of er is geen stroom. Er zijn maar 2 mogelijkheden. We spreken van een binair (of tweetallig/tweeledig) stelsel.

De computer kent in zijn essentie dus ook enkel de binaire waarden 0 en 1 (aan of uit, stroom of geen stroom, een puntje gebrand op de CD of niet, …). Alle data die opgeslagen is, alle informatie die doorgestuurd wordt, is dus in zijn essentie een stroom van 0-en en 1-en.

Een 0 of een 1 wordt een bit genoemd. Een verzameling van 8 bits wordt een byte genoemd.

Waarden worden gecombineerd in een veelvoud van 8 bits m.a.w. in een veelvoud van bytes.

Bijvoorbeeld, het getal 13 wordt als volgt opgeslagen: 00001101

Hoe komen we nu aan die 00001101?

Wel, bekijk onderstaande tabel van rechts naar links. Op de tweede rij ziet u machten van 2. Waarom 2? Wel, omdat, zoals we net gezien hebben, de computer maar 2 waarden kent 0 en 1.

De machten van 2 zijn:

2^0 = 1
2^1 = 2
2^2 = 2 x 2 = 4
2^3 = 2 x 2 x 2 = 8
2^4 = 2 x 2 x 2x 2 = 16
2^5 = 2 x 2 x 2 x 2 x 2 = 32
2^6 = 2 x 2 x 2 x 2 x 2 x 2 = 64
2^7 = 2 x 2 x 2 x 2 x 2 x 2 x 2 = 128

0 0 0 0 1 1 0 1
128 64 32 16 8 4 2 1

Om nu aan de waarde 13 te komen moeten we (1 x 8) + (1 x 4) + (1 x 1) optellen. Dit is de enige combinatie die 13 als resultaat levert. We zetten dus een 1 bij de overeenkomende waarden van 8, 4 en 1 en laten op de andere posities de waarde 0 staan. Dit levert dus 00001101 op als binaire waarde voor het getal 13.

Als we getallen opslaan in een combinatie van maximaal 8 bits zullen we enkel de getallen van 0 (00000000) tot en met 255 (11111111) kunnen opslaan, of een totaal van 256 waarden.

Getallen hoger dan 255

Willen we grotere getallen dan 255 opslaan dan zullen we een veelvoud van 8 bits (een byte) moeten gebruiken. Door bv. 16 bits (2 bytes) te voorzien kunnen we getallen tussen 0 en 65535 (2^16) opslaan.

Negatieve getallen

Willen we negatieve getallen opslaan dan wordt de meest linkse bit gebruikt om het teken (0 voor – en 1 voor +) op te slaan. Mits we dus 1 bit “kwijt” zijn voor het teken betekent dit dat we 1 bit minder hebben voor het eigenlijke getal. We behouden wel de 256 combinaties.

Voorzien we 8 bits en gebruiken we de meest linkse bit om het teken bij te houden dan zullen de getallen die we kunnen opslaan liggen tussen -128 tot 127.

Decimale getallen

Om decimale getallen op te slaan moet ook de positie van de komma opgeslagen worden in de beschikbare bits.

Tekens

Tekens worden ook opgeslagen als een combinatie van bits. Welk teken met welke combinatie overeenkomt is vastgelegd in tabellen, bv. de ASCII tabel.

Bv. A = 65 = 1000001

Een A wordt dus opgeslagen als 1000001.

Omdat de ASCII-tabel slechts 7 bits gebruikt om tekens op te slaan zijn er maar 128 (27) combinaties mogelijk.

Er zijn dus andere karaktersets nodig die meer dan 128 tekens kunnen opnemen. HTML, JavaScript, PHP, ASP,… maken gebruik van Unicode. De eerste 128 tekens uit de Unicode-karakterset zijn dezelfde als de 128 tekens uit de ANSI-tabel.

Afbeeldingen, muziek,…

Ook afbeeldingen, muziek,… worden elk op hun eigen specifieke manier opgeslagen als een combinatie van 0-en en 1-en.

Zo worden afbeeldingen bv. opgeslagen als een combinatie van punten, waarbij ieder punt uit 32bits bestaat. 8 bits voor Rood, 8 bits voor Groen, 8 bits voor Blauw en 8 bits voor andere informatie als bv. de transparantie.

In onderstaande video legt de oprichter van Instagram uit hoe afbeeldingen opgeslagen worden als bits en hoe filters worden toegepast op afbeeldingen door een berekening uit te voeren op deze bits.


Waarom bestaan programmeertalen?

Eigenlijk is de reden heel simpel:

001011101000100011110100111001110011001110000011010101010101110010100110110011111100010001010011000011100011111000010010011000110011100111010010101011110110001100100001101011100000111001010000010101111101000001111101001011111000000111111100101001101010101011111010101

Hebt u enig idee wat ik juist gezegd heb?

Nee? Troost u, ik ook niet. Ik spreek immers geen “computertaal”, geen “binairs”.

Dus waarom bestaan programmeertalen? Heel eenvoudig, om ons, de mens, de programmeur, in staat te stellen instructies te geven aan de computer.

Een programmeertaal is een formele taal waarin de instructies die een computer moet uitvoeren, worden geschreven.

Deze talen hebben een andere syntaxis en grammatica dan natuurlijke talen. Natuurlijke talen zijn te complex en ambigu (dubbelzinning) om als programmeertaal te fungeren.

Code die in een programmeertaal geschreven is, dient maar op één manier te kunnen worden “begrepen” door de computer. Een programmeertaal moet dus:

  • Ondubbelzinnige instructies geven aan de computer.
  • Eenvoudig leesbaar en “schrijfbaar” zijn voor de programmeur.

Voorbeeld: hoe worden waarden weergegeven?

We hebben net gezien dat:

  • 01000001 het getal 65 kan betekenen.
  • 01000001 het teken A kan betekenen.

Hoe laten we nu, als programmeurs, de computer weten of we een 65 of een A bedoelen? Hoe bepalen we dus ondubbelzinnig de eigenlijke waarde van 01000001?

Wel, door de specifieke syntax van de programmeertaal te gebruiken om de gewenste waarde aan te duiden.

Eigenlijk is het simpel. In de meeste programmeertalen doen we dit als volgt:

Het getal 65 geven we in als: 65.
De hoofdletter A geven we in als een string (tussen “” of ”): “A”.
Willen we 65,0 als een decimaal getal gebruiken dan geven we het in als een decimaal getal waarbij we een punt gebruiken voor de positie van het decimaal teken: 65.0.

De programmeertaal interpreteert dit correct als een getal, een teken of een decimaal getal of de programmeur help een handje door een passend datatype te definiëren voor de waarde.

Een vaste waarde wordt ook een Literal genoemd.

Indien u een getalwaarde tussen quotes plaatst “65” wordt deze waarde niet beschouwd als een getal maar als tekst. U zal dus geen berekeningen kunnen maken met de tekstwaarde “65”.


Korte geschiedenis van het programmeren

Het is mogelijk om computers direct in hun eigen machinetaal te programmeren: direct de éénen en nullen te typen die door de processor kunnen worden begrepen. Dit was voor de eerste computers gebruikelijk, met schakelaartjes werden groepen van 8 bits ingesteld en gegevens werden opgeslagen door gaatjes te maken in ponskaarten (Nog niet zo heel lang geleden werden deze nog in de Colruyt gebruikt en moest u bij de aankoop van een product de overeenkomende ponskaart meenemen naar de kassa).

Men ondervond echter snel dat het veel te lastig was om programma’s die op die manier waren geschreven te onderhouden. Snel werd er een symbolische manier bedacht om de machine-instructies als tekst weer te geven in de vorm van mnemonics, een woord of symbool dat dient ter vervanging van een binaire (0 of 1) instructie. Zo werd het mogelijk om instructies veel eenvoudiger te lezen. Deze code noemt men assembler.

Voor het programmeren van assembler en machinetaal moet de programmeur heel veel weten van de computer die hij wil programmeren. Om programmeren gemakkelijker te maken zijn daarna andere programmeertalen, de zogenaamde hogere programmeertalen ontwikkeld. Hoe hoger de orde, hoe verder de taal van de machine-instructies af staat en hoe dichter hij aansluit bij het denken van de mens.

Programmeertalen worden onderverdeeld in generaties:

  • Eerste generatie: machinetaal.
  • Tweede generatie: Assembler (de kale machine-instructies, maar, een beetje, leesbaarder).
  • Derde generatie: gestructureerde programmeertalen als COBOL, Algol, C en Fortran, en later ook objectgeoriënteerde talen zoals C++, Java, C# en VB.NET.
  • Vierde generatie: talen met een hoger abstractieniveau die voor een bepaald doel zijn ontwikkeld, zoals SQL. Deze talen kenmerken zich vaak door hun leesbaarheid.
  • Vijfde generatie: probleemoplossende talen. Hierbij specificeert de programmeur geen algoritme maar het probleem zelf, met een aantal bijbehorende beperkingen. Vijfde generatie-talen worden vooral gebruikt op het gebied van kunstmatige intelligentie. Het bekendste voorbeeld is Prolog.

Voorbeelden

Hieronder ziet u het beroemde “Hello World”, een eenvoudig programmaatje dat de tekst “Hello World” op het scherm laat verschijnen in een aantal populaire programmeertalen in de volgorde van hun verschijnen.

Programmeertalen
“Hello World” in Assembler.

section     .text
global      _start                              
 
_start:                                         
 
    mov     edx,len                             
    mov     ecx,msg                             
    mov     ebx,1                               
    mov     eax,4                               
    int     0x80                                
 
    mov     eax,1                               
    int     0x80                                
 
section     .data
 
msg     db  'Hello, world!',0xa                 
len     equ $ - msg                             

“Hello World” in Cobol 85.

000100 IDENTIFICATION DIVISION.
000200 PROGRAM-ID.     HELLOWORLD.
000300
000400*
000500 ENVIRONMENT DIVISION.
000600 CONFIGURATION SECTION.
000700 SOURCE-COMPUTER. RM-COBOL.
000800 OBJECT-COMPUTER. RM-COBOL.
000900
001000 DATA DIVISION.
001100 FILE SECTION.
001200
100000 PROCEDURE DIVISION.
100100
100200 MAIN-LOGIC SECTION.
100300 BEGIN.
100400     DISPLAY " " LINE 1 POSITION 1 ERASE EOS.
100500     DISPLAY "Hello world!" LINE 15 POSITION 10.
100600     STOP RUN.
100700 MAIN-LOGIC-EXIT.
100800 EXIT.

“Hello World” in Cobol 2002.

 PROGRAM-ID.     HELLOWORLD.
 DATE-WRITTEN.   10/18/12 12:50.
 AUTHOR.         UNKNOWN AUTHOR.
 
 PROCEDURE DIVISION.
   DISPLAY "Hello world"
   STOP RUN.

“Hello World” in C.

 #include <stdio.h>
 
 int main(void)
 {
   printf("Hello world\n");
   return 0;
 }

“Hello World” in C++.

 #include <iostream>
 using namespace std;
 
 int main()
 {
   cout << "Hello world" << endl;
   return 0;
 }

“Hello World” in C#.

 class HelloWorld {
 	static void Main() {
 		System.Console.WriteLine("Hello world");
 	}
 }

“Hello World” in Java.

class HelloWorldApp {
    public static void main(String[] args) {
        System.out.println("Hello World!"); 
    }
}

“Hello World” in JavaScript.

document.write('Hello world');

“Hello World” in Scala.

object HelloWorld {
  def main(args: Array[String]): Unit = {
    println("Hello, world!")
  }
}

“Hello World” in Python.

print("Hello world")

Hebt u er nog niet genoeg van, zeg dan hallo in vele talen.

Programmmeertaal

A programming language is an artificial language that a computer understands. The language is made up of series of statements that fit together to form instructions. These instructions tell a computer what to do.


Programmeerparadigma’s

U kent, voor iemand die net van start gegaan is met het leren programmeren, op dit ogenblik nog te weinig van programmeren om een volledig inzicht te verwerven in programmeerparadigma’s. In dit hoofdstukje zullen ook termen gebruikt worden die nog niet uitgelegd zijn en waarmee u wellicht nog niet vertrouwd bent. Desalniettemin is dit de geschikte plek om een paar belangrijke programmeerparadigma’s even kort te bespreken. Om het toch nog niet te technisch te maken ga ik me bezondigen aan een aantal vereenvoudigingen.

Ik neem het u dan ook niet kwalijk als u dit hoofdstukje (voorlopig) zou overslaan. Ik zou zeggen, lees het nu al eens door en herlees het op het einde van de cursus en veel van wat nu nog onduidelijk is zal dan, hopelijk, veel duidelijker zijn.

Voor zij die verder lezen, laten we beginnen met het woordje paradigma te duiden. Een paradigma is een model, een patroon, een wijze van aanpak.

In de informatica zijn programmeerparadigma’s denkpatronen of uitgesproken concepten van programmeren, die voornamelijk verschillen in de wijze van aanpak om het gewenste resultaat te kunnen behalen.

Een aantal bekende programmeerparadigma zijn:

Imperatief programmeren

Bij imperatief programmeren wordt van boven naar beneden, eerst de eerste instructie, dan de tweede instructie, dan de derde,… uitgevoerd. Het programma volgt stap voor stap, lijn per lijn de instructies. Eventueel kunnen sprongen gemaakt worden met de GOTO-instructie waarbij gesprongen wordt naar een bepaalde regel om dan vanaf die regel weer instructie per instructie uit te voeren (spaghetticode). Instructies die steeds samen moeten worden uitgevoerd kunnen gegroepeerd worden in een subroutine.

Imperatief programmeren vertelt de computer hoe hij stap voor stap instructies moet uitvoeren om het gewenste doel te bereiken. Het gebruikt een opeenvolging van statements (instructies) die elk op zich de staat van het programma een beetje wijzigen (“do modify state”). Het imperatief paradigma sluit het best aan bij de computer architectuur.

Voorbeeld van een imperatieve programmeertaal: Assembler.

“Hello World” in Assembler.

section     .text
global      _start                              
 
_start:                                         
 
    mov     edx,len                             
    mov     ecx,msg                             
    mov     ebx,1                               
    mov     eax,4                               
    int     0x80                                
 
    mov     eax,1                               
    int     0x80                                
 
section     .data
 
msg     db  'Hello, world!',0xa                 
len     equ $ - msg                             

Procedureel programmeren

Procedureel programmeren is een type van imperatief programmeren en beiden worden vaak als synoniemen gezien. Er is echter een heel belangrijk verschil. Bij procedureel programmeren is de GOTO-instructie uit de boze! Er wordt gestructureerd geprogrammeerd door gebruik te maken van procedures (ook wel modules, subroutines of functies genoemd) en van gestructureerde “blokken” zoals if, while en for die het verloop van het programma controleren (control flow).

Twee belangrijke kenmerken zijn:

  • modulariteit: procedureel programmeren nodigt uit om een, groot, complex programma op te delen in kleinere modules (procedures/functies). Deze modules kunnen vanuit andere modules worden aangeroepen, kunnen waarden (parameters) meekrijgen waarmee ze kunnen werken en kunnen een “berekend” resultaat teruggeven.
  • scoping: scoping verhindert dat een module (procedure/functie) variabelen in een andere module (procedure/functie) kan aanspreken. De scope van een variabele is immers beperkt tot de module (procedure/functie) waarin de variabele is gedeclareerd.

Voorbeelden van procedurele programmeertalen zijn: COBOL, Fortran, BASIC, Pascal, C,… U ziet, heel wat populaire talen uit de jaren 70, 80 en begin jaren 90 van de vorige eeuw.

“Hello World” in C.

 #include <stdio.h>
 
 int main(void)
 {
   printf("Hello world\n");
   return 0;
 }

Objectgeoriënteerd programmeren

Bij objectgeoriënteerd programmeren, vaak afgekort tot OO, als afkorting voor het Engelse Object-oriented, wordt een systeem opgebouwd uit objecten en wordt geprogrammeerd via interactie met deze objecten.

Rondom ons zien we overal objecten: een auto, een stoel, een student,… Bij objectgeoriënteerd programmeren staan objecten centraal. Een object heeft eigenschappen/attributen (properties) zoals de kleur, de breedte, de hoogte,… Een object heeft ook methoden (methods), functies die berekeningen, bewerkingen, acties, uitvoeren op/met de eigenschappen van het object.

Bijvoorbeeld, het object student kan de eigenschappen Voornaam en Familienaam hebben en een methode VolledigeNaam die de Voornaam en Familienaam tezamen weergeeft.

Een object is concreet. Het object StudentX verwijst specifiek naar die bepaalde student X met die bepaalde eigenschappen (Naam, Voornaam,…). Als we abstractie nemen van die specifieke student en we het hebben over de studenten (in het algemeen) dan spreken we over een klasse/Class (van studenten). Het is in de klasse dat al de mogelijke eigenschappen en methoden worden gedefinieerd en geprogrammeerd.

De klasse is de blauwdruk voor elk object van die klasse. Een specifiek, concreet object is dus altijd een instantie van een bepaalde klasse. Bijvoorbeeld: de specifieke tafel, een object, waaraan u nu zit is een instantie van de klasse tafel.

De eigenschappen leggen de vorm vast van de objecten die tot de klasse behoren. Bijvoorbeeld, een klasse die een cirkel representeert kan bijvoorbeeld een eigenschap straal en een eigenschap locatie hebben. De methoden bepalen alle potentiële gedragingen van de objecten. Een cirkelklasse kan bijvoorbeeld methoden hebben om de oppervlakte en de omtrek van de cirkel te berekenen.

Een object bestaat uit eigenschappen en de methoden die gebruikt wordt om met die eigenschappen te werken. Bij voorkeur zijn de eigenschappen uitsluitend te benaderen via de bijbehorende methoden. De eigenschappen en methoden van een object bevinden zich tezamen in een klasse. Om een object te concretiseren wordt een instantie genomen van de klasse van het gewenste object.

Objectgeoriënteerd programmeren biedt niet de mogelijkheid om een nieuw soort toepassingen te implementeren. Het dient uitsluitend om programma’s beter te structureren, met het oog op de overzichtelijkheid en herbruikbaarheid van componenten. Een objectgeörienteerde programmeertaal gaat dus een stapje verder dan een gestructureerde/procedurele programmeertaal waarmee het verwant is en is dus eveneens een imperatieve programmeertaal.

Belangrijke kenmerken van objectgeoriënteerd programmeren zijn:

  • Inkapseling: het kunnen verbergen van de interne werking van objecten, waardoor op een hoger niveau geprogrammeerd kan worden. Doordat een klasse de toegang tot eigenschappen/attributen en methoden voor gebruik buiten de klasse kan limiteren, hoeft een programmeur niet na te denken over de interne werking van de klasse.Bijvoorbeeld, een cirkelklasse kan zijn eigenschap/propertie diameter niet publiekelijk maken maar de verschillende methoden om de oppervlakte op te vragen of de diameter te veranderen wel. De cirkelklasse zou dan eenvoudig aangepast kunnen worden om toch, in plaats van de diameter, intern de straal op te slaan, zonder dat de gebruiker van de cirkelklasse dit hoeft te weten, de publiekelijke toegang tot de klasse is immers niet veranderd. De gebruiker heeft geen weet, en hoeft ook niet te weten, dat er in de klasse zelf iets veranderd is. Dit begrip wordt inkapselen (encapsulatie) genoemd.
  • Overerving: overerving laat toe varianten van klassen te maken. We spreken dan van basis- en specifiekere klassen. In sommige situaties kan de basisklasse aangeven welke operaties mogelijk zijn op een object, terwijl een specifieke klasse een specifieke implementatie van de operatie geeft door specifieke eigenschappen en/of methoden toe te voegen.Bijvoorbeeld, er kan een basisklasse Dier gemaakt worden, die als basis kan dienen voor klassen Hondachtigen en Katachtigen. De klassen Hondachtigen en Katachtigen zullen de eigenschappen en methoden van de basisklasse Dier overerven en er specifieke eigenschappen en methoden aan toevoegen. Alle dieren kunnen lopen. De klasse Dieren zal dan ook een methode Lopen bevatten. Maar een kat loopt anders dan een hond. Zowel de klasse Hondachtigen als Katachtigen zullen de methoden Lopen overerven van de klasse Dieren maar zullen deze vervolgens overschrijven om de specifieke manier van lopen weer te geven.
  • Polymorfisme: polymorfisme staat voor veelvormigheid. In het geval van de informatica wordt hiermee bedoeld het gelijkvormig zijn van de interface van klassen en objecten, maar met verschillende implementaties. De gelijkvormigheid betreft dan voornamelijk het gebruik en de naamgeving van methodes. Een methode, met een specifieke naam, kan dankzij polymorfisme op verschillende manieren ingevuld worden maar toch die specifieke naam behouden.Bijvoorbeeld, u hebt een methode Berekenen. De methode moet zowel kunnen rekenen met getallen als met datums. Dank zij polymorfisme moet u geen twee methoden benoemen bv. BerekenGetallen en BerekenDatums maar kunt u zich beperken tot slechts één naam: Berekenen.

Voorbeelden van objectgeörienteerde programmeertalen zijn: C#, Java, Swift, Python, Ruby,… U ziet, heel wat hedendaagse populaire programmeertalen. Dit is geen toeval aangezien objectgeörienteerd programmeren een verbetering is van het procedureel gestructureerd programmeren.

“Hello World” in C#, let op het woordje class.

 class HelloWorld {
 	static void Main() {
 		System.Console.WriteLine("Hello world");
 	}
 }

“Hello World” in Java, let op het woordje class.

class HelloWorldApp {
    public static void main(String[] args) {
        System.out.println("Hello World!"); 
    }
}

Declaratief programmeren

Declaratief programmeren staat tegenover imperatief programmeren.

Imperatief programmeren beschrijft hoe de gewenste taak moet uitgevoerd worden door een opeenvolging van instructies.

Declaratief programmeren beschrijft wat het programma moet uitvoeren.

Een taal is declaratief als de basiselementen geen opdrachten zijn, maar beschrijvingen. Daarmee is nog niets gezegd over de aard van die beschrijvingen. Er is daarom een groot spectrum aan declaratieve talen. Naar vorm zijn tekstuele, opmaaktalen en visuele talen te onderscheiden.

Tekstueel

In een tekstuele taal bestaan de uitdrukkingen uit tekst (wie had dit kunnen vermoeden?). Tekstuele declaratieve talen zijn vaak talen horende tot de vierde of vijfde generatie.

Een voorbeeld is de taal SQL voor het beheren en bevragen van databanken. Deze declaratieve tekstuele taal is vaak heel leesbaar. Begrijpt u wat onderstaand SQL-commando doet?

Select Naam, Voornaam from TabelCursist where Woonplaats = "Ninove" Order By Naam, Voornaam

Hebt u deze instructie begrepen? Nee? Echt niet? … Ok, hier gaan, er vanuit gaande dat TabelCursisten en tabel is met cursistengegevens, zal bovenstaande SQL-instructie aan de computer vragen om: De naam en voornaam van alle cursisten uit Ninove gesorteerd op Naam en vervolgens op Voornaam te selecteren.

Opmaaktalen

Opmaaktalen worden gebruikt voor de opmaak, de opbouw, van de UI (users interface, of kortweg uw “scherm”).

Opmaaktalen zijn wellicht beter gekend onder hun engelstalige benaming Markup Language zoals daar zijn HTML (Hypertext Markup Language) of het alternatief gebruikt door Micrososft namelijk XAML (Extensible Application Markup Language).

Visuele programmeertalen

In een visuele programmeertaal typt  niet langer code maar programmeert u door visueel de instructies, en hun onderlinge verbanden, op te bouwen.

Een voorbeeld van een visuele programmeertaal zijn de Blueprints in Unreal Engine.

Achter deze visuele presentatie ligt vaak een imperatieve programmeertaal en dient de visuele weergave vooral om het programmeren van de achterliggende programmeertaal te vereenvoudigen. In het geval van Unreal Engine is de achterliggende programmeertaal de objectgeörienteerde programmeertaal C++. De visuele Blueprints van Unreal Engine gebruiken dan ook de principes van objectgeörienteerd programmeren.

Functioneel programmeren

Het begrip functie is niet nieuw, we zijn het al een paar keer tegen gekomen. Het verschil is dat bij functioneel programmeren (wiskundige) functies in hun “zuivere” wiskundige betekenis centraal staan. Een functie krijgt een aantal waarden mee via parameters. Deze parameters worden binnen de functie gebruikt om een “berekening” uit te voeren. Het resultaat van deze berekening wordt terug gegeven aan de instructie die de functie aanroept.

Binnen een functie kunnen geen waarden die buiten de functie liggen (bv. een globale variabele) worden gewijzigd. Functioneel programmeren zal de status van een variabele, buiten de functie, niet wijzigen (“don’t modify state”) De functie kan enkel werken met de parameters die het meegekregen heeft. Variabelen gebruikt als accumulator, teller, globale of controle variabele zijn uit den boze.

In dit model vindt een berekening plaats door het toepassen van functies op argumenten: “als ik functie f toepas op argument a krijg ik als antwoord b“. Hoe de toepassing van f op a precies tot b leidt, doet er niet toe – het gaat erom dat b het antwoord is.

Voorbeelden van functionele talen: APL, LISP, Scala, ….

“Hello World” in Scala.

object HelloWorld {
  def main(args: Array[String]): Unit = {
    println("Hello, world!")
  }
}

Het functioneel programmeren paradigma wordt vaak ook toegepast binnen niet-functionele programmeertalen zoals Python, Javascript en via Lambda-functies in C#.

Multi-paradigma

Programmeertalen die meerdere paradigma’s combineren worden Multi-paradigma programmeertalen genoemd.

Vele moderne programmeertalen zijn Multi-paradigma programmeertalen.


Van broncode naar machinetaal

Programmeren wordt, in het algemeen, niet direct in machinetaal gedaan, maar in een programmeertaal. De programmacode die wordt geschreven heet broncode en deze broncode moet worden omgezet naar de machinetaal die die computer begrijpt.

De omzetting van de geschreven broncode naar de machinetaal kan op 4 manieren gebeuren:

Direct

Wanneer het programma (de broncode) is geschreven in de machinetaal van de betrokken computer, kunnen de instructies direct uitgevoerd worden. Het schrijven van machinetaal is echter zo omslachtig en tijdrovend dat het (vrijwel) nooit gebeurt. In de praktijk wordt een assembler gebruikt, die gecompileerd wordt.

Na compilatie

Met behulp van een compiler worden de instructies omgezet in machinetaal die door de processor van de computer kunnen worden begrepen, waarna deze instructies kunnen worden uitgevoerd.

 

Via een interpreter

Een interpreter leest de tekst van de programmeertaal in, interpreteert deze naar machinecode, en voert die direct uit, soms zelfs voordat de gehele tekst is ingelezen. Dit is een andere benadering dan een compiler die een programma al voor de uitvoering geschikt maakt voor de processor.

Via bytecode

Met behulp van een compiler worden de instructies omgezet in een bytecode (tussencode), een speciale interpreter voor die bytecode voert dan deze instructies uit. Bytecode is een soort machinetaal die het resultaat is van de (gedeeltelijke) compilatie van een computerprogramma. In tegenstelling tot “echte” machinetaal is bytecode niet geschikt om direct op een computer te worden uitgevoerd. Bytecode kan worden uitgevoerd op een virtuele machine (zoals de .NET Common Language Runtime (CLR) of de Java Virtual Machine (JVM)) of later vertaald worden naar “echte” machinetaal. Deze benadering maakt het mogelijk platform-onafhankelijke programma’s te schrijven: op elk platform waarvoor een Virtuele Machine beschikbaar is, kan dan hetzelfde programma worden uitgevoerd.

De verschillen tussen een compiler en een interpreter

CompilerInterpreter
Analyseert en vertaalt het programma eerst volledig naar machinecode en pas dan kan het programma worden uitgevoerd.Analyseert en voert de code meteen uit.
Neemt het volledige programma als invoer.Neemt instructie per instructie als invoer.
Het compileren kan lang duren maar de programma’s zelf, zullen na de compilatie, snellere uitgevoerd worden.De uitvoering is trager omdat tegelijkertijd de interpretatie gebeurt.
Fouten worden pas getoond nadat het volledige programma is gecompileerd.Fouten kunnen gegenereerd worden na iedere instructie.
Na iedere wijziging van de broncode moet alles opnieuw gecompileerd worden.

Het voordeel van het gebruiken van een interpreter is dat het testen veel sneller gaat omdat compileren niet nodig is. Daar staat tegenover, dat de uitvoering van programma’s aanzienlijk langzamer kan zijn omdat de instructies telkens opnieuw moeten worden omgezet, terwijl dat bij een compiler maar eenmaal hoeft te gebeuren.


Hoor het eens van iemand anders

Moest u dat van die bits en bytes nog niet zo goed begrepen hebben, hoor het dan eens van iemand anders.

Behandelde Basiscompetenties uit de module ICT Programmeren – Start to program

  • IC BC228 – kent de verschillende principes en onderdelen op basis waarvan een programma kan opgebouwd worden

Programmer

A machine that turns coffee into code.

Geef een reactie

  • Abonneer je op deze website d.m.v. e-mail

    Voer je e-mailadres in om je in te schrijven op deze website en e-mailmeldingen te ontvangen van nieuwe berichten.