【问题标题】:dsl for capturing field name用于捕获字段名称的 dsl
【发布时间】:2014-11-22 23:24:20
【问题描述】:

我正在开发一个映射器,想要一种类型安全的方法来捕获类字段名以进行映射,并使用我在 C# 中使用的语法:

case class Person(name: String, age: Int)

new Mapping[Person]() { 
  field(_.age).name("person_age").colType[java.lang.Integer]
  field(_.name).name("person_name")
}

在哪里def field(m: T => Unit): FieldMap

这会触发以下警告:

Warning:(97, 13) a pure expression does nothing in statement position; you may be omitting necessary parentheses
field(_.age).name("person_age").colType[java.lang.Integer]
        ^
Warning:(98, 13) a pure expression does nothing in statement position; you may be omitting necessary parentheses
field(_.name).name("person_name")
        ^

很明显,这不是一个理想的语法。有什么方法可以调整 field 的签名以避免警告,还是有更惯用的 scala 方式以类型安全的方式映射字段?

注意: @sjrd 的回答确实消除了警告,但尝试的功能似乎并不适用于 scala 反射。我的最终目标是一个 Mapper,它允许以编译时检查的方式指定 T 成员,而不是字符串,因此它不太容易受到拼写错误和重构问题的影响。

【问题讨论】:

    标签: scala reflection


    【解决方案1】:

    field 方法将T => Unit 函数作为参数。因此,等效于 x => x.age 的 lambda _.age 被类型检查为返回 Unit。编译器警告你在语句位置使用了纯表达式(x.age)(预期类型为Unit),这基本上意味着该表达式是无用的,不妨将其删除。

    您的问题有一个非常简单的对症解决方案:将m: T => Unit 替换为m: T => Any。现在您的表达式 x.age 不再处于语句位置,编译器很高兴。

    但是您的代码表明存在更深层次的错误,因为您显然没有在任何地方使用m 的结果。为什么m 仍然存在?

    【讨论】:

    • 这确实解决了警告。然而,我试图复制的 C# 技巧毕竟行不通。 field 从来没有对 m 做任何事情的原因是它应该只存在于以编译检查方式指定 T 成员的副作用,然后通过反射挑选出引用的字段映射。在 C# 中,T => Any 将是一个要检查的表达式。看不到通过 scala 的反射起作用:(
    • 也许你想要宏?宏可以检查其应用程序的树(我想相当于 Expression)。
    • 在看到 Slick 的 Direct Embedding 之后,一直在看宏。看起来这也是比反射更好的方法和更快的方法。谢谢。
    猜你喜欢
    • 2013-02-03
    • 2012-05-14
    • 1970-01-01
    • 1970-01-01
    • 2021-08-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多