【问题标题】:Scala Map ParserScala 地图解析器
【发布时间】:2012-04-25 04:53:30
【问题描述】:

我想构建一个可以接受 Map 输入并输出 Case 类的 Parser。现在我有一些似乎没有利用 FP 的命令式代码。我只是看不到如何构建可以输出 Case 类的 Parser。

这是我所拥有的:

def fromMap(m: Map[String,AttributeValue]): User =  {
    val id = m.get("user-id") map {_.getS}
    val email = m.get("email").get.getS
    val name = m.get("name").get.getS
    val openId = m.get("openId") map {_.getS}
    User(id, email, name, openId)
}

更新: 我想我应该更清楚我想做一些类似于 Anorm 的事情,但使用 scala 中的 Parser Combinators。上面的问题是不灵活或不可重用。调用者必须拿走他们得到的东西。

我希望解析器组合器将是解析 Map 形式结果的正确方法。正如您可能已经猜到的那样,我正在使用 DyanmoDB。

更新 2: 显然我不能很好地解释这个问题。我要做的就是编写一个或多个 Pareser 组合器,它们可以使用调用者指定的绑定将 Map 转换为调用者选择的 Case 类。输入映射 => 输出案例类

更新 3: https://github.com/wfaler/scala-dynamo 看起来很有趣,但不使用解析器组合器。

【问题讨论】:

  • 是的。我正在尝试将发电机结果绑定到案例类。
  • 我不明白你的更新。你的输入值是什么,最后你想得到什么?
  • 输入值是一个 Map[String,AttributeValue]。我想创建一个解析器,以便编写可以将其映射到案例类(在本例中为用户)的函数。

标签: parsing scala map case parser-combinators


【解决方案1】:

@4e6 的类似答案,但仅使用 Scalas 内置方法实现:

case class User(id: String, email: String, name: String, openId: String)

val m = Map("user-id" -> "123", "email" -> "test@test.org", "name" -> "testuser", "openId" -> "456")

def fromMap(m: Map[String, String]): Option[User] = for {
  id <- m get "user-id"
  email <- m get "email"
  name <- m get "name"
  openId <- m get "openId"
} yield User(id, email, name, openId)

scala> fromMap(m)
res0: Option[User] = Some(User(123,test@test.org,testuser,456))

【讨论】:

  • 一旦尝试,我对 scalaz 印象深刻,随着时间的推移,我开始思考它有时会忘记核心 scala 功能:)
  • 这会返回一个Option。这很好,你应该提到它。
  • 我需要避免使用 scalaz,但请参阅上面关于 Parser Combinators 的更新。这只是一个让它工作的功能。我不认为这是一个好的设计。
【解决方案2】:

我认为 scalaz ApplicativeBuilder 是您正在寻找的。此外,最好返回 Option 作为避免异常的方法。不知道getS是什么,所以你的sn-p的简化版本可能是:

case class User(val id: String, val email: String, val name: String, val OpenId: String)

def fromMap(m: Map[String, String]): Option[User] = {
  val id = m.get("user-id")
  val email = m.get("email")
  val name = m.get("name")
  val openId = m.get("openId")
  id |@| email |@| name |@| openId apply User
}

为避免混淆,ApplicationBuilderapply 方法实际上接受了一个函数,所以详细的版本是

(id |@| email |@| name |@| openId) { (id, email, name, openId) =>
  new User(id, email, name, openId)
}

更多applicatives示例可以查看here

【讨论】:

  • 我需要避免使用 scalaz,但请参阅上面关于 Parser Combinators 的更新。这只是一个让它工作的功能。我不认为这是一个好的设计。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-01-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-24
  • 2011-07-01
相关资源
最近更新 更多