[rust-dev] Unified function/method call syntax and further simplification

Gábor Lehel illissius at gmail.com
Fri Oct 18 12:34:25 PDT 2013

Hi list,

This is meant as a followup to an earlier thread[1] on the subject and the
related ticket[2].

[1]: http://thread.gmane.org/gmane.comp.lang.rust.devel/2622/
[2]: https://github.com/mozilla/rust/issues/6974

The idea in those earlier discussions is that methods could also be called
using function syntax, supplying `self` as the first argument, so instead
of `self_arg.method(arg)`, you could write `method(self_arg, arg)`. I'm
wondering if this could be taken a couple steps further to simplify the
whole story regarding functions, methods, traits, and impls. The idea is
that the distiction between functions and methods would be erased almost
completely, and methods (now being just functions) would be imported

It would involve the following pieces:

 - If the first argument of a top-level `fn` is named `self`, it can be
called using method syntax. So if you have `fn foo(self: &MyType, n: int)
{ .. }` at the top level, you can write `object_of_my_type.foo(123)`. You
can also still call it using function syntax: `foo(object_of_my_type, 123)`.

 - Anonymous `impl`s could then be removed in favor of such top-level
`fn`s. Alternately, they could be kept as syntactic sugar for the same

 - Just as the distinction between functions and anonymous-impl methods
would be erased, the distinction between trait methods and associated
functions would also be erased. A function declared inside a trait would
exist in module scope, just like top-level `fn`s. Just like other
functions, you could call it using method syntax if the first argument is
named `self`, or using function syntax either way.

 - The existing syntax for `self` arguments could then be removed.
Alternately, it could be kept as syntactic sugar (`?self` becoming `self:
?T`, where `?` is any sigil or none).

 - Now that everything is a top-level `fn`, they would be imported
explicitly, like they (and all other things) already are. Here we can
remove the restriction on methods needing to be declared in the same
module/crate as their `self` type.

 - Functions can be called using method syntax only if they are declared
in, or imported into, the current scope directly. In other words, if you
could call them using function syntax unqualified.

 - If a method call is ambiguous, you would have the following options to
resolve it:

   (a) Tweak your imports so that only the method you want is in scope.

   (b) Import the method under a different name instead.

   (c) Use function call syntax instead with an explicit module qualifier.

Again, more or less the same options you have with any non-method item in
the current language.

Disadvantages of this scheme:

 - More typing. (Explicit imports for one; if sugar is removed, then that
as well.)


 - Simplicity and transparency. The special rules and language constructs
for declaring and importing methods would go away. Methods would work the
same way as other things do.

 - Correspondingly, you would also have better control over which methods
are imported and invoked.

 - You could declare methods for any type in any crate or module, without
having to create extraneous traits, which I feel is a wart in the current
language. Traits could then be used for abstraction only, which I feel is
their correct purpose.

 - Because methods would just be module-scope functions, they could be
referred to as values (e.g. as arguments to higher-order functions) without
a lambda shim.

 - I was confused at one point because `&self` looks a lot like a pattern
match, but is not one. That could go away.

 - The current difficulties with generic methods (`impl<T: Foo> T { .. }`
in the current language) might, or might not, be reduced. (I don't know of
any similar issues with generic top-level functions, but they might
resurface if called as methods).

 - The significance of the argument named `self` could also potentially be
removed, instead allowing the first argument to be used as the
self-argument in a method call, no matter what it's called. This would
allow for pattern matching on the self-argument in the definition of the
method, which is currently not possible.

Hope this is helpful or interesting,

Your ship was destroyed in a monadic eruption.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/rust-dev/attachments/20131018/8eda82e1/attachment.html>

More information about the Rust-dev mailing list