====== 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:
* **''%%nil%%''** encodes an unknown value for a variable, or a ''%%false%%'' [[#contrstruct|condition]]
* **integer** a 32-bit signed integer (e.g., ''%%90%%'')
* **float** a 32-bit floating-point value (e.g., ''%%1.0%%'', ''%%0.25%%'', ''%%.5%%'')
* **string** a [[#strings|string]] of characters (e.g., ''%%"hello,
world!"%%'')
* **table** a structured type to encode various kinds of data structures (see [[#tables|Tables]])
* **closure** a [[#funpoint|function pointer]]
* **user data** a pointer to a user-defined memory region managed externally to Buzz. See [[#userdata|User Data]] for more information.
===== Scope =====
Buzz variables can be //global// or //local//. To declare a variable as //local// to a code block (e.g., a [[#functions|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.
returns the current number of elements in table ''%%t%%'':
t = { .x = 4 }
print(size(t)) # prints 1
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).%%''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)
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
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:
* ''%%math.abs(x)%%'' returns the absolute value of ''%%x%%''. The type of the result is the same as the type of ''%%x%%''.
* ''%%math.log(x)%%'' returns the natural logarithm of ''%%x%%'' as a float.
* ''%%math.log2(x)%%'' returns the base 2 logarithm of ''%%x%%'' as a float.
* ''%%math.log10(x)%%'' returns the base 10 logarithm of ''%%x%%'' as a float.
* ''%%math.exp(x)%%'' returns e to the power of ''%%x%%'' as a float.
* ''%%math.sqrt(x)%%'' returns the square root of ''%%x%%'' as a float.
* ''%%math.sin(x)%%'' returns the sine of ''%%x%%'' as a float.
* ''%%math.cos(x)%%'' returns the cosine of ''%%x%%'' as a float.
* ''%%math.tan(x)%%'' returns the tangent of ''%%x%%'' as a float.
* ''%%math.asin(x)%%'' returns the arc sine of ''%%x%%'' as a float.
* ''%%math.acos(x)%%'' returns the arc cosine of ''%%x%%'' as a float.
* ''%%math.atan(y,x)%%'' returns the arc tangent of ''%%y,x%%'' as a float.
* ''%%math.min(x,y)%%'' returns the minimum between ''%%x%%'' and ''%%y%%''. The type of the return value corresponds to the type of the minimum value: ''%%min(1.0, 2)%%'' is ''%%1.0%%'', and ''%%min(1,2.0)%%'' is ''%%1%%''.
* ''%%math.max(x,y)%%'' returns the maximum between ''%%x%%'' and ''%%y%%''. The type of the return value corresponds to the type of the maximum value: ''%%max(1.0, 2)%%'' is ''%%2%%'', and ''%%max(1,2.0)%%'' is ''%%2.0%%''.
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.
* **''%%math.rng.uniform()%%''** returns an integer between $-2^{32}$ and $+2^{31}-1$.
* **''%%math.rng.uniform(x)%%''** returns a value between 0 and ''%%x%%''. The type of the returned value matches the type of ''%%x%%''.
* **''%%math.rng.uniform(x,y)%%''** returns a value between ''%%x%%'' and ''%%y%%''. If both ''%%x%%'' and ''%%y%%'' are integers, the returned value is an integer; if either or both are floats, the returned value is a float.
==== 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.
* **''%%math.rng.gaussian()%%''** returns a float from a Gaussian with 0 mean and standard deviation 1.
* **''%%math.rng.gaussian(x)%%''** returns a float from a Gaussian with 0 mean and standard deviation ''%%x%%''.
* **''%%math.rng.gaussian(x,y)%%''** returns a float from a Gaussian with mean ''%%y%%'' and standard deviation ''%%x%%''.
==== 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 =====
* ''%%string.length(s)%%'' returns the length of string ''%%s%%''
* ''%%string.sub(s,...)%%'' returns a substring of the given string. Two signatures are possible: ''%%string.sub(s,n)%%'' returns the substring starting at character ''%%n%%'' (''%%0%%'' is the first character); ''%%string.sub(s,n,m)%%'' returns the substring starting at character ''%%n%%'' and ending at ''%%m%%''.
* ''%%string.concat(s1,s2,...)%%'' returns a new string that is the concatenation of the given strings.
* ''%%string.tostring(o)%%'' transforms object ''%%o%%'' into a new string.
* ''%%string.toint(x)%%'' converts a string into an integer. If the conversion fails, this function returns ''%%nil%%''.
* ''%%string.tofloat(x)%%'' converts a string into a float. If the conversion fails, this function returns ''%%nil%%''.
===== 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.