Подтвердить что ты не робот

Прокси/делегаты в Scala

Недавно я просмотрел несколько вопросов Scala (например здесь, и здесь), который призывал использовать прокси-серверы, и он возникает не один раз в моей собственной работе. Библиотека Scala имеет ряд прокси-признаков (14, если я правильно подсчитал).

Прокси-классы/черты обычно содержат много шаблонов:

class FooProxy(val self: Foo) extends Foo {
   // added behavior
   def mymethod = ...

   // forwarding methods
   def method1 = self.method1
   def method2(arg: String) = self.method2(arg)
   ...
}

trait Foo {
   def method1: Unit
   def method2(arg: String): Unit
}

Моя первая мысль заключалась в определении признака Proxy[T], который можно было бы использовать следующим образом:

class FooProxy(val self: Foo) extends Proxy[Foo] {
   // added behavior
   def mymethod = ...
}

где trait Proxy[T] extends T. Конечно, на самом деле невозможно определить черту Proxy без магии компилятора.

Моя следующая мысль заключалась в том, чтобы искать плагин компилятора (такая возможность явно отсутствует в существующем компиляторе, или источники для этих 14 прокси-характеристик будут намного меньше). Конечно, я нашел плагин Kevin Wright AutoProxy. Плагин предназначен для решения проблемы с прокси-сервером, а также с другими вариантами использования (включая динамические микшины):

class FooProxy(@proxy val self: Foo) { ... }

К сожалению, похоже, что работа над ним застопорилась в ноябре (2009). Итак, мои вопросы:

  • Продолжается ли работа над плагином AutoProxy?
  • Может ли это найти его в компиляторе?
  • Рассматриваются ли какие-либо другие подходы?
  • Наконец, указывает ли это на значительную слабость в Scala? В конце концов, не удалось бы определить черту Proxy с заданными макросами lisp?
4b9b3361

Ответ 1

Четыре вопроса, четыре ответа

  • Я, хотя семья должна быть первой! Кроме того, другие участвуют в рассмотрении общей проблемы с методами синтеза в плагине компилятора.

  • Если это так, это, скорее всего, будет в другой форме, возможно, без использования аннотаций.

  • Я не знаю каких-либо эквивалентных плагинов, хотя один из проектов-кандидатов на Scala GSOC был частично основан на моем автопрокси-коде. Существует, однако, одно очень чистое решение, которое будет работать в большинстве случаев и вообще не нуждается в компиляторе: вы определяете неявное преобразование из FooProxy в Foo, которое просто возвращает член self; это даст вам большую часть пути. Основные проблемы, связанные с этим подходом, состоят в том, что это сделает жизнь сложнее, если вам нужно использовать свой код на Java, он может быть менее эффективным с точки зрения скорости/памяти, а другой - имплицитом, о котором вы должны знать.

  • Отвратительная часть состоит в том, что почти вся необходимая логика уже доступна в компиляторе, и она используется для mixins, поэтому действительно должен быть элегантный способ обработки задачи.

Ответ 2

Адам Варски недавно опубликовал блог о Макро-ориентированный подход, который может работать в Scala 2.11 и определенно работает с плагином компилятора Macro Paradise в Scala 2.10.

Эта библиотека позволит вам написать

class FooProxy(@delegate wrapped: Foo) extends Foo {
    // added behavior
    def mymethod = ...

    // forwarding methods (generated for you)
    // def method1 = wrapped.method1
    // def method2(arg: String) = wrapped.method2(arg)
}

Проект находится на очень раннем этапе доказывания концепции на момент написания этой статьи, поэтому предостережение оправданно.