2016-01-15 27 views
1

Scala如何「想」讓我定義s-expr?在英文中,我們遞歸地定義s-expr,如下所示:「s-expr是一個原子或s-exprs的列表。」你怎麼說在斯卡拉?在Scala中定義s-expr的習慣方式

我敢肯定,這是錯誤的:

// 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可能不是很適合這個,或者說,從那以後,我不得不LeftRight區分,這是題外話。

你如何使這樣的遞歸類定義,以便它與Scala的其餘部分很好地工作?

+0

這個Scala S-expr解析器(帶有SNil和SCons的專業概念)是否包含您所需的內容:http://matt.might.net/articles/parsing-s-expressions-scala/ – NietzscheanAI

+0

@ user217281728是的。哇!這甚至解決了我實際上在做什麼,我認爲這是太多的問題:在一個更大的Scala程序中實現簡單的類似Scheme的語言。 –

+0

作爲獎勵,我認爲該網站也有M表達式... – NietzscheanAI

回答

0

問題是type List[Sexpr] = Sexpr是不是你認爲它的意思。 List是您使用類型參數定義的類型別名,而不是List類。因此,當您嘗試將它匹配爲List(該類)時,它會失敗。這將是沒有什麼不同,寫type L[Sexpr] = Sexpr

你需要定義自己的列表類型。雖然使用scala.collection.immutable.List是不正確的。根據維基百科定義:(x和y)

s表達式經典地定義[1]電感作爲

  1. 的原子,或
  2. 形式的表達,其中x和y是s表達式。

在Scala中ListxList(在x :: y)一個,這不符合上面的定義。 S表達式比鏈表更普遍,是一種二叉樹。斯卡拉List是一個特定類型的S表達式,其中每對的第一縱座標是一個原子,但不是所有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 
+0

這是不回答原來的問題:它是關於*列表*,而不是對。 – Dima

+1

@Dima您是否閱讀過OP提供的鏈接? **列表**和**鏈接列表**是**不是**相同的東西。 OP詢問了如何在Scala中定義一個s表達式,並且他錯誤地認爲它會像一個scala「List」,但事實並非如此。請閱讀關於s表達式實際是什麼。 –

+0

的確,我只是在尋找一種「Scalastic」的方式來定義sexprs,並沒有限制如何。這個答案已經非常有價值了,僅僅通過用'List'做某件事來讓我從思想中解放出來。這個答案回答了更深層次的問題,即如何在Scala中定義遞歸數據結構。 (不巧的是,'List'是用相同的方法定義的。)因此+1。 :) –

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") 
} 
+0

這不是真的正確。 S表達式的定義所指的「list」是不必要的像'scala.collection.immutable.List'這樣的鏈表,它比這更通用。 –

+0

好點。將其更改爲'Iterable'。 – Dima

+0

'Iterable'實際上並不是更好,事實上'Iterable'完全不符合s表達式的定義。一般來說,它不是遞歸的。 –

1

link介紹Scala的解析器爲以下形式S-expresions:

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。

相關問題