Re: [rust-dev] self/mut self in traits considered harmful(?)

2014-06-22 Thread Cameron Zwarich
On Jun 16, 2014, at 3:19 PM, Patrick Walton pcwal...@mozilla.com wrote:

 On 6/16/14 3:17 PM, Cameron Zwarich wrote:
 I stated the right case, but the wrong reason. It’s not for
 vectorization, it’s because it’s not easy to reuse the storage of a
 matrix while multiplying into it.
 
 Wouldn't most matrices be implicitly copyable (and thus optimized--or at 
 least optimizable--into by-ref at the ABI level)?

Sorry for the super-late reply, but if you reuse the same argument multiple 
times, you will have made multiple copies of it, right? A sufficiently 
optimizing compiler would probably be able to optimize it if everything is 
inlined.

However, that also only applies to dense matrices. Sparse matrices are unlikely 
to be Copy.

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


Re: [rust-dev] self/mut self in traits considered harmful(?)

2014-06-17 Thread Tommi
Can you elaborate a bit more on why/how exactly did the earlier language design 
(implicitly clone by default if it's absolutely necessary and otherwise move, 
instead of move by default) result in much more cloning? Because intuitively it 
seems to me that if you try to use data that has been moved away, then it means 
that you didn't intend to move the data away in the first place, but to clone 
it. And vice versa.


On 2014-06-12, at 21:15, Patrick Walton pcwal...@mozilla.com wrote:

 On 6/12/14 11:15 AM, Tommi wrote:
 On 2014-06-12, at 20:59, Corey Richardson co...@octayn.net
 mailto:co...@octayn.net wrote:
 
 Implicit cloning is a non-starter. Clones can be very expensive.
 Hiding that cost is undesirable and would require adding Clone to the
 language (it's currently a normal library feature).
 
 But I think it will be easy to make the error of writing the explicit
 .clone() in places where it's not needed. For example:
 
 fn fooT(value: T) {}
 
 let x = box 123;
 x.clone().foo();
 x.clone().foo();
 
 ...given that `x` is not used after those lines, the last call to
 .clone() is unnecessary. Whereas, if the task of cloning (implicitly) is
 assigned to the compiler, then the compiler can use static analysis to
 make sure such programming errors never occur. The example above would
 become something like:
 
 fn fooT(stable value: T) {}
 
 let x = box 123;
 x.foo(); // here `x` gets cloned here
 x.foo(); // here `x` doesn't get cloned because this is the last use of `x`
 
 We tried that in earlier versions of Rust. There were way too many clones.
 
 Patrick
 

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


Re: [rust-dev] self/mut self in traits considered harmful(?)

2014-06-16 Thread Tommi
On 2014-06-15, at 21:10, Isaac Dupree m...@isaac.cedarswampstudios.org wrote:

 On 6/12/14 11:15 AM, Tommi wrote:
 But I think it will be easy to make the error of writing the explicit
 .clone() in places where it's not needed. For example:
 [...]
 
 Would a compiler warning for unnecessary clones be feasible? useful? Would it 
 have false positives -- situations where a clone would compile as a move but 
 do the wrong thing?

I would just ignore the first 12 of my posts on this thread.

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


Re: [rust-dev] self/mut self in traits considered harmful(?)

2014-06-15 Thread Benjamin Striegel
 The manner in which the expression accomplishes this task is an
implementation detail.

You're welcome to draft a proposal if you think that you have an idea to
make this possible. Though all of the solutions that I can envision require
abandoning the idea of operators-as-traits and introducing a whole lot of
magic in their place.
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] self/mut self in traits considered harmful(?)

2014-06-15 Thread Tommi
On 2014-06-15, at 9:56, Benjamin Striegel ben.strie...@gmail.com wrote:

 You're welcome to draft a proposal if you think that you have an idea to make 
 this possible.

The idea of the `stable` keyword was designed specifically as a bandage on the 
current trait-system to allow a trait to say that: this function argument can 
be passed however you like as long as the caller of this function won't be able 
to see it modified. I introduced this idea on a long, previous post which 
began with:

 The problem:
 Chained calls to certain operators such as binary `*` and `+` may cause 
 unnecessary memory allocations. [..]


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


Re: [rust-dev] self/mut self in traits considered harmful(?)

2014-06-15 Thread Tommi
I realized that, in my proposal, there's a potentially pretty confusing 
asymmetry of what `stable` means. In the trait definition:

pub trait MulRHS, Result {
fn mul(stable self, rhs: RHS) - Result;
}

...the keyword `stable` means that however the type which implements this trait 
decides to pass `self` to `mul`, it must be guaranteed that the caller of `mul` 
won't be able to observe the variable passed in as `self` being modified by 
this call to `mul`. Also, a trait function that has at least one argument 
marked as `stable` wouldn't be allowed to have a provided (default) definition, 
because its signature doesn't say how that `stable` argument should be passed 
in.

But on the actual implementation, like here:

implT: Clone, RHS, Result MulRHS, Result for T {
fn mul(stable self, rhs: RHS) - Result { ... }
}

...the keyword `stable` means that the variable which the caller of `mul` 
passes in as the `self` argument will be implicitly cloned before it's passed 
in if it is necessary to do so in order to ensure that the caller of `mul` 
won't see that variable modified by `mul`. Static analysis will be used by the 
compiler to determine when this implicit cloning can be omitted (it may 
potentially be omitted due to the caller not observing the state of the passed 
in variable after the function call and (possibly) before the variable getting 
assigned a new value).

Perhaps another keyword would be needed for this second meaning of `stable`, 
since it's completely different from the meaning of `stable` in trait 
functions. Maybe something like `cloned`.

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


Re: [rust-dev] self/mut self in traits considered harmful(?)

2014-06-15 Thread Isaac Dupree

On 6/12/14 11:15 AM, Tommi wrote:

But I think it will be easy to make the error of writing the explicit
.clone() in places where it's not needed. For example:
[...]


Would a compiler warning for unnecessary clones be feasible? useful? 
Would it have false positives -- situations where a clone would compile 
as a move but do the wrong thing?


-Isaac

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


Re: [rust-dev] self/mut self in traits considered harmful(?)

2014-06-14 Thread Tommi
I think that the deeper and larger language design issue here is that traits in 
some cases force you to impose on the trait-implementing type some 
implementation details that should remain hidden in the specification of the 
trait and should be left to the trait-implementing type to specify.

The high level (of abstraction) description of an expression like:

a * b

...is that that it should evaluate to the product of `a` and `b` without 
modifying neither `a` nor `b`.

The manner in which the expression accomplishes this task is an implementation 
detail. If the expression above evaluates to a function call where `a` and `b` 
are passed as arguments, then the manner in which the two arguments are passed 
into such a function is an implementation detail, assuming there are multiple 
ways in which the arguments could be passed and the function call could still 
fulfill the high level requirements and guarantees of the expression. For 
example, POD `a` and `b` could be passed to such a product evaluating function 
in multiple ways, namely by value and by reference.

If the definition of `Mul` trait specifies the exact manner in which the 
arguments must be passed to this product evaluating function, then the trait is 
revealing and imposing an implementation detail that should be left to the 
judgement of the type which implements such trait.

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


Re: [rust-dev] self/mut self in traits considered harmful(?)

2014-06-13 Thread Tommi
The problem:
Chained calls to certain operators such as binary `*` and `+` may cause 
unnecessary memory allocations. For example:

struct Vector {
coordinates: Vecint
}

impl Mulint, Vector for Vector {
fn mul(self, rhs: int) - Vector {
let mut new_coordinates = self.coordinates.clone();
for c in new_coordinates.mut_iter() {
*c *= *rhs;
}
Vector { coordinates: new_coordinates }
}
}

fn get_vector() - Vector {
let v = Vector { coordinates: vec!(1, 2, 3) };
v * 2 * 5
}

The last line of `get_vector` causes two new memory allocations. Preferably 
that line wouldn't allocate at all; it should take the guts out of `v` and 
multiply the coordinates in place.

The goal:
We want to be able to write the following function `calculate` and have it be 
guaranteed that `calculate` doesn't cause unnecessary memory allocations.

fn calculateX, T: MulX, T + AddT, T(value: T, mult: X) - T {
value * mult * mult + value
}

Insufficient first idea for a solution:
Change the definition of `Mul` trait to:

pub trait MulRHS, Result {
fn mul(self, rhs: RHS) - Result;
}

And then, change the implementation of `Mul` for `Vector` to:

impl Mulint, Vector for Vector {
fn mul(self, rhs: int) - Vector {
for c in self.coordinates.mut_iter() {
*c *= *rhs;
}
self
}
}

First of all, as a result of these changes, the `calculate` function wouldn't 
compile complaining about the last use of `value` that: error: use of moved 
value: `value`. This could be fixed by changing the definition of `calculate`, 
but this is not the main problem.

But the real problem is that for some types, the binary `*` operator shouldn't 
move the `self` into the `mul` method. For example, when the return type of the 
`mul` method is different from the type of `self` (and both are heap 
allocated), then `mul` method is forced to allocate a new value which it 
returns, and it should take `self` by reference.

My proposed solution:
Add a new keyword `stable` to the language. Marking a function argument 
`stable` gives the guarantee to the caller of that function, that a variable 
passed in as that argument is logically unchanged after the function call ends.

Then, change the definition of `Mul` trait to:

pub trait MulRHS, Result {
fn mul(stable self, rhs: RHS) - Result;
}

Note: any other syntax for marking `self` as `stable` would be illegal.

One could implement `Mul` for any type by taking `self` by shared reference:

implT, RHS, Result MulRHS, Result for T {
fn mul(self, rhs: RHS) - Result { ... }
}

Or, one could implement `Mul` for any type that implements `Copy` by taking 
`self` by value:

implT: Copy, RHS, Result MulRHS, Result for T {
fn mul(self, rhs: RHS) - Result { ... }
}

Or, one could implement `Mul` for any type that implements `Clone` by taking 
`self` by stable value:

implT: Clone, RHS, Result MulRHS, Result for T {
fn mul(stable self, rhs: RHS) - Result { ... }
}

Taking an argument by stable value (as `self` above) means that any 
(clonable) variable passed in as that argument is implicitly cloned before it's 
passed in if the variable is potentially used after been passed in. For example:

impl Mulint, Vector for Vector {
fn mul(stable self, rhs: int) - Vector {
for c in self.coordinates.mut_iter() {
*c *= *rhs;
}
self
}
}

fn testing() {
let mut v = Vector { coordinates: vec!(1, 2, 3) };
v * 1; // Cloned due to not last use
v * 1; // Not cloned due to last use before assignment
v = Vector { coordinates: vec!(2, 4, 6) };
v * 1; // Cloned due to not last use
v = v * 1; // Not cloned due to last use before assignment
v * 1; // Not cloned due to last use
}

Open questions:
What should happen for example with `Rc` types w.r.t. `stable`:

implT, RHS, Result MulRHS, Result for RcT {
fn mul(stable self, rhs: RHS) - Result { ... }
}

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


Re: [rust-dev] self/mut self in traits considered harmful(?)

2014-06-13 Thread Tommi
On 2014-06-13, at 13:14, Tommi rusty.ga...@icloud.com wrote:

 pub trait MulRHS, Result {
 fn mul(stable self, rhs: RHS) - Result;
 }
 
 Note: any other syntax for marking `self` as `stable` would be illegal.

Although, I could see this kind of syntax being allowed as well:

pub trait MulRHS, Result {
fn mul(stable lhs: Self, rhs: RHS) - Result;
}

..and allowing similar syntax for an implementation like:

implT: Clone, RHS, Result MulRHS, Result for T {
fn mul(stable lhs: T, rhs: RHS) - Result { ... }
}

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


Re: [rust-dev] self/mut self in traits considered harmful(?)

2014-06-13 Thread Patrick Walton

I have filed RFC #118 for this:

https://github.com/rust-lang/rfcs/pull/118

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


Re: [rust-dev] self/mut self in traits considered harmful(?)

2014-06-12 Thread Tommi
On 2014-06-11, at 16:27, SiegeLord slab...@aim.com wrote:

 So, I think the situation is pretty bad. What can be done to fix it?

I agree that this seems like a serious regression from C++. If it won't be 
fixed, I think I'll rather stick with C++. Better the devil you know...

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


Re: [rust-dev] self/mut self in traits considered harmful(?)

2014-06-12 Thread Patrick Walton

On 6/12/14 1:02 AM, Tommi wrote:

On 2014-06-11, at 16:27, SiegeLord slab...@aim.com
mailto:slab...@aim.com wrote:


So, I think the situation is pretty bad. What can be done to fix it?


I agree that this seems like a serious regression from C++. If it won't
be fixed, I think I'll rather stick with C++. Better the devil you know...


This message is unhelpful.

Patrick

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


Re: [rust-dev] self/mut self in traits considered harmful(?)

2014-06-12 Thread Patrick Walton

On 6/11/14 6:27 AM, SiegeLord wrote:

So, I think the situation is pretty bad. What can be done to fix it?


Seems to me we can just make the overloaded operator traits take 
by-value self.


Patrick

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


Re: [rust-dev] self/mut self in traits considered harmful(?)

2014-06-12 Thread Tommi
On 2014-06-12, at 19:08, Patrick Walton pcwal...@mozilla.com wrote:

 On 6/11/14 6:27 AM, SiegeLord wrote:
 So, I think the situation is pretty bad. What can be done to fix it?
 
 Seems to me we can just make the overloaded operator traits take by-value 
 self.

I definitely wouldn't want to see something like the following:

pub trait GreaterByOneT {
fn greater_by_one(self) - Self;
}

pub fn my_algorithmX, T: GreaterByOneX + AddT, T(value: T) - T {
value.greater_by_one() +
value.greater_by_one() // error: use of moved value: `value`
}

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


Re: [rust-dev] self/mut self in traits considered harmful(?)

2014-06-12 Thread Patrick Walton
You could just clone the value to get around that error.

On June 12, 2014 10:03:40 AM PDT, Tommi rusty.ga...@icloud.com wrote:
On 2014-06-12, at 19:08, Patrick Walton pcwal...@mozilla.com wrote:

 On 6/11/14 6:27 AM, SiegeLord wrote:
 So, I think the situation is pretty bad. What can be done to fix it?
 
 Seems to me we can just make the overloaded operator traits take
by-value self.

I definitely wouldn't want to see something like the following:

pub trait GreaterByOneT {
fn greater_by_one(self) - Self;
}

pub fn my_algorithmX, T: GreaterByOneX + AddT, T(value: T) - T {
value.greater_by_one() +
value.greater_by_one() // error: use of moved value: `value`
}

-- 
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] self/mut self in traits considered harmful(?)

2014-06-12 Thread Corey Richardson
Or bound by Copy.

On Thu, Jun 12, 2014 at 10:17 AM, Patrick Walton pwal...@mozilla.com wrote:
 You could just clone the value to get around that error.


 On June 12, 2014 10:03:40 AM PDT, Tommi rusty.ga...@icloud.com wrote:

 On 2014-06-12, at 19:08, Patrick Walton pcwal...@mozilla.com wrote:

 On 6/11/14 6:27 AM, SiegeLord wrote:

 So, I think the situation is pretty bad. What can be done to fix it?


 Seems to me we can just make the overloaded operator traits take by-value
 self.


 I definitely wouldn't want to see something like the following:

 pub trait GreaterByOneT {
 fn greater_by_one(self) - Self;
 }

 pub fn my_algorithmX, T: GreaterByOneX + AddT, T(value: T) - T {
 value.greater_by_one() +
 value.greater_by_one() // error: use of moved value: `value`
 }


 --
 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




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


Re: [rust-dev] self/mut self in traits considered harmful(?)

2014-06-12 Thread Tommi
I think a new keyword, something like `stable`, is needed for specifying that 
an argument passed to a trait function is guaranteed to be logically unchanged 
after the function call. For example:

trait Foo {
fn foo(stable self);
}

impl Foo for int {
fn foo(self) {} // OK
}

impl Foo for uint {
fn foo(self) {} // OK
}

impl Foo for Boxint {
fn foo(stable self) {} // OK (implicitly clones self)
}


fn main() {
let x: Boxint = box 42;
x.foo(); // `x` is implicitly cloned
x.foo(); // OK
}

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


Re: [rust-dev] self/mut self in traits considered harmful(?)

2014-06-12 Thread Corey Richardson
It's called Copy. `trait Foo: Copy { ... }`.

On Thu, Jun 12, 2014 at 10:26 AM, Tommi rusty.ga...@icloud.com wrote:
 I think a new keyword, something like `stable`, is needed for specifying that 
 an argument passed to a trait function is guaranteed to be logically 
 unchanged after the function call. For example:

 trait Foo {
 fn foo(stable self);
 }

 impl Foo for int {
 fn foo(self) {} // OK
 }

 impl Foo for uint {
 fn foo(self) {} // OK
 }

 impl Foo for Boxint {
 fn foo(stable self) {} // OK (implicitly clones self)
 }


 fn main() {
 let x: Boxint = box 42;
 x.foo(); // `x` is implicitly cloned
 x.foo(); // OK
 }

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



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


Re: [rust-dev] self/mut self in traits considered harmful(?)

2014-06-12 Thread Tommi
`Copy` types aren't really relevant to a discussion about adding to Rust the 
C++ like optimization of moving rvalues (of non-Copy types) when they're passed 
to certain functions.

On 2014-06-12, at 20:30, Corey Richardson co...@octayn.net wrote:

 It's called Copy. `trait Foo: Copy { ... }`.
 
 On Thu, Jun 12, 2014 at 10:26 AM, Tommi rusty.ga...@icloud.com wrote:
 I think a new keyword, something like `stable`, is needed for specifying 
 that an argument passed to a trait function is guaranteed to be logically 
 unchanged after the function call. For example:
 
 trait Foo {
fn foo(stable self);
 }
 
 impl Foo for int {
fn foo(self) {} // OK
 }
 
 impl Foo for uint {
fn foo(self) {} // OK
 }
 
 impl Foo for Boxint {
fn foo(stable self) {} // OK (implicitly clones self)
 }
 
 
 fn main() {
let x: Boxint = box 42;
x.foo(); // `x` is implicitly cloned
x.foo(); // OK
 }
 
 ___
 Rust-dev mailing list
 Rust-dev@mozilla.org
 https://mail.mozilla.org/listinfo/rust-dev
 
 
 
 -- 
 http://octayn.net/

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


Re: [rust-dev] self/mut self in traits considered harmful(?)

2014-06-12 Thread Patrick Walton

On 6/12/14 10:46 AM, Tommi wrote:

`Copy` types aren't really relevant to a discussion about adding to
Rust the C++ like optimization of moving rvalues (of non-Copy types)
when they're passed to certain functions.


There's nothing to add to Rust. Rust supports moves.

Patrick

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


Re: [rust-dev] self/mut self in traits considered harmful(?)

2014-06-12 Thread Corey Richardson
Implicit cloning is a non-starter. Clones can be very expensive.
Hiding that cost is undesirable and would require adding Clone to the
language (it's currently a normal library feature).

On Thu, Jun 12, 2014 at 10:46 AM, Tommi rusty.ga...@icloud.com wrote:
 `Copy` types aren't really relevant to a discussion about adding to Rust the 
 C++ like optimization of moving rvalues (of non-Copy types) when they're 
 passed to certain functions.

 On 2014-06-12, at 20:30, Corey Richardson co...@octayn.net wrote:

 It's called Copy. `trait Foo: Copy { ... }`.

 On Thu, Jun 12, 2014 at 10:26 AM, Tommi rusty.ga...@icloud.com wrote:
 I think a new keyword, something like `stable`, is needed for specifying 
 that an argument passed to a trait function is guaranteed to be logically 
 unchanged after the function call. For example:

 trait Foo {
fn foo(stable self);
 }

 impl Foo for int {
fn foo(self) {} // OK
 }

 impl Foo for uint {
fn foo(self) {} // OK
 }

 impl Foo for Boxint {
fn foo(stable self) {} // OK (implicitly clones self)
 }


 fn main() {
let x: Boxint = box 42;
x.foo(); // `x` is implicitly cloned
x.foo(); // OK
 }

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



 --
 http://octayn.net/




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


Re: [rust-dev] self/mut self in traits considered harmful(?)

2014-06-12 Thread Tommi
On 2014-06-12, at 20:51, Patrick Walton pcwal...@mozilla.com wrote:

 On 6/12/14 10:46 AM, Tommi wrote:
 `Copy` types aren't really relevant to a discussion about adding to
 Rust the C++ like optimization of moving rvalues (of non-Copy types)
 when they're passed to certain functions.
 
 There's nothing to add to Rust. Rust supports moves.

You're right, I said it wrong (the last part, not the `Copy` being irrelevant 
part). There's no need to add to the language the ability to move (obviously it 
has that), but perhaps there's a need to add the ability to not move certain 
arguments by default, for convenience. I wouldn't want to see generic code 
littered with explicit .clone()'s all over the place.

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


Re: [rust-dev] self/mut self in traits considered harmful(?)

2014-06-12 Thread Dmitry Romanov
Sorry, Im a little new to Rust, but I'm,as many, now considering moving
from c++ to Rust and the topic is really important for my tasks.

Could you give an Rust example for the concern listed above?

Thank you!
On Jun 12, 2014 9:51 PM, Patrick Walton pcwal...@mozilla.com wrote:

 On 6/12/14 10:46 AM, Tommi wrote:

 `Copy` types aren't really relevant to a discussion about adding to
 Rust the C++ like optimization of moving rvalues (of non-Copy types)
 when they're passed to certain functions.


 There's nothing to add to Rust. Rust supports moves.

 Patrick

 ___
 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] self/mut self in traits considered harmful(?)

2014-06-12 Thread Tommi
On 2014-06-12, at 20:59, Corey Richardson co...@octayn.net wrote:

 Implicit cloning is a non-starter. Clones can be very expensive.
 Hiding that cost is undesirable and would require adding Clone to the
 language (it's currently a normal library feature).

But I think it will be easy to make the error of writing the explicit .clone() 
in places where it's not needed. For example:

fn fooT(value: T) {}

let x = box 123;
x.clone().foo();
x.clone().foo();

...given that `x` is not used after those lines, the last call to .clone() is 
unnecessary. Whereas, if the task of cloning (implicitly) is assigned to the 
compiler, then the compiler can use static analysis to make sure such 
programming errors never occur. The example above would become something like:

fn fooT(stable value: T) {}

let x = box 123;
x.foo(); // here `x` gets cloned here
x.foo(); // here `x` doesn't get cloned because this is the last use of `x`

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


Re: [rust-dev] self/mut self in traits considered harmful(?)

2014-06-12 Thread Patrick Walton

On 6/12/14 11:15 AM, Tommi wrote:

On 2014-06-12, at 20:59, Corey Richardson co...@octayn.net
mailto:co...@octayn.net wrote:


Implicit cloning is a non-starter. Clones can be very expensive.
Hiding that cost is undesirable and would require adding Clone to the
language (it's currently a normal library feature).


But I think it will be easy to make the error of writing the explicit
.clone() in places where it's not needed. For example:

fn fooT(value: T) {}

let x = box 123;
x.clone().foo();
x.clone().foo();

...given that `x` is not used after those lines, the last call to
.clone() is unnecessary. Whereas, if the task of cloning (implicitly) is
assigned to the compiler, then the compiler can use static analysis to
make sure such programming errors never occur. The example above would
become something like:

fn fooT(stable value: T) {}

let x = box 123;
x.foo(); // here `x` gets cloned here
x.foo(); // here `x` doesn't get cloned because this is the last use of `x`


We tried that in earlier versions of Rust. There were way too many clones.

Patrick

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


Re: [rust-dev] self/mut self in traits considered harmful(?)

2014-06-12 Thread Tommi
On 2014-06-12, at 21:15, Patrick Walton pcwal...@mozilla.com wrote:

 On 6/12/14 11:15 AM, Tommi wrote:
 On 2014-06-12, at 20:59, Corey Richardson co...@octayn.net
 mailto:co...@octayn.net wrote:
 
 Implicit cloning is a non-starter. Clones can be very expensive.
 Hiding that cost is undesirable and would require adding Clone to the
 language (it's currently a normal library feature).
 
 But I think it will be easy to make the error of writing the explicit
 .clone() in places where it's not needed. For example:
 
 fn fooT(value: T) {}
 
 let x = box 123;
 x.clone().foo();
 x.clone().foo();
 
 ...given that `x` is not used after those lines, the last call to
 .clone() is unnecessary. Whereas, if the task of cloning (implicitly) is
 assigned to the compiler, then the compiler can use static analysis to
 make sure such programming errors never occur. The example above would
 become something like:
 
 fn fooT(stable value: T) {}
 
 let x = box 123;
 x.foo(); // here `x` gets cloned here
 x.foo(); // here `x` doesn't get cloned because this is the last use of `x`
 
 We tried that in earlier versions of Rust. There were way too many clones.

Oh, okay. But I bet you didn't have the `stable` keyword back then, and thus, 
all by-value arguments were implicitly `stable`, which I wouldn't suggest. Some 
functions clearly need to take a hold of the ownership of their argument and 
shouldn't need to guarantee that the variable passed in stays the same from the 
caller's point of view.

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


Re: [rust-dev] self/mut self in traits considered harmful(?)

2014-06-12 Thread Tommi
For some reason I got really side-tracked here. The whole point of that 
`stable` keyword I proposed was not syntax sugar, but that it allows the 
implementor of such a trait to pass by reference when the operator shouldn't 
move the passed in argument(s). Like, when you multiply two matrices and the 
returned type is not the same size as neither of the arguments types, there's 
no point in modifying either of those arguments in place, but rather you need 
to allocate a new matrix.

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


Re: [rust-dev] self/mut self in traits considered harmful(?)

2014-06-11 Thread Sebastian Gesemann
On Wed, Jun 11, 2014 at 3:27 PM, SiegeLord wrote:
 [...] Along the same lines, it is not immediately obvious
 to me how to extend this lazy evaluation idea to something like num::BigInt.
 So far, it seems like lazy evaluation will force dynamic dispatch in that
 case which is a big shame (i.e. you'd store the operations in one array,
 arguments in another and then play them back at the assignment time).

I havn't tried something like expression templates in Rust yet. How
did you come to the conclusion that it would require dynamic dispatch?
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] self/mut self in traits considered harmful(?)

2014-06-11 Thread Huon Wilson

On 11/06/14 23:27, SiegeLord wrote:
Aside from somewhat more complicated impl's, are there any downsides 
to never using anything but by value 'self' in traits?


Currently trait objects do not support `self` methods (#10672), and, 
generally, the interactions with trait objects seem peculiar, e.g. if 
you've implemented Trait for Type, then you would want to be coercing a 
`Type` to a `Trait`, *not* a `(Type)` as is currently required.


However, I don't think these concerns affect the operator overloading 
traits.



https://github.com/mozilla/rust/issues/10672


Huon

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


Re: [rust-dev] self/mut self in traits considered harmful(?)

2014-06-11 Thread SiegeLord

On 06/11/2014 10:10 AM, Sebastian Gesemann wrote:

On Wed, Jun 11, 2014 at 3:27 PM, SiegeLord wrote:

[...] Along the same lines, it is not immediately obvious
to me how to extend this lazy evaluation idea to something like num::BigInt.
So far, it seems like lazy evaluation will force dynamic dispatch in that
case which is a big shame (i.e. you'd store the operations in one array,
arguments in another and then play them back at the assignment time).


I havn't tried something like expression templates in Rust yet. How
did you come to the conclusion that it would require dynamic dispatch?


It's just the first idea I had with how this could work, but you're 
right, I can envision a way to do this without using dynamic dispatch. 
It'd look something like something like this: 
https://gist.github.com/SiegeLord/f1af81195df89ec04d10 . So, if nothing 
comes out of this discussion, at least you'd be able to do that. Note 
that the API is uglier, since you need to call 'eval' explicitly. 
Additionally, you need to manually borrow 'm' because you can't specify 
a lifetime of the self argument in mul (another problem with 
by-ref-self methods).


-SL

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


Re: [rust-dev] self/mut self in traits considered harmful(?)

2014-06-11 Thread Tommi
If the `Mul` trait and similar were changed to take `self` by value, perhaps 
the following kind of language design would make more sense:

If a variable of a type that has a destructor is passed to a function by value 
(moved), and the variable is used after the function call, the variable would 
be implicitly cloned before passing it to the function.

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


Re: [rust-dev] self/mut self in traits considered harmful(?)

2014-06-11 Thread Daniel Micay
On 11/06/14 01:54 PM, Tommi wrote:
 If the `Mul` trait and similar were changed to take `self` by value, perhaps 
 the following kind of language design would make more sense:
 
 If a variable of a type that has a destructor is passed to a function by 
 value (moved), and the variable is used after the function call, the variable 
 would be implicitly cloned before passing it to the function.

Cloning big integers, rationals based on big integers or arbitrary
precision floating point values for every single operation has a high
cost. One of Rust's strength's is that it doesn't have implicit cloning
as C++ does due to copy constructors.



signature.asc
Description: OpenPGP digital signature
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] self/mut self in traits considered harmful(?)

2014-06-11 Thread Tommi
On 2014-06-11, at 21:33, Daniel Micay danielmi...@gmail.com wrote:

 Cloning big integers, rationals based on big integers or arbitrary
 precision floating point values for every single operation has a high
 cost.

I didn't say that all functions should start taking their arguments by value. I 
said `Mul` and similar should do it, i.e. functions that take a variable and 
return a variable of that same type. Instead of passing by reference and making 
a clone of the passed reference inside those functions, you force the caller to 
make the clone and mutate the passed argument in place. This enables the C++ 
like rvalue reference optimization for functions like multiplication.

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


Re: [rust-dev] self/mut self in traits considered harmful(?)

2014-06-11 Thread Corey Richardson
Keeping in mind that the `self` value here can be a reference. Ie,
implementing the traits also for references to a type.

On Wed, Jun 11, 2014 at 11:47 AM, Tommi rusty.ga...@icloud.com wrote:
 On 2014-06-11, at 21:33, Daniel Micay danielmi...@gmail.com wrote:

 Cloning big integers, rationals based on big integers or arbitrary
 precision floating point values for every single operation has a high
 cost.


 I didn't say that all functions should start taking their arguments by
 value. I said `Mul` and similar should do it, i.e. functions that take a
 variable and return a variable of that same type. Instead of passing by
 reference and making a clone of the passed reference inside those functions,
 you force the caller to make the clone and mutate the passed argument in
 place. This enables the C++ like rvalue reference optimization for functions
 like multiplication.


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




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


Re: [rust-dev] self/mut self in traits considered harmful(?)

2014-06-11 Thread Tommi
On 2014-06-11, at 21:47, Tommi rusty.ga...@icloud.com wrote:

 I said `Mul` and similar should do it, i.e. functions that take a variable 
 and return a variable of that same type.


Although, a larger issue of genericity is that multiplication doesn't always 
return the same type as one of its arguments.

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