Search code examples
recursionclojureovertone

Using a metronome in a recursive function in clojure/overtone


Regarding the metronome function from the Clojure Overtone library, all the examples I've studied seem to use it like this: (Example taken from https://github.com/overtone/overtone/wiki/Live-coding)

(defn player [beat]
  (at (metro beat) (kick))
  (at (metro (+ 0.5 beat)) (c-hat))
  (apply-by (metro (inc beat)) #'player (inc beat) []))

(player (metro))

(for context: metro is a metronome instance; kick and c-hat play sounds) As you can see, the recursion is handled by the function calling itself. Apart from articles on overtone, most other Clojure articles recommend against this type of recursion, and advise using the recur function for better efficiency. So my question is: is there a better way of writing the above function?

Thank you, Niall


Solution

  • As far as I can see, this isn't really recursion. Instead, evaluation of the player function causes, as a side effect, a future evaluation of the function in the #'player var to be scheduled. The return value of this evaluation doesn't depend on the next evaluation, and each evaluation unspools from the stack before the next one starts.
    So there isn't actually a stack of self calls there that recur could collapse for us. Every call after the first comes from the same scheduler functions. If you did use recur then you would lose the ability to re-bind the var to different functions for live coding, so in the framework this seems to be the most versatile way of writing it.