cg-Cad

Lisp »Tips 'n Tricks »Uso di Repeat

Repeat valuta ogni espressione un numero specifico di volte e restituisce il valore dell'ultima espressione.
(repeat int espr...)
Int deve essere un numero intero positivo. Ad esempio:
(setq a 1 b 1 n 4)
(repeat n
(setq a (+ a 1))
(setq b (+ b 1))
)
Risultato -> a=5, b=5.

© by Carl BarksForse il tutto è banale e ovvio però l'uso acritico e scontato di una istruzione può portare a generare errori (bugs) nell'esecuzione del programma o alla presenza di bugs indifferenti nel codice sorgente.


Ad esempio nel tradurre il programma graph.pas in graph.lsp (vedi uso di foreach (I)) ho tradotto male questa parte di codice:

repeat
   Write(Output, ' ');
   YPosition := YPosition - 1
until YPosition = 0;

(repeat YPosition
   (setq spazio (strcat spazio " ")) 
   (setq YPosition (- YPosition 1))
)

In Pascal l'istruzione repeat ha la forma:
repeat
istruzioni;
contatore (=variabile)
until test contatore;

mentre in Autolisp è
(repeat contatore (=costante)
(istruzioni)
)

Insomma ho confuso forma con contenuto, ma un errore formale causa sempre un errore nel contenuto?

Ecco un test con repeat:

(defun prova ()
 (setq Y 10)
 (repeat Y
  (setq Y (1+ Y))
  (princ "Y dentro=")
  (princ Y)
  (princ "\n")
 )
 (princ)
)

Command: (prova)
Y dentro=11
Y dentro=12
Y dentro=13
Y dentro=14
Y dentro=15
Y dentro=16
Y dentro=17
Y dentro=18
Y dentro=19
Y dentro=20

Repeat ripete per 10 volte (Y=10) l'istruzione che dichiara al mondo che Y non è 10 ma 11, 12, 13... Repeat è indifferente al mutare del contenuto della variabile Y all'interno del ciclo: allora Y fuori (prima del ciclo) e Y fuori (dopo il ciclo) sono due variabili diverse?

(defun prova ()
 (setq Y 10)
 (princ "Y prima=")
 (princ Y)
 (princ "\n")
 (repeat Y
  (setq Y "talpa")
  (princ "Y dentro=")
  (princ Y)
  (princ "\n")
 )
 (princ "Y dopo=")
 (princ Y)
 (princ)
)

Command: (prova)
Y prima=10
Y dentro=talpa
Y dentro=talpa
Y dentro=talpa
Y dentro=talpa
Y dentro=talpa
Y dentro=talpa
Y dentro=talpa
Y dentro=talpa
Y dentro=talpa
Y dentro=talpa
Y dopo=talpa

Notare che repeat esegue n volte il suo contenuto, mentre repeat ad ogni ciclo fa un test alla variabile n.
Questo codice da un punto di vista formale è più corretto:
(setq a 1 b 1)
(repeat 4
(setq a (+ a 1))
(setq b (+ b 1))
)

Lisp »Tips 'n Tricks

Ultimo Aggiornamento_Last Update: 1 Marzo 2004