Skip to main content
Version: Nightly

@fieldwise_init

You can add the @fieldwise_init decorator on a struct to generate the field-wise __init__() constructor.

For example, consider a simple struct like this:

@fieldwise_init
struct MyPet:
var name: String
var age: Int

Mojo sees the @fieldwise_init decorator and synthesizes a field-wise constructor, the result being as if you had actually written this:

struct MyPet:
var name: String
var age: Int

def __init__(out self, var name: String, age: Int):
self.name = name^
self.age = age

You can synthesize the copy constructor and move constructor by adding the Copyable trait to your struct. For more information about these lifecycle methods, read Life of a value.

Implicit conversion

Implicit conversion lets you pass a value and lets a type build itself, without calling the constructor directly. This keeps caller code simple and clean. You enable this by marking an initializer as @implicit or using @fieldwise_init("implicit") to create one for you.

For example, if MyStruct has an initializer that accepts an Int, you can construct an instance like this:

an_instance = MyStruct(42)

A function that takes a MyStruct will accept that instance, an explicit constructor call, or the value that can be converted into one:

some_function(an_instance)      # pass an instance
some_function(MyStruct(42)) # build one directly
some_function(42) # implicit conversion

All three forms create a MyStruct for the call. Some may have small compile-time or run-time differences.

Declaring implicit initialization

You can declare implicit initializers in two ways:

  • Use @fieldwise_init("implicit") to auto-create one, as long as your type has exactly one instance field. This limit applies to the type itself, not just to initializer arguments.
  • Add @implicit to an initializer you write. The initializer can accept only one argument.

Fieldwise and implicit example

Here is a type that stores an Int. It can be created with an integer or from any value that can be floored and converted to an integer. It uses @fieldwise_init("implicit") for integers and creates an @implicit initializer for other values:

from std.math import Floorable, floor

# Creates an implicit initializer and limits the type to one instance field.
@fieldwise_init("implicit")
struct FlooringInt:
var floored: Int

# Allows implicit conversion from types that can be floored and made into an Int.
@implicit
def __init__[T: Floorable & Intable](out self, value: T):
self.floored = Int(floor(value))

def floored(value: FlooringInt) -> Int:
return value.floored

def main():
print(floored(FlooringInt(42))) # pass an instance, output: 42
print(floored(2)) # pass Int, output: 2
print(floored(52.6)) # pass Float64, output: 52
x = BFloat16(192.3)
print(floored(x)) # pass BFloat16, output: 192
y: FlooringInt = 180
print(y.floored) # output 180
z: FlooringInt = 3.14159
print(z.floored) # output: 3

What you don't see in this example is an initializer for integers. Adding @fieldwise_init("implicit") lets the compiler build it for you. If you wrote this by hand, it might look like this:

@implicit
def __init__(out self, floored: Int):
self.floored = floored