Can't access printer? it's *here*

#1

I’ve got a puzzling problem. Here’s a minimal but complete file that demonstrates it:

def coalesce_e(&block)
end

class Song
	def initialize()
		coalesce_e {|y|}
	end
end

song = Song.new

If I load this file in irb, all goes smoothly. But if I load it in the sonic pi IDE, when I hit Run I get an error:

Runtime Error: [buffer zero, line 10]
 undefined method `coalesce_e' for #<SonicPi::RuntimeMethods::Song:0x0055b27e5624b8>
workspace_zero:6:in `initialize'
workspace_zero:10:in `new'
workspace_zero:10:in `block in __spider_eval'
/usr/lib/sonic-pi/server/sonicpi/lib/sonicpi/runtime.rb:741:in `eval'
/usr/lib/sonic-pi/server/sonicpi/lib/sonicpi/runtime.rb:741:in `block in __spider_eval'

At this point I feel a bit like Eddie Izzard talking to his new computer saying, “Can’t access printer? It’s here!”. What am I doing wrong?

In case it matters, I’m using v2.10 ‘Cowbell’ as installed from the Ubuntu 18.04 package manager.

0 Likes

#2

Try replacing ‘def’ with ‘define’.

However, none of your other code look like
valid SP syntax to me, so expect other
errors ?

Eli…

0 Likes

#3

Hm. If I replace def with define I get a syntax error.

Syntax Error: [buffer zero, line 2]
 syntax error, unexpected keyword_end, expecting end-of-input
[Line 2]: define coalesce_e(&block)

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
0 Likes

#4

Mmm… mostly I’ve just never come across people making new classes in SP…
thats more Ruby perhaps, than it is SP…

Not that I’m in any way an expert, so please ignore my wanderings :slight_smile:

Eli…

0 Likes

#5

Hi there, @Eli is correct, defining classes in Sonic Pi isn’t officially supported.

It’s important to not that whilst Sonic Pi is implemented in Ruby, it isn’t Ruby (although it’s pretty close).

Here’s a more thorough explanation: MIDI loop/recording

0 Likes

#6

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

0 Likes

#7

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.

0 Likes

#8

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. =)

0 Likes