فهم استدعاء طريقة Infix و CONS (: :) في Scala
-
02-10-2019 - |
سؤال
أنا جديد تمامًا على لغة برمجة Scala ، وكنت أحاول شيئًا تمسك به في ذهني بينما كنت أتابع ملاحظات المحاضرة في هنا.
أعتقد أنني لا أستطيع أن أفهم حقًا كيف يعمل مشغل Cons ، إليك بعض الأشياء التي جربتها:
لقد قمت بإنشاء مولد أرقام عشوائي زائفة ، ثم حاولت إنشاء قائمة ذات قيمة عشوائية واحدة:
scala> val gen = new java.util.Random
gen: java.util.Random = java.util.Random@1b27332
scala> gen nextInt 3 :: Nil
<console>:7: error: type mismatch;
found : List[Int]
required: Int
gen nextInt 3 :: Nil
^
لكنها حاولت تمرير قائمة (3) إلى طريقة NextNT. عندما استخدمت parathes ، لم تكن هناك مشكلة
scala> (gen nextInt 3) :: Nil
res69: List[Int] = List(1)
كنت فضوليًا بشأن أمر التنفيذ ، لذلك قمت بإنشاء وظيفة للتحقق منها
scala> def pr(i:Int):Int = { println(i); i }
pr: (i: Int)Int
scala> pr(1) :: pr(2) :: pr(3) :: Nil
1
2
3
res71: List[Int] = List(1, 2, 3)
كما هو موضح في المخرجات ، يكون ترتيب التنفيذ هو نفسه ترتيب المظهر. ثم اعتقدت أن الأمر قد يكون عن وظيفة "NextInt" ، ثم حاولت المتابعة:
scala> 1 + 2 :: Nil
res72: List[Int] = List(3)
تم تنفيذها أولاً ، وبعد تنفيذ السلبيات. إذن هذا هو السؤال: ما هو الفرق بين gen nextInt 3 :: Nil
و 1 + 2 :: Nil
?
المحلول
هناك شيئان يثيران القلق هنا: الأولوية و ثبات. كما ذكر Sepp2k ، يشرح هذا السؤال على Stack Overflow الأسبقية ، واعتقد أن القواعد ، كما هو مقتبس ، ليست كاملة بما فيه الكفاية ، وكانت هناك تغييرات صغيرة جدًا من Scala 2.7 إلى Scala 2.8. الاختلافات تتعلق في الغالب المشغلين ينتهيون =
, ، على أية حال.
أما بالنسبة لل ثبات, ، يتم قراءة كل شيء تقريبًا في Scala من اليسار إلى اليمين ، وهو ما يستخدمه المبرمجين. في Scala ، ومع ذلك ، ينتهي المشغلون :
تقرأ يمينًا إلى اليسار.
خذ ، إذن ، هذا المثال:
1 + 2 :: Nil
أولا ، الأسبقية. ما هو أكثر الأسبقية ، +
أو :
؟ وفقا للجدول ، +
له الأسبقية :
, ، لذلك يتم الإضافة أولاً. لذلك ، فإن التعبير يساوي هذا:
((1).+(2)) :: Nil
الآن ليس هناك صراع الأسبقية ، ولكن منذ ذلك الحين ::
ينتهي :
, ، لديها ثبات مختلف. تتم قراءة اليمين إلى اليسار ، لذلك:
Nil.::((1).+(2))
من ناحية أخرى ، في هذا:
gen nextInt 3 :: Nil
المشغل ::
له الأسبقية nextInt
, ، لان :
له الأسبقية على جميع الحروف. لذلك ، وتذكر ثباته ، يصبح:
gen nextInt Nil.::(3)
الذي يصبح ثم
gen.nextInt(Nil.::(3))
عند هذه النقطة ، يكون الخطأ واضحًا.
ملاحظة: أنا أكتب (1).+(2)
بدلاً من 1.+(2)
لأنه ، في وقت كتابة هذا التقرير ، 1.
يتم تفسيره على أنه رقم مزدوج ، ويصنع 1.+(2)
تعبير Infix يضيف 1.0 إلى 2. يتم إهمال هذا الجملة اعتبارًا من Scala 2.10.0 ، وربما لن يكون موجودًا على Scala 2.11.
نصائح أخرى
إنه يتعلق بالأسبقية وليس أمر التنفيذ. +
له أسبقية أعلى من ::
, ، لذا a + b :: c
أخر من (a + b) :: c
. ومع ذلك ، فإن مكالمات طريقة Infix بأسماء منتظمة لها أسبقية أقل ، لذلك a foo b c
أخر من a foo (b c)
.
نرى هذا السؤال لقائمة المشغلين التي طلبها أسباقهم في سكالا.