Рефакторинг val в метод приводит к ошибке времени компиляции
-
19-09-2019 - |
Вопрос
В настоящее время у меня есть
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>
^
Решение
Вот как мой мозг проанализировал сообщение об ошибке...
error: overloaded method value ->
Это название метода, которое называется '->'.
with alternatives
Далее последует список возможных параметров для -> внутри функции bind().
[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
Ах!Материал, связанный с узлом.Нашими допустимыми параметрами, по-видимому, являются NodeSeq, Seq [Node], Text и Node
cannot be applied to (List[scala.xml.NodeSeq])
Похоже, List[NodeSeq] - недопустимый параметр.
Имея это в виду, вы, вероятно, захотите удалить отдельный NodeSeq из списка, чтобы привязать его к форме.Вы уверены, что действительно хотите вернуть список из вспомогательного метода?
Другие советы
Я не смог увидеть, что 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>
}
}
работает.
Одна из проблем заключается в том, что ваше совпадение на самом деле не имеет никакого смысла:по сути, вы сопоставляете либо пустой список, либо непустой список.Другой возможности нет:
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
В качестве дополнительного примечания, в вашем коде есть одна вещь, которая не работает:
case all: List[NodeSeq]
Из - за удаление типа, нет никакого способа проверить во время выполнения, является ли all
список а List[NodeSeq]
, List[String]
, List[AnyRef]
или что-у-тебя есть.Я почти уверен, что вы, должно быть, получаете предупреждение в этой строке и игнорируете его, потому что не понимаете, о чем оно вас предупреждает (по крайней мере, это то, что случилось со мной, когда я получил такое предупреждение :).Правильной строкой было бы:
case all: List[_]
Который принял бы любой вид List
.Посмотрите мой вопрос об удалении типов и Scala, чтобы узнать немного больше об этом, если вам интересно.