为什么结果不一样,f 斯卡拉中的插值器

  • 本文关键字:插值 结果 不一样 scala
  • 更新时间 :
  • 英文 :

val bb =0
val cc ="%07d"
println(f"$bb$cc")  //0%07d
println(f"$bb%07d") //0000000

我期待

println(f"$bb$cc"(//0000000

println(f"$bb%07d"(//0000000

为什么结果不一样?我怎样才能让它一样?

通过使用 f"string",您声明要制作格式化字符串。

使用 f"$bb$cc",您正在使用变量 bb 和 cc,因此它访问它们的字符串

使用 f"$bb%07d",您告诉它将 bb 转换为小数点后 7 位的数字,如果数字不够大,则转换为 0

有助于理解的更多示例:

val bb = 1
println(f"$bb%07d") // 0000001
println(f"$bb%05d") // 00001
val bb = 11
println(f"$bb%05d") //00011

要获取相同的字符串,请尝试使用 s"string">

val bb = 0
println(s"$bb%07d") // 0%07d

使用字符串作为格式化程序:

val cc = "%07d"
val bb = 0
println(cc.format(bb)) //0000000

欲了解更多信息 http://docs.scala-lang.org/overviews/core/string-interpolation.html

我想你已经知道了,但要清楚:

$用于标记变量引用

%用于格式化引用

通常你使用 f 插值器,如下所示: f"$<reference>%<format>"

当你写:

println(f"$bb$cc")

这是发生的情况:

  1. 解析器识别$bb,没有格式。
  2. 解析器识别没有格式的$cc
  3. 0代替$bb
  4. "%07d"代替$bb

但是当你写:

println(f"$bb%07d")

这是发生的情况:

  1. 解析器通过格式化07d识别$bb
  2. 0代替$bb并根据"07d"格式化,即:7 位数字,用 0 填充是数字短于 7 位数字。

您可能认为此方法像 C 中的#define cc "%07d"一样进行预处理,但事实并非如此。

我目前不知道将格式存储在单独的字符串中的方法。您可以考虑使用基于类的格式化程序来执行此操作。

字符串内插语法需要字符串文本。

f插值器宏的要点是提供编译时安全性。

scala> val x = 0.1
x: Double = 0.1
scala> f"$x"
res0: String = 0.1
scala> f"$x%5.5f"
res1: String = 0.10000
scala> f"$x%5d"
<console>:13: error: type mismatch;
 found   : Double
 required: Int
       f"$x%5d"
          ^
scala> val fmt = "%5d"
fmt: String = %5d
scala> fmt format x
java.util.IllegalFormatConversionException: d != java.lang.Double
  at java.util.Formatter$FormatSpecifier.failConversion(Formatter.java:4302)
  at java.util.Formatter$FormatSpecifier.printInteger(Formatter.java:2793)
  at java.util.Formatter$FormatSpecifier.print(Formatter.java:2747)
  at java.util.Formatter.format(Formatter.java:2520)
  at java.util.Formatter.format(Formatter.java:2455)
  at java.lang.String.format(String.java:2940)
  at scala.collection.immutable.StringLike$class.format(StringLike.scala:318)
  at scala.collection.immutable.StringOps.format(StringOps.scala:29)
  ... 32 elided

这不方便,但您可以分解字符串常量并手动滚动:

scala> final val fmt = "%5d"
fmt: String("%5d") = %5d
scala> new StringContext("", fmt).f(x)
<console>:14: error: type mismatch;
 found   : Double
 required: Int
       new StringContext("", fmt).f(x)
                                    ^

scala> final val fmt = "%5.5f"
fmt: String("%5.5f") = %5.5f
scala> new StringContext("", fmt).f(x)
res8: String = 0.10000
scala> final val fmt = "%5.5"
fmt: String("%5.5") = %5.5
scala> new StringContext("", fmt + "f").f(x)
res9: String = 0.10000
scala> new StringContext("", fmt + "d").f(x)
<console>:14: error: precision not allowed
       new StringContext("", fmt + "d").f(x)
                                   ^
scala> final val fmt = "%5"
fmt: String("%5") = %5
scala> new StringContext("", fmt + "d").f(x)
<console>:14: error: type mismatch;
 found   : Double
 required: Int
       new StringContext("", fmt + "d").f(x)
                                          ^

如果您尝试使用非常量字符串,则会出现错误:

scala> val fmt = "%5d"
fmt: String = %5d
scala> new StringContext("", fmt).f(x)
<console>:14: error: exception during macro expansion:
java.lang.IllegalArgumentException: internal error: argument parts must be a list of string literals
    at scala.tools.reflect.FormatInterpolator.scala$tools$reflect$FormatInterpolator$$copyPart$1(FormatInterpolator.scala:82)
    at scala.tools.reflect.FormatInterpolator.interpolated(FormatInterpolator.scala:181)
    at scala.tools.reflect.FormatInterpolator.interpolate(FormatInterpolator.scala:38)
    at scala.tools.reflect.FastTrack$$anonfun$1$$anonfun$apply$5$$anonfun$applyOrElse$5.apply(FastTrack.scala:54)
    at scala.tools.reflect.FastTrack$$anonfun$1$$anonfun$apply$5$$anonfun$applyOrElse$5.apply(FastTrack.scala:54)
    at scala.tools.reflect.FastTrack$FastTrackEntry.apply(FastTrack.scala:41)
    at scala.tools.reflect.FastTrack$FastTrackEntry.apply(FastTrack.scala:36)
    at scala.tools.nsc.typechecker.Macros$class.macroExpandWithRuntime(Macros.scala:763)
       new StringContext("", fmt).f(x)
                                   ^

最新更新