Less ceremony.
More JVM.

A little room to think. Explicit nullability, steady values, and the Java libraries you already know.

App.kalm
pub fun greeting(name: Text?) -> Text:
    fix display = name ?? "Guest"
    return @"Hello, $display!"

pub fun main() -> Unit:
    sayLine(greeting(null))
$ kalm runHello, Guest!

Language notes

Absence has a type. Give missing values a name, then a gentle fallback. Text? / ?. / ??
pub fun greeting(name: Text?) -> Text:
    fix display = name ?? "Guest"
    return @"Hello, $display!"
Learn more
Values stay put. Bind once. Keep a little record of what matters. fix / data
data Note(title: Text, words: Int)

pub fun main() -> Unit:
    fix note = Note("A quiet morning", 3)
    sayLine(note.title())
Learn more
Java stays within reach. A familiar library is only an import away. use java.time.LocalDate
use java.time.LocalDate

pub fun tomorrow() -> Text:
    return LocalDate.now().plusDays(1L).toString()
Learn more
Two ways to breathe. A little indentation, or a pair of braces. Your call. fun main():
pub fun main() -> Unit:
    sayLine("Room to think.")
Learn more
Let a task take its time. Start work on a virtual thread and await its answer. task / async / await
pub async fun answer() -> Int:
    fix pending: Task<Int> = task:
        return 6 * 7
    return await pending
Learn more
A small set of good tools. Check a thought. Run it. Give it a test. check / run / test / format
kalm check
kalm run
kalm test
kalm format src/main/kalm
Learn more

Learn Kalm

One small program, a few new ideas. Read a file, count its words, and give your text-statistics CLI a set of tests.

Follow the learning path
kalm run -- notes.txt

2 lines / 3 words