Scala "<-" للفهم
-
04-10-2019 - |
سؤال
لقد وجدت أن سكالا لديها دائمًا "تفسير طبيعي" لأي شيء. دائما شيء مثل "أوه ، ولكن هذه مجرد وظيفة يتم استدعاؤها على هذا وهذا الكائن مع هذا وهذا المعلمة". بمعنى ما ، لا يوجد شيء في حقًا برمجيات برمجية كما نعرفه من لغات أخرى.
سؤالي على <- المشغل كما هو مستخدم في الكود التالي:
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 نموذج خاص من التخلص من ، مثل تحويل الأشكال الخاصة للتحديث وتطبيق الأساليب.