gpt4 book ai didi

validation - 通过 for-comprehension 线程 `Try` s

转载 作者:行者123 更新时间:2023-12-03 17:18:51 25 4
gpt4 key购买 nike

another question 触发(尽管后来被编辑掉了),我想尝试将调用链接到 Scala 2.10 的 Try 是多么容易。构造(参见 this presentation ),使用 for-comprehensions。

这个想法是有一个标记列表并将它们与一系列模式匹配,然后返回第一个错误或成功匹配的模式。我得到了以下非常尴尬的版本,我想知道这是否可以变得更简单更好:

import util.Try

trait Token
case class Ident (s: String) extends Token
case class Keyword(s: String) extends Token
case class Punct (s: String) extends Token
case object NoToken extends Token
case class FunctionDef(id: Ident)

case class Expect[A](expectation: String)(pattern: PartialFunction[Token, A]) {
def unapply(tup: (Try[_], Token)) = Some(tup._1.map { _ =>
pattern.lift(tup._2).getOrElse(throw new Exception(expectation))
})
}

现在构建对 Keyword("void") :: Ident(id) :: Punct("(") :: Punct(")") :: tail 的期望
val hasVoid   = Expect("function def starts with void") { case Keyword("void") => }
val hasIdent = Expect("expected name of the function") { case id: Ident => id }
val hasOpen = Expect("expected opening parenthesis" ) { case Punct("(") => }
val hasClosed = Expect("expected closing parenthesis" ) { case Punct(")") => }

构建一个完整的测试用例:
def test(tokens: List[Token]) = {
val iter = tokens.iterator
def next(p: Try[_]) = Some(p -> (if (iter.hasNext) iter.next else NoToken))
def first() = next(Try())

val sq = for {
hasVoid (vd) <- first()
hasIdent (id) <- next(vd)
hasOpen (op) <- next(id)
hasClosed(cl) <- next(op)
} yield cl.flatMap(_ => id).map(FunctionDef(_))

sq.head
}

下面验证测试方法:
// the following fail with successive errors
test(Nil)
test(Keyword("hallo") :: Nil)
test(Keyword("void" ) :: Nil)
test(Keyword("void" ) :: Ident("name") :: Nil)
test(Keyword("void" ) :: Ident("name") :: Punct("(") :: Nil)
// this completes
test(Keyword("void" ) :: Ident("name") :: Punct("(") :: Punct(")") :: Nil)

现在特别是额外的 flatMapmapyield看起来很可怕,还有需要打电话 head关于理解的结果。

有任何想法吗?是 Try非常不适合理解?也不应该 EitherTry是否“固定”以允许这种类型的线程(例如,允许 Try 作为 unapply 的直接结果类型)?

最佳答案

诀窍似乎是不创建 Try内部结构中的实例,而是让它抛出异常并构造一个外部 Try .

首先,让我们摆脱 Try[Unit]的:

case class Expect(expectation: String)(pattern: PartialFunction[Token, Unit]) {
def unapply(token: Token) =
pattern.isDefinedAt(token) || (throw new Exception(expectation))
}

case class Extract[A](expectation: String)(pattern: PartialFunction[Token, A]) {
def unapply(token: Token) = Some(
pattern.lift(token).getOrElse(throw new Exception(expectation))
)
}

然后检查变成:
val hasVoid   = Expect ("function def starts with void") { case Keyword("void") => }
val getIdent = Extract("expected name of the function") { case id: Ident => id }
val hasOpen = Expect ("expected opening parenthesis" ) { case Punct("(") => }
val hasClosed = Expect ("expected closing parenthesis" ) { case Punct(")") => }

以及测试方法:
def test(tokens: List[Token]) = Try {
val iter = tokens.iterator
def next() = Some(if (iter.hasNext) iter.next else NoToken)

(for {
hasVoid() <- next()
getIdent(id) <- next()
hasOpen() <- next()
hasClosed() <- next()
} yield FunctionDef(id)).head // can we get rid of the `head`?
}

关于validation - 通过 for-comprehension 线程 `Try` s,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11990017/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com