Wskazówki do gry w golfa w Tcl

15

Jakie masz ogólne wskazówki na temat gry w golfa w Tcl? Szukam pomysłów, które można by zastosować do ogólnych problemów z golfem, które są przynajmniej nieco specyficzne dla Tcl (np. „Usuń komentarze” nie jest odpowiedzią). Proszę zamieścić jedną wskazówkę na odpowiedź.

Johannes Kuhn
źródło

Odpowiedzi:

7

Użyj lmapzamiast tego foreach. Wymaga to Tcl 8.6.

Składnia jest taka sama, ale lmapzwraca listę z wynikiem każdej pętli.

Johannes Kuhn
źródło
4

Na mojej odpowiedzi /codegolf//a/107557/29325 mogę wykazać:

  1. Zwykle set j 0;while \$j<$n;{...;incr j}jest krótszy niż odpowiednikfor {set j 0} {$j<$n} {incr j} {...}

  2. Gdy zmienna zapętlająca zaczyna się od 1, możemy wykonać przyrost jako część whilewarunku testowego, unikając set i 1niepotrzebnego zapisu przed : while {[incr i]<=$n} {...}zamiastset i 1;while \$i<=$n;{...;incr i}

UWAGA : Można zrobić tylko 2. w przypadku zewnętrznej pętli! Nie mogłem zastosować jej do mojej jzmiennej, ponieważ należy ją zresetować do 1 na zewnątrz własnej wewnętrznej pętli! I incr juzyskałby wartość ustawioną na ostatnim kroku wewnętrznej pętli, zamiast pobierać niezdefiniowaną zmienną, jaby ją przyjąć 0i zwiększyć 1!

sergiol
źródło
4

Czasami warto użyć time {script} ngdzie njest liczba iteracji zamiast normalnej whilelub forpętli. Chociaż timecelem nie jest zapętlenie, osiągnięty efekt jest taki sam.

Niedawno wprowadziłem zmiany do własnych odpowiedzi podążając w tym kierunku.

AKTUALIZACJA: Właśnie odkryłem łatwą do upadku pułapkę: nie możesz zastąpić forani whileprzez timeblok, jeśli zawiera on breaklub a continue.

sergiol
źródło
3

Użyj interaktywnej powłoki. Pozwala to skracać nazwy poleceń, o ile tylko 1 polecenie zaczyna się od pozostałych liter.

Przykład:

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

A interaktywne rozwiązania są bezpłatne: P

Tło :

Gdy tclshdziała z terminalem jako urządzeniem wejściowym, ustawia zmienną tcl_interactivena 1. Powoduje to unknown(domyślna procedura, która zostanie wywołana, jeśli nie można znaleźć polecenia), wyszukiwanie poleceń rozpoczynających się od tej nazwy.

Minus: wydrukuje wynik każdej linii, użyj ;zamiast nowego wiersza.
Och, i może wywoływać zewnętrzne polecenia takie jak w, co jest dobrym skrótem od while.

Johannes Kuhn
źródło
3

Komendy i opcje można (zwykle) skracać. Może to sporo zaoszczędzić, ale musisz przetestować, ponieważ nie wszystko można skrócić w ten sposób ( regsubna przykład opcje nie mogą).

Następnie możesz użyć tego z magią namespacerobienia naprawdę złych rzeczy. Rozważ to:

namespace exp *;namespace en cr -c ?

Następnie ?jest teraz magicznym poleceniem, które pozwala skrócić każde globalne polecenie Tcl, a wszystko to bez nieprzyjemnej niepewności związanej z mieszaniem się unknown.

Donal Fellows
źródło
2

Używam Tcl 8.0.5, ale uważam, że poniższe postanowienia dotyczą wszystkich najnowszych wersji.

  1. Użyj, renameaby zmienić nazwę rename:

    rename rename &
    

    &Może być każdy identyfikator; &po prostu przypomina mi „odniesienia” w C.

  2. Użyj przemianowanej renamenazwy, aby zmienić nazwę set:

    & set =
    

    Ponownie, =może być dowolnym identyfikatorem; =jest dla mnie po prostu intuicyjny.

  3. Teraz zmień nazwę innych poleceń, których warto zmienić nazwę, np

    & regsub R
    & string S
    & while W
    

    Polecenie jest warte zmiany nazwy, jeśli z uwagi na jego długość n oraz wystąpienia k , k (n-1) - (n + 4)> 0 . Rozwiązując dla k , formuła staje się k > (n+4)/(n-1). Oto tabela referencyjna, która ułatwia:

    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. Następnie kompaktowe często używane komendy, takie jak

    = I index
    = L length
    

    więc możesz robić takie rzeczy jak

    S $I $x 7
    S $L $x
    
  5. Niektóre oczywiste różne przypadki:

    1. lappend może ustawić pierwszy element listy, jeśli jeszcze nie istnieje (nie trzeba inicjować).
    2. Można ustawić tablice bez używania array, np set doesNotExist(7) 43 .
    3. Możesz użyć string ( "a b c") zamiast [list a b c].
    4. Można interpolować w ciągach tak: foo${a}bar.
    5. Możesz użyć two\ wordszamiast "two words". (Pamiętaj ogólnie, że w przypadku ciągłych ciągów bez spacji podwójne cudzysłowy można pominąć!)
    6. Prawie zawsze możesz przepisać fors jako whiles, aby zapisać jeden lub dwa znaki, ponieważ whilepuszka może jednocześnie sprawdzać i zwiększać, a jednocześnie forużywa osobnych bloków.
  6. W przypadku większych programów oto sztuczka, o której myślałem, ale jeszcze jej nie zastosowałem:

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

    To emuluje interaktywne skróty poleceń! To kosztuje 54 znaków, ale teraz można używać jdo join, spdo split, stdo string, wdo while, i tak dalej.

Andrew Cheong
źródło
1
Jeśli chcesz emulować interaktywne skróty, użyjinfo script {};set tcl_interactive 1
Johannes Kuhn
Fajne dzięki! Zasłużyłem ci tutaj . Były jednak pewne problemy z tą techniką, których nie spotkałem na unknowntrasie: patrz tutaj i tutaj .
Andrew Cheong,
Pytanie dotyczy wskazówek, które są nieco specyficzne dla Tcl. Operator trójskładnikowy znajduje się we wskazówkach dla wszystkich języków .
Peter Taylor
@PeterTaylor - Dzięki, usunąłem tę wskazówkę.
Andrew Cheong,
2

inne jest opcjonalne

Jak powiedziano na stronie podręcznika , elsejest domyślny dla ifkonstrukcji bloków. Więc co jest

if ... {} else {}

może zostać

if ... {} {}

jak widać na niektórych moich odpowiedziach.

sergiol
źródło
1

Być może powinien on zostać zintegrowany z inną odpowiedzią, ale oto:

Gdy a procma tylko jeden parametr, można go zapisać jako

proc p a {DO THINGS}

zamiast

proc p {a} {DO THINGS}

To samo dotyczy dwóch parametrów procprzy użyciu odwrotnego ukośnika; można to zapisać jako

proc p a\ b {DO THINGS}

zamiast

proc p {a b} {DO THINGS}

Dla większej liczby parametrów {}renderuj krótszy kod.

sergiol
źródło
1

Czasami warto zastąpić dwie setinstrukcje, aby połączyć łańcuchy tylko jedną lappendinstrukcją. Na takiej konstrukcji można zastąpić

set s ""

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

przez

loop {
    # ...
    append s X
}

appendKomenda ma incrtakiego zachowania, które inicjuje jeszcze nie zdefiniowano zmienną.

Należy uważać, aby nie pomyłka appendprzezlappend

sergiol
źródło
1

Jeśli posługujesz się listą z operacją, która syntaktycznie przeplata się między poszczególnymi elementami, czasami możesz joinwykonać określone operacje zamiast przejść przez nie.

Na /codegolf//a/127042/29325 jest przykład:

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

To read stdindaje 23 214 52następnie podzielić dadzą listę {23 214 52}. Po [join {23 214 52} +]zwróci ciąg 23+214+52. Wreszcie expr 23+214+52wykonuje sumowanie

sergiol
źródło
W takim przypadku możesz pominąć split.
Johannes Kuhn
@JohannesKuhn: dzięki. Gotowy.
sergiol
1

Jeśli masz duże kody, możesz uniknąć wielokrotnego exprużycia namespace pat tcl::mathopna początku. Zapewnia operację składni prefiksów jako zwykłą funkcję Tcl. Na przykład:

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

Zobacz oficjalną stronę dokumentu mathop

David
źródło
0

Jeśli masz kilka zmiennych, które były setw kolejnych wierszach, możesz użyć jednej lassignzamiast kilku setinstrukcji, aby osiągnąć ten sam efekt.

Jednym z przykładów jest moja własna odpowiedź /codegolf//a/105789/29325

Aby zdecydować, wystarczy zważyć liczbę zmiennych (zakładając zmienne 1-literowe, jak można się spodziewać podczas gry w golfa):

  • <5, setjest golfistą

  • = 5 seti lassignwygeneruj tę samą liczbę bajtów

  • > 5, lassignjest golfistą

sergiol
źródło