Friday, February 15, 2008

Dr. No vs. anonymous functions

You may remember the first James Bond movie where the hero gets into contaminated areas and thus gets the decontamination treat. Now, this doesn't just happen but is shown in quite some details. As if to show off 'hey, look, we know all this stuff' instead of simply assuming it.

Now there is a similar thing with the syntax of anonymous functions. In some languages it is like function (x) return 2 * x; end while others say the same as \x{2 * x}. The shorter syntax stand less in the way and makes it possible to write, say, list.filter (\x{x.city == quest}).map (\x{x.zipcode}) in one line, while the former notation will cause massive keyword clutter hiding the actual operations.

There is a case in that the longer syntax may have been judiciously chosen to make clear that the use of anonymous functions (plus closures) is not encouraged in this language. I don't assume that it is a case of show-off, as in Cobol which needs to make clear that it can DISPLAY or COMPUTE something, as if this wasn't to be expected of a computer language. But the question remains, whether, in any specific language the form of anonymous functions wasn't just chosen because of its similarity to named functions. In named functions this is no big deal as their opening has a line for itself anyway. Anonymous functions need to be unobtrusive to be really useful, while the more verbose forms make many uses unwieldy. The question is whether the language designers really wanted to discourage that use or whether they didn't think quite that far in that direction, not having actively used functional style themselves.

Monday, February 04, 2008

The other ternary operator

There is an interesting stain on OO languages like C++ and Java, namely with member function invocation. Normally, complex expression can be taken apart, and the intermediate value stored in a variable. int a = 2 * (3 +1); can equally be written int helper = 3 +1; int a = 2 * helper;. However, this breaks with obj.meth (). When you try instead to say helper = obj.meth; helper ();, you will run into a problem: What is the type of helper? It should be a function pointer/reference. Java does not even have functions; in C++ you are equally at a loss for a proper type. (I'm not going into that actually the parameter types aka signature form a part of the method name.)

Indeed the compilers simply go to treat the combination a.b(c) as a single operator. In Java the method and member name spaces are actually separate; a method can have the same name as a member. (Does that make it a Java-2?)

The only language that makes this explicit is Lua. Member invocation is obj:meth(arg), which is the same as obj.meth(obj,arg) (except that obj is only evaluated once).

I don't know of any language that does it properly. Even though a member function exists as code only once, logically there is a distinct function for each object. The member selection needs to bind the function code address and the object pointer together, into something that is quite similar to a closure.

Custom syntax: Macros and closures

I'm lots interested in getting custom syntax for this and that where I get annoyed by C++ or especially Java simply not letting me doing any. For example, in Java you need to write all these EJB-style accessors yourself. In ruby you just say attr_reader :attr1, :attr2, and when reading other people's code you can be sure that there isn't a typo that let getAttr1 return attr2 by accident.

Just as I was embracing the idea that macros are absolutely necessary for much stuff,
ruby came along and brought block arguments. And tada, you can do map and everything without macros just as regular function. Some guys even ported the idea to java. So I became unsure whether macros are really necessary. Ok, basically I still believe that because (programmatic) macros can do anything; I think they are the best way to integrate custom code generators.

And then came along Raganwald and wanted something like ph = find_whatever()&&.author&&.phone: Call find_whatever, and if it returns something, get the author, and if there is one, get his phone number. Otherwise the whole expression is nil.

Now it is amazing that you can get ruby to do something like that at all, even though it cheats on two points: It does not use the intended syntax (obj&&.name) but obj.andand.name (note the conspicious second dot), and it does not actually take the shortcut but instead goes through the rest with a dummy object.

But he does not just to avoid the helper variables, but also to get a left-to-right reading. You just can't do that in lisp, for instance. (Ok, it's going to be the inverse.)

But why this hit me: While I have somes idea how I would bring macros into language with syntax, I have no idea yet how I would make &&. definable. The problems here:
  • When you get to the &&. you are already in the middle of the expression the macro would need to replace, so there would be a need to allow operators be a kind of macro

  • Member selection is not a binary, but a postfix operator! While it looks like one, the right hand side is not an expression, but a compile-time constant. (In a sense there are many different operators, one for each possible member name.)

I guess I need to think about that some more...how to enable user-defined operators not only as functions, but also as macros.

Saturday, February 02, 2008

Burned by override: Limits of refactoring by compiler

In OO programming (here: java) there is the difference between redefining a method in a subclass, and adding a new method in a subclass. It also is quite easy to accidentally add one instead of override one by having a subtly different method signature.

Then there is 'refactoring by compiler' as I call it. Just do the intended interface change at one place and be guided by the compiler errors to all the places that needs adatptions to that. In sufficiently static languages that does actually work (and it is a bit hard to get a program that compiles but does not work).

Anyway in this case I changed, compiled, fixed, and the program did not work in very strange ways. Well, it was the case from above: I started my refactoring by changing the signature of a overridden method, thereby making it into a new one that never got invoked. The macro did no longer think it was one, it went downhill.

Good thing scala requires to declare whether a method is an override. Java does too, but my personal java-fu is from times too old to actively use @override (or to sprinkle code with finals, for that matter).

Back to coding...