2011-08-15 70 views
4

我對Scala完全陌生。現在,我試圖端口分析器我在標準ML寫信給Scala和具有下面的代碼的問題:Scala案例分類和列表

abstract class Token 
case class Zero extends Token 
case class At extends Token 
//... 

object Tokenizer { 
    def tokenize(seq : List[Char]) : List[Token] = seq match { 
    case List() => error("Empty input") 
    case '0' :: rest => Zero :: tokenize(rest) 
    case '@' :: rest => At :: tokenize(rest) 
    //... 
    } 
} 

在SML我就不必申報記號化的返回類型()方法但似乎Scala需要它,它對我提供的類型不太滿意(它抱怨Zero,At是無效類型,而且它們應該是類型Token)。請注意,我還希望在解析階段在稍後的時間點匹配令牌列表。

我做了一些在網上搜索和stackoverflow本身,看看是否有類似的問題之前已經提出(它看起來很瑣碎),但不知何故我找不到任何東西。我很確定我有一些基本的錯誤,請隨時開導我:)

回答

8

如果你想創建ZeroAt案例類的新實例,那麼就應該使用apply工廠方法來實例化它們(或new關鍵字:new Zero),像這樣(在斯卡拉Zero()會等於Zero.apply()):

case '0' :: rest => Zero() :: tokenize(rest) 

如果你寫的只是Zero(而不是Zero()),那麼你正在使用Zero類的同伴對象,它是由編譯器自動創建。

+0

作爲scala自己新手,我想知道爲什麼它不能在這種情況下編譯?你是否說你不能使用(自動生成的)伴侶對象進行模式匹配?如果是這樣,爲什麼不呢? – Droggl

+1

@Droggl:當你在模式匹配中使用'Zero'時,將會使用'Zero.unapply(...)'方法(它也會自動生成case類的伴隨對象),所以你可以* *在模式匹配中使用'Zero'。問題是伴侶對象不會擴展'Token'類 - 只有'Zero' ** class **擴展它。所有'List'的所有元素都應該是'Token'類。 – tenshi

9

AtZero是類,而不是對象,所以它們本身並不是它們的實例Token。爲什麼你需要指定函數的返回類型是Scala的編譯器無法弄清楚的遞歸函數的類型,你可以閱讀

case object Zero extends Token 
case object At extends Token 

原因是:您可以通過改變從case classcase object解決您的代碼更多有關在這裏:Why does Scala require a return type for recursive functions?

+0

謝謝,但'object'修飾符不會使'Zero'和'At'單例類型?我想多次實例化它們。 –

+0

是的,每個只有一個實例。但是你沒有在你的代碼中實例化它們,你將它們用作對象,所以我想這就是你想要的。否則,只要在'At'和'Zero'前面加上'new',一切都會起作用(或者用'()'後綴)。除非您將某個狀態與每個實例相關聯,否則創建多個實例只會造成浪費,不是嗎? – Theo

+0

你是對的。我過度簡化了代碼並刪除了我的一些狀態。對於那個很抱歉。非常感謝您的解釋。 –