为什么结果不一样,f scala中的插值器

时间:2016-05-04 14:25:45

标签: 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

为什么结果不一样? 我怎么能这样做呢?

3 个答案:

答案 0 :(得分:3)

通过使用f“string”,您声明要创建格式化的字符串。

用f“$ bb $ cc”你使用变量bb和cc,所以它访问它们的字符串

用f“$ bb%07d”你告诉它将bb转换为7位小数的​​数字,如果数字不够大则为0s

进一步帮助理解的例子:

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

答案 1 :(得分:1)

我认为你已经知道了,但要明确:

$用于标记变量引用

%用于格式化引用

通常你使用f插值器:f"$<reference>%<format>"

当你写:

println(f"$bb$cc")

这就是:

  1. Parser识别$bb没有格式化。
  2. Parser识别$cc没有格式化。
  3. $bb
  4. 代替0
  5. $bb
  6. 代替"%07d"

    但是当你写:

    println(f"$bb%07d")
    

    这就是:

    1. Parser使用格式$bb
    2. 识别07d
    3. $bb替换为0,并根据"07d"对其进行格式化,即:7位数字,填0,数字短于7位数。
    4. 您可能已经将此方法视为在C中进行#define cc "%07d"之类的预处理,但事实并非如此。

      我目前还没有意识到将格式存储在单独字符串中的方法。您可以考虑使用基于类的格式化程序。

答案 2 :(得分:0)

字符串插值语法需要字符串文字。

f-interpolator宏的目的是为编译时提供安全保障。

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)
                                   ^