[Feature request] Reconsider syntax for `out` result slots

Current syntax for declaring result slots looks as follow:

fn foo(out bar: Bar): ...

IMO it is counterintuitive, as it uses special argument convention, while technicaly it is not an argument. More intuitive would be to put it at rhs, after arrow in example syntax:

fn foo() -> bar: Bar: ...

or:

fn foo() -> Bar as bar: ...

Putting this at rhs would clarify intent.

2 Likes

Funnily enough, the syntax you’re suggesting is actually the syntax I proposed in the original “named output arguments” proposal, but Chris and/or others inside Modular preferred out.

I made my preference clear ages ago, so I’ll leave this discussion to others.

Maybe it is time to revisit this :slight_smile:

Strong agree :slight_smile:

IIRC one of the reason for the current syntax was that it combines named return statements (output slot that do not require a move operation to return a value) and initializers where the first argument is the new self instance that will be returned:

fn __init__(out self):

One syntax for both use cases.

However for init it’s kind of cheating, as it is static method and it should be called __new__because it is what it does (creates object, not initializes it)

Not really. AFAIK __init__ gets an already created Self instance in its out self arg. It only initializes the fields.

The same holds for __moveinit__ and __copyinit__ too.

I may be wrong, but Selfis returned from __init__ (via `out self` which is return slot). It looks like it is a classical constructor (not initializer like in Python)

@christoph_schlumpf What you’re describing is how Python works. In Mojo, __init__ is a static method that returns a new instance of the type, as @gryznar says.

That’s why threating it like instance method (at first glance by out self) is very confusing. If we deviate from Python by adding outrequireness, why not to drop this notion entirely and clearly state:

static fn __new__() -> Self as self: ...

(static keyword instead of @staticmethod on purpose).

Let’s keep dynamic classes to be copy of Python ones, but pretending that constructor is only initializer is not proper way to go IMO

What I mean is that there is some „compiler magic“ going on in __init__ methods. A new instance is already provided in the out self argument/return slot although they are static methods. If you write a differently named (static) method with an out self argument you have to create an instance yourself - nothing is provided.

Therefore it is both in those methods. An argument and a return slot.

But the same could be provided with a different syntax like @gryznar proposed. It just has to be considered.