set - لماذا لم تكن مجموعة Scala غير قابلة للتغيير في نوعها؟




covariance scala-collections (4)

في http://www.scala-lang.org/node/9764 يكتب مارتن أوندرسكي:

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

لذا ، يبدو أن كل جهودنا لبناء سبب مبدئي لهذا كانت مضللة :-)

تعديل : أعد كتابة هذا السؤال استنادًا إلى الإجابة الأصلية

فئة scala.collection.immutable.Set ليست scala.collection.immutable.Set في معلمة النوع الخاص به. لماذا هذا؟

import scala.collection.immutable._

def foo(s: Set[CharSequence]): Unit = {
    println(s)
}

def bar(): Unit = {
   val s: Set[String] = Set("Hello", "World");
   foo(s); //DOES NOT COMPILE, regardless of whether type is declared 
           //explicitly in the val s declaration
}

تحرير : لأي شخص يتساءل لماذا يبدو هذا الجواب خارج الموضوع قليلاً ، وهذا لأن أنا (السائل) عدلت السؤال.

الاستنتاج من نوع سكالا هو جيد بما يكفي لمعرفة أنك تريد CharSequences وليس سلاسل في بعض الحالات. على وجه الخصوص ، الأعمال التالية بالنسبة لي في 2.7.3:

import scala.collections.immutable._
def findCharSequences(): Set[CharSequence] = Set("Hello", "World")

حول كيفية إنشاء immutable.HashSets مباشرة: لا. كما تحسين التنفيذ ، غير قابل للتغيير. HashSets أقل من 5 عناصر ليست في الواقع حالات indutable.HashSet. وهي إما EmptySet أو Set1 أو Set2 أو Set3 أو Set4. هذه الفئات فئة فرعية immutable.Set ، ولكن لا يمكن تعديله. HashSet.


Set غير ثابتة في المعلمة نوع لها بسبب المفهوم وراء مجموعات كوظائف. التوقيعات التالية يجب أن توضح الأمور قليلاً:

trait Set[A] extends (A=>Boolean) {
  def apply(e: A): Boolean
}

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

def elements: Iterable[A]

باختصار ، الحل الأفضل هو إبقاء الأشياء ثابتة ، حتى بالنسبة إلى بنية البيانات غير القابلة للتغيير. ستلاحظ أن immutable.Map غير ثابت أيضًا في أحد معلمات النوع.


فقط لإضافة ، ما يلي:

showStandardStreams = true

هو shorthand ل:

events = ["standard_out", "standard_error"]

من المهم وضع ذلك في الاعتبار عند خلط كلا الإدخالين كما يلي:

test {
    testLogging {
        showStandardStreams = true
        events = ["passed", "failed", "skipped"]
    }
}

سوف يؤدي إلى أي stdout في حين أن الترتيب العكسي:

test {
    testLogging {
        events = ["passed", "failed", "skipped"]
        showStandardStreams = true
    }
}

سيضيف مدخلات stdout إلى القائمة ، بحيث ستعمل stdout .

انظر المصدر للحصول على التفاصيل.





scala set covariance scala-collections