[Prototype-core] Re: Suggested addition to Function Methods: .repeat(seconds[, arg...]) -- Revised from Robert's version

2009-06-25 Thread joe t.

Rick,
Maybe i'm missing how that revision works, but it appears to me that
your stop property doesn't actually stop the repeater. Your stop
returns before further execution happens, but the timeout ID for the
window still exists.

What am i missing?
-joe t.


On Jun 24, 12:20 pm, Rick Waldron waldron.r...@gmail.com wrote:
 I made a few modifications to your version, allowing repeat() to behave like
 delay() with regard to arguments

 I've posted a demo here:

 http://jsbin.com/ekone

 All the output is to the firebug console... i've included fbug lite just in
 case

 Rick

 On Wed, Jun 24, 2009 at 10:50 AM, Rick Waldron waldron.r...@gmail.comwrote:

  I've subbed my implementation with your to do some use-case testing. I'll
  report back anything of interest as I go along.

  Rick

  On Wed, Jun 24, 2009 at 10:49 AM, Rick Waldron 
  waldron.r...@gmail.comwrote:

  This is fantastic feedback - thanks!

  On Wed, Jun 24, 2009 at 9:55 AM, Robert Kieffer bro...@gmail.com wrote:

  I can't say I'm a big fan of this.  For several reasons.

  First, it's just a cosmetic replacement for setInterval(myfunction
  (...).bind(), ...) which simply isn't all that bad.

  Second, I'm not a fan of setInterval in general.  I've seen some
  rather nasty behavior with calls queuing up if the invoked function
  takes longer than the delay to execute.  In particular, this seems to
  be an issue if you do something like put a laptop to sleep.  (But
  maybe others haven't seen this problem???)  Thus, I prefer to use a
  self-invoking timeout like so:

  function myFunction() {
     // do stuff ...
     // call ourselves again
     if (/*we want to continue?*/) setTimeout(myFunction, 1000)
  }

  This doesn't call the function at exactly one second intervals, but
  that type of accuracy is rarely important.  Instead, it guarantees you
  have at least one second of delay between invocations, which for
  distributing cpu load or polling (the more common cases where
  setInterval might be used), is more desireable.

  Finally, as Joe T. points out, there should be a way of cancelling the
  interval that doesn't require the user to store the returned value
  (*that* is what I find most annoying, not the syntax of
  setInterval).

  Thus, I'd suggest this instead:

   Object.extend(Function.prototype, {
     repeat: function(delay) {
       // Reset state
       if (this._repeater) delete this._repeater;
       this._repeatTimeout = clearTimeout(this._repeatTimeout);

       if (!delay) return; // (stop repeating if no args or delay==0)

       // Create setTimeout-based invoker
       var _method = this;
       if (!this._repeater) this._repeater = function() {
         // Let _method cancel repeat by doing return false;
         if (_method() !== false) setTimeout(_method._repeater, delay);
       }

       // Start repeating
       this._repeatTimeout = setTimeout(this._repeater, delay);
     },

     stopRepeating: function() {
       this.repeat();
     }
   });

  For example:

   var count = 0;
   function foo() {
     console.log(count++);
     return count  10;  // Return false when count = 10 to cancel
  the repeat
   }

   // Start repeating 1/sec
   foo.repeat(1000);
   //... some time later change interval to 2/sec
   foo.repeat(500);
   // ... later still stop repeating.
   foo.stopRepeating();

  As you can see, this implementation of repeat() does a lot more for
  you than simply alias'ing setInterval:
   - It guarantees your function is only invoked by one interval
   - It makes changing the interval or cancelling it altogether
  trivial.
   - It allows you to conditionally cancel the repeat from w/in the
  function itself.

  The only thing missing is the bind() behavior but, well, that's what
  bind is for.   If you need to bind arguments, just bind() your
  arguments first.

  On Jun 23, 8:25 am, Rick Waldron waldron.r...@gmail.com wrote:
   I detest the way setInterval() looks, so I came up with this... have
  been
   using it my personal JS for some time.

   Object.extend(Function.prototype, {
     repeat: function() {
       var __method = this, args = $A(arguments), interval = args.shift()
  *
   1000;
       return window.setInterval(function() {
         return __method.apply(__method, args);
       }, interval );
     }

   });

   // usage:
   var _pollInt = 0;
   function repetiousPollFn() {
    console.log(_pollInt++);

   }

   repetiousPollFn.repeat(.5);

   Will, of course, repeat repetiousPollFn() every half second.

   Almost identical to .delay(), except that it returns setInterval
  instead of
   setTimeout. One thing I intend to add is support for clearInterval,
  however
   I figured I'd at least bring it up here first. I've never
   proposed/contributed here before (i'm a lurker of the list :D ) - any
   guidance is appreciated.

   Rick


--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Prototype: Core group.
To 

[Prototype-core] Re: Suggested addition to Function Methods: .repeat(seconds[, arg...]) -- Revised from Robert's version

2009-06-25 Thread Rick Waldron
Note this last revision brings back a bit more of Robert's version, it's
more 50/50 now.


Rick



On Thu, Jun 25, 2009 at 12:53 PM, Rick Waldron waldron.r...@gmail.comwrote:

 You're right... It appears i copied the source in a bit hastily. After
 re-examining, I've revised again...

 http://jsbin.com/ajoqu

 Rick




 On Thu, Jun 25, 2009 at 9:37 AM, joe t. thooke...@gmail.com wrote:


 Rick,
 Maybe i'm missing how that revision works, but it appears to me that
 your stop property doesn't actually stop the repeater. Your stop
 returns before further execution happens, but the timeout ID for the
 window still exists.

 What am i missing?
 -joe t.


 On Jun 24, 12:20 pm, Rick Waldron waldron.r...@gmail.com wrote:
  I made a few modifications to your version, allowing repeat() to behave
 like
  delay() with regard to arguments
 
  I've posted a demo here:
 
  http://jsbin.com/ekone
 
  All the output is to the firebug console... i've included fbug lite just
 in
  case
 
  Rick
 
  On Wed, Jun 24, 2009 at 10:50 AM, Rick Waldron waldron.r...@gmail.com
 wrote:
 
   I've subbed my implementation with your to do some use-case testing.
 I'll
   report back anything of interest as I go along.
 
   Rick
 
   On Wed, Jun 24, 2009 at 10:49 AM, Rick Waldron 
 waldron.r...@gmail.comwrote:
 
   This is fantastic feedback - thanks!
 
   On Wed, Jun 24, 2009 at 9:55 AM, Robert Kieffer bro...@gmail.com
 wrote:
 
   I can't say I'm a big fan of this.  For several reasons.
 
   First, it's just a cosmetic replacement for setInterval(myfunction
   (...).bind(), ...) which simply isn't all that bad.
 
   Second, I'm not a fan of setInterval in general.  I've seen some
   rather nasty behavior with calls queuing up if the invoked function
   takes longer than the delay to execute.  In particular, this seems
 to
   be an issue if you do something like put a laptop to sleep.  (But
   maybe others haven't seen this problem???)  Thus, I prefer to use a
   self-invoking timeout like so:
 
   function myFunction() {
  // do stuff ...
  // call ourselves again
  if (/*we want to continue?*/) setTimeout(myFunction, 1000)
   }
 
   This doesn't call the function at exactly one second intervals, but
   that type of accuracy is rarely important.  Instead, it guarantees
 you
   have at least one second of delay between invocations, which for
   distributing cpu load or polling (the more common cases where
   setInterval might be used), is more desireable.
 
   Finally, as Joe T. points out, there should be a way of cancelling
 the
   interval that doesn't require the user to store the returned value
   (*that* is what I find most annoying, not the syntax of
   setInterval).
 
   Thus, I'd suggest this instead:
 
Object.extend(Function.prototype, {
  repeat: function(delay) {
// Reset state
if (this._repeater) delete this._repeater;
this._repeatTimeout = clearTimeout(this._repeatTimeout);
 
if (!delay) return; // (stop repeating if no args or delay==0)
 
// Create setTimeout-based invoker
var _method = this;
if (!this._repeater) this._repeater = function() {
  // Let _method cancel repeat by doing return false;
  if (_method() !== false) setTimeout(_method._repeater,
 delay);
}
 
// Start repeating
this._repeatTimeout = setTimeout(this._repeater, delay);
  },
 
  stopRepeating: function() {
this.repeat();
  }
});
 
   For example:
 
var count = 0;
function foo() {
  console.log(count++);
  return count  10;  // Return false when count = 10 to cancel
   the repeat
}
 
// Start repeating 1/sec
foo.repeat(1000);
//... some time later change interval to 2/sec
foo.repeat(500);
// ... later still stop repeating.
foo.stopRepeating();
 
   As you can see, this implementation of repeat() does a lot more for
   you than simply alias'ing setInterval:
- It guarantees your function is only invoked by one interval
- It makes changing the interval or cancelling it altogether
   trivial.
- It allows you to conditionally cancel the repeat from w/in the
   function itself.
 
   The only thing missing is the bind() behavior but, well, that's what
   bind is for.   If you need to bind arguments, just bind() your
   arguments first.
 
   On Jun 23, 8:25 am, Rick Waldron waldron.r...@gmail.com wrote:
I detest the way setInterval() looks, so I came up with this...
 have
   been
using it my personal JS for some time.
 
Object.extend(Function.prototype, {
  repeat: function() {
var __method = this, args = $A(arguments), interval =
 args.shift()
   *
1000;
return window.setInterval(function() {
  return __method.apply(__method, args);
}, interval );
  }
 
});
 
// usage:
var _pollInt = 0;
function repetiousPollFn() {
 console.log(_pollInt++);
 
}
 
repetiousPollFn.repeat(.5);
 
Will, of 

[Prototype-core] Re: Suggested addition to Function Methods: .repeat(seconds[, arg...]) -- Revised from Robert's version

2009-06-25 Thread Rick Waldron
You're right... It appears i copied the source in a bit hastily. After
re-examining, I've revised again...

http://jsbin.com/ajoqu

Rick



On Thu, Jun 25, 2009 at 9:37 AM, joe t. thooke...@gmail.com wrote:


 Rick,
 Maybe i'm missing how that revision works, but it appears to me that
 your stop property doesn't actually stop the repeater. Your stop
 returns before further execution happens, but the timeout ID for the
 window still exists.

 What am i missing?
 -joe t.


 On Jun 24, 12:20 pm, Rick Waldron waldron.r...@gmail.com wrote:
  I made a few modifications to your version, allowing repeat() to behave
 like
  delay() with regard to arguments
 
  I've posted a demo here:
 
  http://jsbin.com/ekone
 
  All the output is to the firebug console... i've included fbug lite just
 in
  case
 
  Rick
 
  On Wed, Jun 24, 2009 at 10:50 AM, Rick Waldron waldron.r...@gmail.com
 wrote:
 
   I've subbed my implementation with your to do some use-case testing.
 I'll
   report back anything of interest as I go along.
 
   Rick
 
   On Wed, Jun 24, 2009 at 10:49 AM, Rick Waldron waldron.r...@gmail.com
 wrote:
 
   This is fantastic feedback - thanks!
 
   On Wed, Jun 24, 2009 at 9:55 AM, Robert Kieffer bro...@gmail.com
 wrote:
 
   I can't say I'm a big fan of this.  For several reasons.
 
   First, it's just a cosmetic replacement for setInterval(myfunction
   (...).bind(), ...) which simply isn't all that bad.
 
   Second, I'm not a fan of setInterval in general.  I've seen some
   rather nasty behavior with calls queuing up if the invoked function
   takes longer than the delay to execute.  In particular, this seems to
   be an issue if you do something like put a laptop to sleep.  (But
   maybe others haven't seen this problem???)  Thus, I prefer to use a
   self-invoking timeout like so:
 
   function myFunction() {
  // do stuff ...
  // call ourselves again
  if (/*we want to continue?*/) setTimeout(myFunction, 1000)
   }
 
   This doesn't call the function at exactly one second intervals, but
   that type of accuracy is rarely important.  Instead, it guarantees
 you
   have at least one second of delay between invocations, which for
   distributing cpu load or polling (the more common cases where
   setInterval might be used), is more desireable.
 
   Finally, as Joe T. points out, there should be a way of cancelling
 the
   interval that doesn't require the user to store the returned value
   (*that* is what I find most annoying, not the syntax of
   setInterval).
 
   Thus, I'd suggest this instead:
 
Object.extend(Function.prototype, {
  repeat: function(delay) {
// Reset state
if (this._repeater) delete this._repeater;
this._repeatTimeout = clearTimeout(this._repeatTimeout);
 
if (!delay) return; // (stop repeating if no args or delay==0)
 
// Create setTimeout-based invoker
var _method = this;
if (!this._repeater) this._repeater = function() {
  // Let _method cancel repeat by doing return false;
  if (_method() !== false) setTimeout(_method._repeater, delay);
}
 
// Start repeating
this._repeatTimeout = setTimeout(this._repeater, delay);
  },
 
  stopRepeating: function() {
this.repeat();
  }
});
 
   For example:
 
var count = 0;
function foo() {
  console.log(count++);
  return count  10;  // Return false when count = 10 to cancel
   the repeat
}
 
// Start repeating 1/sec
foo.repeat(1000);
//... some time later change interval to 2/sec
foo.repeat(500);
// ... later still stop repeating.
foo.stopRepeating();
 
   As you can see, this implementation of repeat() does a lot more for
   you than simply alias'ing setInterval:
- It guarantees your function is only invoked by one interval
- It makes changing the interval or cancelling it altogether
   trivial.
- It allows you to conditionally cancel the repeat from w/in the
   function itself.
 
   The only thing missing is the bind() behavior but, well, that's what
   bind is for.   If you need to bind arguments, just bind() your
   arguments first.
 
   On Jun 23, 8:25 am, Rick Waldron waldron.r...@gmail.com wrote:
I detest the way setInterval() looks, so I came up with this...
 have
   been
using it my personal JS for some time.
 
Object.extend(Function.prototype, {
  repeat: function() {
var __method = this, args = $A(arguments), interval =
 args.shift()
   *
1000;
return window.setInterval(function() {
  return __method.apply(__method, args);
}, interval );
  }
 
});
 
// usage:
var _pollInt = 0;
function repetiousPollFn() {
 console.log(_pollInt++);
 
}
 
repetiousPollFn.repeat(.5);
 
Will, of course, repeat repetiousPollFn() every half second.
 
Almost identical to .delay(), except that it returns setInterval
   instead of
setTimeout. One thing I intend to add is 

[Prototype-core] Re: Suggested addition to Function Methods: .repeat(seconds[, arg...])

2009-06-25 Thread Rick Waldron
Thanks for the insight Tobie, definitely appreciated.


Function.prototype.repeat = function(interval) {
 return new PeriodicalExecuter(this, interval);
}

How to stop it? arguments?


This may come to you twice, but this is slightly updated:

http://jsbin.com/opimu


This repeat() method def is 775Bytes, accepts arguments like delay/defer,
uses setTimeout (returns initial setTimeout index) and has a stopping
mechanism.


Rick












On Wed, Jun 24, 2009 at 10:04 PM, Tobie Langel tobie.lan...@gmail.comwrote:


 Hi Rick, hi Robert.

 Fully agree regarding PE. It does however handle issues a regular
 setInterval doesn't (as you mentioned).

 It's clearly an area which would need refinement, but that's better
 done in a backwards compatible way.

 Personally, I'd love to see PE implemented as a method of Function
 instances.

 So since this is the core mailing list, I'm trying to give directions
 on how it could be best implemented given legacy constraints and
 consistency with the rest of the API.

 Clearly, consistency with Function#defer and Function#delay would
 imply returning a setInterval index. Unfortunately, since setTimeout
 is used instead of setInterval, this isn't possible.

 Maybe the simplest solution would be to make Function#repeat return an
 instance of PE. Implementation would then be roughly:

 Function.prototype.repeat = function(interval) {
  return new PeriodicalExecuter(this, interval);
 }

 Note that in that case, modifying Function#delay and Function#defer to
 return a PE-like object instance with a stop method would make more
 sense API wise, but at the expense of a larger memory footprint and
 backwards compatibility.

 As you can see, making the right choice isn't simple.

 Best,

 Tobie

 On Jun 24, 11:28 pm, Rick Waldron waldron.r...@gmail.com wrote:
  Tobie,
 
  I had in fact looked into PeriodicalExecuter and to be perfectly honest,
  with no offense intended, i think it's usage syntax is hideous which is
 what
  led me to writing my own Function.prototype method instead, taking
  inspiration from .delay()
 
  It doesnt matter to me whether or not .repeat() makes it into the
 prototype
  core - I will always have it at my disposal, I simply wanted to share the
  concept with the group.
 
  I think everything I've said sounds like I'm in a bad mood, sorry about
  that! :D
 
  Rick
 
  On Wed, Jun 24, 2009 at 12:53 PM, Tobie Langel tobie.lan...@gmail.com
 wrote:
 
 
 
 
 
   Just to clarify the above: Prototype Core already contains a similar
   functionality: PeriodicalExecuter. The API is different but the
   functionality is the same.
 
   I'd strongly suggest looking into combining both approaches if you
   want your suggestion to be included in core and not just stay a thread
   in the mailing list. :)
 
   Best,
 
   Tobie
 
   On Jun 24, 4:50 pm, Rick Waldron waldron.r...@gmail.com wrote:
I've subbed my implementation with your to do some use-case testing.
 I'll
report back anything of interest as I go along.
 
Rick
 
On Wed, Jun 24, 2009 at 10:49 AM, Rick Waldron 
 waldron.r...@gmail.com
   wrote:
 
 This is fantastic feedback - thanks!
 
 On Wed, Jun 24, 2009 at 9:55 AM, Robert Kieffer bro...@gmail.com
   wrote:
 
 I can't say I'm a big fan of this.  For several reasons.
 
 First, it's just a cosmetic replacement for setInterval(myfunction
 (...).bind(), ...) which simply isn't all that bad.
 
 Second, I'm not a fan of setInterval in general.  I've seen some
 rather nasty behavior with calls queuing up if the invoked
 function
 takes longer than the delay to execute.  In particular, this seems
 to
 be an issue if you do something like put a laptop to sleep.  (But
 maybe others haven't seen this problem???)  Thus, I prefer to use
 a
 self-invoking timeout like so:
 
 function myFunction() {
// do stuff ...
// call ourselves again
if (/*we want to continue?*/) setTimeout(myFunction, 1000)
 }
 
 This doesn't call the function at exactly one second intervals,
 but
 that type of accuracy is rarely important.  Instead, it guarantees
 you
 have at least one second of delay between invocations, which for
 distributing cpu load or polling (the more common cases where
 setInterval might be used), is more desireable.
 
 Finally, as Joe T. points out, there should be a way of cancelling
 the
 interval that doesn't require the user to store the returned value
 (*that* is what I find most annoying, not the syntax of
 setInterval).
 
 Thus, I'd suggest this instead:
 
  Object.extend(Function.prototype, {
repeat: function(delay) {
  // Reset state
  if (this._repeater) delete this._repeater;
  this._repeatTimeout = clearTimeout(this._repeatTimeout);
 
  if (!delay) return; // (stop repeating if no args or
 delay==0)
 
  // Create setTimeout-based invoker
  var _method = this;
  if