Scala如何“希望”我定义s-expr?在英语中,我们递归地定义s-expr,如下所示:“s-expr是原子或s-exprs列表。”你怎么说在斯卡拉?
我很确定这是错的:
// Scala 2.11.2
trait Sexpr
case class Atom(text: String) extends Sexpr
type List[Sexpr] = Sexpr // To my amazement, the compiler accepts this!
val blah = Atom("blah")
def matchtest(sexpr: Sexpr): Unit = sexpr match {
case blah :: Nil => println(blah) // But the compiler won't accept this
case _ => println("no match")
}
matchtest(List(Atom("blah")))
Either
可能也不适合这种情况,因为那时我必须区分Left
和Right
,这不是重点。
如何制作这样的递归类定义,以便与Scala的其余部分很好地协同工作?
答案 0 :(得分:1)
这样的事可能
trait Sexpr
case class Atom(text: String) extends Sexpr
case class SList(list: Iterable[Sexpr]) extends Sexpr
def matchtest(sexpr: Sexpr): Unit = sexpr match {
case SList(blah :: Nil) => println(blah)
case _ => println("no match")
}
答案 1 :(得分:1)
此link以下列形式描述了S-expresions的Scala解析器:
abstract class SExp
case class SInt(val value : Int) extends SExp { ... }
case class SSymbol(val value : String) extends SExp { ...}
case class STrue() extends SExp { ... }
case class SFalse() extends SExp { ... }
case class SCons(val car : SExp, val cdr : SExp) extends SExp { ... }
case class SNil() extends SExp { ... }
正如另一个答案所观察到的,看起来像列表的东西实际上是一种二叉树形式,如显式SNil和SCons所示,它接受SExp类型的参数。
答案 2 :(得分:0)
问题是type List[Sexpr] = Sexpr
不是您认为的意思。 List
是您使用类型参数定义的类型别名,而不是 List
类。因此,当您尝试将其匹配为List
(类)时,它会失败。写type L[Sexpr] = Sexpr
您需要定义自己的列表类型。但是,使用scala.collection.immutable.List
并不正确。根据维基百科的定义:
s表达式经典地定义为[1]归纳为
- 一个原子,或
- 形式(x.y)的表达式,其中x和y是s-表达式。
醇>
在Scala List
中,x
不是List
(在x :: y
中),不符合上述定义。 S表达式比链表更通用,并且是一种二叉树。 Scala List
是S-expression的特定类型,其中每对的第一个纵坐标是原子,但并非所有S表达式都适合List
。
看起来应该更像这样:
sealed trait SExpr[+A]
case object NilAtom extends SExpr[Nothing]
case class Atom[+A](a: A) extends SExpr[A]
case class Pair[+A](a1: SExpr[A], a2: SExpr[A]) extends SExpr[A]
def matchTest[A](sexpr: SExpr[A]): Unit = sexpr match {
case Pair(a1, a2) => println("Not an Atom")
case _ => println("Atom")
}
用法:
scala> matchTest(Pair(Atom("Test"), NilAtom))
Not an Atom
scala> matchTest(Atom("Test"))
Atom