Lisp, een afkorting voor "LISt Processing," is een familie van programmeertalen die een kenmerkende haakjesgebaseerde syntaxis delen, voornamelijk gericht op de manipulatie van symbolen en lijsten. Het is een van de oudste hoog-niveau programmeertalen, oorspronkelijk uitgevonden in de late jaren 1950, en het is door de decennia heen aanzienlijk geëvolueerd. Lisp is vooral bekend om zijn krachtige functies zoals dynamische typing, garbage collection en first-class functies, waardoor het geschikt is voor AI-onderzoek, symbolische berekeningen en snelle prototyping.
Lisp werd in 1958 gecreëerd door John McCarthy als een wiskundige notatie voor computerprogramma's en als een praktische manier om AI te implementeren. De taal is afgeleid van de lambda-calculus, een formeel systeem in de wiskundige logica en computerwetenschappen. De eerste implementatie vond plaats op de IBM 704, en al snel daarna ontstonden er talrijke dialecten, elk met hun eigen functies en complexiteiten.
In de loop der tijd zijn verschillende opmerkelijke dialecten van Lisp ontstaan, waaronder Common Lisp en Scheme. Common Lisp werd in de jaren 1980 gestandaardiseerd om verschillende dialecten te verenigen, terwijl Scheme, dat de nadruk legt op functioneel programmeren en minimalisme, populair werd in de academische wereld. Invloeden van Lisp zijn te zien in veel moderne programmeertalen, vooral die welke functionele programmeerparadigma's ondersteunen, zoals Clojure, Racket en zelfs talen zoals Python en Ruby.
Tegenwoordig behoort Lisp niet tot de meest populaire programmeertalen, maar blijft het invloedrijk, vooral in onderzoek, AI en onderwijs. De gemeenschap ontwikkelt actief nieuwere dialecten zoals Clojure, dat draait op de Java Virtual Machine (JVM) en zich richt op gelijktijdig programmeren.
Lisp gebruikt een unieke syntaxis met haakjes om expressies aan te duiden, waarbij code wordt weergegeven in symbolische expressies (S-expressies). Bijvoorbeeld:
(+ 1 2)
Deze expressie vertegenwoordigt de optelling van 1 en 2.
Functies in Lisp kunnen als argumenten worden doorgegeven, worden geretourneerd vanuit andere functies en aan variabelen worden toegewezen:
(defun square (x) (* x x))
(mapcar #'square '(1 2 3 4)) ; retourneert (1 4 9 16)
Lisp is dynamisch getypeerd, waardoor variabelen waarden van elk datatype kunnen bevatten zonder voorafgaande declaratie:
(setq x 10) ; x is nu een getal
(setq x "hello") ; x is nu een string
Lisp beschikt over krachtige macrosystemen waarmee ontwikkelaars aangepaste syntactische constructies kunnen maken:
(defmacro when (condition &body body)
`(if ,condition
(progn ,@body))
)
De if
en cond
vormen vergemakkelijken de controleflow in Lisp:
(if (> x 0)
(print "Positief")
(print "Niet-positief"))
Lisp beschouwt lijsten als fundamentele datastructuren:
(setq my-list '(1 2 3 4))
(car my-list) ; retourneert 1
(cdr my-list) ; retourneert (2 3 4)
Functies worden gedefinieerd met behulp van de defun
constructie:
(defun factorial (n)
(if (= n 0)
1
(* n (factorial (- n 1)))))
Common Lisp omvat een object-georiënteerd systeem dat bekend staat als het Common Lisp Object System (CLOS):
(defclass person ()
((name :initarg :name :accessor person-name)
(age :initarg :age :accessor person-age)))
(defmethod say-hello ((p person))
(format t "Hallo, mijn naam is ~A en ik ben ~A jaar oud."
(person-name p) (person-age p)))
Lisp biedt een geavanceerd foutafhandelingsmechanisme met behulp van handler-case
:
(handler-case
(/ 1 0)
(division-by-zero () (print "Vangst van deling door nul!")))
Continuaties worden in sommige dialecten ondersteund, waardoor het programma uitvoeringsstatussen kan opslaan en herstellen:
(call-with-current-continuation
(lambda (k)
(k 10)))
Verschillende Integrated Development Environments (IDE's) en compilers zijn beschikbaar voor Lisp-programmering. Populaire keuzes zijn onder andere:
Om een Lisp-project te bouwen, maak je meestal een bestand met een ".lisp" of ".lsp" extensie. Met SBCL kan een typische workflow het laden van je project vanuit de REPL omvatten:
(load "my-project.lisp")
Voor projecten die Quicklisp gebruiken, een bibliotheekbeheerder, kunnen afhankelijkheden eenvoudig worden beheerd en geladen.
Lisp is vooral bekend om zijn toepassingen in kunstmatige intelligentie, symbolische berekeningen en de academische wereld, maar het vindt ook toepassingen in:
Lisp wordt vaak vergeleken met:
Vertalen van Lisp naar andere talen wordt vaak gedaan met behulp van bron-naar-bron vertaaltools. Bijvoorbeeld, de volgende tools bestaan:
Elk van deze tools biedt specifieke mappings die ervoor zorgen dat de kernfunctionaliteiten van Lisp effectief kunnen worden weergegeven in de doeltalen. Voor complexere vertalingen kan handmatige refactoring nodig zijn, vooral voor zwaar macro-geoptimaliseerde code.