[rust-dev] Reminder: Bay Area meetup this Thursday

2014-03-11 Thread Erick Tryzelaar
Hey rusties!

I just wanted to remind everyone we have another meetup this Thursday, 7PM
at Mozilla SF, where Julia Evans will talk about the OS she built with
Rust. Here's the link to sign up:

http://www.meetup.com/Rust-Bay-Area/events/166034142/

I hope you can make it!
Erick
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


[rust-dev] Virtual fn is a bad idea

2014-03-11 Thread Bill Myers
I see a proposal to add virtual struct and virtual fn in the workweek 
meeting notes, which appears to add an exact copy of Java's OO system to Rust.

I think however that this should be carefully considered, and preferably not 
added at all (or failing that, feature gated and discouraged).

The core problem of virtual functions (shared by Java's classes, etc.) is 
that rather than exposing a single public API, they expose two: the API formed 
by public functions, and the API formed by virtual functions to be overridden 
by subclasses, and the second API is exposed in an inflexible and unclean way.

A much better way of allowing to override part of a struct's behavior is by 
defining a trait with the overridable functionality, and allowing to pass in an 
implementation of the trait to the base class, while also providing a default 
implementation if desired.

Another way is to have the subclass implement all the traits that the base 
class implements, include a field of the base class type, and then direct 
all non-overridden functionality to the base class (here syntax sugar can be 
easily added to eliminate the boilerplate, by automatically implementing all 
non-implemented trait functions by calling the same function on the base class 
field).

These approaches can be combined, as the first approach allows to change the 
inside behavior of the base class, while the second one allows to put extra 
behavior around the base class code.

The fact that OO using virtual functions (as opposed to traits) is a bad design 
is one of the crucial steps forward of the design of languages like Go and 
current Rust compared to earlier OO languages, and Rust should not go backwards 
on this.

Here is a list of issues with virtual functions:

1. Incentive for bad documentation

Usually there is no documentation for how virtual functions are supposed to be 
overridden, and it as awkward to add it since it needs to be mixed with the 
documentation on how to use the struct

2. Mishmashing multiple unrelated APIs

With traits, you could pass in multiple objects to implement separate sets of 
overridable functionality; with virtual structs you need to mishmash all those 
interfaces into a single set of virtual functions, all sharing data even when 
not appropriate.

3. No encapsulation

Private data for virtual function implementations is accessible to all other 
functions in the struct.

This means for instance that if you have a virtual function called 
compute_foo() that is implemented by default by reading a foo field in the 
base class, then all other parts of the base class can access foo too.

If anything else accesses mistakenly foo directly, which it can, then 
overriding compute_foo() will not work as expected.

If compute_foo() were provided by an external trait implementation, then foo 
would be private and inaccessible, eliminating the problem.

4. Data for overridden implementations left there in a zombie state.

In the above example, if you override compute_foo(), the foo variable in the 
base class will no longer be used, yet it will still be present in the type and 
allocated in memory.

5. Inability to statically dispatch

With a trait implementation, you can pass the concrete type as a generic 
parameter, allowing static dispatch.

If you instead call an overridable virtual function, then you can't dispatch 
that statically at all (unless you add cumbersome syntax for that).

6. Adds a ton of unnecessary complexity to the language 
  
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Virtual fn is a bad idea

2014-03-11 Thread Maciej Piechotka
On Tue, 2014-03-11 at 19:09 +, Bill Myers wrote:
 I see a proposal to add virtual struct and virtual fn in the workweek 
 meeting notes, which appears to add an exact copy of Java's OO system to Rust.
 
 I think however that this should be carefully considered, and preferably not 
 added at all (or failing that, feature gated and discouraged).
 
 The core problem of virtual functions (shared by Java's classes, etc.) is 
 that rather than exposing a single public API, they expose two: the API 
 formed by public functions, and the API formed by virtual functions to be 
 overridden by subclasses, and the second API is exposed in an inflexible and 
 unclean way.
 
 A much better way of allowing to override part of a struct's behavior is by 
 defining a trait with the overridable functionality, and allowing to pass in 
 an implementation of the trait to the base class, while also providing a 
 default implementation if desired.
 
 Another way is to have the subclass implement all the traits that the base 
 class implements, include a field of the base class type, and then direct 
 all non-overridden functionality to the base class (here syntax sugar can 
 be easily added to eliminate the boilerplate, by automatically implementing 
 all non-implemented trait functions by calling the same function on the base 
 class field).
 
 These approaches can be combined, as the first approach allows to change the 
 inside behavior of the base class, while the second one allows to put extra 
 behavior around the base class code.
 
 The fact that OO using virtual functions (as opposed to traits) is a bad 
 design is one of the crucial steps forward of the design of languages like Go 
 and current Rust compared to earlier OO languages, and Rust should not go 
 backwards on this.
 
 Here is a list of issues with virtual functions:
 
 1. Incentive for bad documentation
 
 Usually there is no documentation for how virtual functions are supposed to 
 be overridden, and it as awkward to add it since it needs to be mixed with 
 the documentation on how to use the struct
 
 2. Mishmashing multiple unrelated APIs
 
 With traits, you could pass in multiple objects to implement separate sets of 
 overridable functionality; with virtual structs you need to mishmash all 
 those interfaces into a single set of virtual functions, all sharing data 
 even when not appropriate.
 
 3. No encapsulation
 
 Private data for virtual function implementations is accessible to all other 
 functions in the struct.
 
 This means for instance that if you have a virtual function called 
 compute_foo() that is implemented by default by reading a foo field in 
 the base class, then all other parts of the base class can access foo too.
 
 If anything else accesses mistakenly foo directly, which it can, then 
 overriding compute_foo() will not work as expected.
 
 If compute_foo() were provided by an external trait implementation, then 
 foo would be private and inaccessible, eliminating the problem.
 
 4. Data for overridden implementations left there in a zombie state.
 
 In the above example, if you override compute_foo(), the foo variable in 
 the base class will no longer be used, yet it will still be present in the 
 type and allocated in memory.
 
 5. Inability to statically dispatch
 
 With a trait implementation, you can pass the concrete type as a generic 
 parameter, allowing static dispatch.
 
 If you instead call an overridable virtual function, then you can't dispatch 
 that statically at all (unless you add cumbersome syntax for that).
 
 6. Adds a ton of unnecessary complexity to the language   
   
 

7. Harder interoperability. For example I've encountered at least 2
Float interfaces for Java from 2 different libraries (both trying to
abstract over Float) which I need to use in one of my projects (long
story) - either one needed to have an adapter or there was a need to
convert float to float. In total there were 3 32-bit floats
representation in single function counting also the float. With traits
they would just add implementation to Java's float.

Best regards


signature.asc
Description: This is a digitally signed message part
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Virtual fn is a bad idea

2014-03-11 Thread Maciej Piechotka
On Tue, 2014-03-11 at 14:37 -0500, Evan G wrote:
 ... Why didn't they just extend Number? (Or, at worst, that was a bad
 design decision on Oracle's part, by choosing to make the Float class
 final)
 
 Either way, I don't see how that's a fault of the language.
 
 

I don't remember - maybe they had, but it wouldn't solved the problem.
And Float is final - and even if it hadn't been it wouldn't solve the
problem at all. Assume that Float is not final and they did extended
Number.

 - Platform P provides interface PI and object PO (say Number and Float)
 - Component A provided and required interface AI and object AO
extending PO and implementing AI and PI
 - Component B provided and required interface BI and object AO
extending PO and implementing BI and PI

Now you cannot pass object AO to component B as it requires BI. You need
either:
 - Provide adapter from AI to BI (or other way round) which implements
AI, BI and PI
 - Each time convert from AO to BO when you transfer between interfaces
In proposed interface there would be only second option due to single
inheritance.

On the other hand with traits:
 - Platform P provides interface PI and object PO
 - Component A provides and requires interface AI and implements AI for
PO (there is no need for adding AI as PO is 'open' for trait
implementation)
 - Component B provides and requires interface BI and implements BI for
PO (there is no need for adding BI as PO is 'open' for trait
implementation)
The user needs to do:
 - Nothing. Everything works out of the box

And before you ask - component A and B were 2 different libraries for
which the Oracle interfaces were insufficient.

Best regards

 
 On Tue, Mar 11, 2014 at 2:35 PM, Maciej Piechotka
 uzytkown...@gmail.com wrote:
 On Tue, 2014-03-11 at 19:09 +, Bill Myers wrote:
  I see a proposal to add virtual struct and virtual fn in
 the workweek meeting notes, which appears to add an exact copy
 of Java's OO system to Rust.
 
  I think however that this should be carefully considered,
 and preferably not added at all (or failing that, feature
 gated and discouraged).
 
  The core problem of virtual functions (shared by Java's
 classes, etc.) is that rather than exposing a single public
 API, they expose two: the API formed by public functions, and
 the API formed by virtual functions to be overridden by
 subclasses, and the second API is exposed in an inflexible and
 unclean way.
 
  A much better way of allowing to override part of a struct's
 behavior is by defining a trait with the overridable
 functionality, and allowing to pass in an implementation of
 the trait to the base class, while also providing a default
 implementation if desired.
 
  Another way is to have the subclass implement all the
 traits that the base class implements, include a field of
 the base class type, and then direct all non-overridden
 functionality to the base class (here syntax sugar can be
 easily added to eliminate the boilerplate, by automatically
 implementing all non-implemented trait functions by calling
 the same function on the base class field).
 
  These approaches can be combined, as the first approach
 allows to change the inside behavior of the base class,
 while the second one allows to put extra behavior around the
 base class code.
 
  The fact that OO using virtual functions (as opposed to
 traits) is a bad design is one of the crucial steps forward of
 the design of languages like Go and current Rust compared to
 earlier OO languages, and Rust should not go backwards on
 this.
 
  Here is a list of issues with virtual functions:
 
  1. Incentive for bad documentation
 
  Usually there is no documentation for how virtual functions
 are supposed to be overridden, and it as awkward to add it
 since it needs to be mixed with the documentation on how to
 use the struct
 
  2. Mishmashing multiple unrelated APIs
 
  With traits, you could pass in multiple objects to implement
 separate sets of overridable functionality; with virtual
 structs you need to mishmash all those interfaces into a
 single set of virtual functions, all sharing data even when
 not appropriate.
 
  3. No encapsulation
 
  Private data for virtual function implementations is
 accessible to all other functions in the struct.
 
  This means for instance that if you have a virtual function
 called compute_foo() that is implemented by default by
 reading a foo field in the base class, then all other parts
 of the base 

Re: [rust-dev] Virtual fn is a bad idea

2014-03-11 Thread Clark Gaebel
I like virtual functions. They're not for everything, and stylistically,
traits are almost always a better solution. However, they can be nice to
reduce code bloat. See how the LLVM devs managed to share a good amount of
code for their SmallVector class thanks to the magic of virtual functions:

http://llvm.org/docs/doxygen/html/classllvm_1_1SmallVector.html

Not sure if it deserves a whole keyword, but a way to do this efficiently
would be nice.

  - Clark


On Tue, Mar 11, 2014 at 3:51 PM, Maciej Piechotka uzytkown...@gmail.comwrote:

 On Tue, 2014-03-11 at 14:37 -0500, Evan G wrote:
  ... Why didn't they just extend Number? (Or, at worst, that was a bad
  design decision on Oracle's part, by choosing to make the Float class
  final)
 
  Either way, I don't see how that's a fault of the language.
 
 

 I don't remember - maybe they had, but it wouldn't solved the problem.
 And Float is final - and even if it hadn't been it wouldn't solve the
 problem at all. Assume that Float is not final and they did extended
 Number.

  - Platform P provides interface PI and object PO (say Number and Float)
  - Component A provided and required interface AI and object AO
 extending PO and implementing AI and PI
  - Component B provided and required interface BI and object AO
 extending PO and implementing BI and PI

 Now you cannot pass object AO to component B as it requires BI. You need
 either:
  - Provide adapter from AI to BI (or other way round) which implements
 AI, BI and PI
  - Each time convert from AO to BO when you transfer between interfaces
 In proposed interface there would be only second option due to single
 inheritance.

 On the other hand with traits:
  - Platform P provides interface PI and object PO
  - Component A provides and requires interface AI and implements AI for
 PO (there is no need for adding AI as PO is 'open' for trait
 implementation)
  - Component B provides and requires interface BI and implements BI for
 PO (there is no need for adding BI as PO is 'open' for trait
 implementation)
 The user needs to do:
  - Nothing. Everything works out of the box

 And before you ask - component A and B were 2 different libraries for
 which the Oracle interfaces were insufficient.

 Best regards

 
  On Tue, Mar 11, 2014 at 2:35 PM, Maciej Piechotka
  uzytkown...@gmail.com wrote:
  On Tue, 2014-03-11 at 19:09 +, Bill Myers wrote:
   I see a proposal to add virtual struct and virtual fn in
  the workweek meeting notes, which appears to add an exact copy
  of Java's OO system to Rust.
  
   I think however that this should be carefully considered,
  and preferably not added at all (or failing that, feature
  gated and discouraged).
  
   The core problem of virtual functions (shared by Java's
  classes, etc.) is that rather than exposing a single public
  API, they expose two: the API formed by public functions, and
  the API formed by virtual functions to be overridden by
  subclasses, and the second API is exposed in an inflexible and
  unclean way.
  
   A much better way of allowing to override part of a struct's
  behavior is by defining a trait with the overridable
  functionality, and allowing to pass in an implementation of
  the trait to the base class, while also providing a default
  implementation if desired.
  
   Another way is to have the subclass implement all the
  traits that the base class implements, include a field of
  the base class type, and then direct all non-overridden
  functionality to the base class (here syntax sugar can be
  easily added to eliminate the boilerplate, by automatically
  implementing all non-implemented trait functions by calling
  the same function on the base class field).
  
   These approaches can be combined, as the first approach
  allows to change the inside behavior of the base class,
  while the second one allows to put extra behavior around the
  base class code.
  
   The fact that OO using virtual functions (as opposed to
  traits) is a bad design is one of the crucial steps forward of
  the design of languages like Go and current Rust compared to
  earlier OO languages, and Rust should not go backwards on
  this.
  
   Here is a list of issues with virtual functions:
  
   1. Incentive for bad documentation
  
   Usually there is no documentation for how virtual functions
  are supposed to be overridden, and it as awkward to add it
  since it needs to be mixed with the documentation on how to
  use the struct
  
   2. Mishmashing multiple unrelated APIs
  
   With traits, you could pass in multiple objects to implement
 

Re: [rust-dev] Virtual fn is a bad idea

2014-03-11 Thread Nathan Myers

Bill's posting pleases me more than any other I have seen
so far.

Virtual functions in C++ have been an especially fruitful
source of unfortunate consequences, both in the language and
in users' programs.  It is common in C++ coding guidelines
to forbid public virtual functions, to help avoid mixing
implementation details into a public interface, but that
only mitigates one problem.

Virtual functions have been a source of confusion, too,
because they can be overloaded two different ways, with
identical syntax but radically different semantics. The
compiler cannot help catch mistakes because either might
reasonably have been intended.  This is part of the
rationale for pure virtual classes, just so that
failing to override a virtual as intended through some
trivial error stands some chance of being noticed. For
this reason, some coding guidelines go farther and _only_
allow overriding a parent's pure virtual functions.

Virtual functions are the chief ingredient in what Alex
Stepanov calls O-O gook.  It should surprise no one
that Java and C# went the wrong way by making all member
functions virtual, thereby exposing all programs and all
programmers to these ills all the time.

That said, virtual functions do provide a more structured
form of function pointer, which we do need.  Any such feature
should start with the problems it must solve, and work toward
a defensible design, not by patching traditional O-O method
overriding. Rust has the advantage over early C++ that
lambdas and macros are available as well-defined building
blocks. Ideally, Rust's architectural replacement for
virtual functions would be purely a standard-library
construct, demonstrating greater expressiveness to enable
user code to do what another language is obliged to have
built into its core.

[aside: I don't know of any family connection to Bill.]

Nathan Myers

On 03/11/2014 12:09 PM, Bill Myers wrote:

I see a proposal to add virtual struct and virtual fn in the workweek 
meeting notes, which appears to add an exact copy of Java's OO system to Rust.

I think however that this should be carefully considered, and preferably not 
added at all (or failing that, feature gated and discouraged).

The core problem of virtual functions (shared by Java's classes, etc.) is 
that rather than exposing a single public API, they expose two: the API formed by public 
functions, and the API formed by virtual functions to be overridden by subclasses, and 
the second API is exposed in an inflexible and unclean way.

A much better way of allowing to override part of a struct's behavior is by 
defining a trait with the overridable functionality, and allowing to pass in an 
implementation of the trait to the base class, while also providing a default 
implementation if desired.

Another way is to have the subclass implement all the traits that the base class implements, 
include a field of the base class type, and then direct all non-overridden functionality to the base 
class (here syntax sugar can be easily added to eliminate the boilerplate, by automatically implementing all 
non-implemented trait functions by calling the same function on the base class field).

These approaches can be combined, as the first approach allows to change the inside 
behavior of the base class, while the second one allows to put extra behavior around 
the base class code.

The fact that OO using virtual functions (as opposed to traits) is a bad design 
is one of the crucial steps forward of the design of languages like Go and 
current Rust compared to earlier OO languages, and Rust should not go backwards 
on this.

Here is a list of issues with virtual functions:

1. Incentive for bad documentation

Usually there is no documentation for how virtual functions are supposed to be 
overridden, and it as awkward to add it since it needs to be mixed with the 
documentation on how to use the struct

2. Mishmashing multiple unrelated APIs

With traits, you could pass in multiple objects to implement separate sets of 
overridable functionality; with virtual structs you need to mishmash all those 
interfaces into a single set of virtual functions, all sharing data even when 
not appropriate.

3. No encapsulation

Private data for virtual function implementations is accessible to all other 
functions in the struct.

This means for instance that if you have a virtual function called compute_foo() that is 
implemented by default by reading a foo field in the base class, then all other parts of the base 
class can access foo too.

If anything else accesses mistakenly foo directly, which it can, then overriding 
compute_foo() will not work as expected.

If compute_foo() were provided by an external trait implementation, then foo 
would be private and inaccessible, eliminating the problem.

4. Data for overridden implementations left there in a zombie state.

In the above example, if you override compute_foo(), the foo variable in the 
base class will no longer be used, yet it will 

Re: [rust-dev] Virtual fn is a bad idea

2014-03-11 Thread Maciej Piechotka
See for example
http://jscience.org/api/org/jscience/mathematics/structure/Field.html
and
http://jscience.org/api/org/jscience/mathematics/number/Float64.html.
Now you cannot just use Double as to use
http://jscience.org/api/org/jscience/mathematics/function/Polynomial.html you 
need to have a type that implements Ring. Then you needed to perform a few 
operations on polynomial and feed it to different library which had it own 
interfaces for float. You cannot just add static method as you're not an user 
of it - the other component is so using interface to abstract numeric 
operations, so function is not a viable workaround (BTW - I don't remember if 
jscience is one of libraries which I've used - they just appeared as one of 
first in Google).

And sure, in ideal world all packages would have one interface but it
wasn't something I controlled or anyone remotely connected with project.
And I wasn't somehow inclined to rewrite 2 libraries.

Another example would be interface which could be implemented in terms
of another. So interface A is subset of B. You could make A a
subinterface of B but it isn't and it is not something you control (for
example first project don't want to depend on second, or does not know
of its existence, or the work is in progress but it hasn't been done
yet).

If you happen to have control over whole system you're in much easier
situation as you can make a single sane hierarchy. If you don't and you
try to pull a few external libraries to work together as a small
component of a larger project it's much more of a problem.

Best regards

On Tue, 2014-03-11 at 15:00 -0500, Evan G wrote:
 I still don't a hundred percent understand... what interface could
 there be that doesn't require the object to store the state necessary
 to implement it? I mean, anything else is really just a function,
 instead of 60.days_after(date) use days_after(60, date).
 
 
 On Tue, Mar 11, 2014 at 2:51 PM, Maciej Piechotka
 uzytkown...@gmail.com wrote:
 On Tue, 2014-03-11 at 14:37 -0500, Evan G wrote:
  ... Why didn't they just extend Number? (Or, at worst, that
 was a bad
  design decision on Oracle's part, by choosing to make the
 Float class
  final)
 
  Either way, I don't see how that's a fault of the language.
 
 
 
 
 I don't remember - maybe they had, but it wouldn't solved the
 problem.
 And Float is final - and even if it hadn't been it wouldn't
 solve the
 problem at all. Assume that Float is not final and they did
 extended
 Number.
 
  - Platform P provides interface PI and object PO (say Number
 and Float)
  - Component A provided and required interface AI and object
 AO
 extending PO and implementing AI and PI
  - Component B provided and required interface BI and object
 AO
 extending PO and implementing BI and PI
 
 Now you cannot pass object AO to component B as it requires
 BI. You need
 either:
  - Provide adapter from AI to BI (or other way round) which
 implements
 AI, BI and PI
  - Each time convert from AO to BO when you transfer between
 interfaces
 In proposed interface there would be only second option due to
 single
 inheritance.
 
 On the other hand with traits:
  - Platform P provides interface PI and object PO
  - Component A provides and requires interface AI and
 implements AI for
 PO (there is no need for adding AI as PO is 'open' for trait
 implementation)
  - Component B provides and requires interface BI and
 implements BI for
 PO (there is no need for adding BI as PO is 'open' for trait
 implementation)
 The user needs to do:
  - Nothing. Everything works out of the box
 
 And before you ask - component A and B were 2 different
 libraries for
 which the Oracle interfaces were insufficient.
 
 Best regards
 
 
  On Tue, Mar 11, 2014 at 2:35 PM, Maciej Piechotka
  uzytkown...@gmail.com wrote:
  On Tue, 2014-03-11 at 19:09 +, Bill Myers wrote:
   I see a proposal to add virtual struct and
 virtual fn in
  the workweek meeting notes, which appears to add an
 exact copy
  of Java's OO system to Rust.
  
   I think however that this should be carefully
 considered,
  and preferably not added at all (or failing that,
 feature
  gated and discouraged).
  
   The core problem of virtual functions (shared by
 Java's
  classes, etc.) is that rather than exposing a 

Re: [rust-dev] Virtual fn is a bad idea

2014-03-11 Thread Daniel Micay
On 11/03/14 03:59 PM, Clark Gaebel wrote:
 I like virtual functions. They're not for everything, and stylistically,
 traits are almost always a better solution. However, they can be nice to
 reduce code bloat. See how the LLVM devs managed to share a good amount
 of code for their SmallVector class thanks to the magic of virtual
 functions:
 
 http://llvm.org/docs/doxygen/html/classllvm_1_1SmallVector.html
 
 Not sure if it deserves a whole keyword, but a way to do this
 efficiently would be nice.
 
   - Clark

Traits already provide a choice between monomorphization and virtual
function tables. I hope that the existing system can be extended in an
orthogonal way. I would be very disappointed if Rust ended up like C++,
where you have two almost completely exclusive systems.

I think object inheritance is a very counter-intuitive concept, without
much basis in either the real world or theory. Traits could be extended
to include non-virtual fields, without us having the concept of base
classes.

Existing object systems like COM, DOM and gobject are worth looking at,
but Rust shouldn't bend over backwards to support them. They're legacy
technologies and while interacting with them is important, I don't think
it should result in any extra complexity being added to Rust.



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


Re: [rust-dev] Virtual fn is a bad idea

2014-03-11 Thread Patrick Walton

On 3/11/14 1:42 PM, Daniel Micay wrote:

Existing object systems like COM, DOM and gobject are worth looking at,
but Rust shouldn't bend over backwards to support them. They're legacy
technologies and while interacting with them is important, I don't think
it should result in any extra complexity being added to Rust.


We have to support the technologies that are in use in a pleasant way, 
or else Rust will not be practical. Regardless of your feelings about 
existing OO systems, Rust has to support them well.


So far nobody in this thread has demonstrated an understanding of the 
constraints here. Traits are simply not sufficient to model the DOM, for 
example.


Patrick

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


Re: [rust-dev] Virtual fn is a bad idea

2014-03-11 Thread Patrick Walton

On 3/11/14 12:09 PM, Bill Myers wrote:

I see a proposal to add virtual struct and virtual fn in the
workweek meeting notes, which appears to add an exact copy of Java's
OO system to Rust.

I think however that this should be carefully considered, and
preferably not added at all (or failing that, feature gated and
discouraged).

The core problem of virtual functions (shared by Java's classes,
etc.) is that rather than exposing a single public API, they expose
two: the API formed by public functions, and the API formed by
virtual functions to be overridden by subclasses, and the second API
is exposed in an inflexible and unclean way.

A much better way of allowing to override part of a struct's behavior
is by defining a trait with the overridable functionality, and
allowing to pass in an implementation of the trait to the base class,
while also providing a default implementation if desired.


This approach is not efficient enough for use cases like the DOM (two 
words on each pointer instead of one, for example), and doesn't allow 
for nonvirtual access of fields through a trait object.


Patrick

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


Re: [rust-dev] Virtual fn is a bad idea

2014-03-11 Thread Brian Anderson
The downsides you list are all more or less applicable to this design, 
indeed. We are seeing real requirements in real code that indicates that 
the current abstraction facilities provided by Rust are efficient enough 
for certain demanding use cases (the DOM in particular).


Here are the identified requirements:

tree of types (single inheritance)
downcasting
thin pointers
cheap field access
easy upcasting

The big problem that putting virtual methods on structs solves is 
removing the need for fat pointers to objects - with a lot of trait 
objects this can involve many duplicated words.


Fortunately, this feature is independent of others and we can feature 
gate it until it's right. So as with many aspects of Rust's design we 
are going to iterate on it using *real code* until it's right, and in 
the end Rust is going to be able to to provide the zero-cost 
abstractions necessary to write very high performance code.


Regards,
Brian


On 03/11/2014 12:09 PM, Bill Myers wrote:

I see a proposal to add virtual struct and virtual fn in the workweek 
meeting notes, which appears to add an exact copy of Java's OO system to Rust.

I think however that this should be carefully considered, and preferably not 
added at all (or failing that, feature gated and discouraged).

The core problem of virtual functions (shared by Java's classes, etc.) is 
that rather than exposing a single public API, they expose two: the API formed by public 
functions, and the API formed by virtual functions to be overridden by subclasses, and 
the second API is exposed in an inflexible and unclean way.

A much better way of allowing to override part of a struct's behavior is by 
defining a trait with the overridable functionality, and allowing to pass in an 
implementation of the trait to the base class, while also providing a default 
implementation if desired.

Another way is to have the subclass implement all the traits that the base class implements, 
include a field of the base class type, and then direct all non-overridden functionality to the base 
class (here syntax sugar can be easily added to eliminate the boilerplate, by automatically implementing all 
non-implemented trait functions by calling the same function on the base class field).

These approaches can be combined, as the first approach allows to change the inside 
behavior of the base class, while the second one allows to put extra behavior around 
the base class code.

The fact that OO using virtual functions (as opposed to traits) is a bad design 
is one of the crucial steps forward of the design of languages like Go and 
current Rust compared to earlier OO languages, and Rust should not go backwards 
on this.

Here is a list of issues with virtual functions:

1. Incentive for bad documentation

Usually there is no documentation for how virtual functions are supposed to be 
overridden, and it as awkward to add it since it needs to be mixed with the 
documentation on how to use the struct

2. Mishmashing multiple unrelated APIs

With traits, you could pass in multiple objects to implement separate sets of 
overridable functionality; with virtual structs you need to mishmash all those 
interfaces into a single set of virtual functions, all sharing data even when 
not appropriate.

3. No encapsulation

Private data for virtual function implementations is accessible to all other 
functions in the struct.

This means for instance that if you have a virtual function called compute_foo() that is 
implemented by default by reading a foo field in the base class, then all other parts of the base 
class can access foo too.

If anything else accesses mistakenly foo directly, which it can, then overriding 
compute_foo() will not work as expected.

If compute_foo() were provided by an external trait implementation, then foo 
would be private and inaccessible, eliminating the problem.

4. Data for overridden implementations left there in a zombie state.

In the above example, if you override compute_foo(), the foo variable in the 
base class will no longer be used, yet it will still be present in the type and allocated 
in memory.

5. Inability to statically dispatch

With a trait implementation, you can pass the concrete type as a generic 
parameter, allowing static dispatch.

If you instead call an overridable virtual function, then you can't dispatch 
that statically at all (unless you add cumbersome syntax for that).

6. Adds a ton of unnecessary complexity to the language 

___
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] Virtual fn is a bad idea

2014-03-11 Thread Patrick Walton

On 3/11/14 1:42 PM, Daniel Micay wrote:

Traits already provide a choice between monomorphization and virtual
function tables. I hope that the existing system can be extended in an
orthogonal way. I would be very disappointed if Rust ended up like C++,
where you have two almost completely exclusive systems.


This is as orthogonal of a way as we could come up with while 
maintaining the constraints of (a) one pointer, not two; (b) statically 
accessed fields at known offsets through trait objects; (c) the prefix 
property for single inheritance.


Patrick

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


Re: [rust-dev] Virtual fn is a bad idea

2014-03-11 Thread SiegeLord

On 03/11/2014 04:52 PM, Brian Anderson wrote:

Fortunately, this feature is independent of others and we can feature
gate it until it's right.
I think that's the crux of the issue some have with this. If a whole 
another, completely disjoint path for inheritance and dynamic 
polymorphism is required for the sake of efficiency, then maybe trait 
objects should go?


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


Re: [rust-dev] Virtual fn is a bad idea

2014-03-11 Thread Maciej Piechotka
On Tue, 2014-03-11 at 13:44 -0700, Patrick Walton wrote:
 On 3/11/14 1:42 PM, Daniel Micay wrote:
  Existing object systems like COM, DOM and gobject are worth looking at,
  but Rust shouldn't bend over backwards to support them. They're legacy
  technologies and while interacting with them is important, I don't think
  it should result in any extra complexity being added to Rust.
 
 We have to support the technologies that are in use in a pleasant way, 
 or else Rust will not be practical. Regardless of your feelings about 
 existing OO systems, Rust has to support them well.
 
 So far nobody in this thread has demonstrated an understanding of the 
 constraints here. Traits are simply not sufficient to model the DOM, for 
 example.
 
 Patrick
 
 

Could you elaborate on DOM? I saw it referred a few times but I haven't
seen any details. I wrote simple bindings to libxml2 dom
(https://github.com/uzytkownik/xml-rs - warning - I wrote it while I was
learning ruby) and I don't think there was a problem of OO - main
problem was mapping libxml memory management and rust's one [I gave up
with namespaces but with native rust dom implementation it would be
possible to solve in nicer way]. Of course - I might've been at too
early stage.

Regarding existing OO systems - Haskell interops with few of them (like
gtk+ for example) using typeclasses without problems I know of. Possible
next stage would be modelling the same hierarchy but since most systems
use multiple inheritance in one form or another it would not help much.

Best regards


signature.asc
Description: This is a digitally signed message part
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Virtual fn is a bad idea

2014-03-11 Thread Patrick Walton

On 3/11/14 2:09 PM, SiegeLord wrote:

On 03/11/2014 04:52 PM, Brian Anderson wrote:

Fortunately, this feature is independent of others and we can feature
gate it until it's right.

I think that's the crux of the issue some have with this. If a whole
another, completely disjoint path for inheritance and dynamic
polymorphism is required for the sake of efficiency, then maybe trait
objects should go?


You still need them for Java `interface`-like functionality, where you 
need to step outside the boundaries of single inheritance. Single 
inheritance alone is too limiting. You can do C++-like multiple 
inheritance in theory with thin pointers, but you lose runtime 
efficiency doing it that way (double dispatch for finding fields) and in 
practice people don't use multiple inheritance with the `virtual` in C++ 
very often for this reason.


Patrick

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


Re: [rust-dev] Virtual fn is a bad idea

2014-03-11 Thread Patrick Walton

On 3/11/14 2:15 PM, Maciej Piechotka wrote:

Could you elaborate on DOM? I saw it referred a few times but I haven't
seen any details. I wrote simple bindings to libxml2 dom
(https://github.com/uzytkownik/xml-rs - warning - I wrote it while I was
learning ruby) and I don't think there was a problem of OO - main
problem was mapping libxml memory management and rust's one [I gave up
with namespaces but with native rust dom implementation it would be
possible to solve in nicer way]. Of course - I might've been at too
early stage.


You need:

1. One-word pointers to each DOM node, not two. Every DOM node has 5 
pointers inside (parent, first child, last child, next sibling, previous 
sibling). Using trait objects would 10 words, not 5 words, and would 
constitute a large memory regression over current browser engines.


2. Access to fields common to every instance of a trait without virtual 
dispatch. Otherwise the browser will be at a significant performance 
disadvantage relative to other engines.


3. Downcasting and upcasting.

4. Inheritance with the prefix property, to allow for (2).

If anyone has alternative proposals that handle these constraints that 
are more orthogonal and are pleasant to use, then I'm happy to hear 
them. I'm just saying that dismissing the feature out of hand is not 
productive.


Patrick

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


Re: [rust-dev] Virtual fn is a bad idea

2014-03-11 Thread Haoyi Li
FWIW, C# requires that you mark overridable functions *virtual*, the
opposite of Java where you need to mark un-overridable functions *final*.
The Scala community is coming to the same conclusion that unrestricted
overriding is pretty dangerous. It's similar to monkey patching, with all
the convenience and danger it provides.


On Tue, Mar 11, 2014 at 2:15 PM, Maciej Piechotka uzytkown...@gmail.comwrote:

 On Tue, 2014-03-11 at 13:44 -0700, Patrick Walton wrote:
  On 3/11/14 1:42 PM, Daniel Micay wrote:
   Existing object systems like COM, DOM and gobject are worth looking at,
   but Rust shouldn't bend over backwards to support them. They're legacy
   technologies and while interacting with them is important, I don't
 think
   it should result in any extra complexity being added to Rust.
 
  We have to support the technologies that are in use in a pleasant way,
  or else Rust will not be practical. Regardless of your feelings about
  existing OO systems, Rust has to support them well.
 
  So far nobody in this thread has demonstrated an understanding of the
  constraints here. Traits are simply not sufficient to model the DOM, for
  example.
 
  Patrick
 
 

 Could you elaborate on DOM? I saw it referred a few times but I haven't
 seen any details. I wrote simple bindings to libxml2 dom
 (https://github.com/uzytkownik/xml-rs - warning - I wrote it while I was
 learning ruby) and I don't think there was a problem of OO - main
 problem was mapping libxml memory management and rust's one [I gave up
 with namespaces but with native rust dom implementation it would be
 possible to solve in nicer way]. Of course - I might've been at too
 early stage.

 Regarding existing OO systems - Haskell interops with few of them (like
 gtk+ for example) using typeclasses without problems I know of. Possible
 next stage would be modelling the same hierarchy but since most systems
 use multiple inheritance in one form or another it would not help much.

 Best regards

 ___
 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] Virtual fn is a bad idea

2014-03-11 Thread Patrick Walton

On 3/11/14 2:19 PM, Haoyi Li wrote:

FWIW, C# requires that you mark overridable functions *virtual*, the
opposite of Java where you need to mark un-overridable functions
*final*. The Scala community is coming to the same conclusion that
unrestricted overriding is pretty dangerous. It's similar to monkey
patching, with all the convenience and danger it provides.


As a systems language we'd definitely need to keep virtual as 
non-default anyhow.


Patrick

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


Re: [rust-dev] Virtual fn is a bad idea

2014-03-11 Thread Oren Ben-Kiki
I can't help but feel that forcing the single inheritance of fast field
access and inheritance of trait functions into one mechanism would be
regrettable.

Would https://github.com/mozilla/rust/issues/10491 address all the
requirements? If not, why?


On Tue, Mar 11, 2014 at 10:52 PM, Brian Anderson bander...@mozilla.comwrote:

 The downsides you list are all more or less applicable to this design,
 indeed. We are seeing real requirements in real code that indicates that
 the current abstraction facilities provided by Rust are efficient enough
 for certain demanding use cases (the DOM in particular).

 Here are the identified requirements:

 tree of types (single inheritance)
 downcasting
 thin pointers
 cheap field access
 easy upcasting

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


Re: [rust-dev] Virtual fn is a bad idea

2014-03-11 Thread Vadim Chugunov
By the way, I didn't see any discussion of the HasPrefix/Coercible
proposalhttps://github.com/mozilla/rust/issues/9912#issuecomment-36073562in
the workweek minutes.  Did anybody bring it up at all?

Vadim


On Tue, Mar 11, 2014 at 2:30 PM, Oren Ben-Kiki o...@ben-kiki.org wrote:

 I can't help but feel that forcing the single inheritance of fast field
 access and inheritance of trait functions into one mechanism would be
 regrettable.

 Would https://github.com/mozilla/rust/issues/10491 address all the
 requirements? If not, why?


 On Tue, Mar 11, 2014 at 10:52 PM, Brian Anderson bander...@mozilla.comwrote:

 The downsides you list are all more or less applicable to this design,
 indeed. We are seeing real requirements in real code that indicates that
 the current abstraction facilities provided by Rust are efficient enough
 for certain demanding use cases (the DOM in particular).

 Here are the identified requirements:

 tree of types (single inheritance)
 downcasting
 thin pointers
 cheap field access
 easy upcasting


 ___
 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] Virtual fn is a bad idea

2014-03-11 Thread Erick Tryzelaar
I've actually come around and now I'm starting to actually like this
virtual struct proposal, although not necessarily the example syntax (yay
bikeshed!). What brought me around is that if you squint your eyes a bit,
the example was mashing together struct inheritance and virtual methods
into one syntax. If we decouple the two we can get a more rust-y syntax (to
me) if we reify the anonymous trait into something that can be implemented
by substructures:

```
// Unsized structs are unsized but *can't* end with an unsized field (so
they can be extended)
unsized struct Base { id: int }
unsized struct Foo: Base { }
struct Bar: Foo  { }

impl Base {
fn a(); // impls can now have unimplemented methods
fn b() { }
}

impl Base for Foo {
fn a() { }
}

impl Foo {
fn c() { }
}

impl Base for Bar {}
impl Foo for Bar {}

fn do_somethingT: Base(t: Base) {
println!({}, t.id); // compiler can figure out the exact field offset
because `Base` is a struct trait
}

fn main() {
let bases = ~[
~Foo { id: 1 } as ~Base, // compiler uses the more optimal
`~(*vtable, obj)` because `Base` is a struct trait
~Bar { id: 2 } as ~Base,
];
for base in bases.iter() {
do_something(base);
}
}
```

One interesting thing we could do with this is allow named traits to also
derive from struct traits. This could allow parallel virtual method trees:

```
unsized struct Base { id: int }
unsized struct Foo: Base { }
struct Bar: Foo  { }

trait BaseTrait1: Base {
fn foo(self) {
println!({}, self.id); // exact offset because id comes from a
struct trait
}
}
impl BaseTrait1 for Base { }
impl BaseTrait1 for Foo { }
impl BaseTrait1 for Bar { }

trait BaseTrait2: Base {
fn bar(self) {
println!({}, self.id); // exact offset because id comes from a
struct trait
}
}
impl BaseTrait2 for Base { }
impl BaseTrait2 for Foo { }
impl BaseTrait2 for Bar { }

fn main() {
let bases = ~[ ~Foo as ~BaseTrait1, ~Bar as ~BaseTrait1 ]; // compiler
uses more optimal ~(*vtable, obj)` layout
for base in bases.iter() { base.foo() }

let bases = ~[ ~Foo as ~BaseTrait2, ~Bar as ~BaseTrait2 ];
for base in bases.iter() { base.foo() }
}
```

I'm not sure if there are any practical applications for this though.
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


[rust-dev] RFC: Updated RFC process

2014-03-11 Thread Brian Anderson

Hey, Rusties.

The freewheeling way that we add new features to Rust has been good for 
early development, but for Rust to become a mature platform we need to 
develop some more self-discipline when it comes to changing the system. 
So this is a proposed modification to our current RFC process to make it 
a more integral part of the overall development process, and one that is 
followed consistently to introduce features to Rust.


Some improvements I would like this to bring over the current process 
include:


* Discourage unactionable or vague RFCs
* Ensure that all serious RFCs are considered equally
* Those with a stake in Rust's development should feel confident they 
understand why new features are being merged


Below is the proposed change to the RFC process. Please read and 
comment. Assuming the feedback is positive I'll update the wiki with 
this later.


-

Many changes, including bug fixes and documentation improvements can be 
implemented and reviewed via the normal GitHub pull request workflow.


Some changes though are substantial, and we ask that these be put 
through a bit of a design process and produce a consensus among the Rust 
community and the [core team].


The RFC (request for comments process) is intended to provide a 
consistent and controlled path for new features to enter the language 
and standard libraries, so that all stakeholders can be confident about 
the direction the language is evolving in.


## When you need to follow this process

You need to follow this process if you intend to make substantial 
changes to the Rust distribution. What constitutes a substantial 
change is evolving based on community norms, but may include the following.


  - Any semantic or syntactic change to the language that is not a bugfix.
  - Changes to the interface between the compiler and libraries, 
including lang items and intrinsics.

  - Additions to `std`

Some changes do not require an RFC:

  - Rephrasing, reorganizing, refactoring, or otherwise changing shape 
does not change meaning.
  - Additions that strictly improve objective, numerical quality 
criteria (warning removal, speedup, better platform coverage, more 
parallelism, trap more errors, etc.)
  - Additions only likely to be _noticed by_ other developers-of-rust, 
invisible to users-of-rust.


If you submit a pull request to implement a new feature without going 
through the RFC process, it may be closed with a polite request to 
submit an RFC first.


## What the process is

In short, to get a major feature added to Rust, one must first get the 
RFC merged into the RFC repo as a markdown file. At that point the RFC 
is 'active' and may be implemented with the goal of eventual inclusion 
into Rust.


* Fork the RFC repo http://github.com/rust-lang/rfcs
* Copy `-template.md` to `active/-my-feature.md` (where 
'my-feature' is descriptive. don't assign an RFC number yet).

* Fill in the RFC
* Submit a pull request. The pull request is the time to get review of 
the design from the larger community.
* Build consensus and integrate feedback. RFCs that have broad support 
are much more likely to make progress than those that don't receive any 
comments.
* Eventually, somebody on the [core team] will either accept the RFC by 
merging the pull request and assigning the RFC a number, at which point 
the RFC is 'active', or reject it by closing the pull request.


Once an RFC becomes active then authors may implement it and submit the 
feature as a pull request to the Rust repo. An 'active' is not a rubber 
stamp, and in particular still does not mean the feature will ultimately 
be merged; it does mean that in principle all the major stakeholders 
have agreed to the feature and are amenable to merging it.


Modifications to active RFC's can be done in followup PR's. An RFC that 
makes it through the entire process to implementation is considered 
'complete' and is moved to the 'complete' folder; an RFC that fails 
after becoming active is 'inactive' and moves to the 'inactive' folder.


### Help this is all too informal!

The process is intended to be as lightweight as reasonable for the 
present circumstances. As usual, we are trying to let the process be 
driven by consensus and community norms, not impose more structure than 
necessary.


[core team]: https://github.com/mozilla/rust/wiki/Note-core-team
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Doc sprint planning

2014-03-11 Thread Erick Tryzelaar
Thanks for this. This sounds great. We should form a group on Thursday at
the meetup and come up with that checklist. I can help track down the
doc-less APIs Friday night and some of Saturday too.



On Mon, Mar 10, 2014 at 5:38 PM, Brian Anderson bander...@mozilla.comwrote:

 Hey,

 As you may know, we've got our first doc sprint scheduled for Sunday, 12-4
 Pacific time. We'll to set up the commons area at the SF office with pizza
 and turn on video conferencing for remoties. Before that day comes though
 we need to come up with some kind of plan, something that is simple and fun.

 Here's my strawman proposal for what we're going to do Sunday:

 We'll focus on API docs since those are bitesize units of work and
 extremely parallelizable. Before the event we come up with a checklist for
 what API docs should include, as well as a list of high-value API's with
 missing docs.

 Sunday we put that list on an etherpad, and let people claim individual
 functions, traits, etc. Additionally, we keep a 'scoreboard' to track who
 completes the most docs. Whoever has the most docs at the end wins (just
 pizza and accolades).

 Does this sound reasonable? Does anybody want to volunteer to 'run' the
 sprint (make the list of needed docs, help people find tasks, collect and
 upstream the results, etc.)?

 Regards,
 Brian
 ___
 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] Virtual fn is a bad idea

2014-03-11 Thread Maciej Piechotka
On Tue, 2014-03-11 at 14:18 -0700, Patrick Walton wrote:
 On 3/11/14 2:15 PM, Maciej Piechotka wrote:
  Could you elaborate on DOM? I saw it referred a few times but I haven't
  seen any details. I wrote simple bindings to libxml2 dom
  (https://github.com/uzytkownik/xml-rs - warning - I wrote it while I was
  learning ruby) and I don't think there was a problem of OO - main
  problem was mapping libxml memory management and rust's one [I gave up
  with namespaces but with native rust dom implementation it would be
  possible to solve in nicer way]. Of course - I might've been at too
  early stage.
 
 You need:
 
 1. One-word pointers to each DOM node, not two. Every DOM node has 5 
 pointers inside (parent, first child, last child, next sibling, previous 
 sibling). Using trait objects would 10 words, not 5 words, and would 
 constitute a large memory regression over current browser engines.
 
 2. Access to fields common to every instance of a trait without virtual 
 dispatch. Otherwise the browser will be at a significant performance 
 disadvantage relative to other engines.
 
 3. Downcasting and upcasting.
 
 4. Inheritance with the prefix property, to allow for (2).
 
 If anyone has alternative proposals that handle these constraints that 
 are more orthogonal and are pleasant to use, then I'm happy to hear 
 them. I'm just saying that dismissing the feature out of hand is not 
 productive.
 
 Patrick
 
 

Ok. I see where my misunderstanding was - I was thinking about DOM
implementation in Ruby for Ruby while you (Mozilla) were talking about
implementation in Ruby for JavaScript.

Please feel free to ignore next paragraph as I haven't given it much
though but my guess would be that it would be possible to avoid the
penalty by enum + alignment + smart compiler. As data have 6 words + in
your scheme (5 described + vtable) the 4 bit alignment (assuming 32+ bit
platform) should not cause much memory waste. This allows for using the
'wasted' bits for other purposes (the trick is used in, for example,
lock-free structures) - for example:

enum ElementChild'r {
   ElementChildElement('r Element),
   ElementChildComment('r Comment),
}

Could be represented as pointer with last bit specifying if it's element
or comment - similar to OptionT optimization. The lookup should
behave much nicer with respect to branch prediction (plus) but getting
pointer is more complicated (minus) and possibly longer code instead of
jump (minus). If data alignes the compiler should be able to optimize
the jumps if it notices that all jumps lead to the same pointer
arithmetic. I'm not sure about handles from JS but I don't think there
is more then 16 choices for types of parent/child/sibling for any node
so it should be achivable - on language side it would just be enum +
pointer (+ specification of alignment as attribute?).

That said a) I have done no measurements/benchmarks so my intuition is
likely to be wrong b) should in above paragraph means 'it looks that it
could work after 5s thought' and c) I'm not a Rust designer and I don't
pay for nor contribute so I don't expect that I should have anything
resembling last word.

Best regards


signature.asc
Description: This is a digitally signed message part
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Virtual fn is a bad idea

2014-03-11 Thread Patrick Walton
I thought about tricks like this, but (a) a sufficiently smart compiler should 
*not* be doing this automatically, as it makes certain common operations like 
fetching the pointer more expensive as well as violating the principle of least 
surprise when it comes to machine representation, and (b) does this sort of 
hack really result in a cleaner design than having some simple language 
extensions? Mind you, I'm all about ways to simplify Rust, but sometimes the 
simplest solution is to build stuff into the language.

On March 11, 2014 7:39:30 PM PDT, Maciej Piechotka uzytkown...@gmail.com 
wrote:
On Tue, 2014-03-11 at 14:18 -0700, Patrick Walton wrote:
 On 3/11/14 2:15 PM, Maciej Piechotka wrote:
  Could you elaborate on DOM? I saw it referred a few times but I
haven't
  seen any details. I wrote simple bindings to libxml2 dom
  (https://github.com/uzytkownik/xml-rs - warning - I wrote it while
I was
  learning ruby) and I don't think there was a problem of OO - main
  problem was mapping libxml memory management and rust's one [I gave
up
  with namespaces but with native rust dom implementation it would be
  possible to solve in nicer way]. Of course - I might've been at too
  early stage.
 
 You need:
 
 1. One-word pointers to each DOM node, not two. Every DOM node has 5 
 pointers inside (parent, first child, last child, next sibling,
previous 
 sibling). Using trait objects would 10 words, not 5 words, and would 
 constitute a large memory regression over current browser engines.
 
 2. Access to fields common to every instance of a trait without
virtual 
 dispatch. Otherwise the browser will be at a significant performance 
 disadvantage relative to other engines.
 
 3. Downcasting and upcasting.
 
 4. Inheritance with the prefix property, to allow for (2).
 
 If anyone has alternative proposals that handle these constraints
that 
 are more orthogonal and are pleasant to use, then I'm happy to hear 
 them. I'm just saying that dismissing the feature out of hand is not 
 productive.
 
 Patrick
 
 

Ok. I see where my misunderstanding was - I was thinking about DOM
implementation in Ruby for Ruby while you (Mozilla) were talking about
implementation in Ruby for JavaScript.

Please feel free to ignore next paragraph as I haven't given it much
though but my guess would be that it would be possible to avoid the
penalty by enum + alignment + smart compiler. As data have 6 words + in
your scheme (5 described + vtable) the 4 bit alignment (assuming 32+
bit
platform) should not cause much memory waste. This allows for using the
'wasted' bits for other purposes (the trick is used in, for example,
lock-free structures) - for example:

enum ElementChild'r {
   ElementChildElement('r Element),
   ElementChildComment('r Comment),
}

Could be represented as pointer with last bit specifying if it's
element
or comment - similar to OptionT optimization. The lookup should
behave much nicer with respect to branch prediction (plus) but getting
pointer is more complicated (minus) and possibly longer code instead of
jump (minus). If data alignes the compiler should be able to optimize
the jumps if it notices that all jumps lead to the same pointer
arithmetic. I'm not sure about handles from JS but I don't think there
is more then 16 choices for types of parent/child/sibling for any node
so it should be achivable - on language side it would just be enum +
pointer (+ specification of alignment as attribute?).

That said a) I have done no measurements/benchmarks so my intuition is
likely to be wrong b) should in above paragraph means 'it looks that it
could work after 5s thought' and c) I'm not a Rust designer and I don't
pay for nor contribute so I don't expect that I should have anything
resembling last word.

Best regards




___
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