cachemoney
Joined 16 years ago
Joined 16 years ago
Alternately, you have Either[A, B], with implementations Left[A](value: A), and Right[B](value: B).
So you can define a function that takes an Either[Int, ErrorMessage], rather than an Int or null. Getting a None[Int] is better than null, because it won't throw NullPointerExceptions if you access it sensibly.
Examples:
def x2or0(i: Option[Int]): Int = i.getOrElse(0) * 2
def x2(i: Option[Int]): Option[Int] = i.map(_ * 2)
def x2danger(iOrPossiblyNull: Int) = i * 2
// throws NullPointerException on null inputEMP Grenades.
There's some people at Twitter who truly love and grok Scala and Scala idioms inside out, and there's some people who look at Scala as a more functional, less verbose Java.
Everyone uses the alternate form: flatMap [B] (f: (A) ⇒ Traversable[B]): CC[B]. Nevertheless, I'll attempt to explain the provided signature.
If you understand Java generics, you should hopefully be able to understand this response.
A, B, and That are type parameters/generics. So they can be filled in by any type. This flatMap method exists on a trait (think Java Interface) called Traversable[A]. Traversable is similar to Iterable in java.
(f: (A) ⇒ Traversable[B]) means that this function takes one argument called f. That argument is a closure or anonymous function. The closure itself takes one argument of type A (an element in the parent Traversable[A]), and returns a Traversable[B], where B is an arbitrary type.
Skipping ahead, flatMap returns an instance of That. But what's a That? It appears to be unspecified. This is where the "(implicit bf: CanBuildFrom[List[A], B, That])" makes it's appearance.
Implicit parameters are like default arguments. "def foo(i: Int = 12)" will use the i if provided, else it will default to 12. "def foo(implicit i: Int)" will take the i given, else it will grab the first available Int in the containing scope. If you, "val c = 11; def foo(implicit i: Int) = i * 2", calling foo(1) yields 2, but calling foo() yields 22.
The object bf is an object that provides an overridable custom definition of concatenation. So when you write your custom collection, you include an instance of CanBuildFrom[List[A], B, That] in the correct scope, and it gets used for the concatenation. CanBuildFrom's type parameters say that it exists in a List[A], takes a B, and returns a That.
So yeah, in your implementation of bf, you could make it a new MyCanBuildFrom[List[A], B, FunkyCollection[B]], and do funky concatenation.
Hope that helps.
Doing this in-memory in java via someAtomicLong.incrementAndGet() sounds appealing.
In those scenarios, I'd like to see both patents thrown out.