Tips untuk bermain golf di Tcl

15

Apa tips umum yang Anda miliki untuk bermain golf di Tcl? Saya mencari ide yang dapat diterapkan pada masalah kode golf secara umum yang setidaknya agak spesifik untuk Tcl (mis. "Hapus komentar" bukan jawaban). Silakan kirim satu tip per jawaban.

Johannes Kuhn
sumber

Jawaban:

7

Gunakan lmapsebagai gantinya foreach. Ini membutuhkan Tcl 8.6.

Sintaksnya sama, tetapi lmapmengembalikan daftar dengan hasil dari setiap loop.

Johannes Kuhn
sumber
4

Pada jawaban saya /codegolf//a/107557/29325 saya dapat menunjukkan:

  1. Biasanya set j 0;while \$j<$n;{...;incr j}lebih pendek dari yang setarafor {set j 0} {$j<$n} {incr j} {...}

  2. Ketika variabel pengulangan dimulai pada 1, kita dapat melakukan kenaikan sebagai bagian dari whilekondisi pengujian, menghindari menulis sebelum set i 1tidak perlu: while {[incr i]<=$n} {...}bukannyaset i 1;while \$i<=$n;{...;incr i}

PERHATIAN : Seseorang hanya bisa 2. dalam kasus loop luar! Saya tidak bisa menerapkannya ke jvariabel saya karena harus diatur ulang ke 1 di luar loop dalamnya sendiri! Dan incr jakan memperoleh nilai yang ditetapkan pada langkah terakhir dari loop dalam, alih-alih mengambil variabel yang tidak ditentukanj untuk mengasumsikan 0dan menambahkannya ke 1!

sergiol
sumber
4

Kadang-kadang layak untuk digunakan di time {script} nmana njumlah iterasi bukan normal whileatau forloop. Meskipun timetujuan tidak berulang, efek yang dicapai adalah sama.

Saya membuat perubahan baru-baru ini untuk jawaban saya sendiri mengikuti arah ini.

PEMBARUAN: Saya baru saja menemukan perangkap yang mudah jatuh: Anda tidak dapat mengganti a foratau a whiledengan timeblok, jika mengandung a breakatau a continue.

sergiol
sumber
3

Gunakan shell interaktif. Ini memungkinkan Anda untuk menyingkat nama perintah selama hanya 1 perintah dimulai dengan huruf yang tersisa.

Contoh:

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

Dan solusi interaktif gratis: P

Latar belakang :

Ketika tclshberjalan dengan terminal sebagai perangkat input, ia menetapkan variabel tcl_interactiveuntuk 1. Ini menyebabkan unknown(prosedur default yang akan dipanggil jika perintah tidak dapat ditemukan) untuk mencari perintah yang dimulai dengan nama itu.

Kelemahan: itu akan mencetak hasil setiap baris, gunakan ;bukan baris baru.
Ohh, dan itu mungkin memanggil perintah eksternal seperti w, yang merupakan singkatan dari while.

Johannes Kuhn
sumber
3

Sub-perintah dan opsi dapat (biasanya) disingkat. Ini dapat menghemat sedikit, tetapi Anda harus menguji karena tidak semuanya dapat dipersingkat dengan cara ini (misalnya regsub, opsi tidak dapat).

Anda kemudian dapat menggunakan ini dengan keajaiban namespaceuntuk melakukan beberapa hal yang benar-benar jahat. Pertimbangkan ini:

namespace exp *;namespace en cr -c ?

Setelah itu, ?sekarang perintah magis yang memungkinkan Anda menyingkat perintah Tcl global, dan semua tanpa ketidakpastian yang mengganggu unknown.

Donal Fellows
sumber
2

Saya menggunakan Tcl 8.0.5, tapi saya percaya yang berikut ini berlaku untuk semua versi terbaru.

  1. Gunakan renameuntuk mengganti nama rename:

    rename rename &
    

    The &dapat berupa identifier; &hanya mengingatkan saya pada "referensi" dalam C.

  2. Gunakan nama yang diubah namanya renameuntuk set:

    & set =
    

    Sekali lagi, =dapat berupa pengidentifikasi apa pun; =hanya intuitif bagi saya.

  3. Sekarang, ganti nama perintah lain yang perlu diganti namanya, misalnya

    & regsub R
    & string S
    & while W
    

    Perintah bernilai penggantian nama jika, diberi panjangnya n , dan kejadian k , k (n-1) - (n + 4)> 0 . Memecahkan untuk k , rumusnya menjadi k > (n+4)/(n-1). Ini tabel referensi yang memudahkan:

    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. Selanjutnya, kompak perintah yang sering digunakan suka

    = I index
    = L length
    

    jadi kamu bisa melakukan hal-hal seperti

    S $I $x 7
    S $L $x
    
  5. Beberapa miscellanea yang jelas:

    1. lappend dapat mengatur elemen pertama dari daftar jika belum ada (tidak perlu diinisialisasi).
    2. Anda dapat mengatur array tanpa menggunakan array, misalnya set doesNotExist(7) 43 .
    3. Anda dapat menggunakan string ( "a b c") alih-alih [list a b c].
    4. Anda dapat interpolasi dalam string seperti: foo${a}bar.
    5. Anda bisa menggunakan two\ wordsdaripada "two words". (Ingat secara umum bahwa untuk string yang berdekatan tanpa spasi, tanda kutip ganda dapat dihilangkan!)
    6. Anda hampir selalu dapat menulis ulang forsebagai whiles untuk menyimpan satu atau dua karakter, karena whiledapat secara bersamaan memeriksa dan menambah sementara formenggunakan blok yang terpisah.
  6. Untuk program yang lebih besar, inilah trik yang saya pikirkan tetapi belum diterapkan:

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

    Ini meniru singkatan perintah interaktif! Biayanya 54 karakter, tetapi sekarang Anda dapat menggunakan juntuk join, spuntuk split, stuntuk string, wuntuk while, dan seterusnya.

Andrew Cheong
sumber
1
Jika Anda ingin meniru singkatan interaktif, gunakaninfo script {};set tcl_interactive 1
Johannes Kuhn
Keren Terimakasih! Saya telah mengkredit Anda di sini . Ada beberapa masalah dengan teknik itu, namun saya tidak menemukan unknownrute: lihat di sini dan di sini .
Andrew Cheong
Pertanyaannya menanyakan tip yang agak spesifik untuk Tcl. Operator ternary termasuk dalam tip untuk semua bahasa .
Peter Taylor
@PeterTaylor - Terima kasih, saya sudah menghapus tip itu.
Andrew Cheong
2

selain itu opsional

Seperti yang dikatakan pada halaman manual jika , elsetersirat pada ifkonstruksi blok. Jadi apa

if ... {} else {}

bisa menjadi

if ... {} {}

seperti yang Anda lihat pada beberapa jawaban saya.

sergiol
sumber
1

Mungkin itu harus diintegrasikan pada jawaban lain, tetapi begini saja:

Ketika a prochanya memiliki satu parameter, ia dapat ditulis sebagai

proc p a {DO THINGS}

dari pada

proc p {a} {DO THINGS}

Hal yang sama berlaku untuk dua parameter procmenggunakan backslash; dapat ditulis sebagai

proc p a\ b {DO THINGS}

dari pada

proc p {a b} {DO THINGS}

Untuk jumlah parameter yang lebih tinggi, {}render kode yang lebih pendek.

sergiol
sumber
1

Kadang-kadang layak untuk mengganti dua setpernyataan untuk menyatukan string dengan hanya satu lappendpernyataan. Pada konstruksi seperti, seseorang dapat menggantikan

set s ""

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

oleh

loop {
    # ...
    append s X
}

Itu append perintah memiliki incrperilaku seperti yang menginisialisasi variabel belum ditentukan.

Berhati-hati untuk tidak kesalahan appenddenganlappend

sergiol
sumber
1

Jika Anda menangani daftar dengan operasi yang secara sintaksis saling terkait di antara setiap elemen, terkadang Anda bisa join elemen untuk melakukan operasi tertentu, alih-alih melewatinya.

Pada /codegolf//a/127042/29325 ada contoh:

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

Ini read stdinmemberi 23 214 52kemudian membagi akan memberikan daftar {23 214 52}. Setelah itu, [join {23 214 52} +]akan mengembalikan string 23+214+52. Akhirnya expr 23+214+52melakukan pekerjaan penjumlahan

sergiol
sumber
Dalam hal ini, Anda dapat menghilangkan split.
Johannes Kuhn
@JohannesKuhn: terima kasih. Selesai
sergiol
1

Jika Anda memiliki kode besar, Anda dapat menghindari beberapa penggunaan exprmenggunakan namespace pat tcl::mathopdi awal. Ini menyediakan operasi awalan-sintaks sebagai fonction Tcl biasa. Sebagai contoh:

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

Lihat halaman doc Mathop resmi

David
sumber
0

Ketika Anda memiliki beberapa variabel yang berada setdi baris berikutnya, Anda dapat menggunakan satu lassignalih-alih beberapaset instruksi untuk mencapai efek yang sama.

Salah satu contoh adalah jawaban saya sendiri /codegolf//a/105789/29325

Untuk memutuskan, seseorang hanya perlu mempertimbangkan jumlah variabel (dengan asumsi variabel 1 huruf, seperti yang diharapkan saat bermain golf):

  • <5, set pegolf

  • = 5, setdanlassign menghasilkan jumlah byte yang sama

  • > 5, lassignlebih pegolf

sergiol
sumber