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: src/mod.mun
# pub fn main() {
# fibonacci(arg());
# }
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/mun.h"
int main(int argc, char *argv[]) {
if (argc < 2) {
return 1;
}
auto lib_path = argv[1];
mun::RuntimeOptions options;
mun::Error error;
if (auto runtime = mun::make_runtime(lib_path, options, &error)) {
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 0;
}
std::cerr << "Failed to construct Mun runtime due to error: "
<< error.message() << std::endl;
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: mod.rs
extern crate mun_runtime;
use mun_runtime::Runtime;
use std::env;
fn main() {
let lib_path = env::args().nth(1).expect("Expected path to a Mun library.");
// Safety: We assume that the library that is loaded is a valid munlib
let builder = Runtime::builder(lib_path);
let mut runtime = unsafe { builder.finish() }.expect("Failed to spawn Runtime");
loop {
let arg: i64 = runtime.invoke("arg", ()).unwrap();
let result: i64 = runtime.invoke("fibonacci", (arg,)).unwrap();
println!("fibonacci({}) = {}", arg, result);
unsafe { runtime.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 mod.mun
source file from Listing 1-2 changes, the --watch
argument must be added:
mun build --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, theruntime 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.