Global side effects

Direct global side effects

Global side effects aren't allowed in ordinary functions. (Though log is allowed.)
That means we still haven't done a proper "Hello, world"!

import keen/io/print main void() global print "Hello, world!"

Any function that directly directly has a global side effect must be marked with the global spec.
Even observing global state, such as reading a file, is considered a global side effect.

Global side effects through a lambda

A function without the global spec can still call lambdas that have global side effects.

import keen/io/print main void() global do-times 10, of print "Hello, world!" do-times void(times nat, f void mut()) for _ in 0 .. times f[]

Notice that while a global side effect happened during do-times, do-times itself does nto have global side effects. So it does not have to be marked global.

Creating a lambda that does global things is global, but calling the lambda is not.

A data lambda can not have global side effects.

Global side effects through an interface

A similar thing can be done with interfaces.

import keen/io/print main void() global print-times 10, my-printer print-times void(times nat, printer printer) for _ in 0 .. times print printer, "hello" printer interface mut print void(message string) my-printer record global, printer case print void(_ my-printer, message string) global print message

Notice how my-printer had to be marked as global.
Marking a record as global makes its new (and named my-printer) functions global as well, so you can only construct a my-printer in global code.
If a record is global, it can implement an interface using global functions.

The interface needs to be mut for this to work, since data types can't have side effects.

Trusting global side effects

trusted allows its argument to call global (in addition to unsafe) functions.
Do this only if you know that the side effects are harmless.

import keen/io/print main void() trusted print "This is allowed"

Global variables

The following defines a global variable:

main void() global, unsafe x := 1 log x x global(nat)

A global variable can have an initializer. Otherwise it defaults to gc-safe-value .

main void() global, unsafe log x x := 2 log x x global(nat) 1