gpt4 book ai didi

scala - DSL 提取案例类字段名称

转载 作者:行者123 更新时间:2023-12-05 00:58:53 24 4
gpt4 key购买 nike

我正在尝试构建 DSL,但遇到了一个问题:它适用于案例类,但我想知道提取案例类字段名称的最简单方法。我想到的一个想法是使用宏来丰富我的 Case 类的类型,但我不想这样做。

trait QueryDSL[CC] {

def meta: CC

implicit object StringIsFieldType extends Field[CC, String] {
def name = "FakeNAME"
}

implicit def implQuery[V](b: V): Query[CC] = new Query[CC](meta)
implicit def implField[V](b: V)(implicit ev: Field[CC, V]): QueryField[CC, V] = new QueryField(ev)
}

case class Query[CC](meta: CC, clauses: List[Clause[_]] = Nil) {

def setProperty[F](clause: CC ⇒ Clause[F]): Query[CC] = copy(clauses = clause(meta) :: clauses)
}

trait Field[V, M] extends scala.AnyRef {
def name: scala.Predef.String
}

abstract class Clause[V](val fieldName: String, value: V)
case class EqClause[V](override val fieldName: String, value: V) extends Clause[V](fieldName, value)

class QueryField[CC, M](field: Field[CC, M]) {
def eqs(v: M) = EqClause(field.name, v)
}

/// #################

case class TestingCaseClass(displayName:String = "Bonjour", active:Boolean = false)
object Testing extends QueryDSL[TestingCaseClass] {
def meta = new TestingCaseClass
}

import Testing._

val query = Testing setProperty(_.displayName eqs "Hallo")

我希望 query.clauses 等于: List(EqClause(displayName,Hallo))
现在它等于:
列表(EqClause(FakeNAME,Hallo))

最佳答案

一些想法

鉴于我正确地设法跟踪了转换流程。你的最后一行

import Testing._
val query = Testing setProperty(_.displayName eqs "Hallo")

带来 QueryDSL 的隐含入范围。为了 Testing获取方法 setProperty它被转换为 Query使用 implQuery .然后 displayName ,为了得到方法 eqs转换为 QueryField使用 implField它本身需要一个类型为 Field[TestingCaseClass, String] 的隐式值.范围内确实存在这种类型的值: StringIsFieldType .它扩展到
val query = Testing.implQuery[QueryDSL[TestingCaseClass]](Testing).setProperty {
(cc : TestingCaseClass) => Testing.implField[String](cc.displayName)(Testing.StringIsFieldType).eqs("Hallo")
}

我想你想要类似的东西
trait Field[CaseClassType, FieldName] {
type typeOfThisField
}

哪里 FieldName将是单例文字类型 String(name) (编译器中的有效类型,但我认为只能使用宏来表达)。

也许你正在寻找什么

使用 shapeless 2.2.5 及其实现 singleton-typed-literals :
import shapeless._

// Clauses

abstract class Clause[V](val fieldName: String, value: V)
case class EqClause[V](override val fieldName: String, value: V) extends Clause[V](fieldName, value)


// Fields

sealed abstract class Field[CC, FieldName] {
// The name of the field
val fieldName: String

// The type of the field
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)
}
}

// Queries

case class Query[CC](meta: CC, clauses: List[Clause[_]] = Nil) {
def setProperty[F](clause: CC ⇒ Clause[F]): Query[CC] = copy(clauses = clause(meta) :: clauses)
}

class QueryField[CC, M](field: Field.Aux[CC, _, M]) {
def eqs(v: M) = EqClause(field.fieldName, v)
}


trait QueryDSL[CC] {

def meta: CC

implicit def implQuery[V](b: V): Query[CC] = new Query[CC](meta)
implicit def implField[fieldName, V](b: V)(implicit ev: Field.Aux[CC, fieldName, V]): QueryField[CC, V] = new QueryField(ev)
}

/// #################


object Example extends App {

case class TestingCaseClass(displayName:String = "Bonjour", active:Boolean = false)

implicit val displayName = Field(Witness("displayName"), (cc : TestingCaseClass) => cc.displayName)
implicit val active = Field(Witness("active") , (cc : TestingCaseClass) => cc.active )


object Testing extends QueryDSL[TestingCaseClass] {
def meta = new TestingCaseClass
}

import Testing._

val queryDisplayName = Testing setProperty(_.displayName eqs "Hallo")
println(s"queryDisplayName = $queryDisplayName")

val queryActive = Testing setProperty(_.active eqs true)
println(s"queryActive = $queryActive")
}

关于scala - DSL 提取案例类字段名称,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31472418/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com