WalkLang v2 Data Modeling, Methods, And Simple Generics

v2 adds experimental structs after the v1 compatibility line. v2.1 adds experimental methods as explicit receiver functions. v2.2 adds simple generic functions for composition without inheritance or magic dispatch.

docs/SPEC.md still defines stable v1. Structs are implemented in v2, but they are not part of the v1 compatibility promise.

Structs

Declare a struct with fixed fields:

struct: User
    name string
    age int

Create values with the positional constructor. Constructor values follow field order.

var: user = User('Walker', 25)
out: user.name

Rules:

field names are fixed by the declaration
field types are fixed by the declaration
constructor values are checked against field order
missing constructor values are compile errors
extra constructor values are compile errors
unknown fields are compile errors

Named-field constructors remain a future design candidate. v2.0 uses positional constructors only.

Field Access And Assignment

Read fields with dot syntax:

out: user.name
out: user.age

Assign fields through mutable roots:

var: user = User('Walker', 25)
user.age = 26

Field assignment is rejected when the root binding is const:.

const: user = User('Walker', 25)
user.age = 26 # type error

Functions

Structs can be function parameters and return values.

func: birthday(user User) User
    user.age = + user.age 1
    return: user

Methods

Methods are functions namespaced by receiver type. They do not add inheritance, hidden state, or class-based dispatch.

struct: User
    name string
    age int

func: User.is_adult(self User) bool
    return: >= self.age 18

var: user = User('Walker', 25)

if: user.is_adult()
    out: 'adult'

The receiver remains an explicit first parameter in the method declaration. A method call passes the receiver as that first argument.

user.is_adult() compiles like User__is_adult(user)

Rules:

methods must be declared on a struct type
the first parameter must match the receiver struct type
method names are namespaced by receiver type
different structs may use the same method name
ordinary method arguments are checked after the receiver
method calls on non-struct values are compile errors
unknown methods are compile errors

Arrays

Struct values can be stored in arrays, indexed, looped over, and updated through mutable array elements.

var: users = [User('Walker', 25), User('Ada', 37)]
users[1].age = 38

for: user in users
    out: user.name

Modules

Modules may declare structs and export functions that return them.

# profile.walk
struct: User
    name string
    age int

func: make_user(name string, age int) User
    return: User(name, age)

exp: make_user
# main.walk
imp: profile

var: user = profile.make_user('Walker', 25)
out: user.name

Simple Generic Functions

Generic functions declare type parameters after the function name.

func: same[T](value T) T
    return: value

out: same(1)
out: same('walk')

Type arguments are inferred from the ordinary call arguments. There is no explicit type-argument call syntax in v2.2.

Generic functions can compose with arrays and structs.

struct: User
    name string
    age int

func: first[T](items array[T]) T
    return: items[0]

var: users = [User('Walker', 25), User('Ada', 37)]
out: first(users).name

Generic functions can be exported from user modules.

# helpers.walk
func: first[T](items array[T]) T
    return: items[0]

exp: first
# main.walk
imp: helpers

var: nums = [1, 2, 3]
out: helpers.first(nums)

Rules:

generic functions are checked with named type parameters
call sites infer one concrete type per type parameter
all uses of a type parameter in one call must agree
generic functions are emitted as predictable specialized C functions
generic functions must be called directly and cannot be passed as values
generic methods are not supported yet

Non-Goals

v2.2 does not add:

inheritance
traits
interfaces
generic structs
generic methods
explicit type-argument calls
named-field constructors
magic dispatch

Structs, methods, and generic functions remain experimental. Traits, interfaces, generic structs, generic methods, named-field constructors, inheritance, and magic dispatch remain outside the implemented v2.2 surface.