惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Application and Cybersecurity Blog
Application and Cybersecurity Blog
N
News | PayPal Newsroom
The Last Watchdog
The Last Watchdog
S
Secure Thoughts
Forbes - Security
Forbes - Security
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
PCI Perspectives
PCI Perspectives
N
News and Events Feed by Topic
Hacker News - Newest:
Hacker News - Newest: "LLM"
Last Week in AI
Last Week in AI
Blog — PlanetScale
Blog — PlanetScale
Hacker News: Ask HN
Hacker News: Ask HN
H
Heimdal Security Blog
D
Docker
Cloudbric
Cloudbric
P
Privacy International News Feed
S
Security Affairs
TaoSecurity Blog
TaoSecurity Blog
博客园 - 聂微东
WordPress大学
WordPress大学
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
T
Tenable Blog
Scott Helme
Scott Helme
人人都是产品经理
人人都是产品经理
Recent Announcements
Recent Announcements
P
Palo Alto Networks Blog
小众软件
小众软件
L
LINUX DO - 最新话题
美团技术团队
Google Online Security Blog
Google Online Security Blog
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
雷峰网
雷峰网
Microsoft Security Blog
Microsoft Security Blog
The Hacker News
The Hacker News
Webroot Blog
Webroot Blog
T
Tor Project blog
G
Google Developers Blog
A
About on SuperTechFans
Y
Y Combinator Blog
K
Kaspersky official blog
A
Arctic Wolf
量子位
I
InfoQ
V
Visual Studio Blog
T
Troy Hunt's Blog
C
Cybersecurity and Infrastructure Security Agency CISA
J
Java Code Geeks
博客园 - 【当耐特】
GbyAI
GbyAI

Modular Blog

Qualcomm to Acquire Modular Modular 26.4: SOTA MoE Serving, Model Bringup via Agent Skills, Mojo 1.0 Beta 2 and More ModCon 2026: Modular’s Developer Conference Day Zero: MiniMax M3 Open Weights on Modular Cloud Modverse #55: Mojo 1.0 Beta, Community Mojo Libraries, and Real-Time Patient Conversations Powered by MAX What about OpenCL and CUDA C++ alternatives? (Democratizing AI Compute, Part 5) Why LLM Inference Needs a New Kind of Router - Part 3 Three trends from MLSys 2026 Why LLM Inference Needs a New Kind of Router - Part 2 How I built a pure Mojo app (and 10 libraries) with AI agents Hippocratic AI partners with Modular to power flexible, high-quality inference for real-time patient conversations Translating to Mojo via AI Agents Inkwell: Why Your Inference Platform Matters As Much As Your Model Why LLM Inference Needs a New Kind of Router - Part 1 Modular 26.3: Mojo 1.0 Beta, MAX Video Gen, and more Modverse #54: AMD AI DevDay, New Modular Offices, and a Community That Keeps Shipping How Frontier Coding Agents Built a Video Diffusion Pipeline on MAX TileTensor Part 1 - Safer, More Efficient GPU Kernels Modular Opens Edinburgh & San Francisco Offices Structured Mojo Kernels Part 4 - Portability and the Road Ahead Day Zero Launch: Fastest Performance for Gemma 4 on NVIDIA and AMD Modverse #54: From GTC to Edinburgh, a Community Building Momentum Software Pipelining for GPU Kernels: Part 1 - The Pipeline Problem Structured Mojo Kernels Part 3 - Composition in Practice Modular 26.2: State-of-the-Art Image Generation and Upgraded AI Coding with Mojo Modular at NVIDIA GTC 2026: MAX on Blackwell, Mojo Kernel Porting, and DeepSeek V3 on B200 Structured Mojo Kernels Part 2 - The Three Pillars Modverse #53: Community Builds, Research Milestones, and a Growing Ecosystem Structured Mojo Kernels Part 1 - Peak Performance, Half the Code The Claude C Compiler: What It Reveals About the Future of Software BentoML Joins Modular The Five Eras of KVCache Modular 26.1: A Big Step Towards More Programmable and Portable AI Infrastructure How to Beat Unsloth's CUDA Kernel Using Mojo—With Zero GPU Experience 🔥 Modular 2025 Year in Review The path to Mojo 1.0 Modverse #52: Advancing AI Together — Community Projects & Platform Milestones Modular 25.7: Faster Inference, Safer GPU Programming, and a More Unified Developer Experience "TTS 1 Max" (powered by Modular Platform) Ranked #1 Speech Model on Artificial Analysis PyTorch and LLVM in 2025 — Keeping up With AI Innovation Achieving State-of-the-Art Performance on AMD MI355 — in Just 14 Days Modular Raises $250M to scale AI's Unified Compute Layer Modular 25.6: Unifying the latest GPUs from NVIDIA, AMD, and Apple Matrix Multiplication on Blackwell: Part 4 - Breaking SOTA Modverse #51: Modular x Inworld x Oracle, Modular Meetup Recap and Community Projects Matrix Multiplication on Blackwell: Part 3 - The Optimizations Behind 85% of SOTA Performance Matrix Multiplication on Blackwell: Part 2 - Using Hardware Features to Optimize Matmul Matrix Multiplication on Blackwell: Part 1 - Introduction Modverse #50: Modular Platform 25.5, Community Meetups, and Mojo's Debut in the Stack Overflow Developer Survey Modular Platform 25.5: Introducing Large Scale Batch Inference SF Compute and Modular Partner to Revolutionize AI Inference Economics AI Agents for AWS Marketplace Modverse #49: Modular Platform 25.4, Modular 🤝 AMD, and Modular Hack Weekend Inside Modular Hack Weekend: Top Projects and Community Highlights How is Modular Democratizing AI Compute? (Democratizing AI Compute, Part 11) Modular 25.4: One Container, AMD and NVIDIA GPUs, No Lock-In Introducing Mammoth: Enterprise-Scale GenAI Deployments Made Simple Modular + AMD: Unleashing AI performance on AMD GPUs Modverse #48: Modular Platform 25.3, MAX AI Kernels, and the Modular GPU Kernel Hackathon Exploring Metaprogramming in Mojo Modular GPU Kernel Hackathon Highlights: Innovation, Community, & Mojo🔥 Modular’s bet to break out of the Matrix (Democratizing AI Compute, Part 10) Modular Platform 25.3: 450K+ Lines of Open Source Code and pip Packaging A New, Simpler License for MAX and Mojo Why do HW companies struggle to build AI software? (Democratizing AI Compute, Part 9) Modverse #47: MAX 25.2 and an evening of GPU programming at Modular HQ What about the MLIR compiler infrastructure? (Democratizing AI Compute, Part 8) What about Triton and Python eDSLs? (Democratizing AI Compute, Part 7) MAX 25.2: Unleash the power of your H200's–without CUDA! What about TVM, XLA, and AI compilers? (Democratizing AI Compute, Part 6) Modverse #46: MAX 25.1, MAX Builds, and Democratizing AI Compute CUDA is the incumbent, but is it any good? (Democratizing AI Compute, Part 4) MAX 25.1 - Introducing MAX Builds How did CUDA succeed? (Democratizing AI Compute, Part 3) Paged Attention & Prefix Caching Now Available in MAX Serve What exactly is “CUDA”? (Democratizing AI Compute, Part 2) Modular DeepSeek's Impact on AI (Democratizing AI Compute, Part 1) Modular Evaluating Llama Guard with MAX 24.6 and Hugging Face Modular Introducing MAX 24.6: A GPU Native Generative AI Platform MAX GPU: State of the Art Throughput on a New GenAI platform Understanding SIMD: Infinite Complexity of Trivial Problems Community Spotlight: Writing Mojo with Cursor Hands-on with Mojo 24.5 MAX 24.5 - With SOTA CPU Performance for Llama 3.1 Announcing stack-pr: an open source tool for managing stacked PRs on GitHub Debugging in Mojo🔥 Write hardware-agnostic custom ops for PyTorch | Modular Take control of your AI Develop locally, deploy globally A brief guide to the Mojo n-body example What's new in MAX 24.4? MAX on macOS, fast local Llama3, native quantization and GGUF support What’s new in Mojo 24.4? Improved collections, new traits, os module features and core language enhancements MAX 24.4 - Introducing quantization APIs and MAX on macOS Deep dive into ownership in Mojo What ownership is really about: a mental model approach Fast⚡k-means clustering in Mojo🔥: a guide to porting Python to Mojo🔥 for accelerated k-means clustering
Hands-on with Mojo 24.6
No items found. · 2025-01-21 · via Modular Blog

Mojo 24.6 has arrived with significant changes to argument conventions and lifetime management. This release marks an important step in Mojo's evolution, making its memory and ownership model more intuitive while maintaining strong safety guarantees. The changes are available now and are bundled with the MAX 24.6 release.

To proceed, make sure you have installed the magic CLI

   

Bash

curl -ssL https://magic.modular.com/ | bash    

   

or update it via

Bash

magic self-update

In this blog post, we'll explore these changes through practical examples that demonstrate the new syntax and features. We'll start with basic argument conventions and gradually introduce more advanced concepts like origins (formerly lifetimes) and implicit conversions. By the end, you'll have a thorough understanding of how to use these enhancements in your Mojo code.

One of the biggest highlights of this release is the significant contributions from our community. We received numerous pull requests from 11 community contributors that included new features, bug fixes, documentation enhancements, and code refactoring.

Special thanks ❤️ to our community contributors: @jjvraw, @artemiogr97, @martinvuyk, @jayzhan211, @bgreni, @mzaks, @msaelices, @rd4com, @jiex-liu, @kszucs, @thatstoasty

For a complete list of changes, please refer to the changelog for version 24.6.

All the code for this blog post is available in our GitHub repository.

Key changes overview

One of the highlights of this release is the renaming of several core concepts to better reflect their purpose:

  • inoutmut for mutable arguments: This better reflects that these parameters can be modified.
  • "lifetime" → "origin" for reference tracking: Better describes the concept of where references come from.

These naming changes make Mojo code more intuitive while preserving the strong safety guarantees that developers expect. Let's dive into each feature with practical examples.

New argument conventions

The most visible change in Mojo 24.6 is the renaming of argument conventions. The inout keyword has been replaced with mut. This change makes the code's intent clearer — mut explicitly indicates that an argument can be modified.

Let's look at a practical example:

Before 24.6

Mojo

@value struct Task:    var description: String    fn __init__(inout self, desc: String):        self.description = desc struct TaskManager:    var tasks: List[Task]    fn __init__(inout self):        self.tasks = List[Task]()    fn add_task(inout self, task: Task):        self.tasks.append(task)        fn show_tasks(self):        for t in self.tasks:            print("- ", t[].description)

After 24.6

Mojo

@value struct Task:    var description: String    # Notice: `inout` -> `out`    fn __init__(out self, desc: String):        # 'out self' indicates we are constructing a fresh Task        self.description = desc struct TaskManager:    var tasks: List[Task]    fn __init__(out self):        # Another 'out self' constructor,        # sets up an empty list of tasks        self.tasks = List[Task]()    # Notice: `inout` -> `mut`    fn add_task(mut self, task: Task):        self.tasks.append(task)    fn show_tasks(self):        for t in self.tasks:            print("- ", t[].description) def main():    # Create a new TaskManager    manager = TaskManager()    # Add tasks    manager.add_task(Task("Walk the dog"))    manager.add_task(Task("Write Mojo 24.6 blog post"))    manager.show_tasks()

To run the example with the magic CLI:

Bash

git clone https://github.com/modular/devrel-extras cd devrel-extras/blogs/hands-on-with-mojo-24-6 magic run example1

Implicit conversions

Another important change in 24.6 is how implicit conversions are handled. Single-argument constructors now require the @implicit decorator to allow implicit conversions. This makes type conversions more explicit and safer by requiring developers to opt-in to implicit conversion behavior.

Here's how it works:

Mojo

struct Task:    var description: String    @implicit  # Explicitly opt-in to implicit conversion    fn __init__(out self, desc: String):        self.description = desc    @implicit  # Also allow conversion from string literals    fn __init__(out self, desc: StringLiteral):        self.description = desc

This change allows for more convenient usage while maintaining type safety:

Mojo

def main():    manager = TaskManager()    # These now work because we opted into implicit conversion    # String → Task    manager.add_task(String("Walk the dog"))    # StringLiteral → Task    manager.add_task("Write Mojo 24.6 blog post")

Without the @implicit decorator, you would need to explicitly create Task objects:

Mojo

# Explicit conversion required manager.add_task(Task("Walk the dog"))

This new approach strikes a balance between convenience and type safety by making implicit conversions opt-in rather than automatic.

Bash

magic run example2

Origins: A more intuitive reference model

One of the most significant changes in Mojo 24.6 is renaming "lifetimes" to "origins" and builds out the reference model significantly. This change better reflects what these annotations actually do—tracking where references come from rather than their complete lifecycle. Don’t forget to check the Mojo manual.

Let's explore this concept with some practical examples:

Mojo

struct TaskManager:    var tasks: List[Task]    fn get_task(ref self, index: Int) -> ref [self.tasks] Task:        # The [self.tasks] annotation shows        # this reference originates from the tasks list        return self.tasks[index] def main():    manager = TaskManager()    manager.add_task("Initial task")    # Get a reference to the first task    first_task = manager.get_task(0)    first_task.description = "Modified task"  # Safe modification

The origin annotation [self.tasks] clearly indicates that the returned reference comes from the tasks list. This makes it easier to understand and track reference relationships in your code.

Bash

magic run example3

Working with multiple origins

Origins become particularly powerful when working with multiple references:

Mojo

fn pick_longer(ref t1: Task, ref t2: Task) -> ref [t1, t2] Task:    # The [t1, t2] annotation shows this reference    # could come from either t1 or t2    return t1 if len(t1.description) >= len(t2.description) else t2 def main():    manager = TaskManager()    manager.add_task("Short task")    manager.add_task("This is a longer task")        # copies so a new origin is detected    first_task = manager.get_task(0)    first_task.description = "Walk the dog ASAP and then write the blog post!"    # Compare tasks by length    longer = pick_longer(first_task, manager.get_task(1))    print("Longer task: ", longer.description)

This function demonstrates how ref [t1, t2] allows the returned reference to originate from either t1 or t2, enabling more flexible and expressive reference management.

Run the example:

Bash

magic run example4

Note: Mojo 24.6 enforces strict argument exclusivity at compile time. For example, the following call:

Mojo

pick_longer(manager.get_task(0), manager.get_task(1))

would produce the compiler error:

Output

# error: argument of 'pick_longer' call allows writing # a memory location previously writable through another aliased argument

This error occurs because the function attempts to modify a memory location that is already writable through another reference, ensuring memory safety and preventing potential data races.

Named results with out

Mojo 24.6 introduces a simpler syntax for named results by using the out convention directly. This replaces the previous Type as out syntax, making it more consistent with how we use out elsewhere in the language.

Let's look at an example that demonstrates this new syntax:

Mojo

struct TaskManager:    var tasks: List[Task]    fn __init__(out self):        self.tasks = List[Task]()    # Named result using the new 'out' convention    @staticmethod    fn bootstrap_example(out manager: TaskManager):        manager = TaskManager()        manager.add_task("Default Task #0")        manager.add_task("Default Task #1")        return  # 'manager' is implicitly returned def main():    # Create a TaskManager with default tasks    mgr = TaskManager.bootstrap_example()    mgr.show_tasks()

The bootstrap_example method demonstrates how named results work:

  1. We declare the result parameter with out manager: TaskManager.
  2. We initialize and populate the manager inside the function.
  3. The return statement implicitly returns the named result.

Try this example:

Bash

magic run example5

New collection types

Mojo 24.6 introduces two important additions to the standard library: Deque and OwnedPointer. Let's explore each one:

Deque: Double-ended queue

The new Deque collection type provides efficient O(1) operations at both ends of the sequence. This is particularly useful when you need to add or remove elements from either end of a collection, such as implementing a work queue with priorities.

Mojo

from collections import Deque struct TaskManager:    # Using Deque instead of List    var tasks: Deque[Task]    fn __init__(out self):        self.tasks = Deque[Task]()    fn add_task(mut self, task: Task):        # Add to back (normal priority)        self.tasks.append(task)    fn add_urgent_task(mut self, task: Task):        # Add to front (high priority)        self.tasks.appendleft(task)

Let's try this example:

Bash

magic run example6

OwnedPointer: Safe memory management

The OwnedPointer type provides safe, single-owner, non-nullable smart pointer functionality. This is particularly useful when dealing with resources that need deterministic cleanup, such as file handles or network connections.

Key features of OwnedPointer:

  • Single ownership semantics
  • Automatic cleanup when going out of scope
  • Move semantics with the ^ operator
  • Non-nullable (always points to valid data)

Here's a basic example showing the concept:

Mojo

from memory import OwnedPointer @value struct HeavyResource:    var data: String    fn __init__(out self, data: String):        self.data = data    fn do_work(self):        print("Processing:", self.data) struct Task:    var description: String    var heavy_resource: OwnedPointer[HeavyResource]    # We keep the @implicit for description    @implicit    fn __init__(out self, desc: StringLiteral):        self.description = desc        self.heavy_resource = OwnedPointer[HeavyResource](HeavyResource("Heavy resource with description: " + desc))    fn __moveinit__(out self, owned other: Task):        self.description = other.description^        self.resource = other.resource^

Run the complete last example with:

Bash

magic run example7

Putting It all together

Let's look at a complete example that combines all these new features — argument conventions, origins, and collection types. This example demonstrates how the various improvements in Mojo 24.6 work together to create cleaner, safer, and more efficient code:

Mojo

from collections import Deque from memory import OwnedPointer from os import abort @value struct HeavyResource:    var data: String    fn __init__(out self, data: String):        self.data = data    fn do_work(self):        print("Heavy work:", self.data) struct Task:    var description: String    var heavy_resource: OwnedPointer[HeavyResource]    # We keep the @implicit for description    @implicit    fn __init__(out self, desc: StringLiteral):        self.description = desc        self.heavy_resource = OwnedPointer[HeavyResource](HeavyResource("Heavy resource with description: " + desc))    fn __moveinit__(out self, owned other: Task):        self.description = other.description^        self.heavy_resource = other.heavy_resource^    # Workaround `CollectionElement` requirement for `Deque`    fn __copyinit__(out self, other: Task):        abort("__copyinit__ should never be called")        while True:            pass    fn do_work(self):        self.heavy_resource[].do_work() struct TaskManager:    var tasks: Deque[Task]    fn __init__(out self):        self.tasks = Deque[Task]()    # Need to use `owned` to avoid Copy    fn add_task(mut self, owned task: Task):        self.tasks.append(task^)    fn add_urgent_task(mut self, owned task: Task):        # or to the front        self.tasks.appendleft(task)    fn show_tasks(self):        for t in self.tasks:            print("- ", t[].description)    @staticmethod    fn bootstrap_example(out manager: TaskManager):        manager = TaskManager()        manager.add_task("Deque-based Task #1")        manager.add_urgent_task("Deque-based Task #0")        return    fn do_work(owned self):        for t in self.tasks:            t[].do_work() def main():    mgr = TaskManager.bootstrap_example()    print("Tasks:")    mgr.show_tasks()    print("Do work:")    mgr^.do_work()    # When 'mgr' goes out of scope, OwnedPointer cleans up all HeavyResources    # so no need for explicit cleanup

This example illustrates:

  • New out, mut, and read Argument Conventions: Clear indications of how each method interacts with the struct's state.
  • @implicit Single-Argument Constructor Conversions: Conveniently adding tasks using string literals without explicit Task construction.
  • Origins with ref [a, b]: Managing references that can originate from multiple sources, enhancing flexibility.
  • Deque Collection Type: Efficiently managing tasks with operations on both ends.
  • OwnedPointer for Safe Resource Management: Ensuring heavy resources are properly managed without manual cleanup.
  • Named Results with out: Simplifying function return conventions for better readability and consistency.

Debugging with Mojo LLDB Debugger and VS Code Enhancements

Mojo 24.6 also brings significant improvements to the tooling ecosystem, enhancing the developer experience with better debugging capabilities and editor integrations. In that regard,

mojo debug --rpc has changed to mojo debug --vscode. Please make sure to check the tooling section of the changelog for version 24.6.

Mojo LLDB Debugger Enhancements

  • Symbol Breakpoints: You can now set breakpoints on specific symbols within your code. For example:

Bash

b main b my_module::main

  • Improved Error Messages: Error messages are now clearer and more concise, eliminating unnecessary type expansions and focusing on the core issue.

VS Code Extension Enhancements

  • Data Breakpoints: Watch specific variables or struct fields for changes during execution.
  • Function Breakpoints: Break execution when specific functions are called.
  • Run and Debug Tab Automation: The extension now automatically opens the Run and Debug tab when a debug session starts.
  • Enhanced LSP and Documentation Display: Origins and parametric types are displayed more clearly in language server protocols and generated API documentation.

Conclusion

Mojo 24.6 significantly enhances the language’s ergonomics while retaining its strong safety guarantees. The new argument conventions (mut, out) clarify code intent, and renaming "lifetimes" to "origins" better conveys their purpose. The introduction of Deque and OwnedPointer broadens the standard library’s capabilities, and the opt-in implicit conversion rules reinforce type safety in your workflows.

These updates make Mojo more intuitive and productive, all while preserving the language’s commitment to performance and safety. Whether you’re new to Mojo or an experienced developer, these improvements provide a more refined and powerful programming experience.

To try out these new features, update to Mojo 24.6 and check out the full changelog.

What’s next?

Now that you've learned about the latest features in Mojo 24.6, it's time to put this knowledge into practice and dive deeper into the Mojo ecosystem. Here are some resources and next steps to help you get started and stay connected:

Until next time! 🔥