When debugging, it is often helpful to output the value of an expression or variable.
We might try something like:
def sum(x: Int32, y: Int32): Int32 = println(x); println(y); x + y
Unfortunately this does not work:
❌ -- Type Error -------------------------------------------------- Main.flix >> Impure function declared as pure. 1 | def sum(x: Int32, y: Int32): Int32 = ^^^ impure function.
The problem is that printing is inherently an effectful operation and hence we
cannot use it to debug our pure functions! We could make our
sum function have
IO effect, but that is rarely what we want. Fortunately, Flix has a
built-in debugging facility that allows us to do print-line debugging.
The debug Function
Flix has a
debug function with the same signature as the
def debug(x: a): a
debug "function" isn't really a function; rather its internal compiler
magic that allows you to print any value while fooling the type and effect
system into believing that it is still pure. Using the
debug function this
def sum(x: Int32, y: Int32): Int32 = debug(x); debug(y); x + y
Now compiles and runs.
debug function returns its argument. Hence its convenient to use in many
For example, we can write:
def sum(x: Int32, y: Int32): Int32 = debug(x + y)
to print the value of
x + y and return it.
We can also use it inside e.g. a
for(i <- List.range(0, 10); j <- debug(List.range(i, 10))) yield (i, j)
Or in a pipeline:
List.range(1, 100) |> List.map(x -> debug(x + 1)) |> List.filter(x -> debug(x > 5))
debug expression (and its variants) do not use the
class. Instead they print the internal Flix representation of the given value.
For example, the expression:
debug(1 :: 2 :: Nil)
Cons(1, Cons(2, Nil))
We can also print values that do not have a
debug(x -> x + 123)
Int32 -> Int32
We can always obtain the
ToString representation by using an interpolated
string. For example:
debug function comes in three variants:
debug: Prints its argument.
debug!: Prints its argument and source location.
debug!!: Prints its argument, source location, and source code.
The following program:
def main(): Unit = debug("A message"); debug!("Another message"); debug!!("A third message"); ()
"A message" [C:\tmp\flix\Main.flix:3] "Another message" [C:\tmp\flix\Main.flix:4] A third message = "A third message"
debug!! variant is intended to be used in situations like:
let x = 123; let y = 456; debug!!(x + y)
where it prints:
[C:\tmp\flix\Main.flix:3] x + y = 579
debugexpression should not be used in production code.
Warning: The Flix compiler treats the
debugexpression as pure, hence under certain circumstances the compiler may reorder or entirely remove a use of