سؤال

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

يحرر:أقوم بتحديث هذا عندما أتلقى تعليقات حول صحته.


تنصل:كل هذه المعلومات غير رسمية ومن المحتمل أن تكون خاطئة.لا تستخدم هذا المنشور للحصول على فهم لكيفية عمل Clojure.


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

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

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

الذرات هي المواقع التي يمكن مشاركتها بشكل متزامن بين المواضيع.أنها تدعم التلاعب الآمن بين المواضيع المختلفة.

إليك ملخصي الودي استنادًا إلى وقت استخدام هذه الهياكل:

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

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

هل كانت مفيدة؟

المحلول

يبدو أنك حقا تحصل على Clojure!أحسنت :)

يحتوي vars على "ربط جذر" مرئي في جميع سلاسل الرسائل ويمكن لكل مؤشر ترابط فردي تغيير القيمة التي يراها دون التأثير على سلاسل الرسائل الأخرى.إذا كان فهمي صحيحًا، فلا يمكن أن يوجد var في مؤشر ترابط واحد فقط بدون ربط جذر مرئي للجميع ولا يمكن "ارتداده" حتى يتم تعريفه بـ (def ...) المرة الأولى.

يتم الالتزام بالمراجع في نهاية (dosync...) المعاملة التي تحتوي على التغييرات ولكن فقط عندما تكون المعاملة قادرة على الانتهاء في حالة متسقة.

نصائح أخرى

أعتقد أن استنتاجك حول الذرات خاطئ:

الذرات تشبه Vars ولكن مع أمان مشاركة الخيط الذي يتم حظره حتى تتغير القيمة

يتم تغيير الذرات مع swap! أو ذات مستوى منخفض مع compare-and-set!.وهذا لا يمنع أي شيء أبدًا. swap! تعمل كمعاملة بمرجع واحد فقط:

  1. القيمة القديمة مأخوذة من الذرة ويتم تخزينها محليًا
  2. يتم تطبيق الدالة على القيمة القديمة لإنشاء قيمة جديدة
  3. إذا نجح هذا، فسيتم استدعاء المقارنة والضبط بالقيمة القديمة والجديدة؛فقط إذا لم يتم تغيير قيمة الذرة بواسطة أي مؤشر ترابط آخر (لا تزال تساوي القيمة القديمة)، تتم كتابة القيمة الجديدة، وإلا يتم إعادة تشغيل العملية عند (1) حتى تنجح في النهاية.

لقد وجدت مشكلتين مع سؤالك.

قول انت:

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

http://clojure.org/agents يقول:

حالة الوكيل متاحة دائمًا على الفور للقراءة بواسطة أي موضوع

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

الكود الخاص ب deref-طريقة ان Agent يبدو مثل هذا (مراجعة SVN 1382):

public Object deref() throws Exception{
    if(errors != null)
    {
        throw new Exception("Agent has errors", (Exception) RT.first(errors));
    }
return state;

}

لا يوجد حظر متضمن.

كما أنني لا أفهم ما تقصده (في قسم المرجع الخاص بك).

يتم تنفيذ المعاملات على المكالمات إلى deref

يتم تنفيذ المعاملات عند اكتمال جميع إجراءات كتلة dosync، ولم يتم طرح أي استثناءات ولم يتسبب أي شيء في إعادة محاولة المعاملة.أظن deref لا علاقة له بالأمر، لكن ربما أسيء فهم وجهة نظرك.

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

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

(def a-promise (promise))
(deliver a-promise :fred)

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

(def f (future (some-sexp)))
(deref f) ; blocks the thread that derefs f until value is available

لا تحتوي Vars دائمًا على رابط جذر.من القانوني إنشاء فار بدون استخدام ملزم

(def x)

أو

(declare x)

ستؤدي محاولة تقييم x قبل أن تحتوي على قيمة إلى

Var user/x is unbound.
[Thrown class java.lang.IllegalStateException]
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top