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

2013-10-21 Thread Jerry Morrison
On Sun, Oct 20, 2013 at 5:28 AM, Gábor Lehel illiss...@gmail.com wrote:

 On Sat, Oct 19, 2013 at 10:52 PM, Patrick Walton pwal...@mozilla.comwrote:

 I think it's unfortunately too late to overhaul the language like this.
 This will require redesigns of all Rust code in existence.

 I do like unified function/method call syntax, but I think it can be done
 in a backwards compatible way.


 This is up to you and the rest of the Rust team, of course. But in my very
 humble opinion, it feels shortsighted to impose backwards compatibility
 constraints at this point. All Rust code in existence is still (hopefully!)
 a negligibly small fraction of the code that is yet to be written. I know
 there's a desire to get 1.0 out the door as soon as possible, and I
 understand it (I want to be using Rust instead of C++, too!), but if Rust
 is still in use years or decades from now, decisions made now about the
 design of the language will echo far louder than whether it was released a
 few months earlier or later. I think it would be unfortunate to start
 suffering a C++-like fate sooner than absolutely necessary.


The Go team has been able to make incompatible language  library changes
by providing a tool that updates existing programs. Since Go's
pretty-printer fully defines the appearance of source code (indenting, line
wrapping, etc.), the updater can't mess up such things (and there are no
debates about them).



 That was a general argument, and it only matters if something is
 considered a good idea on the merits. In this case, it seems we disagree
 about that:


 On Sat, Oct 19, 2013 at 11:46 PM, Patrick Walton pwal...@mozilla.comwrote:

 I was thinking not. The dot operator should still have special name
 lookup rules: it searches through associated impls and all traits in scope.
 It cannot call anything that is not attached to an impl.

 This does make functions and methods somewhat less unified, but it makes
 methods feel more like OO methods from a scoping POV. I feel the draws of
 methods are not only that they switch the order of the receiver and action
 but also that they allow functions associated with a type to be called
 without explicitly importing their names.


 Aha. That's exactly the thing I don't like, and thought would be
 beneficial to change. It's different from everything else for no great
 reason (is being like OO a great reason?), and carries baggage with warts
 and thorny issues in it. (Needing special language constructs to write
 methods; normal `fn`s feel like second-class citizens; can't selectively or
 rename-import methods; can't write method-syntax functions in a different
 crate without introducing spurious abstraction boundaries; the whole `impl
 T { fn(self) }` versus `impl T { fn(self) }` ugliness; traits and generic
 types in paths raise awkward questions; ...)

 --
 Your ship was destroyed in a monadic eruption.

 ___
 Rust-dev mailing list
 Rust-dev@mozilla.org
 https://mail.mozilla.org/listinfo/rust-dev




-- 
   Jerry
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


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

2013-10-20 Thread Gábor Lehel
On Sat, Oct 19, 2013 at 10:52 PM, Patrick Walton pwal...@mozilla.comwrote:

 I think it's unfortunately too late to overhaul the language like this.
 This will require redesigns of all Rust code in existence.

 I do like unified function/method call syntax, but I think it can be done
 in a backwards compatible way.


This is up to you and the rest of the Rust team, of course. But in my very
humble opinion, it feels shortsighted to impose backwards compatibility
constraints at this point. All Rust code in existence is still (hopefully!)
a negligibly small fraction of the code that is yet to be written. I know
there's a desire to get 1.0 out the door as soon as possible, and I
understand it (I want to be using Rust instead of C++, too!), but if Rust
is still in use years or decades from now, decisions made now about the
design of the language will echo far louder than whether it was released a
few months earlier or later. I think it would be unfortunate to start
suffering a C++-like fate sooner than absolutely necessary.

That was a general argument, and it only matters if something is considered
a good idea on the merits. In this case, it seems we disagree about that:

On Sat, Oct 19, 2013 at 11:46 PM, Patrick Walton pwal...@mozilla.comwrote:

 I was thinking not. The dot operator should still have special name lookup
 rules: it searches through associated impls and all traits in scope. It
 cannot call anything that is not attached to an impl.

 This does make functions and methods somewhat less unified, but it makes
 methods feel more like OO methods from a scoping POV. I feel the draws of
 methods are not only that they switch the order of the receiver and action
 but also that they allow functions associated with a type to be called
 without explicitly importing their names.


Aha. That's exactly the thing I don't like, and thought would be beneficial
to change. It's different from everything else for no great reason (is
being like OO a great reason?), and carries baggage with warts and thorny
issues in it. (Needing special language constructs to write methods; normal
`fn`s feel like second-class citizens; can't selectively or rename-import
methods; can't write method-syntax functions in a different crate without
introducing spurious abstraction boundaries; the whole `impl T { fn(self)
}` versus `impl T { fn(self) }` ugliness; traits and generic types in
paths raise awkward questions; ...)

-- 
Your ship was destroyed in a monadic eruption.
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


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

2013-10-20 Thread Patrick Walton
It's different from everything else because it's a non-overlapping feature :)

But yes, I think being like OO is reason enough to do it. If we didn't have 
that, then you'd have to import every method you call. I think that that would 
turn off far too many programmers coming from mainstream languages. Almost 
every mainstream language I can think of that has methods at all does name 
lookup this way. (The main exception in the OO world would be pure 
multimethod-based systems, but they aren't mainstream and I personally question 
whether they can be in part because of this very issue.) Rust was designed to 
be a multiparadigm language, supporting both functional and OO style, and this 
feature is an extremely common part of object-oriented programming.

If it helps, this feature is not without precedent. The search through 
associated methods behavior is the same as Go and similar to Objective-C, with 
its @interface/@implementation divide. The search through traits in scope 
behavior is similar to Scala and C# extension methods.

I don't see the things you mention as warts. They're just consequences of, 
well, having methods in the OO sense. Nearly all of these warts show up in 
other object-oriented languages too. Maybe they're warts of object-oriented 
programming in general and illustrate that OO is a bad idea, but as I mentioned 
before Rust is designed to support OO.

I shouldn't have been so absolute about not changing stuff--we can and will 
change things--but I don't see having to import every method as a positive 
change. We discussed it years ago and concluded that it was a non-starter due 
to the burden it would impose on everyone.

Patrick

Gábor Lehel illiss...@gmail.com wrote:
On Sat, Oct 19, 2013 at 10:52 PM, Patrick Walton
pwal...@mozilla.comwrote:

 I think it's unfortunately too late to overhaul the language like
this.
 This will require redesigns of all Rust code in existence.

 I do like unified function/method call syntax, but I think it can be
done
 in a backwards compatible way.


This is up to you and the rest of the Rust team, of course. But in my
very
humble opinion, it feels shortsighted to impose backwards compatibility
constraints at this point. All Rust code in existence is still
(hopefully!)
a negligibly small fraction of the code that is yet to be written. I
know
there's a desire to get 1.0 out the door as soon as possible, and I
understand it (I want to be using Rust instead of C++, too!), but if
Rust
is still in use years or decades from now, decisions made now about the
design of the language will echo far louder than whether it was
released a
few months earlier or later. I think it would be unfortunate to start
suffering a C++-like fate sooner than absolutely necessary.

That was a general argument, and it only matters if something is
considered
a good idea on the merits. In this case, it seems we disagree about
that:

On Sat, Oct 19, 2013 at 11:46 PM, Patrick Walton
pwal...@mozilla.comwrote:

 I was thinking not. The dot operator should still have special name
lookup
 rules: it searches through associated impls and all traits in scope.
It
 cannot call anything that is not attached to an impl.

 This does make functions and methods somewhat less unified, but it
makes
 methods feel more like OO methods from a scoping POV. I feel the
draws of
 methods are not only that they switch the order of the receiver and
action
 but also that they allow functions associated with a type to be
called
 without explicitly importing their names.


Aha. That's exactly the thing I don't like, and thought would be
beneficial
to change. It's different from everything else for no great reason (is
being like OO a great reason?), and carries baggage with warts and
thorny
issues in it. (Needing special language constructs to write methods;
normal
`fn`s feel like second-class citizens; can't selectively or
rename-import
methods; can't write method-syntax functions in a different crate
without
introducing spurious abstraction boundaries; the whole `impl T {
fn(self)
}` versus `impl T { fn(self) }` ugliness; traits and generic types in
paths raise awkward questions; ...)

-- 
Your ship was destroyed in a monadic eruption.

-- 
Sent from my Android phone with K-9 Mail. Please excuse my brevity.___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


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

2013-10-20 Thread Oren Ben-Kiki
Coming from a functional programming perspective, it would still be very
nice indeed to easily pipeline a series of functions (not methods).

The current method of requiring defining a new trait (with possibly just
one impl!) just to be able to use the `.` syntax means discouraging
functional style in favor of OO style.

If it is impossible to allow for `foo.bar(baz)` to be the same as
`bar(foo, baz)`, without giving up on the OO-like behavior (is it,
really?), is there any chance of introducing a whole new operator (such as
`|`) to do the trick (as in `foo | bar(baz)`)?

See for example Elixir, which provides both a magic `.` OO-ish method
dispatch and also a function-ish pipelining `|` operator.



On Sun, Oct 20, 2013 at 6:11 PM, Marijn Haverbeke mari...@gmail.com wrote:

 I want to add that we did initially have a scheme where you have to
 import every impl you used (not every method), and that this was
 abandoned because it was burdensome and, in typical situations,
 completely redundant.

 Another problem with this proposal seems that it does away with the
 possibility of explicitly grouping a bunch of methods that make up the
 implementation of an interface. Implementing interfaces go-style, by
 just happening to have implemented all the methods that make up the
 interface, seems inappropriate for a language where interfaces aren't
 structural.

 So I very much agree with Patrick. Some aspects of this proposal are
 attractive, but it breaks some essential properties of the way methods
 currently work (and probably can't be adjusted to work around that
 without losing most of it attraction).

 Best,
 Marijn
 ___
 Rust-dev mailing list
 Rust-dev@mozilla.org
 https://mail.mozilla.org/listinfo/rust-dev

___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


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

2013-10-20 Thread Gábor Lehel
On Sun, Oct 20, 2013 at 4:56 PM, Patrick Walton pwal...@mozilla.com wrote:

 I don't see the things you mention as warts. They're just consequences of,
 well, having methods in the OO sense. Nearly all of these warts show up
 in other object-oriented languages too. Maybe they're warts of
 object-oriented programming in general and illustrate that OO is a bad
 idea, but as I mentioned before Rust is designed to support OO.


OO for me was always more tied in with virtual methods than with how
methods are scoped. But either way - I think this is basically my view. :)
The only part of it I like is dot syntax.

-- 
Your ship was destroyed in a monadic eruption.
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


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

2013-10-20 Thread Matthieu Monrocq
It seems to me that maybe there are several concepts/changes that are
discussed at once, and it would be possible to nitpick.

Personally, when I think of unifying calls, I only think of having
foo.bar(baz) being strictly equivalent to bar(foo, baz); nothing more
than a syntax trick in a way. And thus:

+ I do not see any reason not to keep a special associated method
look-up, though instead it would be tied to the first parameter of the
function rather than limited to method-like calls

+ I do not see any reason not to keep automatically exporting/importing all
methods whose first parameter is that of an exported/imported type or trait

+ I do not see any reason to move from explicit trait implementation to
structural and automatic trait implementation (and I would consider it
harmful)


Thus I am wondering:

- if I am missing something fundamental in the proposal by Gabor Lehel (I
am not completely accustomed with the Rust terminology/idioms)

- if such a simple syntax sugar could make its way into the language

-- Matthieu



On Sun, Oct 20, 2013 at 7:22 PM, Gábor Lehel illiss...@gmail.com wrote:

 On Sun, Oct 20, 2013 at 4:56 PM, Patrick Walton pwal...@mozilla.comwrote:

 I don't see the things you mention as warts. They're just consequences
 of, well, having methods in the OO sense. Nearly all of these warts show
 up in other object-oriented languages too. Maybe they're warts of
 object-oriented programming in general and illustrate that OO is a bad
 idea, but as I mentioned before Rust is designed to support OO.


 OO for me was always more tied in with virtual methods than with how
 methods are scoped. But either way - I think this is basically my view. :)
 The only part of it I like is dot syntax.

 --
 Your ship was destroyed in a monadic eruption.

 ___
 Rust-dev mailing list
 Rust-dev@mozilla.org
 https://mail.mozilla.org/listinfo/rust-dev


___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


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

2013-10-20 Thread Gábor Lehel
On Sun, Oct 20, 2013 at 5:11 PM, Marijn Haverbeke mari...@gmail.com wrote:

 Another problem with this proposal seems that it does away with the
 possibility of explicitly grouping a bunch of methods that make up the
 implementation of an interface. Implementing interfaces go-style, by
 just happening to have implemented all the methods that make up the
 interface, seems inappropriate for a language where interfaces aren't
 structural.


No, I completely agree with you here. Traits are awesome and if anyone
wants to remove them, I will fight them with forks. The only difference in
my proposal is how their methods would be scoped: they would be under the
enclosing module, rather than the trait itself being a kind of module.
Basically the Haskell model. (Except Haskell's module system is weaker than
Rust's.)


So I very much agree with Patrick. Some aspects of this proposal are
 attractive, but it breaks some essential properties of the way methods
 currently work (and probably can't be adjusted to work around that
 without losing most of it attraction).


The main cost would be having to import methods explicitly (or using a
glob), as Patrick notes.

-- 
Your ship was destroyed in a monadic eruption.
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


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

2013-10-20 Thread Gábor Lehel
On Sun, Oct 20, 2013 at 7:31 PM, Gábor Lehel illiss...@gmail.com wrote:

 So I very much agree with Patrick. Some aspects of this proposal are
 attractive, but it breaks some essential properties of the way methods
 currently work (and probably can't be adjusted to work around that
 without losing most of it attraction).


 The main cost would be having to import methods explicitly (or using a
 glob), as Patrick notes.


Now I'm wondering, though: going with my proposal, if the module structure
were just a little bit more fine-grained, I think you could achieve
basically the same effect as the current system, if you wanted to. If the
convention were to use a module to enclose a type together with its methods
(which is already the case in many places), and you did a glob import of
that module, you would get what you have now: the type and its methods
would all come into scope. Except you could still import selectively, if
you wanted to, or do things any other way, if you wanted to, and all of the
warts I mentioned would still disappear. In a different crate, you could
similarly create a module of extension methods, which could be imported
together or selectively, if you wanted to.

I don't want to push this too hard if it's past the point of being
productive, but I'm now even more convinced that this would be a beneficial
change. Types should be types, grouping and scoping should be done with
modules (Rust's modules are very capable), and traits should be used for
type-based abstraction. I think it would work great.

-- 
Your ship was destroyed in a monadic eruption.
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


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

2013-10-20 Thread Patrick Walton
Isn't #1 basically what argument-dependent lookup (Koenig lookup) is trying to 
do in C++? I'm very nervous of going down that road.

Patrick

Matthieu Monrocq matthieu.monr...@gmail.com wrote:
It seems to me that maybe there are several concepts/changes that are
discussed at once, and it would be possible to nitpick.

Personally, when I think of unifying calls, I only think of having
foo.bar(baz) being strictly equivalent to bar(foo, baz); nothing
more
than a syntax trick in a way. And thus:

+ I do not see any reason not to keep a special associated method
look-up, though instead it would be tied to the first parameter of the
function rather than limited to method-like calls

+ I do not see any reason not to keep automatically exporting/importing
all
methods whose first parameter is that of an exported/imported type or
trait

+ I do not see any reason to move from explicit trait implementation to
structural and automatic trait implementation (and I would consider it
harmful)


Thus I am wondering:

- if I am missing something fundamental in the proposal by Gabor Lehel
(I
am not completely accustomed with the Rust terminology/idioms)

- if such a simple syntax sugar could make its way into the language

-- Matthieu



On Sun, Oct 20, 2013 at 7:22 PM, Gábor Lehel illiss...@gmail.com
wrote:

 On Sun, Oct 20, 2013 at 4:56 PM, Patrick Walton
pwal...@mozilla.comwrote:

 I don't see the things you mention as warts. They're just
consequences
 of, well, having methods in the OO sense. Nearly all of these
warts show
 up in other object-oriented languages too. Maybe they're warts of
 object-oriented programming in general and illustrate that OO is a
bad
 idea, but as I mentioned before Rust is designed to support OO.


 OO for me was always more tied in with virtual methods than with how
 methods are scoped. But either way - I think this is basically my
view. :)
 The only part of it I like is dot syntax.

 --
 Your ship was destroyed in a monadic eruption.

 ___
 Rust-dev mailing list
 Rust-dev@mozilla.org
 https://mail.mozilla.org/listinfo/rust-dev



-- 
Sent from my Android phone with K-9 Mail. Please excuse my brevity.___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


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

2013-10-20 Thread Patrick Walton
What would happen if two types defined a method called, say, foo, and the 
importing module glob imported them both?

Patrick

Gábor Lehel illiss...@gmail.com wrote:
On Sun, Oct 20, 2013 at 7:31 PM, Gábor Lehel illiss...@gmail.com
wrote:

 So I very much agree with Patrick. Some aspects of this proposal are
 attractive, but it breaks some essential properties of the way
methods
 currently work (and probably can't be adjusted to work around that
 without losing most of it attraction).


 The main cost would be having to import methods explicitly (or using
a
 glob), as Patrick notes.


Now I'm wondering, though: going with my proposal, if the module
structure
were just a little bit more fine-grained, I think you could achieve
basically the same effect as the current system, if you wanted to. If
the
convention were to use a module to enclose a type together with its
methods
(which is already the case in many places), and you did a glob import
of
that module, you would get what you have now: the type and its methods
would all come into scope. Except you could still import selectively,
if
you wanted to, or do things any other way, if you wanted to, and all of
the
warts I mentioned would still disappear. In a different crate, you
could
similarly create a module of extension methods, which could be
imported
together or selectively, if you wanted to.

I don't want to push this too hard if it's past the point of being
productive, but I'm now even more convinced that this would be a
beneficial
change. Types should be types, grouping and scoping should be done with
modules (Rust's modules are very capable), and traits should be used
for
type-based abstraction. I think it would work great.

-- 
Your ship was destroyed in a monadic eruption.

-- 
Sent from my Android phone with K-9 Mail. Please excuse my brevity.___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


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

2013-10-20 Thread Gábor Lehel
On Sun, Oct 20, 2013 at 8:01 PM, Patrick Walton pwal...@mozilla.com wrote:

 What would happen if two types defined a method called, say, foo, and
 the importing module glob imported them both?


Here's the part where I have to say that I'm not intimately familiar with
how Rust's existing method lookup works. But I don't see why it would
necessarily have to work any differently from the way it does now. If you
use dot syntax, it would try to do type-based name resolution (i.e. use the
method in scope whose self-type matches), autoborrowing, autoreferencing,
and whatever else it currently does to try to get an unambiguous match. If
that fails, *then* you would have the option of tweaking your imports,
`use`ing the method under a different name, or switching to function syntax
and adding an explicit module qualifier (along with explicit borrowing and
whatever).

-- 
Your ship was destroyed in a monadic eruption.
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


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

2013-10-20 Thread Patrick Walton
But then it seems strange to require that the methods be imported at all, if 
you're going to do single-dispatch type-based resolution on them anyway.

What we could do, perhaps, is add a third source of methods that the dot 
operator searches: functions in scope. This would allow methods to be attached 
anywhere to pre-existing types in an ad-hoc basis. I'm a bit nervous about 
complicating our already-complicated method lookup further, but maybe it makes 
sense to reduce the number of FooMethods traits people have to write, as well 
as to accommodate function chaining patterns.

Patrick

Gábor Lehel illiss...@gmail.com wrote:
On Sun, Oct 20, 2013 at 8:01 PM, Patrick Walton pwal...@mozilla.com
wrote:

 What would happen if two types defined a method called, say, foo,
and
 the importing module glob imported them both?


Here's the part where I have to say that I'm not intimately familiar
with
how Rust's existing method lookup works. But I don't see why it would
necessarily have to work any differently from the way it does now. If
you
use dot syntax, it would try to do type-based name resolution (i.e. use
the
method in scope whose self-type matches), autoborrowing,
autoreferencing,
and whatever else it currently does to try to get an unambiguous match.
If
that fails, *then* you would have the option of tweaking your imports,
`use`ing the method under a different name, or switching to function
syntax
and adding an explicit module qualifier (along with explicit borrowing
and
whatever).

-- 
Your ship was destroyed in a monadic eruption.

-- 
Sent from my Android phone with K-9 Mail. Please excuse my brevity.___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


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

2013-10-20 Thread Gábor Lehel
On Sun, Oct 20, 2013 at 7:31 PM, Gábor Lehel illiss...@gmail.com wrote:

 On Sun, Oct 20, 2013 at 5:11 PM, Marijn Haverbeke mari...@gmail.comwrote:

 Another problem with this proposal seems that it does away with the
 possibility of explicitly grouping a bunch of methods that make up the
 implementation of an interface. Implementing interfaces go-style, by
 just happening to have implemented all the methods that make up the
 interface, seems inappropriate for a language where interfaces aren't
 structural.


 No, I completely agree with you here. Traits are awesome and if anyone
 wants to remove them, I will fight them with forks. The only difference in
 my proposal is how their methods would be scoped: they would be under the
 enclosing module, rather than the trait itself being a kind of module.
 Basically the Haskell model. (Except Haskell's module system is weaker than
 Rust's.)


Sorry, I think I might have misread the question, which I now believe was
not about traits, but about impls. Basically, only anonymous `impl`s would
go away. Trait impls would stay. But trait impls wouldn't have an effect on
scoping. (Trait methods would be scoped under the module enclosing the
trait, `impl`s would only affect for which types there exists an
implementation for them. You can' t currently choose whether or not to
export or import a trait impl, and you would continue to not be able to do
that.)

-- 
Your ship was destroyed in a monadic eruption.
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


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

2013-10-20 Thread Gábor Lehel
On Sun, Oct 20, 2013 at 8:16 PM, Patrick Walton pwal...@mozilla.com wrote:

 But then it seems strange to require that the methods be imported at all,
 if you're going to do single-dispatch type-based resolution on them anyway.


Well, it would do type-based resolution based on the methods which you
import :). You would still be the one doing the importing, instead of it
happening by magic. You could also /not/ import one or more of them, if you
wanted to, which you can currently only do on a per-trait granularity. And
the rest of the design would still be much cleaner. (Again, leaving to
modules what can be done with modules.)

But FWIW, I think this is mostly orthogonal. If you use dot syntax, method
lookup happens [somehow]. If it fails, you can do the other things. Maybe
method lookup happens with type-based resolution, as it does now. Or maybe
it requires that the name itself be unambiguous (which is simpler and
dumber), as with functions. That's not really the part I care about. The
part I care about is the separation of concerns.



 What we could do, perhaps, is add a third source of methods that the dot
 operator searches: functions in scope. This would allow methods to be
 attached anywhere to pre-existing types in an ad-hoc basis. I'm a bit
 nervous about complicating our already-complicated method lookup further,
 but maybe it makes sense to reduce the number of FooMethods traits people
 have to write, as well as to accommodate function chaining patterns.


I still can't speak to the method resolution code :), but I think this
would be a positive step. (Requiring the explicit `self` argument would
probably make sense, if this were to happen.)

-- 
Your ship was destroyed in a monadic eruption.
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


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

2013-10-20 Thread Patrick Walton
I guess I just don't see the value in requiring imports of names when there can 
be no ambiguity and they're defined in one place (the impl of the type, defined 
in the same place as the type itself). One person's magic is another person's 
smart compiler.

I'm not convinced that this is solving a real problem. The search all traits 
in scope behavior strikes me as far more magical than this. Doing type-based 
lookup without imports, if the names all had to be defined in one place, seems 
like a bog-standard language feature to me. It's probably easier to list 
languages that *don't* have this feature in some form than to list languages 
that do, honestly...

Patrick

Gábor Lehel illiss...@gmail.com wrote:
On Sun, Oct 20, 2013 at 8:16 PM, Patrick Walton pwal...@mozilla.com
wrote:

 But then it seems strange to require that the methods be imported at
all,
 if you're going to do single-dispatch type-based resolution on them
anyway.


Well, it would do type-based resolution based on the methods which you
import :). You would still be the one doing the importing, instead of
it
happening by magic. You could also /not/ import one or more of them, if
you
wanted to, which you can currently only do on a per-trait granularity.
And
the rest of the design would still be much cleaner. (Again, leaving to
modules what can be done with modules.)

But FWIW, I think this is mostly orthogonal. If you use dot syntax,
method
lookup happens [somehow]. If it fails, you can do the other things.
Maybe
method lookup happens with type-based resolution, as it does now. Or
maybe
it requires that the name itself be unambiguous (which is simpler and
dumber), as with functions. That's not really the part I care about.
The
part I care about is the separation of concerns.



 What we could do, perhaps, is add a third source of methods that the
dot
 operator searches: functions in scope. This would allow methods to be
 attached anywhere to pre-existing types in an ad-hoc basis. I'm a bit
 nervous about complicating our already-complicated method lookup
further,
 but maybe it makes sense to reduce the number of FooMethods traits
people
 have to write, as well as to accommodate function chaining patterns.


I still can't speak to the method resolution code :), but I think this
would be a positive step. (Requiring the explicit `self` argument would
probably make sense, if this were to happen.)

-- 
Your ship was destroyed in a monadic eruption.

-- 
Sent from my Android phone with K-9 Mail. Please excuse my brevity.___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


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

2013-10-20 Thread Gábor Lehel
On Sun, Oct 20, 2013 at 9:38 PM, Patrick Walton pwal...@mozilla.com wrote:

 I guess I just don't see the value in requiring imports of names when
 there can be no ambiguity and they're defined in one place (the impl of the
 type, defined in the same place as the type itself). One person's magic
 is another person's smart compiler.


A big part of the motivation would be to allow declaring methods anywhere,
without using traits, and then they're defined in one place stops being
true. For that to be workable you need to have control over imports.
(Luckily with top-level functions, you already do.)



 I'm not convinced that this is solving a real problem.


It's not solving a real problem so much as simplifying the whole thing.
Despite having used the word, my beef with the current system is not so
much that it's magical. It's that it's completely unnecessary. With nothing
more than a simple syntax rule and the existing module system, you can
recover all of the expressive power of the current system, and more.

Compare:


-- Design 1 --

 - You can declare functions using `fn`.

 - Functions in the current scope can be called using dot syntax with the
first argument as the receiver. (Optionally: only if the first argument is
named `self`.)

 - The module system can be used to group types, functions, and other
items, import them together, selectively, or under different names, and
resolve ambiguities between them.


-- Design 2 --

 - Anonymous `impl` blocks can be used to associate methods with a type.

 - Methods are scoped under and imported together with their type or trait.

 - Because of this, an anonymous `impl` can only be declared in the same
module as its type.

 - If you want to declare a method somewhere else, declare an auxiliary
trait and implement it for that type.

 - For a method to be called with dot syntax, it has to be declared using
special `self`, `self`, `~self`, (or so forth) syntax, which only works
with the built-in pointer types. Such a method can't be called with
function syntax.

 - If you want a self-type other than one of the built-in pointers, write
an `impl` specifically for that type.

 - Types and traits are like modules in some ways (you can use them in a
path), but not others (you can't `use` from them).

 - There are special rules and/or syntax for dealing with traits, generic
types, and optionally their type arguments in paths.

 - In addition to methods, you can also declare top-level functions with
`fn`. These can only be called with function syntax.

 - The module system can be used to group, import, rename, and resolve
ambiguities between types, functions, and other items except for methods.

Which one feels like the tighter design?

With some extensions (methods can be called with function syntax, in-scope
functions are also considered during method lookup), Design 2 could close
the expressiveness gap versus Design 1. But the simplicity gap would remain.



 The search all traits in scope behavior strikes me as far more magical
 than this.


All of that said, maybe I'm insufficiently worked up about the method
lookup rules. :) Searching trait impls does sound a little bit scary. What
about, as a less scary in-between solution, while not throwing the baby out
with the bathwater, attempting to unify the type of the receiver with the
types of the first (`self`) arguments of the functions of the given name in
the current scope, but *not* looking at trait impls? And if there's a
unique match (modulo autoborrowing and such) it's selected, otherwise an
error is reported. Whether appropriate trait impls exist would be checked
after a method is selected. This means that if you have a trait method or
function in scope which is generic in its self-type, and any other function
which also matches the type of the receiver, it would lead to ambiguity.
But as (in my proposal) you would no longer have to use traits to implement
extension methods, this would hopefully be a less common occurrence.

Again though, I think this can and should be considered as a separate
matter. It could be done inside the current system, I think, if you wanted
to. The differences in the context of my proposal are the aforementioned
not having to use traits for extension methods, and that you would have
more ways to resolve an ambiguity.


It's probably easier to list languages that *don't* have this feature in
 some form than to list languages that do, honestly...


That's because all of the mainstream languages follow misguided OO ideas,
and most of the others copy them. :-)


-- 
Your ship was destroyed in a monadic eruption.
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


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

2013-10-20 Thread Patrick Walton
Maximum conceptual simplicity has never been a design goal of Rust. If we 
wanted maximum simplicity we would just eliminate the dot operator entirely and 
use explicit existential types for trait objects like Haskell.

I know that the dot operator is additional unnecessary complexity. No argument 
there. The thing is that the lookup rules are complexity I think we should buy 
into because of the convenience and familiarity we get from them. We tried 
explicit implementation importing, as well as having no dot operator at all, in 
early versions of Rust. That language was a lot less convenient and limited 
than Rust of today.

The dot operator is there to allow object-oriented programming, including 
type-based method lookup. If you find OO distasteful, then you should be able 
to avoid use of the dot operator and still program Rust without loss of 
functionality (well, first-class trait objects excepted). That is what I had in 
mind with UMCS.

As for some of the specifics in your list, I'd like to fix them. For example, I 
was going to bring up allowing custom smart pointer self types, as well as 
allowing use from impls, at a meeting soon. In general I have been thinking 
that type implementations and traits should be considered modules and should 
admit everything that can appear in a module.

Patrick

Gábor Lehel illiss...@gmail.com wrote:
On Sun, Oct 20, 2013 at 9:38 PM, Patrick Walton pwal...@mozilla.com
wrote:

 I guess I just don't see the value in requiring imports of names when
 there can be no ambiguity and they're defined in one place (the impl
of the
 type, defined in the same place as the type itself). One person's
magic
 is another person's smart compiler.


A big part of the motivation would be to allow declaring methods
anywhere,
without using traits, and then they're defined in one place stops
being
true. For that to be workable you need to have control over imports.
(Luckily with top-level functions, you already do.)



 I'm not convinced that this is solving a real problem.


It's not solving a real problem so much as simplifying the whole
thing.
Despite having used the word, my beef with the current system is not so
much that it's magical. It's that it's completely unnecessary. With
nothing
more than a simple syntax rule and the existing module system, you can
recover all of the expressive power of the current system, and more.

Compare:


-- Design 1 --

 - You can declare functions using `fn`.

- Functions in the current scope can be called using dot syntax with
the
first argument as the receiver. (Optionally: only if the first argument
is
named `self`.)

 - The module system can be used to group types, functions, and other
items, import them together, selectively, or under different names, and
resolve ambiguities between them.


-- Design 2 --

- Anonymous `impl` blocks can be used to associate methods with a type.

- Methods are scoped under and imported together with their type or
trait.

- Because of this, an anonymous `impl` can only be declared in the same
module as its type.

 - If you want to declare a method somewhere else, declare an auxiliary
trait and implement it for that type.

- For a method to be called with dot syntax, it has to be declared
using
special `self`, `self`, `~self`, (or so forth) syntax, which only
works
with the built-in pointer types. Such a method can't be called with
function syntax.

- If you want a self-type other than one of the built-in pointers,
write
an `impl` specifically for that type.

- Types and traits are like modules in some ways (you can use them in a
path), but not others (you can't `use` from them).

- There are special rules and/or syntax for dealing with traits,
generic
types, and optionally their type arguments in paths.

- In addition to methods, you can also declare top-level functions with
`fn`. These can only be called with function syntax.

 - The module system can be used to group, import, rename, and resolve
ambiguities between types, functions, and other items except for
methods.

Which one feels like the tighter design?

With some extensions (methods can be called with function syntax,
in-scope
functions are also considered during method lookup), Design 2 could
close
the expressiveness gap versus Design 1. But the simplicity gap would
remain.



 The search all traits in scope behavior strikes me as far more
magical
 than this.


All of that said, maybe I'm insufficiently worked up about the method
lookup rules. :) Searching trait impls does sound a little bit scary.
What
about, as a less scary in-between solution, while not throwing the baby
out
with the bathwater, attempting to unify the type of the receiver with
the
types of the first (`self`) arguments of the functions of the given
name in
the current scope, but *not* looking at trait impls? And if there's a
unique match (modulo autoborrowing and such) it's selected, otherwise
an
error is reported. Whether appropriate trait impls exist would be
checked
after a method 

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

2013-10-19 Thread Oren Ben-Kiki
Interesting idea; in that case, one could string together any series of
functions - basically, `.` would become the equivalent of `|` (or whatever
other name you want to call it). That is, instead of writing
`baz(bar(foo(x), y), z)` one could write `foo(x).bar(y).baz(z)`. This would
make it easier to write things in functional style, using the same syntax
as the object style.

It could be viewed as the natural complement for the `do` keyword, which
adds a last block parameter to the end of the function.

I'm less certain about giving up `impl Foo { ... }`, though - that is
useful for logically grouping, documenting and accessing functions (as in
`Foo::foo(...)`). But it seems we don't have to give it up, just make it
optional?

On Sat, Oct 19, 2013 at 3:47 PM, Matthieu Monrocq 
matthieu.monr...@gmail.com wrote:

 I see no reason for the restriction of self. Why not simply say that any
 function can be called with first_arg.func(...) style ?

___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


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

2013-10-19 Thread Gábor Lehel
On Sat, Oct 19, 2013 at 4:08 PM, Oren Ben-Kiki o...@ben-kiki.org wrote:


 I'm less certain about giving up `impl Foo { ... }`, though - that is
 useful for logically grouping, documenting and accessing functions (as in
 `Foo::foo(...)`). But it seems we don't have to give it up, just make it
 optional?


Interesting point. I think this argues in favor of removing anonymous
`impl`s, even as sugar. I was focused on normal (selfish) methods in my
previous letter, rather than static (selfless) ones. You could still
achieve much the same effect, if you wanted to, by writing:

struct Foo { .. }

fn get_thing(self: Foo) - Bar { .. } // for `some_foo.get_thing()`
syntax

mod Foo {
fn new() - Foo { .. } // for `Foo::new()` syntax
}

Rust already allows this trickery: the type and module are imported
together when you write `use some_mod::Foo`. Keeping this seems fine, and
making it more explicit (relative to `impl`) seems like a good thing. What
you lose is that in the case of a generic type, you would have to write the
generic-bits for each function, which is the more typing disadvantage
from earlier. I think losing the `impl` sugar is a small price to pay for
the simplification of the language. Modules would be modules and types
would be types. Append to the advantages list:

 - The complexity related to (possibly-generic) types in paths would go away


On Sat, Oct 19, 2013 at 3:47 PM, Matthieu Monrocq 
 matthieu.monr...@gmail.com wrote:

 I see no reason for the restriction of self. Why not simply say that
 any function can be called with first_arg.func(...) style ?


Yeah, as I mentioned in the last bullet of the previous letter, you could
do this. I don't think it makes much difference either way and don't have a
strong opinion.

In favor of explicit `self` is that it's, well, explicit: you can and
should call this using method syntax. I can imagine there might be
function signatures where using method syntax wouldn't make sense (though
you might say, then don't use it, and I would be inclined to agree). A
non-method function (one without a `self` arg) also wouldn't cause
ambiguity if it were in scope at the same time as you were calling another
method with the same name.

In favor of always allowing method syntax on the first argument is that you
could destructure it in the definition, e.g. `fn area((x, y): (int, int))
- int { x * y }`, and still call the function using method syntax.

They're all pretty minor.

-- 
Your ship was destroyed in a monadic eruption.
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


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

2013-10-19 Thread Patrick Walton
I think it's unfortunately too late to overhaul the language like this. This 
will require redesigns of all Rust code in existence.

I do like unified function/method call syntax, but I think it can be done in a 
backwards compatible way.

Patrick

Gábor Lehel illiss...@gmail.com wrote:
On Sat, Oct 19, 2013 at 4:08 PM, Oren Ben-Kiki o...@ben-kiki.org
wrote:


 I'm less certain about giving up `impl Foo { ... }`, though - that is
 useful for logically grouping, documenting and accessing functions
(as in
 `Foo::foo(...)`). But it seems we don't have to give it up, just make
it
 optional?


Interesting point. I think this argues in favor of removing anonymous
`impl`s, even as sugar. I was focused on normal (selfish) methods in
my
previous letter, rather than static (selfless) ones. You could
still
achieve much the same effect, if you wanted to, by writing:

struct Foo { .. }

   fn get_thing(self: Foo) - Bar { .. } // for `some_foo.get_thing()`
syntax

mod Foo {
fn new() - Foo { .. } // for `Foo::new()` syntax
}

Rust already allows this trickery: the type and module are imported
together when you write `use some_mod::Foo`. Keeping this seems fine,
and
making it more explicit (relative to `impl`) seems like a good thing.
What
you lose is that in the case of a generic type, you would have to write
the
generic-bits for each function, which is the more typing disadvantage
from earlier. I think losing the `impl` sugar is a small price to pay
for
the simplification of the language. Modules would be modules and types
would be types. Append to the advantages list:

- The complexity related to (possibly-generic) types in paths would go
away


On Sat, Oct 19, 2013 at 3:47 PM, Matthieu Monrocq 
 matthieu.monr...@gmail.com wrote:

 I see no reason for the restriction of self. Why not simply say
that
 any function can be called with first_arg.func(...) style ?


Yeah, as I mentioned in the last bullet of the previous letter, you
could
do this. I don't think it makes much difference either way and don't
have a
strong opinion.

In favor of explicit `self` is that it's, well, explicit: you can and
should call this using method syntax. I can imagine there might be
function signatures where using method syntax wouldn't make sense
(though
you might say, then don't use it, and I would be inclined to agree).
A
non-method function (one without a `self` arg) also wouldn't cause
ambiguity if it were in scope at the same time as you were calling
another
method with the same name.

In favor of always allowing method syntax on the first argument is that
you
could destructure it in the definition, e.g. `fn area((x, y): (int,
int))
- int { x * y }`, and still call the function using method syntax.

They're all pretty minor.

-- 
Your ship was destroyed in a monadic eruption.




___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev

-- 
Sent from my Android phone with K-9 Mail. Please excuse my brevity.___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


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

2013-10-19 Thread Ziad Hatahet
On Sat, Oct 19, 2013 at 1:52 PM, Patrick Walton pwal...@mozilla.com wrote:

 I think it's unfortunately too late to overhaul the language like this.
 This will require redesigns of all Rust code in existence.

 I do like unified function/method call syntax, but I think it can be done
 in a backwards compatible way.


What do you have in mind at the moment? Implementing UFCS while still
keeping the `impl` syntax around for structs? What about for primitive
types, e.g. would `fn double(a: int) - { 2*a }` be callable as
`2.double()`, without breaking backward compatibility?

Thanks


--
Ziad
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


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

2013-10-19 Thread David Piepgrass

  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
  explicitly.
 
  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)`.
 

 I see no reason for the restriction of self. Why not simply say that any
 function can be called with first_arg.func(...) style ?


D has that rule (which they call UFCS), and I find it confusing
sometimes. When a function is declared with function syntax and it makes
sense or feels right that it should be a function, my mind is not
expecting to see method syntax and I may have trouble figuring out later
what an apparent method call refers to, even if I've seen the function
declaration. Mind you it is worse in D than Rust, because in D, function
declarations can be hidden inside what they call eponymous templates,
which has stumped me in the past.

In any case, wouldn't it help narrow down searches if you could search for
fn foo(self instead of only fn foo? (again though, Rust is not as bad
for searching as the C-family languages that have no fn keyword.) In C#
it's nice that I can find all the so-called extension methods by searching
for (this .
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


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

2013-10-19 Thread Ziad Hatahet
On Sat, Oct 19, 2013 at 4:35 PM, David Piepgrass qwertie...@gmail.comwrote:

 In C# it's nice that I can find all the so-called extension methods by
 searching for (this .



Aren't `impl`s in Rust somewhat similar to extension methods in C#? For
instance:

trait Doubler {
fn double(self) - Self;
}

impl Doubler for int {
fn double(self) - int { *self * 2 }
}


Then you can call 5.double().


--
Ziad
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


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

2013-10-19 Thread Steven Blenkinsop
On Saturday, October 19, 2013, Ziad Hatahet wrote:

 On Sat, Oct 19, 2013 at 4:35 PM, David Piepgrass 
 qwertie...@gmail.comjavascript:_e({}, 'cvml', 'qwertie...@gmail.com');
  wrote:

 In C# it's nice that I can find all the so-called extension methods by
 searching for (this .



 Aren't `impl`s in Rust somewhat similar to extension methods in C#?


Loosely, if you ignore that each impl overloads an abstract interface
(trait) over the Self type, and that you can constrain a type parameter
based on whether there's an overload of a certain abstract interface for it.
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev