Table of Contents

Variables

Buzz is a dynamically typed language. This means that the type of a variable can change during the execution of a script, and it depends on the type of the value stored by a variable at any moment.

Buzz does not include the concept of constant. Every variable is always mutable.

Primitive Types

Buzz supports the following primitive types:

Scope

Buzz variables can be global or local. To declare a variable as local to a code block (e.g., a function), you need to prepend its first definition with the keyword var:

# A local variable - by default its value is nil
var x
# Another local variable with initialization
var i = 5
# Assignment for a local variable
x = 7.8

To declare a global variable, you simply assign its value without using the var keyword:

# A global variable definition
j = 5

Control Structures

if Statement

while Statement

for Statement

Tables

Tables are the only structured type available in Buzz. Tables are quite flexible: you can use them both as a hash map or as a classical array.

To create an empty table, use this syntax:

t = {}

Internally, Buzz tables are implemented as hash maps, that is, a collection of (key, value) pairs. While in principle you could use any Buzz primitive type as key, the most common types are integers, floats, and strings. In this case, you can use this syntax to populate a table:

t = { .x = 1, .2 = 5.6, .4.5 = "k" }

This syntax creates a table that contains three pairs: ("x",1), (2,5.6), and (4.5,"k"). The table is stored in variable t.

To add new values to a table, or to set new values for existing keys (remember that in hash maps keys can't be duplicated!), use this syntax:

# If the key is an integer
t[6] = "six"
# If the key is a float
t[1.0] = "one point zero"
# If the key is a string, the following two lines are equivalent
t["hello"] = "this is a greeting"
t.hello = "this is a greeting"

To read the value of a table, the same syntax as above applies:

# If the key is an integer
print(t[6])
# If the key is a float
print(t[1.0])
# If the key is a string, the following two lines are equivalent
print(t["hello"])
print(t.hello)

Finally, to erase an element from a table it is enough to set it to nil:

t[1.0] = nil

Table contents can be handled through a number of dedicated commands.

size(t)

returns the current number of elements in table t:

t = { .x = 4 }
print(size(t)) # prints 1

foreach(t,f)

applies a function f(key,value) to each element of table t:

t = { .x = 4, .y = 5, .z = 6 }
foreach(t,
  function(key,value) {
    print("(", key, ", ", value, ")")
  })
# prints
#   (x, 4)
#   (y, 5)
#   (z, 6)

It is important to notice that foreach(t,f) is not meant to modify the values of the table. It is only meant to go through the elements of t and use its values in a read-only fashion. If you want to modify the elements of a table, use map(t,f).

map(t,f)

applies a function f(key,value) to each element of table t and returns a new table. For each element, function f must return a value, which is used to populate the new table. For instance:

t = { .x = 1, .y = 2 }
u = map(t,
      function(key,value) {
        return value + 100
      })
# now u contains:
#   ("x", 101)
#   ("y", 102)

reduce(t,f,a)

applies a function f(key,value,accumulator) to each element of table t. Function f must accept three parameters: the current key, the corresponding value, and an accumulator. Function f must also return a value, that is passed as accumulator to the invocation of f on the next table element. Parameter a of reduce(t,f,a) is the initial value of the accumulator. For instance, if you want to calculate the average of the values in a table, write the following code:

t = { .1 = 1.0, .2 = 2.0, 3. = 3.0 }
avg = reduce(t,
        function(key,value,accumulator) {
          return value + accumulator
        },
        0.0) / size(t)
# avg is now 2.0

Functions

Function Definition

Function Pointers

Math

Basic Math Operations

Math works similarly to most programming languages you are used to. The basic math operations, in decreasing order of precedence, are:

  1. Unary minus (e.g., -5)
  2. Power (e.g., 3^5)
  3. Modulo (e.g., 10 % 4)
  4. Multiplication and division (e.g., 2 * 3 / 4)
  5. Addition and subtraction (e.g., 2 + 3 - 4)

Analogously to other languages, parentheses are used to modify the natural precedence of the operators:

x = 5^(4%(3*(2+1)))
# x = 5^(4%(3*3))
# x = 5^(4%9)
# x = 5^4
# x = 625.0

As the above example shows, the power operator transforms its operands into float, even if the operands are both integers. The other operators return an integer if both operands are integer, and a float if either or both operands are float. A type error is raised if the operands are not integers nor floats.

The math Library

A wider set of mathematical functions is available. These functions are stored into the math table. The math table is set up upon initialization of the Buzz VM, so no include statement is necessary to use it.

The math functions work with both integer and float values. The complete list of functions is as follows:

In addition to these functions, the math table also includes the constant math.PI.

The math.rng Library

The math library also includes a collection of functions for random number generation. These functions are stored into the math.rng table and, similarly to math, do not require an include statement to be used.

The random number generator is based on the well-known Mersenne Twister algorithm.

Setting the Seed

Upon initialization, the Buzz VM sets a random seed taken from the current clock. If you wish to set the random seed explicitly to a value s, use the function math.rng.setseed(s). The value of s must be an integer, or a type error is raised.

Uniform Distribution

To draw numbers from a uniform distribution, use math.rng.uniform(...). The behavior of this function depends on the number and type of parameters passed.

Gaussian Distribution

To draw numbers from a Gaussian distribution, use math.rng.gaussian(...). The behavior of this function depends on the number and type of parameters passed.

Exponential Distribution

To draw numbers from an exponential distribution, use math.rng.exponential(x), where x is the mean. The returned value is a float.

The math.vec2 library

When dealing with the robots, it is often useful to manipulate vectors. Buzz offers a library to handle 2D vectors. The library is stored in INSTALL_PREFIX/ share/buzz/include/vec2.bzz, so to use it a script must first include it. The complete reference of these functions is included in the file.

Strings

Built-in String Operations

Additional String Operations

A number of additional string operations is available as a library that must be included. The library is stored in INSTALL_PREFIX/share/buzz/include/ string.bzz, so to use it a script must first include it. The complete reference of these functions is included in the file.

String Implementation in Buzz

The Buzz VM maintains a data structure that stores every string that was ever encountered during the execution of a script. Each string is associated with a unique identifier, which is simply a counter of strings created so far. Every time a string is used in a script, only the identifier is used. The actual value of the string is stored only once in the data structure. To make string lookup operations fast, strings are stored in binary tree ordered by identifier.

String manipulation often creates large numbers of intermediate strings, which are used only once over the lifetime of a script. To save memory, the Buzz VM internally distinguishes between protected and non-protected strings—protected strings are stored permanently, while non-protected strings are erased during garbage collection if no script variable refers to them. Examples of protected strings are function names, constant names, and other strings that are produced during compilation. Strings that result from manipulation with the string operations are typically non-protected.

When strings are communicated between robots, they must be serialized. It is not possible to force the string indentifiers to be the same across different robots. This is because (in general) different robots might execute different parts of a script, and strings might be created in different order. Therefore, when two robots exchange strings, the full value of the string must be communicated, rather then their identifier.

Files

To handle files, Buzz offers a number of built-in functions collected in the io table.

Swarm Management

Virtual Stigmergy

Neighbor Management

User Data