You get an error, because of this line:
(mFile, data, caseID) = readSinglePair(idCase, mFolder, bName)
Here, readSinglePair
returns an Option[(File, DataType1, String)]
. But writing it this way, Scala expects the right-hand side of the =
to be just the tuple, not wrapped in an Option
. Handling errors with Option takes some getting used to, because things that can fail don’t have the same type any longer as things that can’t (which is good. When using nulls, you can’t see from a method’s signature, that it can fail and return null).
If you would want to only keep the good cases, you could replace =
with <-
here, which would then use the map
function on option, like @cbley explained. map
only does something, if there is a value in the Option
, i.e. if it is a Some
, and otherwise just returns None
again, which when combined with a for
that starts with a list is interpreted as an empty sequence.
But if I understand you correctly, your function should return a second sequence of all ids of failed cases too, correct?
In that case, you’ll probably want an Either
instead of Option
in the readSetOfData
method. An Option
is normally used, when there is only one way something can fail or you aren’t interested in how it failed (e.g. if in your readSinglePair
you don’t care which exception occurred, you could keep Option).
An Either
is similar to an Option
, except that its error case can contain a value, it is either a Right
(analogous to Some
) or a Left
(analogous to None
, but containing a value). In your case, a Left
would contain the id of a failed case.
As you already have a method that returns an Option
for a single file, you can use the Option
's conversion method toRight
:
for {
idCase <- caseIDsList
} yield readSinglePair(idCase, mFolder, bName).toRight(idCase)
If readSinglePair
returns a Some
, toRight
converts it to a Right
with the same contents. Otherwise, it returns a Left
containing the given parameter, in this case its id. This for
would then return a List[Either[String, (File, DataType1, String)]]
.
Now, as you want a separat validCaseList
and invalidCaseList
, you’d have to split this again, but there is a better way. List
provides a method, that for each element runs a given function returning an Either
and sorts the result into two lists: partitionMap.
With that, the method would look like this:
def readSetOfData(caseIDsList: List[String], bName: String, mFolder: String)
: (List[String], List[(File, DataType1, String)]) =
caseIDsList.partitionMap(
idCase => readSinglePair(idCase, mFolder, bName).toRight(idCase)
)
Note that it now returns a tuple of two lists, one with the failed ids and one with the successful results:
It runs readSinglePair
for each id in the input list. If it fails, the toRight
converts it to a Left(idCase)
and it ends up in the first resulting list, if it works, the toRight
keeps the contents of the Option and it ends up in the second list.