LISP-intro – del 1

Lister og deres elementer

Nu går vi så til at se på helt basal programkode, og da navnet LISP jo står for LISt Processing language, er det nok meget logisk at begynde med at se på, hvad en liste er for noget. Her er nogle eksempler på lister:

  • (1 5 8 2 0 9) = liste af seks heltal.
  • (“Hund” “Kat” “Kanin” “Hest” “Ko”) = liste af fem tekst-elementer (vi kalder dem for tekst-strenge .. På engelsk strings)
  • (1.234 5.76 3.936) = liste af tre reelle tal. Det kunne f.eks. være en x-, y- og z-værdi for et punkt.
  • (<Entity name: 23a008a4470> <Entity name: 23a008a4480>) = liste af to entity names. Ethvert objekt i AutoCAD har et såkaldt entity name.
  • (T nil T T nil) = en liste af sande og falske værdier. T står for True, og nil står for False eller Ingenting.

Bemærk, at listerne ovenfor er omsluttet af parenteser. Det er centralt i AutoLisp. Alt er omsluttet af parenteser, og hele ideen er, at man skal kunne gøre noget med de elementer, der er i listerne. Derfor findes der en masse indbyggede funktioner, som kan hjælpe os med at bruge data i listerne til noget fornuftigt.

Funktionen list

Funktionen list har signaturen

(list[expr …])

hvor list er navnet på funktionen
og [expr …] er de elementer, der skal være i listen.
Funktionen returnerer en liste.

Her opretter vi en liste med fem elementer:

(list “Hund” “Kat” “Kanin” “Hest” “Ko”)

… som returnerer listen (“Hund” “Kat” “Kanin” “Hest” “Ko”)

En anden metode til at oprette en liste er at anvende funktionen quote. Der er dog en forskel, som du indtil videre ikke behøver at bekymre dig om.
Sådan her ser funktionen ud: (quote (“Hund” “Kat” “Kanin” “Hest” “Ko”))
Funktionen kan også skrives sådan her: ‘(“Hund” “Kat” “Kanin” “Hest” “Ko”)
Funktionen car.

Funktionen car anvendes til at finde det første element i en liste og har signaturen …

(car list)

hvor car er navnet på funktionen
og list er den liste, vi gerne vil udtage første element fra.
Funktionen returnerer det første element i en liste.

Prøv evt. at skrive følgende på AutoCADs kommandolinje:

(car (list “Hund” “Kat” “Kanin” “Hest” “Ko”))

Det, der sker er, at AutoLISP så at sige arbejder sig indefra og ud. Først evalueres den inderste funktion list, som returnerer listen (“Hund” “Kat” “Kanin” “Hest” “Ko”). Derefter bearbejder den yderste funktion car listen og returnerer det første element i listen. Resultatet bliver tekststrengen ”Hund”.
Vi siger, at funktionen list i dette tilfælde er indlejret (nested) i funktionen car, og det kommer vi til at se nærmere på lidt senere.

Funktionerne cadr og caddr

På tilsvarende måde kan vi anvende funktionen cadr for at få returneret det andet element i listen). Funktionen cadr har samme signatur som car.

Her er et eksempel, hvor vi har anvendt cadr

(cadr (list “Hund” “Kat” “Kanin” “Hest” “Ko”))

Funktionen cadr returnerer det andet element i listen, som i dette tilfælde er ordet ”Kat”.

Funktionen caddr svarer fuldstændig til cadr, men returnerer bare det tredie element i en liste.

Funktionen nth

Men hvad så, hvis vi f.eks. gerne vil have fat i det fjerde element i listen?

I det tilfælde kan vi benytte os af funktionen nth, som kræver to såkaldte argumenter. De to argumenter fortæller i dette tilfælde funktionen dels hvilken position i listen, vi gerne vil finde frem og dels hvilken liste det er, vi ønsker at søge i.

Signaturen for funktionen nth er dette …

(nth n lst)

hvor nth er navnet på funktionen
n er positionsnummer (heltal fra 0 og opefter) for det element i listen, vi gerne vil tilgå
og lst er den liste, vi vil søge i
Funktionen returnerer elementet med positionsnummerer n.

Som nævnt vil vi gerne hente det fjerde element i listen, og det fjerde element i listen har positionsnummeret 3, fordi vi starter fra nul og tæller op.
Det argument n, vi vil putte ind i funktionen, er altså 3, og argumentet lst er den liste, vi vil søge i (”Hund” ”Kat” ”Kanin” ”Hest” ”Ko”)
Vi skriver derfor …

(nth 3 (list “Hund” “Kat” “Kanin” ”Hest” “Ko”))

Hvis vi formulerer funktionen på almindeligt dansk, kunne vi skrive noget lignende ”Find det element i listen (”Hund” ”Kat” ”Kanin” ”Hest” ”Ko”), der har positionsnummeret 3 (lig med det fjerde element, fordi vi tæller op fra nul).
Resultatet bliver “Hest” … På AutoCADs kommandolinje ser det sådan her ud …

På tilsvarende måde ville (nth 4 (list ”Hund” ”Kat” ”Kanin” ”Hest” ”Ko”)) returnere resultatet ”Ko”.
Hvis vi angiver værdien 5 som n-argumentet, får vi resultatet nil, som blot betyder ingenting, hvilket giver mening, da der jo kun er fem elementer i listen, og intet element derfor vil have positionsnummeret 5 (fordi vi tæller op fra nul).

Oprettelse af en variabel

Lad os sige, at vi gerne vil gøre det hele lidt nemmere for os selv, så vi ikke hele tiden skal skrive hele udtrykket (list ”Hund” ”Kat” ”Kanin” ”Hest” ”Ko”), hver gang vi vil tilgå den liste. Derfor gemmer vi listen som en variabel i AutoCAD-dokumentets hukommelse, og til det formål har vi funktionen setq, som sætter værdien af et eller flere symboler til en eller flere associerede værdier.

Setq har signaturen …

(setq sym expr [sym expr], …)
  • setq = funktionens navn
  • sym = det symbol/variabelnavn, vi ønsker at oprette
  • expr = det udtryk/expression, vi ønsker at gemme i variablen. Det kan være et heltal, et reelt tal, en tekststreng, en liste, en fil, et objektnavn (entity name), T (True) eller ingenting (nil)

Vi vil som sagt gerne gemme listen (”Hund” ”Kat” ”Kanin” ”Hest” ”Ko”) i en variabel. Lad os kalde listen PATTEDYR.
Det symbol (variabel), vi gerne vil bruge, har altså navnet PATTDYR, og det udtryk, vi gerne vil gemme, er listen (”Hund” ”Kat” ”Kanin” ”Hest” ”Ko”). Det ser sådan her ud:

(setq PATTEDYR (list “Hund” “Kat” “Kanin” “Hest” “Ko”))

Hvis vi skriver det på AutoCADs kommandolinje, får vi resultatet
(“Hund” “Kat” “Kanin” “Hest” “Ko”), og vi vil efterfølgende kunne kalde denne liste frem ved at skrive !PATTEDYR på kommandolinjen.

Bemærkning 1:
Hvis vi også havde en anden liste (“And” “Gås” “Spurv” “Ørn” “Krage”), kunne vi faktisk i samme funktion gemme denne liste under navnet FUGLE.
Det samlede udtryk ville se således ud …
(setq
PATTEDYR (list “Hund” “Kat” “Kanin” “Hest” “Ko”)
FUGLE (list “And” “Gås” “Spurv” “Ørn” “Krage”)
)
Bemærkning 2:
Faktisk er det ligegyldigt, om vi skriver variabelnavne med stort eller småt eller en blanding. F.eks. er !PATTEDYR og !pattedyr det samme.
AutoLISP er ikke følsom overfor store og små bogstaver. Jeg har bare valgt at skrive variabelnavnet med stort, så det adskiller sig for AutoLISP-funktionerne. Du kan gøre det, som det passer dig bedst.

Da nu listen er gemt i variablen PATTEDYR, kan vi nu nemt tilgå den.
F.eks. vil (nth 3 PATTEDYR) være fuldstændig det samme som (nth 3 (list “Hund” “Kat” “Kanin” ”Hest” “Ko”)). Begge funktioner vil returnere værdien ”Hest”.
På samme måde vil (car PATTEDYR) give fuldstændig samme resultat som (car (list “Hund” “Kat” “Kanin” “Hest” “Ko”)). Begge funktioner vil returnere værdien ”Hund”.

Næste side: Struktur i programkoden