我在想是否可以在Scala中实现类型安全的printf
。假设我们只需要支持字符串文字,%s 和%d
我希望printf("This is number %d", 0)
能够被编译,但printf("This is number %d", "abc")
不会被编译。
我希望printf
在编译时检查参数的数量。因此printf("This is a literal")
会被编译,但printf("This is number %d and string %s", 0)
不会。
我已经看到它可以用宏来完成。是否绝对有必要实现类型安全的printf
?
答案 0 :(得分:5)
Scala的f
字符串格式化程序已经是一种类型安全的printf
。它是使用宏实现的。例如:
scala> val s = "not a number"
s: String = not a number
scala> f"$s%d"
<console>:9: error: type mismatch;
found : String
required: Int
f"$s%d"
^
答案 1 :(得分:2)
这是尝试在没有宏的情况下实现这样的事情。可能有一种不那么丑陋的方式......应该添加一些额外的方法以使其更方便。
import scala.language.implicitConversions
package test {
sealed trait End
sealed trait Prove[T]
object Prove{
implicit object EndProve extends Prove[F[End,End]]
}
class F[A,B](ss: List[String]){
def _d(s: String) = new F[Int,F[A,B]](s :: ss)
def _s(s: String) = new F[String,F[A,B]](s :: ss)
}
}
package object test {
implicit def string2F(s: String) = new F[End,End](List(s))
def printf[A,B](a: A)(f: F[A,B])(implicit ev: Prove[B]) = ???
def printf[A,B,C](b: B, a: A)(f: F[A,F[B,C]])(implicit ev: Prove[C]) = ???
def printf[A,B,C,D](c: C, b: B, a: A)(f: F[A,F[B,F[C,D]]])(implicit ev: Prove[D]) = ???
// and so on...
}
正如您所看到的那样(如果您实施实际打印):
scala> import test._
import test._
scala> printf(4, "string")("a digit: " _d " and a String: " _s ".") // compiles
scala.NotImplementedError: an implementation is missing
scala> printf(4, 6)("a digit: " _d " and a String: " _s ".") // doesn't compile
<console>:11: error: type mismatch;
scala> printf(4)("a digit: " _d " and a String: " _s ".") // doesn't compile
<console>:11: error: type mismatch;