Functions

Figures includes a set of functions for doing common tasks like finding the sine of an angle or the average of a list of values. The number of built-in functions is growing all the time, but sometimes these aren't enough. You may have calculations specific to your profession or hobby. Maybe you want to simplify financial calculations tailored to your accounts. Any time you have something you want to run repeatedly, you can wrap it up in a custom function.

Calling Functions

At its heart, a function is a task that takes a set of values and returns a new value. Here's a few examples of built-in functions:

round(pi)
random(1..10)
average(2, 3, 4)
cos(0)
3
4
3
1

You "call" a function by typing its name followed by a set of values called "arguments" inside parentheses. What arguments you can pass to a function depends on which function you're using. For example, the round function has a single argument that is the number to be rounded, but the average function can take more than one argument.

There are a few ways to know what arguments you can pass to a function. The easiest way is to use completions to insert placeholders for the arguments for you. You could also use the Quick Help feature to see a function's arguments if you Option-click on the name of the function. Finally, you can search the documentation for the function you're interested in.

Defining Functions

In addition to the built-in functions, you can also create your own. With a custom function, you can do a calculation as many times as you need with different arguments to tweak the result.

NOTE

Your custom functions can also be shared between different sheets in your document. This allows you to define some capability in one sheet and reuse it in any other sheet. See Importing for more on how to do this.

Basics

Every function is composed of a name, arguments, and a block of calculations. In the following example, we're creating a function that adds two values together. It begins with the fun keyword followed by the name of the function which is add. After the name is a set of parentheses that contain the arguments of the function. In the example there are two arguments, first and second.

fun add(first, second) {
    first + second
}

add(2, 3)
add(5, 6)




5
11

The block for the add function just adds first and second together. Since there's just one expression in the block, Figures will return the result as the value of the function. If you need more than one statement in the function block, you'll need to return a value using the return keyword.

NOTE

The return keyword is different than the Return key on your keyboard

In the next example, we'll create a function that finds the difference between two positive whole numbers. The function checks which value is larger, subtracts the smaller value, and returns the result.

fun difference(first, second) {
    if first > second {
        return first - second
    } else {
        return second - first
    }
}

difference(5, 2)
difference(2, 5)








3
3

It's also possible for a function to return nothing at all. When this happens the results will remain empty. Here's an example that only returns a result if it's positive.

fun add if positive(first, second) {
    sum = first + second
    if is positive(sum) {
        return sum
    }
}

add if positive(4, 2)
add if positive(-3, 1)







6

NOTE

Function names can be more than one word. Here, both our custom function and the built-in function is positive use more than one word.

The sum of 4 and 2 is positive, so the result of that function call is available. However, -3 + 1 is a negative number so no result was given.

Providing no value to the return statement is another way for a function to have no result. Here's a different approach to the last example:

fun add if positive(first, second) {
    sum = first + second
    if is negative(sum) {
        return
    } else {
        return sum
    }
}

add if positive(7, 9)
add if positive(5, -10)









16

Argument Labels

For some functions, it isn't always obvious what their arguments are referring to. Consider the following function that combines a couple previous examples. It adds two values, but it also provides an option to ignore a negative result.

fun add(first, second, allow negative) {
    sum = first + second
    if allow negative == false, is negative(sum) {
        return
    } else {
        return sum
    }
}

add(2, 3, true)
add(-5, 3, false)









5

The function works as intended, but it isn't clear to someone calling the function what that boolean (true or false) value means. If you were to return to this calculation days later, you'd have to go back and read the function's documentation to understand it. Argument labels can make a big improvement here.

An argument label is an extra name associated with an argument to help describe what it does. The argument label is followed by a colon and then the local name of the argument. Here's a revision of the last example to clarify:

fun add(first, second, allow negative: should allow negative) {
    sum = first + second
    if should allow negative == false, is negative(sum) {
        return
    } else {
        return sum
    }
}

add(2, 3, allow negative: true)
add(-5, 3, allow negative: false)









5

Now it's easier to understand what that boolean value is for. Notice that inside the function's block you use the local name which is should allow negative.

Something unique about Figures is that the argument labels are optional. You can just ignore them if you prefer:

fun add(first: f, second: s) {
    f + s
}

add(2, 5)




7

You can even add your own labels or change the existing ones:

fun add(f, second: s) {
    f + s
}

add(5, second: 3)
add(front: 2, back: 7)




8
9

So why include labels at all if they can be changed when the function is called anyway? First, the labels are included when the function is inserted using completions. This makes it convenient to use the labels as intended for readability. Second, labels allow you to use another function superpower: reordering arguments.

fun add(first, second, allow zero: zeros, allow negative: negatives) {
    sum = first + second
    if zeros == false, sum == 0 {
        return
    } else if negatives == false, is negative(sum) {
        return
    } else {
        return sum
    }
}

add(2, 3, allow negative: true, allow zero: false)











5

Normally arguments need to be given in the order they're defined. By using argument labels, you can give them in a different order as long as it's unambiguous which argument is which. This is useful for functions like in the example where arguments act as options to be set and there's no inherent order for those options.

Default Values

A function's arguments can be made optional by providing a default value for them. This makes it convenient when an argument usually has the same value, but you'd like to be able change it if you want. Let's say you want to find the distance from one number to another:

fun distance(from: first = 0, to: second) {
    second - first
}

distance(to: 5)
distance(from: 2, to: 5)




5
3

By providing a default value, that argument becomes optional when the function is called. The default can even be dynamic:

a = 2
fun add(first, second = a) {
    first + second
}

a = add(5)
add(3)





7
10

Variadic Arguments

If you need a function that can take any number of arguments, you can use a variadic argument. They're defined the same as other arguments except you add ... after the argument name. Inside your function that argument is made available as a list of all the values that were passed.

fun sum up(values...) {
    sum = 0
    for v in values {
        sum += v
    }
    return sum
}

sum up()
sum up(2, 5)
sum up(5, 3, 7)








0
7
15

NOTE

A variadic argument must be the last argument in the function

Functions as Values

Figures uses several different kinds of values including numbers, booleans, and lists. You can assign them to variables, compare them to each other, pass them as arguments to functions, and so on. Functions can also be used as values in the same way. In this example, you can assign a function to variable which effectively renames the function:

cosine = cos
cosine(0)
cosine(pi/2)
cos(_)
1
0

A very useful feature of treating functions as values is that you can pass them as an argument to another function. For example, the map function takes as arguments a sequence of values and a function used to transform them into new values.

map([0, pi/6, pi/2], sin)
map(-1..2, abs)
[0, 0.5, 1]
[1, 0, 1, 2]

map works by passing each element of the sequence through the given function and returning a list of the results. So in the first example, it will run sin(0), sin(pi/6), and sin(pi/2), putting those three results into a list and returning it.

You can write your own function that use this technique. Let's say you want a function that doubles numbers, but only if a function argument returns true. Otherwise they're removed from the results.

fun maybe double(values, function) {
    results = []
    for v in values {
        if function(v) {
            results = append(v × 2, to: results)
        }
    }
    return results
}

maybe double(-2..2, is positive)










[2, 4]

Didn't find what you were looking for?

Contact Us