Soru Perl'deki BEGIN bloğunun rolü nedir?


BEGIN bloğunun bir Perl programının ana gövdesinden önce derlendiğini ve yürütüldüğünü biliyorum. Bundan emin değilseniz, sadece bu komut üzerinde perl -cw komutunu çalıştırmayı deneyin:

#!/ms/dist/perl5/bin/perl5.8

use strict;
use warnings;

BEGIN {
    print "Hello from the BEGIN block\n";
}

END {
    print "Hello from the END block\n";
}

Bir BEGIN bloğunun erken derlenmesinin ve yürütülmesinin, bir programcının ana programın yürütülmesinden önce gerekli kaynakların mevcut olmasını sağladığını öğrettim.

Ve böylece DB bağlantıları gibi şeylerin kurulmuş olduğundan ve ana program tarafından kullanılabildiğinden emin olmak için BEGIN bloklarını kullanıyorum. Benzer şekilde, program bitmeden tüm kaynakların kapatıldığından, silinmesinden, sonlandırılmasından vb. Emin olmak için END bloklarını kullanıyorum.

Bu sabah bir tartışmadan sonra, BEGIN ve END bloklarına bakmanın yanlış bir yol olup olmadığını merak ediyorum.

Perl'de bir BEGIN bloğunun amaçlanan rolü nedir?

1. Güncelleme: Sadece DBI bağlantısının neden çalışmadığını öğrendim. Bu küçük Perl programından sonra:

use strict;
use warnings;

my $x = 12;

BEGIN {
    $x = 14;
}

print "$x\n";

yürütüldüğünde 12 yazdırır.

Güncelleme 2: Eric Strom'un bu yeni sürümün altındaki yorumu sayesinde daha net hale getirildi:

use strict;
use warnings;

my $x = 12;
my $y;

BEGIN {
    $x = 14;
    print "x => $x\n";
    $y = 16;
    print "y => $y\n";
}

print "x => $x\n";
print "y => $y\n";

ve çıktı

x => 14
y => 16
x => 12
y => 16

Bir kez daha teşekkürler Eric!


32
2017-10-22 15:56


Menşei


compuspec.net/reference/language/perl/BEGIN_and_END.shtml - jantimon
Bu durumda, standart DBI connect () işlevini kullanarak bir BEGIN bloğu içinde bir DB'ye DBI bağlantısı oluşturamıyorum? BEGIN bloğunu çıkarırsam, bağlantı yapılır - Rob Wells
Güncellemeniz için: çünkü my $x = 12 değişken derleme zamanında bildirir, ancak ödevi gerçekleştirmez. Daha sonra başlangıç ​​bloğu çalışır, bu da 14'ü atar. Sonra program çalışmaya başladığında my satırın atama 12 size verir. - Eric Strom


Cevaplar:


Değiştirmeyi denediniz mi BEGIN{} bir için engellemek INIT{} blok? Bu, derleme sırasında sadece bir kez değil, her bir ayrı çalışma için her şeyi yeniden başlatmanız gerektiğinden, "derleme, bir kez-çalıştır" modelini kullanan modperl gibi şeyler için standart yaklaşımdır.

Ama neden hepsinin özel bir bloğa olduğunu sormalıyım. Neden sadece bir çeşit yapmıyorsun prepare_db_connection() işlevini başlatın ve program başladığında ihtiyaç duyduğunuz şekilde çağırın.

Çalışmayacak bir şey BEGIN{} Ayrıca bir modül dosyasında ana hat kodu ise aynı sorunu olacak used. Bu kullanmak için başka olası bir sebep INIT{} blok.

Ayrıca, benzer bir şey kullanarak çözülmek zorunda olan karşılıklı tekrarlamanın ölümcül kucaklama sorunlarını da gördüm. require yerine useya da INIT{} yerine BEGIN{}. Ama bu oldukça nadirdir.

Bu programı düşünün:

% cat sto-INIT-eg
#!/usr/bin/perl -l
print               "    PRINT: main running";
die                 "    DIE:   main dying\n";
die                 "DIE XXX /* NOTREACHED */";
END         { print "1st END:   done running"    }
CHECK       { print "1st CHECK: done compiling"  }
INIT        { print "1st INIT:  started running" }
END         { print "2nd END:   done running"    }
BEGIN       { print "1st BEGIN: still compiling" }
INIT        { print "2nd INIT:  started running" }
BEGIN       { print "2nd BEGIN: still compiling" }
CHECK       { print "2nd CHECK: done compiling"  }
END         { print "3rd END:   done running"    }

Sadece derlendiğinde, üretir:

% perl -c sto-INIT-eg 
1st BEGIN: still compiling
2nd BEGIN: still compiling
2nd CHECK: done compiling
1st CHECK: done compiling
sto-INIT-eg syntax OK

Derlenmişken ve yürütülür, bunu üretir:

% perl sto-INIT-eg 
1st BEGIN: still compiling
2nd BEGIN: still compiling
2nd CHECK: done compiling
1st CHECK: done compiling
1st INIT:  started running
2nd INIT:  started running
    PRINT: main running
    DIE:   main dying
3rd END:   done running
2nd END:   done running
1st END:   done running

Ve kabuğun başına 255'lik bir çıkış bildiriyor. die.

İhtiyacınız olduğunda bağlantı kurulmasını sağlayabilmeniz gerekir. BEGIN{} çok erken kanıtlıyor.

Hm, yeni hatırladım. İle bir şey yapma şansın yok DATA içinde BEGIN{}, var mı? Bu tercüman çalışana kadar kurulmadı; derleyiciye açık değil.


21
2017-10-23 23:01





Süre BEGIN ve END tanımladığınız gibi bloklar kullanılabilir, tipik kullanım sonraki derlemeyi etkileyen değişiklikler yapmaktır.

Örneğin, use Module qw/a b c/; ifade aslında demektir:

BEGIN {
   require Module;
   Module->import(qw/a b c/);
}

benzer şekilde, alt rutin beyanı sub name {...} aslında:

BEGIN {
   *name = sub {...};
}

Bu bloklar derleme zamanında çalıştırıldığı için, bir blok çalıştıktan sonra derlenen tüm satırlar, BEGIN bloklarının yaptığı yeni tanımları kullanacaktır. Bu, parantez olmadan altprogramları nasıl arayabileceğiniz veya çeşitli modüllerin "dünyanın çalışma şeklini nasıl değiştirdiği" olarak tanımlayabilirsiniz.

ENDblokları değiştirmek için blokları kullanılabilir BEGIN bloklar yaptık ama bir DESTROY yöntem.

Temizlemeye çalıştığınız durum DBI bağlantısıysa, bunu bir END blok iyi. Bağlantıyı bir BEGIN çeşitli nedenlerden dolayı olsa da engellemek. Genellikle derleme zamanında bağlantının mevcut olmasına gerek yoktur. Derleme zamanında bir veritabanına bağlanma gibi eylemler gerçekleştirme, sözdizimi denetimi kullanan herhangi bir düzenleyiciyi önemli ölçüde yavaşlatacaktır (çünkü bu çalışır perl -c).


31
2017-10-22 16:05



Teşekkürler Eric. OO olmayan bir programda END bloklarını kullanma konusunda soruma bir uyarı eklemekten emin değildim. - Rob Wells


Diğer cevaplar doğru olsa da, aynı zamanda BEGIN ve END kullanırken bloklar -n veya -p Perl'e geçer.

itibaren http://perldoc.perl.org/perlmod.html

-N ve -p anahtarlarını Perl'e kullandığınızda, BEGIN ve END, tıpkı dehşet verici bir durum gibi, awk'ta olduğu gibi çalışır.

İle yabancı olanlar için -n geçiş, Perl'e programı şu şekilde kaydırmasını söyler:

while (<>) {
    ...  # your program goes here
}

http://perldoc.perl.org/perlrun.html#Command-Switches Perl anahtarları hakkında daha spesifik bilgi almak istiyorsanız.

Kullanımını göstermek için bir örnek olarak BEGIN ile -n switch, bu Perl one-liner satırlarının numaralarını ls komut:

ls | perl -ne 'BEGIN{$i = 1} print "$i: $_"; $i += 1;'

Bu durumda BEGIN-block değişkeni başlatmak için kullanılır $i satırlarını işlemeden önce 1 ile ayarlayarak ls. Bu örnek şöyle bir sonuç verecektir:

1: foo.txt
2: bar.txt
3: program.pl
4: config.xml

3
2017-07-24 09:17