Functions and the Fat Arrow

Functions are an incredibly useful feature of JavaScript (and any complete programming language). In this post, I’ll explain what functions are, describe how to use them, and list a few useful functions that can be used in many if not all of your sheet worker script blocks.

Possibly have a separate article for each type of these

  • Number conversion: int and num
  • Changes – avoiding typing change: over and over
  • sum/produce: directly targetting the values object
  • Javascript Features: Variables (and default values), Object Variable (inc. as database/lookup, getAttrs, setAttrs), Template Literal, Functions (and arrow functions), Callbacks/passing functions, Arrays: Map/Join, Filter, Reduce (needs its own article, inclue the different syntaxes that allow single line syntax, eg (acc[something]:curr, acc), Chaining functions
  • Fat Arrow Syntax – difference between function() and fat arrow syntax

This post is for those who already know how to use Sheet Workers and is a collection of function snippets I use in almost every character sheet.

What is a Function?

A function is any block of code you want to run on its own. Whenever you repeat code in a worker, you should make a function of it, and make it simpler to write.

In Roll20 character sheets, you often want to grab the attribute, coerce it to a number, and put in a variable. For example you do this:

const stat = parseInt(values.stat) || 0;Code language: JavaScript (javascript)

You might do that dozens or hundreds of times in a single character sheet, and might even do it several times in the same worker. So, you could copy much of that out into a function, a little bit of repeatable code, to save a bunch of typing.

<script type="text/worker">
function int(score) {
   return parseInt(score) || 0;
}
/* skip lots of code */
const stat = int(values.stat);Code language: JavaScript (javascript)

In this example, we have created a function called int. We create it once, at the start of the script block, and then can use it in every sheet worker in the format described. Typing int() is much simpler than typing parseInt() || 0 each time.

There are other advantages too. For example, if you want to add two numbers together, you must enclose each in a set of brackets, like so:

// this is wrong. 
const sum = parseInt(values.stat1) || 0 + parseInt(values.stat2) || 0;
// this is correct.
const sum = (parseInt(values.stat1) || 0) + (parseInt(values.stat2) || 0);
// this is better
const sum = int(values.stat1) + int(values.stat2;
// this is my preferred alternative (it's better for debugging)
const stat1 = int(values.stat1);
const stat2 = int(values.stat2);
const sum = stat1 + stat2;Code language: JavaScript (javascript)

That first one is deceptive. It might look correct, but bear in mind the position of the || boolean check. That says:

  • calculate parseInt(values.stat1);
  • if that is an error, calculate parseInt(values.stat2),
  • and if that is also an error, the result is 0.

This is one reason it’s better to separate grabbing each stat into its own calculation, like the last example, but using a function to calculate int avoids that problem.

Whenever you find yourself repeating similar code, it’s a good idea to figure out how to turn it into a function.

Function Parameters

In the above example, we created a score parameter. Scores are temporary variables created within the function. You pass a value to it, and the function treats the parameter as that value.

function int(score) {
   return parseInt(score) || 0;
}Code language: JavaScript (javascript)

You can create multiple parameters and even given them default values.

function int(score, default = 0) {
   return parseInt(score) || default;
}Code language: JavaScript (javascript)

In the first of the following two examples, we assume the default is going to be zero so we don’t have to specify it. In the second example, we specify a different default.

const stat1 = int(values.stat1);
const stat2 = int(values.stat2, 1);Code language: JavaScript (javascript)

Separate parameters with commas.

The Big Reason

The main reason to create functions is to reduce errors. If you have the same code repeated three times, or a hundred times, in your sheet workers, and decide you need to change them, you have to go through all that code and change them all. It’s very easy to create a small mistake in one or more of them.

If you use a function, you only have one set of code to change, and if you have an error in that code, you’ll spot it and correct it more easily. When you correct it for one place, it is corrected for all places that function might be used. When you do a lot of programming, this is incredibly useful.

Fat Arrow Syntax

There’s another way you can write functions, called the fat arrow syntax. This affects the first line of functions. The following two are identical*:

function int(score, default = 0) {
const int = (score, default = 0) => {Code language: JavaScript (javascript)

Notice that this replaces the word function with a variable declaration (const or let), then an = before the parameters, then that fat arrow.

One big advantage of fat arrow syntax is the ability to create a function as a single line item and removing the return statement. These are both the same way of writing the same thing:

function int(score, default = 10) {
   return parseInt(score) || default;
}
const int = (score, default = 10) => parseInt(score) || default; Code language: JavaScript (javascript)

Think of the fat arrow as “goes to”. I find the second version easier to write. But if there are multiple complicated statements in the function, you will need to use a code block.

Standard Roll20 Functions

Roll20 includes a lot of functions that aren’t explicitly called out as functions. The event line of a worker, and the getAttrs and setAttrs lines are all functions. You can use the fat arrow syntax with these.

on('change:stat', function () {
  getAttrs(['stat'], function(values) {
     /* some working */
};Code language: JavaScript (javascript)

It’s very common to write above with fat arrow syntax, like this:

on('change:stat', () => {
  getAttrs(['stat'], values => {
     /* some working */
};Code language: JavaScript (javascript)

Whenever you have the word function you can remove it on the left of the parameters, and put the fat arrow on the right side.

In practice, it doesn’t matter which you use, but the fat arrow syntax saves a bit of writing.

Other JavaScript Functions

You can use this technique with a lot of code. Remember to look for the word function. I often use it with forEach loops. Here’s a standard loop:

const output = {};
const stats = ['str', 'dex', 'con', 'int', 'wis', 'cha'];
stats.forEach(function(stat) {
   const score = int(values[stat]);
   const mod = Math.floor(score/2 - 5);
   output[`${stat}_mod`] = mod;
});
setAttrs(output);Code language: JavaScript (javascript)

This code loops through the six attributes and adds their value to the output object. This uses a lot of techniques already covered in this series – for example, the int function, and creating an output object using a template literal.

Here’s one way to write the code using Fat Arrow syntrax.

const output = {};
const stats = ['str', 'dex', 'con', 'int', 'wis', 'cha'];
stats.forEach(stat => {
   const score = int(values[stat]);
   const mod = Math.floor(score/2 - 5);
   output[`${stat}_mod`] = mod;
});
setAttrs(output);Code language: JavaScript (javascript)

And here’s an extremely compact version of the same code.

const output = {};
const stats = ['str', 'dex', 'con', 'int', 'wis', 'cha'];
stats.forEach(stat => output[`${stat}_mod`] = Math.floor(int(values[stat])/2 -5) );
setAttrs(output);Code language: JavaScript (javascript)

I personally wouldn’t compact the code this much, but it shows what can be done with the Fat Arrow syntax.

Code Snippets

I’ll shortly make another post describing some commonly helpful functions and may expand that file as time goes on. Watch for the Function Library post.

Series Navigation<< Template LiteralsStrings in Sheet Workers >>

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.