You've probably noticed code like this (taken from the Artima web site: Working with Lists):
def isort(xs: List[Int]): List[Int] = if (xs.isEmpty) Nil else insert(xs.head, isort(xs.tail))
Here, I want to present a recommendation for generalizing this notion. In the same way that a sequence (Seq) of x is written xs, then a Future of x should be written xf. A Try of x might be written xt but I'm going to recommend something slightly different (xy) because t is useful for Tuple. So, the general scheme is:
val ac = C[A]
where C is some container type and A is some element type. Obviously, these can be composed such that if A happens to be a sequence of X (for example) then we end up with:
val xsc = C[Seq[X]]
In a for-comprehension, patterns/generators look very simple: for (x <- xs) yield x, for example.
Here are my recommendations for the abbreviations (but of course you should choose your own):
Sometimes you might have more than one identifier of the same type in which case you can follow the single letter with 1, 2, etc. Or, alternatively, you might use a single uppercase character to add context, for example gD for a document string and gL for a line string. You might also decide to use t2 for a Tuple2, etc. In the situation where we have an Either of form Either[String,X] or Either[Throwable,X] then we simply use the identifier xe, ignoring the left-side types.
Some confusion might arise between a as an Array (i.e. a container) and a as a generic type A (or ActorRef). This should be clear in that types are found at the start of the identifier string. Similarly, f as a Future and f as a Function. And s if you use it both for a String and a Seq.
Here are some examples of code which uses this idea:
Here are my recommendations for the abbreviations (but of course you should choose your own):
Container | Abbreviation |
---|---|
Seq/List, etc. | s |
Array | a |
Map | m |
Future | f |
Try | y |
Promise | p |
Tuple | t |
Option | o |
Iterator/iterable | i |
Either | h |
RDD | r |
Type | Abbreviation |
---|---|
My own type | x |
Generic type A, B, T, etc. | a, b, t, etc. |
String (line/document) | g |
String (word) | s or w |
URL | u |
Double | d |
Int | n |
Function | f |
ActorRef | a |
Exception | e |
Sometimes you might have more than one identifier of the same type in which case you can follow the single letter with 1, 2, etc. Or, alternatively, you might use a single uppercase character to add context, for example gD for a document string and gL for a line string. You might also decide to use t2 for a Tuple2, etc. In the situation where we have an Either of form Either[String,X] or Either[Throwable,X] then we simply use the identifier xe, ignoring the left-side types.
Some confusion might arise between a as an Array (i.e. a container) and a as a generic type A (or ActorRef). This should be clear in that types are found at the start of the identifier string. Similarly, f as a Future and f as a Function. And s if you use it both for a String and a Seq.
Here are some examples of code which uses this idea:
def flatten[X](xsfs: Seq[Future[Seq[X]]])(implicit c: ExecutionContext): Future[Seq[X]] = Future.sequence(xsfs) map {_ flatten}
def sequence[X](xy: Try[X]): Either[Throwable,X] =
xy match {
case Success(s) => Right(s)
case Failure(e) => Left(e)
}
def sequence[X](xos : Seq[Option[X]]): Option[Seq[X]] = (Option(Seq[X]()) /: xos) {
(xso, xo) => for (xs <- xso; x <- xo ) yield xs :+ x
}
val ws = List("http://www.htmldog.com/examples/","http://www.google.com")
val uys = for ( w <- ws ) yield Try(new URL(w))
BTW, an alternative for a tuple, say a (K,V) tuple, is to use kV (or _kv_) instead of t. This makes it clearer that it's a tuple of k and v, rather than just any old tuple. If you use that style, then you can use t for Try (rather than y).
ReplyDeleteAnd yet another possibility: In keeping with the right-to-left identifiers, I'm recommending that a variable for, say, a Map[String,Int] should be named: iSm where S indicates a "perpendicular" direction in type-space. Lower-case letters indicate leftward (outer) direction in type-space.
DeleteAnd yet another possibility: name the identifiers based on Tuple (or Map, which is really just a sequence of 2-tuples) using the backtick, such as: val `[wn]m` = Map[String,Int]()
ReplyDelete