Tips untuk bermain golf di Perl 6

16

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

Harap perhatikan bahwa Perl 6 bukan Perl 5, jadi pertanyaan ini bukan duplikat. Sebagian besar tips untuk bermain golf Perl 5 tidak berlaku untuk Perl 6.

Konrad Borowski
sumber

Jawaban:

9

Hindari subliteral. Dalam banyak kasus, Anda cukup menggunakan {}untuk blok kode. Misalnya, jangan menulis kode berikut.

sub ($a){$a*2}

Sebagai gantinya, gunakan sintaks blok. Ini juga memungkinkan Anda untuk menggunakan $_,, @_dan %_variabel placeholder, jika Anda hanya perlu satu variabel. Jika Anda membutuhkan lebih banyak, Anda dapat menggunakan $^a, $^bvariabel, dan sebagainya.

{$_*2}

Juga, dalam kasus langka tertentu, dimungkinkan untuk menggunakan kode apa pun (terutama ketika Anda memiliki ekspresi sederhana). The *menggantikan argumen placeholder.

* *2
Konrad Borowski
sumber
8

Perl 6 memiliki fitur yang sangat aneh di mana memungkinkan semua karakter Unicode dalam kategori Nd , Nl , dan  No digunakan sebagai literal angka rasional. Beberapa di antaranya lebih pendek daripada menuliskan nilai numeriknya di ASCII:

  • ¼(2 byte) lebih pendek dari .25atau 1/4(3 byte).
  • ¾(2 byte) lebih pendek dari .75atau 3/4(3 byte).
  • (3 byte) lebih pendek dari 1/16(4 byte).
  • 𐦼(4 byte) lebih pendek dari 11/12(5 byte).
  • 𒐲(4 byte) lebih pendek dari 216e3(5 byte).
  • 𒐳(4 byte) lebih pendek dari 432e3(5 byte).
Lynn
sumber
Sebagai tindak lanjut untuk ini, Anda juga dapat menggunakan eksponen Unicode, bahkan dengan beberapa digit dan / atau minus: say (3² + 4², 2²⁰, 5⁻²)==> (25 1048576 0.04). Daftar lengkap Unicode yang dapat Anda penyalahgunaan seperti ini ada di sini: docs.perl6.org/language/unicode_texas .
Ramillies
8

Pelajari fungsi untuk membaca input. Perl 6 memiliki banyak fungsi menarik yang dapat dengan mudah membaca input dari ARGV, atau STDIN (jika tidak ada yang ditentukan pada ARGV), yang dapat mempersingkat kode Anda jika digunakan dengan benar. Jika Anda memanggil mereka sebagai metode STDINpenanganan file , Anda dapat memaksa mereka untuk bekerja pada penanganan file tertentu (berguna jika Anda misalnya membaca dari , tetapi Anda harus membaca argumen pada ARGV).

get

Fungsi ini mendapat satu baris, dan secara otomatis chomps, jadi Anda tidak perlu. Ini berguna jika Anda hanya perlu membaca satu baris.

lines

Fungsi ini mendapatkan semua baris dari file atau STDIN. Ini daftar yang malas, jadi jika Anda menggunakannya for, itu hanya akan membaca apa yang Anda butuhkan. Sebagai contoh.

say "<$_>"for lines

slurp

Ini akan membaca seluruh file atau STDIN, dan akan mengembalikan hasilnya sebagai string tunggal.

Konrad Borowski
sumber
Bug itu diperbaiki - tidak tahu kapan, tetapi say "<$_>" for linesberfungsi sekarang
cat
5

Peringatan : Dinding teks mendekat. Banyak trik kecil yang saya kumpulkan dari waktu ke waktu.

Tulis solusi Anda sebagai blok anonim

Ini sudah disebutkan tetapi saya ingin mengulanginya. Di TIO, Anda bisa menulis my $f =ke header, blok ke kode yang tepat, dan memulai footer dengan a; . Ini tampaknya merupakan cara terpendek untuk menyelesaikan pekerjaan (karena Anda tidak perlu peduli membaca input apa pun, itu diberikan kepada Anda dalam argumen).

Cara lain yang bagus adalah menggunakan tombol -natau -p, tetapi saya tidak menemukan cara untuk membuatnya bekerja di TIO.

Gunakan sintaks titik dua untuk meneruskan argumen

Artinya, alih-alih thing.method(foo,bar), Anda dapat melakukan thing.method:foo,bardan menyimpan 1 karakter. Sayangnya, Anda tidak dapat memanggil metode lain pada hasil karena alasan yang jelas, jadi masuk akal untuk menggunakan hanya untuk metode terakhir dalam satu blok.

Gunakan $_sebanyak yang Anda bisa

Terkadang lebih baik mengambil argumen daftar tunggal daripada beberapa argumen terpisah karena ini. Saat mengakses $_, Anda dapat memanggil metode hanya dengan memulai dengan titik: misalnya .sortsama dengan$_.sort .

Namun, ingatlah bahwa setiap blok mendapatkan miliknya sendiri $_, sehingga parameter blok luar tidak akan merambat ke bagian dalam. Jika Anda perlu mengakses parameter fungsi utama dari blok dalam, ...

Gunakan ^variabel jika Anda tidak dapat menggunakan$_

Masukkan ^antara sigil dan nama variabel, seperti ini: $^a. Ini hanya berfungsi di dalam blok. Kompiler pertama menghitung berapa banyak yang Anda miliki di blok ini, mengurutkannya secara leksikografis, dan kemudian memberikan argumen pertama ke yang pertama, yang kedua ke yang kedua dan seterusnya. The ^kebutuhan untuk digunakan hanya dalam kejadian pertama dari variabel. Jadi, {$^a - $^b}ambil 2 skalar dan kurangi. Satu-satunya hal yang penting adalah urutan abjad, demikian {-$^b + $^a}juga hal yang sama.

Jika Anda pernah merasa ingin menggunakan sintaks blok runcing (seperti ->$a,$b {$a.map:{$_+$b}}), Anda jauh lebih baik menulis pernyataan palsu di awal blok menggunakan ^untuk setiap argumen yang tidak akan Anda gunakan di blok utama (seperti {$^b;$^a.map:{$_+$b}}) (Catatan cara yang lebih baik untuk bermain golf ini adalah {$^a.map(*+$^b)}. Saya hanya ingin memamerkan konsepnya.)

Baca dokumen operator dengan cermat

Operator sangat kuat dan seringkali mereka adalah cara terpendek untuk menyelesaikan sesuatu. Terutama meta-operator (operator yang menganggap operator sebagai argumen)[] , [\], X, <</ >>dan Zlayak perhatian Anda. Jangan lupa bahwa meta-op dapat menggunakan meta-op lain sebagai argumen (seperti XZ%%saya berhasil menggunakan di sini ). Anda dapat menggunakan >>untuk pemanggilan metode juga, yang bisa menjadi jauh lebih murah daripada peta ( @list>>.methodbukannya @list.map(*.method), tapi hati-hati, mereka tidak sama! ). Dan, akhirnya, sebelum Anda menggunakan biner << >>, ingatlah bahwa Zakan sering melakukan hal yang sama dalam karakter yang jauh lebih sedikit.

Jika Anda menumpuk banyak meta-op satu sama lain, Anda dapat menentukan prioritas menggunakan tanda kurung siku []. Itu akan menyelamatkan Anda ketika Anda menumpuk begitu banyak operator sehingga membingungkan kompiler. (Itu tidak sering terjadi.)

Akhirnya, jika Anda perlu memaksa sesuatu ke Bool, Int atau Str, jangan gunakan metode .Bool, .Intdan .Str, melainkan operator ?, +dan ~. Atau bahkan lebih baik, cukup masukkan mereka ke dalam ekspresi aritmatika untuk memaksa mereka ke Int dan seterusnya. Cara terpendek untuk mendapatkan panjang daftar adalah +@list. Jika Anda ingin menghitung 2 pangkat dari panjang daftar, katakan saja 2**@listdan itu akan melakukan The Right Thing.

Gunakan variabel status bebas $, @dan%

Di setiap blok, setiap kemunculan $(atau @atau %) merujuk ke variabel status skalar (atau array, atau hash) baru yang mengkilap (variabel yang nilainya tetap ada di seluruh panggilan ke blok). Jika Anda memerlukan variabel status yang perlu direferensikan hanya sekali dalam kode sumber, ketiganya adalah teman besar Anda. (Paling sering $.) Misalnya, dalam tantangan Reverse Math Cycles , itu dapat digunakan untuk memilih operator secara siklikal dari sebuah array, yang diindeks oleh $++%6.

Gunakan sub bentuk map, grepet al.

Itu berarti: lakukan map {my block},listdaripada list.map({my block}). Bahkan jika Anda berhasil menggunakan list.map:{my block}, kedua pendekatan ini keluar pada jumlah byte yang sama. Dan sering kali, Anda perlu mengurung daftar saat memanggil metode, tetapi tidak saat memanggil sub. Jadi sub pendekatan yang keluar selalu lebih baik atau setidaknya sama dengan metode yang satu.

Satu-satunya pengecualian di sini adalah ketika objek yang akan dibuat map ped, grepped dan sebagainya, berada di $_. Maka .map:{}jelas berdetak map {},$_.

Gunakan persimpangan ( &dan |) alih-alih &&dan ||.

Jelas, mereka 1 byte lebih pendek. Di sisi lain, mereka harus dihancurkan dengan dipaksa ke dalam konteks boolean. Ini selalu dapat dilakukan dengan a ?. Di sini Anda harus mengetahui meta-op!op yang memaksa konteks bool, menggunakan opdan meniadakan hasilnya.

Jika Anda memiliki daftar dan ingin mengubahnya menjadi persimpangan, jangan gunakan [&]dan [|]. Alih-alih menggunakan .anydan .all. Ada juga .noneyang tidak dapat dengan mudah ditiru oleh ops persimpangan.

Ramillies
sumber
1
Saya pikir &&dan ||masih berguna untuk hubungan arus pendek?
ASCII
@ Khusus ASCII: Ya, tentu saja.
Ramillies
4

Kurangi ruang yang digunakan untuk variabel

Ada beberapa bagian untuk ini.

Hapus spasi putih

Variabel yang dideklarasikan menggunakan mybiasanya dapat dideklarasikan tanpa spasi di antara mydan nama variabel. my @asetara denganmy@a .

Gunakan variabel sigil-less

Anda bisa mendeklarasikan variabel menggunakan backslash untuk menghapus sigil sebelum nama variabel, seperti:

my \a=1;

(sayangnya Anda tidak dapat menghapus spasi :()

Ini berguna karena Anda dapat merujuknya hanya sebagai nama variabel kosong nanti.

 a=5;
 a.say

Pada dasarnya ini menghemat byte jika Anda menggunakan variabel lebih dari satu kali di tempat lain dalam kode Anda. Kelemahannya adalah bahwa variabel perlu diinisialisasi.

Gunakan $!dan$/

Variabel pra-deklarasi ini biasanya digunakan untuk pengecualian dan kecocokan regex masing-masing, tetapi tidak perlu didefinisikan menggunakan my.

$!=1;
$/=5;

Terutama berguna adalah menggunakan $/sebagai array dan menggunakan cara pintas $diikuti oleh nomor untuk mengakses elemen $/array;

$/=100..200;
say $5;  #105
say $99; #199
Jo King
sumber
2

Gunakan ...sebagai gantifirst

Biasanya, jika Anda ingin menemukan nomor pertama yang cocok dengan beberapa kondisi &f, Anda dapat menggambarkannya seperti:

first &f,1..*

Namun, sebagai gantinya Anda dapat menggunakan ...operator:

+(1...&f)

Jika Anda harus mulai dari 0, Anda dapat memiliki -1setelahnya +.

Jika Anda ingin indeks elemen pertama dalam daftar @ayang memiliki kondisi &f, biasanya Anda lakukan:

first &f,@a,:k

Sebagai gantinya:

(@a...&f)-1

(atau sebaliknya jika Anda ingin 0 diindeks). Dengan cara yang sama, Anda bisa mendapatkan semua elemen hingga yang pertama yang melewati kondisi.

Kelemahan dari hal ini adalah bahwa daftar harus melewati kondisi di beberapa titik, jika tidak ...operator akan mencoba untuk meramalkan akhir daftar, dan kemungkinan besar akan membuat kesalahan. Anda juga tidak dapat menggunakan kode apa pun di sebelah kiri, karena itu akan ditafsirkan sebagai bagian dari urutan.

Jo King
sumber