Consejos para jugar golf en Tcl

15

¿Qué consejos generales tienes para jugar al golf en Tcl? Estoy buscando ideas que se puedan aplicar a los problemas de golf de código en general que sean al menos algo específicos para Tcl (por ejemplo, "eliminar comentarios" no es una respuesta). Por favor, publique un consejo por respuesta.

Johannes Kuhn
fuente

Respuestas:

7

Usar en su lmaplugar foreach. Esto requiere Tcl 8.6.

La sintaxis es la misma, pero lmapdevuelve una lista con el resultado de cada ciclo.

Johannes Kuhn
fuente
4

En mi respuesta /codegolf//a/107557/29325 puedo demostrar:

  1. Generalmente set j 0;while \$j<$n;{...;incr j}es más corto que el equivalentefor {set j 0} {$j<$n} {incr j} {...}

  2. Cuando la variable de bucle comienza en 1, podemos hacer el incremento como parte de la whilecondición de prueba, evitando escribir antes set i 1innecesariamente: en while {[incr i]<=$n} {...}lugar deset i 1;while \$i<=$n;{...;incr i}

ATENCIÓN : ¡Uno solo puede hacer 2. en el caso de un bucle externo! ¡No pude aplicarlo a mi jvariable ya que necesita restablecerse a 1 en el exterior de su propio bucle interno! ¡Y incr jadquiriría el valor que se estableció en el último paso del bucle interno, en lugar de tomar una variable indefinidaj para suponer 0e incrementarla 1!

sergiol
fuente
4

A veces vale la pena usar time {script} ndonden está el número de iteraciones en lugar de un normal whileo un forbucle. Aunque timeel propósito no es circular, el efecto logrado es el mismo.

Hice cambios recientemente a mis propias respuestas siguiendo esta dirección.

ACTUALIZACIÓN: Acabo de descubrir una trampa fácil de caer: no puede reemplazar a foro a whilepor un timebloque, si contiene a breako a continue.

sergiol
fuente
3

Usa el shell interactivo. Esto le permite abreviar los nombres de los comandos siempre que solo 1 comando comience con las letras restantes.

Ejemplo:

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

Y las soluciones interactivas son gratuitas: P

Antecedentes :

Cuando se tclshejecuta con un terminal como dispositivo de entrada, establece la variable tcl_interactiveen 1. Esto provoca unknown(procedimiento predeterminado que se llamará si no se puede encontrar un comando) buscar comandos que comiencen con ese nombre.

Desventaja: imprimirá el resultado de cada línea, use en ;lugar de nuevas líneas.
Ohh, y podría invocar comandos externos como w, que es una buena abreviatura de while.

Johannes Kuhn
fuente
3

Los subcomandos y las opciones pueden (generalmente) abreviarse. Esto puede ahorrar bastante, pero debe probarlo, ya que no todo se puede acortar de esta manera (regsub las opciones no pueden, por ejemplo).

Luego puedes usar esto con la magia de namespacehacer algunas cosas verdaderamente malvadas. Considera esto:

namespace exp *;namespace en cr -c ?

Después de eso, ?ahora es un comando mágico que le permite abreviar cualquier comando Tcl global, y todo sin la desagradable incertidumbre de perder el tiempo unknown.

Compañeros de Donal
fuente
2

Estoy usando Tcl 8.0.5, pero creo que lo siguiente es aplicable a todas las versiones recientes.

  1. Use renamepara renombrar rename:

    rename rename &
    

    El &puede ser cualquier identificador; &solo me recuerda las "referencias" en C.

  2. Use el renombrado renamepara renombrar set:

    & set =
    

    De nuevo, =puede ser cualquier identificador; =Es intuitivo para mí.

  3. Ahora, cambie el nombre de otros comandos que vale la pena renombrar, por ejemplo

    & regsub R
    & string S
    & while W
    

    Vale la pena renombrar un comando si, dada su longitud n , y las ocurrencias k , k (n-1) - (n + 4)> 0 . Resolviendo para k , la fórmula se convierte en k > (n+4)/(n-1). Aquí hay una tabla de referencia que lo hace fácil:

    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. A continuación, compacte subcomandos de uso frecuente como

    = I index
    = L length
    

    para que puedas hacer cosas como

    S $I $x 7
    S $L $x
    
  5. Algunas misceláneas obvias:

    1. lappend puede establecer el primer elemento de una lista si aún no existe (no es necesario inicializar).
    2. Puede configurar matrices sin usar array, p . Ej. set doesNotExist(7) 43 .
    3. Puede usar cadenas ( "a b c") en lugar de [list a b c].
    4. Se puede interpolar en las cadenas de este modo: foo${a}bar.
    5. Puedes usar en two\ wordslugar de "two words". (¡Recuerde en general que para cadenas contiguas sin espacios, se pueden omitir comillas dobles!)
    6. Casi siempre puede reescribir fors como whiles para guardar un carácter o dos, ya que whilepuede verificar e incrementar simultáneamente mientras forusa bloques separados.
  6. Para programas más grandes, aquí hay un truco en el que pensé pero que aún no he aplicado:

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

    ¡Esto emula abreviaturas de comandos interactivos! Cuesta 54 caracteres, pero ahora puede usar jpara join, sppara split, stpara string, wpara while, etc.

Andrew Cheong
fuente
1
Si desea emular abreviaturas interactivas, useinfo script {};set tcl_interactive 1
Johannes Kuhn
¡Genial, gracias! Te he acreditado aquí . Sin embargo, hubo algunos problemas con esa técnica que no encontré con la unknownruta: ver aquí y aquí .
Andrew Cheong
La pregunta pide consejos que son algo específicos para Tcl. El operador ternario se incluye en las sugerencias para todos los idiomas .
Peter Taylor
@PeterTaylor - Gracias, he eliminado esa sugerencia.
Andrew Cheong
2

más es opcional

Como se dice en la página del manual , elseestá implícito en iflas construcciones de bloques. Entonces que es

if ... {} else {}

puede llegar a ser

if ... {} {}

como puedes ver en algunas de mis respuestas.

sergiol
fuente
1

Puede ser que debería integrarse en otra respuesta, pero aquí va:

Cuando a procsolo tiene un parámetro, se puede escribir como

proc p a {DO THINGS}

en lugar de

proc p {a} {DO THINGS}

Lo mismo se aplica a dos parámetros procusando una barra invertida; se puede escribir como

proc p a\ b {DO THINGS}

en lugar de

proc p {a b} {DO THINGS}

Para un mayor número de parámetros, el {}código de representación más corto.

sergiol
fuente
1

A veces vale la pena reemplazar las dos setdeclaraciones para concatenar cadenas por una sola lappenddeclaración. En una construcción como, uno puede sustituir

set s ""

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

por

loop {
    # ...
    append s X
}

El appendcomando tiene un incrcomportamiento similar, que inicializa una variable aún no definida.

Tenga cuidado de no equivocarse appendporlappend

sergiol
fuente
1

Si está manejando una lista con una operación que se entrelaza sintácticamente entre cada elemento, a veces puede joinhacer que los elementos realicen una operación específica, en lugar de atravesarla.

En /codegolf//a/127042/29325 hay un ejemplo:

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

Se read stdinda 23 214 52entonces dividida dará la lista {23 214 52}. Después, [join {23 214 52} +]devolverá la cadena 23+214+52. Finalmente expr 23+214+52hace el trabajo de resumir

sergiol
fuente
En este caso, puede omitir el split.
Johannes Kuhn el
@JohannesKuhn: gracias. Hecho.
sergiol
1

Si tiene códigos grandes, es posible evitar múltiples usos de expruso namespace pat tcl::mathopal principio. Proporciona la operación de sintaxis de prefijo como una función Tcl normal. Por ejemplo:

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

Ver página oficial de documentación de mathop

david
fuente
0

Cuando tiene varias variables que han estado seten líneas posteriores, puede usar una en lassignlugar de varias setinstrucciones para lograr el mismo efecto.

Un ejemplo es mi propia respuesta /codegolf//a/105789/29325

Para decidir, uno solo necesita ponderar el número de variables (suponiendo variables de 1 letra, como se espera al jugar al golf):

  • <5, setes más golfista

  • = 5, sety lassigngenera el mismo número de bytes

  • > 5, lassignes más golfista

sergiol
fuente