modularml / mojo

The Mojo Programming Language
https://docs.modular.com/mojo/manual/
Other
23.16k stars 2.59k forks source link

[Feature Request] Reconsider Python compatibility layer #2164

Open gryznar opened 6 months ago

gryznar commented 6 months ago

Review Mojo's priorities

What is your request?

Mojo which tends to be Python superset unfortunately has to follow its naming convention. This is a big hit in its consistency, because Python as a long living language has a lot of inconsistency at its own. Currently there are trends to just follow Python convention (as here: https://github.com/modularml/mojo/pull/2038), but this approach will strictly tight Mojo to Python which has a lot of caveats. My solution is:

  1. short-termed: aliases. e.g.:

    struct String:
    fn remove_prefix(....):
        # real implementation goes here
    
    fn removeprefix(....):
        self.remove_prefix(...)
  2. long-termed - move aliases to seperate extension layer, if extensions like in Swift will be supported.

Method removeprefix() may be additionaly marked as deprecated. As I see it, the compiler may point that out and add suggestion to use CLI linter which automatically will replace Python namings with proper ones. To improve user experience and not show 2 names, LSP server may ignore these namings from compatible layer and do not show them at all during typing

What is your motivation for this change?

API consistency, do not be tied to Python naming issues, ability to follow official style guide: https://github.com/modularml/mojo/blob/nightly/stdlib/docs/style-guide.md

Any other details?

No response

Benny-Nottonson commented 6 months ago

IMHO Mojo should focus on a quality product rather than a Python remake. I think the syntactic similarities between languages still make it an easy switch for Python developers, and I don't think that Mojo should sacrifice language and code quality to try and match potentially misguided features of Python.

soraros commented 6 months ago

If we have type extension in the future, we can easily confine the compatibility symbols in the extensions and simply don't import them by default. Straw man syntax:

# strint/__init__.mojo
from impl import String
import compat as compat

# string/impl.mojo
struct String:
  fn remove_prefix(...): ...

# string/compat.mojo
extension String:
  fn removeprefix(...): ...

# main.mojo
from string.compat import *

fn main():
  var s = String("test").removeprefix("t")
Brian-M-J commented 6 months ago

I support this (providing a default Mojo stdlib which is as good as possible, not being constrained by Python compatibility, followed by a separate compatibility layer) not just for naming but also for functionality. It'd be a shame if Mojo's stdlib was hamstrung by needing to be the exact same as Python's. Python is a scripting language, and its stdlib was designed with that in mind.

Think about this: would you rather have Mojo's file i/o and filesystem library only perform the exact same functionality as Python's pathlib (like it is currently doing), or would you rather have the default be something like LLFIO...

Its i/o overhead, including syscall overhead, has been benchmarked to 100 nanoseconds on Linux which corresponds to a theoretical maximum of 10M IOPS @ QD1, approx 40Gb/sec per thread

...which is able to take full advantage of async i/o utilities like io_uring and Windows' IoRing?

Edit: Also see #2113

gryznar commented 6 months ago

I support this (providing a default Mojo stdlib which is as good as possible, not being constrained by Python compatibility, followed by a separate compatibility layer) not just for naming but also for functionality. It'd be a shame if Mojo's stdlib was hamstrung by needing to be the exact same as Python's. Python is a scripting language, and its stdlib was designed with that in mind.

Think about this: would you rather have Mojo's file i/o and filesystem library only perform the exact same functionality as Python's pathlib (like it is currently doing), or would you rather have the default be something like LLFIO...

Its i/o overhead, including syscall overhead, has been benchmarked to 100 nanoseconds on Linux which corresponds to a theoretical maximum of 10M IOPS @ QD1, approx 40Gb/sec per thread

...which is able to take full advantage of async i/o utilities like io_uring and Windows' IoRing?

Edit: Also see #2113

+1 I highly support this! The best stdlib as it could be implemented and move compatibility with Python in terms of modules or whole packages to this layer. Mojo has big potential on its own and it will be a pity to waste opportunity to make it the best due to Python decisions made years ago

ivellapillil commented 6 months ago

If we have type extension in the future, we can easily confine the compatibility symbols in the extensions and simply don't import them by default. Straw man syntax:

# strint/__init__.mojo
from impl import String
import compat as compat

# string/impl.mojo
struct String:
  fn remove_prefix(...): ...

# string/compat.mojo
extension String:
  fn removeprefix(...): ...

# main.mojo
from string.compat import *

fn main():
  var s = String("test").removeprefix("t")

Agreed with this approach. It might not be possible to be 100 percent compatible, but if we can cover 80%, that's already enough.