Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature Request] Rename __init__ to __new__, and make it a true static method #3916

Open
1 task done
nmsmith opened this issue Dec 28, 2024 · 3 comments
Open
1 task done
Labels
enhancement New feature or request mojo-repo Tag all issues with this label

Comments

@nmsmith
Copy link
Contributor

nmsmith commented Dec 28, 2024

Review Mojo's priorities

What is your request?

  1. Rename __init__ to __new__.
  2. Require constructors to be annotated with @staticmethod, for consistency with other static methods.
  3. Use a different naming convention for the named result lot of a constructor, e.g. fn __new__(out result).

Long term, we should consider making the syntax for static methods more concise.

What is your motivation for this change?

In the recent nightly releases of Mojo, the out convention has been unified with ordinary result slots. This means the following method signatures are equivalent from the caller's perspective:

struct Foo:
    fn __init__(out self): ...
    fn __init__() -> Self: ...

In other words, __init__ is now officially a static method, that returns a newly constructed instance.

This raises some concerns:

  1. In Python, __init__ is an instance method that mutates an already existing instance, and returns None. We don't want people to be confused by this discrepancy.
  2. For some reason, even though Mojo's __init__ methods are static, they don't need to be decorated with @staticmethod. This is inconsistent with the rest of Mojo, and will probably confuse people.
  3. (Less importantly) In existing Mojo codebases, everybody is using the identifier self for the first argument of __init__, which misleadingly suggests that __init__ is an instance method.

To address the first concern, @lattner proposes we rename __init__ to __new__. This seems like an improvement: In Python, __new__ is the lifecycle method that actually returns a new instance of the class. More precisely, it is a static method whose return type is Self. This matches the design of Mojo constructors.

To address the second concern, we should require constructors to be annotated as @staticmethod.

  • Aside: To be honest, I don't like the verbosity of this decorator, but having a consistent syntax for static methods seems more important than being concise. In the longer term, we should consider treating the absence of a self argument as the syntax for a static method, as was discussed on Discord. This would give us the best of both worlds.

To address the third concern, we should consider settling on a new naming convention for the result slot of a constructor, for example:

  • fn __new__(out result)
  • fn __new__(out target)
  • fn __new__(out dest)

I'd love to hear other suggestions.

@nmsmith nmsmith added enhancement New feature or request mojo-repo Tag all issues with this label labels Dec 28, 2024
@gryznar
Copy link
Contributor

gryznar commented Dec 28, 2024

+1
ad 3. Personally I think that self(instance mark) in Foo.__new__(out self) is proper, because it refers to result, not to argument. Everything different is strange, as Mojo the same as Python names instance as self.

The biggest mislead here is the possibility to declare result slot in arguments area, but it is a different case

@nmsmith
Copy link
Contributor Author

nmsmith commented Dec 28, 2024

Regarding concern 2: Chris pointed out that __new__ is implicitly static in Python, even without the decorator. I suppose we could use this fact to argue that it's okay for Mojo's __new__ method to be implicitly static as well.

However, that doesn't sit right with me. IMO we should be striving for Mojo to have an internally consistent design. "Python is internally inconsistent, so we should stick with that" is a valid argument, but not strong one.

I've taught a lot of Python, and these kinds of "exceptional situations" are what makes languages hard to teach and learn. Having the occasional exception isn't the end of the world, but they quickly add up.

If we make such an exception for __new__, we should do it with the above in mind.

@gryznar
Copy link
Contributor

gryznar commented Dec 28, 2024

How about getting rid of @staticmethod and @classmethod in structs and make static methods via presence of argument via concrete name? self for instance methods and maybe type for struct ones?

classmethod and cls is especially strange, as struct is not class

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request mojo-repo Tag all issues with this label
Projects
None yet
Development

No branches or pull requests

2 participants