Поради щодо гольфу в Tcl


15

Які загальні поради щодо гольфу в Tcl? Я шукаю ідеї, які можна застосувати до коду проблем із гольфом взагалі, які принаймні дещо характерні для Tcl (наприклад, "видалити коментарі" - це не відповідь). Будь ласка, опублікуйте одну пораду на відповідь.

Відповіді:


7

Використовуйте lmapзамість цього foreach. Для цього потрібно Tcl 8.6.

Синтаксис той самий, але lmapповертає список з результатом кожного циклу.


4

У своїй відповіді /codegolf//a/107557/29325 я можу продемонструвати:

  1. Зазвичай set j 0;while \$j<$n;{...;incr j}коротше, ніж еквівалентfor {set j 0} {$j<$n} {incr j} {...}

  2. Коли змінна циклічна величина починається з 1, ми можемо робити приріст як частина whileтестової умови, уникаючи запису раніше, ніж set i 1зайве: while {[incr i]<=$n} {...}замістьset i 1;while \$i<=$n;{...;incr i}

УВАГА : Можна зробити лише 2. у випадку зовнішньої петлі! Я не зміг застосувати його до моєї jзмінної, оскільки її потрібно скинути на 1 у зовнішній її внутрішній цикл! І incr jнабуде значення, яке було встановлено на останньому кроці внутрішнього циклу, замість того, щоб захоплювати невизначену змінну jдля припущення 0та збільшення її 1!


4

Іноді варто використовувати time {script} n де nкількість ітерацій замість нормальної whileчи forциклічної. Хоча timeмета не циклічна, досягнутий ефект той самий.

Нещодавно я змінив власні відповіді за цим напрямом.

ОНОВЛЕННЯ: Я щойно виявив непростий падіння: ви не можете замінити блок a forабо whilea timeблоком, якщо він містить a breakабо a continue.


3

Використовуйте інтерактивну оболонку. Це дозволяє скоротити імена команд до тих пір, поки лише 1 команда починається з решти літер.

Приклад:

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

І інтерактивні рішення безкоштовні: P

Фон :

Коли tclshпрацює з терміналом як пристроєм введення, він встановлює змінну tcl_interactiveна 1. Це викликає unknown(процедура за замовчуванням, яка буде викликана, якщо команду не знайти), шукати команди, які починаються з цього імені.

Нижня сторона: вона буде друкувати результат кожного рядка, використовувати ;замість нових рядків.
Ох, і це може викликати зовнішні команди типу w, що є гарною абревіатурою while.


3

Підкоманди та варіанти можуть (як правило) скорочуватися. Це може зекономити небагато, але ви повинні перевірити, оскільки не все можна скоротити таким чином (наприклад regsub, параметри не можуть).

Потім ви можете використовувати це з магією, namespaceщоб зробити якісь справді злі речі. Врахуйте це:

namespace exp *;namespace en cr -c ?

Після цього ?тепер є магічна команда, яка дозволяє скоротити будь-яку глобальну команду Tcl, і все без жахливої ​​невизначеності возитися unknown.


2

Я використовую Tcl 8.0.5, але я вважаю, що наступне стосується всіх останніх версій.

  1. Використовувати renameдля перейменування rename:

    rename rename &
    

    Ідентифікатором &може бути будь-який ідентифікатор; &просто нагадує мені "посилання" в С.

  2. Використовуйте перейменований renameдля перейменування set:

    & set =
    

    Знову ж таки, =може бути будь-який ідентифікатор; =для мене просто інтуїтивно зрозумілий.

  3. Тепер перейменуйте інші команди, які варто перейменувати, наприклад

    & regsub R
    & string S
    & while W
    

    Команду варто перейменувати, якщо, враховуючи її довжину n , та входження k , k (n-1) - (n + 4)> 0 . Розв’язуючи для k , формула стає k > (n+4)/(n-1). Ось довідкова таблиця, яка спрощує:

    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. Далі, компактні часто використовувані підкоманди типу

    = I index
    = L length
    

    щоб ви могли робити такі речі

    S $I $x 7
    S $L $x
    
  5. Деякі очевидні розмови:

    1. lappend може встановити перший елемент списку, якщо він ще не існує (не потрібно ініціалізувати).
    2. Ви можете встановлювати масиви без використання array, наприклад, set doesNotExist(7) 43 .
    3. Ви можете використовувати рядки ( "a b c") замість [list a b c].
    4. Ви можете інтерполювати в рядках так: foo${a}bar.
    5. Ви можете використовувати, two\ wordsа не "two words". (Згадайте загалом, що для суміжних рядків без пробілів подвійні лапки можна опустити!)
    6. Ви можете майже завжди переписати fors як whiles для збереження символу чи двох, оскільки a whileможе одночасно перевіряти та збільшувати, коли a forвикористовує окремі блоки.
  6. Щодо великих програм, я вигадав трюк, який я ще не застосував:

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

    Це імітує інтерактивні скорочення команд! Це коштує 54 символів, але тепер ви можете використовувати jдля join, spдля split, stдля string, wдля while, і так далі.


1
Якщо ви хочете наслідувати інтерактивні абревіатури, використовуйтеinfo script {};set tcl_interactive 1
Йоганнес Кун,

Класно, дякую! Я зарахував вас тут . Однак з цією технікою були деякі проблеми, з якими я не стикався з unknownмаршрутом: дивіться тут і тут .
Ендрю Чонг,

Питання задає поради, які є дещо характерними для Tcl. Потрійний оператор включений у підказки для всіх мов .
Пітер Тейлор

@PeterTaylor - Дякую, я видалив цю пораду.
Ендрю Чонг

2

інше необов’язково

Як сказано на сторінці інструкцій , elseна ifблокові конструкції неявно . Отже, що є

if ... {} else {}

може стати

if ... {} {}

як ви бачите на деяких моїх відповідях.


1

Можливо, це має бути інтегровано в іншій відповіді, але ось це:

Коли у a procє лише один параметр, він може бути записаний як

proc p a {DO THINGS}

замість

proc p {a} {DO THINGS}

Те саме стосується двох параметрів procза допомогою зворотної косої риски; це можна записати як

proc p a\ b {DO THINGS}

замість

proc p {a b} {DO THINGS}

Для більшої кількості параметрів {}рендеруйте коротший код.


1

Іноді варто замінити два setтвердження для об'єднання рядків лише одним lappendтвердженням. На таку конструкцію, яку можна замінити

set s ""

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

від

loop {
    # ...
    append s X
}

У appendкоманді єincr подібну поведінку, яке ініціалізує ще не визначену змінну.

Подбайте , щоб не помилка appendпоlappend


1

Якщо ви обробляєте список операцією, яка синтаксично переплітається між кожним елементом, іноді ви можете joinелементами виконати певну операцію, а не перетинати її.

На /codegolf//a/127042/29325 є приклад:

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

Це read stdinдає 23 214 52тоді розкол дасть список {23 214 52}. Після, [join {23 214 52} +]поверне рядок 23+214+52. Нарешті expr 23+214+52виконує роботу підбиття підсумків


У цьому випадку ви можете опустити split.
Йоганнес Кун

@JohannesKuhn: спасибі Зроблено.
сергіол

1

Якщо у вас є великі коди, можливо уникнути багаторазового exprвикористання namespace pat tcl::mathopна початку. Він забезпечує операцію префікса-синтаксису як звичайну функцію Tcl. Наприклад:

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

Дивіться офіційну сторінку doc


0

Якщо у вас є декілька змінних, які були setу наступних рядках, ви можете використовувати одну lassignзамість кількох setінструкцій, щоб досягти однакового ефекту.

Один із прикладів - моя власна відповідь /codegolf//a/105789/29325

Щоб вирішити, потрібно просто зважити кількість змінних (припускаючи змінні 1 літери, як це очікується при гольфі):

  • <5, setє гольфіст

  • = 5, setі lassignгенерувати однакове число байтів

  • > 5, lassignє гравцем

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.