[rust-dev] Struct members in trait definitions

2013-09-20 Thread Andres Osinski
Hi all, I have a question which I'm sure must have already been discussed
and dealt with, but I wanted to understand the design rationale:

A lot of trait-level functionality would be enhanced if a trait could
specify members to be included in the struct which implements the trait.
This can be solved in practice by wrapping member access in accessor
methods, but I fail to see why that would be preferable.

The reason I'm asking is because I'm trying to design data structures which
contain a couple of arrays, and I wanted to define the trait by not only a
set of supported operations but by the existence of both arrays so that a
default method could deal with any struct which implements the trait,
instead of having to define for every struct an accessor method for each
structure and then have to call the accessors in the trait to do anything.

Thanks

-- 
Andrés Osinski
http://www.andresosinski.com.ar/
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Struct members in trait definitions

2013-09-20 Thread Felix S. Klock II

Andres (cc'ing rust-dev)-

An initial question, since I'm not clear on one thing:

What is your goal in proposing this change?

That is, is your primary concern that you dislike writing either method 
invocations or method definitions?  Or are you concerned about the 
ability of the compiler to optimize the generated code if one uses 
methods instead of struct fields?




Justifications for why traits should be expressed in terms of associated 
methods, not associated fields (and thus why Rust does things this way):


1.) Method definitions are strictly more general than fields, in terms 
of allowing other implementations to dynamically compute the value, read 
it from a database, from an input stream, etc).  I assume you already 
are aware of this, and just want to know why we don't provide special 
handling for Trait designers willing to rule out such generality up-front.


2.) Associated struct-fields would either disallow mixing traits whose 
names collide, or would require extending the `impl` item syntax with a 
struct-field renaming feature.


Elaboration of point 2:

Traits are designed to be mixed together; the language should discourage 
patterns that make mixing traits on a single type difficult.


The fields of a struct are written down with the `struct` definition.

The associated methods for an implementation are written down with the 
`impl` item.


If two traits require the same kind of associated state, right now you 
would give them identical method names, and the one struct could 
implement both traits (i.e. mixing them) with no ambiguity.


If traits were to define struct names, to get the same amount of 
generality we would need to provide some way to map the field name of 
the struct to the name expected by the trait within `impl` items.  But 
why do that?  A method definition is a perfectly reasonable way to 
express this.




Concrete illustration of point 2 above: How would you express the below 
in your proposal, assuming that *both* T1 and T2 are revised to require 
`state` to be a member field rather than a method?


```rust
trait T1 { fn state(self) - int; }

trait T2 { fn state(self) - int; }

struct one_int { state: int }

struct two_ints { state: int, state2: int }

impl T1 for one_int { fn state(self) - int { self.state } }
impl T2 for one_int { fn state(self) - int { self.state } }

impl T1 for two_ints { fn state(self) - int { self.state } }
impl T2 for two_ints { fn state(self) - int { self.state2 } }
```



Again, to be clear: I'm not saying its impossible to express the example 
above via hypothetical Traits with fields.  But I think it would add 
unnecessary complexity (e.g. extensions to `impl` item syntax).  So 
that's why I wanted to know what the driving motivation here is.


If the motivation is concern over syntactic overhead: method invocations 
vs field deference seems trivial.  The method definitions are more 
annoying boilerplate code, but I imagine that one could write an easy 
macro_rules! for the common case where the Trait method name is the same 
as the struct field name.


If the motivation is concern over the quality of the generated code: I 
assume that LLVM does a good job inlining these things. (If I'm wrong 
about that, I'd like to know.)


Cheers,
-Felix


On 20/09/2013 13:02, Andres Osinski wrote:
Hi all, I have a question which I'm sure must have already been 
discussed and dealt with, but I wanted to understand the design 
rationale:


A lot of trait-level functionality would be enhanced if a trait could 
specify members to be included in the struct which implements the 
trait. This can be solved in practice by wrapping member access in 
accessor methods, but I fail to see why that would be preferable.


The reason I'm asking is because I'm trying to design data structures 
which contain a couple of arrays, and I wanted to define the trait by 
not only a set of supported operations but by the existence of both 
arrays so that a default method could deal with any struct which 
implements the trait, instead of having to define for every struct an 
accessor method for each structure and then have to call the accessors 
in the trait to do anything.


Thanks

--
Andrés Osinski
http://www.andresosinski.com.ar/


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



--
irc: pnkfelix on irc.mozilla.org
email: {fklock, pnkfelix}@mozilla.com

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


Re: [rust-dev] Struct members in trait definitions

2013-09-20 Thread Meredith L. Patterson
Hi Andres,

I'm thinking about your question from a structural typing point of view, so
let me see if an analogy from Scala (which has its own take on traits)
helps. Scala is more of an OO language than Rust is, and Scala traits can
extend classes (abstract or not), which is how it's possible for a trait to
incorporate members (what Niko just described as struct inheritance) --
but the trait itself cannot name a new member, only methods, as with Rust.
So in that regard, traits are also an awful lot like Go's interfaces, in
that they describe the interface that a value must be able to satisfy at
compile time. All three languages are structurally typed, but Go has the
fewest bells and whistles in the type system, Scala the most, and Rust
somewhere in the middle (thanks to generics and type bounds). There are
efficiency reasons for that; it's relevant that Scala is a JVM language.

This isn't a particularly concrete answer, but I hope it helps.

Cheers,
--mlp


On Fri, Sep 20, 2013 at 2:18 PM, andres.osin...@gmail.com wrote:

 It would be audacious to propose this as a change; I'm merely trying to
 understand the philosophy behind certain design decisions,

 My personal motivation comes from an interest in seeing how expressive
 Rust can be as a language to model business objects; I think the
 intersection between high-level logic and type classes with low-level
 access, extreme efficiency, and deterministic memory access, is a very
 interesting domain which, thus far, no language manages to handle well, and
 Rust shows immense promise in that.

 Something I really dislike and consider a huge antipattern is the question
 of logical indirection and boilerplate; anything that hinders the
 understanding of the code through unnecessary invocations or synax is a big
 no-no for me (a great example being Java's requirement for type
 declarations everywhere and the disgusting use of accessor methods
 everywhere even when they make no sense).

 Rust is a very lean language and seems to be extremely concise for what
 it's capable of. And the thing is, if a trait has a data dependency rather
 than a behavior (method existence) dependency, then why are we working
 around the data through methods when it just happens to be that what we
 really want is to fetch the data in a struct with no logical
 intermediaries, regardless of whether the compiler turns that into a
 straight memory access?

 The first use case that came to mind was when I was attempting to create a
 business object library that could be used a starting point for forms, data
 persistency, serialization, validation, and the like. I wanted to define,
 for a model, a series of validators that would depend on the struct
 definition; something easy to do with Enums and macros. However when it
 came to validation, i wanted to store certain conditions in a data
 structure, such that all models have a validate() method that would query
 the data needed to perform validation.

 The current trait implementation would require me to needlessly define a
 getter/setter for the validation data structure in order to have a trait.
 In reality, i just want to define the trait as a the existence of a certain
 struct member data definition (a corresponding validators data structure),
 with no limits in how I may want to access of modify such data.

 The beauty of this would be that i would only need to define said member
 and trait in order to get all the features i could ever want out of a
 validation library, and default methods would take care of the rest,
 whereas as it's now, i would have to define the accessors, or use a macro
 so that any model definition would come with an automatic accessor
 definition. This is not ideal if I have a system with several hundred
 models, which may be trivial in their definition but require a useless
 method definition for each of them.

 And while I think it's great that a macro is capable of that, it seems to
 me that as a language feature it would be substantially more useful.

 Like I said before, I'm just toying around; I have little frame of
 reference as to whether there are hidden downsides to such a feature. I
 just wanted to know what the community thinks about this.

 Thanks
 Enviado desde mi BlackBerry de Movistar (http://www.movistar.com.ar)
 --
 *From: * Felix S. Klock II pnkfe...@mozilla.com
 *Date: *Fri, 20 Sep 2013 13:41:02 +0200
 *To: *Andres Osinskiandres.osin...@gmail.com
 *Cc: *rust-dev@mozilla.orgrust-dev@mozilla.org
 *Subject: *Re: [rust-dev] Struct members in trait definitions

 Andres (cc'ing rust-dev)-

 An initial question, since I'm not clear on one thing:

 What is your goal in proposing this change?

 That is, is your primary concern that you dislike writing either method
 invocations or method definitions?  Or are you concerned about the ability
 of the compiler to optimize the generated code if one uses methods instead
 of struct fields?

 

 Justifications for why traits

Re: [rust-dev] Struct members in trait definitions

2013-09-20 Thread Brendan Zabarauskas
Adding struct members in traits would be… weird. Where would those members be 
stored when passing things around by value?

This sounds like something for properties. But as Nikko says it is not a 
planned feature at the moment – there is enough on the table for 1.0 as it is. 
I'm sure they would be a controversial proposal too (although I think they 
would be nice).

~Brendan

On 20/09/2013, at 9:02 PM, Andres Osinski andres.osin...@gmail.com wrote:

 Hi all, I have a question which I'm sure must have already been discussed and 
 dealt with, but I wanted to understand the design rationale:
 
 A lot of trait-level functionality would be enhanced if a trait could specify 
 members to be included in the struct which implements the trait. This can be 
 solved in practice by wrapping member access in accessor methods, but I fail 
 to see why that would be preferable.
 
 The reason I'm asking is because I'm trying to design data structures which 
 contain a couple of arrays, and I wanted to define the trait by not only a 
 set of supported operations but by the existence of both arrays so that a 
 default method could deal with any struct which implements the trait, instead 
 of having to define for every struct an accessor method for each structure 
 and then have to call the accessors in the trait to do anything.
 
 Thanks
 
 -- 
 Andrés Osinski
 http://www.andresosinski.com.ar/
 ___
 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] Struct members in trait definitions

2013-09-20 Thread Oren Ben-Kiki
How about allowing anonymous fields, like go does? It seems to provide most
of the benefits at very little language complexity cost.
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Struct members in trait definitions

2013-09-20 Thread Andres Osinski
When I mention struct members I'm saying that in order for a struct to
satisfy trait properties (explicitly conforming to the interface, not
implicitly like Go), the struct must have implemented the functions for the
trait and also contain the required members.

Looking at a few more examples, I think what I'm looking for here is a
mixin for composition ( inheritance would not be too relevant here) a la
Scala's, or a purpose-made Python asbtract class that defines class members
and methods pertaining only to those members.


On Fri, Sep 20, 2013 at 2:55 PM, Oren Ben-Kiki o...@ben-kiki.org wrote:

 How about allowing anonymous fields, like go does? It seems to provide
 most of the benefits at very little language complexity cost.




-- 
Andrés Osinski
http://www.andresosinski.com.ar/
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Struct members in trait definitions

2013-09-20 Thread Tobias Müller
Andres Osinski andres.osin...@gmail.com
wrote:
 Hi all, I have a question which I'm sure must have already been discussed
 and dealt with, but I wanted to understand the design rationale:
 
 A lot of trait-level functionality would be enhanced if a trait could
 specify members to be included in the struct which implements the trait.
 This can be solved in practice by wrapping member access in accessor
 methods, but I fail to see why that would be preferable.

IMO this would completely defeat the  advantage of traits over inheritance
based interfaces.

The beauty of traits is, that the trait and the type are separated, only
connected by the implementation:
- You can add an implementation for your custom trait to any existing type.
- You can add an implementation for any existing trait to your custom type.

Now if you add a fields specification to the trait, the former isn't true
anymore. The type has now a dependency on the trait since it must at least
contain a field of a given type, if not even with a given name.

If you the concrete type is under your control, this is obviously not a
problem, as it is the case with inheritance based interfaces. But you
cannot simply assume that for every use case.

Tobi

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


Re: [rust-dev] Struct members in trait definitions

2013-09-20 Thread Oren Ben-Kiki
AFAIK the go solution walks a thin line here. An anonymous field means one
can directly access any subfield, and also that the container has all the
included struct traits - as implemented by the included struct. It is also
possible to override the implementation.

This is different from what was asked which was the opposite - the go way
is the struct implies the trait, what was asked was that the trait implies
the struct.

I think the go approach makes a lot of sense - I found it to need very
useful and simple (e.g. ambiguities are not allowed). The go docs have a
better description - give it a look...
On Sep 20, 2013 11:30 PM, Tobias Müller trop...@bluewin.ch wrote:

 Andres Osinski andres.osin...@gmail.com
 wrote:
  Hi all, I have a question which I'm sure must have already been discussed
  and dealt with, but I wanted to understand the design rationale:
 
  A lot of trait-level functionality would be enhanced if a trait could
  specify members to be included in the struct which implements the trait.
  This can be solved in practice by wrapping member access in accessor
  methods, but I fail to see why that would be preferable.

 IMO this would completely defeat the  advantage of traits over inheritance
 based interfaces.

 The beauty of traits is, that the trait and the type are separated, only
 connected by the implementation:
 - You can add an implementation for your custom trait to any existing type.
 - You can add an implementation for any existing trait to your custom type.

 Now if you add a fields specification to the trait, the former isn't true
 anymore. The type has now a dependency on the trait since it must at least
 contain a field of a given type, if not even with a given name.

 If you the concrete type is under your control, this is obviously not a
 problem, as it is the case with inheritance based interfaces. But you
 cannot simply assume that for every use case.

 Tobi

 ___
 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