سؤال

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

سؤالي على <- المشغل كما هو مستخدم في الكود التالي:

for(i <- 0 to 10) println(i)

في هذا المثال ، أستطيع أن أراها إعادة كتابتها إلى شيء مثل:

0.to(10).foreach((i:Int)=>println(i))

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

أظن أنني اكتشفت أخيرًا شيئًا ما في الواقع سحر المترجم

شكرا على وقتك.

للتوضيح، سؤالي هو: كيف يعمل <- المشغل في السطر الأول من التعليمات البرمجية لأنني لست كائنًا يمكن تسميته كدالة.

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

المحلول

<- هو رمز الكلمات الرئيسية المعرفة من اللغة ، كما هو => ولكن في تناقض مميز مع -> (وهو رمز محدد). لأنه جزء من قواعد Scala الأساسية ، يمكن استخدامه لإنشاء روابط (ل i في مثالك) وهو شيء لا يمكن القيام به عن طريق بنيات محددة من قبل المستخدم.

نصائح أخرى

لزيادة إجابة ديف ، إليك مخطط ترجمة لـ "التفريغ" من مواصفات لغة سكالا:

فهم for (enums) yield e يقيم التعبير e لكل الربط الناتج عن العدادات العدادات. يبدأ تسلسل العداد دائمًا بمولد ؛ يمكن أن يتبع ذلك المزيد من المولدات أو تعريفات القيمة أو الحراس.

مولد p <- e ينتج روابط من تعبير e وهو مطابق بطريقة ما ضد النمط p. تعريف القيمة val p = e يربط اسم القيمة p (أو عدة أسماء في نمط p) إلى نتيجة تقييم التعبير e. حارس if e يحتوي على تعبير منطقي يقيد الارتباطات المذكورة.

يتم تعريف المعنى الدقيق للمولدات والحراس من خلال الترجمة إلى دعوات من أربع طرق: map, filter, flatMap, ، و foreach. يمكن تنفيذ هذه الطرق بطرق مختلفة لأنواع ناقلات مختلفة.

مخطط الترجمة كما يلي. في الخطوة الأولى ، كل مولد p <- e, ، حيث لا يمكن دحض p (§8.1) لنوع نوع e لقد بدل بواسطة

 p <- e.filter { case p => true; case _ => false }

بعد ذلك ، يتم تطبيق القواعد التالية بشكل متكرر حتى يتم القضاء على جميع الشاملات.

  • من أجل التفريغ for (p <- e) yield e0 ترجم إلى e.map { case p => e0 }.

  • من أجل التفريغ for (p <- e) e0 ترجم إلى e.foreach { case p => e0 }.

  • من أجل التفريغ for (p <- e; p0 <- e0 . . .) yield e00, ، أين . . . يتم ترجمة تسلسل (ربما فارغ) من المولدات أو الحراس ، إلى:
    e.flatMap { case p => for (p0 <- e0 . . .) yield e00 }.

  • من أجل التفريغ for (p <- e; p0 <- e0 . . .) e00 أين . . . يتم ترجمة تسلسل (ربما فارغ) من المولدات أو الحراس ، إلى:
    e.foreach { case p => for (p0 <- e0 . . .) e00 } .

  • مولد p <- e يليه حارس if g ترجم إلى مولد واحد:
    p <- e.filter((x1, . . . , xn) => g )
    أين x1, . . . , xn هي المتغيرات الحرة ل p.

  • مولد p <- e متبوعًا بتعريف قيمة val p0 = e0 يتم ترجمته إلى المولد التالي لأزواج القيم ، حيث x و x0 أسماء جديدة:

    val (p, p0) <- 
      for(x@p <- e) yield { val x0@p0 = e0; (x, x0) }
    

في هذه الحالة ، إنه حقًا القليل من سحر المترجم. الترجمة من الفهود إلى التصفية/MAP/FlatMap نموذج خاص من التخلص من ، مثل تحويل الأشكال الخاصة للتحديث وتطبيق الأساليب.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top