Archive for the ‘english’ Category

math explained

December 2nd, 2012

I've always found it really painful to read math. Yet I've never really been able to pinpoint why. It feels like using a really horrible piece of software where it's ridiculously hard to figure out what is what and how to do what you want.

Then it hit me. Math notation is a dead ringer for the International Obfuscated C Code Contest. I've always had this unarticulated sensation that when I read math, be it a textbook, a proof, anything with formal notation, I constantly have to decrypt the horrible code into its meaning and store that in memory. Eventually the number of symbols and operators grows to a point where I encounter an out of memory error.

If you've ever looked at what javascript looks like when it comes out of a minifier, you've noticed that descriptive function names and variable names have all been turned into identifiers like "a", "b" etc. Sure, on the web the size of the payload matters. But are mathematicians too embroiled in some misguided quest for Huffman coding?

People criticize c++ because you can overload the operators to mean anything you want. But math is such a cognitive overload of operators that it's worse than any c++. And people who need math to explain something formally routinely redefine operators to mean whatever they want.

You know what else math doesn't have? Scope. It's fabulous reading a paper with that tingling of anxiety because you never know when a symbol defined 10 pages back is about to make a comeback.

So in the end it's all operators and single identifier names in a global namespace, in a word: delightful. Holy cow, I *wish* we had awful Hungarian notation practices, it would improve the code by levels of magnitude. In fact, so many of the tips in the seminal How to Write Unmaintainable Code would be a godsend for math writing.

multi-lingual code cracking

June 10th, 2012

Spending time in our native language, where everything for the most part is clear, understood an unambiguous, gives us a skewed perception of what language really is like. Understanding quite effortlessly is something we get used to, and that's what makes our encounters with so-called foreign languages uncomfortable.

A language you know intimately is the exception. A great deal of language happens between individuals who communicate effectively despite their linguistic shortcomings. That to me is the real magic of language.

Dealing with a foreign language is always a matter of partial knowledge.

poster_afficheTake this poster and the word "affiche".

To begin with, Dutch has many French loan words and this is obviously one. "affiche" must be a noun, thus the corresponding verb is likely to be "afficher" or perhaps "ficher a" (to "ficher" at something or onto something).

In Polish "afisz" is a sign or a notice and it's simply a straight import from French.

In Spain recently I noticed it is very commonplace to write "prohibido fijar carteles" on all kinds of surfaces to discourage people from putting up posters. When you see that sentence on a wall that clearly has seen lots of posters torn down with remains of adhesive and dirt, the context is so clear that it's hard to misunderstand. "fijar" and "ficher" thus occur in a similar context.

Meanwhile, in Portuguese there is a very common word in "ficar" which is used in practically every context that has to do with entering a state of mind, eg. "eu fiquei feliz". This is very close to the Italian way of saying "sono rimasto deluso", where the verb to remain is used instead of, as in English, to become.

These three verbs are not exactly the same, but they have a strong common base of intention. "afficher" is the verb that corresponds to "fijar", ie. to fix or fasten something. Meanwhile, "ficher" has the metaphorical meaning of "ficar", namely to enter a state of mind.

exit yes, but not too quickly

April 7th, 2012

It's a weekday. It's morning. The train arrives at the destination full of commuters. The platform is mingling with commuters waiting to get on the train to go where we just came from. We disembark. A sea of people as these two streams conflate and confuse. As we head to the exits and they board the train we slowly disentangle. There are so many of us that a long line forms before the escalator down from the platform. Not even a line, more of a V-shaped traffic jam that extends to nearly the whole width of the platform. Slowly we converge on the escalator that shall deliver us from this overcrowded place. We could only wish the line were moving faster. Then, at last, we've made it, we step onto the escalator and... just stand there. All this waiting just to be able to stand in line some more? Yes, the escalator is moving, but why not walk down it? Especially since there are so many people, we'd be able to exit the platform quicker that way. But that isn't the custom. Apparently, if something moves us we must not move ourselves, we must appreciate and make it last as long as possible.

los compañeros

April 1st, 2012

- Bonjour, monsieur. Qu'est-ce que vous voulez manger?

- Bom dia.

- Non non non, Roberto, fais pas ça! Il faut toujours parler français avec les gens du pays quand on est en France. Sinon ils deviennent fous.

- Por qué? El portugués no es un idioma muy complicado. Yo entiendo fácilmente los turistas en Madrid cuando me preguntan el camino por algún lugar.

- Eu não falo francês, Michel. Só sei falar inglês.

- No, ça c'est pire encore!

- Ma rilassati, Michel. Che possono farci se non parliamo francese? Ci capiamo benissimo tra di noi. Questo basta per intenderci.

- Eu entendo tudo o que dizem os franceses. Assim eles podem entender-me também.

- Sí, esto me parece muy lógico.

- Alors, avez-vous choisi?

- Per favore, signore, non stia lì a spiarci facendo finta di non capire. O partecipi alla discussione o si allontani. Se non ordiniamo è perché non siamo pronti.

- Mas eu estou pronto, só que não posso pedir na língua justa!

- Yo también estoy listo para pedir.

- Guys, what the hell are you talking about?? I don't understand a damn word of what you're saying.

- Les mecs, nous avons oublié que David est avec nous!

monads for the layman

March 11th, 2012

I've done a fair bit of coding in Haskell, yet I could never fully understand monads. And if you don't get monads then coding Haskell is... tense. I could still get things done with some amount of cargo culting, so I was able to use them, but I couldn't understand what they really were.

I tried several times to figure it out, but all the explanations seemed to suck. People are so excited by the universality of monads that they make up all kinds of esoteric metaphors and the more of them you hear about the less you understand. Meanwhile there's no simple explanation to be found. That's when they're not simply too eager to skip ahead to equations that have them weeping like an art critic in front of the Mona Lisa and tell you all about the monadic laws as it that helps.

Fortunately, help is at hand, for today I will show you the first truly good explanation of monads I've ever seen, written by the charming Dan Piponi in the distant 2006 (I rather wish I had found it sooner). What I will do here is use Dan's method to explain it, using some python examples for easier comprehension, and keep it even more basic.

Rationale

monads_primitive_funcsIt's good to get this one straightened out right off the bat. Basically, it's nice to be able to have some piece of data that you can pass to any number of functions, however many times you want, and in whatever order you want. Imagine them lined up one after another like a pipeline, and your data goes through it. In other words: function composition. We like that because it makes for clear and concise code.

To achieve this we need functions that can be composed, ie. have the same signature:

def inc(x):
    return x+1

def double(x):
    return x*2

print "Primitive funcs:", double( inc(1) )
# Primitive funcs: 4

Logging functions

monads_logging_funcsSometimes, however, you find that you want to add something to a function that is not strictly necessary to participate in the pipeline. Something that is more like metadata. What if you wanted your functions to also log that they had been called?

def inc_log(x):
    return inc(x), "inc_log called."

def double_log(x):
    return double(x), "double_log called."

# This will not work properly:
print "Logging funcs:", double_log( inc_log(1) )
# Logging funcs: ((2, 'inc_log called.', 2, 'inc_log called.'), 'double_log called.')

# What we wanted:
# Logging funcs: (4, 'inc_log called.double_log called.')

Now, instead of each function taking one input and giving one output, it gives two outputs. So what happened when we ran it was this:

  1. inc_log received 1
  2. inc_log returned (2, 'inc_log called.')
  3. double_log received (2, 'inc_log called.')
  4. double_log returned ((2, 'inc_log called.', 2, 'inc_log called.'), 'double_log called.')
    Instead of doubling the number it doubled the tuple.

Restoring composability (bind)

monads_bindSo how can we solve this? It's not that hard. If you look at the diagram you see that inc_log produces two outputs, yet double_log should only receive one of these. The other should still be saved, somehow, and then joined with the output of double_log after it's finished executing. So we need a wrapper around double_log to change the arguments it receives and change the arguments it returns!

def bind(g):
    def new_g(pair):
        f_num, f_str = pair
        g_num, g_str = g(f_num)
        return g_num, f_str + g_str
    return new_g

new_double_log = bind(double_log)

print "Logging funcs:", new_double_log( inc_log(1) )
# Logging funcs: (4, 'inc_log called.double_log called.')

The name "bind" is not the most self explanatory imaginable, but what the wrapper does is just what we said in the description:

  1. Receive a pair of values.
  2. Call double_log with the first of these values.
  3. Receive a new pair of values from double_log.
  4. Return a third pair of values that we construct from the other pairs.

The key thing to notice is this: we have "adapted" double_log to be a function that accepts two inputs and returns two outputs. We could use the wrapper on any number of other functions with the same "shape" as double_log and chain them all together this way, even though their inputs don't match their outputs!

Mixing function types

monads_decSo far so good, but what if we now we want to mix logging functions with primitive functions in our pipeline?

def dec(x):
    return x-1

# This will not work:
new_dec = bind(dec)
print "Logging funcs:", new_dec( inc_log(1) )

Granted dec is not a logging function, so we can't expect it to do any logging. Still, it would be nice if we could use it without the logging.

But we can't use bind with dec, because bind expects a function with two outputs. dec simply does not have have the shape of a logging functions, so we are back to square one. Unless...

Using bind with primitive functions

Unless we could fake it, that is. And make dec look like a logging function. In the diagram we can see that there is a gap between the end point of dec and that of bind. bind is expecting two outputs from dec, but it only receives one. What if we could plug that gap with a function that lets the first output through and just makes up a second one?

def unit(x):
    return x, ""

monads_liftYes, just like that! Except that now we have two functions dec and unit, and we don't want to think of them as such, because we really just care about dec. So let's wrap them up so that they look like one!

def lift(func):
    return lambda x: unit( func(x) )

lifted_dec = lift(dec)
new_dec = bind(lifted_dec)

print "Logging funcs:", new_dec( inc_log(1) )
# Logging funcs: (1, 'inc_log called.')

So lift does nothing more than calling dec first, then passing the output to unit and that's it. dec+unit now has the shape of a logging function and lift wraps around them both, making the whole thing into a single function.

And with the lifted dec (a logging function should anyone inquire), we use bind as we've done with logging functions before. And it all works out!

The log says that we've only called inc_log. And yet dec has done its magic too, as we see from the output value.

Conclusions

If you look back at the diagram you might think we've gone to a lot of trouble just to call dec, quite a lot of overhead! But that's also the strength of this technique, namely that we don't have to rewrite functions like dec in order to use them in cases we hadn't anticipated. We can let dec do what it's meant for and do the needed plumbing independently.

If you look back at the code and diagrams you should see one other thing: if we change the shape of logging functions there are two functions we need to update: bind and unit. These two know how many outputs we're dealing with, whereas lift is blissfully ignorant of that.