perfection kills

Exploring prototype by example

Protolicious

May 27th, 2008 by kangax
Categories: Protolicious

Comments

  1. Gravatar

    Frederick Polgardy said:

    This is a nice little set of functional helpers!

    I recently had occasion to create a Function#guard method:

    Function.prototype.guard = function(test, fail_value) {
    var __method = this;
    return function() {
    return (test.apply(this, arguments) ? __method.apply(this, arguments) : fail_value);
    };
    };

    It returns a new function that applies a "guard" function to the original one, which will receive the same set of arguments. If the guard returns true, the result of calling the original method is returned; if not, the original method is not called, and fail_value is returned.

  2. Gravatar

    Dan Dorman said:

    Good work as usual, kangax.

  3. Gravatar

    bugrain said:

    I like addAdvice().

    Stick a load of these in a separate JS file that's only included locally/during development to get debug info without polluting your deployable/releasable code.

    Good job.

  4. Gravatar

    Frederick Polgardy said:

    Hmm, I'm not sure you want to be firing the same around function before and after the function you're advising. You won't know which time is which, especially if there is only one arg. I've done something like this using the more traditional AOP technique of calling the around advice and passing an "invocation object":

      Function.prototype.around = function(advice) {
        var _method = this;
        return function() {
          var _object = this, _args = arguments;
          return advice({
            method: _method,
            object: _object,
            args: _args,
            proceed: function() {
              return _method.apply(_object, _args);
            }
          });
        }
      }
    
      function add(a, b, c) {
        return a + b + c;
      }
    
      add = add.around(function(inv) {
        console.log('receiving: ' + $A(inv.args));
        var result = inv.proceed();
        console.log('returning: ' + result);
      });
    
      add(1, 2, 3);
    

    (Sorry this isn't indented, but the code tags won't do it.)

    Let me know what you think!

  5. Gravatar

    kangax said:

    @Frederick,

    #guard looks great. Would you mind sharing a couple of real life use cases?

    As far as #addAdvice, I never really needed to differentiate between 2 callbacks. The main concern was to ensure that "around" is executed after "before" and before "after" (sorry for a convoluted sentence :)

    Your #around looks very similar to prototype's Function#wrap:

    add = add.wrap(function(){
      var args = $A(arguments), proceed = args.shift();
      console.log('receiving: ' + $A(args));
      var return = proceed.apply(proceed, args);
      console.log('returning: ' + result);
    })
    

    I'm a fan of #wrap, but performing same "wrapping" pattern seemed a little too excessive : )

    @Dan, @bugrain

    Thanks guys.

  6. Gravatar

    Frederick Polgardy said:

    @kangax-

    Yeah, now that I see your example, I can see how wrap() does the job a little more generically. But I didn't originally write that function as a Prototype extension. :-) Anyway, I don't know what it is, but even though I *like* #wrap() in theory, the resulting code always seems just a little bit cryptic.

    I'll think some more about use cases for #guard. I've only used it in one case, and it was mostly a proof of concept.

    -Fred

  7. Gravatar

    Nicolás Sanguinetti said:

    w00t, nice. I've been following the github commits somewhat, but I'm too lazy to comment sometimes :P

    Function#not is great, even if it remembers me of Borat.

    Of runOnce I don't like the name. I see runOnce and somehow think of a method that will run once and be replaced by an "empty" function. (I think either moo or jquery--or someone else?--had something like this for events, where the handler would be run the first time and then the event gets disconnected, or the handler replaced by an empty function--can't remember exactly, but I could be wrong).

    I'm not sure of what'd be a better name tho.

    Overall, protolicious gets my thumbs up :-D

    (ps: and please, add some padding between paragraphs in the comments, the text looks too cramped)

  8. Gravatar

    Frederick Polgardy said:

    Yes, jQuery has a variation on .bind() for event handlers called .once(), that removes itself after the first time it's called.

    I think double newlines are being replaced with br tags, so you're not getting real spacing between paragraphs.

  9. Gravatar

    kangax said:

    Nic, good to see you around.

    I agree that runOnce is not the most descriptive name. Maybe: runImmediately, callImmediately, callReturn?
    Any suggestions are welcomed.

    I have just fixed comment formatting - it should look a little better now. Thanks.

  10. Gravatar

    Frederick Polgardy said:

    #invokeAndReturn()?

  11. Gravatar

    Pedro De Almeida said:

    Seems that the content of your post is not available! I can read comments but the text of Protolicious entry is empty...

    Safely delete my comment once you have corrected that ;)

  12. Gravatar

    kangax said:

    Pedro, My wordpress is bugging out. This post seems to exist in the database and is published, yet the body just doesn't display : /

  13. Gravatar

    TimC said:

    ref: missing body

    Looks like you've been hacked...check out your source code.
    Lots and lots of links after your body tag.

Trackbacks

Leave a Comment

Allowed tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong>