It's my 10 year anniversary on Tumblr 🥳. The frustration of the jump from Microsoft to Scala at Tumblr was a decade ago. Time flies!
The Stonewall Inn

Product Placement

if i look back, i am lost
untitled
NASA
YOU ARE THE REASON
Cosimo Galluzzi
Color Me Curious
Claire Keane
todays bird

❣ Chile in a Photography ❣
𓃗
Keni

gracie abrams

Game Changer & Make Some Noise
Monterey Bay Aquarium
The Bowery Presents
hello vonnie
Sade Olutola
cherry valley forever

seen from Brazil
seen from Iraq

seen from Denmark
seen from Vietnam
seen from Bolivia

seen from Palestinian Territories

seen from Malaysia

seen from Türkiye

seen from United States

seen from Malaysia

seen from Singapore

seen from Dominican Republic

seen from Qatar

seen from United States
seen from Vietnam
seen from United Kingdom

seen from Austria
seen from Mexico
seen from Ukraine
seen from United States
@clr-man-jvm-world
It's my 10 year anniversary on Tumblr 🥳. The frustration of the jump from Microsoft to Scala at Tumblr was a decade ago. Time flies!
When writing Go, to return interface{} is to admit defeat. I shall not be defeated.
Fuck golang in its smug fucking mouth
Oh, look at me! I have a type system! I hate exceptions! I’m GREAT for systems programming. I’m sooo much better than anything JVM based!
Bullshit. Bullshit on a plate hiding under Sriracha and a handlebar mustache. And I’m holding the spoon.
First of all, Go is still a memory-managed language. And while its garbage collection is way better than it was a year or two ago, compared to the JVM or CLR it is a weak ass toy. I wrote a thing that had to read a lot of files (hundreds of thousands of files, dozens of terabytes) and I ended up manually managing my read buffers because Go would take all the memory on the machine even though I only had 20 files open simultaneously. Yeah, it should have had a performance penalty, but it shouldn’t have run up multiple gigabytes of RAM usage. Shame on you, Go!
Secondly, Go can’t talk all this wonderful crap about how great aspect-based programming is and not provide a way of pattern matching on an interface. Before you get your panties in a bunch, I mean without reflection. Not that the reflection pattern it takes to pull this off is sensible either, but fuck you it’s great and if you don’t like it you’re clearly stupid. Aspect-based is nice, but as it stand in Go now, it is not good enough. This makes me miss Scala desperately.
Thirdly, saying that fields are not members of an interface means that there is no way to be DRY. Consider the GetObjectOutput and HeadObjectOutput structs from the Amazon S3 service. See a lot of fields in common you might want to wrap in HTTP response headers in your shiny new proxy service? Tough shit. Write it twice.
There is a massive focus on functional composition and immutability. The concept is nearly 100 years old and Lisp has been around for nearly 60 years. Popular, existing, “mainstream” OO languages have been adding such features for years: C# in 2007, C++ in 2011, Java in 2012, and many others. Lambdas and currying are part of the story, but without tail-call elimination a lot of the functional patterns you would want to use won’t work. Again, not available in Go.
There is a lot of ballyhoo about the power of goroutines and channels. Assuming your model fits, it’s great. Producer-consumer and message-passing are both very easily modeled with those tools. And unlike in Akka, you don’t lose type information when you use channels! That’s all great stuff. However...
What’s a semaphore? Fuck you, it’s a channel of empty structs. What’s a mutex? Well, a mutex is a mutex but you don’t get access to any of the kernel stuff because it isn’t a real mutex most of the time. Hey, I know kernel transitions are expensive, but sometimes that is a trade-off that is worth it to me. My function body, my choice.
Wanna have a timeout? Well, make another channel, you chump. And a goroutine with a sleep in it. Do you want a high-performance, low-overhead timer you can use when you don’t care about exactly hitting on-time? Fuck you again right in your ear, you needy little cry-baby! Forced cancellation is for jerks and if you want it you must be a jerk too. Are you a jerk? Why can’t you learn to be cooperative? Windows 3.1 was cooperative. Are you worse than 16-bit Windows? Oh, and if you didn’t implement the thing you are calling and it doesn’t support cooperative cancellation... um... golang is going to have to get back to you on that one.
I can understand how Go’s rigidity (both in the language and in project structure) is a breath of fresh air to anyone who’s worked on a Ruby project. It’s speed of compilation is amazing, especially if you’re coming from the Scala world. I like the static-compilation-by-default style because disk is cheap and developer hours are expensive. References-by-git is limiting, but wonderful in 95% of cases. Golint is really damned good. The performance of your Go program is very likely going to be way faster than the same algorithm in a scripting language, on par with other memory-managed languages. If your algorithm fits the model, goroutines and channels are easy to work with and hard to fuck up.
I may change my mind as I use the language more, but for now I say fuck Go and the high-horse it rode in on.
The need, requirement or constraint to keep backwards compatibility made things difficult, then we have other important conditions like the lack of value types, type erasure and checked exceptions. If Java had the first and lacked of the other two the design of JDK 8 would probably have been different. So, we all must understand that these were difficult problems with lots of tradeoffs and the EG had to draw a line somewhere and make a decisions.
Misplaced rage, but rage nonetheless
I was about to post about how annoying it is that the JVM (Java, Scala, etc.) doesn't have multi-dimensional arrays. Not jagged arrays (a.k.a. arrays-of-arrays) but actual blocks of memory that don't require an extra pointer jump to get to an element. You know, the thing where iterating vertically costs the same as iterating horizontally?
While true, it doesn't really matter. Since you can't create objects on the stack anyway (built-in PODTs don't count), you are probably going to have to follow another pointer into the heap anyway. This is obviously not just limited to jagged arrays. And since we are following extra heap pointers for every element access anyway, what's one more?
JVM is a pile of ass (redux)
Iterable[T] isn't a thing because of type erasure. Iterable[object] is. Therefore, any Java iterables that leak into my Scala world suck!
Language features vs. runtime features
At an orientation meeting today a salesman was discussing an advertisements from his childhood that still resonates with him decades later. I don't often think of this Prego ad, but today it bubbled its way up to the top when I got mad thinking about the JVM again.
In a previous post I explained why I consider the implementation of generics as a language feature to be a mistake. I am not the first to make this argument and I'm sure I won't be the last. But I want to extend this and hopefully establish a pattern: Whenever possible, any feature will be implemented as a feature of Java the language, not the JVM. Going even a step further: This both create a raison d'être for Scala as well as its downfall.
Consider operator overloading. There is no place in the JVM to do this. Instead, this is done by naming functions "magically" and letting the compiler subvert the runtime. This works most of the time, but it fails in strange ways. This also holds for array indexers. Arrays are "special" in Java, but the idea of indexing really fits all kinds of data structures. In order to break this apart in Scala, the "magical" apply and update functions can fake this behavior. The "apply" magic name is used all over Scala, but "update" is both more rare and far more likely to be used inadvertently by an author to do something else -- something other than what the language designers meant for the contract of "update."
Maybe the real answer is the the JVM is just fine and the designers of Scala made a mistake. To that I say "HA!" and "no." Scala is an alternate representation of programmer intent from Java, but it is really an effort to create a stronger semantic framework over what Java had to offer. You can't tell me that indexing into a vector should be syntactically different than indexing into an array. I won't believe that boxing every integer in some generic data structure is ok. You can't tell me that it should be impossible to define a structure to hold complex numbers that has a useful addition operator.
Scala says you can do these things, but the mismatch with JVM creates the opportunity for nasty edge cases that simply shouldn't be a problem.
This turned into more of a rant than I meant. Maybe that's because I'm too intimidated to write the post about how awesome pattern matching and comprehensions are in Scala, while this was easy!
Scott Hanselman's session. Makes my C# homesickness flare.
Virtually awesome
Author's disclaimer: This is a HUGE topic and I'm going to give a fairly brief treatment. Consider this a starting place for the question, not the answer.
In Scala, methods are all virtual by default. You can opt-out with the "final" keyword, and even partially opt-out for inlining by sealing the class. In C#, methods are non-virtual by default. You opt-in with the "virtual" keyword. It is worth mentioning that overridden abstract methods are virtual, implemented interface methods are non-virtual in C#, but that's not the point.
There is a deep philosophical difference here. Scala expects class consumers to override methods. You can even override with an anonymous class in a method. Very powerful, kind of bugs me out. In C#, the expectation is that the base class author should have more control over how consumers will use their stuff, and there are potential efficiency gains that go along with that.
There may be no greater metaphor for the relationship between the open-source-centric Java world and the closed-source Microsoft world than this single design decision. As a guy who prefers writing core library/infrastructure code, I think I prefer the Microsoft approach here, but the power of mix-ins and anonymous overrides in Scala are pretty darned cool.
Let's consider these classes, defined in vaguely agnostic and very explicit pseudo-code:
class Foo { methodA; methodB; virtual methodC; }
class Bar inherits Foo { new methodB; override methodC; }
When the instance of type "Bar" has been cast into a reference of "Foo," which bodies to call?
The answer depends on how the method was declared:
barInstance.methodA => Foo.methodA
((Foo)barInstance).methodA => Foo.methodA
barInstance.methodB => Bar.methodB
((Foo)barInstance).methodB => Foo.methodB
barInstance.methodC => Bar.methodC
((Foo)barInstance).methodC => Bar.methodC
#1 and #2 are equivalent, for obvious reasons. Bar didn't declare a body for methodA, so you have to invoke Foo.methodA. But how do #3/4 and #5/6 differ? Syntax aside, the answer is that virtual methods are referenced from a v-table. The instance is carrying around it's type information, which has a table of pointers to implementations. When you call methodC, the instance looks the body up in the table and invokes it. However, methodB is not virtual; it is invoked on the type. So if an instance of Bar is masquerading as a Foo, it had better be ready to invoke Foo's body for methodB.
This is a powerful thing! The naive way to think about these things strongly favors the behavior of virtual methods, but there is a cost. Virtual methods pay for that v-table lookup. Much more importantly, it is very easy to inline non-virtual methods at compile time. Inlining virtual methods cannot be done until JIT time, and even then is path fraught with danger. In other words, non-virtual methods can significantly more efficient to call. How significant depends on how much work the method is doing in its body, YMMV.
Functional perspectives
I cut my teeth on functional programming with SML/NJ in college with the intimidating and brilliant Robert Harper. I loved hanging a program together on what felt more like "flow" rather than the "surface" of an object. I still do.
Scala and C# have similar goals in that they meld imperative, object-oriented environments with powerful functional tools. Specifically, both have first-class function parameters, anonymous functions, closures, tail recursion optimization, etc. However, there is a fundamental difference in the mindset of the authors of these languages.
In C#, at least to me, IEnumerable<T> and it's buddy "yield" were the center of the functional universe. You would operate on sets of things. You could create pipelines without ever actually realizing the whole set. It held together with PLINQ's Task<T>, allowing your pipelines to operate asynchronously.
Scala focuses on map, flatMap, and for comprehensions. There are futures and options and all the same stuff I was used to in C#. The for comprehensions in Scala feel more powerful than "IEnumerable.Select." That comes from the nifty context control that you get in Scala. It is worth noting that "yield" in Scala is completely unrelated to "yield" in C#. I don't know the Scala tool to get what I want there yet.
There is something more pure about centering on verbs rather than nouns, so the win goes to Scala there. However, when it comes to passing these things around, it doesn't make a huge difference. Scala's idiomatic distate for null still strikes me funny, but it does have certain advantages when you can get the empty items culled from your sequence (iteration, whatever) without having to call "filter" ("where" in C#). I still haven't fully drunk the Kool-Aid on that one yet.
Certain problems lend themselves so naturally to a functional style. I love the option to choose how I'm going to attack. Somehow, I feel like Dr. Harper would not approve of Scala or C#.
Generics, type-erasure, and fuck you JVM
In 1998, certified smarty-pants Philip Wadler bolted Generics on top of the fairly young JVM. To Philip, I wish to join the ACM and other distinguished institutions in congratulating you on a job well done. To the smart folks working on the JVM between 1998 and 2004 when Generics became an official feature, allow me to say humbly, you fucked up.
Back in the dark ages, when templates in C++ needed to get "pounded out," developers had a healthy respect for what was really going on -- the compiler was doing some snappy find-and-replace action on your code, ensuring type-safety, and producing regular, old type-specific code to do the real work. The manual parts of this are largely gone, leaving C++ developers to deal with the black arts of partial template specialization and other assorted necromancy.
But Java and .NET run in managed environments. Compilation is incomplete, potentially up to the moment of invocation. That leaves an opportunity to "pound out" the code as needed, reducing bloat but still retaining type safety.
Wadler, however, did not have that choice. There was no great place to hook-in his generics because the uses of a generic class could not be known at compile time. There isn't any way in JVM bytecode to represent generics at all, so it can't be done when you JIT. Instead, he had no choice but to blow the type information away, treat everything as "object," and cast back to the strong type before the caller got to touch anything. Type safety is preserved at compile time, which is when it is most important.
We folks in .NET land had the same problem. There were no generics in .NET until 2.0 came out in late 2005! We had neither Wadler's brilliant hack, nor the pound-it-out of early templated C++, but rather the Byzantine horror of CollectionGen and similar tools that would create strongly-typed classes in C# or VB.NET, based on their own templating language. These would be compiled, often into their own assemblies, and you were off to the races -- type-safe and efficient.
But in 2004 and 2005, Sun and Microsoft went radically different directions. Sun kept generics as a Java (language) feature. Microsoft made generics a CLR (runtime) feature. Syntactically, Java and C# generics are nearly identical. At runtime, the difference could not be more stark.
Collections of value types must be boxed. Consider List<int> in .NET versus the equivalent ArrayList<int> in Java. It is a single array in .NET, one heap allocation. It is N+1 heap objects in Java, with all of the locality penalties associated with that. But the fun doesn't stop there! In Java, you pay a casting penalty with any generic call. In .NET, there is literally no difference. Everything in Java that touches anything generic will be cast to object at some point, which makes Jesus cry.
These days I'm working mostly in Scala. Scala goes through a lot of trouble and pain trying to undo type erasure. I appreciate their valiant and noble efforts. I wish that the fine folks at Oracle would answer my prayers and the prayers of so many other developers and right this wrong -- put generics in the runtime. It will break backwards compatibility, but it is worth it.
Don't make me beg.
Know your shit, be curious
My first job out of school was for a consulting company in Washington, D.C. It was 1998, which means that developers were very hard to come by. My firm was very good at making risky hires, separating the strong from the weak, and turning a big profit on both groups. Again, it was 1998. That kind of thing worked back then.
I liked the people I worked with, but there were some pretty big gaps in basic computer science among large segments of the group. So I asked and was given permission to run two sessions of two hours on the subject. My goals were not lofty, and not completely altruistic -- I was sick of dealing with crappy code.
I stood before my friends and colleagues, a young fool of 22 or so, explaining the virtues of sorting things you intend to search; of the difference between arrays, vectors, and lists; of encapsulation and interfaces. I didn't touch on balancing trees or hashing or anything esoteric. No way to get to the end of the road in four hours or four years or forty years. I just wanted to get people on the road.
The sessions went well. I got through my material at a decent pace. Participation was about what I expected. The stronger engineers at the firm congratulated me on my presentation. When it was over I asked a friend, one of those who I thought needed the help, what he thought.
"I thought it was all pretty interesting, Mike, but I don't know when I'm ever going to use this stuff."
I died inside, just a little.
Chris went dancing
I am pretty comfortable in saying that I am the only person in the world who is thinking about the mocking serenade that Rory Blythe made in honor of Chris Sells's trip to Burning Man in 2004. The point of that particular tune was that a.) Chris wore a kilt (man-gown) to the desert Bacchanalia; b.) Chris was going to dance everywhere, probably badly; c.) Chris would stay out in the desert if not for is love of .NET. Ladies and gentlemen of the Internet, I feel like Chris Sells out there in the desert.
I met the CLR during the Spring of 2001. It was liberating, empowering, beautiful even in its beta form. Coming from 3 years of hard time as a VB6/ASP programmer, Fortran was starting to look pretty good, too! But my time studying .NET that spring landed me a job that I had for nearly a dozen years, working largely on .NET and SQL for FactSet Research Systems, Inc. I liked working at FactSet and I really liked my tool chain, but my job became too non-technical and it was time to go.
To my great joy, I landed at Tumblr, working on back-end stuff that most people don't have to think about. My kind of problems! But where FactSet was corporate, entrenched, and more comfortable with a vendor-based product than open-source, Tumblr is 180 degrees the other way. That means Scala/JVM instead of C#/.NET. That means sharing tons of code and tools with others in our space (Twitter, Google, LinkedIn, Yahoo!, Apache, a host of others). That means MySQL instead of SQL Server. It also brings in a host of other great tools I didn't get to use much at FactSet, like Redis.
This tumblog is my attempt to catalog my bumbling road from recently-reborn n00b to something resembling proficient. I will make many mistakes along the way. I'm going to try to be fair and objective, but I am just one guy with a job and a family, so I'm going to miss some stuff.
Your humble tumblr bumbler,
-Mike.