Можно ли в scala 2 использовать макрос или любую языковую функцию для переписывания механизма реификации абстрактного типа во всех подклассах? Как насчет Scala 3?

В scala 2 известно, что макросы строго локальны и выполняются только один раз, когда класс определен. Эта функция кажется особенно слабой при сочетании с абстрактным типом, поскольку процесс преобразования абстрактных типов в конкретный обычно обходит макрос и использует свои собственные примитивные правила.

Один простой пример, демонстрирующий противоречащий интуиции результат, представлен в следующем тестовом коде:

        trait BB {

    def ttag = implicitly[TypeTag[this.type]]
  }

  case class AA() extends BB

  it("can TypeTag") {

    val kk = AA()

    TypeViz(kk.ttag).peek // this function visualise the full type tree of the type tag
  }

в случае выполнения тип kk оказывается:

      -+ BB.this.type
 !-+ InfoCTSpec.this.BB
   !-+ Object
     !-- Any

К сожалению, тип AA полностью игнорируется, потому что implicitly[TypeTag[this.type]] поддерживается встроенным неявным макросом, который выполняется только ОДИН РАЗ, когда определен BB, а не когда определен AA и реифицирует фактическое kk.this.type. Я считаю его довольно громоздким и склонным к ухудшению некоторых других функций (например, сопоставление с образцом, лямбда-тип) из-за стирания типа во время выполнения.

Я хотел бы написать / использовать расширение языка, например, сделать TypeTag[this.type]подтип AA, БЕЗ введения накладных расходов времени выполнения и объектов контекста вне области видимости (так что БЕЗ ПОСЛЕДСТВИЯ). Как я могу сделать это с наименьшим количеством взлома? Я открыт для очень хардкорных решений, таких как расширение компилятора и макрос, но, очевидно, предпочтительнее элегантный обходной путь, который можно плавно перенести на scala 3/dotty.

PS похоже, что функция dotty «inline / compiletime» частично реализовала то, что я задумал. Это правильное впечатление?

1 ответ

Вы можете писать макросы и плагины компилятора, но обычный механизм для отсрочки неявного разрешения от сайта определения к сайту вызова заключается в замене implicitly с неявным параметром

      trait BB {
  def ttag(implicit tt: TypeTag[this.type]) = tt
}

Почему при неявном разрешении с параметрами типа имеет значение размещение val?

БЕЗ введения накладных расходов времени выполнения и объектов контекста вне области видимости (так что НЕ ПОДРАЗУМЕВАЕТСЯ).

Непонятно, почему вы хотите избежать имплицитов. Последствия разрешаются во время компиляции. Если вы замените это макросами или подключаемыми модулями компилятора, вы в любом случае разрешите имплициты вручную во время компиляции.

Другие вопросы по тегам