2017-04-21 75 views
2

我試圖拿出一個CSV分析器,可以這樣調用:DSL類似的語法在斯卡拉

parser parse "/path/to/csv/file" using parserConfiguration 

凡解析器將包含目標案例類到其中的類CSV文件將被解析成:

class CSVParser[A] { 

     def parse(path: String) = Source.fromFile(fromFilePath).getLines().mkString("\n") 

     def using(cfg: ParserConfig) = ??? How do I chain this optionally??? 
    } 

val parser = CSVParser[SomeCaseClass] 

我設法爬起來的地步,我可以打電話:

parser parse "/the/path/to/the/csv/file/" 

但我不想要運行解析方法,因爲我想要像上面提到的那樣使用像DSL一樣的應用配置!所以這裏有兩條規則。如果調用者不提供parserConfig,我應該可以使用默認運行,但是如果用戶提供了parserConfig,我想應用配置並運行解析方法。我試着用implicits的組合,但不能讓它們正常工作!

有什麼建議嗎?

編輯:因此,該解決方案看起來像這樣按從「西里爾Corpet」評論:

class CSVReader[A] { 
    def parse(path: String) = ReaderWithFile[A](path) 

    case class ReaderWithFile[A](path: String) { 
    def using(cfg: CSVParserConfig): Seq[A] = { 
     val lines = Source.fromFile(path).getLines().mkString("\n") 
     println(lines) 
     println(cfg) 
     null 
    } 
    } 
    object ReaderWithFile { 
    implicit def parser2parsed[A](parser: ReaderWithFile[A]): Seq[A] = parser.using(defaultParserCfg) 
    } 
} 
object CSVReader extends App { 

    def parser[A] = new CSVReader[A] 

    val sss: Seq[A] = parser parse "/csv-parser/test.csv" // assign this to a val so that the implicit conversion gets applied!! Very important to note! 
} 

我想我需要的隱含範圍在這裏我所說的解析器解析的位置,但在同時我不想搞亂我上面的結構!

回答

1

您的parse方法應該只給出部分結果,根本不做任何事情。爲了應對默認implem,你可以使用隱式轉換爲輸出類型:

class CSVParser[A] { 
    def parse(path: String) = ParserWithFile[A](path) 
} 

case class ParserWithFile[A](path: String) { 
    def using(cfg: ParserConfig): A = ??? 
} 

object ParserWithFile { 
    implicit def parser2parsed[A](parser: ParserWithFile[A]): A = parser.using(ParserConfig.default) 
} 

val parser = CSVParser[SomeCaseClass] 
+0

好的!幾乎在那裏,但我怎樣才能把這個組織成適當的結構呢?看看我上面編輯的帖子! – sparkr

+0

你可以看看我編輯過的文章嗎? – sparkr

+0

好的!我終於開始工作了! – sparkr

2

如果你能夠以比parse更高優先級的運營商更換using你能得到它,而無需額外的類型註釋工作。以<<爲例:

object parsedsl { 
    class ParserConfig 
    object ParserConfig { 
    val default = new ParserConfig 
    } 

    case class ParseUnit(path: String, config: ParserConfig) 
    object ParseUnit { 
    implicit def path2PU(path: String) = ParseUnit(path, ParserConfig.default) 
    } 

    implicit class ConfigSyntax(path: String) { 
    def <<(config: ParserConfig) = ParseUnit(path, config) 
    } 

    class CSVParser { 
    def parse(pu: ParseUnit) = "parsing" 
    } 
} 

import parsedsl._ 

val parser = new CSVParser 

parser parse "path" << ParserConfig.default 

parser parse "path" 
+0

感謝您的回覆!但是我不會像這樣做一件破解工作。我仍然喜歡用英文寫作表達。沒有花哨的操作員! – sparkr

+0

我明白我不得不用類型註釋來寫這個,但我仍然喜歡這樣做! – sparkr

+0

我確實認同英文版本更好。但我也認爲不必隱式轉換'parse'的結果會更好。所以這取決於哪個更糟糕:p –