0

我目前有

  def list(node: NodeSeq): NodeSeq = {
    val all = Thing.findAll.flatMap({
      thing => bind("thing", chooseTemplate("thing", "entry", node),
        "desc" -> Text(thing.desc.is),
        "creator" -> thing.creatorName.getOrElse("UNKNOWN"),
        "delete" -> SHtml.link("/test", () => delete(thing), Text("delete"))
        )
    })

    all match {
      case Nil => <span>No things</span>
      case _ => <ol>{bind("thing", node, "entry" -> all)}</ol>
    }
  }

我试图将它重构为

  def listItemHelper(node: NodeSeq): List[NodeSeq] = {
    Thing.findAll.flatMap({
      thing => bind("thing", chooseTemplate("thing", "entry", node),
        "desc" -> Text(thing.desc.is),
        "creator" -> thing.creatorName.getOrElse("UNKNOWN"),
        "delete" -> SHtml.link("/test", () => delete(thing), Text("delete"))
        )
    })
  }

  def list(node: NodeSeq): NodeSeq = {
    val all = listItemHelper(node)

    all match {
      case Nil => <span>No things</span>
      case all: List[NodeSeq] => <ol>{bind("thing", node, "entry" -> all)}</ol>
      case _ => <span>wtf</span>
    }
  }

但我得到以下信息。我已经跟踪了所有返回类型,但我看不出我的重构与内部发生的情况有何不同。我什至尝试添加更多匹配案例(如您在重构代码中所见)以确保我选择了正确的类型。

/Users/trenton/projects/sc2/supperclub/src/main/scala/com/runbam/snippet/Whyme.scala:37: error: overloaded method value -> with alternatives [T <: net.liftweb.util.Bindable](T with net.liftweb.util.Bindable)net.liftweb.util.Helpers.TheBindableBindParam[T] <and> (Boolean)net.liftweb.util.Helpers.BooleanBindParam <and> (Long)net.liftweb.util.Helpers.LongBindParam <and> (Int)net.liftweb.util.Helpers.IntBindParam <and> (Symbol)net.liftweb.util.Helpers.SymbolBindParam <and> (Option[scala.xml.NodeSeq])net.liftweb.util.Helpers.OptionBindParam <and> (net.liftweb.util.Box[scala.xml.NodeSeq])net.liftweb.util.Helpers.BoxBindParam <and> ((scala.xml.NodeSeq) => scala.xml.NodeSeq)net.liftweb.util.Helpers.FuncBindParam <and> (Seq[scala.xml.Node])net.liftweb.util.Helpers.TheBindParam <and> (scala.xml.Node)net.liftweb.util.Helpers.TheBindParam <and> (scala.xml.Text)net.liftweb.util.Helpers.TheBindParam <and> (scala.xml.NodeSeq)net.liftweb.util.Helpers.TheBindParam <and> (String)net.liftweb.util.Helpers.TheStrBindParam cannot be applied to (List[scala.xml.NodeSeq])
      case all: List[NodeSeq] => <ol>{bind("thing", node, "entry" -> all)}</ol>
                                                                  ^
4

4 回答 4

3

以下是我的大脑如何解析错误信息...

error: overloaded method value ->

这是方法的名称,即'->'。

with alternatives 

接下来是 bind() 函数中 -> 的可能参数列表。

[T <: net.liftweb.util.Bindable](T with net.liftweb.util.Bindable)net.liftweb.util.Helpers.TheBindableBindParam[T] 

这表示任何实现或包含 Bindable 特性的东西都是公平的游戏。

<and> (Boolean)net.liftweb.util.Helpers.BooleanBindParam 
<and> (Long)net.liftweb.util.Helpers.LongBindParam 
<and> (Int)net.liftweb.util.Helpers.IntBindParam 
<and> (Symbol)net.liftweb.util.Helpers.SymbolBindParam 
<and> (Option[scala.xml.NodeSeq])net.liftweb.util.Helpers.OptionBindParam 
<and> (net.liftweb.util.Box[scala.xml.NodeSeq])net.liftweb.util.Helpers.BoxBindParam 

一堆特定类型的选项。

<and> ((scala.xml.NodeSeq) => scala.xml.NodeSeq)net.liftweb.util.Helpers.FuncBindParam 
<and> (Seq[scala.xml.Node])net.liftweb.util.Helpers.TheBindParam 
<and> (scala.xml.Node)net.liftweb.util.Helpers.TheBindParam 
<and> (scala.xml.Text)net.liftweb.util.Helpers.TheBindParam 
<and> (scala.xml.NodeSeq)net.liftweb.util.Helpers.TheBindParam 
<and> (String)net.liftweb.util.Helpers.TheStrBindParam 

啊! 节点相关的东西。我们的有效选项似乎是 NodeSeq、Seq[Node]、Text 和 Node

cannot be applied to (List[scala.xml.NodeSeq])

看起来 List[NodeSeq] 不是一个有效的选项。

考虑到这一点,您可能希望从 List 中取出一个单独的 NodeSeq,以便将其绑定到表单。你确定你真的想从辅助方法返回一个 List 吗?

于 2009-11-13T00:22:07.453 回答
1

我没有看到 NodeSeq 扩展了 Seq[Node],所以我在提取的方法上有错误的返回类型。将其更改为

  def listItemHelper(node: NodeSeq): NodeSeq = {
    Thing.findAll.flatMap({
      thing => bind("thing", chooseTemplate("thing", "entry", node),
        "desc" -> Text(thing.desc.is),
        "creator" -> thing.creatorName.getOrElse("UNKNOWN"),
        "delete" -> SHtml.link("/test", () => delete(thing), Text("delete"))
        )
    })
  }

  def list(node: NodeSeq): NodeSeq = {
    val all = listItemHelper(node)

    all.length match {
      case 0 => <span>No things</span>
      case _ => <ol>{bind("thing", node, "entry" -> all)}</ol>
    }
  }

作品。

于 2009-11-13T00:19:46.630 回答
1

一个问题是您的匹配实际上没有任何意义:基本上您正在匹配一个空列表或非空列表。没有其他可能:

all match {
  case Nil          =>  //if list is empty
  case nonEmptyList =>  //if list is not empty
}

当然你也可以这样做:

case Nil       =>
case x :: Nil  => //list with only a head
case x :: xs   => //head :: tail
于 2009-11-13T00:20:06.973 回答
1

作为旁注,您的代码中有一件事不起作用:

case all: List[NodeSeq]

由于类型擦除,无法在运行时测试alllist a List[NodeSeq]List[String]List[AnyRef]what-have-you。我很确定您一定会在该行收到警告并忽略它,因为您不明白它在警告您什么(至少,当我收到此类警告时,这就是发生在我身上的事情:)。正确的行是:

case all: List[_]

哪个会接受任何类型的List. 如果您有兴趣,请查看我关于类型擦除和 Scala 的问题以了解更多信息。

于 2009-11-13T11:50:35.940 回答