H
Hubert Kauker
In a recent article about higher order JavaScript functions I found
the following example:
function testFor( fn ) {
return function() {
for( var i = 0; i < arguments.length; i++ ) {
if( fn( arguments ) ) return true;
}
};
}
Oops, I said to myself, what is this function doing?
Its argument fn is supposed to be a function, as its name fn and the
article's context
made sufficiently clear.
More precisely, reading the code reveals that it is supposed to be a
Boolean valued
function taking any Object argument. Right?
And what is the return function?
Clearly, it is a Boolean valued function taking any number of Object
arguments.
Note that "any number of ..." is quite different from "an array
of ...".
Well, good practice requires always to write comment in one's
projects, even on seemingly innocent and straightforward code.
It makes time consuming reasoning absolutely superfluous.
How could we comment the above example?
There are several ways.
First of all, we might write the usual kind of half-formalized prose:
@param fn a Boolean valued function of any Object
@return a Boolean valued function of any number of Objects which
returns true
as soon as fn sequentially applied to one of the given objects
returns true.
Attention: fn should not have side effects since it may not be
applied to
all given objects.
That requires a lot of reading, too.
Well, JavaScript has no formalism to write down type declarations, let
alone
type declarations for functions.
But we might use comments to write
Boolean Function(Object)
to denote the parameter type, and
Boolean Function( Object ... )
to denote the return type.
Note how I use "Type ..." to denote "any number of Type",
and to denote "array of Type" I would use "Type[]".
So, our example then might read like this.
/* Boolean Function( Object ... ) */
function testFor( /* Boolean Function( Object ) */ fn )
{
return function() {
for( var i = 0; i < arguments.length; i++ ) {
if( fn( arguments ) ) return true;
}
};
}
Outside the "function" keyword I write down the type of the return
value.
Inside the parameter list, each parameter is preceded by its own type,
and I would recommend to do that even if it were a simple type like
Object, Number, Date, or any other, even self defined, by which I mean
an instance of a self defined constructor function.
That is already pretty much clearer, isn't it?
And what is the type of the higher order function testFor itself?
This might be useful, if testFor itself were used as an argument in
another
function of even higher order.
So, here it is:
(Boolean Function( Object ... )) Function( Boolean Function( Object ))
== Arrow Notation ==
The above notation of function types might be called "functional",
because it
contains the Function keyword and the usual parentheses.
It is certainly intuitive in simple cases.
But it is not so easy to read in complex cases because of its many
redundant parts.
Therefore I am looking for a less cluttered notation which can be read
even better
for more complex higher order functions.
We shall convert from function notation to arrow notation.
Instead of writing
ReturnType Function( ParameterType )
we might just as well write
ParameterType -> ReturnType
Here the two-character sequence "->" is meant to faintly resemble an
arrow.
The advantage is that we can omit the Function keyword and the
parentheses.
Then our above type of testFor reads:
(Object -> Boolean) -> ((Object ... ) -> Boolean)
Of course, the complexity of this type requires that internal
parentheses are still being used.
However, since none of this notation is official JavaScript, it always
has to be placed inside comments.
So it does not really matter which alternative we choose, as long as
we make ourselves sufficiently clear.
So our above example might also be written like this.
/* (Object ... ) -> Boolean */
function testFor( /* Object -> Boolean */ fn )
{
return function() {
for( var i = 0; i < arguments.length; i++ ) {
if( fn( arguments ) ) return true;
}
};
}
That is pretty easy to read, I think.
Of couse, some further comment to this function might still be in
order, such as the warning about
side effects and the order of evaluation.
What do you think?
Do you practice a similar approach or do you know of other schemes?
Hubert
the following example:
function testFor( fn ) {
return function() {
for( var i = 0; i < arguments.length; i++ ) {
if( fn( arguments ) ) return true;
}
};
}
Oops, I said to myself, what is this function doing?
Its argument fn is supposed to be a function, as its name fn and the
article's context
made sufficiently clear.
More precisely, reading the code reveals that it is supposed to be a
Boolean valued
function taking any Object argument. Right?
And what is the return function?
Clearly, it is a Boolean valued function taking any number of Object
arguments.
Note that "any number of ..." is quite different from "an array
of ...".
Well, good practice requires always to write comment in one's
projects, even on seemingly innocent and straightforward code.
It makes time consuming reasoning absolutely superfluous.
How could we comment the above example?
There are several ways.
First of all, we might write the usual kind of half-formalized prose:
@param fn a Boolean valued function of any Object
@return a Boolean valued function of any number of Objects which
returns true
as soon as fn sequentially applied to one of the given objects
returns true.
Attention: fn should not have side effects since it may not be
applied to
all given objects.
That requires a lot of reading, too.
Well, JavaScript has no formalism to write down type declarations, let
alone
type declarations for functions.
But we might use comments to write
Boolean Function(Object)
to denote the parameter type, and
Boolean Function( Object ... )
to denote the return type.
Note how I use "Type ..." to denote "any number of Type",
and to denote "array of Type" I would use "Type[]".
So, our example then might read like this.
/* Boolean Function( Object ... ) */
function testFor( /* Boolean Function( Object ) */ fn )
{
return function() {
for( var i = 0; i < arguments.length; i++ ) {
if( fn( arguments ) ) return true;
}
};
}
Outside the "function" keyword I write down the type of the return
value.
Inside the parameter list, each parameter is preceded by its own type,
and I would recommend to do that even if it were a simple type like
Object, Number, Date, or any other, even self defined, by which I mean
an instance of a self defined constructor function.
That is already pretty much clearer, isn't it?
And what is the type of the higher order function testFor itself?
This might be useful, if testFor itself were used as an argument in
another
function of even higher order.
So, here it is:
(Boolean Function( Object ... )) Function( Boolean Function( Object ))
== Arrow Notation ==
The above notation of function types might be called "functional",
because it
contains the Function keyword and the usual parentheses.
It is certainly intuitive in simple cases.
But it is not so easy to read in complex cases because of its many
redundant parts.
Therefore I am looking for a less cluttered notation which can be read
even better
for more complex higher order functions.
We shall convert from function notation to arrow notation.
Instead of writing
ReturnType Function( ParameterType )
we might just as well write
ParameterType -> ReturnType
Here the two-character sequence "->" is meant to faintly resemble an
arrow.
The advantage is that we can omit the Function keyword and the
parentheses.
Then our above type of testFor reads:
(Object -> Boolean) -> ((Object ... ) -> Boolean)
Of course, the complexity of this type requires that internal
parentheses are still being used.
However, since none of this notation is official JavaScript, it always
has to be placed inside comments.
So it does not really matter which alternative we choose, as long as
we make ourselves sufficiently clear.
So our above example might also be written like this.
/* (Object ... ) -> Boolean */
function testFor( /* Object -> Boolean */ fn )
{
return function() {
for( var i = 0; i < arguments.length; i++ ) {
if( fn( arguments ) ) return true;
}
};
}
That is pretty easy to read, I think.
Of couse, some further comment to this function might still be in
order, such as the warning about
side effects and the order of evaluation.
What do you think?
Do you practice a similar approach or do you know of other schemes?
Hubert