لماذا يقوم Perl بتقييم الكود في $ {...} أثناء الاستيفاء السلسلة؟

StackOverflow https://stackoverflow.com/questions/2332815

  •  22-09-2019
  •  | 
  •  

سؤال

لماذا يعمل المقتطف التالي على الإطلاق؟ وما هو الشر الممكن باستخدام هذا؟ ولكن على محمل الجد ، هل هناك أي سبب ، الرمز في ${} يتم تقييمها على الإطلاق ثم تستخدم كمرجع العددية؟

use strict;
no strict 'refs';

our $message = "Hello world!";
print "${ lc 'MESSAGE' }\n";
هل كانت مفيدة؟

المحلول

حسنا، ما لم تستخدم المراجع الرمزية. افترض الرمز التالي:

my %messages = (hello => "Hello world!", bye => "Bye-bye, world!");
sub get_message_ref { return \$messages{$_[0]} }; # returns scalarref
print "${ get_message_ref('bye') }\n";

أوافق على ذلك ، فائدتها ليست واضحة مع scalarrefs ، لكنها مفيدة للغاية مع ArrayRefs.

print "keys: @{[keys %messages]}\n";

نصائح أخرى

نوضح هذا بعمق في بيرل وسيطة.

بناء الجملة العام للبحث المتغير هو:

 SIGIL  BLOCK  INDEXY-THING

للحصول على عدد بسيط يشبه:

 print $   { foo };

ربما تكون قد رأيت هذا عندما تحتاج إلى فصل اسم متغير عن الأشياء المحيطة به:

 print "abc${foo}def\n";

إذا كان لديك فقط معرف Perl في الكتلة ولا توجد فوضى محيطة ، فيمكنك ترك الأقواس ، وهي الحالة الشائعة:

 print $foo;

ومع ذلك ، هذا هو نفس الشيء لإلغاء مرجع:

 SIGIL  BLOCK-RETURNING-REFERENCE  INDEXY-THINGS

إذا كان الشيء الذي تحصل عليه في الكتلة مرجعًا ، فإن بيرل يحاول أن يضعفه كما طلبته أيضًا:

 my $ref = \ '12345';
 print $     { $ref };

هذه كتلة حقيقية ، وليس فقط السكر. يمكنك الحصول على العديد من العبارات التي تريدها هناك:

 print $     { my $ref = \ '1234'; $ref };

أنت الآن لا تحدد فقط معرف Perl ، لذلك لا تفترض Perl أنك تعطيه معرفًا ويقوم بتنفيذ التعليمات البرمجية ويستخدم النتيجة كمرجع. النظر في الفرق بين هذه متطابقة تقريبا say صياغات:

    use 5.010;
our $foo = "I'm the scalar";

sub foo { \ "I'm the sub" }

say ${foo};
say ${foo;};

في تلك الثانية say يرى بيرل شبه الكولون ، ويدرك أنه ليس معرفًا ، ويفسر الرمز داخل الأقواس كنص ، ويعيد النتيجة. نظرًا لأن النتيجة مرجعية ، فإنها تستخدم ${...} لترشيح ذلك. لا يهم من أين تفعل ذلك ، بحيث تقوم بذلك داخل سلسلة مزدوجة غير مخصصة.

أيضا ، لاحظ our هناك. هذا مهم الآن بعد أن فكرت في شيء أكثر صعوبة:

    use 5.010;
our $foo = "I'm the scalar";

sub foo { \ "I'm the sub" }
sub baz { 'foo' }

say ${foo};
say ${foo;};
say ${baz;};

intreprets perl التي تدوم say كرمز ويرى أن النتيجة ليست مرجعا ؛ إنها السلسلة البسيطة foo. يرى بيرل أنه ليس مرجعًا ولكنه الآن في سياق dereferencing لذا فهو يقوم مرجعًا رمزيًا (مثل يصف جريج بيكون). نظرًا لأن المراجع الرمزية تعمل مع المتغيرات في جدول الرموز ، فإن ذلك $foo يجب أن يكون متغير الحزمة.

نظرًا لأنه من السهل إفساد هذا الأمر ، strict لديه فحص مفيد لذلك. ومع ذلك ، عند إيقاف تشغيله ، لا تتفاجأ عندما تعضك. قون

من "استخدام المراجع" قسم من وثائق Perlref:

في أي مكان تضع معرفًا (أو سلسلة من المعرفات) كجزء من اسم متغير أو روتين فرعي ، يمكنك استبدال المعرف بكتلة إرجاع مرجع للنوع الصحيح. بمعنى آخر ، يمكن كتابة الأمثلة السابقة مثل هذا:

$bar = ${$scalarref};
push(@{$arrayref}, $filename);
${$arrayref}[0] = "January";
${$hashref}{"KEY"} = "VALUE";
&{$coderef}(1,2,3);
$globref->print("output\n");  # iff IO::Handle is loaded

من المسلم به ، أنه من السخف بعض الشيء استخدام التجعيد في هذه الحالة ، ولكن يمكن أن تحتوي الكتلة على أي تعبير تعسفي ، على وجه الخصوص ، التعبيرات المشتركة:

&{ $dispatch{$index} }(1,2,3);    # call correct routine

بسبب القدرة على حذف التجعيد للحالة البسيطة $$x, ، غالبًا ما يخطئ الناس في مشاهدة رموز إزالة التخلص من المشغلين المناسبة ، ويتساءلون عن أسباقهم. إذا كانوا ، على الرغم من ذلك ، يمكنك استخدام الأقواس بدلاً من الأقواس. هذا ليس هو الحال. النظر في الفرق أدناه ؛ الحالة 0 هي نسخة قصيرة من الحالة 1 ، وليس الحالة 2:

$$hashref{"KEY"}   = "VALUE";     # CASE 0
${$hashref}{"KEY"} = "VALUE";     # CASE 1
${$hashref{"KEY"}} = "VALUE";     # CASE 2
${$hashref->{"KEY"}} = "VALUE";   # CASE 3

الحالة 2 خادعة أيضًا في أنك تصل إلى متغير يسمى %hashref, ، وليس التخلص من خلال $hashref إلى التجزئة ، من المفترض أنه يشير. ستكون هذه الحالة 3.

في وقت لاحق في "المراجع الرمزية":

قلنا أن الإشارات الربيع إلى الوجود عند الضرورة إذا كانت غير محددة ، لكننا لم نقول ما يحدث إذا تم تعريف القيمة المستخدمة كمرجع بالفعل ، ولكنها ليست مرجعًا صعبًا. إذا كنت تستخدمه كمرجع ، فسيتم معاملته كمرجع رمزي. وهذا يعني أن قيمة العددية هي اسم المتغير ، بدلاً من رابط مباشر لقيمة مجهولة (ربما).

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top