04. Functions and Other Functionality:
Filter:
Tutorials/Getting-Started | Tutorials > Getting-Started

04. Functions and Other Functionality

Getting Started With SuperCollider
WARNING: If you are using headphones or external speakers, it is recommended to set your volume low before playing the following example and then bring it up to a comfortable level. Raw synthesized tones can sometimes seem louder than music and the other forms of audio we usually listen to.

The easiest way to get sound from SC is to use the play Function. After making sure the server is booted, run the simple example below.

When you've had enough, stop the sound by pressing Ctrl-. (Cmd-. on macOS). This will always stop all running processes and sound in SC. You'll be using it a lot, so learn it by heart.

Not too inspiring? Don't worry, we're just getting started, and this is just a simple example to demonstrate Functions and sound. We'll take it apart a bit below.

Before we get to doing that though, let's learn a little about Functions in general.

A Function is just a reusable bit of code. You define a Function by enclosing code in curly brackets: { }. Here's an example:

The stuff within the curly brackets is what will get executed each time you reuse, or "call", or "evaluate" the Function. Note that this is written like an equation, i.e. f = {...}. This is not an equation in the mathematical sense, it's what's called an "assignment". Basically it allows me to name the Function I've created, by storing it in a variable called f. A variable is a name representing a slot in which we can store things, such as a Function, a number, a list, etc. Execute the following lines one at a time and watch the post window:

Both times it should say 'a Function'. Now, whenever we want to refer to our Function we can just use the letter f. That's in fact what makes it reusable! Otherwise we'd need to type the Function in every time.

Functions can also span multiple lines. Double-click on the first line to make sure everything between the parentheses is selected (all the code inside the curly brackets, but also the f =):

So how do we reuse it? Execute the following lines one at a time and watch the post window:

Our Function is an object, (i.e a thing that does something or represents something), which we have defined and stored in the variable f. The bit of code that says '.value' says evaluate this function now. This is an example of sending a message to an object. This follows the syntax someObject.someMessage. The dot must go in between.

Now, this next bit is a little bit tricky. In a given object, each message calls (calls means executes) a particular method. Different types of objects may have methods with the same name, and thus respond to the same message in different ways. Read it again slowly, as this is pretty important:

Different types of objects may have methods with the same name, and thus respond to the same message in different ways.

What's interesting about this is that the actual methods may differ in what they do, but as long as they implement a method with that name, they become interchangeable in your code.

A good example is "value". All objects in SC respond to the message "value". When you "call" a method, it always "returns" something. When you call the "value" method on a Function it will evaluate and return the result of its last line of code. The Function example below and will return the result on the last line (5):

Often methods simply return the object itself. This is the case with most objects and the message "value". The example below demonstrates this. (Everything to the right of the // is a "comment", which means that SC just ignores it. Comments are often used to leave notes on complicated or confusing pieces of code for future readers)

By using the "value" method Functions and other objects can be interchangeable in your code. This is an example of polymorphism, which is one of the powerful features of what's called Object Oriented Programming (OOP). Polymorphism means that different objects are interchangeable if they respond to the same message. More on this later.

Functions can also have what are called arguments. These are values which are passed into the Function when it is evaluated. The example below demonstrates how this works. See if you can guess what the result will be before executing it.

Arguments are declared at the beginning of the Function, using the keyword 'arg'. You can then refer to them just like variables. When you call value on a Function, you can pass in arguments, in order, by putting them in parentheses: someFunc.value(arg1, arg2). This is the same with any method that takes arguments, not just value.

You can specify different orders by using what are called keyword arguments:

You can mix regular and keyword style if you like, but the regular args must come first:

(Note that SC has no operator precedence, i.e. math operations are done in left-to-right order, and division and multiplication are not done first. To force an order use parentheses. e.g. 4 + (2* 8) )

Sometimes it's useful to set default values for arguments. You can do this like so:

Default values must be what are called literals. Literals are basically numbers, strings, symbols (more on these later), or collections of them. Don't worry if that doesn't totally make sense, it will become clearer as we go on.

There is an alternate way to specify args, which is to enclose them within two vertical lines. (On most keyboards the vertical line symbol is Shift-\ ) The following two Functions are equivalent:

Why have two different ways? Well some people like the second one better and consider it a shortcut. SC has a number of syntax shortcuts like this, which can make writing code a little faster. In any case you will encounter both forms, so you need to be aware of them.

You can also have variables in a Function. These you need to declare at the beginning of the Function, just after the args, using the keyword 'var'.

Variable and argument names can consist of letters and numbers, but must begin with a lower-case letter and cannot contain spaces.

Variables are only valid for what is called their scope. The scope of a variable declared in a Function is that Function, i.e. the area between the two curly brackets. Execute these one at a time:

You can also declare variables at the top of any block of code which you execute altogether (i.e. by selecting it all). In such a case that block of code is the variable's scope. Execute the block (in parentheses) and then the last line.

You may be wondering why we haven't needed to declare variables like f, and why they keep their values even when executing code one line at a time (i.e. have a global scope). The letters a to z are what are called interpreter variables. These are pre-declared when you start up SC, and have an unlimited, or "global", scope. This makes them useful for quick tests or examples. You've already encountered one of these, the variable "s", which you'll recall by default refers to the localhost server.

With arguments, we can see an example of how polymorphism works:

Start to see how this could be useful?

For more information see:

Functions, Function, Assignment Statements, Introduction to Objects, Literals, Scoping and Closure

____________________

This document is part of the tutorial Getting Started With SuperCollider.

Click here to go on to the next section: 05. Functions and Sound

Click here to return to the table of Contents: 00. Getting Started With SC