ما هو لون وظيفتك؟

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


(في هذه الأثناء ، أنت وأنا لا نستخدم سوى اللغة الأكثر استنارة والأدوات المتطورة المصممة للأيدي البراعة للسادة مثلنا).


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


من أجل حماية نفسي من النار الصالحة وعدم الإساءة إلى مشاعرك (ربما الحساسة) ، سأتحدث عن اللغة ...


... الذي جاء للتو. حول دمية صغيرة ، يتمثل دورها الوحيد في إحراق النقاد على المحك.


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


لغة جديدة


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


اخترت JS ليس لأن هذا المقال هو عنه. إنها مجرد لغة من المرجح أن يصل إليها القارئ العادي. فويلا:


 function thisIsAFunction(){ return "!"; } 

نظرًا لأن حيواننا المحشو عبارة عن لغة رائعة (سيئة - سيئة) ، فإنه يحتوي على وظائف من الدرجة الأولى . حتى تتمكن من كتابة شيء مثل هذا:


 //  ,     , //    function filter(collection, predicate) { var result = []; for (var i = 0; i < collection.length; i++) { if (predicate(collection[i])){ result.push(collection[i]); } } return result; } 

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


ربما في الاختبارات:


 describe("", function(){ it(" ", function(){ expect("").not.toBe(""); }); }; 

أو عندما تحتاج إلى تحليل (تحليل) البيانات:


 tokens.match(Token.LEFT_BRACKET, function(token){ // Parse a list literal... tokens.consume(Token.RIGHT_BRACKET); }); 

بعد ذلك ، بعد التسارع ، يمكنك كتابة جميع أنواع المكتبات والتطبيقات القابلة لإعادة الاستخدام والتي تدور حول الوظائف ، ومكالمات الوظائف ، وإرجاع الوظائف من الوظائف - كشك وظيفي.


الترجمة: في "Functapalooza" الأصلي. البادئة- a-palooza رائعة لدرجة أنك تريد مشاركتها مع الجميع.

ما هو لون وظيفتك؟


وهنا تبدأ الشذوذ. لغتنا ميزة واحدة غريبة:


1. كل وظيفة لها لون.


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


 blue*function doSomethingAzure(){ //   ... } red*function doSomethingCarnelian(){ //    ... } 

لغتنا لا تحتوي على وظائف عديمة اللون. تريد أن تجعل ميزة؟ - يجب اختيار اللون. هذه هي القواعد. وهناك عدد قليل من القواعد التي يجب عليك اتباعها:


2. يؤثر اللون على طريقة استدعاء الوظيفة


تخيل أن هناك بناء جملة اثنين لوظائف الاستدعاء - "الأزرق" و "الأحمر". شيء مثل:


 doSomethingAzure(...)*blue; doSomethingCarnelian()*red; 

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


حكم غبي ، أليس كذلك؟ أوه ، لكن هناك شيء آخر:


3. الوظيفة الحمراء فقط هي التي تسبب الوظيفة الحمراء.


يمكنك استدعاء وظيفة الأزرق من اللون الأحمر. هذا كوشير:


 red*function doSomethingCarnelian(){ doSomethingAzure()*blue; } 

ولكن ليس العكس. إذا حاولت:


 blue*function doSomethingAzure(){ doSomethingCarnelian()*red; } 

- سوف يزورك المهرج العنكبوت القديم.


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


4. وظائف حمراء تسبب الألم


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


لا يهم ما هو عليه ، ولكن إذا قررت أن تجعل الوظيفة حمراء ، فإن أي شخص يستخدم واجهة برمجة التطبيقات (API) الخاصة بك سيرغب في البصق في القهوة أو القيام بشيء أسوأ.


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


للأسف ، الساديون الذين طوروا هذه اللغة (يعلم الجميع أن مؤلفي لغات البرمجة هم ساديون ، أليس كذلك؟) ألصق آخر شوكة فينا:


5. بعض الوظائف الأساسية للغة حمراء.


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


هذا هو كل خطأ في اللغات الوظيفية!


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


إذا اتصلنا بالوظائف الزرقاء فقط ، فإننا نجعل جميع وظائفنا زرقاء. خلاف ذلك ، نحن نصنع اللون الأحمر. حتى نقوم بإنشاء وظائف تأخذ وظائف ، لا داعي للقلق بشأن "تعدد الأشكال للون الوظيفة" (متعدد الألوان؟) أو غير ذلك من الهراء.


ولكن للأسف ، فإن الدرجات العليا هي مجرد مثال واحد. تنشأ المشكلة في كل مرة نريد فيها تقسيم برنامجنا إلى وظائف لإعادة الاستخدام.


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


في وقت لاحق كنت بحاجة لاستخدام هذه الخوارزمية في مكان آخر. وبطبيعة الحال ، يمكنك لف الكود في وظيفة منفصلة. اتصل بها من المكان القديم ومن الجديد. ولكن ما هو اللون الذي يجب أن تكون عليه الوظيفة؟ ربما ستحاول جعلها زرقاء ، لكن ماذا لو استخدمت إحدى هذه الوظائف "الحمراء الوحيدة" السيئة من مكتبة kernel؟


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


لون الرمز


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


وظائف حمراء - غير متزامن


إذا قمت بالبرمجة في JavaScript أو Node.js ، في كل مرة تحدد فيها وظيفة تستدعي وظيفة رد اتصال (رد اتصال) "لإرجاع" النتيجة ، فإنك تكتب وظيفة حمراء. انظر إلى قائمة القواعد هذه ولاحظ مدى ملاءمتها لاستعاري:


  1. الدالات المتزامنة تُرجع نتيجة ، الدوال غير المتزامنة لا ؛ في المقابل ، يسمون رد اتصال.
  2. تقوم الدالات المتزامنة بإرجاع النتيجة كقيمة إرجاع ، بينما تقوم الدالات غير المتزامنة بإرجاعها ، مما يؤدي إلى رد الاتصال الذي قمت بتمريره إليهم.
  3. لا يمكنك استدعاء دالة غير متزامنة من وظيفة متزامنة ، لأنه لا يمكنك معرفة النتيجة حتى يتم تنفيذ الوظيفة غير المتزامنة لاحقًا.
  4. لا يتم تجميع الوظائف غير المتزامنة في التعبيرات بسبب عمليات الاسترجاعات ، وتتطلب معالجة أخطاءهم بشكل مختلف ، ولا يمكن استخدامها في كتلة try/catch أو في عدد من التعبيرات الأخرى التي تتحكم في البرنامج.
  5. كل شيء عن Node.js هو أن مكتبة kernel كلها غير متزامنة. (على الرغم من أنها تتبرع مرة أخرى وبدأت في إضافة إصدارات _Sync() إلى العديد من الأشياء.)

عندما يتحدث الناس عن "معاودة الاتصال بالجحيم" ، فإنهم يتحدثون عن مدى مزعج وجود وظائف "حمراء" في لغتهم. عندما ينشئون 4089 مكتبة للبرمجة غير المتزامنة (في عام 2019 بالفعل 11217 - مترجم تقريبًا) ، فإنهم يحاولون التعامل مع المشكلة على مستوى المكتبة التي تم تعليقها مع اللغة.


أعدك أن المستقبل أفضل


في الترجمة: "أعدك أن المستقبل أفضل" تضيع المسرحية على كلمات من عنوان ومحتويات القسم

أدرك الناس في Node.js منذ فترة طويلة أن عمليات الاسترجاعات تؤلمهم ويبحثون عن حلول. واحدة من التقنيات التي ألهمت الكثير من الناس هي promises ، والتي قد تعرفها أيضًا من خلال اللقب futures .


باللغة الروسية IT ، بدلاً من ترجمة "الوعود" على أنها "وعود" ، تم إنشاء ورقة تتبع من الإنجليزية - "وعود". يتم استخدام كلمة "العقود الآجلة" كما هي ، ربما لأن "العقود الآجلة" مشغولة بالفعل بالعامية المالية.

بروميس عبارة عن غلاف لرد الاتصال ومعالج الأخطاء. إذا كنت تفكر في تمرير رد اتصال للنتيجة واستدعاء آخر للخطأ ، فإن future هو تجسيد لهذه الفكرة. هذا هو كائن أساسي هو عملية غير متزامنة.


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


ولكن أن نكون صادقين ، هو مثل الفرق بين ضربة في المعدة أو الفخذ. نعم ، هذا غير مؤلم ، لكن لن يسعد أحد بهذا الاختيار.


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


لا تزال الوعود تقسم عالمك إلى نصفين غير متزامن ومتزامن مع كل المعاناة التي تلت ذلك. لذلك ، حتى لو كانت لغتك تدعم promises أو futures ، فإنها لا تزال تشبه إلى حد كبير حبي.


(نعم ، هذا يشمل حتى السهام الذي أستخدمه. لذلك ، أنا سعيد جدًا لأن جزءًا من الفريق يحاول أساليب أخرى للتوازي )


رابط المشروع مهجور رسميا

أنا في انتظار الحل


من المحتمل أن يشعر المبرمجون في C # بالدخان (والسبب في أنهم أصبحوا أكثر وأكثر ضحية هو أن Halesberg ورفاقه جميعهم يرشون ويرشون اللغة بالسكر النحوي). في C # ، يمكنك استخدام الكلمة الرئيسية التي await لاستدعاء دالة غير متزامنة.


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


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


لا يزال لديك لونين. تنتظر Async- الانتظار المشكلة المزعجة رقم 4 - فهي تجعل استدعاء الوظائف الحمراء أكثر صعوبة من استدعاء الوظائف الزرقاء. لكن بقية القواعد لا تزال هنا:


  1. ترجع الدالات المتزامنة قيمًا ، بينما ترجع الدالات غير المتزامنة غلافًا ( Task<T> في C # أو Future<T> في Dart) حول القيمة.
  2. متزامن يسمى فقط ، والحاجة غير متزامن await .
  3. عن طريق استدعاء دالة غير متزامنة ، تحصل على كائن مجمّع عندما تريد حقًا قيمة. لا يمكنك توسيع القيمة حتى تجعل وظيفتك غير متزامنة await (ولكن انظر الفقرة التالية).
  4. بالإضافة إلى الزخرفة التي تنتظر قليلاً ، فقد حللنا هذه المشكلة على الأقل.
  5. مكتبة C # الأساسية أقدم من عدم التزامن ، لذلك أعتقد أنهم لم يواجهوا هذه المشكلة على الإطلاق.

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


أي لغة ليست ملونة؟


لذلك JS ، دارت ، C # وبيثون لديهم هذه المشكلة. CoffeeScript ومعظم اللغات الأخرى التي يتم تجميعها في JS أيضًا (و Dart موروثة). أعتقد أنه حتى ClojureScript لديه هذا المصطلح ، على الرغم من جهوده النشطة مع core.async


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


كل شيء موجود بالفعل في جافا

C # ، في الواقع ، يمكن أن تتغلب أيضا على هذه المشكلة. اختاروا أن يكون لون. قبل أن يضيفوا غير متزامن ، وكل هذه Task<T> ، يمكنك استخدام مكالمات API متزامنة منتظمة. ثلاث لغات أخرى ليس لديها مشكلة "ألوان": Go و Lua و Ruby.


تخمين ما لديهم من القواسم المشتركة؟


مجاري المياه. أو بتعبير أدق: العديد من مجموعات مكالمات المكالمات المستقلة التي يمكنها التبديل . هذه ليست بالضرورة مؤشرات ترابط لنظام التشغيل. Coroutines في Go ، coroutines في Lua ، والخيوط في Ruby كلها كافية.


(لهذا السبب يوجد هذا التحذير الصغير لـ C # - يمكنك تجنب الألم غير المتزامن في C # باستخدام الخيوط.)


ذاكرة العمليات السابقة


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


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


ولكن من أجل إجراء I / O غير متزامن ، يجب عليك الاسترخاء ، وتجاهل مكدس المكالمة بالكامل في C. Type Trick-22. لديك I / O بسرعة فائقة ، ولكن لا يمكنك استخدام النتيجة! جميع اللغات ذات الإدخال / الإخراج غير المتزامن تحت الغطاء - أو في حالة JS ، حلقة حدث المستعرض - تضطر إلى التعامل مع هذا بطريقة أو بأخرى.


العقدة ، مع مسيرات الاسترجاعات اليمنى إلى الأبد ، تملج كل هذه المكالمات في الإغلاق. عندما تكتب:


 function makeSundae(callback) { scoopIceCream(function (iceCream) { warmUpCaramel(function (caramel) { callback(pourOnIceCream(iceCream, caramel)); }); }); } 

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


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


وظيفة شرسة الارتباط

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


لم يخطر ببال أحد أن المبرمج يمكنه كتابة مثل هذا الكود . ثم ظهرت العقدة ، وفجأة نتظاهر جميعًا بكتابة واجهة مترجم. أين ننتقل إلى الطريق الخطأ؟


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


في انتظار حل ولدت


Async- انتظار يساعد حقا . إذا نظرت أسفل الغطاء إلى المترجم عندما تواجهه ، فسترى أنه يقوم بالفعل بتحويل CPS. لهذا السبب تحتاج إلى استخدام await في C # - هذا تلميح إلى المحول البرمجي - "أوقف الوظيفة في المنتصف هنا." كل شيء بعد await يصبح وظيفة جديدة يقوم المحول البرمجي بتوليفها نيابة عنك.


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


ربما تتساءل عندما أذكر المولدات. هل هناك yield في لغتك؟ ثم يمكنه فعل شيء مشابه جدا.


(أعتقد أن المولدات و async-await هي في الواقع غير متجانسة. في مكان ما في الزوايا المتربة والكراني على القرص الصلب الخاص بي هو جزء من التعليمات البرمجية التي تنفذ حلقة لعبة على المولدات باستخدام فقط async-wait.)


إذن أين أنا؟ اوه نعم لذا ، من خلال عمليات الاسترجاعات والوعود والانتظار غير المتزامن والمولدات ، ينتهي بك الأمر إلى أخذ وظيفتك غير المتزامنة وتقسيمها إلى مجموعة من عمليات الإغلاق التي تعيش على الكومة.


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


هذا هو المكان الذي تأتي منه القاعدة: "يمكنك استدعاء الدالة الحمراء فقط من الوظيفة الحمراء". يجب عليك حفظ مكدس المكالمة بالكامل في عمليات الإغلاق إلى main() أو معالج الأحداث.


استدعاء تنفيذ المكدس


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


لغة Go ، في فهمي ، تقوم بهذا بشكل مثالي. بمجرد القيام بأي عملية إدخال / إخراج ، ستقوم Go بإيقاف هذا coroutine ومتابعة أي عمليات أخرى غير محظورة بواسطة I / O.


إذا نظرت إلى عمليات الإدخال / الإخراج في مكتبة Golang القياسية ، فإنها تبدو متزامنة. بمعنى آخر ، إنهم يعملون فقط ثم يعيدون النتيجة عندما يكونون جاهزين. ولكن هذا التزامن لا يعني نفسه كما هو الحال في جافا سكريبت. Go- , IO . Go .


Go — , . , , .


, API, , . .





, , . , . , 50% .


, , , .


Javascript -, , , JS , JS , . , JS .


, ( ) — , , , async . import threading ( , AsyncIO, Twisted Tornado, ).


, , , , , , .


, Go, Go .


, , , ( - ) , "async-await ". .


, .


, , .

Source: https://habr.com/ru/post/ar466337/


All Articles