Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala 动态字符串插值_Scala_String Interpolation - Fatal编程技术网

Scala 动态字符串插值

Scala 动态字符串插值,scala,string-interpolation,Scala,String Interpolation,我想漂亮地打印产品,例如案例类,因此我创建了以下特性: trait X extends Product { def fmtStrs = productIterator map { case _ : Double => "%8.2f" case _ => "%4s" } map (_ + separator) toSeq override def toString = { new StringCon

我想漂亮地打印
产品
,例如
案例类
,因此我创建了以下特性:

  trait X extends Product {
    def fmtStrs =
      productIterator map {
        case _ : Double => "%8.2f"
        case _ => "%4s"
      } map (_ + separator) toSeq
    override def toString = {
      new StringContext("" +: fmtStrs : _*) f (productIterator.toSeq : _*)
    }
  }
这使用了ScalaDoc for中描述的字符串插值

但这不会编译,有一个神秘的错误:

Error:(69, 70) too many arguments for interpolated string
      new StringContext("" +: fmtStrs : _*) f (productIterator.toSeq : _*)
这是错误还是宏的限制?请注意,执行以下操作效果良好,因此我怀疑这可能与变量参数列表有关:

scala> val str2 = StringContext("","%4s,","%8.2f").f(1,23.4)
str2: String = "   1,   23.40"

之所以
f
是一个宏,是因为当格式说明符和参数的类型不匹配时,它会给您一个错误,而这是不可能通过查看
(“”+:fmtStrs:*)
(productIterator.toSeq:*)
来检查的,所以这不起作用并不特别令人惊讶。错误信息可能更清楚,所以让我们看看到底发生了什么

如果您查看(我花了一些时间才真正找到它,我最终通过搜索错误消息找到了它),您将看到

c.macroApplication match {
  //case q"$_(..$parts).f(..$args)" => 
  case Applied(Select(Apply(_, parts), _), _, argss) => 
    val args = argss.flatten
    def badlyInvoked = (parts.length != args.length + 1) && truly {
      def because(s: String) = s"too $s arguments for interpolated string"
      val (p, msg) =
        if (parts.length == 0) (c.prefix.tree.pos, "there are no parts")
        else if (args.length + 1 < parts.length)
          (if (args.isEmpty) c.enclosingPosition else args.last.pos, because("few"))
        else (args(parts.length-1).pos, because("many"))
      c.abort(p, msg)
    }
    if (badlyInvoked) c.macroApplication else interpolated(parts, args)
c.宏应用程序匹配{
//案例q“$\(..$parts).f(..$args)”=>
已应用案例(选择(应用(u,零件),u),u,argss)=>
val args=argss.flatte
def badlyInvoked=(parts.length!=args.length+1)&&true{
def,因为(s:String)=s“插入字符串的参数太多$s”
val(p,msg)=
如果(parts.length==0)(c.prefix.tree.pos,“没有零件”)
否则如果(参数长度+1<零件长度)
(如果(args.isEmpty)c.enclosuringposition else args.last.pos,因为(“很少”))
else(args(parts.length-1).pos,因为(“许多”))
c、 中止(p,msg)
}
if(badly调用)c.macroApplication else插值(部件、参数)
调用时,
parts
argss
中都有一棵树,并且
parts.length!=args.length+1
为真,因此
badlycalleced
为真


s
不在乎它的参数是什么样子,所以它只是一个方法,你的场景也能工作。

相当奇怪的是,如果你把
f
插值器改成
s
插值器,这看起来很复杂(而且有效)…谢谢;为了记录在案,我们没有使用字符串插值,而是直接调用了
java.lang.String.Formatter