Skip to content

Authoring Programmes

A complete guide to writing LOVE-LANG programmes, from base statements to complex multi-phase applications.

This guide walks you through writing real LOVE-LANG programmes — from simple key-value statements to multi-phase applications using the full bracket hierarchy.


A LOVE programme is a sequence of base statements optionally interspersed with decorator directives (@Something). There is no required main function — evaluation proceeds top-to-bottom.

programme.love
# 1. Imports
@Import[Prelude::*]
@Import[Invariants::DependencyInjection]
# 2. Configuration
name = "My Programme"
version = 1.0.0
# 3. Logic
result = [[ + 1 2 3 ]]
# 4. Effects
[[[[[
@print result
]]]]]

The @Import directive brings modules into scope:

# Import everything from Prelude
@Import[Prelude::*]
# Import a specific invariant
@Import[Invariants::DependencyInjection]
# Import a named module
@Import[Stdlib::Math]
@Import[Stdlib::String]
@Import[Stdlib::List]

The @DependencyInjection decorator wires dependencies automatically:

di-example.love
@Import[Prelude::*]
@Import[Invariants::DependencyInjection]
# Basic DIjust declare the entry point
@DependencyInjection
[#mode Automatic]
init = [#! [args :List[String]] ]

In automatic mode, LOVE resolves dependencies by inspecting the type signatures of your functions and injecting matching values from the current scope.

ssg.love
@DependencyInjection
[#mode Automatic ::alias[AutomaticMode]]
init = [#! [args :List[String]]
@and[>]
result :List = args
-> @apply[self]
-> @create[List <- args]
-> @filter[@and[True]] ]

This is the actual ssg.love example from the LOVE-LANG repository — a static site generator bootstrap.


Use base statements and type annotations to define your data:

data-model.love
# User model
user-id @[Number] = 1
user-name @[String] = "Alice"
user-email @[String] = "[email protected]"
user-active @[Boolean] = true
user-roles @[List] = [:admin :user]
schemas.love
UserRecord = [[[
id @[Number]
name @[String]
email @[String]
active @[Boolean]
roles @[List[Symbol]]
]]]
PostRecord = [[[
id @[Number]
title @[String]
body @[String]
author-id @[Number]
tags @[List[String]]
published @[Boolean]
]]]

LOVE uses S-expression style control flow:

# Conditional
result = [[ if active "User is active" "User is inactive" ]]
# Unless
fallback = [[ unless active "Default value" ]]
# And / Or
all-valid = [[ @and [condition-a condition-b condition-c] ]]
any-valid = [[ @or [condition-a condition-b] ]]

LOVE supports Elixir-style pipeline notation:

processed = args
-> @apply[self]
-> @create[List <- args]
-> @filter[@and[True]]

  1. Set up imports and effectors

    auth.love
    @Import[Prelude::*]
    @Import[Invariants::DependencyInjection]
  2. Define the type contract

    UserPayload = [[[
    name @[String]
    hash @[String]
    ]]]
  3. Write the logic

    raw_pass = "password123"
    user_name = "alice"
    hashed_pass = [[ @hash_pass raw_pass ]]
  4. Apply the type contract

    validated = [[[ UserPayload ]]] {
    :name user_name
    :hash hashed_pass
    }
  5. Perform the side effect (L5)

    [[[[[
    @sql_write "users" validated
    ]]]]]