চতুর্মুখীতে শেপলেস কীভাবে ব্যবহার করবেন?


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) এর জন্য কোনও ধরণের টিকা প্রদানের চেষ্টা করেছেন ?
ট্র্যাভিস ব্রাউন 17

@ ট্র্যাভিস ব্রাউন হ্যাঁ আমি ম্যাক্রো টিকা (ম্যাক্রো প্যারাডাইস) ব্যবহার করে এটি নির্মাণ করছি। আমি এর মতো প্রকারটি দেওয়ার চেষ্টা করেছি: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}"
      }
    }
  }
}

এটি নিশ্চিতভাবে আরও ভাল কোয়াসিকোট ব্যবহার করে উন্নত হতে পারে, তবে আমার লক্ষ্যটি যথাসম্ভব ক্লিনার হিসাবে দেখানো ছিল।

এটি হিসাবে ব্যবহার করা যেতে পারে:

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

যেমন এটি ইতিমধ্যে চিহ্নিত করা হয়েছিল, একটি সম্পূর্ণ কার্যকারণ উদাহরণ ছাড়াই, একটি বিস্তৃত উত্তর লেখার পক্ষে এটি বেশ কঠিন।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.