Skip to content

Builder chain

Owned method chaining through consuming self.

struct Server:
host: String
port: i32
workers: i32
struct ServerBuilder:
host: String
port: i32
workers: i32
impl Server:
def builder() -> ServerBuilder:
return ServerBuilder(host=String.from_str("localhost"), port=80, workers=1)
impl ServerBuilder:
def host(self: Self, value: view str) -> Self:
var next = self
next.host = String.from_str("127.0.0.1")
return next
def port(self: Self, value: i32) -> Self:
var next = self
next.port = value
return next
def workers(self: Self, value: i32) -> Self:
var next = self
next.workers = value
return next
def build(self: Self) -> Server:
return Server(host=self.host, port=self.port, workers=self.workers)
def main() -> i32:
let server = Server.builder()
.host("127.0.0.1")
.port(3000)
.workers(4)
.build()
if server.host.len == 9:
return 0
return 1

What’s worth noticing:

  • Each builder method takes self: Self by value and returns the next owned value: the call chain consumes the previous instance and produces the next.
  • Self resolves to the surrounding impl’s receiver type. Same as writing ServerBuilder here, but reads cleaner.
  • The chain uses indented continuation: Server.builder() followed by indented .host(...), .port(...), etc. This is the supported method-chain form.
  • The consuming chain moves String storage out of self between calls: this is permitted because ServerBuilder does not define drop.

For the rules on which receiver shapes work in chains, see Methods and impl.