لماذا يتم تعيين غير قابل للتغيير سكالا لن التغاير في نوعه؟
-
21-08-2019 - |
سؤال
تعديل : في إعادة كتابة هذا السؤال على أساس الإجابة الأصلية
والطبقة 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
}
المحلول
وSet
غير ثابتة في معلمة نوعه بسبب المفهوم الكامن وراء مجموعات وظائف. يجب التواقيع التالية توضيح الأمور قليلا:
trait Set[A] extends (A=>Boolean) {
def apply(e: A): Boolean
}
إذا تم التغاير Set
في A
، وطريقة apply
لن تكون قادرة على اتخاذ معلمة من نوع A
بسبب contravariance من الوظائف. Set
يحتمل أن يكون <م> contravariant في A
، ولكن هذا يسبب أيضا مشاكل عندما تريد أن تفعل أشياء من هذا القبيل:
def elements: Iterable[A]
وباختصار، فإن الحل الأفضل هو الحفاظ على الأشياء ثابتة، حتى بالنسبة للبنية بيانات غير قابل للتغيير. ستلاحظ أن immutable.Map
هو أيضا ثابتة في واحدة من المعلمات نوعه.
نصائح أخرى
http://www.scala-lang.org/node/9764 يكتب مارتن أوديرسكي:
<اقتباس فقرة>و"وفيما يتعلق بمسألة مجموعات، وأعتقد أن عدم التباين-ينبع أيضا من التنفيذ. وتنفذ مجموعات الشائعة كما hashtables، والتي هي صفائف غير متغير من نوع المفتاح. وأنا أتفق انها مخالفة مزعج قليلا."
اقتباس فقرة>وهكذا، يبدو أن كل جهودنا لبناء السبب المبدئي لهذا كانت مضللة: -)
تعديل : للأحد يتساءل لماذا تبدو هذه الإجابة قليلا خارج الموضوع، وذلك لأن I (السائل) عدلت هذه المسألة.
ونوع الاستدلال سكالا هو جيد بما فيه الكفاية لمعرفة أن كنت تريد CharSequences وليس سلاسل في بعض الحالات. على وجه الخصوص، الأعمال التالية بالنسبة لي في 2.7.3:
import scala.collections.immutable._
def findCharSequences(): Set[CharSequence] = Set("Hello", "World")
وأما بالنسبة لكيفية إنشاء immutable.HashSets مباشرة: لا. باعتبارها الأمثل التنفيذ، immutable.HashSets أقل من 5 عناصر ليست في الواقع حالات immutable.HashSet. فهي إما EmptySet، SET1، SET2، Set3، أو Set4. هذه الفئات فئة فرعية immutable.Set، ولكن ليس immutable.HashSet.