Have you heard of LINQPad? Have you used it? If not, its website defines it as
a C#/VB/F# scratchpad that instantly executes any expression, statement block or program with rich output formatting and a wealth of features that "just work"
That it is! It's great for just starting up and being able to quickly type out whats on your mind to see how something compiles and runs. You'll see I made the phrase rich output formatting bold in the description. I did this because LINQPad adds an extension method on objects called Dump. It takes no arguments, returns what called it, and displays to the console nicely formatted output for any object. For instance take the code (in c#):
var x = 4;
x.Dump();
In the console, this will simply produce 4. However, things gets nicer when dumping more complex things. Take this for example:
class Animal
{
public int Height { get; set; }
public string Name { get; set; }
}
void Main()
{
List<animal> animals = new List<animal>
{
new Animal { Height = 4, Name = "Charlie" },
new Animal { Height = 14, Name = "Lacy" }
};
animals.Dump() ;
}
Dumping this list of animals produces this output:
image missing
The formatting is pretty superb, and makes inspecting objects very easy. Another great feature about Dump() is that you can call it on objects and continue working like nothing has happened! Check out this string replacement code where I call Dump() in the middle of replacing all chars in a string:
var utensil = "knife";
utensil.Dump();
utensil.
Replace('k','s').
Replace('n','p').
Replace('i','o').Dump().
Replace('f','o').
Replace('e','n').Dump();
You'll see 3 Dump() calls in that snippet. This is what gets produced by the console:
knife spofe spoon
Now I'll assume you have an idea of what I'm trying to do: add a method on every object (or Any notice the capitalization there you Scala wizards) which will output information on the object and return an object of the type that called dump. Well I'm going to use camel case now, so try to change your mindset from .NET/C# to Scala. I want to be able to run this similar code (now in Scala):
val utensil = "knife"
utensil.dump
utensil.
replace('k','s').
replace('n','p').
replace('i','o').dump.
replace('f','o').
replace('e','n').dump
So to do this, I had to create a class called Dumpable which has a method on it: dump() which writes some output to the console about the object AND returns the object. To do this I needed to use some pretty basic generics. Check out the class:
class Dumpable[T](obj: T) {
def dump: T = { println(obj.toString) obj }
}
Finally I need something that converts Anything into a Dumpable[some type]. To do this, I need to an implicit method which converts anything to a Dumpable[Type that called dump]. Notice, we can't convert Any to a Dumpable, we need to generically convert Anything to a Dumpable. Hence this, which is my first try, doesn't work:
implicit def toDumpable(obj: Any) = new Dumpable(obj)
This doesn't work because this converts Anything to a Dumpable[Any]. So an Any is returned from dump(), which then loses your type you were using, and you'd have to cast (ugh.). So let's make the implicit conversion method generic also!
implicit def toDumpable[T](obj: T) = new Dumpable(obj)
Using this implicit conversion from a generic T to a Dumpable[T] works great! Now the output of the scala code is:
knife spofe spoon
similar to the c#/LINQPad's behavior!