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.
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.
Jawaban:
Pada jawaban saya /codegolf//a/107557/29325 saya dapat menunjukkan:
Biasanya set j 0;while \$j<$n;{...;incr j}lebih pendek dari yang setarafor {set j 0} {$j<$n} {incr j} {...}
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!
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.
Gunakan shell interaktif. Ini memungkinkan Anda untuk menyingkat nama perintah selama hanya 1 perintah dimulai dengan huruf yang tersisa.
Contoh:
gets -> gelassign -> lasexpr -> expputs -> puDan 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.
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.
Saya menggunakan Tcl 8.0.5, tapi saya percaya yang berikut ini berlaku untuk semua versi terbaru.
Gunakan renameuntuk mengganti nama rename:
rename rename &
The &dapat berupa identifier; &hanya mengingatkan saya pada "referensi" dalam C.
Gunakan nama yang diubah namanya renameuntuk set:
& set =
Sekali lagi, =dapat berupa pengidentifikasi apa pun; =hanya intuitif bagi saya.
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
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
Beberapa miscellanea yang jelas:
lappend dapat mengatur elemen pertama dari daftar jika belum ada (tidak perlu diinisialisasi).array, misalnya set doesNotExist(7) 43 ."a b c") alih-alih [list a b c].foo${a}bar.two\ wordsdaripada "two words". (Ingat secara umum bahwa untuk string yang berdekatan tanpa spasi, tanda kutip ganda dapat dihilangkan!)forsebagai whiles untuk menyimpan satu atau dua karakter, karena whiledapat secara bersamaan memeriksa dan menambah sementara formenggunakan blok yang terpisah.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.
unknownrute: lihat di sini dan di sini .
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.
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.
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
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
split.
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
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
info script {};set tcl_interactive 1