【问题标题】:Why the scala :_* to expand a Seq into variable-length argument list does not work in this case?为什么将 Seq 扩展为可变长度参数列表的 scala :_* 在这种情况下不起作用?
【发布时间】:2013-04-09 14:06:50
【问题描述】:

为什么 scala :_* 将 Seq 扩展为可变长度参数列表在这种情况下不起作用?

以及如何优雅地解决它?

import java.sql.Connection
import scalikejdbc.ConnectionPool
import anorm.{SQL, SqlQuery, SqlRow, Row}

object AnormExample extends App {
  Class.forName("org.hsqldb.jdbc.JDBCDriver")
  ConnectionPool.singleton("jdbc:hsqldb:mem:hsqldb:WithAnorm", "", "")
  implicit val conn: Connection = ConnectionPool.borrow()

  // this works
  SQL("insert into emp (id, name) values ({id}, {name})").onParams(3, "name3").executeUpdate()  

  // this does not compile
  val row = Seq(4, "name4")
  SQL("insert into emp (id, name) values ({id}, {name})").onParams(row:_*).executeUpdate()  // david
}

错误:

scala: type mismatch;
 found   : Seq[Any]
 required: Seq[anorm.ParameterValue[?]]
  SQL("insert into emp (id, name) values ({id}, {name})").onParams(row:_*).executeUpdate()  // david

ps:

<dependency>
  <groupId>play</groupId>
  <artifactId>anorm_2.10</artifactId>
  <version>2.1.1</version>
</dependency>

<dependency>
  <groupId>com.github.seratch</groupId>
  <artifactId>scalikejdbc_2.10</artifactId>
  <version>1.5.1</version>
</dependency>

<dependency>
  <groupId>org.hsqldb</groupId>
  <artifactId>hsqldb</artifactId>
  <version>2.2.9</version>
</dependency>

任何优雅的解决方案?

更新

根据senia的回答,这解决了问题:

def toParameterValueSet(seq: Seq[Any]) = seq.map(v => v: anorm.ParameterValue[_])
val row = Seq(5, "name5")
SQL("insert into emp (id, name) values ({id}, {name})").onParams(toParameterValue(row):_*).executeUpdate()

有没有办法消除声明/使用 toParameterValueSet 的需要?

(例如,告诉scala在自动扩展:_*上使用隐式转换)

更新

更紧凑一点:

implicit def toParameterValueSet(seq: Seq[Any]): Seq[anorm.ParameterValue[_]] = seq.map(v => v: anorm.ParameterValue[_])
val row = Seq(5, "name5")
SQL("insert into emp (id, name) values ({id}, {name})").onParams(row:_*).executeUpdate()

@Typesafe 团队:你能在 acrom SQL 上添加一个参数来获取一系列值吗? (而不是必须使用:_*) (我同意使用命名参数是首选,但有时使用未命名参数仍然有用)

【问题讨论】:

    标签: scala playframework-2.0 anorm


    【解决方案1】:

    你可以尝试替换

    val row = Seq(4, "name4")
    

    val row = Seq[anorm.ParameterValue[_]](4, "name4")
    

    所有类型都有隐式转换,因此您可以使用row.map{ e =&gt; e: anorm.ParameterValue[_] } 转换您的集合

    【讨论】:

    • 问题不在于没有隐式转换表单 Any 到 anorm.ParameterValue。替换为 'val row: Seq[String] = Seq("hello", "world")' 也不起作用。似乎问题在于使用扩展时的隐式转换。
    • 您的提议有效。但是,我们只是在转移问题:如何将 Seq("hello", "world") 转换为 Seq[anorm.ParameterValue[_]]("hello", "world")。我们可以使用 map 函数来转换每个参数;但是真的不能使用自动扩展吗?
    • @DavidPortabella:如果你有一个Seq[String],你可以使用seq.map{s =&gt; s: anorm.ParameterValue[_]}将它转换成Seq[anorm.ParameterValue[_]],但是如果你有Seq[Any],类型信息就会丢失并且你不能创建ParameterValue.
    • @DavidPortabella:存在从所有类型到 anorm.ParameterValue 的隐式转换。这是我的错误。您可以随时转换您的收藏。
    【解决方案2】:

    只需指定type&lt;: 定义了类型绑定。

    A <: B
    

    说 A 必须被类型 B 绑定,或者任何 A 都是 B 的子类型。给 row:_* 一个适当的 type 绑定。我认为String 界限有效。 anorm.ParameterValue[String].

    更具体地说,val row = Seq[anorm.ParameterValue[_]](4, "name4")。这应该执行implicit 转换。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-11-26
      • 2010-12-29
      • 1970-01-01
      • 2021-08-05
      • 2011-11-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多