First-class functions should be a part of every language. It's funny that this incredibly powerful idea is usually the basis of the computer science curriculum, but it finds little application in modern programming practice.
There's an obvious reason for this: the dominant programming languages (Java and C++) don't have 'em. The lack of them in C++ is excusable; functions-as-a-datatype is a little beyond the close-to-the metal features one expects from C++, but I think their absence in Java is bizarre.
I think there's another, more subtle, reason that you don't see wide adoption of first-class functions in commercial software: the closure idea is hard to grok, and it feels obtuse in languages where you can even treat a plain 'ol int as an object.
I like Javascript's implementation of functions (though once again the syntax is a little off-putting.) There are two ways I can write a function in Javascript. One is like this:
function highPass( x ){
return x > 10 ? x : 10;
}
The other is like this:
highPass = function( x ){
return x > 10 ? x : 10;
}
Either way, these statements are true:
highPass( 12 ) == 12;
highPass( 5 ) == 10;
These are in every way equivalent; the name-in-the-declaration syntax is just a special case of assigning a function to a global slot.
One interesting note: if I define an object
var o = { n : 10 };
And then attach a function to it:
o.lowPass = function ( x ){
return x < this.n ? x : this.n;
}
I can call that function as a method of o. So
o.lowPass( 12 ) == 10
is true. However, a reference to o.f is not bound. So if I write this:
var g = o.lowPass;
This statement is true:
g( 12 ) == undefined;
The reason for this is that there is no 'this' context for the function g. The global g slot is a reference to f, not a reference to f-in-the-context-of-o.
Here's a little Laszlo unit test to make sure I'm not making any of this up:
The ECMA-262 spec includes syntax for emulating a bound reference, although you have to remember both the function to call, and the object to call it on.
//call is unimplemented in Laszlo
var p = { n : 15 };
g.call( p , 12 ) == 15;
The call syntax is nice becuase the original function doesn't even have to be a slot in the object p for this to work, but as I noted, "call" is not implemented in the Flash player.
One thing that's funny about "call" is that it is a little backward from the usual OOP paradigm. Usually, you want to ask an object which function to call based on its name, which is the basis of polymorphism. With the call syntax, the programmer retains a reference to a specific function, which may or may not be the one that the given object or class wants to define as this-is-what-I-do-when-you-call "f()".
As a side note, this deficiency in Javascript is the basis for Laszlo's delegates, which are essentially a little datum containing a callback context (the object) and the name of a function to call on it.
Anyway, there is a way to attach data to a function without any of this fancy object business, and I think it's pretty nifty. Although the ECMA spec includes closures, alas the Flash player does not. If the Flash player supported closures, you could write a function generator this way:
//this won't work in Laszlo
function makeFilter ( low, high ){
return function ( x ){
return x < low ? low : ( x > high ? high : x );
}
}
This relies on the magic binding of the anonymous function created inside the makeFilter to the scope in which it was created. Admittedly, if you've written an interpreter, this isn't quite as arbitrary as it seems, but if you're just an everyday programmer, it doesn't make a ton of sense, especially given the way that you can just add properties to just about anything in Javascript. Also, closures have the problem that the data which is bound to the function is implicit; there's no easy way to poke at the values for high and low once you've generated the closure.
Javascript offers a nifty alternative, wrapped (as usual) in bad syntax. Within the context of a function, the function itself can be referenced by using the callee property of the implicit arguments array. Here's a rewrite that uses arguments.callee:
function makeFilter ( low, high ){
var f = function ( x ){
var low = arguments.callee.low;
var high = arguments.callee.high;
return x < low ? low : ( x > high ? high : x );
}
f.low = low;
f.high = high;
return f;
}
This has the additional advantage that I can later inspect and/or change the values for low and high. Here's a little program that puts this to use filtering an array of random numbers.
I call the return type of makeFilter a pseudo-closure. If the Flash player followed the ECMA spec, I probably wouldn't have adopted this idiom, but now that I have, I prefer it to closures. I think it's easier to understand and maintain.
Here's a little program that adds a filter capability to arrays and then uses pseudo-closures to take advantage of it.
<canvas height="200">
<script>
<![CDATA[
Array.prototype.filter = function ( f ){
for ( var i = 0; i < this.length; i++ )
this[ i ] = f( this[ i ] );
}
]]>
</script>
<method name="initArray">
<![CDATA[
var a = [];
for ( var i = 0; i < 20; i++ )
a[ i ] = Math.floor( Math.random() * 100 );
return a;
]]>
</method>
<method name="makeFilter" args="low, high">
<![CDATA[
var f = function ( x ){
var low = arguments.callee.low;
var high = arguments.callee.high;
return x < low ? low : ( x > high ? high : x );
}
f.low = Number( low );
f.high = Number( high );
return f;
]]>
</method>
<attribute name="anArray" value="$once{ canvas.initArray() }"/>
<simplelayout spacing="10"/>
<text text="${canvas.anArray}" width="400"/>
<view>
<text y="2">Low: </text> <edittext id="lo" x="40" width="40" text="20"/>
</view>
<view>
<text y="2">High:</text> <edittext id="hi" x="40" width="40" text="80"/>
</view>
<button>Add filter
<method event="onclick">
var f = canvas.makeFilter( lo.getText() , hi.getText() );
canvas.anArray.filter( f );
//make the text field update
canvas.onanArray.sendEvent( );
</method>
</button>
</canvas>