Consume in Swift 5.9

Hey Swifters, today we will explore the consume operator in Swift 5.9. So, you are cruising through your Swift code, writing functions, structs, maybe even dabbling in generics. Then Swift 5.9 rolls in with something new, the consume operator. And if your first reaction is:

“Wait… why do I need this? I’ve been doing just fine without it.”

You’re not alone. But let’s break it down clearly, and with code. 🧑‍💻

Swift is all about safety. Behind the scenes, it uses Automatic Reference Counting (ARC) to manage memory. When a value is no longer needed, Swift cleans it up. You usually don’t think twice about it. But sometimes you do care. Like when you are working in performance-critical environments (like games, machine learning, embedded systems), or writing lower-level Swift where memory overhead matters.

So What Is consume, Anyway? 🤔

In Swift 5.9 the consume operator was introduced to explicitly mark when a value is being consumed meaning:

“I’m done with this. Take it. Destroy it. Move on.”

Before Swift 5.9 (Implicit Copying)

Swift
struct Ingredient {
    var name: String
}

func use(_ ingredient: Ingredient) {
    print("Using \(ingredient.name)")
}

var tomato = Ingredient(name: "Tomato")
use(tomato)   // Copy happens here
use(tomato)   // And again

Here, Swift copies tomato each time you pass it to use(). That’s fine for a tiny struct, but for large objects, it can be inefficient.

After Swift 5.9 (Enter consume)

Swift
func use(_ ingredient: Ingredient) {
    print("Used up \(ingredient.name)")
}

var tomato = Ingredient(name: "Tomato")
use(consume tomato) // or let tomatoCopy = consume tomato
use(tomato)  // Ownership moved here; `tomato` cannot be used again

After consume tomato, you’ve handed over the value. If you try to use tomato after that, you’ll get a compile-time error. The compiler enforces this rule to make sure your code is safe and predictable. Pretty useful right? You can also define a parameter that expects a consumed value:

Swift
func build(_ thing: consuming Thing) {
    // use thing here, it's moved
}

Now callers must pass a consumed value. It makes ownership rules clear at the API level, just like inout clarifies mutation.

Alright, So When Should You Use consume?

Well you don’t need it for every app, especially if performance isn’t a big concern. But here are good places to consider it:

  • Game dev where real-time performance matters
  • ML/data processing and working with big data blobs
  • Embedded/IoT with low memory footprint
  • System-level Swift or building your own frameworks or allocators

So that was a brief exploration of the consume keyword i hope you liked it 🙂 Stay tuned for more interesting articles.


Posted

in