« Tcl: Iterazioni: comandi continue e breakAppunti di Tcl/TkTcl: Creazione di nuovi comandi: comandi proc e return »

Tcl

Iterazioni

una implementazione Tcl del comando do

In Tcl puro non esiste l'equivalente dell'istruzione do ... while del C. Tuttavia data la natura estendibile di Tcl, è possibile implementarsela! Tcl è uno dei pochi linguaggi che permette di implementare nuove strutture di controllo in modo semplice. Questo è dovuto al fatto che in Tcl ci sono solo comandi, quindi anche le strutture di controllo sono dei comandi, ovvero possono essere definite come comandi o procedure, con l'aiuto di qualche altro comando specializzato.

Per esemplificare riportiamo di seguito l'implementazione di un comando do con la seguente semplice sintassi, simile a quella di while(n):

while body test
#!/bin/sh
# restart using tclsh \
exec tclsh8.4 "$0" "$@"

proc do {body test} {
  set code [catch {uplevel 1 $body} string]
  switch $code {
    0 {
      # TCL_OK
    }

    1 -
    2 {
      # TCL_ERROR, TCL_RETURN
      return -code $code $string
    }

    3 {
      # TCL_BREAK
      return
    }

    4 {
      # TCL_CONTINUE
    }
  }

  uplevel [list while $test $body]
}

Ecco uno spezzone di codice di test, che permette di giocare ad "indovina-un-numero":

# test:
# the guess-a-number game

set num [expr int(1+rand()*10)]
set tries 0

puts {Guess a number between [1-10].}
do {
  incr tries
  puts -nonewline "try #$tries: "
  flush stdout

  if {[gets stdin line]==-1 || [scan $line %d guess]!=1} {
    break
  }

  if {$guess==$num} {
    puts "You won with $tries tries."
    exit
  }
} {$tries<5}

puts "Game over. Number was $num."

Alcune osservazioni sull'implementazione di do:

Il package control di Tcllib (una collezione di moduli di utilità per Tcl) fornisce un comando do ancora più flessibile, in quanto è possibile scegliere se la condizione deve essere una condizione di continuazione (semantica tipo while) o di terminazione del ciclo (semantica tipo until). Per usarlo basta caricare il package e utilizzare il nome pienamente qualificato del comando o importarlo nel namespace corrente:

package require control

control::do {
  # corpo del ciclo
  # ...
} while {test di continuazione} 

namespace import ::control::*
do {
  # corpo del ciclo
  # ...
} until {test di terminazione}

Vedere inoltre la manpage control(n), sezione LIMITATIONS, per una descrizione di una sottile limitazione legata alla gestione degli errori, di cui soffrono purtroppo tutti i comandi che implementano nuove strutture di controllo direttamente in Tcl, senza far ricorso ad estensioni scritte in C.

« Tcl: Iterazioni: comandi continue e breakAppunti di Tcl/TkTcl: Creazione di nuovi comandi: comandi proc e return »