View on GitHub

pxt-reporter-blocks

Create custom blocks in MakeCode from functions that return values

Beyond The Blocks

Custom Reporter Blocks

Create Functions That Return Values to MakeCode

by David Sparks

Originated September 2019

This article will explain how to add custom blocks that execute a function and return a value to a MakeCode project.

Functions that return values become "reporter" blocks in MakeCode. They are shaped to fit the openings in the puzzle-piece blocks. You can use them like variable names. It will be easiest to introduce reporter blocks with the example in Figure 1.

Figure 1
Figure 1
A custom reporter block

How did we get this custom block? By writing specially-formatted code.

I made some assumptions about the knowledge level and the goals of people most likely to read this article. I imagine you:

Readers having some experience with coding may get the most value from this article. However, every reader is welcome and I hope this article will at least help you see that MakeCode can take you far beyond the standard blocks.

The topic of Functions is far too large to teach or to explain in a short article like this. The W3Schools web site offers a good introduction at the following link: JavaScript Functions.

The introductory articles in this series illustrated in detail the steps to create custom blocks using the MakeCode editor. Please refer to the articles listed below if you have a question about the steps. "Top Ten Tricks" also lists the references that I go to often when I need to look something up.

Open the custom.ts file in a new project. Quick reminder — click links in the MakeCode editor in the sequence listed below to open the custom.ts file in a new project.

  1. JavaScript button
  2. Explorer button
  3. plus sign ("+")
  4. "Go ahead!" button

Replace the default code in custom.ts with the listing in Exhibit 1, below. The syntax is important and this example will be discussed in detail later in the article. For now, it might be best simply to copy the code and paste it into the file, replacing what was there.

Exhibit 1
Code for a custom reporter block
/**
 * Custom blocks
 */
//% weight=100 color=#0fbc11 icon="\uf0c3"
namespace custom {
    /**
     * convert a temperature 
     * given in degrees Celsius (°C)
     * into its equivalent 
     * in degrees Farhenheit (°F)
     */
    //% block="fahrenheit|%celsius"
    export function fahrenheit(celsius: number): number {
        return (celsius * 1.8) + 32;
    }
}

Click the Blocks button to compile the code. Then refresh the browser to activate the new block. It will be in the "Custom" group that appears in the main blocks list. Use the block to convert negative 13.3333 degrees (below zero) Celsius into its equivalent: 8 degrees (above zero) Fahrenheit. (Figure 2)

Figure 2
Figure 2
Showing the Custom group and the fahrenheit reporter block being used.

Reporter blocks are oval-shaped for numbers and strings. For bookean values they are six-sided with pointed ends, like the true and false blocks in the Logic group.

Their shape gives a clue how to use them. They fit into openings in the stackable blocks that look like puzzle pieces.

MakeCode responds to the values returned by reporter blocks as if it were reading the value of a variable.


Exercise #1

Look through the standard blocks. 
Count the reporter blocks you find. 
Each one has code similar to Exhibit 1.
Now you have seen how create your own.

The Syntax of a Reporter Block

Every line of code listed in Exhibit 1 can teach something about writing custom reporter blocks.

The Comments

MakeCode examines the contents of comments. Sometimes it uses information from the comments when it builds a custom block from your code.

This feature of the MakeCode editor is important to understand for writing custom blocks. We will explain in the sections that follow.

It remains a good coding practice to include regular comments in your code.

A quick review of JavaScript comment syntax

Regular comments provide helpful documentation for humans to read but generally do not participate in the execution of your code at run-time.

JavaScript offers two ways to encode comments.

The Custom Group Metacode

MakeCode extends the idea of the single-line comment by adding a % character to define a special kind of comment, called metacode. These special comments give instructions for how to prepare your code.

The distinction between regular comments and metacode comments deserves some emphasis.

Metacode comments begin with //%, followed by definitions. A definition is a name=value pair.

The Custom group metacode precedes the namespace (discussed next) and tells MakeCode how to set up the Custom group.

//% weight=100 color=#0fbc11 icon="\uf0c3"

A metacode comment line can contain more than one instruction. This example has three:

The Namespace

Custom blocks must be coded inside a JavaScript namespace. The following lines selected from Exhibit 1 declare and enclose the namespace.

Notice the curly brackets that must be present both before and after the actual custom block code.

namespace custom {

    // your code goes here
    // between the curly brackets

}

The Pre-Block Comment

Make a habit of providing a pre-block comment for each of your custom blocks. The format resembles a JavaScript multi-line comment, with some special detail.

The first line will have a slant followed by two asterisks: /**.

Lines that begin with an asterisk followed by plain text will become the "help" text for your custom block. You can see this illustrated in Figure 1, above.

Use tabs and space characters to line up the asterisks carefully. Follow the pattern presented in the listing below, and in Exhibit 1.

The final line will have an asterisk followed by a slant:*/

Here is the complete listing for the pre-block comment of the fahrenheit block:

    /**
     * convert a temperature 
     * given in degrees Celsius (°C)
     * into its equivalent 
     * in degrees Farhenheit (°F)
     */

The Essential //% block Metacode

The official documentation for custom blocks states, "Any exported JavaScript function can be turned into a block by simply adding a //% block comment."

In other words, you must precede the code for your block with this metacode:

//% block

It tells MakeCode to prepare the code that follows as a block.

The //% block metacode is an exception to the usual name=value format for other metacodes. //% block does not require a value.

If no value is supplied, MakeCode will by default use the name of the function as the name of the custom block. However, if you want to include a parameter in the block then you need to supply a formatting string as the value for the //% block metacode. The string determines the visual presentation of the custom block.

The fahrenheit block in our example incorporates a parameter. It must tell MakeCode where to place the parameter in the block. The fahrenheit block's formatting string places the parameter at the end:

    //% block="fahrenheit|%celsius"

The formatting string specifies:

Parameters can be placed between words in a //% block formatting string. An example of this will be provided later in the article.

Declare and Export the Function

As stated by the documentation quoted above, your function must be exported to become a custom block. What does it mean?

Simply place the keyword, export, at the start of the line that declares the function.

    export function fahrenheit(celsius: number): number {

There is a lot going on in this declaration:

The return Statement

A reporter block must include a return statement. In this example, it is the only line of code in the function. The statement performs the conversion calculation and returns the result.

        return (celsius * 1.8) + 32;

Semicolons!

The code you write for custom blocks must conform to JavaScript syntax. This means that semicolons are required at the ends of statements.

This behavior is more strict compared to the way MakeCode deals with the JavaScript for the main code of the editor, where semicolons are optional.

A bit of deliberate trial and error with semicolons will help you come to grips with the nature of coding custom blocks.

Frequently-asked Questions

What types of values can be returned by a reporter block?

Custom blocks like our fahrenheit example can return any one of the so-called primitive types: numbers, strings, and boolean (true/false) values.

Simply declare the function to be of the corresponding type.

More advanced types of JavaScript values can be returned also, including arrays and objects. These types are outside the scope of this article. I intend to cover them elsewhere in this series.

What else can I do with custom reporter blocks?

Functions can do many things. Study examples provided in the documentation. Use your imagination. Try things; find out what works. A partial list might include:

Figure 3
Figure 3
Showing the rollDice custom block in use with a result in the micro:bit display

Where can I learn more about defining functions and parameters for reporter blocks?

There are many metacode instructions for custom blocks. Extensive information, with examples, is provided at the following link: https://makecode.com/defining-blocks.

The author especially appreciates all of the "playground" examples this resource provides. Very, very helpful.