Question

I want to make a CoffeeScript function that even if it is invoked multiple times, has its effects only run once.

Is one of these, or another way a good way to make a once-invokable function ? Is the extra do an issue or actually better ?

once_maker_a = (f)-> 
  done=false
  ->
    f.call() unless done
    done=true

once_maker_b = (f)->
  do(done=false)-> 
    -> 
      f.call() unless done
      done=true

oa = once_maker_a(-> console.log 'yay A')
ob = once_maker_b(-> console.log 'yay B')

oa()
yay A      #runs the function passed to the once_maker
undefined  #return value of console.log
oa()
undefined  #look, does not reprint 'yay A'

ob()
yay B
undefined
ob()
undefined

I know about http://api.jquery.com/one/ and http://underscorejs.org/#once but in this case using those libraries is not an option.

Was it helpful?

Solution

Is one of these a good way to make a once-invokable function?

As @UncleLaz stated in the comments, you're ignoring any arguments to the function. Also you don't memoize the return value of the function, and always just return true. If you're really only caring about side effects, then that might not be a problem.

Is the extra do an issue or actually better?

In your case it's an issue. Check out the compiled javascript. Even if you corrected the indentation, it's not better since it's just unnecessarily introducing another scope.

A better, minimalistic way might be

once_maker = (f) ->
  -> 
    f?.apply this, arguments
    f = null

(still not caring about the return value)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top