Skip to content

Archive

Archive for March, 2012

Back to ZSH

Mar 16

A little while ago, I gave up on Zsh. There were a number of people that showed me how I could have fixed up Zsh so it would suck less, but I just didn’t have time. Well, I found myself with some time yesterday that couldn’t be spent doing much useful, so I made the switch.

It now feels like Bash but a little bit better, so I’m pretty happy. Thanks to @datanoise, and others for the tips.

Here’s what I did to make it useful:

  • unsetopt nomatch: I have no idea why this defaults to “on”. It’s useful about %0.00001 of the time and a pain in the bloody ass the other %99.99999 of the time.
  • Use bindkey -v instead of the vi-mode plugin: This is also odd. Most of what is needed (the prompt stuff) is pointless eye-candy and the zle reset-prompt is just an awful feature. You hit ESC-\ and it deletes the line above… which a lot of the time, carried data that you really wanted to read.
  • Ported my directory stacking stuff to Zsh (just barely :D). I can’t leave this feature behind… without it, running around the filesystem is a major drag.

My config can be found on GitHub if you’re interested in having a look.

I recently enjoyed a couple of days with Heiko Seeberger and Josh Suereth as they dragged me through some Advanced Scala Training and it was quite awesome. As an exercise, to test out my new found skills I pimped a new method onto “numbers” in Scala and I thought it might be instructive to share.

The Goal

The goal is really quite simple. All we want to do is add a new method, squared onto “numbers”. I don’t mean Int directly, but anything that Scala considers a number. We should see things like this:

5.squared    // == 25
25.0.squared // == 625.0

The Code

The code is wonderfully simple for this.

implicit def numeric2Powerable[A : Numeric](i: A) = new {
  def squared: A = implicitly[Numeric[A]].times(i, i)
}

Done. What we’ve managed to do in such a small amount of code is quite surprising. Let’s break it down.

  • implicit: The implicit puts the conversion definition into the local scope so that we can get a transparent conversion from our number to our pimped object.
  • [A : Numeric]: This is a context bound. It states that the type parameter we’re going to constrain this implicit conversion to must have an instance of the Numeric type class in scope. It’s this constraint that limits the types we’re pimping down to being numbers.
  • implicitly[...]: Because we’ve chosen the “clean” declaration for the context bound (as opposed to the slightly uglier curried parameter version) the instance of the type class has not been bound to an identifier that we can later use. In order to get access to the instance, we must “look it up”. Because scala.Predef is always imported by default, and because implicitly is defined there, we have access to it, and this is what we use to resolve the implicit instance.

The reset is self-explanatory.

That’s all there is to it. We’ve defined an implicit conversion from a number to a new pimp-class, used a type class to narrow the target types for the pimp, and pulled in the instance of the type class to give us a concrete tool to use in performing the computation. Not bad for a couple of lines of code.

Addendum: Missingfaktor showed me another little fun bit that you can add on to the code above to make the implementation feel more natural. We can import the implicits that are defined on Numeric to give us some infix notation instead.

implicit def numeric2Powerable[A : Numeric](i: A) = new {
  import Numeric.Implicits._
  def squared: A = i * i
}

It doesn’t change the API at all, but it does look a little niftier with respect to the implementation. It’s a little less simple, from an instructive point of view, because you start to wonder where the implicitly wandered away to. So, some more explanation is probably in order.

Specifically, what we’re importing is:

object Numeric {
  trait ExtraImplicits {
    implicit def infixNumericOps[T](x: T)(implicit num: Numeric[T]): Numeric[T]#Ops = new num.Ops(x)    
  }
  object Implicits extends ExtraImplicits { }
}

So, it’s really the infixNumericOps that we’re pulling in, and it’s delegating to Ops. So, what’s Ops?

Ops is defined as an inner class to the Numeric type trait and looks like:

class Ops(lhs: T) {
  def +(rhs: T) = plus(lhs, rhs)
  def -(rhs: T) = minus(lhs, rhs)
  def *(rhs: T) = times(lhs, rhs)
  def unary_-() = negate(lhs)
  def abs(): T = Numeric.this.abs(lhs)
  def signum(): Int = Numeric.this.signum(lhs)
  def toInt(): Int = Numeric.this.toInt(lhs)
  def toLong(): Long = Numeric.this.toLong(lhs)
  def toFloat(): Float = Numeric.this.toFloat(lhs)
  def toDouble(): Double = Numeric.this.toDouble(lhs)    
}

So, when we stitch this together, here’s what happens:

  1. We bring infixNumericOps into scope.
  2. We then invoke i * i, which is equivalent to i.*(i).
  3. The * can’t be found on i since i is of type A.
  4. However, now that we have infixNumericOps in scope, the compiler can use that conversion to create an instance of Numeric[A]#Ops.
  5. Numeric[A]#Ops does have * defined for type A, thus, a new Ops is constructued, holding our value i within it.
  6. The compiler then applies the * operator to to the second value of i and we’re done.

Cooler, but a hell of a lot more complicated to explain :)

I recently responded to someone’s question on StackOverflow and now I have to rant about something.

There is a large problem I find with programmers that I meet (generally in Real Life, as opposed to on the ‘net because on the ‘net I associate with passionate programmers) when it comes to learning new “stuff”. The first thing they do is try to draw it close to something they already understand. For example, they pick up Python and try to relate it to something like Java. This is not a problem.

The problem comes from the fact that it’s not just the first thing they do, it’s also the last thing they do. Why is this a problem? Oh for so many reasons…

It’s new

Relating this ‘new’ thing to something you are familiar with is vital in the first stages in order to get a foothold on a new experience. But once you’ve got that, you need to forget it.

Let’s take a new language as an example. If you’re a Java coder and you’ve never coded in Ruby before, then when you see Ruby you’re going to be looking for objects. This is all well and good, and it gets you into the language so you can start expressing your ideas. Awesome. But if Ruby was just a scripted Java then it wouldn’t have a lot of use, would it?

What you’re going to miss with Ruby (among about a million other things) is that Ruby is very much about functions and not so much about objects (Ok, I don’t want to get in a big debate with people here… I get it, it’s about objects too… and a lot of other stuff). And missing this means you’re going to miss out on a solid opportunity to enhance the way you think about designing and writing software.

Languages are not nearly as important as the paradigms they help you express. All we do for a living is think and the better you can think about your problems and their solutions, the better you are at what you do.

It’s not that other thing…

If the “other thing” you’re used to is worth anything at all, then it’s going to have some “good points” to it – it damn well better have. The “new thing” is going to have good points too, and they’re going to be different than those in your wheel house. If you’re used to feature X, chances are you’re not going to see feature X in this new thing. Why? It’s not that other thing. Seems obvious, right? If it’s so obvious then why do I see so many people not getting it?

Here’s an example. There’s a colleague of mine that loves Erlang – great language, and it’s awesome to love it. When talking about Akka, he asked me whether or not you could hibernate an Actor (closest equivalent to an Erlang ‘process’ as far as our discussion went). I said “no”. I was immediately met with statements like, “It must have that or it’s no good,” and stuff like that. What he didn’t grasp, until explained, was that Akka is modeled completely differently and has no need of the hibernate functionality. This is a fundamental difference between the two designs – and there are definite trade-offs being made for many different reasons. The point I’m making here is that, unless I explained it, he would have written off the technology based on a fabricated fantasy.

If you expect a new thing to be exactly the same as the old thing, then why would you look at the new thing? It’s not that other thing!

It misses the whole point

I’ve already said this earlier but it’s a very general idea. How many ways are there to solve problems in our industry? It’s pretty much infinite, right? I can select any language I want, for starters. I can then choose any tool within that language, or I can choose another language and bolt that on to help solve the problem. I can use existing programs or libraries from anywhere else to do it. And I haven’t even started coding yet. Once I start coding, I can code in nearly any paradigm I want to, or any hybrid set of paradigms that I want to (made easier by a multi-paradigm language of course).

So, let me ask you this: If all you know is one language, and one set of tools, and you view every other language and every other tool through the foggy lens of “what you already know”, then how many ways are there to solve problems when you’re the one solving it? Not many, right? You’ll probably come up with solutions, but if they suck, you’re stuck – you have no other tools in your head to help solve these things. You’re stuck with sucking. Not awesome.

The whole point of learning new things is to learn new things. Please, if you find yourself looking at something and scoffing and saying “Well, it’s not like this other thing that I’m comfortable with”, then say “GREAT!” If you find yourself outside your comfort zone then you’re doing it right.

If it were comfortable and familiar then you wouldn’t be learning, and if you’re not learning, then stop what you’re doing and go back to doing something productive with what you already know. Save that time for finding something to learn that you’re really not comfortable with.

Switch to our mobile site