MON Cookbook
Welcome to the MON Cookbook! This guide provides practical MON examples and MON patterns to help you solve common data structuring problems using MON. Think of it as a collection of recipes for writing clean, efficient, and powerful MON configurations, often providing more elegant solutions than traditional formats like JSON or TOML.
Recipe 1: Your First Configuration File
Section titled “Recipe 1: Your First Configuration File”-
Define your configuration keys and values. Use unquoted keys for simplicity and add comments (
//) for notes. MON supports basic data types likeString,Number, andBoolean.config.mon {// The name of our applicationapp_name: "Awesome App",// Network settingshost: "localhost",port: 8080,// Feature flags. MON accepts on/true and off/false for booleans.enable_feature_x: on,enable_https: false,// A list of admin usersadmins: ["alice", "bob"],} -
Review the result. The resulting configuration is clean, self-documenting, and easy for anyone on your team to read and edit.
Recipe 2: Avoiding Repetition (The DRY Principle)
Section titled “Recipe 2: Avoiding Repetition (The DRY Principle)”-
Create a reusable template with an Anchor (
&). An anchor gives a nickname to any value (object,array,string, etc.), turning it into a template. The anchor itself doesn’t appear in the final output.{// The & makes `default_user` a template.&default_user: {theme: "dark",notifications: on,},} -
Make copies with an Alias (
*). An alias makes a deep copy of an anchor. Each copy is completely separate.{&default_user: { theme: "dark" },// alice_settings is a perfect copy of the templatealice_settings: *default_user,// bob_settings is another, totally independent copybob_settings: *default_user,} -
Extend templates with a Spread (
...*). A spread unpacks an anchor’s content into a new object or array, allowing you to extend it.For Objects: Spreads merge keys. If a key exists in both the template and your new object, the local value wins.
{&base_config: {host: "localhost",log_level: "info",},prod_config: {...*base_config, // 1. Inherit host and log_levelhost: "api.myapp.com", // 2. Override the hostlog_level: "error", // 3. Override the log_level},}For Arrays: Spreads combine elements.
{&base_permissions: ["READ", "WRITE"],admin_permissions: ["LOGIN",...*base_permissions, // Inserts "READ" and "WRITE" here"DELETE",],}
Recipe 3: Modular Data with Imports
Section titled “Recipe 3: Modular Data with Imports”-
Define your shared data in a separate file. For example, create a
schemas.monfile to hold your type definitions.schemas.mon{User: #struct { name(String) },Status: #enum { Active, Inactive },} -
Import the data into your main file. All
importstatements must appear at the top of the file, before the opening{of the root object.Namespace Imports (Safest): This bundles everything from another file into a single name, preventing conflicts.
main.mon // Import everything from schemas.mon into the `schemas` nameimport * as schemas from "./schemas.mon"{// Access imported members using the namespaceadmin :: schemas.User = { name: "Admin" },current_status: $schemas.Status.Active,}Named Imports (Convenient): Import specific parts directly into your file’s scope.
main.mon // Import only User and Statusimport { User, Status } from "./schemas.mon"{// Use them without a prefixguest :: User = { name: "Guest" },current_status: $Status.Inactive,}
Recipe 4: Enforcing Data Quality
Section titled “Recipe 4: Enforcing Data Quality”-
Define a Struct Blueprint. A struct defines what keys an object should have and what their value types should be.
{// A blueprint for a Product objectProduct: #struct {id(String), // Required String fieldprice(Number), // Required Number fieldin_stock(Boolean) = false, // Optional Boolean, defaults to false},} -
Validate Your Data with
::. Use the::operator to validate an object against a struct. The MON compiler will report an error if the data doesn’t match the blueprint.{Product: #struct { id(String), price(Number) },// This object is valid and matches the Product structmy_book :: Product = {id: "978-0321765723",price: 55.99,},// INVALID: The compiler would throw an error here because `price` is a string.// my_widget :: Product = {// id: "widget-123",// price: "25.00",// },}