حلقة اقرأ-قيِّم-اطبع أو REPL -اختصارًا للعبارة Read Evaluate Print Loop- هي صدفة تفاعلية interactive shell تعالج تعابير جافاسكربت البرمجية ضمن بيئة نود، حيث تقرأ تلك الصدفة الشيفرات التي يدخلها المستخدم وتُصرّفها ثم تُقيّم نتيجتها وتطبع تلك النتيجة للمستخدم على الشاشة آنيًا، وتكرر ذلك لحين خروج المستخدم من تلك الصدفة، وتأتي REPL مثبتة مسبقًا مع نود، وتسمح لنا باختبار واستكشاف شيفرات جافاسكربت داخل بيئة نود بسرعة ودون الحاجة لحفظها أولًا داخل ملف ثم تنفيذها، وسيلزمك في هذا الفصل للمتابعة معرفة بأساسيات لغة جافاسكريبت، ولبيئة نود مُثبتة على الجهاز.
الدخول والخروج من الوضع REPL
بعد تثبيت نود على جهازك، سيكون وضع حلقة REPL متاحًا للاستخدام مباشرةً، وللدخول إليه ننفذ الأمر node
فقط ضمن سطر الأوامر كالتالي:
node
سيدخلنا ذلك في وضع التفاعلي:
>
حيث يشير الرمز >
في بداية السطر لإمكانية إدخالنا شيفرات جافاسكربت لتُعالج، ويمكننا تجربة ذلك بجمع عددين كالتالي:
> 2 + 2
نضغط زر الإدخال ENTER لتُقيّم صدفة نود ذلك التعبير البرمجي وتطبع نتيجته مباشرةً:
4
للخروج من ذلك الوضع يمكننا إما كتابة الأمر .exit
أو الضغط من لوحة المفاتيح على الاختصار CTRL+D، أو الضغط مرتين على الاختصار CTRL+C، للخروج والعودة إلى سطر الأوامر.
والآن بعد أن علمنا طريقة الدخول والخروج من الوضع REPL، سنتعلم طريقة تنفيذ بعض شيفرات جافاسكربت البسيطة ضمنه.
تنفيذ شيفرة جافاسكربت ضمن REPL
يمنحنا الوضع REPL التفاعلي طريقة سريعة لاختبار شيفرات جافاسكربت فورًا، ودون الحاجة لإنشاء ملف لها أولًا، حيث يمكننا تنفيذ أي تعبير برمجي سليم يمكن تنفيذه عادةً ضمن بيئة نود، إذ اختبرنا في المثال السابق جمع عددين، ولنختبر الآن تنفيذ قسمة عددين.
ندخل أولًا إلى الوضع REPL كما تعلمنا:
node
ونُدخل التعبير البرمجي ونضغط زر الإدخال لتنفيذه:
> 10 / 5
نحصل على الخرج التالي وهو ناتج العملية السابقة:
2
يمكن أيضًا مثلًا تنفيذ العمليات على السلاسل النصية، ولنختبر ذلك بتنفيذ ضم سلسلتين نصيتين كالتالي:
> "Hello " + "World"
وسيظهر لنا نتيجة ضم السلسلتين:
'Hello World'
نلاحظ ظهور النص في النتيجة محاطًا بعلامات اقتباس مفردة بدلًا من علامات الاقتباس المزدوجة، ففي جافاسكربت لا يؤثر نوع علامات الاقتباس على قيمة السلسلة النصية، لذا يستخدم الوضع REPL عند إظهار نتيجة فيها سلسلة نصية علامات الاقتباس المفردة دومًا.
استدعاء التوابع
يستخدم التابع العام console.log
أو توابع طباعة الرسائل المشابهة له كثيرًا في بيئة نود، حيث يمكننا داخل REPL استدعاء التوابع أيضًا، فلنجرب مثلًا أمر طباعة رسالة كالتالي:
> console.log("Hi")
سيُستدعى التابع وتظهر نتيجة التنفيذ التالية:
Hi undefined
يمثل السطر الأول نتيجة استدعاء التابع console.log
، والذي يطبع الرسالة إلى المجرى stdout
والذي يمثل الشاشة، ولأن الوظيفة طباعة وليس إعادة عبر التعبير return
كنتيجة لتنفيذ التابع، نلاحظ عدم وجود علامات الاقتباس حولها، بينما السطر الثاني يعرض القيمة undefined
وهي النتيجة التي أعادها التابع بعد انتهاء تنفيذه.
تعريف متغيرات
تُستخدم المتغيرات variables أيضًا بكثرة خلال كتابتنا للشيفرات البرمجية ولا نكتفي بالتعامل مع القيم مباشرة، لذا يتيح لنا REPL إمكانية تعريف المتغيرات تمامًا كما لو كنا نكتبها ضمن ملفات جافاسكريبت، ويمكننا اختبار ذلك كالتالي:
> let age = 30
تظهر لنا النتيجة التالية بعد ضغط زر الإدخال:
undefined
كما لاحظنا سابقًا عند استدعاء التابع console.log
كانت القيمة التي يعيدها هي undefined
، وهنا أيضًا جرى تعريف المتغير age
ولم نُعد أي قيمة، وسيكون ذلك المتغير متاحًا حتى الانتهاء والخروج من جلسة REPL الحالية، ولاختبار ذلك نستخدم المتغير age
ضمن عملية ما ولتكن ضربه بعدد كالتالي:
> age * 2
تظهر لنا نتيجة العملية بعد الضغط على زر الإدخال:
60
نلاحظ أن REPL يعيد ويطبع لنا نتيجة التعبير البرمجي فورًا، لذا لا نحتاج لاستخدام التابع console.log
في كل مرة نريد طباعة قيمة على الشاشة، حيث سيطبع تلقائيًا أي قيمة يعيدها الأمر المُدخل.
إدخال الشيفرات متعددة الأسطر
يدعم REPL أيضًا إدخال الشيفرات متعددة السطر، ولنختبر ذلك ننشئ تابعًا يضيف القيمة 3 إلى العدد المُمرر له، ونبدأ تعريفه بإدخال أول سطر منه كالتالي:
const add3 = (num) => {
وبعد الضغط على زر الإدخال ستلاحظ تغير الرمز <
في أول السطر إلى رمز النُقط الثلاث:
...
يلاحظ REPL وجود قوس معقوص }
في نهاية الأمر المدخل، ما يشير إلى وجود بقية له، فيتم إضافة هامش من النقط وانتظار إدخالنا لباقي الأمر، وذلك لتسهيل القراءة حيث يضيف REPL ثلاث نقط ومسافة في السطر التالي، ليبدو أن الشيفرة يسبقها مسافة بادئة، ونكمل إدخال سطر جسم الدالة، ثم سطر قوس الإغلاق لإنهاء تعريف التابع، ونضغط زر الإدخال بعد كل سطر منها:
return num + 3; }
وبعد إدخال آخر سطر الحاوي على قوس الإغلاق للتابع، ستظهر لنا القيمة undefined
، والتي تدل على القيمة المُرجعة من أمر إسناد الدالة إلى الثابت، ونلاحظ عودة الرمز في بداية السطر إلى رمز إدخال الأوامر >
بدلًا من النقط ...
، وتظهر لنا قيمة الأمر المُدخل:
undefined >
يمكننا الآن استخدام الدالة التي عرفناها add3()
بتمرير قيمة لها كالتالي:
> add3(10)
ويظهر لنا نتيجة الإضافة التي تعيدها الدالة كالتالي:
13
يمكن الاستفادة من REPL في تجربة شيفرات جافاسكربت واللعب بها قبل إضافتها إلى النظام أو المشروع الذي نعمل عليه، حيث يوفر REPL اختصارات تساعدنا خلال تلك العملية سنتعرف عليها في الفقرة التالية.
التعرف على الاختصارات في REPL
يوفر REPL عدة اختصارات تسهل عملية ادخال الشيفرات وتوفر الوقت، فمثلًا يحفظ REPL -كما معظم الصدفات- سجلًا بالأوامر المدخلة السابقًا لنتمكن من الرجوع إليها بدلًا من إعادة إدخالها يدويًا مرة أخرى.
جرب مثلًا كتابة القيمة النصية الطويلة التالية:
> "The answer to life the universe and everything is 32"
يظهر لنا النص نفسه كنتيجة لذلك الأمر:
'The answer to life the universe and everything is 32'
الآن إذا أردنا إدخال النص السابق نفسه، لكن مع اختلاف وهو تبديل العدد 32 إلى 42، فيمكننا ذلك عبر الضغط على مفتاح السهم العلوي UP من لوحة المفاتيح للوصول إلى آخر قيمة أدخلناها:
> "The answer to life the universe and everything is 32"
بعدها يمكننا تحريك المؤشر داخل النص وإزالة العدد 3
وتبديله إلى العدد 4
ونضغط زر الإدخال ENTER مجددًا:
'The answer to life the universe and everything is 42'
يمكن بالضغط المستمر على السهم العلوي UP الرجوع في سجل تاريخ الأوامر المدخلة سابقًا واحد تلو الآخر، وبالمقابل يمكن الضغط على مفتاح السهم السفلي DOWN للتقدم إلى الأمام في سجل تاريخ الأوامر، ويمكن بعد الانتهاء من تفحص سجلات الأوامر المُخزنة الضغط مرارًا على مفتاح السهم السفلي DOWN إلى حين العودة إلى سطر الإدخال الفارغ لكتابة أمر جديد، ويمكن الوصول إلى قيمة آخر نتيجة عبر محرف الشرطة سفلية _
، ولاختبار ذلك نكتب الرمز _
ثم نضغط على زر الإدخال:
> _
سيظهر لنا السلسلة النصية التي أدخلناها مؤخرًا:
'The answer to life the universe and everything is 42'
يتيح REPL أيضًا ميزة الإكمال التلقائي للتوابع والمتغيرات والكلمات المفتاحية أثناء كتابة الشيفرة، فمثلًا إذا أردنا استخدام التابع العام Math.sqrt
لحساب الجذر التربيعي لعدد يمكننا فقط كتابة الأحرف الأولى لذلك الاستدعاء كالتالي مثلًا:
> Math.sq
ثم الضغط على زر الجدولة تاب TAB ليكمل لنا REPL كتابة باقي اسم التابع بشكل صحيح كالتالي:
> Math.sqrt
وعندما يكون هناك أكثر من طريقة لإكمال الأمر، سيظهر لنا جميع الاحتمالات الممكنة، فمثلًا إذا حاولنا استدعاء تابع ما من الصنف Math
كالتالي:
> Math.
بالضغط على زر الجدولة مرتين سيظهر لنا جميع الاحتمالات الممكنة للإكمال التلقائي لذلك الأمر:
> Math. Math.__defineGetter__ Math.__defineSetter__ Math.__lookupGetter__ Math.__lookupSetter__ Math.__proto__ Math.constructor Math.hasOwnProperty Math.isPrototypeOf Math.propertyIsEnumerable Math.toLocaleString Math.toString Math.valueOf Math.E Math.LN10 Math.LN2 Math.LOG10E Math.LOG2E Math.PI Math.SQRT1_2 Math.SQRT2 Math.abs Math.acos Math.acosh Math.asin Math.asinh Math.atan Math.atan2 Math.atanh Math.cbrt Math.ceil Math.clz32 Math.cos Math.cosh Math.exp Math.expm1 Math.floor Math.fround Math.hypot Math.imul Math.log Math.log10 Math.log1p Math.log2 Math.max Math.min Math.pow Math.random Math.round Math.sign Math.sin Math.sinh Math.sqrt Math.tan Math.tanh Math.trunc
بحيث تظهر النتيجة السابقة بتنسيق يناسب حجم نافذة سطر الأوامر من ناحية عدد الأعمدة والأسطر لتلك الاحتمالات، وتمثل تلك الاحتمالات جميع التوابع أو الخاصيات المتاحة ضمن الوحدة Math
.
يمكننا في أي وقت الحصول على سطر فارغ جديد لإدخال الأوامر بالضغط على الاختصار CTRL+C، وذلك دون تنفيذ الأمر الجاري كتابته في السطر الحالي.
إن معرفة الاختصارات السابقة يزيد من كفاءة وسرعة كتابة الشيفرات داخل REPL، كما يحتوي أيضًا على أوامر تزيد الإنتاجية سنتعرف عليها في الفقرة التالية.
أوامر REPL
يوفر REPL كلمات مفتاحية خاصة تساعدنا في التحكم به، ويبدأ كل من تلك الأوامر برمز النقطة .
سنتعرف عليها.
الأمر .help
لعرض كل الأوامر المتاحة ضمن REPL يمكننا استخدام الأمر .help
كالتالي:
> .help
سيظهر لنا جميع الأوامر المتاحة الخاصة بالوضع REPL وهي قليلة لكن مفيدة:
.break Sometimes you get stuck, this gets you out .clear Alias for .break .editor Enter editor mode .exit Exit the repl .help Print this help message .load Load JS from a file into the REPL session .save Save all evaluated commands in this REPL session to a file Press ^C to abort current expression, ^D to exit the repl
يفيد تنفيذ هذا الأمر في حال نسيان الأوامر المتاحة أو وظيفة كل منها.
الأمران .break و .clear
تظهر فائدة الأمران .break
و .clear
خلال كتابتنا الشيفرة متعددة الأسطر إذ تساعد على الخروج من ذلك الوضع، ولنختبر ذلك بكتابة أول سطر من حلقة التكرار for
كالتالي:
for (let i = 0; i < 100000000; i++) {
بدلًا من إكمال كتابة أسطر ذلك الأمر يمكننا تنفيذ الأمر .break
أو الأمر .clear
للخروج:
.break
سيظهر لنا الرمز >
من جديد، ونلاحظ أن REPL استجاب لهذا الأمر وانتقل إلى سطر جديد فارغ دون تنفيذ الشيفرة التي كنا نحاول إدخالها تمامًا كما لو أننا ضغطنا على الاختصار CTRL+C.
الأمران .save و .load
يُمكّننا الأمر .save
من حفظ كافة الشيفرات التي أدخلناها منذ بداية جلسة REPL الحالية إلى ملف جافاسكربت، بالمقابل يُمكّننا الأمر .load
من تنفيذ شيفرات جافاسكربت من ملف خارجي داخل REPL، وذلك بدلًا من كتابة تلك الشيفرات يدويًا، و لاختبار ذلك نخرج أولًا من الجلسة الحالية إما بتنفيذ الأمر .exit
أو باستخدام الاختصار CTRL+D، ونبدأ جلسة REPL جديدة بتنفيذ الأمر node
، حيث ستحفظ كل الشيفرات التي سنقوم بكتابتها منذ الآن داخل الملف عند استخدامنا لأمر الحفظ .save
لاحقًا.
نُعرّف مصفوفة من الفواكه:
> fruits = ['banana', 'apple', 'mango']
في سطر النتيجة سيظهر:
[ 'banana', 'apple', 'mango' ]
نحفظ الآن المتغير السابق إلى ملف جديد بالاسم fruits.js
كالتالي:
> .save fruits.js
ستظهر رسالة تؤكد حفظ الملف بنجاح:
Session saved to: fruits.js
مكان حفظ ذلك الملف هو نفس مسار المجلد الذي بدأنا منه جلسة REPL من سطر الأوامر، فمثلًا لو كان مسار سطر الأوامر عندها هو مجلد المنزل home للمستخدم، فسيُحفَظ الملف داخل ذلك المجلد.
والآن نخرج من الجلسة الحالية ونبدأ جلسة جديدة بتنفيذ الأمر node
مرة أخرى، ونُحمِّل ملف fruits.js
الذي حفظناه سابقًا بتنفيذ الأمر .load
كالتالي:
> .load fruits.js
ليظهر لنا:
fruits = ['banana', 'apple', 'mango'] [ 'banana', 'apple', 'mango' ]
قرأ الأمر .load
كل سطر داخل ذلك الملف ونفذه تمامًا كطريقة عمل مفسر جافاسكربت، حيث أصبح بإمكاننا الآن استخدام المتغير fruits
كما لو أننا أدخلناه سابقًا يدويًا ضمن الجلسة الحالية، ولنختبر ذلك ونحاول الوصول لأول عنصر من تلك المصفوفة:
> fruits[1]
نحصل على الخرج المتوقع:
'apple'
ويمكن تحميل أي ملف جافاسكربت باستخدام الأمر .load
مهما كان، وليس فقط الملفات التي نحفظها، لنختبر ذلك بكتابة ملف جافاسكربت بسيط نُنشئ ملفًا جديدًا ونفتحه باستخدام محرر النصوص:
nano peanuts.js
ثم ندخل ضمنه الشيفرة التالية ونحفظ التغييرات:
console.log('I love peanuts!');
نبدأ جلسة REPL جديدة من نفس مسار المجلد الحاوي على ملف جافاسكربت peanuts.js
الجديد بتنفيذ الأمر node
، ونُحمِّل الملف إلى الجلسة الحالية بتنفيذ التالي:
> .load peanuts.js
سيُنفذ الأمر .load
التعبير البرمجي console
ضمن ذلك الملف ويُظهر الخرج:
console.log('I love peanuts!'); I love peanuts! undefined >
تظهر فائدة كلا الأمرين .save
و .load
عند كتابة الكثير من الشيفرات داخل REPL أو عندما نريد حفظ ما أدخلناه خلال الجلسة الحالية ومشاركته ضمن ملف جافاسكربت.
ختامًا
تتيح لنا بيئة REPL التفاعلية تنفيذ شيفرات جافاسكربت دون الحاجة لإنشاء ملف لها أولًا، كتنفيذ التعابير البرمجية واستدعاء التوابع وتعريف المتغيرات، وتوفر العديد من الاختصارات والأوامر والمزايا الداعمة لتلك العملية، كتنسيق النص تلقائيًا للأوامر متعددة الأسطر، وسجل بتاريخ الأوامر المُدخلة، إلى أوامر المسح أو الحفظ والتحميل، يضيف لك تعلم REPL مهارة قد تحتاج إليها خلال عملك في وقت ما.
ترجمة -وبتصرف- للمقال How To Use the Node.js REPL لصاحبه Stack Abuse.
تعليقات
إرسال تعليق