Shapeless bir Quasiquote içinde nasıl kullanılır?


272

Bir aramaya çalışıyorum Shapelessiçeride a gelen makro quasiquoteile Scalave ben almak istiyorum alamıyorum.

Benim makro hataları dönmez ama genişletmek değil Witness(fieldName)içineWitness.Lt[String]

val implicits = schema.fields.map { field =>
  val fieldName:String = field.name
  val fieldType = TypeName(field.valueType.fullName)
  val in = TermName("implicitField"+fieldName)
  val tn = TermName(fieldName)
  val cc = TermName("cc")
  q"""implicit val $in = Field.apply[$className,$fieldType](Witness($fieldName), ($cc:   $className) => $cc.$tn)"""
}

İşte benim Fieldtanımım:

sealed abstract class Field[CC, FieldName] {
  val  fieldName: String
  type fieldType

  // How to extract this field
  def  get(cc : CC) : fieldType
}

object Field {
  // fieldType is existencial in Field but parametric in Fied.Aux
  // used to explict constraints on fieldType
  type Aux[CC, FieldName, fieldType_] = Field[CC, FieldName] {
    type fieldType = fieldType_
  }

  def apply[CC, fieldType_](fieldWitness : Witness.Lt[String], ext : CC => fieldType_) : Field.Aux[CC, fieldWitness.T, fieldType_] =
    new Field[CC, fieldWitness.T] {
      val fieldName  : String = fieldWitness.value
      type fieldType = fieldType_
      def get(cc : CC) : fieldType = ext(cc)
    }
}

Bu durumda oluşturduğum örtük şöyle görünür:

implicit val implicitFieldname : Field[MyCaseClass, fieldWitness.`type`#T]{
  override type fieldType = java.lang.String
}

Dışında tanımlanmış quasiquoteolsaydı, şöyle bir şey üretirdi:

implicit val implicitFieldname : Field.Aux[MyCaseClass, Witness.Lt[String]#T, String] = ...

Yapılacak bir şey var mı?


Bunu bir makro ek açıklamada mı kullanıyorsunuz? $in(Kullanmayı gerektireceğini düşündüğüm) için bir tür ek açıklama sağlamayı denediniz ConstantTypemi?
Travis Brown

@TravisBrown evet Bunu bir makro ek açıklama (Macro Paradise) kullanarak yapıyorum. Böyle bir tür sağlamaya çalıştım:q"""implicit val $in : Field.Aux[$className, Witness.Lt[String]#T, String] = Field.apply[$className,$fieldType](Witness($fieldName), ($cc: $className) => $cc.$tn)"""
Roch

(Benim eski öncesi Biçimsizler 2.0 blog yazısı örneğin bkz olsa Sen, tür ek açıklaması belirli alan adı gerekir burada kullanarak bir örnek için ConstantType). Etrafta tam bir çalışma örneği var mı?
Travis Brown

Yanıtlar:


1

Bu benim eski çözüm makro ek açıklamalarını kullanan çalışma çözümüm.

import scala.language.experimental.macros
import scala.reflect.macros.blackbox.Context
import scala.annotation.StaticAnnotation

class fieldable extends StaticAnnotation {
  def macroTransform(annottees: Any*): Any = macro fieldableMacro.impl
}

object fieldableMacro {
  def impl(c: Context)(annottees: c.Expr[Any]*): c.Tree = {
    import c.universe._
    annottees.map(_.tree) match {
      case (param @ q"case class $className(..$fields)") :: Nil => {
        val implicits = fields.collect {
          case field @ q"$mods val $tname: $tpt" => q"""
            implicit val $tname = Field.apply[$className,$tpt](
              Witness(${tname.decodedName.toString}), _.$tname
            )"""
        }; q"$param; object ${className.toTermName} {..$implicits}"
      }
    }
  }
}

Elbette, daha iyi quasquotes kullanarak geliştirilebilir, ancak amacım mümkün olduğunca daha temiz bir şey göstermekti.

Şu şekilde kullanılabilir:

@fieldable
case class MyCaseClass(foo: String, bar: Int)

Bu, MyCaseClassgerekli Fieldsetkileri olan bir tamamlayıcı nesne üretir :

implicit val foo = Field.apply[MyCaseClass, String](Witness("foo"), ((x$1) => x$1.foo));
implicit val bar = Field.apply[MyCaseClass, Int](Witness("bar"), ((x$2) => x$2.bar));

Daha önce de belirtildiği gibi, tam bir çalışma örneği olmadan, kapsamlı bir cevap yazmak oldukça zordur.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.