我的函數有1個參數,類型是字符串,但是長度是4,我可以在編譯時驗證這個參數嗎?如何在編譯時使用scala驗證字符串格式
在haskell和F#中有類型級別,它可以在編譯時進行驗證,如nonEmptyList。
如何使它在scala中。我認爲shapless可以做到這一點,但我不明白
感謝您提前建議
我的函數有1個參數,類型是字符串,但是長度是4,我可以在編譯時驗證這個參數嗎?如何在編譯時使用scala驗證字符串格式
在haskell和F#中有類型級別,它可以在編譯時進行驗證,如nonEmptyList。
如何使它在scala中。我認爲shapless可以做到這一點,但我不明白
感謝您提前建議
是的,無形可以做到這一點。也許是這樣的:
def f(s: Sized[IndexedSeq[Char], Nat._4]): ...
雖然你不能直接傳遞字符串。你必須做類似f(Sized('a', 'b', 'c', 'd'))
你不能用香草斯卡拉。
,你可以去爲這個創造的一種特殊類型,最好的方法 -
case class SpecialString(string: String) {
require(string.length == 4)
}
然後,讓你的函數接收SpecialString
作爲參數,而不是String
。
使用宏也是編譯時驗證的選項。看到這個帖子由Arnout恩格倫:http://blog.xebia.com/compile-time-evaluation-scala-macros/
我修改他的例子來定義字符串驗證功能:
object CompileTimeStringCheck {
import scala.language.experimental.macros
// This function exposed to consumers has a normal Scala type:
def stringCheck(s: String): String =
// but it is implemented as a macro:
macro CompileTimeStringCheck.stringCheck_impl
import scala.reflect.macros.blackbox.Context
// The macro implementation will receive a 'Context' and
// the AST's of the parameters passed to it:
def stringCheck_impl(c: Context)(s: c.Expr[String]): c.Expr[String] = {
import c.universe._
// We can pattern-match on the AST:
s match {
case Expr(Literal(Constant(nValue: String))) =>
// We perform the calculation:
val result = normalStringCheck(nValue)
// And produce an AST for the result of the computation:
c.Expr(Literal(Constant(result)))
case other =>
// Yes, this will be printed at compile time:
println("Yow!")
???
}
}
// The actual implementation is regular old-fashioned scala code:
private def normalStringCheck(s: String): String =
if (s.length == 4) return s
else throw new Exception("Baaaaaah!")
}
這裏的漁獲,但:這需要才能使用它來進行編譯,即把它放入一個utils jar或其他東西。再次
import CompileTimeStringCheck._
object Test extends App {
println(stringCheck("yes!"))
}
,看到Arnout恩格倫的帖子更多細節和原溶液(http://blog.xebia.com/compile-time-evaluation-scala-macros/):然後你就可以在以後編譯時使用它。
非常感謝,但這是非常複雜的大聲笑。 –