Странное поведение при уменьшении и свертывании идентичного блока кода

EDIT
Хорошо, @dhg обнаружил, что требуется синтаксис точечного метода, если блок кода для fold() не привязан к val (почему с reduce() в том же блоке кода можно использовать синтаксис метода пробела, я не знаю). Во всяком случае, конечный результат довольно лаконичен:

result.map { row =>
  addLink( row.href, row.label )
}.fold(NodeSeq.Empty)(_++_)

Что в некоторой степени отрицает первоначальный вопрос; т. е. во многих случаях можно упорядочить сценарии «или/или» в более высоком порядке и избежать «жирных», повторяющихся операторов if/else.

ORIGINAL
Попытка уменьшить обработку if/else при работе с потенциально пустыми коллекциями, такими как List[T]

Например, предположим, что мне нужно получить последние новостные статьи, чтобы создать NodeSeq из html-новостей <li><a>links</a></li>:

val result = dao.getHeadlines // List[of model objects]
if(result.isEmpty) NodeSeq.Empty
else 
  result map { row =>
    addLink( row.href, row.label ) // NodeSeq
  } reduce(_ ++ _)

Это нормально, довольно лаконично, но я обнаружил, что хочу использовать троичный стиль, чтобы обратиться к этим единственным случаям:

result.isEmpty ? NodeSeq.Empty :
  result map { row =>
    addLink( row.href, row.label )
  } reduce(_ ++ _)

Я видел несколько старых сообщений о сутенерстве троичного в логическое, но любопытно узнать, какие есть альтернативы, если таковые имеются, для оптимизации if/else?

match {...}, IMO, немного раздут для этого сценария, и for {...} yield, похоже, тоже мало помогает.


person virtualeyes    schedule 08.04.2012    source источник


Ответы (1)


Вам вообще не нужно проверять пустоту. Просто используйте fold вместо reduce, поскольку fold позволяет указать «пустое» значение по умолчанию:

scala> List(1,2,3,4).map(_ + 1).fold(0)(_+_)
res0: Int = 14

scala> List[Int]().map(_ + 1).fold(0)(_+_)
res1: Int = 0

Вот пример с List из Seqs:

scala> List(1,2).map(Seq(_)).fold(Seq.empty)(_++_)
res14: Seq[Int] = List(1, 2)

scala> List[Int]().map(Seq(_)).fold(Seq.empty)(_++_)
res15: Seq[Int] = List()

EDIT: похоже, проблема в вашем образце связана с удалением символов точки (.) между методами. Если вы держите их внутри, все работает:

scala> List(1,2,3).map(i => node).fold(NodeSeq.Empty)(_ ++ _)
res57: scala.xml.NodeSeq = NodeSeq(<li><a href="/foo">Link</a></li>, <li><a href="/foo">Link</a></li>, <li><a href="/foo">Link</a></li>)
person dhg    schedule 08.04.2012
comment
таким образом, вопрос о пустом результате получил трассировку стека re: empty reduceLeft. Компилятору не нравится кратная версия сокращения. - person virtualeyes; 08.04.2012
comment
Обратите внимание, что fold и reduce имеют разные подписи. Если вы измените reduce на fold, вам нужно добавить аргумент значения по умолчанию. - person dhg; 08.04.2012
comment
Может быть, но это не работает со List[NodeSeq], во всяком случае, со сгибом. Кажется, что тип потерян, тогда как с уменьшением NodeSeq выводится. Не уверен, в чем дело. - person virtualeyes; 09.04.2012
comment
Можете ли вы опубликовать полный пример, который компилируется, показывающий сбой? - person dhg; 09.04.2012
comment
если я сохраняю коллекцию для сворачивания в val, то это работает до некоторой степени; дает мне список [NodeSeq], но я ищу NodeSeq в дополнение к сокращению нажатий клавиш без добавления ;-) Я думаю, если fold может работать так же, как в настоящее время работает сокращение, тогда вопрос if/else/тройной было решено, так как это, вероятно, будет наиболее кратким способом работы с коллекциями без опций при попытке создать NodeSeqs и тому подобное. - person virtualeyes; 09.04.2012
comment
да, но тогда это не так, тогда компилятор запрашивает тип для строки в карте результатов { row =› (см. Исходный пост), который он прекрасно выводит (model.Article) с сокращением (без синтаксиса метода .) и с fold, когда я сначала сохраняю содержимое в val. Я согласен, что fold — это правильный путь, если он может обрабатывать пустой регистр, но только если он не требует лишнего ввода, которого я пытаюсь избежать в первую очередь (да, if/else достаточно лаконичен). , но когда у вас есть более сотни фрагментов представления NodeSeq для создания, чем меньше, тем лучше) - person virtualeyes; 09.04.2012
comment
извините, только +1, сложная проблема, у которой, похоже, нет простого ответа (иначе я предполагаю, что мы увидели бы несколько подходов к решению) - person virtualeyes; 09.04.2012
comment
отбросьте это, вы поняли, ВСЕ. синтаксис метода, необходимый для fold (я пропустил открытие list.map) - person virtualeyes; 09.04.2012