Skip to content
📖 Auto vs RustBook contents

Using Structs to Structure Related Data ​

A struct, or structure, is a custom data type that lets you package together and name multiple related values that make up a meaningful group. In Auto, structs are defined using the type keyword instead of Rust's struct keyword, but the concept is the same. If you're familiar with an object-oriented language, a struct is like an object's data attributes.

In this chapter, we'll compare and contrast tuples with structs, demonstrate how to define and instantiate structs, and discuss how to define associated functions and methods using both inline definitions within type blocks and the ext keyword for method extensions.

Defining and Instantiating Structs ​

Structs are similar to tuples in that both hold multiple related values. Like tuples, the pieces of a struct can be different types. Unlike with tuples, in a struct you'll name each piece of data so it's clear what the values mean.

To define a struct in Auto, we use the type keyword and name the type. Then, inside curly brackets, we define the names and types of the fields. Note that Auto uses space-separated type annotations (name Type) instead of Rust's colon syntax (name: Type).

A `User` type definition

Key differences from Rust:

FeatureAutoRust
Define structtype Name { }struct Name { }
Field type syntaxname Typename: Type
Create instanceName(val1, val2)Name { field: val }
Mutable instancevar user = Name(...)let mut user = Name { ... }

Auto uses positional constructor syntax (User(true, "name", ...)) instead of Rust's named field syntax (User { active: true, ... }). The arguments are matched to fields in the order they are declared.

Mutable Instances ​

To modify a field, use var to create a mutable instance:

Changing the value in the `email` field of a mutable `User` instance

Note that the entire instance must be mutable; Auto doesn't allow us to mark only certain fields as mutable, just like Rust.

An Example Program Using Structs ​

Let's write a program that calculates the area of a rectangle, starting with simple variables and refactoring toward structs.

Using Separate Variables ​

Calculating the area of a rectangle specified by separate width and height variables

The issue with this code is that width and height are related, but the function signature doesn't convey that relationship. Let's refactor using a type.

Refactoring with Types ​

Defining a `Rectangle` type and calculating its area

Now the function signature clearly states that it calculates the area of a Rectangle, and the fields width and height are named and related.

Borrowing with .view ​

As discussed in Chapter 4, we can use .view to borrow a value without taking ownership:

Using `.view` to borrow a Rectangle

Methods ​

Methods are functions defined within the context of a type. In Auto, methods can be defined in two ways:

  1. Inline methods — defined directly inside a type { } block
  2. Extension methods — defined in an ext block outside the type definition

Both approaches generate Rust impl blocks.

Defining Methods Inline ​

In Auto, you can define methods directly inside the type block. The self parameter is implicit — inside method bodies, use .field to access the instance's fields:

Defining an `area` method on the `Rectangle` type

Key differences:

FeatureAutoRust
Define methodsInside type { } blockIn separate impl block
Self parameterImplicit (not written)Explicit &self
Access own fields.fieldself.field

The .field syntax is shorthand for self.field. Auto automatically injects &self as the first parameter and converts .field to self.field in the transpiled Rust code.

Methods with Multiple Parameters ​

You can add additional parameters to methods after the implicit self:

A `Rectangle` type with multiple methods

Associated Functions with ext ​

In Rust, associated functions (like String::from) are defined in impl blocks without self as the first parameter. In Auto, you use the ext keyword to add associated functions and methods to a type after its initial definition:

Using `ext` to add an associated function

Key mapping differences for associated functions:

FeatureAutoRust
Define extensionext TypeName { }impl TypeName { }
Call associated fnTypeName.method()TypeName::method()
Constructor callTypeName(args)TypeName { field: val }

The ext keyword is Auto's equivalent of Rust's impl for adding methods and associated functions to types. Unlike impl, ext can be used anywhere in the codebase, not just after the type definition.

Multiple ext Blocks ​

Each type can have multiple ext blocks. This is useful for organizing methods by functionality:

Using multiple `ext` blocks

Tuple-Like Types ​

Auto doesn't have Rust's "tuple structs" (unnamed fields). Instead, use regular types with named fields, which provide better readability:

Named types instead of tuple structs

Ownership of Type Data ​

In Auto, just like in Rust, types can own their data (using String) or borrow it (using .view). When a type owns its data, the data is valid for as long as the entire type instance is valid. Auto's compiler automatically handles lifetime checking without requiring explicit annotations.

Summary ​

Auto's type keyword provides the same functionality as Rust's struct, with a more streamlined syntax:

ConceptAutoRust
Define typetype Name { fields }struct Name { fields }
Field syntaxname Typename: Type
Create instanceName(val1, val2)Name { field: val }
Mutable instancevar x = Name(...)let mut x = Name { ... }
Inline methodInside type { } blockIn impl block
Extension methodext Name { }impl Name { }
Self access.fieldself.field
Associated functionext Name { fn new() }impl Name { fn new() }
Call associated fnName.fn()Name::fn()

Types and enums (discussed in Chapter 6) are the building blocks for creating new types in your program's domain to take full advantage of Auto's compile-time type checking.

Let's move on to Chapter 6 and look at enums and pattern matching with the is keyword.

Released under the MIT License.