تقريبا. حارة: اجتمع اليوم على تويتر مضحك جدا ، للوهلة الأولى ، موضوع. ثم ألقى نظرة فاحصة وأدرك أنه لم يكن مضحكا فقط ، ولكن أيضا مسلية. وبما أنه حدث أن يوم الجمعة هو يوم الجمعة ، فقد قررت أن الأمر يستحق مشاركة النتائج مع رفاقي :)
احفظ البرنامج التالي في /tmp/quine.pl
Illegal division by zero at /tmp/quine.pl line 1.
قم بتشغيله باستخدام الأمر
perl /tmp/quine.pl
وستخرج كودها الخاص.
من السهل جدًا تكوين "حيل الزلازل" في العديد من لغات البرمجة ، حيث يستفز خطأ في بناء الجملة في المصدر محلل لإخراج خطأ يتزامن مع الكود المصدر للبرنامج. لقد
نشرت العديد من هذه الحيل على Twitter ، بما في ذلك ما يلي:
File "quine.py", line 1 File "quine.py", line 1 ^ IndentationError: unexpected indent
لكن الشعير اللؤلؤي في بداية هذا المقال هو خدعة من نوع مختلف تمامًا - فهم البرنامج
بشكل صحيح .
وأنها لا تعمل لفترة طويلة ، حتى يتعثر على خطأ القسمة على الصفر. هذا السطر هو حساس للغاية لتسمية الملفات - على سبيل المثال ، لن يعمل ./quine.pl.
إذن رسالة الخطأ هذه هي في الواقع البرنامج بأكمله؟!
يستخدم هذا البرنامج الكثير من المحلل اللغوي في شريط اللؤلؤ.
يعتمد الرمز / للغاية على سياق التطبيق ويمكن اعتباره رمز تقسيم أو بداية تعبير عادي. وحتى التغييرات الطفيفة في رمز هذا البرنامج تؤدي إلى خطأ في تحليل الانتظام ، وليس لتنفيذ التعليمات البرمجية. في هذه الحالة ، تظهر كلتا الحرفين / في سياق المشغل.
الأجزاء الأخرى غير القاموس من هذا البرنامج هي
1.
، والتي يتم تفسيرها ببساطة كرقم و
.
وهو عامل التسلسل.
ثم ماذا تعني الكلمات؟
يمكن أن تكون الكلمات في Perl أسماء الروتين أو الطرق أو الحزم أو الفئات. أو (في وضع كسول) خطوط بدون فاصل أو ربما حتى شيء آخر نسيت!
يستخدم Perl أيضًا طريقة استدعاء بناء جملة غير عادية تسمى "
بناء جملة كائن غير مباشر " ، والتي تبدو كما يلي:
في معظم الأحيان يمكنك أن ترى كيف
print $filehandle "message"; my $instance = new Class(args);
على الرغم من أن Perl ، يفضل بناء الجملة التالي:
$filehandle->print("message"); my $instance = Class->new(args);
وثائق
perlobj تقول:
يستخدم Perl الأساليب البحثية لتحليل هذا الرمز ، استنادًا إلى أسماء الحزم التي يعرفها ، والوظائف الفرعية الموجودة في الحزمة الحالية ، والكلمات التي واجهتها من قبل ، وتحليل بيانات الإدخال الأخرى. وغني عن القول أن الاستدلال يمكن أن ينتج نتائج غير متوقعة للغاية!
كيف يتم تحليل هذا الرمز؟
بدءا من الجانب الأيمن
pl line 1.
تحليل كمكالمة طريقة
line->pl(1.)
حيث line هو اسم الحزمة (class) ، و pl هي الطريقة.
في الوسط ، يتم تحليل كلمة "at" و "tmp" و "quine" ككلمات بسيطة ، أي الخط. يتم تحليل التعبير على النحو التالي:
(("at" / "tmp") / "quine") . line->pl(1.)
على اليسار نوعان من مكالمات الطريقة غير المباشرة المطوية ،
division->Illegal(zero->by( ... ))
التعبير الداخلي المنفذ أولاً:
"at" / "tmp"
وهذا يتسبب على الفور الانقسام من قبل الصفر استثناء.