Thursday, January 26, 2012

Anonymous function, part 2, win. Epic win.

I think I've figured out why anonymous functions are great, and here's why:
function doSomething() {
  var x
  if (someLogic) {
     x = somethingHere
  }

  var k = doOtherStuff()

  if (k) {
    x = k.something
  }

  if (x) {
    doSomethingHere(x)
  }
}

Looking at this, it becomes very easy to forget to set x, or to screw up dealing with x. This code is all backwards. the thing we care about is x, not all the crap around it.

function doSomething() {
  ((function(x) {
    doSomethingHere(x)
  })(someLogic ? somethingHere : 
       (function(k) {k ? k.something : null})(doOtherStuff())))
}


Why is this good? It looks a bit like a cluster-fuck at first glance. I think there are two reasons why it's good. And I'm going to talk briefly about why I've discovered I LOVE the ternary operator.

With the ternary operator, we have no choice but to declare the result for both sides of the conditional. We can't just fall through if we don't care, we always have to care. This means we eliminate lazy code paths. We can't accidentally forget about a potentially important condition. And that bubbles up to the overall logic. Instead of some complex chain of if then and honestly maybe, we have a clear decision tree. With sequential if statements we essentially create a new clause which I'm going to call "maybe".

To rewrite the line
if (someLogic) {
  x = somethingHere
}

to
x maybe assigned somethingHere if someLogic happens to be true

I know that doesn't really scan in some ways, because ultimately, x will definitely be assigned is someLogic is true. But, we're not saying what happens after that, and that's when it becomes a maybe. Because there is no code path on the negative side of k, by the time we reach our doSomethingHere call, x maybe somethingHere, or it maybe k.something, or maybe it's nothing at all!

If we make this function more and more complex it becomes increasingly hard to track what order things needed to be in and create a bug because we screwed up the if statement order. If the order is important, then it should have been nested properly not created sequentially, and that's where our crazy functional syntax comes in. You can't write code sequentially in this style. As a result, you have to express the conditions clearly as a decision tree.

Wednesday, January 25, 2012

Anonymous functions, epic win, or total fail?

As I've been working with Scala over the past weeks and months, I've started using the anonymous function construct a fair bit.  I like the way it wraps things up, and it seems like the best way to do certain things.

The same construct is available in some other languages, most notable Javascript, so something like:

function doSomething() {
  var o = document.getElementById('thing');
  o.innerHTML = "Stuff";
  o.style.height="300px";
  o.style.backgroundColor="#ffffff;"
}

could end up as:

function doSomething() {
  (function(o) {
    o.innerHTML = "Stuff";
    o.style.height="300px";
    o.style.backgroundColor="#ffffff";
  })(document.getElementById('thing');
}
why is this good?

I'm not entirely sure. I think that when you have multiple blocks and when you have multiple arguments it could help with scoping. I think it might make things clearer potentially, though I'm not so sure. It would mean the args to the function are at the bottom not the top. That could be seen as either a good thing or a bad thing.

I could see it being helpful syntactically when processing lists perhaps?

function doSomething() {
  (function(v,c) {
    for (var t = 0; t<v.length; t+=1) {
      v[t].style.backgroundColor=c;
    }
  })(document.getElementByTagName('div'),'#ffffff');
}

Or is it really just functional programming wankery that doesn't have any place outside the confines of Scala and other similar things?

I've noticed there is a way to call an anonymous function recursively too, but I think that is definitely descending into the realm of esoteric to the point of silliness.