使用注释+宏或外部脚本生成Scala代码?

时间:2015-01-10 21:55:30

标签: scala

我想知道:

  1. Scala注释/转换可以实现下面的代码生成吗? (目标)
  2. 与使用外部工具生成源代码相比,有哪些权衡取舍? (目标)
  3. 有更好的方式/你会怎么做? (主观)
  4. 背景:

    我正在为Scala + Java设计嵌入式数据库作为辅助项目。虽然我希望它可以从Java中使用,但是我在Scala中编写它以获得额外的灵活性/功能,并且因为编写Java代码会使我的灵魂死亡。

    我正在研究我想要的模型定义。我最初的想法是解析一些模型定义文件并生成Scala类。但是我认为现在我希望它们可以在Scala代码中定义,这样就不需要解析,人们可以充分利用Scala来定义和定制模型(例如自定义列类型)。&#39 ;我的Python / Django体验中的一个有价值的功能。

    到目前为止,我有类似的内容:

    @model
    class Person {
      val Name = StringColumn(length=32)
      val BirthDate = DateColumn(optional=true)
    }
    
    @model
    class Student extends Person {
      val GPA = FloatColumn(propertyName="gpa")
    }
    
    @model
    class Teacher extends Person {
      val salary = NumericColumn()
    }
    

    哪会产生:

    class Person {
      val Name = StringColumn(name="name", length=32)
      val BirthDate = DateColumn(name="birthDate", optional=true)
    
      // generated accessor methods
      def name = Person.Name.get(...)
      def name_= (name : String) : Unit = Person.Name.set(..., name)
      // etc ...
    }
    
    // static access to model metadata, e.g. Person.Name is an immutable StringColumn instance
    object Person extends Person
    
    class Student extends Person {
      val GPA = DoubleColumn(name = "GPA")
    
      def gpa = ...
      def gpa_= (value : Float) = ...
    }
    
    object Student extends Student
    
    class Teacher extends Person {
      // You get the idea
    }
    
    object Teacher extends Teacher
    

    在线查看一些示例并进行一些研究,似乎使用特殊的@model注释进行AST转换实际上可以生成所需的代码,可能需要一些帮助,例如:让用户定义对象以及模型定义。我是对的,这可以做到吗?

    这个想法让我遇到了一些问题:

    1. 对象将混乱使用无用的属性,它只需要Column对象。这可以通过将类拆分为两个类来修复,PersonMeta和Person扩展PersonMeta,Person对象仅扩展PersonMeta。
    2. IDE可能不会接收生成的属性,导致它们用波浪线(eww ...)为它们加下划线,并使其对于无法工作的属性名称进行自动完成。代码仍然是编译时检查的,所以它实际上只是一个IDE陷阱(动态,毫无疑问,有同样的问题。)
    3. 使用脚本生成代码更加适合IDE,但它很麻烦,可能需要更多工作,尤其是因为您必须保留自定义方法和事物。它还需要一个自定义构建步骤,您必须在更改模型时运行(这意味着您可能忘记执行此操作。)虽然IDE可能无法帮助您生成宏代码(但无论如何),编译器会对您大喊大叫如果你弄错了。这使我倾向于使用宏+注释。

      你怎么看?我是Scala的新手,我有点怀疑我是如何定义模型并为它们生成实现的最佳方法。你会怎样做得更好?

1 个答案:

答案 0 :(得分:1)

可能是的。编写和调试宏可能会令人不愉快,但它们确实有效。

  1. 好像你已经有了解决方案

  2. Scala IDE倾向于正确处理宏(我的意思是,他们必须,他们是语言的一部分,并在一些非常基础的库中使用),所以我不担心;如果有任何宏比外部代码步更加理想,因为宏将与用户的更改保持同步。

  3. 在使用宏之前,我会看看你是否可以在vanilla scala中实现你想要的东西。请记住,类似于类的东西不一定是实际的案例类;看看Shapeless generic records,了解如何从外部某处表示一个类型良好的“行”命名值。我认为一个能够将这些记录与SQL之间的结构映射到一起的系统最终可能比基于“特殊”案例类的系统更具原则性(即更易于推理)。