编辑1

我已经看到了这个问题:Applying a function to a tuple in Scala

理想情况下,我只想这样做:

scala> val t = ("A", "B", "C")
t: (java.lang.String, java.lang.String, java.lang.String) = (A,B,C)

scala> "%-10s %-50s %s".format(t) // or some closer syntax


哪个应该给输出

res12: String = A          B                                                  C


编辑2

或者从某种意义上说,Scala编译器应该能够推断出我实际上是在使用正确的参数和类型进行调用

"%-10s %-50s %s".format(t.untuple)扩展为"%-10s %-50s %s".format(t._1, t._2, t._3)

我可以使用宏来执行此操作吗?

原始问题如下

我有一个元组,用于格式化字符串:

scala> val t = ("A", "B", "C")
t: (java.lang.String, java.lang.String, java.lang.String) = (A,B,C)

scala> "%-10s %-50s %s".format(t.productElements.toList: _*)
warning: there were 1 deprecation warnings; re-run with -deprecation for details
res10: String = A          B                                                  C

scala> "%-10s %-50s %s".format(t._1, t._2, t._3)
res11: String = A          B                                                  C


到目前为止一切正常。但这失败了:

scala> val f = "%-10s %-50s %s".format(_)
f: Any* => String = <function1>

scala> f(t.productElements.toList: _*)
warning: there were 1 deprecation warnings; re-run with -deprecation for details
java.util.MissingFormatArgumentException: Format specifier '-50s'
    at java.util.Formatter.format(Formatter.java:2487)
    at java.util.Formatter.format(Formatter.java:2423)
    at java.lang.String.format(String.java:2797)
    at scala.collection.immutable.StringLike$class.format(StringLike.scala:270)
    at scala.collection.immutable.StringOps.format(StringOps.scala:31)
    at $anonfun$1.apply(<console>:7)
    at $anonfun$1.apply(<console>:7)
    at .<init>(<console>:10)
    at .<clinit>(<console>)
    at .<init>(<console>:11)
    at .<clinit>(<console>)
    at $print(<console>)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at scala.tools.nsc.interpreter.IMain$ReadEvalPrint.call(IMain.scala:704)
    at scala.tools.nsc.interpreter.IMain$Request$$anonfun$14.apply(IMain.scala:920)
    at scala.tools.nsc.interpreter.Line$$anonfun$1.apply$mcV$sp(Line.scala:43)
    at scala.tools.nsc.io.package$$anon$2.run(package.scala:25)
    at java.lang.Thread.run(Thread.java:744)


这也会失败:

scala> f.apply(t)
java.util.MissingFormatArgumentException: Format specifier '-50s'
    at java.util.Formatter.format(Formatter.java:2487)
    at java.util.Formatter.format(Formatter.java:2423)
    at java.lang.String.format(String.java:2797)
    at scala.collection.immutable.StringLike$class.format(StringLike.scala:270)
    at scala.collection.immutable.StringOps.format(StringOps.scala:31)
    at $anonfun$1.apply(<console>:7)
    at $anonfun$1.apply(<console>:7)
    at .<init>(<console>:10)
    at .<clinit>(<console>)
    at .<init>(<console>:11)
    at .<clinit>(<console>)
    at $print(<console>)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at scala.tools.nsc.interpreter.IMain$ReadEvalPrint.call(IMain.scala:704)
    at scala.tools.nsc.interpreter.IMain$Request$$anonfun$14.apply(IMain.scala:920)
    at scala.tools.nsc.interpreter.Line$$anonfun$1.apply$mcV$sp(Line.scala:43)
    at scala.tools.nsc.io.package$$anon$2.run(package.scala:25)
    at java.lang.Thread.run(Thread.java:744)


我究竟做错了什么 ?如何将元组参数应用于“变量”样式函数?

最佳答案

问题出在lambda定义中

val f = "%-10s %-50s %s".format(_)

等效于:

val f = x => ("%-10s %-50s %s".format)(x)

因此,您只是在这里将序列作为第一个参数传递。

正确的lambda是:(x: Seq[Any]) => ("%-10s %-50s %s".format)(x: _*)甚至只是val f: Seq[Any] => String = "%-10s %-50s %s".format

例子:

scala> val f = x => ("%-10s %-50s %s".format)(x)
f: Seq[Any] => String = <function1>

scala> f(Seq(1,2,3))
java.util.MissingFormatArgumentException: Format specifier '-50s'

scala> val f: Seq[Any] => String = "%-10s %-50s %s".format
f: Seq[Any] => String = <function1>

scala> f(Seq(1,2,3))
res75: String = 1          2                                                  3


不幸的是,scala无法理解("%-10s %-50s %s".format)(_: _*),因此您不能使用下划线。

有趣的是:如果您尝试在不使用下划线的情况下进行同样的操作-您将不必明确指定_ *:

scala> val f = ("%-10s %-50s %s": scala.collection.immutable.StringLike[_]).format _
f: Seq[Any] => String = <function1>

scala> f(Seq(1,2,3))
res81: String = 1          2                                                  3


但是您必须明确指定类型类,因为function _构造doesn't work with implicits

10-01 10:52