First to the question, though I don't get what @
in the title is supposed to mean.
The _
is a wildcard in scala. So, in the code above
case _ => acc
matches all cases not matched by the cases before. In the code above that is all values from mapBefore and mapAfter with the same key, that do not differ. Therefore the result of the previous fold cycle is kept, while in the other cases pairs of different values are added.
Now about the rest of the code (I'm not the author, but I can guess):
type JsonMap = Map[String, Any]
Is a type alias defined just for conciseness and convenience.
def getMapDiffs(mapBefore: JsonMap, mapAfter: JsonMap) : (JsonMap, JsonMap) = {
val sameKeys = mapBefore.keySet intersect mapAfter.keySet
val startAcc = (Map.empty[String, Any], Map.empty[String, Any])
samekeys
is a Set of keys that are defined in both input maps
startAcc
is the start value for the upcoming foldLeft.
sameKeys.foldLeft(startAcc){ case (acc @ (deltaBefore, deltaAfter), key) =>
foldLeft
takes a start value and then traverses through the collection it has been called on. For each item of the collection the result of the last step and the current element of the collection are given as input to the fold function. In the first step the start value replaces the result.
The function call could be rewritten to:
sameKeys.foldLeft(startAcc){ inputTuple: ((JsonMap, JsonMap), String) =>
However, as you would then have to access the tuples content in rather cumbersome and hardly readable way (e.g. inputTuple._1._2 to get the second map of the previous result), developers make use of the fact that we can directly match inputs for fold, map, flatMap and the like functions. Thus
case (acc @ (deltaBefore, deltaAfter), key) =>
to bind the contents of the two tuples to readable local vals and the tuple itself to acc (that's what the @ is for). This way we can conveniently use the two maps as well as the complete result tuple of the last iteration, which is especially useful in the default case (case _ => acc
)
(mapBefore(key), mapAfter(key)) match {
retrieves the values from both input maps for the same current key and starts a match.
case (beforeMap: Map[_, _], afterMap: Map[_, _]) =>
val (deltaB, deltaA) =
getMapDiffs(beforeMap.asInstanceOf[JsonMap], afterMap.asInstanceOf[JsonMap])
(deltaBefore + (key -> deltaB), deltaAfter + (key -> deltaA))
matches values that are themselves Map
s and applies the recursive function to get all differences of these maps and add them to the result of this fold step.
case (beforeValue, afterValue) if beforeValue != afterValue =>
(deltaBefore + (key -> beforeValue), deltaAfter + (key -> afterValue))
matches all other values of both input maps that are NOT equal and adds them to the result of this fold step.
So in the end you should get two Maps with the same keySet and all values that are different in the original two input maps.