What makes you say the other code doesn’t look valid? As I said, irb likes it just fine; and even the Sonic Pi IDE likes both of the following two files just fine, so I don’t think it’s a syntax thing.
# file 1: don't use a class, do make the call to coalesce_e
def coalesce_e(&block)
end
def song_initialize()
coalesce_e {|y|}
end
song_initialize
# file 2: define a class, but don't call coalesce_e
def coalesce_e(&block)
end
class Song
def initialize()
end
end
song = Song.new
Yikes, okay, thanks for the discussion! I think avoiding classes won’t be too big a loss, though I think I’ll forge ahead through the Wild West of using blocks for now… but don’t worry, at least now I’ll know that when the horse thieves arrive there won’t be any police to call in for backup. =P
It would be super useful to know about any new functionality you’d like to work with that you could imagine implementing with standard Ruby but can’t express in Sonic Pi.
Sure. I’ll do my best to give a high-level explanation of what I’m trying to do, though you’ll have to forgive me – experience tells me that when I’m tied close in to the details of a project, I do a bad job of communicating to folks outside the project. Please tell me which places I’m not making sense or motivating my technical choices!
I’m dabbling with algorithmic composition; eventually I’d like to reach a point where I can just hit “go” and have some randomly shifting chiptunes playing in the background while I stream on twitch.
In the first versions of this, I did the composition on the fly; my live_loop invented one musical phrase at a time, played it all the way through, then began again. But more and more I found that the modifications I wanted to make were inter-phrasal. The very simple motivating example I’m using in the current refactoring that introduced class usage is to tie together the bassline notes from one phrase to the next, if one phrase’s bass note happens to be the same as the next phrase’s starting note. (N.B. this may mean planning several phrases ahead if some phrase has just one bass note!) I’d love to get into more complicated inter-phrasal planning eventually, though; e.g. planning when to replay an old motif with a slight variation, when and how to do key changes, and the like, that may require looking arbitrarily far in the past (or future, depending on how you look at it).
So the approach I tried is to do some high-level planning first (before entering the live_loop), then have the live_loop “just” play the music made by the plan. Since I want it to go indefinitely, for me this meant building a lazy, infinite plan object – that is, one which initially had just a small part of the plan, but which could be expanded on the fly as needed. You can see how this manifests as code in this branch, which uses Ruby’s Enumerator and a memoized version that allows multiple consumers to iterate over it of my own devising called MemoEnumerator.
Of course it doesn’t work at all, even after avoiding the syntactic pitfall described earlier in the thread… I’m still thinking about what alternate approach to take to deal with that. (Try the master branch if you want to see something that does work and does almost the same thing, minus tying together consecutive equal bass notes.) Suggestions welcome. =)