Let's start off with a very simple example. We'll write a program that increments a counter from 0 to 100, printing the multiples of 10 to the console as we go.
namespace program;
import gu4::Out;
value class Program {
entry fn main() -> void {
let mutable counter = 0;
for i in 0..100 {
counter = counter + 1;
if counter % 10 == 0 {
Out::println("counter reached: " + counter);
}
}
Out::println("Done!");
}
}
Most of this code should be familiar to you, but you will notice a few trivial differences from the likes of Java or C++:
let to declare variables.fn to declare functions.-> T after the parameter list.: T after the name. Type inference usually renders this optional.:: to access static members, like in C++.if and for.a..b syntax creates an Iterator<int> over the half-open interval [a, b). There is no C-style for
loop in Guardian, only a foreach-style loop.
a..=b syntax creates a range over the closed interval [a, b].One less-trivial difference is the presence of keyword mutable in the declaration of variable counter. In Guardian,
the bindings of fields and local variables are immutable by default. Making a binding mutable means that you won't be
able to share it between threads, even if bound to a type which is normally safe to share.
To compile and run this program in one shot, you can use the grun tool. Assuming you have the grun tool in your
path, and a file called program.gu with your Guardian code in it, you can invoke grun like so:
$ grun program.gu
You can pass multiple files to grun to compile them all. If there is a single entry fn across all the
files, it will be invoked. If there are multiple, you will have to set the entryClass env var to indicate which class
contains the entry point of the program.
$ grun MainProgram.gu HelperClass.gu
$ entryClass=Program1 grun Program1.gu Program2.gu
If you insist, you can also use gu4c (the Guardian v4 compiler) to compile the program to the chosen target.
You will then be responsible for the rest of the build process. As of writing, the only supported backend is Java,
so that entails invoking javac and java on the output of gu4c. The compiler will generate a .gu4manifest.json
file which lists all the generated files and their dependencies.
$ gu4c -o path/to/output/dir program.gu
If you want to run the test suite, that's grunt:
$ grunt
Both grun and grunt are written in the Flour Language,
so you will need that in your path as well.
If you happen to be developing on the Flour Notebook Server, you will need cell magics to
interact with grun.
In the first cell of a notebook, you will need the following:
from flour import grun
With that executed, you can use the %%grun cell magic to execute a Guardian program.
%%grun
namespace notebook;
import gu4::Out;
value class Main {
entry fn main() -> void {
Out::println("Hello, notebook!");
}
}
When you execute the program with grun, you should see something like the following:
[grun] Invoking gu4c... (may take a while if gradle needs to rebuild the compiler)
[grun] Invoking javac...
[grun] Executing your program (entry class: program.Program)
counter reached: 10
counter reached: 20
counter reached: 30
counter reached: 40
counter reached: 50
counter reached: 60
counter reached: 70
counter reached: 80
counter reached: 90
counter reached: 100
Done!
Now, let's get parallelizing.
Next page: Counting in Parallel