Hello,
On Mon, Oct 8, 2012 at 3:19 PM, Eddy Cizeron <[email protected]> wrote: > Hi everyone > > 2012/10/6 Tim Chevalier <[email protected]> >> Traits and impls in Rust are based on type classes, which originated >> in Haskell. You may find it interesting to read about type classes: >> "Type classes: exploring the design space" by Simon Peyton Jones, Mark >> Jones, and Erik Meijer, is a good start: >> http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.48.5674 > > Thank you for the reference Tim. I'm not really fluent in Haskell but I > think I understand the concepts and apparently multi-parameter type classes > are very close to what I would expect from Rust interfaces/traits. > > 2012/10/6 Tim Chevalier <[email protected]> >> ("Interfaces" have been renamed to "traits" in the soon-to-be-released >> Rust 0.4 release, by the way; it looks like you may be looking at the docs >> from Rust 0.3.) > > Right, I was looking at docs 0.3 but I could not find any newer > documentation. > > 2012/10/6 Sebastian Sylvan <[email protected]> >> I strongly feel that the focus on inheritance in (recent) OOP is a >> huge mistake. OOP was originally more about the metaphor of messages >> and objects than inheritance. Inheritance leads to so many bugs and >> [...] >> Interfaces (even trees of them) are great, just not inheritance of >> implementation. > > 2012/10/6 Daniel Patterson <[email protected]> >> Inheritance seems to solve a different problem - how to write code that >> targets many different types of objects in a simple way. But inheritance >> isn't really needed there, >> [...] >> Of course, that's just my opinion (and, I am more of a functional >> programmer than an OO programmer). > > Sorry I have not made myself clear enough. My point is absolulety not say > that inheritance is a good/bad/required/unnecessary feature. My point is > that if you're not using it (or at least if you're not using dynamic > linkage), I cannot see where or why OOP concepts and syntax are relevant > anymore. (But apparently there are some attempts to use dynamic linkage with > interfaces and I didn't know that). > > Your remark about the metaphor is indeed interesting. Actually I cannot > remember where I had read someone complaining about that. This guy said "I > know what is sending messages, and it's certainly not that". His point was > precisely that this metaphor fails because the notion of message implies > asynchrony (I'm not paralyzed when I'm waiting for a response to a mail) and > this is certainly not the intended meaning in OOP. I agree with this view. > > You both focus on the functional inspiration for Rust. This is good news. > It's obvious to me the functional paradigm has deep roots in the math world. > Which is also good news. But in mathematics nobody wonder if such-and-such a > function is owned by one of its argument and which one. Or to say it a la > OOP, if this function is a method of one of its argument. This bias, when > taken to the extreme, has generaly lead some languages to syntactical > "oddities" (some of my neurones would say "monstrosities") like: "x = (PI / > 4).sin;" or "y = 2.'+'(7);" Can anyone explain me why it makes more sense to > think about this addition as a message sent to 2 with parameter 7? It does not make sense. Think about a general add interface. It's type could be like the following (I am still fuzzy on rust's memory location/lifetime type modifiers, so here I assume T is somehow copy-by-value): add( a: T, b: T ) -> T There's nothing special about a compared to b, and also the return type is the same type. If we could generalize this to an interface called "Addable", then a single implementation would exist for a given type, and there'd be nothing special about which argument position(s) have that type. I seem to recall there was some constraint on rust traits which says the parameterized type must appear in a particular position. Is this still true? Is this a constraint that will be lifted in the future? I hope so, because then interfaces can be much more expressive, such as as "JSON-compatible interface": to_json( x: T ) -> ~str; from_json( text: ~str ) -> Option<T>; This seems like a coherent and useful kind of interface. > What does > this metaphor makes clearer ? One may justifiably argue that mathematical > concepts are different from everyday life ones. But I don't think > 'file.moveTo(directory)' or 'directory.move(file)' carries better meaning > than 'moveTo(directory, file)'. If you want to express more efficiently the > purpose of every argument of a function, named arguments are a far better > idea. > > 2012/10/6 Daniel Patterson <[email protected]> >> I think saying that objects are only useful in so far as inheritance >> exists is strange. The point of objects, as I've understood them, is to >> provide some form of encapsulation - to be able to give limited access >> to certain data so that you can maintain invariants on the data that are >> not expressible with a type system (if such a system even exists). >> Objects can exist without inheritance (and are still useful). > > This is a question of terminology. Unfortunately in computer science and > programming, definitions are generally fuzzy or/and depend on the author. I > keep the word "encapsulation" for the idea of grouping together data and > functions and personally prefer the expression "data hidding" or "data > accessibility" for the feature you're describing. And the fact is this too > concepts are certainly not as strongly linked as you might think. You can > perfectly imagine a system where data accessibility does not apply to the > exterior of a class but to the exterior of other bundles (modules, packages, > etc). This way you can craft more precisely the accessibility of multiple > types in multiple functions. Classes are not needed for this. The common OO idiom you allude to specifically ties interface, data accessibility, and namespace together. That's a particular choice. You are right that these can be decoupled. I'm personally a fan of "fewer ways to do it; less flexibility", so I like nailing down a namespace and data accessibility for example. Or for another example, I'm a fan of "the namespace must correlate directly to the file path in some manner" versus having those decoupled. But that's just me, and I see more flexibility in rust. I'm not certain but I think data accessibility may be tied to namespaces (which are decoupled from filenames somewhat), as well as types, so maybe it already has the flexibility you describe? > > 2012/10/6 Daniel Patterson <[email protected]> >> As for your example, you can probably define an implementation for pairs, >> i.e.: >> trait ShapeDrawing<(Sf,Sh)> { >> … >> } >> [...] >> It is certainly a different approach, but I think you'll find that it >> isn't less >> powerful (and you may find it to be more flexible - but you may not!). > This is intriguing, but not as general as multi-parameter type classes. Consider an interface for two types, A and B, like this: insert( elem: A, container: B ) -> void; peek( container: B ) -> Option<A>; There's no (A,B) parameter or return type anywhere. That would fit into insert(), but it would not make sense for peek, where I have no B at hand. > Well as long as I have not read some document about traits, any criticism or > any conclusion from me about this would be pointless (I've just noticed > Brian's link to new documentation). But after a first glance it does not > seem to remove the limitations I found in the previous concept of > interfaces. And I'm almost sure that interfaces, as they where explained in > the documentation 0.3 are less powerfull. For the same reason the authors of > the article proposed by Tim explain single-parameter type classes in Haskell > are less powerfull than multi-parameter type classes. I'll come back as soon > as my comprehension of Rust traits will be less superficial (and after a > session of self-flagellation if my premonitions/arguments turn out to be > wrong :-)) > Just to recap, rust traits are constrained to be single-type-parameter. I also read somewhere (but can't find the reference off-hand) that they are also constrained in the position of the type parameter in all methods. Relaxing the latter constraint would allow more expressiveness, and relaxing the former would allow even more. I am not very clear on how feasible or difficult relaxing either would be. I don't see particular design problems with relaxing the positional constraint, but I may be missing other related aspects of rust. There may be some confusing cases or developer confusion around multi-parameter traits. > 2012/10/6 Brian Anderson <[email protected]> >> Additionally your concern about resources and classes not needing to be >> interrelated >> is spot on, and that issue will be resolved. In 0.4 still structs are the >> only type >> that contain destructors, but the intent is to make destructors just an >> implementation >> of `trait Drop` (or `Finalize` maybe). > > Precisely, I'm not sure that the fact destructors are turned into methods is > good news to me. > > Thank you for this stimulating discussion and references > > -- > Eddy Cizeron > Regards, Nathan Wilcox > > _______________________________________________ > Rust-dev mailing list > [email protected] > https://mail.mozilla.org/listinfo/rust-dev > _______________________________________________ Rust-dev mailing list [email protected] https://mail.mozilla.org/listinfo/rust-dev
