1

Is there a Scala construct for building and returning a list like so?

def getOutput(isValidInput: Boolean): List[Output] =
  if (isValidInput) {
    yield Output(1) // Pseudo-code... I know yield is not intended for this!
    yield Output(2)
  }

Instead of...

def getOutput(isValidInput: Boolean): List[Output] =
  if (isValidInput)
    List(Output(1), Output(2))
  else
    Nil

In C# the use of 'yield' allows you to return lazy-evaluated collections - is there something similar in Scala?

Lawrence Wagerfield
  • 6,471
  • 5
  • 42
  • 84
  • The question is not clear to me if you want lazyness or conciseness of code. The List won't be created in your example unless the boolean is true. – sksamuel Jun 14 '13 at 20:34
  • What you want is a form of continuation. This is somewhat supported, but probably less readable than other options. See http://www.scala-lang.org/node/2096 – gzm0 Jun 14 '13 at 20:49

1 Answers1

1

If you want a lazy sequence, use a Stream:

case class Output(value: Int)

def getOutput(isValidInput: Boolean):Stream[Output] = getOutput(isValidInput, 1)

def getOutput(isValidInput: Boolean, index: Int):Stream[Output] =
  if (isValidInput && index < 3) {
    println("Index: " + index)
    Output(index) #:: getOutput(isValidInput, index+1)
  } else {
    Stream.empty[Output]
  }

println("Calling getOutput")
val result: Stream[Output] = getOutput(true)
println("Finished getOutput")

result foreach println

This results in:

Calling getOutput
Index: 1
Finished getOutput
Output(1)
Index: 2
Output(2)

If you want to keep the return type as List[Output], using yield is a valid approach:

def getOutput(isValidInput: Boolean):List[Output] =
  if (isValidInput) {
    (for (i <- 1 until 3) yield Output(i))(collection.breakOut)
  } else {
    List.empty[Output]
  }

Also, using a Vector is often preferable over a List.

Related:

Community
  • 1
  • 1
dbyrne
  • 59,111
  • 13
  • 86
  • 103