3

Can a fold be used here to convert from a List[JsObject] to JsArray?

    def getJsonArray(list: List[JsObject]): JsArray = {
        def go(l: List[JsObject], acc: JsArray) : JsArray = l match {
            case x :: xs => go(xs, acc ++ Json.arr(x))
            case Nil => acc
        }
        go(list, JsArray())
    }
Kevin Meredith
  • 41,036
  • 63
  • 209
  • 384

1 Answers1

6

Yes, this should be roughly equivalent:

  def getJsonArray(list: List[JsObject]): JsArray = {
    list.foldLeft(JsArray())((acc, x) => acc ++ Json.arr(x))
  }
Noah
  • 13,821
  • 4
  • 36
  • 45
  • Thanks. Why did you pick foldLeft over foldRight? – Kevin Meredith Oct 16 '13 at 23:42
  • 1
    `foldRight` starts at the head of the list and builds up a giant function going to the end, and then applies that function which can lead to a stack overflow. `foldLeft` starts at the head of the list and applies your function, then goes to the next element so you don't have a giant built up function which can cause a stack overflow. For a better answer you can look here http://stackoverflow.com/questions/1446419/how-do-you-know-when-to-use-fold-left-and-when-to-use-fold-right – Noah Oct 17 '13 at 17:42
  • Why don't use ```(acc, x) => acc +: x```? – SexyNerd May 18 '15 at 23:18
  • I think you mean `acc :+ x` and I just copied the supplied function from the question – Noah May 19 '15 at 00:47
  • using fold like that keeps accumulating results into JsArray which is immutable, meaning a new JsArray object is constructed for every element in the list. Is there not a better way to do this? – Khorkhe Apr 18 '16 at 00:31
  • @Khorkhe, no, if you allow for mutability, get rid of the `foldLeft`, then yeah sure you can probably come up with a more memory efficient way. – Noah Apr 18 '16 at 02:01