One thing that is working against you here is that SC culture prefers to give a lot of alternatives, even when it may not be appropriate.
“How do I…?”
- You could do this, or this.
- Or this! Don’t forget about this!
- IMO this is the best way.
- But you could also do that…
And now you’re in the position of evaluating which of these is ideal. This requires background knowledge and context, which you’re still in the middle of learning.
So this type of discussion is sometimes not actually helpful, especially for beginners.
Starting over, then:
“Why isn’t q making a sound ,despite the console launching synths when executing q ?”
Was it, though? Did you see the “s” number going up?
“The method call play is stored within the variable q”
No, it isn’t. This is definitely never how variables work. Best to delete this idea from your brain.
A variable is a pointer to an object that exists somewhere in memory.
Objects are the results of expressions.
q = ... something...
means: Step 1. Evaluate “something” – this will produce an object as the result. Step 2. Change q to point to this result.
The result of { }.play
is a Synth. q
then refers to this Synth object.
q.free
then deletes that Synth object from the server (but this does nothing to change q in the language).
q
is still the synth object, but it’s defunct. So accessing q
simply calls up the old synth object, which isn’t doing anything.
Remember also that the only way SC does anything is with a method call.
In q
, where is the method call? Where’s the receiver and method selector? There’s not one. So this doesn’t take any action. It only gives you back a prior result.
At this point, semiquaver wanted to give you a q
that could make new synths. That’s valid but perhaps premature. In any case, writing an action into a function, and saving that function into a variable for reuse, is an important way to write clearer programs.
Then it really went off the rails with q.()
. This is a shortcut syntax. IMO it’s better to avoid shortcut syntax with new users because it’s confusing!
So to explain the hidden bits:
Let’s say that you have assigned into q a synth-making function: q = { { SinOsc.ar(110, 0, 0.1).dup }.play };
.
If you want it to do its thing – again, nothing happens in SC without a method call. So you need to call a method on the object stored in q.
This method is value
. When you send the message value
to a function object, it evaluates its stored instructions (which, here, are to play a function).
q.value;
In this case, q
declares no arguments, so there’s no argument list given to the value
message. But in other contexts, it could be myFunction.value(... args...)
.
Now the fun bit: SC allows the keyword value
to be omitted if it’s being applied as a method selector to an object. That would leave q.
– but this is ambiguous syntax – if it were allowed, then there could be some obscure uses of dots where the compiler couldn’t reduce it to one and only one meaning. So there needs to be something to disambiguate. And this is – when you’re leaving out value
, you must write an argument list in parentheses – always q.( ... something ...)
, never just q.
But then the argument list may be empty – so q.()
is a valid shortcut for q.value
without arguments. (It has nothing to do with events.)
Do you need to know all that right now? Probably not. If I were teaching you privately, I would not have gone into this at this moment. There are too many other concepts that are more important.
Do keep the thing about method calls in mind. It’s the top #1 rule in SC.
hjh