कैसे Quasiquote में Shapeless का उपयोग करें?


272

मैं एक कॉल करने के लिए कोशिश कर रहा हूँ Shapelessके अंदर एक से मैक्रो quasiquoteके साथ Scalaहै और मैं नहीं मिल रहा है मैं प्राप्त करना चाहते हैं क्या।

मेरे मैक्रो किसी भी त्रुटि वापस नहीं करता है, लेकिन यह विस्तार नहीं करता है Witness(fieldName)मेंWitness.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)"""
}

यहाँ मेरी Fieldपरिभाषा है:

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)
    }
}

इस मामले में मेरे द्वारा उत्पन्न निहितार्थ इस प्रकार है:

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

अगर इसे बाहर परिभाषित किया गया है तो यह quasiquoteकुछ उत्पन्न करेगा:

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

क्या ऐसा कुछ है जो किया जा सकता है?


क्या आप मैक्रो एनोटेशन में इसका उपयोग कर रहे हैं? क्या आपने $in(जो मुझे लगता है कि उपयोग करने की आवश्यकता होगी ConstantType) के लिए एक प्रकार का एनोटेशन प्रदान करने की कोशिश की है ?
ट्रैविस ब्राउन

@TravisBrown हाँ, मैं इसे मैक्रो एनोटेशन (मैक्रो पैराडाइज़) का उपयोग करके बना रहा हूँ। मैंने इस तरह का एक प्रकार प्रदान करने की कोशिश की है:q"""implicit val $in : Field.Aux[$className, Witness.Lt[String]#T, String] = Field.apply[$className,$fieldType](Witness($fieldName), ($cc: $className) => $cc.$tn)"""
रोच

आप प्रकार एनोटेशन में, विशिष्ट क्षेत्र नाम की आवश्यकता है, हालांकि (जैसे मेरे पुराने पूर्व निराकार 2.0 ब्लॉग पोस्ट देखेंगे यहाँ का उपयोग करने का एक उदाहरण के लिए ConstantType)। क्या आपके पास काम करने का एक पूरा उदाहरण है?
ट्रैविस ब्राउन

जवाबों:


1

यह पुरानी शैली के मैक्रो एनोटेशन का उपयोग करके मेरा काम करने वाला समाधान है।

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}"
      }
    }
  }
}

यह, निश्चित रूप से, बेहतर quasiquotes का उपयोग करके सुधार किया जा सकता है, लेकिन मेरा लक्ष्य संभव के रूप में क्लीनर के रूप में कुछ दिखाना था।

इसका उपयोग इस प्रकार किया जा सकता है:

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

यह MyCaseClassआवश्यक वस्तु होने के साथ एक साथी वस्तु का उत्पादन करता है Fields:

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));

जैसा कि यह पहले से ही बताया गया था, पूर्ण कार्य उदाहरण के बिना, एक विस्तृत उत्तर लिखना काफी मुश्किल है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.