Clean | ||||
---|---|---|---|---|
Paradigma | zuiver functioneel programmeren, functioneel programmeren | |||
Verschenen | 1987 (36 jaar) | |||
Ontwerper | Radboud Universiteit Nijmegen | |||
Ontwikkelaar | Radboud Universiteit Nijmegen | |||
Huidige versie | 3.1 (22 september 2022)[1] | |||
Typesysteem | dynamisch typesysteem, sterke typering | |||
Beïnvloed door | Haskell | |||
Besturingssysteem | Linux, macOS, Windows | |||
Licentie | LGPL | |||
Bestandsextensies | icl, dcl, abc | |||
Website | (en) Officiële website | |||
|
Clean is een functionele programmeertaal, ontwikkeld aan de Radboud Universiteit Nijmegen. Clean werd ontwikkeld voor het maken van praktische toepassingen.[2] Een functionele programmeertaal betekent dat programma’s opgesteld worden in de vorm van een functie die toegepast wordt om een resultaat te vinden.[3] Omdat Clean een functionele programmeertaal is, kan het gemakkelijker zijn om Clean aan te leren wanneer men al bekend is met algebra van de middelbare school.[4] Clean heeft veel gelijkenissen met andere moderne functionele programmeertalen zoals Miranda, Haskell en ML.[5] Clean is beschikbaar voor Windows, Linux en macOS.[6]
Oorspronkelijk was Clean een subset van Lean, ontworpen als experimentele programmeertaal met als doel het graph rewriting model te bestuderen.[2] Graph rewriting houdt in dat men een nieuwe graaf maakt van de originele graaf door gebruik te maken van een automatische machine. Daar men zich wilde concentreren op de essentiële implementatieproblemen, werd doelbewust gekozen om weinig syntaxisregels in te voeren in Clean. Clean werd meer en meer gebruikt voor het maken van toepassingen en uiteindelijk werd Clean dan ook omgevormd naar een general purpose functionele programmeertaal.[2] Hiermee wordt bedoeld dat het een functionele programmeertaal is die gebruikt wordt voor verschillende doeleinden. In mei 1995 werd Clean voor het eerst vrijgegeven.[2]
Dynamics is een feature in Clean die de mogelijkheid biedt een expressie weg te schrijven naar opslag of te verzenden over een netwerk. Hierdoor wordt het mogelijk een expressie door te sturen naar een ander systeem, of een module-gebaseerd systeem te ontwikkelen. Een reden kan zijn dat je in je code een functie wil gebruiken, maar je niet zeker weet of er mogelijk later nog een efficiëntere manier van deze functie gevonden wordt. In het geval van een sorteerfunctie zou je bijvoorbeeld kunnen zeggen dat je een functie wilt van type [a] → [a] uit bestand X. Dan kun je daarna dit bestand vervangen door een andere implementatie, waardoor je dus vrij eenvoudig een andere implementatie van dezelfde functie kunt gebruiken.
Ervaring met het ontwikkelen van grote programma's heeft aangetoond dat het zeer handig is om het programma eerst te controleren voor het uit te voeren. Niet enkel kan de compiler de syntaxis controleren, maar er kan ook gecontroleerd worden of het wel zin heeft om een functie toe te passen op een bepaald argument (bv. een vierkantswortel nemen van een string heeft geen zin). Dit laatste wordt type checking genoemd. Enkele voorbeelden van programmeertalen die aan type checking doen zijn ML, Miranda, Haskell en natuurlijk ook Clean. De mogelijkheid om functies te definiëren die werken met andere functies en om functies als resultaat te hebben, is een belangrijke eigenschap van deze programmeertalen.[5]
Type checking van Clean garandeert dat runtime type errors niet zullen voorkomen. Dit elimineert de behoefte aan uitgebreide tests of het programma al dan niet vrij is van dit soort fouten. Type checking door de compiler is ook sneller en veiliger.
Samen maken deze eigenschappen het veel gemakkelijker om goede algoritmen te schrijven. Ook wordt het gemakkelijker om te begrijpen wat anderen geschreven hebben en om al bestaande functies te veranderen. Dit maakt functionele talen zoals Clean zeer geschikt voor evolutionaire ontwikkeling. Onderhoud wordt gemakkelijker en hergebruik is eindelijk mogelijk.
square :: Int → Int square n = n * n
Regel 1 duidt de types aan van de functie: integer als argument en integer als resultaat. Regel 2 duidt aan hoe het resultaat berekend moet worden: vermenigvuldig het argument met zichzelf.
fac :: Int →Int fac 0 = 1 fac n = n * fac (n-1)
Regel 2 wordt uitgevoerd wanneer het argument 0 is. Regel 3 wordt uitgevoerd wanneer het argument iets anders dan 0 is.
Start :: String Start = "Hello world"
De waarde van Start wordt getoond aan de gebruiker. Regel 2 zorgt er dus voor dat Hello world op het scherm verschijnt.[7]