【问题标题】:Appending a label to immutable case classes in Scala将标签附加到 Scala 中的不可变案例类
【发布时间】:2011-03-28 09:57:42
【问题描述】:

我正在尝试使用包括标签和 goto 在内的命令为小语言创建解析器:

...
lazy val cmds  = opt("{")~>rep(cmd<~opt(";"))<~opt("}") ^^ {...}
lazy val cmd = ("if"~boolexpr~"then"~cmds~"else"~cmds 
   ^^ { case _~b~_~c1~_~c2 => IFCMD(boolexpr,c1
 | ident ~":="~numericLit ^^ {case i1~_~v => ASSIGN(i1,v) }
 | "goto" ~>ident ^^ { case l => GOTO(l) }
 | ident~":"~cmd ^^ { case l~_~c  => <APPENDLABELTO_CORE>
...

GOTOIFCMD 等是扩展抽象类Core 的案例类

为了与功能/scala-like/immutable-objecty 方式保持一致,我认为像这样定义 Core错误

abstract class Core(var label:Option[String] = None )

但允许我用 &lt;APPENDLABELTO_CORE&gt; 替换部分:

 | ident~":"~cmd ^^ { case l~_~c  => c.label = Some(l); c }

谁能指出这样做的“scalaish”方式?

(我试过c copy (label=Some(l)),但抽象基类没有自动复制构造函数)

【问题讨论】:

    标签: scala functional-programming parser-combinators case-class


    【解决方案1】:

    完全可以创建自己的类复制方法:

    abstract class Core(val label: Option[String]) {
      def set(label: Option[String]): Core
    }
    class Impl(label: Option[String] = None) extends Core(label) {
      def set(label: Option[String] = this.label) = new Impl(label)
    }
    

    如此使用:

    scala> val i = new Impl
    i: Impl = Impl@1930ebb
    
    scala> i.label
    res0: Option[String] = None
    
    scala> i.set(label = Some("thing"))
    res1: Impl = Impl@b28f30
    
    scala> res1.label
    res2: Option[String] = Some(thing)
    

    但是,从务实的角度来看,我不会很快就在这里忽略 vars 的使用。对不可变值进行推理更容易,但据我所知,您得到的值在解析器中非常独立。另一种想法是创建一个方法,在最后将所有内容转换为不可变版本,或者如果解析器代码最终将所有数据存储在其他地方,则让它保持可变。

    另一种方法是使抽象类不是抽象的,而是实际上使它成为一个案例类。您可以从案例类派生类(但是,从案例类派生案例类是不可以的)。那么诀窍就是让您可能需要在字段中保存的可变数据:

    abstract class SpecializedStuff { }
    case class ParticularStuff(val i: Int) extends SpecializedStuff
    case class Core(details: SpecializedStuff, label: Option[String] = None)
    class Impl(p: ParticularStuff) extends Core(p)
    
    scala> val i = new Impl( ParticularStuff(5) )
    i: Impl = Core(ParticularStuff(5),None)
    
    scala> i.copy(label = Some("thing"))
    res0: Core = Core(ParticularStuff(5),Some(thing))
    

    【讨论】:

      猜你喜欢
      • 2012-09-19
      • 1970-01-01
      • 2018-08-17
      • 2018-04-28
      • 2013-03-23
      • 1970-01-01
      • 2015-12-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多