Friday, November 23, 2012

Nomadic programming

DISCLAIMER: This is about my opinion. And may or may not contain some boasting. And is also a bit of a brain dump.

Yep, this is not a typo. Not monadic but nomadic. Although monads are cool too.
A few days ago the CTO of a company I work for said it's time to specialize. He was talking about my career. Offering me a few things to try and then pick one. But this got me thinking.
Today another CTO told me that I'm "essentially a good dev" and that chosen software stack doesn't matter. And I agree. (Patrick does too).
20 years later all this fits in your pocket
I'm an engineer not a programmer(or god forbid, a coder). I solve problems not just write code. It just happens that code is solution to most problems I try to solve. World is increasingly more computer orientated. Now everything(literally!) has a processor inside. But processors are dumb. So you need people to program them. These people are the equivalent of the factory workers before robots started taking over. So now people need to migrate one level up on the abstraction ladder. Labor is now mental. Not everything is the same(like in a traditional factory) but it is the same concept. And you are pumping out slightly different versions.  Welcome to a modern software shop.
But all this "computerization" also pushes up the upper bound of complexity. And this is where engineers kick in. If you have complex solution you require (hopefully less) complex solutions. And you need people who can manage this complexion. Not by being machines but by understanding, inventing concepts and structuring them. Big software has millions if not billions of moving parts. Imagine a machine of such complexity. There probably isn't a human out there who could manage this in it's entirety. But software engineers are expected to do this. You need the ability to see something and relate it to known concepts or invent a new concept and relate it to oter stuff. Connect things together. And to do this well you need broad knowledge. Yes you need specialization - depth - to do something very well but this is a lesser problem. See a good engineer can go from zero to awesome in a new field very quickly. Learning a new language can be done in a week and a software stack in a bit more. I'm not saying you become an expert or the very best in the field but if you have the urge to learn you are not far behind. So a good engineer is the one who has the ability to learn and to produce real solutions with this knowledge.


Nomads

So where does nomadic programming fit into this philosophy? Going from language to language, from framework to framwork and changing software stacks. Not settling down. This (in my opinion) teaches you what can be done and haw can stuff be done. In all possible ways. So you can figure out the best solution. Learning all the time also keeps you on the bleeding edge and this is fun and engaging. Having new toys all the time! I can't image myself working with just one thing for the rest of my life. Meeting new languages and new framework is what I do in my free time. So when a customer says they need Ruby on Rails and I never used it before....it's not a problem. I've seen ruby, I know python and I know how MVC is supposed to work. Putting it all together is not that hard. You can even hit the ground running and start working right away. Of course you'll be a bit slower in the start but you can catch up.  So no, I don't want to specialize. I want to know everything that is there to know! And I believe this will make me a better engineer. Or developer. Or person. And I believe that quality of their employees shoud matter to the employer. It is developers who create their products. 

You should always strive to become better!
Enhanced by Zemanta

Monday, November 19, 2012

Cool Monday: CERC and my trip to Krakow


This week's post is a bit different. Well very different. My team qualified for CERC ICPC(european programming contest) and that means a trip to Krakow, Poland. I plan on writing this in a journal style. A bit every day.

Friday, 11. am

I got up at 6. to check news and read a bit before departing. And of course to charge my laptop and phone to 100% batter for the long trip. Then a 10 minute walk across Ljubljana(quite cold outside) and bus left at 7.15am. Yes, we're riding a bus. And we will be riding this bus for quite some time. Approximately 12 hours total! I guess it would be cheaper to buy plane tickets for low end jet-line than renting a bus(and two drivers) for whole weekend. Not to mention faster. Twelve hours!!
Anyway, first stop is Maribor to pick up some more teams and eat sandwiches. By the time we left Slovenia it was already 10 am. I honestly didn't know it takes that much to get from the country.
And it's kinda boring here on bus. Since we're in a foreign country I'm in a roaming network and data can get pricey. So no internets for me. At least the hotel we're staying in should have wifi. But I've written a blogpost anyway and wil zemanta-fy and post it when we get there. This is my second writing today.
Life gets boring here. I've talked to some interesting people..but then everybody got to do something. Bus has a DVD player, but it only plays DVDs, no avi or and other format. And of course the only thing we've got was twenty-something Poirot moveis. Not my thing. Somebody bought some empty DVD at the gas station(they have those there!!) and we've had an adventure trying to burn something. Success. But approximately two guys at the front are watching Poirot currently so we'll have to wait to see if it had in fact worked.
Oh yeah, and I can't read(or program for that matter) on a bus because reading vibrating text makes me nauseas. It's funny how I'm writing this. Laptop in my lap(that's why it's called a laptop!), screen brightness to minimum, typing and looking through the windows and around the bus. I occasionally glance at screen to correct the mistakes I've made.
I surely hope something happens because I don't know if I can stand that much boredom.

Saturday, 1. am


Slovakian border
We stopped in Slovakia for lunch. In a restaurant that was something like 20m from the highway. They only had three dishes and everything was mediocre. Reading signs was a mood lifter. Slovenian and Slovakian language are quite close, but not the same. So “out of order sign” on the toilet read as “don't eat”. Not to mention that Slovakian word for soup is a curse word in Finnish.
And back to the bus. I've grown to like Poirot. Apart from his ego, he's quite a likable character. I'd probably die of boredom if I wouldn't watch the movies. And then was fog. Lots of it. And there was the end of the highway... And we still had nearly 100km to go. All in all the trip was 14 hours long.
Food in the fancy restaurant
Hotel is real nice! Four stars and solid internet connection in rooms(that's what matters!). I got lucky and got a room of my own, while others are sharing rooms for two. Or is that bad for me?
Anyway..I check my emails, talk to my girlfriend, give up on amount of unprocessed info on social networks and go hang out with new friends. And because we're programmers hanging out means going to dinner in a fancy restaurant at midnight and drinking tea. Poland is cheap! The restaurant was really nice but I don't believe anyone paid more than 5€(converted from their currency). 
Only problem was that our hotel is something like a 35 minute walk from city center. And we had zero idea how to use public transport. And it's quite cold outside. But tea warmed us up. And time passed by quickly because conversations were interesting. I like hanging out with smart guys.

Saturday, 11. pm

My wannabe English breakfast
Today was way better. Breakfast was ok. Apart from weird meat-with-marmalade thingy that I ate accidentally. Then a trip to university where actual competition will take place. I couldn't remember it's name if my life depended on it. Starts with J. We got here at 10pm so we missed registrations on Friday so we had to do late registration today. Got some prospects and an ugly t-shirt. Opening ceremony..blablabla...and a nice lecture on cryptology. Prezi and live demos. And a good delivery. +1 for that polish student. Now I finally understand elliptic curve cryptography.

And then an organization epic fail. They mis-planed for an hour and a half. So a quick walk to hotel was in order...because we didn't have wifi at the university. Another fail.
And another with lunch. They ran out of food(that wasn't even that good) and even drinks. Kinda disappointed here.
the university
Then the practice session. Apparently the polish take security very seriously. We had to show ids to enter. And weren't even allowed snacks in the computer room. Nothing special about the problems. We've solved some and ranked somewhere in the middle. Though it may be that this problems were easy compared with what's coming up, since a few teams solved all of them pretty much in matter of minutes.
But that's not the interesting part of the day. The interesting part was seeing Krakow. This is weird coming from my mouth since I'm not much of a travel person. But I truly enjoyed seeing a different culture. Although it would be much better if it weren't for dense fog that obscures anything more than 50m away. It destroys pictures too.
And polish cuisine isn't half bad too. We visited a restaurant with traditional polish food in city centre. Had some laughs about dish names and talking to the waitresses. Our coaches are some real funny(dare I say special) guys. Two mathematicians and a sysadmin(not sure??) with a thing for Slavic languages. I surely hope for more adventures.

Sunday, 20. pm

Well things started early today. Woke up at seven to pack stuff and have breakfast before checking out at 8am and leaving for the university. And I still can't remember it's name. I tried, I really tried.
Krakow at night. In fog.
There was a brief introduction with few announcements and at 9.30 the party started. It was some intense five hours. There were 11 problems and winners solved 10 of them. We've got correct results on 2 and ranked 56 among 77 teams. But I get my piece from knowing we've got correct ideas for two more and just got a few bugs in the code and nearly got the right approach for one more. But we've failed miserably at the last problem we solved. Oh yeah, in case you don't know at CERC you get a problem, write a program and then the test system compiles it and runs tests. If it passes all of them you get a point. Else you get nothing. So that was fun. I need more practice.
Then a weird spot in the schedule. Two hours of free time instead out food there wasn't anything special. Yes food is that important to me.
Colleague walking around with his ballons
There was a lecture on problem solutions afterwards...and the hardest problems were really puzzling. Especially the one nobody solved. I didn't get any of that. It would probably help if I've read the problem statement.
Oh yeah, the really cool part is you get a helium balloon attached to your table when you solve a problem. So you can see how everybody is progressing. Like you need that when you have online real-time ranking...but it's fun having balloons.
The ceremony went on forever. They shown picture of half the teams and invited about 20 of them on stage. Banquet after was more of a failure too. More chatting and slovenian teams boarded the bus. And now' we're driving home. It's currently 8.34 an we've got something like 12 hours more to drive. Apparently we'll watch some movies, but it's gonna be one long ride. Not to mention sleeping on a bus leaves you in a much worse state. Neck pain, back pain, you-part-you-didn't-even-know-can-hur pain... Yay. CERC is in Krakow next year too, and Slovenia will probably be going with a bus again. But I still wanna qualify. Because despite all the inconveniences it means hanging out with cool guys, seeing a nice city, solving interesting problems and competing with some of the smartest people in my generation(there are many world gold medalists from central Europe). Now I just need to practice. And perhaps get a mentorship.

Enhanced by Zemanta

Saturday, November 17, 2012

Why Linux will never win the desktop


Don't get me wrong, I'm a huge linux fan. I use it on all my machines(even my phone, Android is basically linux) and even converted my sister and a few friends. But if you don't convert somebody, chance they'll try a new operating system is slim to none. Only geeks like me install funky stuff as their primary software just to try it.
But the major problem lies somewhere else. People hate making choices. And linux is all about choice. It gives you power and you choose what you'll do with it. And it starts with selecting selecting distribution.

You don't install linux. You install a distribution. You install Debian, Ubuntu, Slackware, Fedora... There's a sea of different versions what to choose! I would even argue that all this fragmentation hurts development. Sure it's great to have different implementations and approaches and let time what's the best. But there is also quite a lot of duplicate work being done. And this cost's time and money that could be put to better use.
Back to choices. I like choice. I have a problem and need a piece of software(or hardware) and spend a few hours(or days) browsing the web looking at pros and cons, reading reviews, testing stuff, or just surfing the ebay and hunt for good prices. I like to do this for fun. But I hate doing it when I need to get something done. And most people just need software to get stuff done. They don't care about open source spirit or ability to hack around...they just need something that solves their problem. And when you have a solution, why change? Why fix something that isn't broken?

I attended a great talk on future of web search(by @dusano) and somebody addressed this problem...”Why fix search if it ain't broken?”. Answer was along the lines of “Because if you don't somebody else will. And he will dominate the industry”. I'm not quite sure this is so true in the short run. It's like with promotions in the supermarket. People are used to buying one brand of product and consciously selecting another is equivalent to mental work. And people are lazy. So they'll avoid thinking about possibilities because frankly they don't care enough about value/price ratio of their coffee to invest their time into it.

And it's similar when it comes to software and computers in general. A colleague once said that people who don't understand how computers work shouldn't be allowed to use them(he's linux sysadmin), but I strongly disagree. People want to use computers as tools and they should be able to. Not everybody is a developer! And that's why MacOS is popular. See Windows is here from the dawn of time. At least from youngster like me who used computer for the first time in this millenia.
MacOS might be a BSD but it's only one and it's locked down. It doesn't give you options but everything works. Perfect for most people.

Luckily things are changing for the better. Ubuntu broke the “easy linux” taboo and make things friendlier. And on my laptop I have Linux Mint which is even better. Installation is super easy and everything works out of the box. And I'm writing this post because a friend posted a video about ElementaryOS which is another Ubuntu fork that looks very much Mac-esque.

So things like Ubuntu, Mint or Elementary might have a fighting chance on the desktop if they try real hard. But most of the converted users won't know they're actually running linux under the hood. Anyway I should stop blabbering about desktop and focus on post-pc era. But that's a whole other story.

Enhanced by Zemanta

Monday, November 12, 2012

Cool Monday: Scala Macros

Garden flower
Macro shot (Photo credit: Wikipedia)
For me the highlight of this week was discovering Bootstrap. I heard of it before but never looked into it. Probably because I wasn't doing web stuff. The thing is bloody awesome. Back on topic.

Scala 2.10 RC2 was released this Friday. Considering 2.9 had 3 RC releases, 2.10 final is probably quite near. And it brings some awesome features. One of them are macros

Macros

So what are macros basically? Code executed at compile time. And that's about it. 
So what is so great about that? Well you can do AST modifications and stuff that gets quite into compiler-plugin territory in your regular code. That means you can do pretty advanced stuff and do abstraction with performance. Oh yeah, you can also do type checking and emit compile-time errors. Safety first kids!

Usages

SLICK uses macros(in the experimental API) to transform scala expressions into SQL. At compile time! ScalaMock uses it to provide more natural API for testing. As said, you can use it for code generation or validation at compile time. Good library design will be able to minimize boilerplate code even further now. And some people will argue that macros make scala even harder language.

Type Macros

This is the best part for me. But unfortuntely it's not implemented yet. Or at least not dcumented. There are some methods with suspisious names in the API but no useful documentation. In all presentations this is referred to as "future work" but I still have my fingers crossed it makes it into final release.
So what's the fuss? Automatically generated types. Large scale code-gen. 
As in ability to programatically create types at compile time. As a consequence you can create whole classes with bunch of methods. And I already have a use case of my own. I want to make a typesafe ORM for Android that's super fast. I did YodaLib ORM while back. It uses reflection(although it's fast enough usually) and provides a Cursor that lazily wraps rows into classes. And you need to make sure by hand that your class coresponds to columns of your result set. Not very safe. I had an idea to make static-typed safe inferface for the database when I first heard about HList. You would do projection as a HList and result rows would be lazily wrapped into HLists. But using them for wrapping every row(possibly filling data in with reflection) would be a performance penalty. Not to mention a mess to implement. Now consider using a macro to generate code for wrapping. It would be no slower than accessing columns by hand. And a type macro would automatically create a case class for given projection. Heavens. I'm just waiting for official documentation on macros...this is a tempting project.
(oh yeah, it would manage your scema too, so you don't need to worry about consistency between your code and your schema)

Documentation

Here's scalamacros.org which gives some information. Also some quite useful slides. I hope now that 2.10 is in RC things stabilize, because in the milestone releases api was changing constantly. Nightly API scaladoc.... Proper documentation is apparently coming soon,

Le Code

A use case for macros, loop unrolling.
Below is a trivial sample of repetitive code.
class Manual{
    def show(n: Int){
        println("number "+n)
    }
    
    def code(){
        show(1)
        show(2)
        show(3)
        show(4)
        show(5)
    }
}
We can deal with repetition writing a loop. (Higher order function really)
for( i <- 1 to 5 ) show(i)
But this doesnt generate the same AST(and bytecode)!
Protip: use
scalac -Xprint:parser -Yshow-trees Manual.scala
to see AST after parsing.
Sometimes(rarely!) you want to unroll the loop to produce same byte code as typing all the iterations by hand.
Macros.unroll(1,5,1)(show)
With a proper unroll macro defined. I spent an hour to come up with this implementation...and then scalac started crashing on me... Is there something terrible in my code?
I gave up and went on to do useful stuff...But macros hear me! I'll be back.
import reflect.macros.{Context}
import scala.language.experimental.macros

object Macros {
  def unroll(start: Int, end: Int, step: Int)(body: Int => Unit) = 
    macro unrollImpl

  def unrollImpl(c: Context)(start: c.Expr[Int] ,end: c.Expr[Int], step: c.Expr[Int])(body: c.Expr[Int => Unit]): c.Expr[Any] = {
    import c.universe._
    val Literal(Constant(start_value: Int)) = start.tree
    val Literal(Constant(end_value: Int)) = end.tree
    val Literal(Constant(step_value: Int)) = step.tree

    val invocations = Range(start_value, end_value, step_value) map { n =>
      val n_exp = c.Expr(Literal(Constant(n)))
      reify{
        ((body.splice)(n_exp.splice))
      }.tree
    }
    c.Expr(Block(invocations:_*))
  }
}
Enhanced by Zemanta

Monday, November 5, 2012

Cool Monday: Hindley-Milner on a dynamic language

So I'm getting into type theory. Slowly. Note to self: read a proper book on this topic. I'm getting familiar with it through some practical applications. Namely scala and haskell. 
That same discussion about design patterns also included dynamic vs static typing. And I asked twitter about it. HairyFotr link this amazing talk about type inference to me. Basically there are two conclusions to be drawn
  • Every static typed language should have at least limited type inference. It's compiler's job to do so and quite trivial to implement.
  • Properly done static typed language provides all features the that dynamic typed languages can. Safely.
As I'm (still) implementing a language that happens to be dynamic(because I was too lazy to look-up how to do type checking) second point interests me more. 

Can I turn my language into a static one without changing syntax(adding type annotations) and losing features? That would be awesome!
After a day of thinking, answer seems to be YES!

Global type inference in a nutshell

So I want a dynamic-like syntax(no types anywhere). Good news is I don't have nominal types, so I can use inference to get structural types. 
Java, C# and many other mainstream languages use nominal typing at the level of the vm. This means that type A is a subtype of type B precisely when name of A is a subtype of name ob B. For example 
interface Foo{
    void method(int a);
}


interface Bar{
    void method(int b);
}
If you have a method that takes in an instance of Foo, you cannot pass an instance of Bar. Because Bar isn't subtype of Foo. Even though they are structurally the same. Fun fact: because JVM is designed like this, scala cannot have global type inference.
See, global inference(or "type reconstruction") looks at usages and reconstructs properties and structure.  Another example
a = b.c + 1
That would be legal scrat code(or python, ruby or many other things). You take b's property named c, add one to it and assign the result to a. So b must have property c. That's the first structural requirement. From the + operator you can see that this c must be numeric. And from this follows that a is also numeric as it's the result of this computation.
If this were a body of a method and b it's parameter, type requirement for be would be(in made up syntax) b: { c: Number } - object with member of Number type. But that doesn't give you no class names.
So why is this global inference? It goes through the whole block of code(usually a function body) and puts in stub types where it doesn't have enough info and then solves the system of requirements and substitutes back.

Possible problems

First of all, I have objects. This means I have to reconstruct object structure. This shouldn't be too bad. And you can quite easily figure out that A is subtype of B if set of requirements for A is a superset of requirements for B. 
Then there's "mutable types". I concluded that following code should be illegal
a = 1
a = "two"
as type of a should remain the same as in first assignment. This lets you reason about the code much more. But there's a hidden mutability. I use regular functions as object constructors returning a keyword "this" that evaluates to current scope. But throughout the body you still access this scope and it's type(it's an object after all) changes with every new (first) assignment and function definition. But this should be tracked through all possible code paths. Only problem is an if expression. Type of an if(and it's side-effects) can only be common super type of both then and else branch - an intersection of requirement sets. In a dynamic language you can reason about conditions and conclude when something should definitely be in scope and use it. Automatic reasoning about conditions? This could turn out tricky. Perhaps in later implementation.
An there's third an final problem(that I can see). Infinite types. I have not seen a practical usage but it doesn't work and that bothers me. Dynamic code in scrat just works, but same code translated to haskell yields a compiler error - "can't instantiate infinite type". But apparently infinite types can be detected, so maybe I can find a way to present them and it will compile. More about this soon.

Conclusion

There are some problems but I believe I can make it work. It would be super awesome to have a language that feels dynamic but gives you all benefits of static typing. Compilers should do the hard work after all! And they should be capable of inferring general enough types that all correct programs type check.
Or am I missing some important aspect that works only with dynamic types?

Otherwise...code coming soon.
Enhanced by Zemanta