كيف تكون "0" الناتجة عن ReadDir () ليست خاطئة في حالة من الوقت؟
-
20-08-2019 - |
سؤال
أنظر أيضا: أين في الوثائق يقول أنه بينما اختبارات ReadDir للخصم؟. (ليس مكرر فقط مرتبط ارتباطا وثيقا.)
كثير من الناس يعاملون الحلقة أدناه على أنها اصطلاح:
while (defined(my $file = readdir($dir)) {
...
}
بدلاً من:
while (my $file = readdir($dir)) {
...
}
لأنه من المفترض مع الإصدار الأخير إذا كان اسم الملف هو "0" (صفر) ، يجب أن ينهي الحلقة ، في حين أنه يعيد "undef" عندما لا يكون هناك المزيد من الملفات.
ولكن في مرحلة ما من الماضي هذا الاختبار defined()
توقف عن الضرورة - يبدو أن هناك رمز حالة خاص يسمح للإصدار الأخير بالعمل بغض النظر.
أود أن أعرف كيف يعمل هذا؟
من الغريب ، إذا استبدلت المكالمة readdir()
مع دعوة إلى foo()
في حين أن:
sub foo
{
my ($dir) = @_;
return readdir($dir);
}
while (my $file = foo($dir)) {
...
}
ثم الرمز يفعل افعل ما كنت أتوقعه ، وإنهاء الحلقة عند العثور على ملف يسمى "0".
(تم اختباره مع Perl 5.8.9 على MacOS X 10.5.6)
المحلول
إنه سحر. على وجه التحديد أثناء توثيقه (موثق في perlsyn
, perlop
, ، وربما أماكن أخرى لا أتذكرها). يتيح لك Perl بعض الرموز المختصرة. إذا كنت تريد أن ترى ما الذي يفعله بيرل خلف ظهرك ، يمكنك استخدامه B::Deparse
. فيما يلي ملف يستخدم حلقة الاختزال:
#!/usr/bin/perl
use strict;
use warnings;
opendir my $dir, "/tmp" or die "$!";
while (my $file = readdir($dir)) {
print "$file\n";
}
اذا ركضت perl -MO=Deparse filename.pl
تحصل على الرمز الذي يرى بيرل:
use warnings;
use strict 'refs';
die "$!" unless opendir my $dir, '/tmp';
while (defined(my $file = readdir $dir)) {
do {
print "$file\n"
};
}
filename.pl syntax OK