Static Wikipedia February 2008 (no images)

aa - ab - af - ak - als - am - an - ang - ar - arc - as - ast - av - ay - az - ba - bar - bat_smg - bcl - be - be_x_old - bg - bh - bi - bm - bn - bo - bpy - br - bs - bug - bxr - ca - cbk_zam - cdo - ce - ceb - ch - cho - chr - chy - co - cr - crh - cs - csb - cu - cv - cy - da - de - diq - dsb - dv - dz - ee - el - eml - en - eo - es - et - eu - ext - fa - ff - fi - fiu_vro - fj - fo - fr - frp - fur - fy - ga - gan - gd - gl - glk - gn - got - gu - gv - ha - hak - haw - he - hi - hif - ho - hr - hsb - ht - hu - hy - hz - ia - id - ie - ig - ii - ik - ilo - io - is - it - iu - ja - jbo - jv - ka - kaa - kab - kg - ki - kj - kk - kl - km - kn - ko - kr - ks - ksh - ku - kv - kw - ky - la - lad - lb - lbe - lg - li - lij - lmo - ln - lo - lt - lv - map_bms - mdf - mg - mh - mi - mk - ml - mn - mo - mr - mt - mus - my - myv - mzn - na - nah - nap - nds - nds_nl - ne - new - ng - nl - nn - no - nov - nrm - nv - ny - oc - om - or - os - pa - pag - pam - pap - pdc - pi - pih - pl - pms - ps - pt - qu - quality - rm - rmy - rn - ro - roa_rup - roa_tara - ru - rw - sa - sah - sc - scn - sco - sd - se - sg - sh - si - simple - sk - sl - sm - sn - so - sr - srn - ss - st - stq - su - sv - sw - szl - ta - te - tet - tg - th - ti - tk - tl - tlh - tn - to - tpi - tr - ts - tt - tum - tw - ty - udm - ug - uk - ur - uz - ve - vec - vi - vls - vo - wa - war - wo - wuu - xal - xh - yi - yo - za - zea - zh - zh_classical - zh_min_nan - zh_yue - zu

Web Analytics
Cookie Policy Terms and Conditions Common Lisp - Wikipedia

Common Lisp

aus Wikipedia, der freien Enzyklopädie

Common Lisp oder auch Common-Lisp, häufig abgekürzt CL, ist eine standardisierte Programmiersprache der Lisp-Familie. Common Lisp ist keine Implementierung sondern eine Spezifikation zu der sowohl kommerzielle als auch freie Implementierungen existieren. Die Sprache Common Lisp ist seit dem 8. Dezember 1994 offizieller ANSI-Standard (ANSI/X3.226-1994) und somit die erste standardisierte objektorientierte Programmiersprache.

Common Lisp ist eine Allzweckprogrammiersprache, wodurch sie sich gegenüber anderen heute angewandten Lisp-Dialekten Emacs Lisp und AutoLISP abgrenzt, welche nur eingebettete Erweiterungssprachen für bestimmte Programme darstellen.

Common Lisp und Scheme benutzen im Gegensatz zu vielen älteren Dialekten (wie MacLisp oder ZetaLisp) lexikalischen Gültigkeitsbereich (lexical scope) für Variablen.

Common Lisp ist eine Multiparadigmensprache, die

  • sowohl imperatives, funktionales und objekt-orientiertes Programmieren unterstützt,
  • mittels optionaler Typdeklarationen effizient kompiliert werden kann, und
  • durch standardisierte Sprachelemente wie z.B. Lisp-Makros (Neuanordnung von Code zur Kompilierzeit durch das Programm selbst) und Reader-Makros (Syntaxerweiterungen, die bestimmten Zeichen neue Bedeutungen geben) erweitert werden kann.

Inhaltsverzeichnis

[Bearbeiten] Syntax

Common Lisp ist ein Lisp. Daher nutzt es S-Expressions, um sowohl Code als auch Daten darzustellen. Funktions- und Makroaufrufe werden als Listen geschrieben, die als erstes Element den Namen der Funktion bzw. des Makros enthalten. Kommentare werden mit ; eingeleitet.

;; Addiere 2 und 2
(+ 2 2)
;; Setze die Variable p auf 3.1415
(setf p 3.1415)
;; Eine Funktion, die ihr Argument quadriert
(defun square (x)
  (* x x))
;; Quadriere 3
(square 3)

[Bearbeiten] Datentypen

Common Lisp unterstützt eine Vielzahl von Datentypen, mehr als viele andere Sprachen. Diese Typen sind hierarchisch angeordnet.

[Bearbeiten] Skalare Typen

Zahlen in Common Lisp sind vom Typ number. Untertypen von number sind u.a. integer (Ganzzahlen), ratio (rationale Zahlen bzw. Brüche), real (Fließkommazahlen) und complex (komplexe Zahlen). Arithmetik mit Ganzzahlen und Brüchen ist beliebig genau. Eine Klasse von Programmfehlern in Sprachen wie C, die durch überlaufende Ganzzahlen verursacht werden, ist in Common Lisp somit praktisch ausgeschlossen.

Der Common Lisp character-Typ ist nicht auf ASCII beschränkt, was nicht überrascht, da Lisp älter als ASCII ist. Viele Implementierungen unterstützen Unicode, siehe [1] (englisch).

Der Typ symbol ist ein besonderes Merkmal fast aller Lisp-Dialekte, aber in anderen Sprachfamilien größtenteils unbekannt. Ein Symbol in Lisp ist ähnlich einem Bezeichner in anderen Sprachen, da es als Variable benutzt wird und Werte zugewiesen bekommen kann. Da sie aber Objekte erster Klasse sind, können sie auch zu anderen Zwecken benutzt werden.

[Bearbeiten] Datenstrukturen

Common Lisp kennt eine Reihe vordefinierter Datenstrukturen. Dazu zählen unter anderem Hashtables, Datenverbünde (sogenannte structures), mehrdimensionale Arrays und Folgen. Letztere umfassen klassische Lisp-Listen, aber auch Bitvektoren, allgemeine Vektoren und Zeichenketten.

Hashtables speichern Zuordnungen von Objekten. So kann zum Beispiel einer Zeichenkette eine Zahl zugewiesen werden oder einem Symbol eine Funktion.

Bei Datenverbünden handelt es sich um beliebig verschachtelte Strukturen, die Daten jedes beliebigen Typs vorhalten können. Ein einzelner Verbund speichert in einer jeweils festen Menge von sogenannten slots Werte, die später nach Belieben verändert und extrahiert werden können.

Arrays sind n-dimensionale Listen von Werten, die entweder alle denselben Typen haben müssen (in sogenannten homogenen Arrays), oder – im Falle von heterogenen Arrays – beliebig zusammengestellt sein können. Sie unterstützen die üblichen Matrixrechenoperationen und können auch in dynamisch veränderbaren Größen auftreten. Berechnungen mit homogenen, in ihrer Größe festgelegten Arrays können von Compilern meist sehr effizient übersetzt werden.

Vektoren sind der Spezialfall von Arrays mit nur einer Dimension. Es gibt vordefinierte Vektortypen wie die Zeichenkette, ein Vektor von Zeichen, oder den Bitvektor, eine komfortable und effiziente Möglichkeit, Bits zu speichern und mit ihnen zu rechnen.

Klassische Lisp-Listen bestehen aus sogenannten CONS-Zellen. Damit sind geordnete Paare gemeint, deren erstes Element, der sogenannte CAR, einen Wert enthält, während deren zweites Element, der sogenannte CDR, auf die jeweils nächste Zelle oder im Falle des Listenendes auf das Symbol NIL zeigt. Im Grunde handelt es sich bei Lisp-Listen also um einfach verkettete Listen. Sie werden heute hauptsächlich verwendet, um Code darzustellen und mithilfe von Makros beliebig zu manipulieren – ein Mechanismus, der Lispprogrammierern einen Grad an Freiheit bietet, der bei anderen Programmiersprachen dem Sprachdesigner vorbehalten bleibt. Komplexere Daten speichert man für gewöhnlich in Klassen oder Verbünden, und Daten, mit denen man effizient rechnen möchte, in Arrays bzw. Vektoren.

Wie oben erwähnt, enthält Common Lisp zualledem ein ausgereiftes klassenbasiertes Objektsystem, das ebenfalls zur Definition neuer Datentypen dienen kann.

[Bearbeiten] Paketsystem

Common Lisp enthält ein Paketsystem, das es erlaubt, Namensräume für Symbole zu definieren und Letztere zu im- und exportieren. Außerdem können der Bequemlichkeit und Lesbarkeit halber Abkürzungen bzw. Spitznamen für Pakete vergeben werden.

Alle im Common-Lisp-Standard vorgegebenen Symbole befinden sich im Paket COMMON-LISP, abgekürzt CL. Weiters ist ein Paket namens COMMON-LISP-USER bzw. CL-USER vorgegeben, das für einfachere Arbeiten des Anwenders vorgesehen ist und alle Symbole aus dem CL-Paket importiert. Komplexere Projekte sollten ihre eigenen Pakete definieren.

Symbole, die sich in anderen Namensräumen als dem aktuellen befinden, können angesprochen werden, indem man vor ihre Namen mit einem Doppelpunkt getrennt den jeweiligen Paketnamen schreibt. Beispielsweise zeigt der Name cl:format stets auf das FORMAT-Symbol im Pakete CL, unabhängig davon, ob im aktuellen Paket möglicherweise eine Funktion definiert ist, die ebenfalls FORMAT heißt.

[Bearbeiten] Funktionen

In Common Lisp sind Funktionen normale Objekte, die als Parameter übergeben oder von einer Funktion zurückgegeben werden können. Dadurch können sehr allgemeine Operationen ausgedrückt werden.

Die Common Lisp Standardbibliothek benutzt solche Funktionen höherer Ordnung oft. Zum Beispiel nimmt die sort-Funktion einen Vergleichsoperator als Argument.

Das Auswertungsschema für Funktionen ist sehr einfach. Wenn ein Ausdruck der Form (F A1 A2...) vorliegt, kann angenommen werden, dass das Symbol mit dem Namen F:

  1. ein spezieller Operator ist (special operator).
  2. ein schon definiertes Makro ist.
  3. der Name einer Funktion ist.

Wenn F der Name einer Funktion ist, dann werden die Argumente A1, A2, ... von links nach rechts ausgewertet und der entsprechenden Funktion als Parameter übergeben.

[Bearbeiten] Definieren neuer Funktionen

Das Makro defun definiert Funktionen. Eine Funktionsdefinition beschreibt den Namen der Funktion, die Namen aller Argumente und den Funktionsrumpf:

(defun square (x)
   (* x x))

Funktionsdeklarationen können Deklarationen beinhalten, die dem Compiler Hinweise zur Optimierung u.a. bzgl. Typen geben. Zusätzlich können auch sogenannte documentation strings oder kurz docstrings angegeben werden, die das Laufzeitsystem benutzen kann, um dem Benutzer interaktive Hilfe zu bieten.

(defun square (x)
   "Berechnet das Quadrat von X."
   (declare (fixnum x)    ; Typangabe für ein Argument
            (optimize (speed 3)
                      (debug 0)
                      (safety 1)))
   (the fixnum (* x x)))  ; Typangabe für den Rückgabewert

Anonyme Funktionen (Funktionen ohne expliziten Namen) werden mittels lambda Operator erzeugt. Viele Lisp-Programme benutzen Funktionen höherer Ordnung, bei denen es nützlich ist anonyme Funktionen als Argumente zu übergeben.

[Bearbeiten] Objektorientierung

Das Common Lisp Object System (kurz CLOS) ist eine standardisiertes Modul zur objektorientierten Programmierung mit Common Lisp.

Im Gegensatz zu den meisten objektorientierten Programmiersprachen sind Methoden bei CLOS über generische Funktionen implementiert und nicht Bestandteil der Klasse.

(defclass lager ()
  ((bestand :initarg  :bestand
            :accessor bestand)
   (produkt :initarg  :produkt
            :reader   produkt)))

(defmethod einlagern ((dieses-lager lager) anzahl)
  "Lagere eine Anzahl an Produkten im Lager DIESES-LAGER ein."
  (incf (bestand dieses-lager) anzahl))

;; MAKE-INSTANCE legt Instanzen von Klassen an.
(let ((n (make-instance 'lager
                        :produkt "Gold"
                        :bestand 0)))
  (einlagern n 100)
  (bestand n))  ; => 100

[Bearbeiten] Lese-, Kompilier- und Laufzeit

Als Besonderheit gegenüber anderen Sprachen erlaubt Common Lisp es dem Programmierer, eigenen Code nicht nur zur Laufzeit auszuführen, sondern auch in zwei anderen Phasen, der Lese- und der Kompilierzeit.

[Bearbeiten] Lesezeit und Lesemakros

Code, der während der Lesezeit ausgeführt wird, kann den Parser steuern und so eigene Syntax definieren. Meist geschieht dies in Form von sogenannten Lesemakros (read macros oder auch reader macros), die einzelnen Sonderzeichen zugewiesen werden und beliebigen Text in Code umwandeln können. So gibt es beispielsweise Lesemakros, die für arithmetische Ausdrücke die gewohnte Infix-Syntax bereitstellen und Ausdrücke wie 3 * (4 + 3) in Lisp gültig machen.

[Bearbeiten] Kompilierzeit und Lisp-Makros

Das Unterscheidungsmerkmal von Lisp schlechthin ist allerdings die Möglichkeit, Code zur Kompilierzeit auszuführen und damit die den Programmcode darstellenden S-Ausdrücke beliebig zu manipulieren, zu generieren und umzuformen. Die Sprache sieht dafür in erster Linie die sogenannten Makros vor. Da Lisp-Makros auf der Ebene der Programmstruktur arbeiten und sich dadurch in die Sprache selbst perfekt einfügen, sind sie mit Makrosystemen anderer Sprachen nicht vergleichbar und würden daher eigentlich einen eigenen Namen verdienen.

Makros können auf alle Lispfunktionen, auch selbstdefinierte, zugreifen, wodurch ihnen sehr viele Möglichkeiten offenstehen, Code umzuformen. Lispprogrammierer verwenden Makros oft, um anwendungsspezifische Sprachen in Lisp einzubauen, die sich nahtlos in die Sprache einpassen und ihre Ausdrucksstärke erhöhen. Auch ist es möglich, Makros zur Bereitstellung neuer Programmierparadigmen zu nutzen.

Das im Common-Lisp-Standard enthaltene klassenbasierte Objektsystem CLOS ist ein bekanntes Beispiel für einen umfangreichen Satz von Makros, der ein eigenständiges und beliebtes Programmierparadigma implementiert. Es gibt auch Erweiterungen von Drittentwicklern, die z.B. aspekt- und kontextorientierte Programmierung bereitstellen oder funktionale Programmierung mit statischer Typsicherheit in Lisp möglich machen.

[Bearbeiten] Variablenbindung

Wie die meisten anderen Sprachen kennt auch Common Lisp das Konzept des Bindens von Werten an Namen. Es erweitert dieses Konzept jedoch durch zwei Aspekte: Einerseits können Variablennamen selbst als normale Objekte verwendet und zum Beispiel weitergegeben oder gespeichert werden, und andererseits stehen zwei ganz unterschiedliche Formen der Variablenbindung zur Verfügung. Der erstere Aspekt wurde bereits im Abschnitt über Datentypen erläutert.

[Bearbeiten] Lexikalische Bindung und lexikalische Variablen

Im Gegensatze zu früheren Mitgliedern der Lisp-Sprachfamilie, verwendet Common Lisp standardmäßig lexikalische Bindung, ein Konzept, das Scheme seinerzeit in die Lisp-Welt eingeführt hat. Dabei sind Namen immer in einem bestimmten, abgeschlossenen Teil des Quelltexts gültig, so daß es bei der Bindung nicht zu Überschneidungen mit zuvor oder künftig definierten Bindungen kommen kann.

Da Bindungen in Lisp jederzeit erzeugt werden können und Überschneidungen ausgeschlossen sind, ist es möglich, mit ihrer Hilfe allein durch Funktionsdeklarationen Datenstrukturen zu erzeugen. Dabei nutzt man einen Effekt aus, den man closure nennt: das automatische Einfangen von Bindungen.

Möchte man beispielsweise den CONS-Operator definieren, der ein Paar aus zwei Werten erzeugt, so könnte man auf die Idee kommen, diesen eine anonyme Funktion (also einen LAMBDA-Ausdruck) zurückliefern zu lassen, die die beiden Werte eingefangen hat, und auf Anfrage, d.h. wenn sie mit einem Argument NUM aufgerufen wird, einen der beiden zurückliefert (und zwar den ersten Wert für NUM = 0 und sonst den zweiten):

(defun cons (x y)
  (lambda (num)
    (if (zerop num)
        x
        y)))

Man kann die von diesem Operator erzeugten Werte zum Beispiel wie folgt verwenden (man beachte: FUNCALL ist der Operator zum Aufrufen von Funktionen, die in Variablen gespeichert sind):

(defvar *paar-A* (cons 100      200))     ;=> *PAAR-A*
(defvar *paar-B* (cons *paar-A* 42))      ;=> *PAAR-B*
(print (funcall *paar-A* 0))              ;=> 100
(print (funcall *paar-A* 1))              ;=> 200
(print (funcall *paar-B* 0))              ;=> (LAMBDA ...)
(print (funcall (funcall *paar-B* 0) 1))  ;=> 200

Man beachte hierbei, daß die verschiedenen Bindungen von *PAAR-A* und *PAAR-B* für die Namen X und Y sich nicht überschneiden, sondern für jeden Aufruf von CONS jeweils neu erschaffen werden. Es ist auch möglich, solche Bindungen nachträglich zu ändern, wie der folgende Codeausschnitt zeigt, der eine versteckte Bindung namens ZÄHLER definiert:

(let ((zähler 0))
  (defun zähler+     () (incf zähler))
  (defun zähler-     () (decf zähler))
  (defun hole-zähler () zähler))

(hole-zähler)  ;=> 0
(zähler+)      ;=> 1
(zähler+)      ;=> 2
(hole-zähler)  ;=> 2
(zähler-)      ;=> 1
(hole-zähler)  ;=> 1

;(setf zähler 100)  ;=> Fehler, weil ZÄHLER nicht global definiert ist.

[Bearbeiten] Dynamische Bindung und Sondervariablen

Nach wie vor unterstützt Common Lisp auch die in der Lisp-Familie so traditionsreiche dynamische Bindung, die globale Namen, aber zeitlich begrenzt gültige Wertbindungen verwendet. Aufgrund der möglichen Namenskonflikte wird diese Art der Wertbindung nur in Sonderfällen verwendet, weshalb der Common-Lisp-Standard in dem Zusammenhang auch von special variables, also Sondervariablen, spricht.

Es ist üblich, die Namen von Sondervariablen zwischen zwei Sternchen zu setzen, um dem Leser ihre Natur auf einen Blick deutlichzumachen.

Der Nutzen von Sondervariablen liegt gerade in ihren zeitlich begrenzten, aber globalen Auswirkungen begraben. Man kann sie sich auch als eine Form von impliziten Argumenten vorstellen, die den gesamten Aufrufsbaum hinab weitergereicht werden, ohne auf jeder Ebene explizit genannt werden zu müssen.

Ein Beispiel macht das Prinzip verständlicher. Nehmen wir an, es sei eine Funktion PRINT-DATE vordefiniert (z.B. in einer Bibliothek eines Drittanbieters), die das aktuelle Datum in besonders schöner Form auf die Standardausgabe schreibt. Nun möchten wir diese unersetzliche Funktion nutzen, aber das Ergebnis stattdessen in eine Datei schreiben. Hat nun der Entwickler der Funktion nicht an diese Möglichkeit gedacht und einen entsprechenden Parameter eingebaut, können wir uns die Tatsache zunutze machen, daß die Standardausgabe als Sondervariable definiert ist:

(let ((*standard-output* ausgabedatei))
  (format t "~&Das aktuelle Datum ist: ")
  (print-date))

Die Tatsache, daß wir *STANDARD-OUTPUT* dynamisch an unsere AUSGABEDATEI binden, sorgt dafür, daß jede Standardausgabe dort landet, wo wir sie haben wollen. LET sorgt hierbei dafür, daß die Bindung nach Beendigung des Blocks wieder auf ihren Ausgangszustand zurückgesetzt wird.

Sondervariablen haben einen weiteren interessanten Aspekt, der im Falle von Nebenläufigkeit zutage tritt und ihre Implementierbarkeit oberhalb der eigentlichen Sprachebene unmöglich macht oder doch zumindest sehr erschwert: Ihre Bindungen sind nämlich threadlokal. Das heißt, daß zwei parallele Programmabläufe, die auf denselben Namen zugreifen, unterschiedliche Bindungen für diesen Namen verwenden können, obwohl Namen von Sondervariablen global sind. Der obige Code würde demnach auch funktionieren, wenn zwischen der zweiten und der dritten Zeile ein anderer Thread auf die Idee käme, *STANDARD-OUTPUT* an seine eigene Datei zu binden. Da die beiden Bindungen voneinander unabhängig sind, stören sich die beiden Threads dadurch nicht. Man spricht hierbei von Bindungsüberlagerung, weil nicht etwa die bestehende Bindung verändert, sondern immer neue Bindungen auf die alten aufgelagert und bei Beendigung des LET-Blocks wieder heruntergenommen werden.

[Bearbeiten] Entwicklungsumgebungen

Common Lisp eignet sich dank seiner einfachen Syntax besonders für den Einsatz mächtiger Codeanalyse- und Managementprogramme. Außerdem können Entwicklungsumgebungen mit Lisp auf vielfältige Art und Weise integriert werden, bei Bedarf auch bis hin zur Vermengung von Programm- und IDE-Code, wie es früher in Lispmaschinen der Fall war.

Eine weit verbreitete freie Entwicklungsumgebung ist SLIME [2], der Superior Lisp Interaction Mode für Emacs, welcher den üblichen interaktiven Softwareentwicklungsprozeß in Lisp gut unterstützt. Das Fehlen von Refaktorierungswerkzeugen wird nur von wenigen Lispern als ein großes Problem angesehen, zumal die Sprache selbst mit ihren Makros gute Möglichkeiten dafür auf der Quelltextebene bietet.

Weiters existieren zahlreiche kommerzielle Lisp-Entwicklungssysteme, wie zum Beispiel Allegro-CL von Franz Inc. und Lispworks von Xanalys.

[Bearbeiten] Verfügbarkeit von Paketen und Bibliotheken

Ähnlich wie bei anderen Programmiersprachen (z.B. CPAN im Falle von Perl), existiert mit ASDF-Install [3] eine Sammlung von Common-Lisp-Modulen, die sich automatisch installieren lassen.

Es gibt zahlreiche Pakete für die unterschiedlichsten Einsatzgebiete, beispielsweise für Webentwicklung, 3D-Graphik, Textverarbeitung und vieles mehr. Auch stehen Bindings für GUI-Toolkits wie Gtk+, Cocoa, Microsoft Windows, Tk und andere ebenso zur Verfügung wie Implementierungen des Common Lisp Interface Managers (kurz CLIM) und ein Binding für .NET.

[Bearbeiten] Implementierungen

[Bearbeiten] Frei

[Bearbeiten] Kommerziell

  • Allegro Common Lisp
  • CormanLisp
  • LispWorks
  • Macintosh Common Lisp
  • Scieneer Common Lisp

[Bearbeiten] Weblinks

[Bearbeiten] E-Books

Static Wikipedia 2008 (no images)

aa - ab - af - ak - als - am - an - ang - ar - arc - as - ast - av - ay - az - ba - bar - bat_smg - bcl - be - be_x_old - bg - bh - bi - bm - bn - bo - bpy - br - bs - bug - bxr - ca - cbk_zam - cdo - ce - ceb - ch - cho - chr - chy - co - cr - crh - cs - csb - cu - cv - cy - da - de - diq - dsb - dv - dz - ee - el - eml - en - eo - es - et - eu - ext - fa - ff - fi - fiu_vro - fj - fo - fr - frp - fur - fy - ga - gan - gd - gl - glk - gn - got - gu - gv - ha - hak - haw - he - hi - hif - ho - hr - hsb - ht - hu - hy - hz - ia - id - ie - ig - ii - ik - ilo - io - is - it - iu - ja - jbo - jv - ka - kaa - kab - kg - ki - kj - kk - kl - km - kn - ko - kr - ks - ksh - ku - kv - kw - ky - la - lad - lb - lbe - lg - li - lij - lmo - ln - lo - lt - lv - map_bms - mdf - mg - mh - mi - mk - ml - mn - mo - mr - mt - mus - my - myv - mzn - na - nah - nap - nds - nds_nl - ne - new - ng - nl - nn - no - nov - nrm - nv - ny - oc - om - or - os - pa - pag - pam - pap - pdc - pi - pih - pl - pms - ps - pt - qu - quality - rm - rmy - rn - ro - roa_rup - roa_tara - ru - rw - sa - sah - sc - scn - sco - sd - se - sg - sh - si - simple - sk - sl - sm - sn - so - sr - srn - ss - st - stq - su - sv - sw - szl - ta - te - tet - tg - th - ti - tk - tl - tlh - tn - to - tpi - tr - ts - tt - tum - tw - ty - udm - ug - uk - ur - uz - ve - vec - vi - vls - vo - wa - war - wo - wuu - xal - xh - yi - yo - za - zea - zh - zh_classical - zh_min_nan - zh_yue - zu -

Static Wikipedia 2007 (no images)

aa - ab - af - ak - als - am - an - ang - ar - arc - as - ast - av - ay - az - ba - bar - bat_smg - bcl - be - be_x_old - bg - bh - bi - bm - bn - bo - bpy - br - bs - bug - bxr - ca - cbk_zam - cdo - ce - ceb - ch - cho - chr - chy - co - cr - crh - cs - csb - cu - cv - cy - da - de - diq - dsb - dv - dz - ee - el - eml - en - eo - es - et - eu - ext - fa - ff - fi - fiu_vro - fj - fo - fr - frp - fur - fy - ga - gan - gd - gl - glk - gn - got - gu - gv - ha - hak - haw - he - hi - hif - ho - hr - hsb - ht - hu - hy - hz - ia - id - ie - ig - ii - ik - ilo - io - is - it - iu - ja - jbo - jv - ka - kaa - kab - kg - ki - kj - kk - kl - km - kn - ko - kr - ks - ksh - ku - kv - kw - ky - la - lad - lb - lbe - lg - li - lij - lmo - ln - lo - lt - lv - map_bms - mdf - mg - mh - mi - mk - ml - mn - mo - mr - mt - mus - my - myv - mzn - na - nah - nap - nds - nds_nl - ne - new - ng - nl - nn - no - nov - nrm - nv - ny - oc - om - or - os - pa - pag - pam - pap - pdc - pi - pih - pl - pms - ps - pt - qu - quality - rm - rmy - rn - ro - roa_rup - roa_tara - ru - rw - sa - sah - sc - scn - sco - sd - se - sg - sh - si - simple - sk - sl - sm - sn - so - sr - srn - ss - st - stq - su - sv - sw - szl - ta - te - tet - tg - th - ti - tk - tl - tlh - tn - to - tpi - tr - ts - tt - tum - tw - ty - udm - ug - uk - ur - uz - ve - vec - vi - vls - vo - wa - war - wo - wuu - xal - xh - yi - yo - za - zea - zh - zh_classical - zh_min_nan - zh_yue - zu -

Static Wikipedia 2006 (no images)

aa - ab - af - ak - als - am - an - ang - ar - arc - as - ast - av - ay - az - ba - bar - bat_smg - bcl - be - be_x_old - bg - bh - bi - bm - bn - bo - bpy - br - bs - bug - bxr - ca - cbk_zam - cdo - ce - ceb - ch - cho - chr - chy - co - cr - crh - cs - csb - cu - cv - cy - da - de - diq - dsb - dv - dz - ee - el - eml - eo - es - et - eu - ext - fa - ff - fi - fiu_vro - fj - fo - fr - frp - fur - fy - ga - gan - gd - gl - glk - gn - got - gu - gv - ha - hak - haw - he - hi - hif - ho - hr - hsb - ht - hu - hy - hz - ia - id - ie - ig - ii - ik - ilo - io - is - it - iu - ja - jbo - jv - ka - kaa - kab - kg - ki - kj - kk - kl - km - kn - ko - kr - ks - ksh - ku - kv - kw - ky - la - lad - lb - lbe - lg - li - lij - lmo - ln - lo - lt - lv - map_bms - mdf - mg - mh - mi - mk - ml - mn - mo - mr - mt - mus - my - myv - mzn - na - nah - nap - nds - nds_nl - ne - new - ng - nl - nn - no - nov - nrm - nv - ny - oc - om - or - os - pa - pag - pam - pap - pdc - pi - pih - pl - pms - ps - pt - qu - quality - rm - rmy - rn - ro - roa_rup - roa_tara - ru - rw - sa - sah - sc - scn - sco - sd - se - sg - sh - si - simple - sk - sl - sm - sn - so - sr - srn - ss - st - stq - su - sv - sw - szl - ta - te - tet - tg - th - ti - tk - tl - tlh - tn - to - tpi - tr - ts - tt - tum - tw - ty - udm - ug - uk - ur - uz - ve - vec - vi - vls - vo - wa - war - wo - wuu - xal - xh - yi - yo - za - zea - zh - zh_classical - zh_min_nan - zh_yue - zu