Scala中的类型安全字符串插值

Scala中的类型安全字符串插值,scala,type-safety,scala-macros,string-interpolation,scala-macro-paradise,Scala,Type Safety,Scala Macros,String Interpolation,Scala Macro Paradise,受此启发,我想知道是否可以在Scala中使用类型安全的字符串插值(可能使用宏) 例如,我想要这样的东西 def a[A] = ??? val greetFormat = f"Hi! My name is ${a[String]}. I am ${a[Int]} years old" greetFormat.format("Rick", 27) // compiles //greetFormat.format("Rick", false) // does not compile //gree

受此启发,我想知道是否可以在Scala中使用类型安全的字符串插值(可能使用宏)

例如,我想要这样的东西

def a[A] = ???
val greetFormat = f"Hi! My name is ${a[String]}. I am ${a[Int]} years old" 
greetFormat.format("Rick", 27)  // compiles
//greetFormat.format("Rick", false)  // does not compile
//greetFormat.format(27, "Rick") // does not compile
//greetFormat.format("Rick", 27, false) // does not compile
//greetFormat.format("Rick") // does not compile or is curried?

把它包装成一个函数

def greet(name: String, age: Int) = s"Hi! My name is $name.  I am $age years old"

把它包装成一个函数

def greet(name: String, age: Int) = s"Hi! My name is $name.  I am $age years old"

f
字符串插值器已使用宏实现

这可以在REPL中演示:

scala> val b = "not a number"
b: String = not a number

scala> f"$b%02d"
<console>:9: error: type mismatch;
 found   : String
 required: Int
              f"$b%02d"
                 ^
scala>val b=“不是数字”
字符串=不是一个数字
scala>f“$b%02d”
:9:错误:类型不匹配;
找到:字符串
必填项:Int
f“$b%02d”
^

字符串插值器已通过宏实现

这可以在REPL中演示:

scala> val b = "not a number"
b: String = not a number

scala> f"$b%02d"
<console>:9: error: type mismatch;
 found   : String
 required: Int
              f"$b%02d"
                 ^
scala>val b=“不是数字”
字符串=不是一个数字
scala>f“$b%02d”
:9:错误:类型不匹配;
找到:字符串
必填项:Int
f“$b%02d”
^

您可以向f插值器提供隐式:

scala> case class A(i: Int)
defined class A

scala> implicit def atoi(a: A): Int = a.i
warning: there were 1 feature warning(s); re-run with -feature for details
atoi: (a: A)Int

scala> f"${A(42)}%02d"
res5: String = 42
有关详细信息,请参见和解决方案。我花了大约一分钟才想出那个好主意

"a123bc" match {
  case res @ xr"(?<c>a)(?<n>\d+)(?<s>bc)" => assert {
    res.c == 'a' && res.n == 123 && res.s == "bc"
  }
}
但人们认为这对穷人来说太过分了。你必须像另一个答案那样写函数

在窗体中,宏可以看到
“${a[Int]}”
并使用
Int
参数编写函数,实现起来并不困难

f插值器的其他功能包括其他静态错误检查:

scala> f"$b%.02d"
<console>:19: error: precision not allowed
              f"$b%.02d"
                   ^

快速宏可能会发出
(i:Int)=>f“${new Formattable{…}}”

您可以向f-interpolator提供隐式:

scala> case class A(i: Int)
defined class A

scala> implicit def atoi(a: A): Int = a.i
warning: there were 1 feature warning(s); re-run with -feature for details
atoi: (a: A)Int

scala> f"${A(42)}%02d"
res5: String = 42
有关详细信息,请参见和解决方案。我花了大约一分钟才想出那个好主意

"a123bc" match {
  case res @ xr"(?<c>a)(?<n>\d+)(?<s>bc)" => assert {
    res.c == 'a' && res.n == 123 && res.s == "bc"
  }
}
但人们认为这对穷人来说太过分了。你必须像另一个答案那样写函数

在窗体中,宏可以看到
“${a[Int]}”
并使用
Int
参数编写函数,实现起来并不困难

f插值器的其他功能包括其他静态错误检查:

scala> f"$b%.02d"
<console>:19: error: precision not allowed
              f"$b%.02d"
                   ^

快速宏可能会发出
(i:Int)=>f“${new Formattable{…}}”

在大多数情况下可能是更好的设计,但不会回答OPs关于如何以通用方式执行的问题在大多数情况下可能是更好的设计,但不会回答OPs关于如何以通用方式执行的问题。但是,它迫使我为它提供格式化程序,以触发类型检查失败,例如,如果我只是执行
f“$b”
,并且
b
Int
它仍然可以工作。我想要像
f“${a[String]}”
@wrick这样的东西,它实际上与类型安全的字符串插值无关-您想要确保变量符合字符串插值甚至不需要的类型。在任何情况下,使用
f“${a:String}”
f“$b”
都可以轻松完成您想要的操作,我明白了,这只是
f“$b%s”的缩写。但是,它迫使我为它提供格式化程序,以触发类型检查失败,例如,如果我只是执行
f“$b”
,并且
b
Int
它仍然可以工作。我想要像
f“${a[String]}”
@wrick这样的东西,它实际上与类型安全的字符串插值无关-您想要确保变量符合字符串插值甚至不需要的类型。在任何情况下,使用
f“${a:String}”
f“$b”
都可以轻松完成所需的操作,它只是
f“$b%s”