Conseils pour jouer au golf à Tcl

15

Quels conseils généraux avez-vous pour jouer au golf à Tcl? Je suis à la recherche d'idées pouvant être appliquées aux problèmes de golf de code en général qui sont au moins quelque peu spécifiques à Tcl (par exemple, "supprimer les commentaires" n'est pas une réponse). Veuillez poster un pourboire par réponse.

Johannes Kuhn
la source

Réponses:

7

Utilisez lmapplutôt foreach. Cela nécessite Tcl 8.6.

La syntaxe est la même, mais lmaprenvoie une liste avec le résultat de chaque boucle.

Johannes Kuhn
la source
4

Sur ma réponse /codegolf//a/107557/29325 je peux démontrer:

  1. set j 0;while \$j<$n;{...;incr j}Est généralement plus court que l'équivalentfor {set j 0} {$j<$n} {incr j} {...}

  2. Lorsque la variable de bouclage commence à 1, nous pouvons faire l'incrément dans le cadre de la whilecondition de test, en évitant d'écrire avant set i 1inutilement: while {[incr i]<=$n} {...}au lieu deset i 1;while \$i<=$n;{...;incr i}

ATTENTION : On ne peut faire que 2. dans le cas d'une boucle extérieure! Je n'ai pas pu l'appliquer à ma jvariable car elle doit être réinitialisée à 1 à l'extérieur de sa propre boucle intérieure! Et incr jacquerrait la valeur qui a été définie à la dernière étape de la boucle interne, au lieu de saisir une variable non définiej pour l'assumer 0et l'incrémenter 1!

sergiol
la source
4

Parfois, il vaut la peine d'utiliser time {script} nnest le nombre d'itérations au lieu d'une normale whileou d'une forboucle. Bien que timel'objectif ne soit pas de boucler, l'effet obtenu est le même.

J'ai récemment modifié mes propres réponses en suivant cette direction.

MISE À JOUR: Je viens de découvrir un piège facile à tomber: vous ne pouvez pas remplacer un forou un whilepar un timebloc, s'il contient un breakou un continue.

sergiol
la source
3

Utilisez le shell interactif. Cela vous permet d'abréger les noms de commande tant qu'une seule commande commence par les lettres restantes.

Exemple:

  • gets -> ge
  • lassign -> las
  • expr -> exp
  • puts -> pu

Et les solutions interactives sont gratuites: P

Contexte :

Lorsqu'il tclshs'exécute avec un terminal comme périphérique d'entrée, il définit la variable tcl_interactivesur 1. Cela provoque unknown(procédure par défaut qui sera appelée si une commande est introuvable) la recherche de commandes commençant par ce nom.

Inconvénient: il imprimera le résultat de chaque ligne, utilisez à la ;place des nouvelles lignes.
Ohh, et il pourrait invoquer des commandes externes comme w, ce qui est une bonne abréviation de while.

Johannes Kuhn
la source
3

Les sous-commandes et options peuvent (généralement) être abrégées. Cela peut économiser beaucoup, mais vous devez tester car tout ne peut pas être raccourci de cette façon ( regsubles options de ne peuvent pas, par exemple).

Vous pouvez ensuite l'utiliser avec la magie de namespacefaire des choses vraiment mauvaises. Considère ceci:

namespace exp *;namespace en cr -c ?

Après cela, ?est maintenant une commande magique qui vous permet d'abréger n'importe quelle commande globale Tcl, et le tout sans l'incertitude désagréable de déconner unknown.

Associés Donal
la source
2

J'utilise Tcl 8.0.5, mais je pense que les éléments suivants s'appliquent à toutes les versions récentes.

  1. Utilisez renamepour renommer rename:

    rename rename &
    

    Le &peut être n'importe quel identifiant; &me rappelle juste des "références" en C.

  2. Utilisez le renommé renamepour renommer set:

    & set =
    

    Encore une fois, le =peut être n'importe quel identifiant; =est juste intuitif pour moi.

  3. Maintenant, renommez d'autres commandes qui méritent d'être renommées, par exemple

    & regsub R
    & string S
    & while W
    

    Une commande mérite d'être renommée si, compte tenu de sa longueur n , et des occurrences k , k (n-1) - (n + 4)> 0 . Résolvant pour k , la formule devient k > (n+4)/(n-1). Voici un tableau de référence qui vous facilite la tâche:

    length of       minimum         example(s)
    command         occurrences
    ------------------------------------------------
    2               6               if (consider renaming to "?")
    3               4               for, set (consider renaming to "=")
    4               3               eval, expr, incr (consider renaming to "+"), info, join, proc, puts, scan
    5               3               break, catch, lsort, split, subst, trace, unset, while
    6               3               format, lindex, lrange, regexp, regsub, rename, return, string, switch
    7               2               foreach, lappend, linsert, llength, lsearch, unknown
    .               2               lreplace
    .               2               continue
    .               2               
    
  4. Ensuite, compactez les sous-commandes fréquemment utilisées comme

    = I index
    = L length
    

    afin que vous puissiez faire des choses comme

    S $I $x 7
    S $L $x
    
  5. Quelques miscellanea évidents:

    1. lappend peut définir le premier élément d'une liste s'il n'existe pas encore (pas besoin d'initialiser).
    2. Vous pouvez définir des tableaux sans utiliser array, par exemple set doesNotExist(7) 43 .
    3. Vous pouvez utiliser des chaînes ( "a b c") au lieu de [list a b c].
    4. Vous pouvez interpoler dans les chaînes comme ceci: foo${a}bar.
    5. Vous pouvez utiliser two\ wordsplutôt que "two words". (Souvenez-vous en général que pour les chaînes contiguës sans espaces, les guillemets doubles peuvent être omis!)
    6. Vous pouvez presque toujours réécrire fors en whiles pour enregistrer un ou deux caractères, car un whilepeut simultanément vérifier et incrémenter tandis qu'un forutilise des blocs séparés.
  6. Pour les programmes plus importants, voici une astuce à laquelle j'ai pensé mais que je n'ai pas encore appliquée:

    proc unknown {c args} {eval [info commands $c*] $args}
    

    Cela émule des abréviations de commandes interactives! Il coûte 54 caractères, mais vous pouvez maintenant l'utiliser jpour join, sppour split, stpour string, wpour while, etc.

Andrew Cheong
la source
1
Si vous souhaitez émuler des abréviations interactives, utilisezinfo script {};set tcl_interactive 1
Johannes Kuhn
Cool merci! Je vous ai crédité ici . Il y avait cependant quelques problèmes avec cette technique, que je n'ai pas rencontrés avec l' unknownitinéraire: voir ici et ici .
Andrew Cheong
La question demande des conseils quelque peu spécifiques à Tcl. L'opérateur ternaire est inclus dans les conseils pour toutes les langues .
Peter Taylor
@PeterTaylor - Merci, j'ai supprimé cette astuce.
Andrew Cheong
2

sinon est facultatif

Comme il est dit sur la page if , elseest implicite sur ifles constructions de blocs. Donc qu'est-ce

if ... {} else {}

peut devenir

if ... {} {}

comme vous pouvez le voir sur certaines de mes réponses.

sergiol
la source
1

Peut-être devrait-il être intégré sur une autre réponse, mais voilà:

Quand a procn'a qu'un seul paramètre, il peut s'écrire

proc p a {DO THINGS}

au lieu de

proc p {a} {DO THINGS}

La même chose s'applique à deux paramètres procutilisant une barre oblique inverse; il peut s'écrire

proc p a\ b {DO THINGS}

au lieu de

proc p {a b} {DO THINGS}

Pour un nombre plus élevé de paramètres, le {}code est plus court.

sergiol
la source
1

Parfois, il vaut la peine de remplacer les deux setinstructions pour concaténer des chaînes par une seule lappendinstruction. Sur une construction comme, on peut substituer

set s ""

loop {
    # ...
    set s $s\X
}

par

loop {
    # ...
    append s X
}

La appendcommande a un incrcomportement similaire, qui initialise une variable non encore définie.

Faites attention à ne pas vous tromper appendenlappend

sergiol
la source
1

Si vous gérez une liste avec une opération qui entrelace syntaxiquement entre chaque élément, vous pouvez parfois joinutiliser des éléments pour effectuer une opération spécifique, au lieu de la traverser.

Sur /codegolf//a/127042/29325 il y a un exemple:

puts \n[expr [join [split [read stdin]] +]]

Il read stdindonne 23 214 52alors split donnera la liste {23 214 52}. Après, [join {23 214 52} +]retournera la chaîne 23+214+52. Enfin, expr 23+214+52le travail de sommation

sergiol
la source
Dans ce cas, vous pouvez omettre le split.
Johannes Kuhn
@JohannesKuhn: merci. Terminé.
sergiol
1

Si vous avez de gros codes, il est possible d'éviter plusieurs exprutilisations namespace pat tcl::mathopau début. Il fournit une opération de préfixe-syntaxe comme une fonction Tcl régulière. Par exemple:

namespace pat tcl::mathop
set sum [+ 1 2 3]
set prod [* {*}{1 2 3 4}]
puts $sum\ $prod

Voir la page officielle du doc ​​mathop

David
la source
0

Lorsque plusieurs variables se trouvent setsur des lignes suivantes, vous pouvez utiliser une lassignau lieu de plusieurs setinstructions pour obtenir le même effet.

Un exemple est ma propre réponse /codegolf//a/105789/29325

Pour décider, il suffit de pondérer le nombre de variables (en supposant des variables à 1 lettre, comme cela est prévu lors du golf):

  • <5, setest golfeur

  • = 5, setet lassigngénérer le même nombre d'octets

  • > 5, lassignest golfeur

sergiol
la source