لماذا تمنع التقنيات التوليدية للوقت للكتابة الهيكلية تجميعًا منفصلًا؟

StackOverflow https://stackoverflow.com/questions/3498954

  •  29-09-2019
  •  | 
  •  

سؤال

كنت أقرأ (حسنًا ، قشط) Dubochet و Odersky's تجميع الأنواع الهيكلية على JVM وكان مرتبكًا من الادعاء التالي:

تقنيات التوليد تنشئ واجهات Java للوقوف في الأنواع الهيكلية على JVM. يكمن تعقيد مثل هذه التقنيات في أن جميع الفئات التي سيتم استخدامها كنوع هيكلي في أي مكان في البرنامج يجب أن تنفذ الواجهات الصحيحة. عندما يتم ذلك في وقت الترجمة ، فإنه يمنع تجميع منفصل.

(تم اضافة التأكيدات)

النظر في مثال AutoClose من الورقة:

type Closeable = Any { def close(): Unit }

def autoclose(t: Closeable)(run: Closeable => Unit): Unit = {
   try { run(t) }
   finally { t.close }
}

لا يمكننا إنشاء واجهة ل Closeable اكتب على النحو التالي:

public interface AnonymousInterface1 {
   public void close();
}

وتحويل تعريفنا autoclose إلى

// UPDATE: using a view bound here, so implicit conversion is applied on-demand
def autoclose[T <% AnonymousInterface1](t: T)(run: T => Unit): Unit = {
   try { run(t) }
   finally { t.close }
}

ثم فكر في موقع مكالمة autoclose:

val fis = new FileInputStream(new File("f.txt"))
autoclose(fis) { ... }

حيث fis هو FileInputStream, ، الذي لا ينفذ AnonymousInterface1, ، نحتاج إلى إنشاء غلاف:

class FileInputStreamAnonymousInterface1Proxy(val self: FileInputStream) 
      extends AnonymousInterface1 {
   def close() = self.close();
}

object FileInputStreamAnonymousInterface1Proxy {
   implicit def fis2proxy(fis: FileInputStream): FileInputStreamAnonymousInterface1Proxy =
      new FileInputStreamAnonymousInterface1Proxy(fis)
}

يجب أن أكون مفقودًا شيئا ما, ، لكن من غير الواضح بالنسبة لي ما هو عليه. لماذا هذا النهج يمنع تجميع منفصل؟

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

المحلول

أنا في الواقع أستخدم النهج الضمني (باستخدام النماذج الناتجة) التي تصفها في مكتبة ذراع Scala. تذكر أن هذا حل مشفر يدويًا للمشكلة.

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

نرى: نوعية الموارد وكلها أغلفة محددة مسبقًا.

أيضًا ، قمت بالتدوين حول هذه التقنية التي تصف سحر الدقة الضمنية بمزيد من التفصيل: قرد الترقيع ، وكتابة البط ونوع الفصول الدراسية.

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

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

نصائح أخرى

كما أتذكر من نقاش على ال Scala-inernals القائمة البريدية ، المشكلة في هذا هو هوية الكائن ، والتي يتم الحفاظ عليها من خلال النهج الحالي للتجميع ، تُفقد عند لف القيم.

فكر في الأمر. النظر في الفئة أ

class A { def a1(i: Int): String = { ... }; def a2(s: String): Boolean = { ... }

مكان ما في البرنامج ، ربما في مكتبة تم تجميعها بشكل منفصل ، يتم استخدام هذا النوع الهيكلي:

{ def a1(i: Int): String }

وفي أي مكان آخر ، يتم استخدام هذا:

{ def a2(s: String): Boolean }

كيف ، بصرف النظر عن التحليل العالمي ، يتم تزيين الفئة A بالواجهات اللازمة للسماح باستخدامها حيث يتم تحديد تلك الأنواع الهيكلية البعيدة؟

إذا تم استخدام كل نوع هيكلي ممكن يمكن أن يتوافق معه فئة معينة لإنشاء واجهة تلتقط هذا النوع الهيكلي ، فهناك انفجار لهذه الواجهات. تذكر أن النوع الهيكلي قد يذكر أكثر من عضو واحد مطلوب ، لذلك بالنسبة إلى فئة مع العناصر العامة (Vals أو DEFS) ، تكون جميع المجموعات الفرعية الممكنة من هؤلاء المطلوبة ، وهذا هو قوى n التي تكون Cardinality 2^n.

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