Structs in Luma: What’s Possible Today and What’s Coming Next

Structs in Luma: What’s Possible Today and What’s Coming Next

November 27, 2025·
Luma Core Team

Over the last weeks we’ve been expanding Luma with one of the most important building blocks of any modern language: structs. They now integrate cleanly with the compiler, runtime, lists, maps, optional types, and even with the first version of impl blocks (methods + associated functions).

Today, we’re happy to share what’s already possible - and what exciting improvements are coming soon.

What You Can Do With Structs Today

Define rich data types

struct Person {
    name: str
    age: int
}

Luma compiles this into a fully-typed Go struct behind the scenes.

Create values (two ways!)

Positional:

alice: Person = Person("Alice", 25)

Named:

bob: Person = Person {
    name: "Bob",
    age: 30,
}

Both forms are safe and type-checked.

Work with lists and maps of structs

people: [Person] = [
    Person("Alice", 25),
    Person("Bob", 30),
]

people.walk(p) -> print(p.name)

people_by_name: {str: Person} = {
    "Alice": Person { name: "Alice", age: 25 },
}

Structs are treated like any other type - they fit naturally into all of Luma’s collections.

Use optional structs (?Person)

Optional structs work exactly like optional ints, strings, and floats:

best_friend: ?Person = Person("Alice", 25)
maybe: ?Person = nil

print(maybe == nil)       // true
print(best_friend == nil) // false

Add methods with impl blocks

Luma now supports instance methods:

impl Person {
    fn greet(self) -> str {
        return "Hi, ${self.name}!"
    }
}

alice: Person = Person("Alice", 25)
print(alice.greet())

and associated functions (static methods):

impl Person {
    fn new(name: str, age: int) -> Person {
        return Person(name, age)
    }
}

alice: Person = Person.new("Alice", 25)

Both compile down to clean Go code.

Mutate fields

alice.age = alice.age + 1

Simple and natural.

What’s Coming Next

Now that structs and methods are stable, we’re preparing the next step of Luma’s type-system evolution. Here’s what we’re working on:

Auto-deref for optional structs

Right now, accessing a field on an optional requires checking for nil:

if user != nil {
    print(user.name)
}

Soon, Luma will automatically allow this pattern:

if user != nil {
    print(user.name) // auto-dereferenced safely
}

The compiler will ensure it only works where it is guaranteed safe.

Better error messages for struct field mismatches

If you mistype a field name or forget one, the compiler will soon guide you with more helpful messages:

“Unknown field nam - did you mean name?”

This makes working with named struct literals clearer and more beginner-friendly.

Struct copy/update syntax

A convenient way to clone and update values:

updated = Person { ..alice, age: alice.age + 1 }

This keeps Luma expressive without requiring mutation everywhere.

Traits (Luma’s version of interfaces)

Traits will allow you to write reusable behavior and generic algorithms:

trait Greetable {
    fn greet(self) -> str
}

impl Greetable for Person {
    fn greet(self) -> str { return "Hi, ${self.name}" }
}

This opens the door to polymorphism and clean architecture patterns.

Method chaining improvements

With auto-deref and traits in place, method chaining becomes much smoother:

result = user
    .birthday()
    .greet()
    .to_upper()

The compiler will help ensure calls are legal and well-typed at each step.

Pointer vs value receiver semantics

Today, Luma simplifies everything to value receivers.
Soon, the compiler will infer when something should be a pointer (mutating methods) or a value (non-mutating methods), without requiring the programmer to think about Go-specific details.

Example (future):

impl Counter {
    fn inc(self) {
        self.value = self.value + 1  // compiled as pointer receiver
    }
}

The Bigger Picture

Structs turned Luma from a toy language into something you can build real applications with - game entities, API models, UI components, state machines, even simple servers.

These upcoming improvements will take Luma to the next level:

  • Safer optional types
  • Fluent method chaining
  • Better user experience
  • Richer type system
  • Cleaner compiler messages
  • More expressive code

And all while keeping Luma’s core promise:

Simple to read, simple to learn, simple to build with.

Stay tuned - the next few weeks will bring some exciting new capabilities.

If you want to try out structs today, check the updated playground examples in the documentation.

Last updated on