Hello our valued visitor, We present you the best web solutions and high quality graphic designs with a lot of features. just login to your account and enjoy ...

<none>

Hello our valued visitor, We present you the best web solutions and high quality graphic designs with a lot of features. just login to your account and enjoy ...

CAPTCHA
This question is for testing whether or not you are a human visitor and to prevent automated spam submissions.
7 + 2 =
Solve this simple math problem and enter the result. E.g. for 1+3, enter 4.

أخبار تكنلوجيا

رقم الخبر عنوان الخبر التفاصيل
28,744 «غالاكسي واتش 3» أحدث إبداعات «سامسونغ» كشفت «سامسونغ» عن ساعتها الجديدة «غالاكسي واتش 3» (Galaxy Watch) قبل أسبوعين، تزامناً مع حدث الإعلان عن هاتفها الرائد «غالاكسي نوت 20 ألترا». وتقول الشركة إن ساعتها الجديدة تعدّ رفيقاً مثالياً للمستخدم طوال اليوم، حيث يمكنها مساعدته في زيادة الإنتاجية والحفاظ على الصحة وتحقيق أهداف اللياقة البدنية، كما تؤكد أن ساعة «واتش 3» تجمع بين الإتقان في التصنيع والتصميم المريح الذي يجعلها مناسبة للارتداء طوال الليل والنهار.
وأصبحت الساعة متوفرة في الأسواق العربية منذ يوم السبت الماضي، لذا قامت «الشرق الأوسط» باختبارها.
التصميم والشاشة
28,743 متعة اللعب الجماعي في «فول غايز: ألتيميت نوكآوت» طرحت شركة «ميدياتونيك» Mediatonic لعبة «فول غايز: ألتيميت نوكآوت» Fall Guys: Ultimate Knockout على الكومبيوتر الشخصي و«بلايستيشن 4» التي تقدم نمط لعب جماعي ممتع لجميع أفراد العائلة. وتستمد اللعبة آلية اللعب من البرامج التلفزيونية التنافسية الترفيهية؛ مثل «الحصن» Takeshi’s Castle وIt’s a Knockout وTotal Wipeout، والتي يجب فيها على اللاعبين تجاوز العقبات الآلية التي تحاول دحرهم عن التقدم والوصول إلى خط النهاية بطرق طريفة. ويستطيع 60 لاعبا التنافس عبر الإنترنت في هذه اللعبة باستخدام شخصيات طريفة والتنقل في عالم ثلاثي الأبعاد والقفز والغوص والتمسك بالعناصر المختلفة.
28,742 لينوفو تكشف عن لابتوب الألعاب Legion Slim 7i بسعر 1,330 دولار أمريكي

كشفت شركة لينوفو عن لابتوب الألعاب الجديد Legion Slim 7i حيث يأتي بهيكل هو الأنحف على الإطلاق على مستوى سلسلة حواسيب الألعاب المحمولة من الشركة.

تفاصيل العتاد والسعر

Legion Slim 7i يأتي بمعالج إنتل الراقي من الجيل العاشر Core i9 HK متوافق مع وحدة تخزين SSD بسعة قصوى 2 تيرا بايت وذاكرة وصول عشوائي ” رام ” تصل بحد أقصى 32 جيجا بايت.

شاشة اللابتوب تأتي بقياس 15.6 بوصة لكن بخيارين الأول بدعم تقنية عرض 4K مع معدل تحديث 60 هيرتز وقوة سطوه 600 نت والثاني FHD مع معدل تحديث 144 هيرتز وكلا الشاستين تدعمان Dolby Vision.

ويبلغ وزن Slim 7i أربعة باوندات أي 1.8 كيلو جرام في حين أنه مدعم بنظام  رسومات إنفيديا المتطور ” Optimus ” بخيارات تصل بأقصاها إلى دعم معالج رسومات GeForce RTX 2060 مع تقنية Max-Q.

وبفضل تقنية معالجات إنفيديا المتطورة يمكن للابتوب ألعاب لينوفو التبديل بين وضع استهلاك الطاقة الأدنى والأقصى في بضع لحظات والدفع نحو أداء عالي لبطاقة الرسومات عند الحاجة، مما يساعد بالحفاظ وتحسين أداء البطارية والوصول لمعدل إطارات أعلى أيضاً.

وللتوضيح أكثر فإن البنية القائمة عليها هذه التقنية ” Max-Q Dynamic Boost  ” تسمح للنظام بنقل الطاقة من المعالج المركزي إلى معالج الرسومات أثناء النشاطات والعبء الثقيل كالألعاب مثلاً مما يؤدي إلى زيادة في سرعة الأداء بنسبة تصل 10%.

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

ويبدأ سعر اللابتوب  من 1,329 دولار أمريكي بالمواصفات المعيارية ويزداد وفقاً لرغبة المستخدم وتخصيصاته، بينما سيكون متوفراً في السوق العالمي مع دخول أكتوبر المقبل.

المصدر

Engadget

التدوينة لينوفو تكشف عن لابتوب الألعاب Legion Slim 7i بسعر 1,330 دولار أمريكي ظهرت أولاً على عالم التقنية.

28,741 كوالكوم تكشف عن معالج الهواتف المتوسطة الجديد سنابدراجون 732G

كشفت شركة كوالكوم اليوم عن معالج سنابدراجون 732G الجديد والذي يستهدف بطبيعة الحال الهواتف المتوسطة ليكون النسخة المحدثة من 730G الذي أطلقته الشركة العام الماضي.

النسخة الجديدة من المعالج المتوسط جاءت بتحسينات تشمل الرفع من كفاءة محرك الذكاء الاصطناعي وكذلك سرعة التردد والتوافق مع بطاقات الرسوميات في الهواتف المتوسطة.

وعلى غرار تدعيم شاومي لهاتفها Poco X2 فبراير الماضي بمعالج سنابدراجون 730G أعلنت الشركة اليوم أن نسختها القادمة من الهاتف المنافس وصاحب الشعبية الكبيرة ستأتي بمعالج 732G أيضاً لكنها لم تكشف أي تفاصيل حول السعر وباقي المواصفات.

وصرح Sam Jiang وهو الرئيس العالمي للعلامة التجارية المنفصلة Poco قائلاً ” إننا ننثق أن الهاتف سيحقق رقماً جديداً على مقياس كفاءة الهواتف المتوسطة معيداً تعريف العلاقة بين السعر والقدرات بشكل كامل”.

وعند مقارنة الأداء بين المعالج الحالي وسابقه نرى أن تردد 732G يصل 2.3 جيجا هيرتز بينما 730G بتردد 2.2 جيجا هيرتز كما أن النسخة الأخيرة تأتي بتوافق أكبر مع معالج الرسومات Adreno 618؛ فيما تكمن الإضافة الكبيرة في تدعيم 732 بقدرات طالمات اقتصرت على المعالجات الراقية التي تظهر فارقاً في ألعاب HDR وإخراج الألوان.

ويجدر بالذكر أن عقل الذكاء الاصطناعي في معالج سنابدراجون 732G جاء مع تحسينات تضمن ضعف أداء نسخته السابقة حسب ما صرحت الشركة. وبخصوص الهواتف التي سَتدعم به مستقبلاً لا يبدو الأمر واضحاً حيث لم تكشف الشركة الأمريكية تفاصيل بهذا الخصوص عدا ما جاء على لسان Poco شاومي.

المصدر

Engadget

التدوينة كوالكوم تكشف عن معالج الهواتف المتوسطة الجديد سنابدراجون 732G ظهرت أولاً على عالم التقنية.

28,740 تطبيق Tap Tap يأتي بميزة Back Tap في iOS 14 على أي هاتف أندرويد

لربما لا تعلم بأن جوجل أوجدت ميزة Back Tap “النقر المزدوج خلف الهاتف” من على الإصدار التجريبي أندرويد 11، والتي تُنفّذ إجراءات مثل تشغيل مساعد جوجل وكاميرا جوجل والتحكم في تشغيل الوسائط، ولكن تم إزالتها لاحقًا، بعد ذلك، قررت آبل إضافة هذه الميزة لنظامها iOS 14 والتي حملت اسمين Back Tap و Rear Touch.

ومع ذلك، قرر أحد المُطورين إعادة الميزة وجعلها متاحة تقريبًا على أي هاتف يعمل بإصدار أندرويد، وذلك عبر تطبيقه الذي حمل اسم Tap Tap، المتاح للعمل مع أندرويد 7.0 فأحدث، حيث يستخدم هذا التطبيق نفس أنماط التعلم الآلي للتعرف على النقرات المزدوجة على الجزء الخلفي من أجهزة جوجل بيكسل.

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

أخيرًا، تطبيق Tap Tap هو مفتوح المصدر ويمكنك متابعة تطويره على GitHub، وفي الوقت الحالي هو غير متاح على متجر جوجل بلاي كونه في مراحل التطوير الأولى، على أن تتمكن من تجربته عبر تحميل ملفه الـ APK من هنا.

التدوينة تطبيق Tap Tap يأتي بميزة Back Tap في iOS 14 على أي هاتف أندرويد ظهرت أولاً على عالم التقنية.

28,739 لينوفو تطلق اللوحي Tab P11 Pro بقياس كبير مخصص للأعمال

أعلنت شركة لينوفو اليوم عن مجموعة من الأجهزة المختلفة، من بينها لوحي Tab P11 Pro بمواصفات عالية نسبياً وقياس كبير يمثل عودة الشركة لاختبار قدرتها على المنافسة في هذا المجال أمام آبل ومايكروسوفت.

اللوحي Tab P11 Pro يأتي بشاشة 11.5 بوصة بدقة 1600*2560 بكسل تدعم ألوان HDR10 نوعها OLED وتقنية Dolby Vision سطوعها 500 nits. بالرغم من أن اللوحي مخصص للأعمال والإنتاجية، إلا أنه يعمل بمعالج سناب دراغون 730G المخصص لأجهزة الألعاب ونفس الموجود في هاتف Pixel 4A من جوجل.

لا يقدم اللوحي أداء قوي وكبير مثل ما رأيناه في اللوحي Tab S7 من سامسونج بسبب اختياره لمعالج قديم من إصدار العام الماضي. لذا سيعطيك أداء جيد ما لم تستخدمه في الألعاب القوية.

ويدعم اللوحي اكسسوارات خارجية مثل لوحة مفاتيح وقلم ويتميز بوجود سماعات JBL مع دعم صوت محيطي وخوارزميات ذكية للتحقق من الموقع وتعديل الصوت بناءً عليه.

ويتميز بكاميرا قادرة على التعرف على الوجه مع حساساتها لفتح اللوحي ببصمة الوجه وتمويه الخلفية في مكالمات الفيديو.

سيتوفر لوحي لينوفو Tab P11 Pro في نوفمبر القادم بسعر يبدأ من 499 دولار.

المصدر:

9to5Google

التدوينة لينوفو تطلق اللوحي Tab P11 Pro بقياس كبير مخصص للأعمال ظهرت أولاً على عالم التقنية.

28,738 جوجل تطلق “مساحة الأطفال” Kids Space على لوحيات أندرويد

أعلنت شركة جوجل عن “وضع” جديد مخصص للأطفال تحت اسم مساحة الأطفال Kids Space وهو بيئة استخدام ستدعم لوحيات أندرويد ، والآن متوفرة على أحدث لوحي من لينوفو M10 HD Gen 2.

هناك العديد من اللوحيات المصنعة خصيصاً للأطفال بتصاميم تتحمل الصدمات وتحمل ألوان ممتعة، لكن جوجل تريح أن تجعل أي لوحي مناسباً للأطفال من خلال التعديلات البرمجية.

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

ويمكن اعتبار أن Kids Space نوع خاص من ملفات المستخدمين لأن أندرويد يدعم تعدد المستخدمين.

يوفر Kids Space مكتبة مخصصة للأطفال تحوي تطبيقات وألعاب وفيديوهات وكتب كلها تم اختيارها لتناسب الأطفال لاسيما الذين أعمارهم تحت 9 سنوات.

واستخدمت الألوان المفرحة والمتنوعة في الواجهات لتسهيل تصفح الأطفال لها، كما يمكن فصل المحتوى حسب الموضوع مثل محتوى خاص بالسيارات وآخر بالحيوانات وحتى المساعدة بالدراسة.

وهناك تسميات للتبويبات مثل “Make” ،“Play”، “Read”، و “Watch” تشير إلى نوع المحتوى المقدم فيها كالكتب الإلكترونية والفيديوهات والألعاب. كما يمكن للأطفال إنشاء أفاتار خاص بهم يعبر عن شخصيتهم.

يذكر أن جوجل لديها تطبيق الرقابة العائلية Family Link والذي يعمل على كل أجهزة أندرويد ويتيح للآباء التحكم بهواتف أولادهم والرقابة على المحتوى وحساباتهم وحتى تعيين مدة استخدام الجهاز والتطبيقات المسموحة والإغلاق عن بعد.

تعد جوجل بإتاحة Kids Space على المزيد من الحواسب اللوحية لاحقاً تباعاً.

المصدر:

The Verge

التدوينة جوجل تطلق “مساحة الأطفال” Kids Space على لوحيات أندرويد ظهرت أولاً على عالم التقنية.

28,736 الدرس 41: المعالجة الأولية Preprocessor في Cpp

معالج C الأولي هو محلّل/مبدّل نصوص يُشغَّل قبل التصريف الفعلي للشيفرة، ويُستخدم لتوسيع وتيسير استخدام لغة C (وكذلك C++‎ لاحقًا)، ويمكن استخدامه من أجل:

  1. تضمين ملفّات أخرى باستخدام ‎#include‎.
  2. تعريف شيفرة جامعة (macro)، لاستبدال النص باستخدام ‎#define‎
  3. التصريف الشرطي باستخدام ‎#if‎ ‎#ifdef‎.
  4. توجيه شيفرة معيّنة لمنصّة أو مٌصرّف معيّن (امتداد للتصريف الشرطي)
قيود التضمين

قد تُضمّن ترويسة من قبل ترويسة أخرى. لذلك، فالملفّات المصدرية التي تتضمّن عدّة ترويسات قد تتضمّن بعض الترويسات أكثر من مرّة بشكل غير مباشر. وإن كانت إحدى الترويسات المُضمّنة أكثر من مرّة تحتوي على تعريفات، فإنّّ المٌصرّف -بعد المعالجة الأوّلية- سيرصد انتهاكًا لقاعدة التعريف الواحد (الفقرة 3.2 من المعيار C++‎ لعام 2003) ومن ثم يحدث خطأ في التصريف.

يمكن منع التضمين المتعدّد باستخدام دروع التضمين "include guards"، وتُعرَف أيضًا بدروع الترويسة، أو دروع الشيفرة الجامعة (macro guards). وتُنفَّذ هذه الدروع باستخدام مُوجِّهات المُعالج الأوّلي ‎#define‎ و ‎#ifndef‎ و ‎#endif‎. انظر:

// Foo.h #ifndef FOO_H_INCLUDED #define FOO_H_INCLUDED class Foo // تعريف صنف { }; #endif

الميزة الرئيسية لاستخدام دروع التضمين أنّها تعمل مع جميع المُصرّفات المتوافقة مع المعايير والمُعالجات الأوّلية.

من ناحية أخرى، قد تخلق دروع التضمين بعض المشاكل للمطورين، لوجوب التأكد أنّ وحدات الشيفرة الجامعة فريدة في جميع الترويسات المُستخدمة في المشروع، خاصة إذا استَخدَمت ترويستين (أو أكثر) ‎FOO_H_INCLUDED‎ كدروع تضمين، فإنّّ أولى تلك الترويستين المُضمّنتين في وحدة تصريف ستمنع تضمين الترويسات الأخرى. هذه التحديات تظهر خاصّة إذا كان المشروع يستخدم مكتبات الطرف الثالث، والتي تحتوي على ترويسات تشترك في استخدام دروع تضمين.

من الضروري أيضًا التأكد من أنّ وحدات الشيفرة الجامعة المستخدمة في دروع التضمين لا تتعارض مع وحدات الشيفرة الجامعة الأخرى المُعرَّفة في الترويسة.

معظم تنفيذات C++‎ تدعم المُوجِّه ‎#pragma once‎ الذي يحرص على عدم تضمين الملفّ إلّا مرّة واحدة فقط في كل عمليّة تصريف، وهو مُوجِّه قياسي، لكنه ليس جزءًا من أيّ معيار من معايير ISO C++‎. مثلا:

// Foo.h #pragma once class Foo {};

في الشيفرة السابقة: بينما تُجنِّب ‎#pragma once‎ بعض المشاكل المرتبطة بدروع التضمين، فإنّ ‎#pragma‎ -حسب المعيار- هي بطبيعتها خُطَّاف خاص بالمٌصرّف (compiler-specific hook)، وستُتجاهل بصمت من قبل المٌصرّفات التي لا تدعمها. حمل المشاريع (أي porting) التي تستخدم ‎#pragma once‎ إلى المٌصرّفات التي لا تدعمها ليس بالأمر الهيّن.

هناك عدد من إرشادات التشفير ومعايير C++‎ التي توصي بعدم استخدام أيّ مُعالج أوّلي إلا من أجل تضمين ملفات الترويسة ‎#include‎، أو لأجل وضع دروع التضمين في الترويسات.

المنطق الشرطي والتعامل مع تعدد المنصات

باختصار، يتمحور منطق المعالجة الأوّلية الشرطية حول التحكم في جعل منطق الشيفرة متاحًا للتصريف أو غير متاح باستخدام تعاريف الشيفرات الجامعة.

هذه ثلاث حالات استخدام أساسية:

  • عدّة إصدارات من تطبيق (مثلًا: إصدار للتنقيح، وآخر للإطلاق، وآخر للاختبار، وآخر للتحسين)
  • التصريفات متعدّدة المنصات (cross-platform compiles) - نفس الشيفرة المصدرية، مع تصريفات لعدة منصات
  • استخدام نفس الشيفرة لأجل عدة إصدارات من التطبيق (مثلًا: إصدار Basic و Premium و Pro من البرنامج) - مع ميزات مختلفة قليلاً.

مثال أ: مقاربة متعددة المنصات لإزالة الملفّات:

#ifdef _WIN32 #include <windows.h > // وبقية ملفات نظام ويندوز #endif #include <cstdio> bool remove_file(const std::string &path) { #ifdef _WIN32 return DeleteFile(path.c_str()); #elif defined(_POSIX_VERSION) || defined(__unix__) return (0 == remove(path.c_str())); #elif defined(__APPLE__) //TODO: دالة مُخصّصة مع نافذة حوار للترخيص NSAPI التحقق مما إذا كان لـ return (0 == remove(path.c_str())); #else #error "This platform is not supported" #endif }

مثال ب: إتاحة إمكانية التسجيل الإضافي لأجل التنقيح:

void s_PrintAppStateOnUserPrompt() { std::cout << "--------BEGIN-DUMP---------------\n" << AppState::Instance()->Settings().ToString() << "\n" #if ( 1 == TESTING_MODE ) // الخصوصية: لا نريد المعلومات الشخصية للمستخدم إلا عند الاختبار << ListToString(AppState::UndoStack()->GetActionNames()) << AppState::Instance()->CrntDocument().Name() << AppState::Instance()->CrntDocument().SignatureSHA() << "\n" #endif << "--------END-DUMP---------------\n" }

مثال ج: توفير ميزة مدفوعة (premium feature) في منتج منفصل (ملاحظة: هذا المثال توضيحي. من الأفضل إتاحة الميزة دون الحاجة إلى إعادة تثبيت التطبيق)

void MainWindow::OnProcessButtonClick() { #ifndef _PREMIUM CreatePurchaseDialog("Buy App Premium", "This feature is available for our App Premium users. Click the Buy button to purchase the Premium version at our website"); return; #endif //… الميزات الفعلية هنا }

بعض الطرق الشائعة:

  • تعريف رمز في وقت الاستدعاء (invocation): يمكن استدعاء المُعالج الأوّلي برموز مسبقة (مع تهيئة اختيارية). على سبيل المثال (‎gcc -E‎ يعمل فقط على المُعالج الأوّلي):
gcc - E - DOPTIMISE_FOR_OS_X - DTESTING_MODE = 1 Sample.cpp

يُعالَج Sample.cpp كما لو أنّ ‎#define OPTIMISE_FOR_OS_X‎ و ‎#define TESTING_MODE 1‎ مُضافان إلى أعلى Sample.cpp.

  • التأكد أن شيفرة جامعة ما معرَّفة: إذا لم تكن الشيفرة الجامعة مُعرّفة وقورنت قيمتها أو تم التحقق منها، فسيفترض المعالج الأوّلي دائمًا أنّ القيمة ستساوي ‎0‎. وهناك عدّة طرق للتعامل مع هذا، إحداها هي افتراض أنّ الإعدادات الافتراضية تُمثَّل بالعدد 0، ويجب إجراء أيّ تغييرات لازمة بشكل صريح (على سبيل المثال ENABLEEXTRADEBUGGING = 0 افتراضيًا، مع الإسناد -DENABLEEXTRADEBUGGING = 1 لإعادة التعريف).

هناك طريقة أخرى، وهي جعل جميع التعاريف والقيم الافتراضية صريحة، ويمكن تحقيق ذلك بدمج المُوجِّهين ‎#ifndef‎ و ‎#error‎:

#ifndef (ENABLE_EXTRA_DEBUGGING) // إن لم تكن مضافة سلفا DefaultDefines.h برجاء إضافة # error "ENABLE_EXTRA_DEBUGGING is not defined" #else # if ( 1 == ENABLE_EXTRA_DEBUGGING ) //code # endif #endif وحدات الشيفرة الجامعة التوليدية X-macros

هي تقنية اصطلاحية لتكرار توليد بنيات برمجية في وقت التصريف، وتتكون الشيفرات الجامعة التوليدية من جزأين: القائمة، وتنفيذ القائمة.

هذا مثال توضيحي:

#define LIST\ X(dog)\ X(cat)\ X(racoon) // class Animal { // public: // void say(); // }; #define X(name) Animal name; LIST #undef X int main() {#define X(name) name.say(); LIST #undef X return 0; }

هذا المثال سيُوسَّع من قبل المعالج الأوّلي إلى ما يلي:

Animal dog; Animal cat; Animal racoon; int main() { dog.say(); cat.say(); racoon.say(); return 0; }

عندما تصبح القوائم كبيرة (أكثر من 100 عنصر)، فإنّ هذه التقنية تساعد على تجنّب الإكثار من النسخ واللصق. وإذا أردت تجنّب التعريف غير الضروري لـ ‎X‎ قبل استخدام ‎LIST‎، فيمكنك تمرير اسم شيفرة جامعة كوسيط أيضًا:

#define LIST(MACRO)\ MACRO(dog)\ MACRO(cat)\ MACRO(racoon)

الآن، يمكنك تعريف الشيفرة الجامعة الذي يجب استخدامها عند توسيع القائمة، كما يلي:

#define FORWARD_DECLARE_ANIMAL(name) Animal name; LIST(FORWARD_DECLARE_ANIMAL)

إذا وجب على كل استدعاء لـ ‎MACRO‎ أن يأخذ معاملات إضافية ثابتة بالنسبة للقائمة، فيمكن استخدام وحدات شيفرات جامعة متغيّرة (variadic macros):

// Visual studio #define EXPAND(x) x #define LIST(MACRO, ...)\ EXPAND(MACRO(dog, __VA_ARGS__))\ EXPAND(MACRO(cat, __VA_ARGS__))\ EXPAND(MACRO(racoon, __VA_ARGS__))

يُمرَّر الوسيط الأولى عبر ‎LIST‎، بينما تُوفّر الوسائط الأخرى عبر المستخدم عند استدعاء ‎LIST‎. مثلا، الشيفرة التالية:

#define FORWARD_DECLARE(name, type, prefix) type prefix## name; LIST(FORWARD_DECLARE, Animal, anim_) LIST(FORWARD_DECLARE, Object, obj_)

سوف تتوسع على النحو التالي:

Animal anim_dog; Animal anim_cat; Animal anim_racoon; Object obj_dog; Object obj_cat; Object obj_racoon; الشيفرات الجامعة Macros

تُصنّف وحدات الشيفرة الجامعة إلى مجموعتين رئيسيتين: وحدات الشيفرة الجامعة المشابهة للكائنات (object-like macros)، ووحدات الشيفرة الجامعة المشابهة للدوالّ (function-like macros). تُعامَل وحدات الشيفرة الجامعة كأداة لتعويض مقطع (token) معيّن من الشيفرة أثناء عملية التصريف، هذا يعني أنّه يمكن تجريد المقاطع الكبيرة (أو المكرّرة) من الشيفرة عبر شيفرة جامعة. انظر:

// هذه شيفرة جامعة تشبه الكائنات #define PI 3.14159265358979

هذه شيفرة جامعة تشبه الدوال، لاحظ أنه يُمكننا استخدام الشيفرَات الجامعة المُعرّفة مسبقًا في تعريفات شيفرة جامعة أخرى. ولا يعرف المصرِّف أيّ نوع يتعامل معه، لذلك يفضل استخدام الدوال المضمّنة:

#define AREA(r) (PI *(r) *(r)) // يمكن استخدامها على النحو التالي double pi_macro = PI; double area_macro = AREA(4.6);

تستخدم مكتبة Qt هذه التقنية لإنشاء نظام وصفي للكائنات (meta-object system) عن طريق مطالبة المستخدم بتعريف الشيفرة الجامعة Q_OBJECT في رأس الصنف الذي يوسّع QObject. وتُكتب أسماء وحدات الشيفرة الجامعة في العادة بأحرف كبيرة لتسهيل تمييزها عن الشيفرات العادية. هذا ليس شرطًا لكنّ يستحسنه كثير من المبرمجين.

عند مصادفة شيفرة جامعة مشابهة للكائنات فإنها تُوسّع كعملية لصق-نسخ بسيطة، مع استبدال اسم الشيفرَة الجامعة بتعريفها. أمّا الشيفرات الجامعة المشابهة للدوال، فيُوسّع كلّ من اسمها ومعاملاتها.

double pi_squared = PI * PI; double pi_squared = 3.14159265358979 * 3.14159265358979; double area = AREA(5); double area = (3.14159265358979 *(5) *(5))

وغالبًا ما تُوضع معاملات الشيفرة الجامعة الشبيهة بالدالّة (function-like macro parameters) بسبب هذا ضمن الأقواس، كما في ‎AREA()‎ أعلاه، وذلك لمنع أيّ أخطاء قد تحدث أثناء توسيع الشيفرة الجامعة، خاصة الأخطاء التي قد تنتج عن مُعاملات الشيفرة الجامعة التي تتألّف من عدة قيم.

#define BAD_AREA(r) PI *r *r double bad_area = BAD_AREA(5 + 1.6); // ما يراه المصرف: double bad_area = 3.14159265358979 * 5 + 1.6 * 5 + 1.6; double good_area = AREA(5 + 1.6); // ما يراه المصرف: double good_area = (3.14159265358979 *(5 + 1.6) *(5 + 1.6));

لاحظ أيضًا أنّه يجب توخي الحذر بخصوص المعاملات المُمرّرة إلى وحدات الشيفرة الجامعة بسبب هذا التوسيع البسيط، وذلك لمنع الآثار الجانبية غير المتوقعة. وإذا عُدِّل المُعامل أثناء التقييم فسيُعُدَّل في كل مرّة يُستخدَم في الشيفرة الجامعة الموسَّعة، ونحن لا نريد ذلك عادة. يبقى هذا صحيحًا حتى لو كانت الشيفرة الجامعة تُحيط المعاملات بالأقواس لمنع كسر الشيفرة بسبب التوسيع.

int oops = 5; double incremental_damage = AREA(oops++); // ما يراه المصرف: double incremental_damage = (3.14159265358979*(oops++)*(oops++));

بالإضافة إلى ذلك، لا توفّر وحدات الشيفرة الجامعة أيّ حماية من أخطاء الأنواع، ممّا يصعّب فهم الأخطاء الناتجة عن عدم تطابق الأنواع.

ولمّا كان المبرمجون ينهون السطر بفاصلة منقوطة في العادة، فغالبًا ما تُصمَّم وحدات الشيفرة الجامعة المراد استخدامها كسطور مستقلة "لابتلاع" الفاصلة المنقوطة، هذا يمنع أيّ أخطاء غير مقصودة ناتجة عن وجود فاصلة منقوطة إضافية.

#define IF_BREAKER(Func) Func(); if (some_condition) // Oops. IF_BREAKER(some_func); else std::cout << "I am accidentally an orphan." << std::endl;

في هذا المثال، كسرت الفاصلة المنقوطة المزدوجة غير المقصودة كتلة ‎if...else‎، ومنعت المٌصرّف من مطابقة ‎else‎ بـ ‎if‎. ولكي نمنع هذا، تُحذَف الفاصلة المنقوطة من تعريف الشيفرة الجامعة، ممّا يتسبب في "ابتلاع" الفاصلة المنقوطة مباشرةً بعد أيّ استخدام لها.

#define IF_FIXER(Func) Func() if (some_condition) IF_FIXER(some_func); else std::cout << "Hooray! I work again!" << std::endl;

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

#define DO_SOMETHING(Func, Param) Func(Param, 2) // ... some_function(DO_SOMETHING(some_func, 3), DO_SOMETHING(some_func, 42));

عادة، ينتهي تعريف الشيفرة الجامعة في نهاية السطر، فإذا احتاجت الشيفرة الجامعة إلى أن تمتدّ على عدّة أسطر، فيمكن استخدام شرطة عكسية \ في نهاية السطر للإشارة إلى ذلك. ويجب أن تكون هذه المشروطة العكسية هي الحرف الأخير من السطر، فذلك يُخطر المُعالج الأوّلي بوجوب ضمّ السطر التالي إلى السطر الحالي، ومعاملتهُما كسطرٍ واحد. يمكن استخدام هذا عدّة مرات على التوالي.

#define TEXT "I \ am \ many \ lines." // ... std::cout << TEXT << std::endl; // I am many lines.

هذا مفيد بشكل خاص في وحدات الشيفرة الجامعة المعقّدة الشبيهة بالدوالّ، والتي قد تحتاج إلى الامتداد على عدّة أسطر.

#define CREATE_OUTPUT_AND_DELETE(Str) \ std::string* tmp = new std::string(Str); \ std::cout << *tmp << std::endl; \ delete tmp; // ... CREATE_OUTPUT_AND_DELETE("There's no real need for this to use 'new'.")

أمّا بخصوص وحدات الشيفرة الجامعة المعقدة الشبيهة بالدوالّ، فقد يكون من المفيد منحها نطاقًا خاصًّا بها لمنع التداخلات في الأسماء أو التسبب في تدمير الكائنات في نهاية الشيفرة الجامعة، وذلك على غرار الدوالّ الفعلية.

المقاربة الشائعة لهذا هي استخدام الحلقة do while 0، حيث تُوضع الشيفرة الجامعة في كتلة التكرار. لا تُتبع هذه الكتلة عادة بفاصلة منقوطة، ممّا يسمح لها بابتلاع واحدة.

#define DO_STUFF(Type, Param, ReturnVar) do {\ Type temp(some_setup_values);\ ReturnVar = temp.process(Param);\ } while (0) int x; DO_STUFF(MyClass, 41153.7, x); int x; do { MyClass temp(some_setup_values); x = temp.process(41153.7); } while (0);

هناك أيضًا وحدات شيفرة جامعة متغايرة (variadic)، والتي تأخذ عددًا متغيّرا من الوسائط، ثم توسّعها جميعًا بدلاً من المُعامل الخاص ‎__VA_ARGS__‎.

#define VARIADIC(Param, ...) Param(__VA_ARGS__) VARIADIC(printf, "%d", 8); // ما يراه المصرِّف: printf("%d", 8);

لاحظ أنّه يمكن وضع ‎__VA_ARGS__‎ أثناء التوسيع في أيّ مكان في التعريف، وسيُوسّع بشكل صحيح.

#define VARIADIC2(POne, PTwo, PThree, ...) POne(PThree, __VA_ARGS__, PTwo) VARIADIC2(some_func, 3, 8, 6, 9); some_func(8, 6, 9, 3);

في حالة المعامِل المتغير الذي ليس له وسائط، فإنّ المٌصرّفات تتعامل مع الفاصلة الزائدة بشكل مختلف، حيث تبتلع بعض المُصرّفات -مثل Visual Studio- الفاصلة بصمت بدون أيّ صيغة خاصّة، فيما ستطلّب منك مُصرّفات أخرى -مثل GCC- وضع ‎##‎ مباشرة قبل ‎__VA_ARGS__‎. ويكون من الحكمة بسبب هذا أن تضع تعريف وحدات الشيفرة الجامعة التي تأخذ عددًا متغيّرا من الوسائط في عبارة شرطية إذا كنت حريصًا على قابلية الشيفرة للعمل في أكثر من مكان. في المثال التالي: COMPILER هو شيفرة جامعة تحدد المصرِّف المستخدم.

#if COMPILER == "VS" #define VARIADIC3(Name, Param, ...) Name(Param, __VA_ARGS__) #elif COMPILER == "GCC" #define VARIADIC3(Name, Param, ...) Name(Param, ##__VA_ARGS__) #endif /* COMPILER */ الشيفرات الجامعة المُعرّفة مسبقًا (Predefined macros)

الشيفرة الجامعة المُعرّفة مسبقًا هي تلك التي يعرّفها المٌصرّف -على النقيض من تلك التي يعرّفها المستخدمون في الملف المصدري-، ويجب ألّا يُعاد تعريف تلك الشيفرات الجامعة أو إلغاء تعريفها من قِبل المستخدم.

الشيفرات الجامعة التالية مُعرّفة مسبقًا وفقًا لمعيار C++‎:

  • ‎__LINE__‎ - تحتوي على رقم السطر الذي تُسُتخدم فيه هذه الشيفرة الجامعة، ويمكن تغييرها عبر المُوجِّه ‎‎#line.
  • ‎__FILE__‎ - تحتوي على اسم الملفّ الذي تُستخدم فيه هذه الشيفرة الجامعة في، ويمكن تغييرها عبر المُوجِّه ‎‎#line.
  • ‎__DATE__‎ - تحتوي تاريخ تصريف الملف (بتنسيق "Mmm dd yyyy")، ويتم تنسيق Mmm كما لو كانت مُعادة من قبل ‎std::asctime()‎.
  • ‎__TIME__‎ - تحتوي زمن تصريف الملف وفق التنسيق "HH: MM: SS".
  • ‎__cplusplus‎ - تُعرَّف من قبل مصرّف C++‎ أثناء تصريف ملفات C++‎، وقيمتها هي الإصدار القياسي الذي يتوافق مع المٌصرّف، أي ‎199711L‎ لـ C++‎ 98 و C++‎ 03، و ‎201103L‎ لـ C++‎ 11، و ‎201402L‎ لمعيار C++‎ 14.

الإصدار ≥ C++‎ 11

  • ‎__STDC_HOSTED__‎ - تُعطى القيمة ‎1‎ إذا كان التطبيق مُستضافًا (hosted)، أو ‎0‎ إذا كان قائما بذاته (freestanding).

الإصدار ≥ C++‎ 17

  • ‎__STDCPP_DEFAULT_NEW_ALIGNMENT__‎ - تحتوي على size_t حرفية، والتي تمثّل المحاذاة المستخدمة لإجراء استدعاء للعامل ‎operator new‎ غير المدرِك للمحاذاة.

بالإضافة إلى ذلك، يُسمح للشيفرة الجامعة التالية أن تُعرَّف مسبقًا من قبل التنفيذات، لكنّها غير إلزامية:

  • ‎__STDC__‎ - يعتمد معناها على التنفيذ، ولا تٌعرَّف عادة إلّا عند تصريف ملف في لغة C للدلالة على الامتثال الكامل مع معيار C القياسي، أو قد لا تُنفّد إذا قرّر المٌصرّف عدم دعم هذه الشيفرة الجامعة.

الإصدار ≥ C++‎ 11

  • ‎__STDC_VERSION__‎ - يعتمد معناها على التنفيذ، وعادة ما تساوي قيمتها إصدارَ لغة C، على نحو مشابه لـ ‎__cplusplus‎ في إصدار C++‎، أو قد لا تُعرَّف، إذا قرر المٌصرّف عدم دعم هذه الشيفرة الجامعة.
  • ‎__STDC_MB_MIGHT_NEQ_WC__‎ - تُعطى القيمة ‎1‎، إذا كان ممكنًا لقيم الترميز الضيق لمجموعة المحارف الأساسية، ألا تساوي قيم نظرائها الواسعة، مثلًا في حال كان ‎(uintmax_t)'x' != (uintmax_t)L'x'‎.
  • ‎__STDC_ISO_10646__‎ - تُعرّف في حال كان wchar_t مُرمّزًا بترميز اليونيكود (Unicode)، وتُوسّع إلى عدد صحيح على شكل ‎yyyymmL‎ إشارةً إلى دعم آخر مُراجَعة لليونيكود.
  • ‎__STDCPP_STRICT_POINTER_SAFETY__‎ - تُعطى القيمة ‎1‎ إذا كان للتنفيذ نظام أمان صارم للمؤشّرات (strict pointer safety)
  • ‎__STDCPP_THREADS__‎ - تُعطى القيمة ‎1‎ إذا أمكن احتواء البرنامج على أكثر من خيط (thread) واحد للتنفيذ، ينطبق هذا على التنفيذ المستقل (freestanding implementation) أما التنفيذات المستضافة فيمكن أن يكون لها أكثر من خيط واحد.

ربما تجب الإشارة إلى ‎__func__‎، وهي ليست شيفرة جامعة ولكنّها متغيِّر محلّي لدالّة مُعرّفة مُسبقا (predefined function-local variable). يحتوي هذا المتغير على اسم الدالّة التي تُستخدَم فيها على شكل مصفوفة حروف ساكنة وفق تنسيق مُعرّف من قِبل التنفيذ.

ويمكن أن يكون للمٌصرّفات مجموعة خاصّة بها من وحدات الشيفرة الجامعة المسبقة، وذلك إضافة إلى وحدات الشيفرة الجامعة القياسية المُعرّفة مسبقًا، ارجع إن شئت إلى توثيق المٌصرّف للاطلاع عليها. على سبيل المثال:

توجد بعض تلك الشيفرات الجامعة للاستعلام عن دعم بعض الميزات فقط:

#ifdef __cplusplus // C++ في حال صُرِّفت عبر مصرّف extern "C" { //C يجب أن تُزخرَف شيفرة // هنا C ترويسة مكتبة } #endif

البعض الآخر مفيدة جدًا للتنقيح:

الإصدار ≥ C++‎ 11

bool success = doSomething( /*some arguments*/ ); if( !success ){ std::cerr << "ERROR: doSomething() failed on line " << __LINE__ - 2 << " in function " << __func__ << "()" << " in file " << __FILE__ << std::endl; }

والبعض الآخر للتحكم في الإصدار:

int main(int argc, char *argv[]) { if( argc == 2 && std::string( argv[1] ) == "-v" ){ std::cout << "Hello World program\n" << "v 1.1\n" // عليك تحديث هذا يدويا << "compiled: " << __DATE__ << ' ' << __TIME__ // هذا يُحدّث تلقائيا << std::endl; } else { std::cout << "Hello World!\n"; } } عمليات المعالجة الأولية

يُستخدم المُعامل ‎#‎ أو مُعامل التنصيص (stringizing operator) لتحويل مُعامل شيفرة جامعة إلى سلسلة نصية، ولا يمكن استخدامه إلّا مع شيفرة جامعة ذات وسائط. انظر المثال التالي حيث يحول المعالج الأولي المعامِلَ x إلى السلسلة النصية المجردة x:

#define PRINT(x) printf(#x "\n") PRINT(This line will be converted to string by preprocessor); printf("This line will be converted to string by preprocessor" "\n");

يضمّ المُصرّف سلسلتين نصّيتين إلى بعضهما، وسيكون الوسيط ‎printf()‎ النهائي عبارة عن سلسلة نصية مجردة تنتهي بمحرف السطر الجديد. وسيتجاهل المُعالج الأوّلي المسافات البيضاء الموجودة قبل أو بعد وسيط الشيفرة الجامعة، لذلك ستطبع الشيفرة التالية نفس النتيجة.

PRINT(This line will be converted to string by preprocessor);

إذا تطلب مُعامل السلسلة النصية المجردة تسلسل تهريب (escape sequence)، كما هو الحال قبل علامة الاقتباس المزدوجة، فسيُدرَج تلقائيًا عبر المعالج الأوّلي.

PRINT(This "line" will be converted to "string" by preprocessor); printf("This \"line\" will be converted to \"string\" by preprocessor""\n");

يُستخدم العامل ‎##‎ أو عامل لصق القِطع (Token pasting operator) لضمّ سلسلتين نصّيتين أو مقطعَين خاصين بشيفرة جامعة. انظر المثال التالي حيث يدمج المعالجُ الأولي المتغيرَ مع x:

#define PRINT(x) printf("variable" #x " = %d", variable##x) int variableY = 15; PRINT(Y); printf("variable""Y"" = %d", variableY);

وسنحصل على الناتج التالي:

variableY = 15 ‎‎ #pragma once

تدعم معظم تطبيقات C++‎ المُوجِّه ‎#pragma once‎ الذي يتحقّق من أنّ الملفّ لن يُضمَّن إلّا مرّة واحدة في كل عملية تصريف، وهو ليس جزءًا من أيّ معيار من معايير ISO C++‎.

على سبيل المثال:

// Foo.h #pragma once class Foo {};

بينما تتجنب ‎#pragma once‎ بعض المشاكل المرتبطة بدروع التضمين (include guards) التي ذكرناها آنفًا، فإنّ ‎#pragma‎ -حسب تعريفها في المعايير- هي خطّاف خاصّ بالمٌصرّف (compiler-specific hook)، وسيُتجاهَل بصمت من قبل المٌصرّفات التي لا تدعمه.

ويجب تعديل المشاريع التي تستخدم ‎#pragma once‎ لتكون متوافقة مع المعايير، وقد يؤدّي ‎#pragma once‎ إلى تسريع كبير لعملية التصريف في بعض المُصرِّفات -خاصّة تلك التي تستخدم الترويسات المُصرّفة مسبقًا-. وبالمثل، تسرّع بعض المُعالجات الأوّلية عملية التصريف من خلال التحقق من الترويسات المُتضمّنة التي تستخدم الدروع.

قد تزيد الفائدة من استخدام كل من ‎#pragma once‎ والدروع معًا أو تنقص بحسب التنفيذ ووقت التصريف. وقد كان يوصى بدمج ‎#pragma once‎ مع دُروع التضمين عند كتابة تطبيقات MFC على ويندوز، وكانت تُنشأ بواسطة الأدوات ‎add class‎ و ‎add dialog‎ و ‎add windows‎ الخاصة بـ Visual Studio، لذا من الشائع أن تجدها في تطبيقات C++‎ الموجّهة لويندوز.

رسائل خطأ المُعالج الأوّلي

يمكن توليد أخطاء التصريف باستخدام المعالج الأوّلي، هذا مفيد لعدد من الأسباب:

  • إخطار المستخدم في حال كان على منصّة أو مٌصرّف غير مدعوم.
  • إعادة خطأ في حال كان الإصدار أقل من gcc 3.0.0.
#if __GNUC__ < 3 #error "This code requires gcc > 3.0.0" #endif

إعادة خطأ إن كان التصريف على حاسوب Apple.

#ifdef __APPLE__ #error "Apple products are not supported in this release" #endif

هذا الدرس جزء من سلسلة مقالات عن C++‎.

ترجمة -بتصرّف- للفصل Chapter 75: Preprocessor من كتاب C++ Notes for Professionals

28,735 تقنية Currying في جافاسكربت

مفهوم Currying هو تقنية متقدمة للعمل مع الدوالّ. يستخدم في العديد من اللغات البرمجية الأخرى من بينهم جافاسكربت.

Currying عبارة عن طريقة لتحويل الدوالّ التي تقيم الدالّة ذات الاستدعاء-أكثر من وسيط- f (a، b، c)‎ لتصبح قابلة للاستدعاء -بوسيط واحد- هكذا f(a)(b)(c)‎.

تحول تقنية Currying الدالّة فقط ولا تستدعها.

لنرى في البداية مثالًا، لفهم ما نتحدث عنه فهمًا أفضل، وبعدها ننتقل للتطبيقات العملية.

سننشئ دالة مساعدة باسم curry (f)‎ والتي ستُنفذّ تقنية Currying على الدالّة f التي تقبل وسيطين. بتعبير آخر، تحول الدالة curry(f)‎ الدالّة f(a, b)‎ ذات الوسيطين إلى دالة تعمل كوسيط واحدf(a)(b)‎:

function curry(f) { // ‫الدالة curry(f)‎ هي من ستُنفذّ تحويل currying return function(a) { return function(b) { return f(a, b); }; }; } // طريقة الاستخدام function sum(a, b) { return a + b; } let curriedSum = curry(sum); alert( curriedSum(1)(2) ); // 3

كما نرى، فإن التنفيذ بسيط: إنه مجرد مغلفين للوسطاء.

  • نتيجة curry(func)‎ هي دالة مغلّفة function(a)‎.
  • عندما تسمى هكذا curriedSum(1)‎، تُحفظ الوسطاء في البيئة اللغوية للجافاسكربت (وهي نوع مواصفات اللغة تستخدم لتعريف ارتباط المعرّفات بالمتغيّرات والدوالّ المحددة وذلك بناءً على بنية الترابط اللغوية في شيفرة ECMAScript)، وتعيد غلاف جديد function(b)‎.
  • ثمّ يُسمى هذا المغلّف باسم 2 نسبةً لوسطائه، ويُمرّر الاستدعاء إلى الدالّة sum(a,b)‎ الأصليّة.

من الأمثلة المتقدمة باستخدام تقنية currying هو _curry من مكتبة Lodash، والتي تُعيد غِلافًا الّذي يسمح باستدعاء الدالّة طبيعيًا وجزئيًا:

function sum(a, b) { return a + b; } let curriedSum = _.curry(sum); // ‫استخدام ‎_.curry من مكتبة lodash alert( curriedSum(1, 2) ); // ‫النتيجة: 3، لايزال بإمكاننا استدعاؤه طبيعيًا alert( curriedSum(1)(2) ); // ‫النتيجة: 3، الاستدعاء الجزئي لماذا نحتاج لتقنية currying؟

لابد لنا من مثالٍ واقعي لفهم فوائد هذه التقنية.

مثلًا، ليكن لدينا دالّة التسجيل log(date, importance, message)‎ والّتي ستُنسّق المعلومات وتعرضها. مثل هذه الدوالّ مفيدة جدًا في المشاريع الحقيقة مثل: إرسال السجلات عبر الشبكة، في مثالنا سنستخدم فقط alert:

function log(date, importance, message) { alert(`[${date.getHours()}:${date.getMinutes()}] [${importance}] ${message}`); }

لنُنفذ تقنية currying عليها!

log = _.curry(log);

بعد ذلك ستعمل دالّة log وفق المطلوب:

log(new Date(), "DEBUG", "some debug"); // log(a, b, c)

… ولكنها تعمل أيضًا بعد تحويلها بتقنية currying:

log(new Date())("DEBUG")("some debug"); // log(a)(b)(c)

الآن يمكننا بسهولة إنشاء دالّة مناسبة للسجلات الحالية:

// ‫logNow سيكون دالة جزئية من log مع وسيط أول ثابت let logNow = log(new Date()); // استخدامه logNow("INFO", "message"); // [HH:mm] INFO message

الآن logNow هو نفس الدالة log بوسيط أول ثابت، بمعنى آخر "دالّة مطبقة جزئيًا" أو "جزئية" للاختصار.

يمكننا المضي قدمًا وإنشاء دالّة مناسبة لسجلات تصحيح الأخطاء الحالية:

let debugNow = logNow("DEBUG"); debugNow("message"); // [HH:mm] DEBUG message

إذا:

  1. لم نفقد أي شيء بعد التحويل بتقنية currying: ولا يزال يمكننا أيضًا استدعاء الدالّة log طبيعيًا.
  2. يمكننا بسهولة إنشاء دوالّ جزئية مثل: سجلات اليوم.
الاستخدام المتقدم لتقنية currying

في حالة رغبتك في الدخول في التفاصيل، إليك طريقة الاستخدام المتقدمة لتقنية currying للدوال ذات الوسطاء المتعددة والّتي يمكننا استخدامها أعلاه.

وهي مختصرة جدًا:

function curry(func) { return function curried(...args) { if (args.length >= func.length) { return func.apply(this, args); } else { return function(...args2) { return curried.apply(this, args.concat(args2)); } } }; }

إليك مثالًا لطريقة استخدامه:

function sum(a, b, c) { return a + b + c; } let curriedSum = curry(sum); alert( curriedSum(1, 2, 3) ); // 6, still callable normally alert( curriedSum(1)(2,3) ); // 6, currying of 1st arg alert( curriedSum(1)(2)(3) ); // 6, full currying

تبدو تقنية currying للوهلة الأولى معقدةً، ولكنها في الحقيقة سهلة الفهم جدًا.

نتيجة استدعاء curry(func)‎ هي دالّة مُغلّفة curried والّتي تبدو هكذا:

// func is the function to transform function curried(...args) { if (args.length >= func.length) { // (1) return func.apply(this, args); } else { return function pass(...args2) { // (2) return curried.apply(this, args.concat(args2)); } } };

عند تشغيله، هناك فرعين للتنفيذ من الجملة الشرطية if:

  1. سيكون الاستدعاء الآن هكذا: إن كان عدد الوسطاء args المُمرّرة هو نفس العدد الدالة الأصليّة المعرّفة لدينا (func.length) أو أكثر، عندها نمرّر الاستدعاء له فقط.
  2. وإلا سيكون الاستدعاء جزئيًا: لم تُستدعى الدالّة func بعد. وإنما أعيد بدلًا منها دالّة المغلِّفة أخرى pass، والتي ستُعيد تطبيق الدالة curried مع تقديم الوسطاء السابقين مع الوسطاء الجدد. وثمّ في استدعاء الجديد سنحصل إما على دالة جزئية جديدة (إن لم يكُ عدد الوسطاء كافي) أو النتيجة النهائية.

لنرى مثلًا ما يحدث في حال الاستدعاء الدالة هكذا sum(a, b, c)‎. أي بثلاث وسطاء، وبذلك يكون sum.length = 3.

عند استدعاء curried(1)(2)(3)‎:

  1. الاستدعاء الأول curried (1)‎ تحفظ 1 في بيئته اللغوية، ويُعيد دالّة المغلف pass.
  2. يُستدعى المغلّف pass مع الوسيط المُمرّر (2): إذ يأخذ الوسطاء السابقين (1)، ويدمجهم مع الوسيط الذي حصل عليه وهو (2) ويستدعي الدالّة curried(1, 2)‎ مع استخدام جميع ما حصل عليه من وسطاء. وبما أن عدد الوسطاء لا يزال أقل من 3 ، فإن الدالّة curry ستُعيد الدالّة pass.
  3. يُستدعى المغلّف pass مرة أخرى مع الوسيط المُمرّر (3): ومن أجل الاستدعاء التالي pass (3)‎ سيأخذ الوسطاء السابقين (1, 2) ويضيف لهم الوسيط 3، ليكون الاستدعاء هكذا curried(1, 2, 3)‎- أخيرًا لدينا ثلاث وسطاء، والّذين سيمرّروا للدالّة الأصلية. إذا لم تتوضح الفكرة حتى الآن ، فما عليك إلا تتبع تسلسل الاستدعاءات في عقلك أو على الورقة وستتوضح الأمور أكثر.

ملاحظة: تعمل مع الدوالّ ثابتة الطول فقط

يجب أن يكون للدالّة عدد ثابت من الوسطاء لتطبيق تقنية currying.

إن استخدمت دالّةّ ما معاملات البقية، مثل: f(...args)‎، فلا يمكن معالجتها بهذه التقنية.

ملاحظة: أكثر بقليل من مجرد تقنية تحويل

انطلاقًا من التعريف، يجب على تقنية currying تحويل الدالّة sum(a, b, c)‎ إلى sum(a)(b)(c)‎.

لكن غالبية تطبيقات هذه التقنية في جافاسكربت متقدمة، وكما وضحنا سابقًا: فهي تحافظ على الدالّة قابلة للاستدعاء بعدة تنويعات للوسطاء المُمرّرة.

خلاصة

تقنية Currying هو عملية تحويل تجعل f(a,b,c)‎ قابلة للاستدعاء كـ f(a)(b)(c)‎. عادةً ما تحافظ تطبيقات الجافاسكربت على الدوالّ بحيث تكون قابلة للاستدعاء بالشكل الطبيعي أو الجزئي إن كان عدد الوسطاء غير كافٍ.

كما تسمح لنا هذه التقنية أيضًا بالحصول على دوالّ جزئية بسهولة. كما رأينا في مثال التسجيل، بعد تنفيذ هذه التقنية على الدالّة العالمية ذات الثلاث وسطاء log(date, importance, message)‎ فإن ذلك سيمنحنا دوالّ جزئية عند استدعاؤها باستخدام وسيط واحد (هكذا log(date)‎) أو وسيطين (هكذا log(date, importance)‎).

ترجمة -وبتصرف- للفصل Currying من كتاب The JavaScript language

28,712 تعرف على جديد واتساب.. البحث عن "الإيموجي" أبرزها

يعمل مطورو تطبيق واتساب بجد على تطوير مزايا جديدة لتطبيق المراسلة وإجراء تعديلات للتخلص من بعض نقاط الضعف – من الوضع المظلم إلى الملصقات المتحركة – ولكن ما الذي سيحدث بعد ذلك؟

يتخصص الخبراء في (WABetaInfo) في اختبار أحدث إصدارات واتساب التجريبية بحثًا عن علامات على الأدوات الجديدة والتعديلات التي تصل إلى التحديثات المستقبلية، وعادةً ما يتم رصدها جيدًا قبل أن تصبح متاحة للاستخدام للجميع.

مزايا واتساب الجديدة التي نتوقع رؤيتها قريبًا جدًا:

إدارة تخزين أسهل:

قد لا يستهلك واتساب نفسه مساحة كبيرة، ولكن عندما يكون لديك الكثير من الدردشات النشطة، يمكن أن يتم تحميل جميع الملفات التي تم تنزيلها قريبًا، لكن يمكنك حذف جميع الوسائط التي تم حفظها على جهازك، ولكن قد تكون هناك بعض اللقطات ومقاطع الفيديو التي تريد حفظها.

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

البحث عن ملصق:

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

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

وصول أسهل إلى الكاميرا:

هذه ميزة يجب أن تروق لأي شخص سارع لالتقاط لحظة ومشاركتها في واتساب لكنه تخبط في العثور على زر الكاميرا.

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

الدردشات الملونة:

الآن يبدو أن المطورين يعملون على ميزة جديدة ستسمح لك بتعيين خلفية مخصصة لكل محادثة، حيث سيساعد ذلك على عدم إرسال رسالة لوالديك بدلًا من أصدقائك.

الصفحات

أنت هنا