Hello, Hot Reloading!
Mun distinguishes itself from other languages by its inherent hot reloading
capabilities. The following example illustrates how you can create a hot
reloadable application by slightly modifying the Hello,
fibonacci? example. In Listing 1-2, the
fibonacci_n
function has been removed and the pub
keyword has been added to
both args
and fibonacci
.
Filename: hello_fibonacci.mun
pub fn arg() -> i64 {
5
}
pub fn fibonacci(n: i64) -> i64 {
if n <= 1 {
n
} else {
fibonacci(n - 1) + fibonacci(n - 2)
}
}
Apart from running Mun libraries from the command-line interface, a common use case is embedding them in other programming languages.
Mun embedded in C++
Mun exposes a C API and complementary
C++ bindings for the Mun Runtime. Listing 1-3 shows a C++ application that
constructs a Mun Runtime for the hello_fibonacci
library and continuously
invokes the fibonacci
function and outputs its result.
Filename: main.cc
#include <iostream>
#include "mun/runtime.h"
int main() {
if (argc < 2) {
return 1;
}
auto lib_path = argv[1];
if (auto runtime = mun::make_runtime(lib_path)) {
while (true) {
auto arg = mun::invoke_fn<int64_t>(*runtime, "arg").wait();
auto result =
mun::invoke_fn<int64_t>(*runtime, "fibonacci", arg).wait();
std::cout << "fibonacci(" << std::to_string(arg) << ") = " << result
<< std::endl;
runtime->update();
}
}
return 2;
}
Mun embedded in Rust
As the Mun Runtime is written in Rust, it can be easily embedded in Rust
applications by adding the mun_runtime
crate as a dependency. Listing 1-4
illustrates a simple Rust application that builds a Mun Runtime and continuously
invokes the fibonacci
function and prints its output.
Filename: main.rs
extern crate mun_runtime;
use mun_runtime::{invoke_fn, RetryResultExt, RuntimeBuilder};
use std::{cell::RefCell, env, rc::Rc};
fn main() {
let lib_path = env::args().nth(1).expect("Expected path to a Mun library.");
let mut runtime = RuntimeBuilder::new(lib_path)
.spawn()
.expect("Failed to spawn Runtime");
loop {
let arg: i64 = invoke_fn!(runtime, "arg").wait();
let result: i64 = invoke_fn!(runtime, "fibonacci", arg).wait();
println!("fibonacci({}) = {}", arg, result);
runtime.borrow_mut().update();
}
}
Hot Reloading
The prior examples both update the runtime every loop cycle. In the background, this detects recompiled code and reloads the resulting Mun libraries.
To ensure that the Mun compiler recompiles our code every time the
hello_fibonacci.mun source file from Listing 1-2 changes, the --watch
argument must be added:
mun build hello_fibonacci.mun --watch
When saved, changes in the source file will automatically take effect in the
running example application. E.g. change the return value of the arg
function
and the application will log the corresponding Fibonacci number.
Some changes, such as a type mismatch between the compiled application and the hot reloadable library, can lead to runtime errors. When these occur, the runtime will log the error and halt until an update to the source code arrives.
That's it! Now you are ready to start developing hot reloadable Mun libraries.