JavaScript Type Declarations

Discussion in 'Javascript' started by Hubert Kauker, Aug 24, 2009.

  1. 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
    Hubert Kauker, Aug 24, 2009
    #1
    1. Advertising

  2. Hubert Kauker wrote:
    > In a recent article about higher order JavaScript functions I found
    > the following example: [...]


    Is there also a legible variant of your posting?


    PointedEars
    --
    realism: HTML 4.01 Strict
    evangelism: XHTML 1.0 Strict
    madness: XHTML 1.1 as application/xhtml+xml
    -- Bjoern Hoehrmann
    Thomas 'PointedEars' Lahn, Aug 24, 2009
    #2
    1. Advertising

  3. On Aug 24, 10:59 am, Thomas 'PointedEars' Lahn <>
    wrote:

    > Is there also a legible variant of your posting?


    I am reading this posting in Firefox, and it looks quite ok.
    Even the indented parts of the function.

    What specifically are you hinting at?

    Hubert
    Hubert Kauker, Aug 24, 2009
    #3
  4. Hubert Kauker wrot:
    > Thomas 'PointedEars' Lahn wrote:
    >> Is there also a legible variant of your posting?

    >
    > I am reading this posting in Firefox, and it looks quite ok.
    > Even the indented parts of the function.
    >
    > What specifically are you hinting at?


    Your paragraphs are borken, and your posting style is rather long-winded.

    <http://jibbering.com/faq/#posting>


    PointedEars
    --
    Prototype.js was written by people who don't know javascript for people
    who don't know javascript. People who don't know javascript are not
    the best source of advice on designing systems that use javascript.
    -- Richard Cornford, cljs, <f806at$ail$1$>
    Thomas 'PointedEars' Lahn, Aug 24, 2009
    #4
  5. In comp.lang.javascript message <>, Mon,
    24 Aug 2009 10:59:17, Thomas 'PointedEars' Lahn <>
    posted:
    >Hubert Kauker wrote:
    >> In a recent article about higher order JavaScript functions I found
    >> the following example: [...]

    >
    >Is there also a legible variant of your posting?

    ^^^^^^^

    You really are obnoxious. It is to be hoped that you will not succeed
    in driving HK away. Perhaps HK can advise you about the provision of
    mental health services in Germany; another Kaiser is not needed.

    It's rather amusing that, in criticising HK's way of expressing himself
    in English, you yourself write faulty English. HK's article is exactly
    as legible, to each of us, as all other articles (apart from those in
    HTML); legibility is a matter of the distinctness of the displayed
    glyphs, and has nothing to do with the selection of the characters which
    they express.

    HK's English is, perhaps, not quite as elegantly effective as that of,
    for example, Winston S Churchill [1], but, for those who really know the
    language, it presents no significant problems.


    HK:

    Function testFor apparently processes a variable number of arguments
    with its first argument, until one is "liked". Possibly its for loop
    start with an index of 1.

    Argument fn can, in testFor, be given an argument of any type. But it
    is not necessarily intended that a specific instance of fn need be
    capable of usefully handling all types of argument; it is only necessary
    that the arguments of testFor, up to and including the one that is
    "liked", or the end, should be compatible with the fn of that call.

    One must consider side-effects of fn; but I see no reason to ban them.

    You have function testFor( /* Boolean Function( Object ) */ fn )
    Where it can be used, I think // comment is better; it does not fragment
    the code, and on seeing its beginning one knows instantly where it ends.

    Using Tab to indent is deprecated in News; I find two (or three) spaces
    generally better and easier on the eyes.

    When documenting languages or programs or anything else, one must
    consider who is to read the material. Within a closed group, such as a
    language development team, it is possible to have an efficient compact
    notation which has to be taught and learned. But where the group is not
    closed, documentation should require no more than an understanding of
    the natural language used. That is why the FAQ is wrong in introducing
    (and without explanation) an "@param" notation.



    [1] An exception to the normal English omission of middle initials; but
    he had good cause, as explained in the chapter "Oldham" of his "My Early
    Like" (recommended to those with a sense of humour) - and he was of
    semi-US descent.

    --
    (c) John Stockton, Surrey, UK. ?@merlyn.demon.co.uk Turnpike v6.05 MIME.
    Web <URL:http://www.merlyn.demon.co.uk/> - FAQish topics, acronyms, & links.
    Proper <= 4-line sig. separator as above, a line exactly "-- " (SonOfRFC1036)
    Do not Mail News to me. Before a reply, quote with ">" or "> " (SonOfRFC1036)
    Dr J R Stockton, Aug 24, 2009
    #5
  6. Hubert Kauker

    JR Guest

    On Aug 24, 6:34 am, Thomas 'PointedEars' Lahn <>
    wrote:

    > Your paragraphs are borken, and your posting style is rather long-winded.


    "borken"?

    ---
    JR, Aug 25, 2009
    #6
  7. JR wrote:
    > On Aug 24, 6:34 am, Thomas 'PointedEars' Lahn <>
    > wrote:
    >
    >> Your paragraphs are borken, and your posting style is rather long-winded.

    >
    > "borken"?


    From wikipedia: Borken or b0rken is internet slang for "broken," often
    referring to a computer program or a feature of a program that is not
    working as expected.

    Andrew Poulos
    Andrew Poulos, Aug 25, 2009
    #7
  8. Hubert Kauker

    JR Guest

    On Aug 24, 8:28 pm, Andrew Poulos <> wrote:
    > JR wrote:
    > > On Aug 24, 6:34 am, Thomas 'PointedEars' Lahn <>
    > > wrote:

    >
    > >> Your paragraphs are borken, and your posting style is rather long-winded.

    >
    > > "borken"?

    >
    >  From wikipedia: Borken or b0rken is internet slang for "broken," often
    > referring to a computer program or a feature of a program that is not
    > working as expected.
    >
    > Andrew Poulos


    Thanks. But "paragraphs are borken" might not be a good "posting
    style" recommendation.

    --
    JR
    JR, Aug 25, 2009
    #8
  9. Hubert Kauker

    SAM Guest

    Le 8/25/09 1:06 AM, JR a écrit :
    > On Aug 24, 6:34 am, Thomas 'PointedEars' Lahn <>
    > wrote:
    >
    >> Your paragraphs are borken, and your posting style is rather long-winded.

    >
    > "borken"?


    <http://catb.org/~esr/jargon/html/B/borken.html>

    --
    sm
    SAM, Aug 25, 2009
    #9
  10. Hubert Kauker wrote:
    > 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?


    This returns a function that tests an argument list and returns
    undefined or, if -fn- returns true for any argument, a boolean - true -.

    Who calls that function and what do they use it for.

    Whatever it is, it could be better.

    >
    > Its argument fn is supposed to be a function, as its name fn and the
    > article's context


    Calling something that is not [[call]]able would result in an error,
    functions are callable, but there are other things that are callable,
    too. Regexp, in SPidermonkey, for example:

    /a/('a');

    > made sufficiently clear.
    > More precisely, reading the code reveals that it is supposed to be a
    > Boolean valued
    > function taking any Object argument. Right?



    No, it's a tester function. - testFor - is to test to see if the
    argument list contains an argument for which - fn - will return true.

    That function uses - arguments - but could use an array instead. i.e.
    instead of:-

    testFor(obj1, obj2, obj3);
    - use: -

    testFor([obj1, obj2, obj3]);

    Some implementations will make an optimization, based on a lexical scan
    of the function. If it does - arguments - or - eval -, an arguments
    object won't be created.

    > And what is the return function?


    Sounds like your' e asking about the return statement returning a function.

    That function returns a function. The returned function has fn up the
    scope chain that contains - fn - which it uses.

    > Clearly, it is a Boolean valued function taking any number of Object
    > arguments.


    There is no test of the value returned whatsoever. The value returned
    gets passed to [[ToBoolean]] in the - if - statement.

    Not only is - fn - not required to return boolean, the returned function
    (that calls fn) returns boolean or undefined.

    > 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?


    I would reformat to spaces and mention the issues in comments that I
    think are bad ideas. They are:
    * variant return type,
    * questionable pattern usage
    * use of - arguments - object

    [postulation about type annotated comments]


    >
    > What do you think?


    That function is unclear, formatted with tabs, and doesn't have a
    consistent return type. What ever it is being used for, and I don't know
    what that is, but hwatever it is, it could be done better. More clearly
    and probably a lot more efficiently.

    Since you didn't provide one, here is an example of that function:-

    function catchFish(fisherman){
    return fisherman.luck > .9;
    }

    function Fisherman(i){
    this.luck = Math.random();
    };

    var fishermen = [];
    for(var i = 0; i < 5; i++) {
    fishermen.push(new Fisherman(i));
    }

    function testFor( fn ) {
    return function() {
    for( var i = 0; i < arguments.length; i++ ) {
    if( fn( arguments ) ) return true;
    }
    };
    }

    typeof testFor(catchFish).apply(null, fishermen);

    You can get better luck by adding more fisherman or changing "catchFish".

    > Do you practice a similar approach or do you know of other schemes?


    Commenting things that are obvious just so that JSDoc Toolkit would pick
    it up made the code less readable. Code that is littered with many long
    comments can be harder to read.

    I decided that code readability was more important than documentation.

    Clear variable names, simple functions that do only one thing. I comment
    what is unclear, or complicated. I comment browser issues with an
    example, where possible, e.g.

    // XXX Opera 1.3 needs a non-empty string; it won't set attribute if
    // second argument is "", so we use setAttribute(x, ";");

    Long functions are harder to follow and just adding comments won't help
    much.

    Closures are an exception to the "short functions" rule. These functions
    provides a lexical scope and does nothing else. They aren't procedures;
    they're functions used solely for the scope they provide.

    In javascript, function calls are more expensive than property access.
    This is usually only an issue in loops, animation, or mousemove.
    Refactoring a long function to many smaller ones usually helps
    readability, but this can come at a cost of performance and in a
    performance-critical function, it can be worth careful reconsideration.

    Garrett
    --
    comp.lang.javascript FAQ: http://jibbering.com/faq/
    Garrett Smith, Aug 25, 2009
    #10
  11. Hubert Kauker <> writes:

    > 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;
    > }
    > };
    > }
    >


    You are really just doing type annotation. You can do better, if you
    want good documentation.

    You might use a notation similar to Java's JavaDoc. That already
    exists, e.g., http://jsdoc.sourceforge.net/

    > Instead of writing
    >
    > ReturnType Function( ParameterType )
    >
    > we might just as well write
    >
    > ParameterType -> ReturnType


    Warms my old SML programmer's heart :)

    > What do you think?
    > Do you practice a similar approach or do you know of other schemes?


    I've seen JSDoc used (but haven't really used it myself).

    /L
    --
    Lasse Reichstein Holst Nielsen
    'Javascript frameworks is a disruptive technology'
    Lasse Reichstein Nielsen, Aug 25, 2009
    #11
  12. Hubert Kauker a écrit :
    > 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?


    Seems quite obvious. So obvious, in fact, that I personnaly find it more
    readable in the above form than in any natural language description I
    could provide.

    (snip long post)

    > 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.


    That's only line noise IMHO.

    > 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?


    That you're wasting your time.

    > Do you practice a similar approach


    Good god, hopefully not.

    > or do you know of other schemes?


    yes : only write useful comments - stuff like references to the specs or
    the explanation of a known algorithm, or eventually explanations about
    non-obvious or sub-optimal implementation points, so the maintainer at
    least has a chance to understand why this particular piece of code is
    written that way.
    Bruno Desthuilliers, Aug 25, 2009
    #12
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Roger Levy
    Replies:
    20
    Views:
    891
    Neal Gafter
    Jan 5, 2005
  2. jan V
    Replies:
    15
    Views:
    655
    Dale King
    Sep 12, 2005
  3. Wolfgang Meyer
    Replies:
    1
    Views:
    326
    Rob Williscroft
    Apr 24, 2004
  4. Marcus Lessard

    Mangled function type declarations?

    Marcus Lessard, Oct 17, 2003, in forum: C Programming
    Replies:
    1
    Views:
    347
    Eric Sosman
    Oct 17, 2003
  5. Mark 'Kamikaze' Hughes

    Re: does lack of type declarations make Python unsafe?

    Mark 'Kamikaze' Hughes, Jun 29, 2003, in forum: Python
    Replies:
    4
    Views:
    796
    Anton Vredegoor
    Jul 1, 2003
Loading...

Share This Page