Lisp »Tips 'n Tricks
»Uso di Foreach (I) »(II)
Foreach valuta tutte le espressioni dei membri di una lista:
(foreach nome lista istruzioni).
La funzione esamina la lista, assegna ogni elemento della lista a nome e valuta tutte le istruzioni al suo interno.
Ad esempio questo lisp legge con (foreach) il contenuto di una lista e controlla se l'elemento nome è un numero reale o intero con la funzione (numberp elem).
Numberp restituisce T se elem è un numero, altrimenti restituisce nil.
Se non è (if not) vero (T) allora stampa (princ) l'elemento della lista (nome).
(defun for ()
(setq lista (list "io" 0 -1 2 -3 7.5 " e " -0.5 "la talpa" 13))
(foreach nome lista
(if (not (numberp nome))
(princ nome)
)
)
(princ)
)
Command: (for)
io e la talpa
In un certo qual modo la funzione (foreach) può sostituire l'istruzione for presente in altri linguaggi di programmazione.
Ecco un esempio, prima in linguaggio Pascal e poi tradotto in Lisp.
"Il programma (graph.pas) mette in diagramma una funzione reale f(X) con l'asse X che si sviluppa verticalmente, ed appone un asterisco nelle posizioni corrispondenti alle coordinate.
La posizione dell'asterisco si ottiene calcolando Y=f(X), moltiplicando per un fattore di scala, arrotondando il prodotto al successivo numero intero e poi aggiungendo una costante e lasciando che l'asterisco sia preceduto da tanti spazi bianchi quanto è il valore del prodotto arrotondato suddetto" (op. cit)
graph.pas
(*
Graph.pas
Generate graphic representation of the function:
f(x) = exp(-x)*sin(2*pi*x)
Dal testo: 'Manuale del Pascal', K. Jensen, N. Wirth
*)
program Graph(Output);
const
XLines=16;
Scale=32;
ZeroY=34;
XLimit=32;
var
Delta: Real;
TwoPi: Real;
X,Y: Real;
Point: Integer;
YPosition: Integer;
begin
Delta:=1/Xlines;
TwoPi:=8*ArcTan(1.0);
for Point:=0 to XLimit do
begin
X := Delta * Point;
Y := Exp(-X) * Sin(TwoPi*X);
YPosition := Round(Scale*Y) + ZeroY;
repeat
Write(Output, ' ');
YPosition := YPosition - 1
until YPosition = 0;
Writeln(Output, '*')
end
end.
|
graph.lsp
;|
Graph.lsp by Claudio Piccini (29/02/2004)
www.cg-cad.com
Salva su file graph.txt il diagramma della funzione:
f(x) = exp(-x)*sin(2*pi*x)
Basato su:
Program 4.7 - "Manuale del Pascal",
K. Jensen, N.Wirth
|;
(defun c:graph ( )
(setq Xlines 16)
(setq Scale 32)
(setq ZeroY 34)
(setq Delta (/ 1.0 Xlines))
(setq i 0)
(while (< i 33)
(setq Xlimit (append Xlimit (list i)))
(setq i (1+ i))
)
(setq nomeDir (getvar "dwgprefix"))
(setq nf (strcat nomeDir "graph.txt"))
(setq f1 (open nf "w"))
(foreach Point Xlimit
(setq x (* Delta Point))
(setq y (*
(exp (* x -1))
(sin (* 2 pi x))
)
)
(if (>= (* Scale y) 0)
(setq Round (fix (+ (* Scale y) 0.5)))
(setq Round (fix (- (* Scale y) 0.5)))
)
(setq YPosition (+ Round ZeroY))
(setq spazio "")
(repeat YPosition
(setq spazio (strcat spazio " "))
(setq YPosition (- YPosition 1))
)
(setq asterisco (strcat spazio "*"))
(write-line asterisco f1)
)
(close f1)
)
;;;eof
|
Test del lisp
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
|
In Autolisp non esiste la funzione round(R).
Che cos'è la funzione round(R)?
Con R numero reale il risultato di round(R) è un numero intero arrotondato, cioè round(R) equivale a trunc(R + 0.5) se R>=0 e a trunc(R - 0.5) se R<0.
Che cos'è la funzione trunc(R)?
Con R numero reale il risultato di trunc(R) è un numero intero troncato, ad esempio trunc(3.7)=3 e trunc(-3.7)=-3.
Esiste in Autolisp una funzione uguale a trunc? Sì, è la funzione (fix)
Quindi l'istruzione in Pascal:
YPosition := Round(Scale*Y) + ZeroY;
Si traduce così in Autolisp:
(if (>= (* Scale y) 0)
(setq Round (fix (+ (* Scale y) 0.5)))
(setq Round (fix (- (* Scale y) 0.5)))
)
(setq YPosition (+ Round ZeroY))
Infine notare che l'istruzione in Pascal:
Delta:=1/Xlines;
Cambia così in Autolisp:
(setq Delta (/ 1.0 Xlines))
Questo perché Xlines è dichiarato come const e Delta come variabile Real; in Autolisp non esiste la distinzione tra l'intestazione e il blocco del programma.
Ad esempio con questo sorgente pascal:
program Prova(Output);
(* intestazione del programma *)
const
x = 12;
var
y: Real;
(* blocco del programma *)
begin
y := 1/x;
Writeln('Y=', y)
end.
Si ottiene questo output: Y= 8.3333333333E-02
Invece in Autolisp:
Command: (setq x 12)
12
Command: (setq y (/ 1 x))
0
Quindi si deve forzare in questo modo:
Command: (setq y (/ 1.0 x))
0.0833333
Per ultimo (ma non ultimo) notare che la funzione pascal Exp(-X) si trasforma nell'istruzione in autolisp (exp (* x -1))
Lisp »Tips 'n Tricks
Ultimo Aggiornamento_Last Update: 29 Febbraio 2004
|