Fitur tersembunyi dari Perl?


143

Apa saja fitur bahasa esoterik yang benar-benar bermanfaat di Perl yang sebenarnya bisa Anda gunakan untuk melakukan pekerjaan yang bermanfaat?

Pedoman:

  • Cobalah untuk membatasi jawaban pada inti Perl dan bukan CPAN
  • Tolong beri contoh dan deskripsi singkat

Fitur Tersembunyi juga ditemukan di Fitur Tersembunyi bahasa lain:

(Ini semua dari jawaban Corion )

  • C
    • Perangkat Duff
    • Portabilitas dan Standar
  • C #
    • Kutipan untuk daftar dan string yang dibatasi whitespace
    • Ruang nama yang dapat diubah
  • Jawa
    • Peminat Statis
  • JavaScript
    • Fungsinya adalah warga negara kelas satu
    • Blokir ruang lingkup dan penutupan
    • Metode panggilan dan accessor secara tidak langsung melalui variabel
  • Rubi
    • Menentukan metode melalui kode
  • PHP
    • Baca dokumentasi online
    • Metode ajaib
    • Referensi simbolik
  • Python
    • Pertukaran nilai satu baris
    • Kemampuan untuk mengganti fungsi inti dengan fungsi Anda sendiri

Fitur Tersembunyi Lainnya:

Operator:

Mengutip konstruk:

Sintaks dan Nama:

Modul, Pragma, dan opsi baris perintah:

Variabel:

Kontrol loop dan aliran:

Ekspresi reguler:

Fitur lainnya:

Trik lain, dan meta-jawaban:


Lihat juga:


Sebagian besar fitur ini digunakan sehari-hari, beberapa terjadi di sebagian besar skrip Perl, dan sebagian besar terdaftar di bawah "Lainnya" masih berasal dari bahasa lain, menyebut "tersembunyi" ini mengubah maksud pertanyaan.
reinierpost

Jawaban:


54

Operator flip-flop berguna untuk melewatkan iterasi pertama ketika mengulangi catatan (biasanya baris) yang dikembalikan oleh file handle, tanpa menggunakan variabel flag:

while(<$fh>)
{
  next if 1..1; # skip first record
  ...
}

Jalankan perldoc perlopdan cari "flip-flop" untuk informasi dan contoh lebih lanjut.


Sebenarnya itu diambil dari Awk, di mana Anda dapat melakukan flip-flop antara dua pola dengan menulis pattern1, pattern2
Bruno De Fraine

15
Untuk memperjelas, aspek "tersembunyi" dari ini adalah bahwa jika salah satu operan ke skalar '..' adalah konstanta nilainya secara implisit dibandingkan dengan nomor baris input ($.)
Michael Carman

47

Ada banyak fitur yang tidak jelas di Perl.

Misalnya, apakah Anda tahu bahwa ada ruang setelah sigil?

 $ perl -wle 'my $x = 3; print $ x'
 3

Atau Anda dapat memberikan nama numerik subs jika Anda menggunakan referensi simbolik?

$ perl -lwe '*4 = sub { print "yes" }; 4->()' 
yes

Ada juga operator kuasi "bool", yang mengembalikan 1 untuk ekspresi benar dan string kosong untuk false:

$ perl -wle 'print !!4'
1
$ perl -wle 'print !!"0 but true"'
1
$ perl -wle 'print !!0'
(empty line)

Hal menarik lainnya: dengan use overload Anda dapat membebani string literal dan angka (dan misalnya membuatnya BigInts atau apa pun).

Banyak dari hal-hal ini sebenarnya didokumentasikan di suatu tempat, atau mengikuti secara logis dari fitur-fitur yang didokumentasikan, tetapi beberapa tidak diketahui.

Perbarui : Satu lagi yang bagus. Di bawah q{...}konstruk penawaran disebutkan, tetapi apakah Anda tahu bahwa Anda dapat menggunakan huruf sebagai pembatas?

$ perl -Mstrict  -wle 'print q bJet another perl hacker.b'
Jet another perl hacker.

Anda juga dapat menulis ekspresi reguler:

m xabcx
# same as m/abc/

2
"Apakah kamu tahu bahwa ada ruang setelah sigil?" Saya benar-benar terperangah. Wow.
Aristoteles Pagaltzis

1
Keren! !! $ undef_var tidak membuat peringatan.
Axeman

4
Saya pikir contoh Anda menggunakan huruf untuk membatasi string harus " Just another perl hacker" daripada "Jet another perl hacker" = P
Chris Lutz

Bagian terburuknya adalah Anda juga bisa menggunakan hal-hal lain sebagai pembatas. Bahkan menutup kurung. Yang berikut ini valid: s} regex} penggantian} xsmg; q] string literal];
Ryan C. Thompson

46

Tambahkan dukungan untuk file terkompresi melalui ARGV ajaib :

s{ 
    ^            # make sure to get whole filename
    ( 
      [^'] +     # at least one non-quote
      \.         # extension dot
      (?:        # now either suffix
          gz
        | Z 
       )
    )
    \z           # through the end
}{gzcat '$1' |}xs for @ARGV;

(kutipan sekitar $ _ diperlukan untuk menangani nama file dengan karakter meta shell di)

Sekarang <>fitur tersebut akan mendekompres semua @ARGVfile yang diakhiri dengan ".gz" atau ".Z":

while (<>) {
    print;
}

2
Saya tidak berpikir Anda harus lolos |dari penggantian.
Chris Lutz

Saya menatap ini dan saya tidak tahu cara kerjanya. Pada titik mana zcat |diuraikan sebagai perintah untuk pipa melalui?
Eter

1
@ Ether => mendeteksi pipa adalah fitur dari dua argumen terbuka, yang digunakan operator berlian saat membuka setiap file di@ARGV
Eric Strom

40

Salah satu fitur favorit saya di Perl adalah menggunakan ||operator boolean untuk memilih di antara serangkaian pilihan.

 $x = $a || $b;

 # $x = $a, if $a is true.
 # $x = $b, otherwise

Ini berarti seseorang dapat menulis:

 $x = $a || $b || $c || 0;

untuk mengambil nilai sebenarnya pertama dari $a, $b, dan$c , atau default0 sebaliknya.

Di Perl 5.10, ada juga //operator, yang mengembalikan sisi kiri jika sudah ditentukan, dan sisi kanan sebaliknya. Yang ditunjuk mengikuti pertama didefinisikan nilai dari $a, $b, $c, atau0 sebaliknya:

$ x = $ a // $ b // $ c // 0;

Ini juga dapat digunakan dengan form tangan pendeknya, yang sangat berguna untuk menyediakan default:

$ x || = 0; # Jika $ x salah, sekarang bernilai 0.

$ x // = 0; # Jika $ x tidak terdefinisi, sekarang memiliki nilai nol.

Cheerio,

Paul


4
Ini adalah idiom umum yang hampir tidak memenuhi syarat sebagai fitur "tersembunyi".
Michael Carman

3
Sayang printer cantik berpikir // adalah komentar :)
John Ferguson

2
Pertanyaan, adakah "fitur pakai" untuk menggunakan operator baru ini, atau apakah standarnya diaktifkan? Saya masih condong ke fitur Perl 5.10.
JJ

6
// ada di sana secara default, tidak perlu tweak khusus. Anda juga dapat mem-backportnya ke 5.8.x dengan dor-patch ... lihat direktori penulis / id / H / HM / HMBRAND / pada mirror CPAN. FreeBSD 6.x dan selanjutnya melakukan ini untuk Anda dalam paket perl mereka.
dland

2
Kapan || atau // digabungkan dengan do {}, Anda dapat merangkum tugas yang lebih kompleks, yaitu $ x = $ a || do {my $ z; 3 atau 4 garis derivasi; $ z};
RET

39

Operator ++ dan unary - tidak hanya bekerja pada angka, tetapi juga pada string.

my $_ = "a"
print -$_

cetakan -a

print ++$_

cetakan b

$_ = 'z'
print ++$_

mencetak aa


3
Mengutip perlvar: "Operator auto-decrement tidak ajaib." Jadi --tidak berfungsi pada string.
moritz

"aa" tampaknya bukan unsur alami yang mengikuti "z". Saya mengharapkan nilai ascii tertinggi berikutnya, yaitu "{".
Eter

4
Jangan tanya programmer apa yang muncul setelah "z"; tanya manusia. Fitur ini bagus untuk penomoran item dalam daftar panjang.
Barry Brown

17
Ketika baru mengenal Perl, saya menerapkan fitur ini sendiri dengan perilaku z to aa yang tepat, lalu menunjukkannya kepada rekan kerja yang tertawa dan saya dan berkata "biarkan saya menunjukkan sesuatu". Saya menangis sedikit tetapi mempelajari sesuatu.
Copas

2
@ Lain - Jika Anda menginginkannya, gunakan angka dan autoconvert ke ASCII dengan ord(). Atau, tulis kelas kecil dan membebani operator untuk melakukannya untuk Anda.
Chris Lutz

36

Karena Perl memiliki hampir semua bagian "esoterik" dari daftar lain, saya akan memberi tahu Anda satu hal yang tidak dapat Perl:

Satu hal yang Perl tidak dapat lakukan adalah memiliki URL sewenang-wenang dalam kode Anda, karena // operator digunakan untuk ekspresi reguler.

Untuk berjaga-jaga kalau tidak jelas bagi Anda fitur apa yang ditawarkan Perl, berikut adalah daftar pilihan entri yang mungkin tidak sepenuhnya jelas:

Perangkat Duff - dalam Perl

Portabilitas dan Standar - Kemungkinan ada lebih banyak komputer dengan Perl daripada dengan kompiler C

Kelas manipulasi file / jalur - File :: Find berfungsi bahkan pada sistem operasi yang lebih banyak daripada .Net

Kutipan untuk daftar dan string yang dibatasi whitespace - Perl memungkinkan Anda untuk memilih kutipan yang hampir sewenang-wenang untuk daftar Anda dan pembatas string

Ruang nama yang dapat diubah - Perl memiliki ini melalui penugasan glob:

*My::Namespace:: = \%Your::Namespace

Inisialisasi statis - Perl dapat menjalankan kode di hampir setiap fase kompilasi dan instantiasi objek, dari BEGIN(parse kode) ke CHECK(setelah parse kode) ke import(pada impor modul) ke new(instantiasi objek) ke DESTROY(objek penghancuran) ke END( penghancuran objek) ke (keluar dari program)

Fungsinya adalah warga negara kelas satu - seperti di Perl

Blok cakupan dan penutupan - Perl memiliki keduanya

Metode panggilan dan accessor secara tidak langsung melalui variabel - Perl juga melakukannya:

my $method = 'foo';
my $obj = My::Class->new();
$obj->$method( 'baz' ); # calls $obj->foo( 'baz' )

Mendefinisikan metode melalui kode - Perl juga memungkinkan :

*foo = sub { print "Hello world" };

Dokumentasi pervasive online - Dokumentasi Perl online dan mungkin juga ada di sistem Anda

Metode ajaib yang dipanggil setiap kali Anda memanggil fungsi "tidak ada" - Perl mengimplementasikannya dalam fungsi AUTOLOAD

Referensi simbolik - Anda disarankan untuk menjauh dari ini. Mereka akan memakan anak-anakmu. Tapi tentu saja, Perl memungkinkan Anda untuk menawarkan anak-anak Anda kepada iblis yang haus darah.

Swapping nilai satu garis - Perl memungkinkan penugasan daftar

Kemampuan untuk mengganti fungsi inti dengan fungsi Anda sendiri

use subs 'unlink'; 
sub unlink { print 'No.' }

atau

BEGIN{
    *CORE::GLOBAL::unlink = sub {print 'no'}
};

unlink($_) for @ARGV

Saya penggemar dokumentasi Perl dibandingkan dengan bahasa lain, tapi saya masih berpikir bahwa untuk Regex dan referensi itu bisa dirasionalisasi banyak. mis. primer terbaik untuk regex bukanlah Perlre, tetapi Perlop
John Ferguson

9
"Satu-satunya yang tidak bisa dilakukan Perl adalah memiliki URL sewenang-wenang dalam kode Anda, karena // operator digunakan untuk ekspresi reguler." - ini omong kosong.

Terima kasih atas wawasan Anda. Saya telah melihat beberapa cara untuk memiliki URL telanjang http: // ... URL dalam kode Perl tanpa menggunakan filter sumber, dan tidak menemukan cara. Mungkin Anda dapat menunjukkan bagaimana ini mungkin? // digunakan untuk ekspresi reguler dalam versi Perl hingga 5.8.x.Pada 5.10 ini digunakan kembali untuk tugas-atau yang ditentukan.
Corion

8
Mengapa / di mana Anda ingin URL telanjang dalam kode Anda? Saya tidak bisa memikirkan contoh.
terbuang

18
Tidak ada yang mau itu, itu hanya meme Jawa. " foo.com " adalah label http: dan kemudian "foo.com" dalam komentar. Beberapa orang menganggap ini menarik karena ... mereka bodoh.
jrockway

35

Autovivification . AFAIK tidak ada bahasa lain yang memilikinya .


Saya tidak tahu bahwa Python, dkk, tidak mendukung ini.
skiphoppy

@davidnicol: Benarkah? Dapatkah Anda menyediakan sebuah sambungan? Pencarian cepat saya di google tidak menghasilkan apa-apa. Bagi mereka yang tidak tahu ECMAscript adalah nama yang benar untuk Javascript. en.wikipedia.org/wiki/ECMAScript
JJ

1
Dan ada modul untuk menonaktifkan autovivication
Alexandr Ciornii

1
@Gregg Lind - Mengingat bahwa Python secara otomatis membuat variabel setiap kali Anda menetapkannya, autovivification akan menciptakan masalah besar hanya dari satu kesalahan ketik.
Chris Lutz

3
@tchrist - a = [[x * y untuk y di xrange (1,11)] untuk x in xrange (1,11)]
Mahakuasa

31

Sangat mudah untuk mengutip hampir semua jenis string aneh di Perl.

my $url = q{http://my.url.com/any/arbitrary/path/in/the/url.html};

Faktanya, berbagai mekanisme penawaran dalam Perl cukup menarik. Mekanisme mengutip seperti regex Perl memungkinkan Anda untuk mengutip sesuatu, menentukan pembatas. Anda dapat menggunakan hampir semua karakter khusus seperti #, /, atau membuka / menutup karakter seperti (), [], atau {}. Contoh:

my $var  = q#some string where the pound is the final escape.#;
my $var2 = q{A more pleasant way of escaping.};
my $var3 = q(Others prefer parens as the quote mechanism.);

Mekanisme mengutip:

q: kutipan literal; hanya karakter yang perlu melarikan diri adalah karakter akhir. qq: kutipan yang ditafsirkan; memproses variabel dan melarikan diri karakter. Bagus untuk string yang perlu Anda kutip:

my $var4 = qq{This "$mechanism" is broken.  Please inform "$user" at "$email" about it.};

qx: Bekerja seperti qq, tetapi kemudian menjalankannya sebagai perintah sistem, non-interaktif. Mengembalikan semua teks yang dihasilkan dari standar keluar. (Redirection, jika didukung dalam OS, juga keluar) Juga dilakukan dengan tanda kutip kembali (karakter `).

my $output  = qx{type "$path"};      # get just the output
my $moreout = qx{type "$path" 2>&1}; # get stuff on stderr too

qr: Mengartikan seperti qq, tetapi kemudian mengkompilasinya sebagai ekspresi reguler. Bekerja dengan berbagai opsi pada regex juga. Anda sekarang dapat melewatkan regex sebagai variabel:

sub MyRegexCheck {
    my ($string, $regex) = @_;
    if ($string)
    {
       return ($string =~ $regex);
    }
    return; # returns 'null' or 'empty' in every context
}

my $regex = qr{http://[\w]\.com/([\w]+/)+};
@results = MyRegexCheck(q{http://myurl.com/subpath1/subpath2/}, $regex);

qw: Operator penawaran yang sangat berguna. Mengubah seperangkat kata yang dikutip dari spasi putih yang dikutip menjadi daftar. Sangat bagus untuk mengisi data dalam unit test.


   my @allowed = qw(A B C D E F G H I J K L M N O P Q R S T U V W X Y Z { });
   my @badwords = qw(WORD1 word2 word3 word4);
   my @numbers = qw(one two three four 5 six seven); # works with numbers too
   my @list = ('string with space', qw(eight nine), "a $var"); # works in other lists
   my $arrayref = [ qw(and it works in arrays too) ]; 

Mereka bagus untuk menggunakannya kapan pun hal itu membuat lebih jelas. Untuk qx, qq, dan q, kemungkinan besar saya menggunakan operator {}. Kebiasaan paling umum orang menggunakan qw biasanya operator (), tetapi kadang-kadang Anda juga melihat qw //.


1
Saya terkadang menggunakan qw "" sehingga syntax highlighters akan menyorotnya dengan benar.
Brad Gilbert

Bekerja untuk saya di SlickEdit. :)
Robert P

1
@fengshaun, Para editor saya biasanya menggunakan do menyoroti ini dengan benar. Saya merujuk, sebagian ke stabilo sintaks di StackOverflow.
Brad Gilbert

@ Rad Gilbert: Stack Overflow tidak bisa (well, (tidak) mengurai Perl layak jongkok. ā˜¹
tchrist

my $moreout = qx{type "$path" 2>&1};... Aku tidak tahu kamu bisa melakukan itu! [TM]
dland

27

Tidak benar-benar tersembunyi, tetapi banyak programmer setiap hari Perl tidak tahu tentang CPAN . Ini terutama berlaku untuk orang-orang yang bukan pemrogram penuh waktu atau tidak memprogram dalam waktu penuh Perl.


27

Pernyataan "untuk" dapat digunakan dengan cara yang sama "dengan" digunakan dalam Pascal:

for ($item)
{
    s/&ā€Žnbsp;/ /g;
    s/<.*?>/ /g;
    $_ = join(" ", split(" ", $_));
}

Anda dapat menerapkan urutan operasi s / / /, dll untuk variabel yang sama tanpa harus mengulangi nama variabel.

CATATAN: ruang tanpa putus di atas (& nbsp;) telah menyembunyikan Unicode di dalamnya untuk menghindari penurunan harga. Jangan menyalinnya :)


Dan "map" juga melakukan trik yang sama ... map {....} $ item; Salah satu keuntungan menggunakan "untuk" lebih dari "peta" adalah Anda dapat menggunakan berikutnya untuk keluar.
draegtun

2
Juga, karena item dimanipulasi terdaftar sebelum kode melakukan manipulasi, yang mengarah ke keterbacaan yang lebih baik.
Robert P

@ RobertTP: Itu benar sekali. Seorang pembuat topik berguna dalam wacana.
tchrist

26

Operator kata sandi adalah salah satu hal favorit saya. Membandingkan:

my @list = ('abc', 'def', 'ghi', 'jkl');

dan

my @list = qw(abc def ghi jkl);

Jauh lebih sedikit noise, lebih mudah pada mata. Hal lain yang sangat bagus tentang Perl, yang sangat dirindukan ketika menulis SQL, adalah bahwa tanda koma adalah sah:

print 1, 2, 3, ;

Itu terlihat aneh, tetapi tidak jika Anda indentasi kode dengan cara lain:

print
    results_of_foo(),
    results_of_xyzzy(),
    results_of_quux(),
    ;

Menambahkan argumen tambahan ke pemanggilan fungsi tidak mengharuskan Anda untuk mengutak-atik koma pada garis sebelumnya atau garis akhir. Perubahan garis tunggal tidak berdampak pada garis sekitarnya.

Ini membuatnya sangat menyenangkan untuk bekerja dengan fungsi variadic. Ini mungkin salah satu fitur Perl yang paling rendah.


2
Sebuah kasus sudut yang menarik dari sintaks Perl adalah bahwa yang berikut ini valid: untuk $ _ qw (daftar barang) {...}
ephemient

1
Anda bahkan dapat menyalahgunakan sintaks glob untuk mengutip kata-kata, selama Anda tidak menggunakan karakter khusus seperti * ?. Jadi, Anda dapat menulisfor (<a list of stuff>) { ... }
moritz

1
@ephemient: hampir. Itu hanya berfungsi dengan leksikal: untuk $ x qw (abc) {...} Misalnya: untuk $ _ qw (abc) {print} # mencetak apa
dland

mengapa menambahkan leksikal tambahan ketika Anda dapat menikmati default favorit perl? untuk (qw / abcd /) {print; }
fengshaun

2
@ephemient, @fengshaun, @moritz, @dland: Itu "diperbaiki" dalam blead ; lihat utas p5p ini .
tchrist

26

Kemampuan untuk mem-parsing data yang langsung disisipkan ke dalam blok DATA . Tidak perlu menyimpan ke file uji untuk dibuka di program atau serupa. Sebagai contoh:

my @lines = <DATA>;
for (@lines) {
    print if /bad/;
}

__DATA__
some good data
some bad data
more good data 
more good data 

Dan sangat berguna dalam tes kecil!
fengshaun

@ Peter Mortensen, bagaimana Anda memiliki beberapa blok? Dan bagaimana Anda mengakhiri blok?
Kodok

@ Memuat: ini adalah jawaban allan (lihat daftar revisi). Lebih baik untuk mengatasi pengguna itu. Atau, karena pengguna telah meninggalkan Stack Overflow, mungkin alamat tidak ada yang khusus (sehingga ahli Perl nyata dapat meluruskannya nanti).
Peter Mortensen

3
@ Hai: Tidak itu tidak jelek - sebenarnya, justru kebalikan dari jelek: itu bersih, langsing, minim, dan indah; dalam satu kata, itu luar biasa, dan bahasa tanpa itu adalah PITA. @peter mortensen, @toad: Salah satu jawaban untuk bagaimana memiliki beberapa blok data dalam program yang sama adalah dengan menggunakan modul Inline :: Files dari CPAN.
tchrist

Inline :: File diimplementasikan menggunakan filter sumber. Ada juga Data :: Bagian yang menyediakan beberapa blok inline dan tidak menggunakan filter sumber.
Prakash K

24

Operasi Blok Baru

Saya akan mengatakan kemampuan untuk memperluas bahasa, membuat operasi pseudo block adalah satu.

  1. Anda mendeklarasikan prototipe untuk sub yang menunjukkan bahwa dibutuhkan referensi kode terlebih dahulu:

    sub do_stuff_with_a_hash (&\%) {
        my ( $block_of_code, $hash_ref ) = @_;
        while ( my ( $k, $v ) = each %$hash_ref ) { 
            $block_of_code->( $k, $v );
        }
    }
  2. Anda kemudian dapat menyebutnya di dalam tubuh seperti itu

    use Data::Dumper;
    
    do_stuff_with_a_hash {
        local $Data::Dumper::Terse = 1;
        my ( $k, $v ) = @_;
        say qq(Hey, the key   is "$k"!);
        say sprintf qq(Hey, the value is "%v"!), Dumper( $v );
    
    } %stuff_for
    ;

( Data::Dumper::Dumperadalah permata semi-tersembunyi.) Perhatikan bagaimana Anda tidak memerlukannyasub kata kunci di depan blok, atau koma sebelum hash. Itu akhirnya tampak seperti:map { } @list

Filter Sumber

Juga, ada filter sumber. Di mana Perl akan memberikan Anda kode sehingga Anda dapat memanipulasinya. Baik ini, dan operasi blok, cukup banyak jangan-coba-ini-di rumah.

Saya telah melakukan beberapa hal yang rapi dengan filter sumber, misalnya seperti membuat bahasa yang sangat sederhana untuk memeriksa waktu, memungkinkan Perl satu kalimat pendek untuk beberapa pengambilan keputusan:

perl -MLib::DB -MLib::TL -e 'run_expensive_database_delete() if $hour_of_day < AM_7';

Lib::TL hanya akan memindai "variabel" dan konstanta, membuat mereka dan menggantikannya sesuai kebutuhan.

Sekali lagi, filter sumber bisa berantakan, tetapi sangat kuat. Tetapi mereka dapat mengacaukan hal-hal buruk - dan bahkan peringatan dapat dicetak dengan nomor baris yang salah. Saya berhenti menggunakan Damian's Switch karena debugger akan kehilangan semua kemampuan untuk memberi tahu saya di mana saya sebenarnya. Tetapi saya telah menemukan bahwa Anda dapat meminimalkan kerusakan dengan memodifikasi bagian kecil kode, menjaganya tetap pada baris yang sama.

Pengait Sinyal

Sudah cukup sering dilakukan, tetapi tidak begitu jelas. Berikut adalah pawang mati yang mendukung piggy yang lama.

my $old_die_handler = $SIG{__DIE__};
$SIG{__DIE__}       
    = sub { say q(Hey! I'm DYIN' over here!); goto &$old_die_handler; }
    ;

Itu berarti setiap kali modul lain dalam kode ingin mati, mereka harus datang kepada Anda (kecuali orang lain menimpa $SIG{__DIE__} ). Dan Anda dapat diberitahu bahwa ada sesuatu yang salah pada seseorang.

Tentu saja, untuk hal-hal yang cukup Anda hanya dapat menggunakan END { }blok, jika semua yang ingin Anda lakukan adalah membersihkan.

overload::constant

Anda dapat memeriksa literal jenis tertentu dalam paket yang menyertakan modul Anda. Misalnya, jika Anda menggunakan ini di importsub Anda :

overload::constant 
    integer => sub { 
        my $lit = shift;
        return $lit > 2_000_000_000 ? Math::BigInt->new( $lit ) : $lit 
    };

itu berarti bahwa setiap bilangan bulat lebih besar dari 2 miliar dalam paket panggilan akan diubah menjadi Math::BigIntobjek. (Lihat kelebihan :: konstan ).

Literal Integer yang Dikelompokkan

Sementara kita melakukannya. Perl memungkinkan Anda untuk memecah sejumlah besar menjadi kelompok tiga digit dan masih mendapatkan integer parsable dari itu. Catatan di 2_000_000_000atas untuk 2 miliar.


5
Saat menggunakan penangan $ SIG { DIE }, sangat disarankan agar Anda memeriksa $ ^ S untuk melihat apakah program Anda benar-benar sekarat, atau hanya melempar pengecualian yang akan ditangkap. Biasanya Anda tidak ingin mengganggu yang terakhir.
pjf

Blok baru sangat instruktif! Saya berpikir itu adalah semantik bahasa! terimakasih banyak.
ZeroCool

Penggunaan filter sumber secara instruktif adalah NiceSlice pdl ( pdl.perl.org/?docs=NiceSlice&title=PDL::NiceSlice ) sehingga orang tidak perlu menggunakan ->slicesebagai metode setiap kali diperlukan irisan.
Joel Berger

24

Biner "x" adalah operator pengulangan :

print '-' x 80;     # print row of dashes

Ini juga berfungsi dengan daftar:

print for (1, 4, 9) x 3; # print 149149149

Ini adalah salah satu alasan mengapa Perl sangat populer di kalangan peretas. perl -e 'print 0x000 x 25';
JJ

4
Penggunaan favorit saya untuk ini adalah menghasilkan placeholder untuk bagian terakhir dari pernyataan SQL INSERT: @p = ('?') X $ n; $ p = join (",", @p); $ sql = "INSERT ... VALUES ($ p)";
skiphoppy

24

Pemeriksaan noda. Dengan pemeriksaan noda diaktifkan, perl akan mati (atau memperingatkan, dengan-t ) jika Anda mencoba meneruskan data tercemar (secara kasar, data dari luar program) ke fungsi yang tidak aman (membuka file, menjalankan perintah eksternal, dll.). Sangat membantu ketika menulis skrip setuid atau CGI atau apa pun di mana skrip memiliki hak istimewa yang lebih besar daripada orang yang memberinya data.

Goto ajaib. goto &submelakukan panggilan ekor yang dioptimalkan.

Debugger.

use strictdan use warnings. Ini dapat menyelamatkan Anda dari banyak kesalahan ketik.


1
Mengapa bahasa lain tidak memiliki fitur ini? Fitur ini digunakan membuat skrip web perl urutan lebih besar lebih aman.
Matthew Lock

22

Berdasarkan cara "-n"dan "-p"sakelar diimplementasikan di Perl 5, Anda dapat menulis program yang tampaknya salah termasuk }{:

ls |perl -lne 'print $_; }{ print "$. Files"'

yang dikonversi secara internal ke kode ini:

LINE: while (defined($_ = <ARGV>)) {
    print $_; }{ print "$. Files";
}

@martin clayton: Mengapa disebut demikian?
tchrist

@tchrist - karena, konon, sepertinya dua orang menggosok hidung. Dalam profil, jika Anda melihat apa yang saya maksud.
martin clayton

18

Mari kita mulai dengan Operator Ruang Angkasa .

$a = 5 <=> 7;  # $a is set to -1
$a = 7 <=> 5;  # $a is set to 1
$a = 6 <=> 6;  # $a is set to 0

1
@Leon: C / C ++ tidak melakukan pengembalian nilai 3 untuk angka. Jika memori berfungsi fungsi comapre String adalah nilai kembali hanya 3 yang saya tahu dalam seluruh bahasa STL. AFAIK Python tidak memiliki perbandingan 3 angka kembali. Java juga tidak memiliki angka 3 perbandingan pengembalian.
JJ

7
Perlu disebutkan apa yang sangat berguna tentang -1/0/1 operator perbandingan, karena tidak semua orang mungkin tahu: Anda dapat menghubungkan mereka bersama-sama dengan atau-operator untuk melakukan primary / secondary / etc. macam. Jadi ($a->lname cmp $b->lname) || ($a->fname cmp $b->fname)macam orang dengan nama belakang mereka, tetapi jika dua orang memiliki nama belakang yang sama maka mereka akan dipesan dengan nama depan mereka.
hobbs

@JJ Python memang memiliki perbandingan 3-nilai: cmp () >>> cetak (cmp (5,7), cmp (6,6), cmp (7,5)) (-1, 0, 1)
bukzor

18

Ini adalah meta-jawaban, tetapi arsip Perl Tips berisi segala macam trik menarik yang dapat dilakukan dengan Perl. Arsip tips sebelumnya adalah online untuk browsing, dan dapat berlangganan melalui milis atau feed atom.

Beberapa tips favorit saya termasuk membangun executables dengan PAR , menggunakan autodie untuk melempar pengecualian secara otomatis , dan penggunaan switch dan konstruksi smart-match di Perl 5.10.

Pengungkapan: Saya adalah salah satu penulis dan pengelola Perl Tips, jadi saya jelas sangat memikirkan mereka. ;)


2
Itu mungkin salah satu bahasa terbaik yang didokumentasikan di luar sana, dan mengatur pola alat untuk mencari dokumentasi. Bahwa daftar dalam pertanyaan ini mungkin tidak diperlukan seperti bahasa lain.
Axeman

1
Autodie terlihat sangat bagus.
j_random_hacker

18

map - bukan hanya karena itu membuat kode seseorang lebih ekspresif, tetapi karena itu memberi saya dorongan untuk membaca sedikit lebih banyak tentang "pemrograman fungsional" ini.


15

Klausa melanjutkan loop. Ini akan dieksekusi di bagian bawah setiap loop, bahkan yang berikutnya.

while( <> ){
  print "top of loop\n";
  chomp;

  next if /next/i;
  last if /last/i;

  print "bottom of loop\n";
}continue{
  print "continue\n";
}

15

Pilihan saya akan untuk grup (? {}) Dan (?? {}) dalam ekspresi reguler Perl. Yang pertama mengeksekusi kode Perl, mengabaikan nilai kembali, kode mengeksekusi kedua, menggunakan nilai kembali sebagai ekspresi reguler.


perl menemukan begitu banyak ekstensi regexp sehingga program lain sekarang sering menggunakan pcre (perl kompatibel regex) alih-alih bahasa regex asli.
Sec

Baca uraian singkat di sini perldoc.perl.org/... :-D
JJ

Perl benar-benar memiliki (sejauh yang saya tahu), memimpin paket, ketika datang ke regexps.
Brad Gilbert

Sejauh ini yang saya ketahui masih eksperimental, dan mungkin tidak bekerja dengan cara yang sama di Perls di masa depan. Bukan untuk mengatakan bahwa itu tidak berguna, tetapi versi yang sedikit lebih aman dan dapat digunakan dapat ditemukan di bendera s / / perintah / e: s/(pattern)/reverse($1);/ge;# membalikkan semua patterns.
Chris Lutz

@ Chris Lutz, @Leon Timmerman: Perhatikan bahwa kedua konstruk tersebut sekarang mencolok. Juga perhatikan bahwa yang kedua tidak perlu lagi digunakan untuk mempengaruhi pola rekursif, sekarang kita bisa kambuh pada kelompok tangkapan. @ Rad Gilbert: Itu benar, meskipun PCRE melakukan pekerjaan yang layak untuk melacak kami; satu area keunggulan regex di mana Perl benar-benar tidak tertandingi adalah aksesnya ke properti Unicode; melihat distribusi unitrio saya uninames, unicharsdan terutama unipropsuntuk melihat hanya bagian dari apa yang saya maksud.
tchrist

13
while(/\G(\b\w*\b)/g) {
     print "$1\n";
}

jangkar \ G. Ini panas .


3
... dan itu menunjukkan posisi akhir dari pertandingan sebelumnya.
Dave Sherohman

1
Tetapi Anda harus memanggil regex Anda dalam konteks skalar.
davidnicol

@davidnicol: Kode di atas berfungsi. Bisakah Anda mengklarifikasi maksud Anda?
JJ

13

The m//operator memiliki beberapa kasus khusus jelas:

  • Jika Anda menggunakan ? sebagai pembatas itu hanya cocok sekali kecuali Anda menelepon reset.
  • Jika Anda menggunakan 'sebagai pembatas, polanya tidak diinterpolasi.
  • Jika polanya kosong, ia menggunakan polanya dari pertandingan terakhir yang berhasil.

2
Ini lebih seperti gotcha tersembunyi daripada fitur tersembunyi! Saya tidak kenal siapa pun yang menyukainya. Sebuah utas pada p5p beberapa waktu lalu membahas kegunaan dari bendera m / $ foo / r yang diduga, di mana / r akan berarti tidak ada interpolasi (surat itu tidak penting) karena tidak ada yang dapat mengingat satu hal tanda kutip.
dland

2
@ tanah: Setuju; Saya akan memanggil fitur mis tersembunyi ini dan tidak akan pernah menggunakannya dalam kode produksi.
Michael Carman

7
Saya tidak bisa membayangkan seorang programmer Perl tidak dapat mengingat (atau bahkan menebak) bahwa tanda kutip tunggal berdiri tanpa interpolasi. Penggunaannya dengan semantik ini hampir universal dalam bahasa yang saya lebih suka berharap ini menjadi begitu ...
sundar - Reinstate Monica

dan jika polanya kosong dan pertandingan terakhir yang berhasil dikompilasi dengan / o modifier, sejak saat itu akan terjebak pada pola itu.
davidnicol

1
Saya pikir perilaku pola kosong telah usang. Terutama karena pola seperti m / $ foo / menjadi bug jahat ketika $ foo kosong.
Matius S

12

Operator berlian filehandle nol <>memiliki tempat dalam membangun alat-alat baris perintah. Kerjanya suka <FH>membaca dari pegangan, kecuali bahwa secara ajaib memilih mana yang ditemukan pertama kali: nama file baris perintah atau STDIN. Diambil dari perlop:

while (<>) {
...         # code for each line
}

4
Hal ini juga mengikuti semantik UNIX menggunakan "-" berarti "membaca dari stdin Jadi Anda bisa melakukan. perl myscript.pl file1.txt - file2.txt, Dan perl akan memproses file pertama, kemudian stdin, maka file kedua.
Ryan C. Thompson

Anda dapat overloaddengan <>operator pada objek sendiri ( <$var>) bekerja seperti iterator. Namun itu tidak berfungsi seperti yang Anda harapkan dalam konteks daftar.
dolmen

11

Blok kode khusus seperti BEGIN, CHECKdanEND . Mereka berasal dari Awk, tetapi bekerja secara berbeda di Perl, karena tidak berbasis catatan.

The BEGINblok dapat digunakan untuk menentukan beberapa kode untuk tahap parsing; itu juga dieksekusi ketika Anda melakukan sintaks-dan-variabel-cek perl -c. Misalnya, memuat dalam variabel konfigurasi:

BEGIN {
    eval {
        require 'config.local.pl';
    };
    if ($@) {
        require 'config.default.pl';
    }
}

11
rename("$_.part", $_) for "data.txt";

mengganti nama data.txt.part menjadi data.txt tanpa harus mengulang sendiri.


10

Agak tidak jelas adalah "operator" tilde-tilde yang memaksa konteks skalar.

print ~~ localtime;

sama dengan

print scalar localtime;

dan berbeda dari

print localtime;

5
Ini sangat tidak jelas karena perl5.10.0 juga memperkenalkan "operator pencocokan pintar" ~~, yang dapat melakukan pencocokan regex, dapat melihat apakah suatu item terkandung dalam array dan sebagainya.
moritz

Itu tidak jelas, itu dikaburkan (dan berguna untuk golf dan JAPH).
Michael Carman

Ini tidak benar! ~~ tidak aman pada referensi! Itu membuat mereka kaku.
Leon Timmermans

Baiklah. Stringifikasi adalah apa yang terjadi pada referensi ketika dipaksa ke dalam konteks skalar. Bagaimana hal itu membuat "~~ memaksa konteks skalar" salah?
Dave Sherohman

3
@Nomad Darwis: Konteks skalar / = stringifikasi. mis. "$ n = @a" adalah konteks skalar. "$ s = qq '@ a'" adalah stringifikasi. Berkenaan dengan referensi, "$ ref1 = $ ref2" adalah konteks skalar, tetapi tidak mengikat.
Michael Carman


9

"Mode putus asa" dari konstruksi kontrol loop Perl yang menyebabkan mereka mencari tumpukan untuk menemukan label yang cocok memungkinkan beberapa perilaku aneh yang diuji :: Lebih mengambil manfaat, baik atau buruk.

SKIP: {
    skip() if $something;

    print "Never printed";
}

sub skip {
    no warnings "exiting";
    last SKIP;
}

Ada file .pmc yang sedikit diketahui. "use Foo" akan mencari Foo.pmc di @INC sebelum Foo.pm. Ini dimaksudkan untuk memungkinkan bytecode yang dikompilasi dimuat terlebih dahulu, tetapi Module :: Compile mengambil keuntungan dari ini untuk cache modul yang disaring sumber untuk waktu muat yang lebih cepat dan lebih mudah untuk debugging.

Kemampuan untuk mengubah peringatan menjadi kesalahan.

local $SIG{__WARN__} = sub { die @_ };
$num = "two";
$sum = 1 + $num;
print "Never reached";

Itulah yang bisa saya pikirkan dari atas kepala saya yang belum disebutkan.


9

Operator kambing *:

$_ = "foo bar";
my $count =()= /[aeiou]/g; #3

atau

sub foo {
    return @_;
}

$count =()= foo(qw/a b c d/); #4

Ini berfungsi karena penugasan daftar dalam konteks skalar menghasilkan jumlah elemen dalam daftar yang ditugaskan.

* Catatan, bukan benar-benar operator


Itu adalah "operator" yang paling indah (paling tidak paling indah).
Chris Lutz
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.