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

2014-03-12 Thread Oren Ben-Kiki
I like the way this handles all sorts of trivial casts. There seems to be
a downside in that inherited struct field access becomes very noisy.
Perhaps it would be possible to unify this with an anonymous fields syntax
to get the best of both worlds?


On Wed, Mar 12, 2014 at 1:51 AM, Vadim Chugunov vadi...@gmail.com wrote:

 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 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] Thoughts on the Rust Roadmap

2013-12-31 Thread Oren Ben-Kiki
Not to re-ignite the thread about this, but one way `proc`s aren't
sufficient because they are send-able (that is, allocated on the heap).
Rust lacks a call-once stack-allocated closure types, which are immensely
useful for manipulating container elements, creating DSL-ish syntax, etc.

That's separate from the `decltype` issue, though.

On Tue, Dec 31, 2013 at 3:55 PM, Armin Ronacher armin.ronac...@active-4.com
 wrote:

 Hi,

 On 30/12/2013 17:29, Patrick Walton wrote:

 Is `proc` not sufficient? We could prioritize adding unboxed closures,

 but since they're backwards compatible as far as I know, I don't see a
 major need to add them before 1.0.

 Procs can be called once.

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


Re: [rust-dev] Thoughts on the Rust Roadmap

2013-12-31 Thread Oren Ben-Kiki
The point is that sometimes you really *don't* want the closure to be
send-able, because you want it to access from the surrounding context both
owned pointers (- be called-once) _and also_ borrowed pointers (- be
stack-allocated). This is vital for some use cases and is impossible today
(ok, possible by painfully wrapping a cell around each owned pointer and
taking its value in the stack closure).


On Tue, Dec 31, 2013 at 4:20 PM, Daniel Micay danielmi...@gmail.com wrote:

 On Tue, Dec 31, 2013 at 9:15 AM, Oren Ben-Kiki o...@ben-kiki.org wrote:
  Not to re-ignite the thread about this, but one way `proc`s aren't
  sufficient because they are send-able (that is, allocated on the heap).
 Rust
  lacks a call-once stack-allocated closure types, which are immensely
 useful
  for manipulating container elements, creating DSL-ish syntax, etc.
 
  That's separate from the `decltype` issue, though.

 Closures don't need to be heap-allocated to be `Send`. An unboxed
 closure with only `Send` captures would be `Send` itself too.

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


Re: [rust-dev] Thoughts on the Rust Roadmap

2013-12-31 Thread Oren Ben-Kiki
Great news... I'll admit I have no idea what unboxed closures are,
exactly, google wasn't helpful finding out a post clearly describing them.
The example in
http://www.mail-archive.com/rust-dev@mozilla.org/msg07569.html shows
passing a closure to a map, so it obviously isn't a call-once so it can't
consume an owned pointer. E.g., if it was `|x| x +
f(move-some-owned-pointer-from-the-context-to-be-consumed-by-f)`, then it
wouldn't - and shouldn't - work.

But writing something like my_container.modify_value_of_existing_key(key,
|old| f(old, move-some-owned-pointer-from-context))` should work - I don't
see how both closures can have the same type.


On Tue, Dec 31, 2013 at 4:29 PM, Patrick Walton pcwal...@mozilla.comwrote:

 On 12/31/13 6:26 AM, Oren Ben-Kiki wrote:

 The point is that sometimes you really *don't* want the closure to be
 send-able, because you want it to access from the surrounding context
 both owned pointers (- be called-once) _and also_ borrowed pointers (-
 be stack-allocated). This is vital for some use cases and is impossible
 today (ok, possible by painfully wrapping a cell around each owned
 pointer and taking its value in the stack closure).


 You can do all of that with unboxed closures.

 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] Thoughts on the Rust Roadmap

2013-12-31 Thread Oren Ben-Kiki
Thanks for the explanation. Of course, the point is that you'd meed two
types, `OnceFn` which is stack-allocated (non-send-able, can take borrowed
pointers from its context) and `SendFn` which is heap-allocated (send-able,
can't take borrowed pointers from its context). Both would be able to
consume an owned pointer.

I guess we'll see how this ends up when it evolves past being a sketch of
an idea :-)


On Tue, Dec 31, 2013 at 4:42 PM, Patrick Walton pcwal...@mozilla.comwrote:

 On 12/31/13 6:39 AM, Oren Ben-Kiki wrote:

 Great news... I'll admit I have no idea what unboxed closures are,
 exactly, google wasn't helpful finding out a post clearly describing
 them. The example in
 http://www.mail-archive.com/rust-dev@mozilla.org/msg07569.html shows
 passing a closure to a map, so it obviously isn't a call-once so it
 can't consume an owned pointer. E.g., if it was `|x| x +
 f(move-some-owned-pointer-from-the-context-to-be-consumed-by-f)`, then
 it wouldn't - and shouldn't - work.


 Presumably along with `FnT,U` there will be something like `OnceFnT,U`:

 trait OnceFnRet,Args... {
 fn call(self, args: Args) - Ret;
 //   note by-value self; this is what makes it one-shot
 }

 Note: This is just a strawman sketch of the idea; it may well not work, no
 promises, etc.

 Patrick


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


Re: [rust-dev] Let’s avoid having both foo() and foo_opt()

2013-12-06 Thread Oren Ben-Kiki
There was a whole thread about the need for once-stack-closures. They are
really vital for simple programming with higher-order functions such as
these. I'm not optimistic about them being added though :-(


On Sat, Dec 7, 2013 at 8:15 AM, Brendan Zabarauskas bjz...@yahoo.com.auwrote:


 On 7 Dec 2013, at 10:47 am, Simon Sapin simon.sa...@exyr.org wrote:

  This is why we have methods like .map() and .and_then()

 I like using these higher order functions, but I run into lots of issues
 with moved values because we don’t have once functions. I end up having to
 use matches, which are awfully verbose for simple things. :(

 ~Brendan
 ___
 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] do

2013-11-30 Thread Oren Ben-Kiki
Once stack functions have nothing to do with RAII. It is about container
manipulation methods. Consider the mangle function of a hashmap for
example. It makes perfect sense to be able to access a borrowed pointer and
also consume an owned pointer inside the mangle actions. This is currently
impossible just because.

I have ~10K of Rust LOC in my pet project and I run into this problem more
than a dozen times. I ended up using cells and other nastiness to work
around what is essentially an artificial restriction.

Passing actions to other tasks is all well and good, and repeatedly
applying a function to many container members (e.g., mapping or
folding) is also common. Both of these use cases are very well supported.
But it is as common to have a container that invokes a function exactly
once on one specific member (as another example, basically any function of
the Option type that invokes an action). And this common use case is very
badly supported.



On Sat, Nov 30, 2013 at 10:23 AM, Patrick Walton pwal...@mozilla.comwrote:

 I don't want stack once functions, because I feel that their use cases are
 better served with RAII, which serves the same purposes without rightward
 drift and without forcing LLVM to perform devirtualization.

 Patrick

 Oren Ben-Kiki o...@ben-kiki.org wrote:

 I find `do` syntax form is vital for DSL-ish code. Getting rid of it
 makes a lot of code look downright ugly. I'd rather it used a more Ruby-ish
 notation though, I find that putting the `do` far away from the `{ ... }`
 doesn't read well. `foo() do |...| { ... }` would have made more sense
 for me (think of `do` as a macro-ish binary operation injecting the proc
 into the function on the left). But the current form is acceptable.

 Syntax niceties aside, I find it extremely problematic that we have only
 two forms of callable, one that is on the stack but can be called
 multiple times, and one that is on the heap and can only be called once.
 This arrangement sort-of-makes-sense when one thinks from an implementation
 point of view, but I find it to lack a crucial use case, that of a form
 that is on the stack and is also called only once.

 The reason this 3rd form is so important is the extremely common case of
 a container that wants to take an action as a parameter for a method.

 ```
 ... some_non_sendable_variable ...
 ... some_owned_variable ...
 do container.do_something_at_most_once |...| { ... use *both* variables
 ... }
 ```

 This is a lose-lose situation. If the container takes a `proc`, then Rust
 complains that it can't capture the non-send-able variable. But if the
 container takes a stack closure, then Rust complains it can't use the owned
 variable. Of course, the container will _not_ send the action and will also
 _not_ call it twice, but it can't express this in the action type :-) The
 only workaround I found is to use a closure and wrap each and every
 non-send-able variable in a cell - this is an pointless and downright
 annoying manual boilerplate code.

 As long as this area of the language is being changed, I think that
 adding this missing 3rd variant should definitely be discussed (and
 hopefully implemented). This would affect the syntax discussion because
 there would be three forms instead of two; there are some more and less
 obvious choices here but they are secondary to the core issue of allowing
 the 3rd variant in the 1st place.

 On Sat, Nov 30, 2013 at 9:02 AM, Chris Morgan m...@chrismorgan.infowrote:

 (a) Kill ``do``

 ...

 (b) Make ``do`` support both closures and procedures

 ...

 --

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


 --
 Sent from my Android phone with K-9 Mail. Please excuse my brevity.

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


Re: [rust-dev] do

2013-11-30 Thread Oren Ben-Kiki
That would help a bit, but it would still require the programmer to
manually setup and teardown the tuples, pass them to the closure, and so
on. We'll also need to change each and every function that takes an action
parameter to take the extra tuple in every container or container-like
type. And then there's the possibility of modifying variables... It sounds
like a lot of effort working around something the compiler can do
automatically and actually already does automatically; all it needs is the
ability to communicate the programmer intent via the type system so it can
support and enforce it.


On Sat, Nov 30, 2013 at 4:20 PM, Benjamin Herr b...@0x539.de wrote:

 On Sat, 2013-11-30 at 09:34 +0200, Oren Ben-Kiki wrote:

  This is a lose-lose situation. If the container takes a `proc`, then
  Rust complains that it can't capture the non-send-able variable. But
  if the container takes a stack closure, then Rust complains it can't
  use the owned variable. Of course, the container will _not_ send the
  action and will also _not_ call it twice, but it can't express this in
  the action type :-) The only workaround I found is to use a closure
  and wrap each and every non-send-able variable in a cell - this is an
  pointless and downright annoying manual boilerplate code.

 I think another previously mentioned workaround is to change all your
 closure-taking functions to have a name ending in _with and take an
 extra generic parameter by value that is then passed to the closure. In
 practice, that might end up being a tuple with all the values you're
 need to move into and from within the closure.

 It's not ideal and requires cooperation from the API but it probably
 reads better than a bunch of cells. :)

 -benh


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


Re: [rust-dev] do

2013-11-30 Thread Oren Ben-Kiki
Just to mention in passing - there's a related principle that converting a
block to a closure shouldn't change its semantics. This obviously doesn't
fully work because of return/break/continue; that said, if a block without
such flow control constructs is wrapped into a closure, you'd expect it to
just work. It doesn't, because to work it would have to be a
once-called-stack-allocated lambda, which Rust doesn't have (I don't get
the reason for that either :-)

On Sat, Nov 30, 2013 at 9:40 PM, Kevin Ballard ke...@sb.org wrote:

 On Nov 30, 2013, at 10:20 AM, Patrick Walton pcwal...@mozilla.com wrote:

  On 11/30/13 10:05 AM, Kevin Cantu wrote:
  While we're changing this stuff, I'd like to see lambdas allow return,
  now that the need for forbidding that is gone, IIRC.  That's more likely
  to continually trip me up than unusual allocation mechanisms.
 
  No objections here.

 Quite a while ago the restriction on `return` was explained to me as
 conforming to some principle (I forget the name, sadly) that basically says
 that wrapping a block of code in a closure and immediately calling the
 closure should not change the semantics of the code. Basically, `return`
 shouldn't return from the lambda because that's not what it would do if the
 closure was inlined manually.

 I didn't really understand the point of this, of course.

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


Re: [rust-dev] do

2013-11-30 Thread Oren Ben-Kiki
There were several threads about this,
https://mail.mozilla.org/pipermail/rust-dev/2013-October/006105.html for
example. I don't see how that code can be converted to RAII at all. Sure it
can be done with cells, or possibly with tuples (though, well, doing this
_manually_? shudder). It really just begs for
stack-allocated-once-closures.


On Sat, Nov 30, 2013 at 11:28 PM, Patrick Walton pcwal...@mozilla.comwrote:

 On 11/30/13 11:38 AM, Kevin Ballard wrote:

 The problem here is that the type system already understands the idea
 of a `once` fn, it just has an artificial limitation that means it
 can only apply that to a heap closure and not a stack closure.


 No, it's merged with the idea of a heap/stack closure. Separating them out
 into separate axes would increase type system complexity.

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

2013-11-30 Thread Oren Ben-Kiki
Like I said, this is a boiled-down example of the essence of the problem.
Yes, the hashmap mangle is an example, and the option map, and similar
standard container methods, and quite a few similar functions in my own
specific container classes (contrary to popular opinion, in non-trivial
projects people do end up writing their own specialized containers...). In
general the problem is I am a container, give me a function to modify some
piece of me combined with an invoker that says do the following to modify
some piece of the container, accessing and updating all sort of variables.
It is a pretty significant use case, which seems to have nothing to do with
RAII, and bugs me a lot in my code.


On Sat, Nov 30, 2013 at 11:57 PM, Patrick Walton pcwal...@mozilla.comwrote:

 On 11/30/13 1:54 PM, Oren Ben-Kiki wrote:

 There were several threads about this,
 https://mail.mozilla.org/pipermail/rust-dev/2013-October/006105.html for
 example. I don't see how that code can be converted to RAII at all. Sure
 it can be done with cells, or possibly with tuples (though, well, doing
 this _manually_? shudder). It really just begs for
 stack-allocated-once-closures.


 Well, the functions `attempt_1` and `attempt_2` in that message don't do
 anything, so there isn't anything to convert. Do you have other specific
 common examples of functions that can't be converted to RAII?

 `mangle` is one. `Option::map` and friends are another. Are there others?

 Patrick


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


Re: [rust-dev] do

2013-11-29 Thread Oren Ben-Kiki
I find `do` syntax form is vital for DSL-ish code. Getting rid of it makes
a lot of code look downright ugly. I'd rather it used a more Ruby-ish
notation though, I find that putting the `do` far away from the `{ ... }`
doesn't read well. `foo() do |...| { ... }` would have made more sense
for me (think of `do` as a macro-ish binary operation injecting the proc
into the function on the left). But the current form is acceptable.

Syntax niceties aside, I find it extremely problematic that we have only
two forms of callable, one that is on the stack but can be called
multiple times, and one that is on the heap and can only be called once.
This arrangement sort-of-makes-sense when one thinks from an implementation
point of view, but I find it to lack a crucial use case, that of a form
that is on the stack and is also called only once.

The reason this 3rd form is so important is the extremely common case of a
container that wants to take an action as a parameter for a method.

```
... some_non_sendable_variable ...
... some_owned_variable ...
do container.do_something_at_most_once |...| { ... use *both* variables ...
}
```

This is a lose-lose situation. If the container takes a `proc`, then Rust
complains that it can't capture the non-send-able variable. But if the
container takes a stack closure, then Rust complains it can't use the owned
variable. Of course, the container will _not_ send the action and will also
_not_ call it twice, but it can't express this in the action type :-) The
only workaround I found is to use a closure and wrap each and every
non-send-able variable in a cell - this is an pointless and downright
annoying manual boilerplate code.

As long as this area of the language is being changed, I think that adding
this missing 3rd variant should definitely be discussed (and hopefully
implemented). This would affect the syntax discussion because there would
be three forms instead of two; there are some more and less obvious choices
here but they are secondary to the core issue of allowing the 3rd variant
in the 1st place.

On Sat, Nov 30, 2013 at 9:02 AM, Chris Morgan m...@chrismorgan.info wrote:

 (a) Kill ``do``

...

 (b) Make ``do`` support both closures and procedures

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


Re: [rust-dev] Implementation Inheritance / mixins

2013-11-15 Thread Oren Ben-Kiki
On Fri, Nov 15, 2013 at 11:47 AM, Huon Wilson dbau...@gmail.com wrote:

  As I understand it, default methods are specialised/monomorphised for
 each type for which the trait is implemented. The only time a virtual call
 ever happens is when one explicitly has a trait object.


That would be awesome, if it were true; it is quite a trick to pull that
off when the default methods are implemented in a different crate. Can
someone provide an authoritative answer on this?

Also, C++ faces the problem of providing a single copy of monomorphised
functions (for templates). This is done during the link phase and AFAIK is
one of the causes of C++ links taking a painfully long time. Will Rust
suffer from the same problem?
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Implementation Inheritance / mixins

2013-11-15 Thread Oren Ben-Kiki
Thanks for the explanation! So virtual function calls are kept to the
absolute theoretical minimum, that's very good to know.

In my case I have one crate for some infrastructure and another crate for
the application using it (there would be several of these). I guess
having two copies isn't that bad.


On Fri, Nov 15, 2013 at 2:30 PM, Daniel Micay danielmi...@gmail.com wrote:

 On Fri, Nov 15, 2013 at 6:54 AM, Oren Ben-Kiki o...@ben-kiki.org wrote:
 
  That would be awesome, if it were true; it is quite a trick to pull that
 off
  when the default methods are implemented in a different crate. Can
 someone
  provide an authoritative answer on this?
 
  Also, C++ faces the problem of providing a single copy of monomorphised
  functions (for templates). This is done during the link phase and AFAIK
 is
  one of the causes of C++ links taking a painfully long time. Will Rust
  suffer from the same problem?

 Rust serializes any generic or inline functions to an AST stored in
 the crate metadata and will re-compile them as-needed per-crate.

 In both Rust and C++, you end up with one copy of these at runtime for
 each dynamically linked shared object. With C++ templates, the linker
 or link-time optimization discards duplicate instantiations across
 compilation units.

 Rust doesn't have compilation units smaller than a crate so there is
 no equivalent functionality. If you use crates as compilation units to
 make compiles incremental/parallel, the situation is much worse than
 C++ as you'll have many duplicates and they won't even go away with
 link-time optimization until `mergefunc` works.

 There's almost no point in doing anything but a massive crate at this
 point...

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


Re: [rust-dev] Treating Vectors Like Any Other Container

2013-11-15 Thread Oren Ben-Kiki
If the traits were polymorphic in the index type (instead of always
expecting an integer), then one could use them to make hash tables use
vector syntax (e.g., `hash[foo] = 1`)... Ruby does that, for example. So
something like bitset (with integer indices) isn't the only example.

Not sure whether we want to go that way, though...


On Fri, Nov 15, 2013 at 3:35 PM, Diggory Hardy li...@dhardy.name wrote:

 In reply to Nicholas Matsakis's post:

 http://smallcultfollowing.com/babysteps/blog/2013/11/14/treating-vectors-like-any-other-container/

 That's a really nice write-up Nicholas. I wanted to chip in because I had a
 think about some similar issues in the past, but your review is far more
 thorough and knowledgeable than I could have managed.

 Regarding Gc[uint] (or @[T]), this seems fairly useless to me, given that
 @mut[T] would not be memory safe (unless it is @mut ~[T] or reallocating
 the
 buffer is not allowed), thus the only way of constructing @[T] would be to
 coerce a ~[T] or a literal.

 For me, the biggest plus of your proposal is uniformity: e.g. someone could
 implement something like C++'s std::bitset and have it look syntactically
 equivalent to VectorT (although given that std::bitset is not very useful
 and Boost's Pointer Containers are redundant in both C++11 and Rust, I'm
 struggling to find an example where this is actually needed). Given the
 three
 big drawbacks (implementation effort, syntax and pattern matching) it may
 not
 be worth it.

 Using a builder trait to construct user-defined objects from literals is a
 nice
 approach (I believe it could also be useful in type-safe printf-like
 formatters and embedded DSLs for things like constructing HTML or parser
 rules), but some things like method lookup won't always be possible:

 let v : Vectorint = [1,2,3].append_one( 4 )
 ___
 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] Treating Vectors Like Any Other Container

2013-11-15 Thread Oren Ben-Kiki
Slice traits weren't: though, does `tree.mut_slice_between(foo, bar)`
even make sense?


On Fri, Nov 15, 2013 at 3:44 PM, Huon Wilson dbau...@gmail.com wrote:

  On 16/11/13 00:39, Oren Ben-Kiki wrote:

 If the traits were polymorphic in the index type (instead of always
 expecting an integer), then one could use them to make hash tables use
 vector syntax (e.g., `hash[foo] = 1`)... Ruby does that, for example. So
 something like bitset (with integer indices) isn't the only example.

  Not sure whether we want to go that way, though...

  Note that the traits in the blog posts are parameterised by the index
 type:

 trait IndexI, E { fn index'a('a self, index: I) - 'a E; }

 Etc.

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


Re: [rust-dev] Implementation Inheritance / mixins

2013-11-15 Thread Oren Ben-Kiki
I'm not certain whether it is better than anonymous members; one has to
list all the data members one by one, and there's more magic syntax. But
it is up to the powers-that-be.


On Sat, Nov 16, 2013 at 5:48 AM, Tommi rusty.ga...@icloud.com wrote:

 So... did anyone think that my idea (of doing multiple-inheritance by
 separating the responsibilities of providing functionality and providing
 data between the trait and the type which implements the trait) would
 warrant an enhancement request at github? Or how do these things tend to
 work around here? (I've done plenty of bug/enhancement reporting for D, but
 I know that language fairly well whereas I've just barely read the Rust
 tutorial/manual).

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


Re: [rust-dev] Implementation Inheritance / mixins

2013-11-14 Thread Oren Ben-Kiki
I added https://github.com/mozilla/rust/issues/10491 which links to
https://github.com/mozilla/rust/issues/9728 to propose that single
inheritance can co-exist and be compatible with anonymous fields, achieving
the best of both worlds.
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Implementation Inheritance / mixins

2013-11-14 Thread Oren Ben-Kiki
In your code, when providing a default implementation for `inflate_by`, you
are invoking the trait (hence virtual) method `get_radius`. If the
compiler compiles `inflate_by` when seeing just the `Inflate` source code,
then this must be translated to an indirect call through the vtable.

The point of anonymous members (and, to a greater extent, of the single
inheritance) is to ensure that access to data members is just that, without
any function calls.

To achieve that with the approach you described, the compiler will need to
re-compile `inflate_by` for each and every struct that implements it; only
then it would be able to inline `get_radius`.

Is this what the Rust compiler does today? I have no specific knowledge of
the answer, but the simplest thing for the compiler would be to
keep `get_radius` as a virtual function call.

Doing otherwise would require quite a bit of machinery (e.g., what
if `Inflate` is defined in another crate, and all we have is its
fully-compiled shared object file? There would need to be some extra
stuff available to the compiler to do this re-compilation, as the source
is not available at that point).

Therefore I suspect that this approach would suffer from significant
performance issues.


On 2013-11-15, at 2:09, Tommi rusty.ga...@icloud.com wrote:

 trait Inflate {
 fn get_radius's('s mut self) - 's mut int;

 fn inflate_by(mut self, amount: int) {
 *self.get_radius() += amount;
 }
 }

 trait Flatten {
 fn get_radius's('s mut self) - 's mut int;

 fn release_all_air(mut self) {
 *self.get_radius() = 0;
 }
 }

 struct Balloon {
 radius: int
 }

 impl Inflate for Balloon {
 fn get_radius's('s mut self) - 's mut int {
 mut self.radius
 }
 }

 impl Flatten for Balloon {
 fn get_radius's('s mut self) - 's mut int {
 mut self.radius
 }
 }


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


Re: [rust-dev] Implementation Inheritance / mixins

2013-11-13 Thread Oren Ben-Kiki
This is probably as good as we can get in the current system (I do
something similar in my code today).

I also think you probably need both super and mut_super, so it would be
two methods to implement instead of one (still pretty good). I wonder
whether it is possible to write a macro that automates writing these
boilerplate methods?

The key weakness is that (I think) the compiler can't inline the accesses
to super so that you end up with a chain of virtual function calls every
time it is accessed, so performance would be pretty bad.


On Wed, Nov 13, 2013 at 10:27 AM, Eric Reed ecr...@cs.washington.eduwrote:

 Here's how I would do it using just existing Rust (assuming this hasn't
 all changed under me in the past couple months).
 NB: I haven't actually tried compiling this, but I'm pretty sure it (or
 something like it) would work.

 Nice properties over this solution:
 - Doesn't require language extensions (although syntax sugar wouldn't be
 unwelcome)
 - Doesn't require trait objects (i.e. static dispatch is possible)
 - Only need to implement one method for each derived type (super) in
 addition to overridden methods
 - Supports multiple inheritance in two ways (and avoids the diamond
 problem I think -- not a C++ expert so I may have misunderstood that)
   + no default parent and programmer must select which parent to use
 before calling
   + implementer-chosen default parent and programmer can chose to use
 a different parent if desired

 Neutral?:
 - Doesn't enforce or care about the prefix property. Not sure if that
 still matters so much w/o dynamic dispatch.

 Downsides:
 - Performance of delegation depends on LLVM's ability to inline (I think).
 - Does require repeating all the methods once (for delegating default
 implementations)

 // The base type
 struct Base {
 data : int;
 }

 // Characterize it's extensible behavior in a trait
 trait Trait {
 fn method(self);
 }

 // Implement the base behavior
 impl Trait for Base {
 fn method(self) { ... }
 }

 // Extension of trait that supports upcasting to existing implementations
 trait DerivingTraitP : Trait : Trait {
 // one extra method for accessing a parent's implementation. ideally
 this would be inlined by the compiler
 fn super(self) - P;
 // default implementations for all the methods in Trait let us avoid
 writing delegation everywhere manually
 fn method(self) {
  self.super().method() // just delegate to parent
 }
 }

 // Single inheritance
 struct Single {
 parent: Base,
 moreData: int,
 }

 impl DerivingTraitBase for Single {
 fn super(self) - Base { self.parent }
 }

 // Overriding behavior
 struct Override {
 parent: Base,
 otherData: u8,
 }

 impl DerivingTraitBase for Override {
 fn super(self) - Base { self.parent }
 fn method(self) { ... }
 }

 // Multiple inheritance
 struct Multiple {
 single: Single,
 override: Override,
 evenMoreData: ~str,
 }

 // must specify which parent's implementation we want (could hide wrapping
 inside of as_* methods impl'd on Multiple if you like)
 // if we want one of them as the default, then we can impl DerivingTrait
 on Multiple directly
 struct MultipleAsSingle(Multiple);
 struct MultipleAsOverride(Multiple);

 impl DerivingTraitSingle for MultipleAsSingle {
 fn super(self) - Single { self.single }
 }

 impl DerivingTraitOverride for MultipleAsOverride {
 fn super(self) - Override { self.override }
 }

 fn main() {
 let base = Base { ... };
 let single = Single { ... };
 let override = Override { ... };
 let multiple = Multiple { ... };

 base.method();
 base.super(); // compile time error

 single.method(); // =inline delegation= single.super().method()
 =inline upcast= single.base.method()
 override.method(); // done! no delegating
 MultipleAsSingle(multiple).method(); // =delegate=
 MAS(multiple).super().method() =upcast= multiple.single.method()
 =delegate= multiple.single.super().method() =upcast=
 multiple.single.base.method()
 MutlipleAsOverride(multiple).method(); // =delegate=
 MAO(multiple).super().method() =upcast= multiple.override.method()
 }

 Thoughts?

 Eric


 On Tue, Nov 12, 2013 at 10:30 PM, Kevin Ballard ke...@sb.org wrote:

 On Nov 12, 2013, at 10:26 PM, Kevin Ballard ke...@sb.org wrote:

  And even that restriction could be lifted if ~Trait objects could be
 represented using an array of pointers (one to each inherited struct), e.g.
 ([*A,*B,*C],*vtable) instead of just (*A,*vtable), though I suspect this is
 not worth doing.

 Upon further reflection, this  would need to be done anyway because of
 the ability to combine traits. If I have

 trait TraitA : A {}
 trait TraitB : B {}

 and I want to use ~TraitA+TraitB then I would need a fat trait.
 Although in this case the number of value pointers is equal to the number
 of combined traits, so it's a bit more sensible to allow for fat trait
 pointers here.

 -Kevin
 

Re: [rust-dev] linking to cells inside a data structure

2013-11-13 Thread Oren Ben-Kiki
You are right that the compiler needs to ensure no pointers escape the
struct itself, so it is OK to move it (and all the pointers it includes).
Intuitively this would require another level of static type checking
(whether there are existing outside-the-struct borrowed pointers at any
point), probably not easy to do.


On Wed, Nov 13, 2013 at 6:08 PM, Niko Matsakis n...@alum.mit.edu wrote:

  I don't know how to make that sound, unfortunately, other than using
  an arena and allocating all the nodes into it (losing the ability to
  deallocate individual nodes).

 Arenas don't require that you lose the ability to deallocate
 individual nodes. See my thoughts in #10444. Briefly, the idea is that
 the arena allocation returns an affine type like `ArenaAlloc'self`.
 You can then have a free method that consumes this instance and adds
 it to a free list to be reused for future allocation.




 Niko
 ___
 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] Implementation Inheritance / mixins

2013-11-13 Thread Oren Ben-Kiki
Hmmm. Perhaps I was too hasty. It would be interesting to look at the
generated binary code and see if it actually work this way...

On Wed, Nov 13, 2013 at 8:08 PM, Eric Reed ecr...@cs.washington.edu wrote:

 I'm not sure I follow.
 My implementation doesn't use any trait pointers, so the only time there
 were would be a trait pointer is if you casted to ~Trait yourself.
 In that case, only the original method call would be dynamic dispatch; all
 the internal calls (delegating and upcasting) are still static dispatch.
 So my version doesn't pay for any dynamic dispatch over what the
 programmer is already paying for.

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


Re: [rust-dev] The future of M:N threading

2013-11-13 Thread Oren Ben-Kiki
On Wed, Nov 13, 2013 at 10:51 PM, james ja...@mansionfamily.plus.comwrote:

  On 13/11/2013 19:30, Daniel Micay wrote:
  I had high hopes of Rust having lightweight segmented stacks and precise
 per-task
 GC and portability too.  Sort of Erlang with type safety and AOT
 compilation with a
 sane model.


That's something I'd also love to see! The Erlang with type safety and
compilation is definitely something I was (am!) expecting from Rust.

(I think Rust could be a good basis for distributed actor-style systems,
due to the owned pointers it is clear how to send messages from one machine
to another, but that's another story...)


 But now much of this seems abandoned or clearly a long way out and it is
 becoming
 more like C++ with some functional bits, and  I can get that with Scala
 and F# now.


To be fair, Scala and F# are still VM languages while Rust is compiled. And
I _hope_ not all is lost, so that Rust would still be friendly to
actor-style programs (as well as to socket-server style programs). It does
seem the focus has shifted away from this :-(

I find it more scary that Rust might be turning towards a universal
platform for implementing your own pointers/scheduler/abstractions rather
than an opinionated platform providing a great set of
pointers/scheduler/abstractions. The need to allow for any and every
pattern combined with extract the last 1% of performance has IMO poisoned
C++; I was drawn to Rust as take the good parts, bake them into the
language, and ignore the rest, even at some reasonable performance cost.

It is somewhat ironic that Rust, which at times has a much lower level
feel to it, provides essential higher-level features like algebraic types
and pattern matching and generics, while a more abstract language like Go
doesn't. As an application developer who doesn't care about the last 15% of
the performance, but cares a lot about productivity, I can't help but wish
for a happy medium between the two :-)

At any rate, language design is _hard_. Rust is actually doing pretty
well... and one can drastically evolve the runtime/scheduler over time -
even provide different versions for different needs. It is much harder to
fix the basic language abstractions, which Rust gets pretty well.
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Implementation Inheritance / mixins

2013-11-12 Thread Oren Ben-Kiki
The Rust way to do that would be to have an array of objects that all
implement the needed trait. But that would mean that access to the data
members would be a virtual function call, while access to the data
members of the new kind of traits you described would be cheap.

I think that introducing two kinds of traits would have non-obvious
implications on the type system, in addition to saddling us with all the
pains of a single-inheritance types hierarchy system.

Also, assuming you do introduce two types of traits, for the reason you
described, making implementation reuse a feature of _only_ one kind of
traits feels very wrong. There should be some way to do reasonable
implementation reuse for the current kind of traits as well.

You could view the new kind of traits you described as a special case of
what I described. In fact you could say that `pub struct Foo : Bar { ... }`
means exactly `pub struct Foo { reuse Bar::*; ... }`, and also allow the
kind of pointer casts/heterogeneous arrays you are talking about.

Or, we could move in the direction of anonymous members, which should also
allow for the kind of pointer casts/heterogeneous arrays you want... These
would offer a somewhat different tradeoff than the source code
transformation approach, so you might like them better :-)



On Tue, Nov 12, 2013 at 9:56 AM, Patrick Walton pcwal...@mozilla.comwrote:

 On 11/12/13 4:53 PM, Oren Ben-Kiki wrote:

 Your solution does not match the performance of single inheritance,
 because it has virtual method calls for every field access from the
 outside of the trait.

 Sorry, I don't follow.

 Access to members from outside of the traits would require accessing the
 concrete type. Since the approach I described used source
 transformation, then this would just be a normal data member access, as
 efficient as single inheritance.


 Oh, source transformation. I didn't read closely. That won't work as a
 replacement for single inheritance because it doesn't provide truly
 existential types--for example, an array of heterogeneous objects all of
 which share a common prefix.

 Patrick


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


Re: [rust-dev] linking to cells inside a data structure

2013-11-12 Thread Oren Ben-Kiki
I have been struggling with variants of this for a while and there's no
best solution.

First, if the array holds values (as opposed to pointers to values), then
pretty much your only option is to replace your pointers with indices to
the array. You'd need access to the container to access the values, of
course. But this is the only safe way because adding into the array may
relocate it, invalidating all pointers.

If your array holds pointers, then you can do something; e.g., store RcT
in the array cells and also in the places you want to link to the values.
If reference cycles are an issue you can use @T instead of RcT (keep in
mind this will change to GcT or something in the future).

If sending the whole thing is an issue, you are pretty much forced to use
ArcT (and forget about reference cycles). And, of course, each of these
(Rc, @, Arc) has a different name if you want mutation (RcMut, @mut, ArcRW).

In performance-critical code I sometimes give up and just have an array of
~T and use an unsafe ptr to T in all my other references... which is OK as
long as these only live as long as the container, but I get zero compiler
support for that. I wish there was a way to say this borrowed pointer
lives only as long as its container. That doesn't seem to be in the cards
though :-(


On Tue, Nov 12, 2013 at 2:24 PM, spir denis.s...@gmail.com wrote:

 Hello Rust people,

 A data structure holds (unpointed) cells in an array. Then, a number of
 linked lists part of the data structure link to those same cells. What is
 the right Rust way to do that? I cannot have the language accept the
 instruction establishing a link, whatever kind of pointer I use (both for
 self and for cells).

 Code and/or details on demand.

 Denis

 PS: It is in fact a hash table [1] which buckets are link lists as
 usually, but the cells are stored in an array instead of spread around the
 memory at the allocator's convenience ;-). First advantage is indeed
 entries are in order.
 (To move on in the meanwhile, I'll remove this aspect.)

 [1] Actually a mod table since keys are uints, there is no hash, only
 modulo.
 ___
 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] linking to cells inside a data structure

2013-11-12 Thread Oren Ben-Kiki
Yes, you lose the ability to deallocate individual nodes. Pretty hard to
express in a type system. Still I wish I could at least have the compiler
help me to ensure my unsafe pointers never escape the lifetime of the
container; right now I must trust the programmer (and in my case, the
container basically lives as long as the program, anyway).

Slots sound nice. Is the idea that one would do RcT for read-only access
and RcSlotT for mutable access? How does this protect against multiple
mutations at once?

On Tue, Nov 12, 2013 at 3:13 PM, Patrick Walton pcwal...@mozilla.comwrote:


 In performance-critical code I sometimes give up and just have an array
 of ~T and use an unsafe ptr to T in all my other references... which is
 OK as long as these only live as long as the container, but I get zero
 compiler support for that. I wish there was a way to say this borrowed
 pointer lives only as long as its container. That doesn't seem to be in
 the cards though :-(


 I don't know how to make that sound, unfortunately, other than using an
 arena and allocating all the nodes into it (losing the ability to
 deallocate individual nodes).

 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] copying pointers

2013-11-12 Thread Oren Ben-Kiki
For linked lists with no cycles, why not use OptionRcT (or RcMut)?


On Tue, Nov 12, 2013 at 4:06 PM, spir denis.s...@gmail.com wrote:

 PS: What would be, in fact, the rusty way for a simplissim linked list. I
 use Option~Cell for now, to have something clean (None) to end the list,
 since Rust looks rather functional. But as always with Option this way
 quite obscures and complicates the code (Some() expressions, match
 expressions...). I'd rather just use a NULL pointer, for here it is fully
 safe. But this does not look rusty at all, I guess.
 What is your view?


 Denis




 ___
 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] Implementation Inheritance / mixins

2013-11-12 Thread Oren Ben-Kiki
It seems the argument on single-inheritance hinges on the following use
case:

struct Foo { foo: int }

struct Bar : Foo { bar: bar }

fn main() {
let myFoos = [Foo{ foo: 1 } as ~Foo, Bar{ foo: Foo{foo: 1}, bar: 2} as
~Foo];
for myFoo in myFoos.iter() {
myFoo.foo; // Fixed offset access
}
}

If I understand correctly, this member access is vital for Servo.

At the same time, I (and I think others) would like to see some form of a
flexible implementation reuse for traits, with the understanding the
invoking trait methods incurs the cost of a virtual function anyway.

I think it is obvious that the same mechanism can't do both. So how about
a compromise? There would be two mechanisms, but we'll make them play nice
with each other.

Mechanism #1: Struct-traits.
Mechanism #3: Anonymous fields.

struct Foo { foo: int }

// Note: Use Foo as a trait.
// Any type implementing Foo has a publicly-reachable Foo member at
offset 0.
// The trait Foo allows constant-offset access to all the Foo data
members.
fn use_fooT: Foo(ptr: T) - int {
ptr.foo // Fixed offset
}

// By construction, Bar implements the Foo struct-trait
struct Bar {
Foo;
bar: int;
}

(It is also possible to add a new syntax struct Bar : Foo { bar int }, if
this is seen as clearer, but IMO it isn't really needed).

// Baz also implements Foo by construction.
struct Baz {
Bar;
baz: int;
}

// Qux doesn't implement Foo.
struct Qux {
qux: int,
Foo
}

As for non-struct traits, anonymous fields would provide a default
implementation. That is, suppose that:

impl Trait for Foo { ... }

Then one would be need to write (explicitly!):

impl Trait for Bar {} // Just use the default from Foo

Or:

impl Trait for Bar { ... override some of the methods ... };

(I think it is a bad idea to have traits be implemented implicitly just
because one anonymous field implements them; IMVHO an explicit impl Trait
for Container is a very good idea).

This way you can have your cake and eat it 2. I think it is pretty clean -
traits do arbitrary mixin things with virtual-function cost (_with_
implementation reuse); And there's a by definition single inheritance
special access-my-data-members-at-fixed-offset trait whose existence does
not impact the power of the normal mixin traits in any way.
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] formats 'Standard' {} and 'Poly' {:?}

2013-11-11 Thread Oren Ben-Kiki
I thought the trait for `{}` was called `Default`. At any rate, I also
don't understand why we need both `{}` and `{:s}`, `{:i}`, etc. There's
some reason for `{:x}` (change the output base to hexadecimal), but that's
about it.
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


[rust-dev] Implementation Inheritance / mixins

2013-11-11 Thread Oren Ben-Kiki
I googled around and this has been asked before several times; there are
answers that use obsolete syntax and Rust concepts, so I thought it might
be a good idea to revisit the issue.

The basic use case is having some trait, and having some (base/mixin)
struct implementing it. Now, one wants to have a 2nd (derived/importing)
struct implementing the trait, based on the 1st struct implementation
(including its data members).

I'm not certain what the idiomatic Rust answers to this common use case is,
today.

One can obviously simply duplicate the data members and the trait
implementation, if the size of the code is small enough. This is very WET
though.

One can have the derived/importing class contain a member of the base/mixin
struct, then delegate each and every trait function to it (providing
overrides where needed). This is pretty tedious and results with a lot of
boilerplate code. Performance would probably suffer. It is also difficult
to override methods that are invoked by imported methods.

One can write the 1st struct in a way that is intended to be overridden,
e.g. by providing a trait with a get base accessor and using that all
over the place. This makes the base struct code uglier (and, I think, less
efficient), but results in less boilerplate code in the derived class. It
makes overrides much trickier though. In general seems pretty restricted.

One can implement a bunch of macros to automate injecting the common code
into derived structs (I think - I'm not clear whether macros are allowed to
add methods and members to a struct). Setting up the macros isn't fun,
especially when one wants to take overrides into account.

If there another option? Which one is more idiomatic Rust code?

There are many options that would require compiler/language support...
these basically automate the above approaches.

Personally I am fond of a somewhat unusual approach I first saw in Sather
(I think), which was to automate the macro based approach. That is, define
implementation inheritance (actually, mixins) as a source-level
operation.

The source code of the imported/reused members from the base (mixin) struct
would be (logically anyway) pasted inside the definition of the
derived/importing struct, and then compiled as usual.

This is very simple to define (it is basically similar to use - in fact,
this resonates with the idea of changing the division of labor between
structs and modules, but it is a separate discussion).

It allows for great flexibility: one can import only specific methods and
members, providing a different implementation for others; Using the ability
to import something under a different name, it is possible to wrap the
imported methods with additional functionality (foo { ...;
renamed_imported_foo(); ... }), etc.

So, this provides the functionality of virtual functions (an imported
function calling one that is redefined - that is, not imported but
implemented locally - will get the overriden behavior). At the same time,
unlike virtual functions, it still allows for aggressive optimizations
(since when compiling a struct, all methods are fully known and can be
inlined etc.).

It sidesteps a lot of sticky issues with a vtable-sharing oriented approach
(like in C++). For example, re-importing would cause multiple definitions
of the same member/method.

It even allows for separate compilation (if the object file contains the
AST tucked in it somewhere), and for reuse of compiled methods (if they
don't invoke overriden methods - but that may be tricky to implement).

At any rate, I'm not claiming this is necessarily the best approach for
Rust; I'm just wondering, what is the proposed way to address this use
case? None of the manual approaches seems very appealing (unless there's a
better one I missed).

Thanks,

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


Re: [rust-dev] Implementation Inheritance / mixins

2013-11-11 Thread Oren Ben-Kiki
Ah, thanks. I wasn't aware of that. I should start tracking that RSS feed...

I am very concerned that single-inheritance takes the language in the wrong
direction. I feel that a more mixin-oriented solution would better match
Rust's traits based type system. I posted a comment the blog entry you
gave, which I assume is a more appropriate venue than this thread...?

Either way, I gather there's no current idiomatic pattern for this - we are
waiting until some solution is agreed upon (and implemented :-)

Thanks,

Oren.


On Mon, Nov 11, 2013 at 11:43 PM, Patrick Walton pcwal...@mozilla.comwrote:

 On 11/12/13 5:16 AM, Oren Ben-Kiki wrote:

 I googled around and this has been asked before several times; there are
 answers that use obsolete syntax and Rust concepts, so I thought it
 might be a good idea to revisit the issue.

 The basic use case is having some trait, and having some (base/mixin)
 struct implementing it. Now, one wants to have a 2nd (derived/importing)
 struct implementing the trait, based on the 1st struct implementation
 (including its data members).


 There are proposals for this, if I understand you correctly. This is
 needed in Servo.

 http://smallcultfollowing.com/babysteps/blog/2013/10/24/
 single-inheritance/

 Patrick

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


Re: [rust-dev] State of private

2013-11-09 Thread Oren Ben-Kiki
Well... you could consider each member as if it was implemented by accessor
method, and control these methods even if it was an actual member; of
course, also provide a the same syntax for accessing actual members and
method-defined-members... but I think this is too far from the current Rust
direction.

A friend keyword, on the other hand, should be pretty simple to implement
and is a rather minor tweak to the existing system.


On Sat, Nov 9, 2013 at 5:50 AM, Gábor Lehel illiss...@gmail.com wrote:


 On Sat, Nov 9, 2013 at 7:43 AM, Oren Ben-Kiki o...@ben-kiki.org wrote:

 Many thanks for the replies.

 My problem is actually in accessing private methods/members of a struct
 defined in a different, but very closely related module. It seems @
 nikomatsakis https://github.com/nikomatsakis is saying in the final
 text comment of https://github.com/mozilla/rust/issues/8215 that it is
 not possible to specify methods/members that are only accessible from
 within a small set of modules; they are either completely public, or
 private to a single module.


 FWIW, I think this might also be partially addressed by my earlier
 proposal to remove methods as a distinct concept, and just allow using
 dot-syntax with any function? (I have a draft of a follow-up to that thread
 that's been sitting there for two weeks... sigh.)

 It wouldn't help with struct members though, which is interesting. Maybe
 the import syntax could be extended to accomodate that?

 E.g.

 mod a { pub struct Point { x: int, y: int } }

 mod b { use a::Point; } // currently exists, import all fields

 mod c { use a::Point { * }; } // also import all fields

 mod d { use a::Point { }; } // import no fields

 mod e { use a::Point { x }; } // import only x, not y

 Then you could play similar games with struct fields as with items.

 --
 Your ship was destroyed in a monadic eruption.

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


Re: [rust-dev] About owned pointer

2013-11-08 Thread Oren Ben-Kiki
Now I'm confused; doesn't this mean str is fixed size, so the proposal to
just use str for the 3-word struct and have ~str and str just be the
normal thing makes sense after all?

On Fri, Nov 8, 2013 at 8:56 PM, Marvin Löbel loebel.mar...@gmail.comwrote:

 On 11/08/2013 07:50 PM, Igor Bukanov wrote:

 On 8 November 2013 18:35, Patrick Walton pcwal...@mozilla.com wrote:

 But Daniel did some performance measurements and found that this had
 suboptimal performance characteristics when compared to:

  struct ~str {
  char *ptr;
  int size;
  int cap;
  }

 So we're changing to the latter.

 Does this mean that when ~str is passed as a parameter the compiler
 copies 3 words and that makes things faster?

 According to https://github.com/mozilla/rust/issues/8981, yes and yes
 apparently. :)

 You rarely pass around a ~[T] directly anyway, usually you work with
 slices to them, which right now consist of exactly two words. (Though that
 might change to three words too for unrelated consistency reasons)

 Other speed improvements come from the fact that empty vectors no longer
 allocate, and that you no longer need to dereference a pointer into heap
 memory to get the size of an vector.



 ___
 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] About owned pointer

2013-11-08 Thread Oren Ben-Kiki
So, the core question is whether we think of str as an object or as a
pointer. Either we see it as an object (with fixed size, 3 words), which
internally holds a nested pointer to a dynamically-sized region of
characters; or we see it as a direct smart pointer to this array.

The physics of str seem to be the former, but the abstraction presented
to the programmer is the latter. Of course, there's also value in providing
clean abstractions, but this is a leaky one. For example, it isn't very
clean to have a concrete type T which allows ~T, T, @T, *T but forbids
having a simple T (unless one is talking about a trait, which str isn't).
It is weird and causes all sort of edge cases when trying to write generic
code.

Also, str != ~[u8] (for good reason). The internal array is hidden anyway,
so pretending to be a smart pointer to it doesn't make a lot of sense to
me. Of course there's a very related issue of whether we see a vector as a
smart pointer or as an object, so even if str was == ~[u8] it would
probably still make sense to view it as an object :-)

In general, in a system language, one wants the low-level abstractions
(such as str) to be close to the physics, so people would be able to
easily reason about the code behavior. This would also lend support to the
proposal of seeing str as a struct and not as a pointer.


On Fri, Nov 8, 2013 at 11:22 PM, Patrick Walton pcwal...@mozilla.comwrote:

 On 11/8/13 11:33 AM, Oren Ben-Kiki wrote:

 Now I'm confused; doesn't this mean str is fixed size, so the proposal
 to just use str for the 3-word struct and have ~str and str just be
 the normal thing makes sense after all?


 No, `str` is not fixed-size. An *owned pointer* to a string is fixed-size
 (as all pointers are), but the string *itself* is dynamically sized.

 The size of pointers changes based on the kind of thing they point to.

 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] About owned pointer

2013-11-08 Thread Oren Ben-Kiki
Yes, the down side is another level of indirection. This could be optimized
away for 'static str, but not for str. Good point.


On Sat, Nov 9, 2013 at 12:06 AM, Patrick Walton pcwal...@mozilla.comwrote:

 On 11/8/13 2:00 PM, Oren Ben-Kiki wrote:

 Also, str != ~[u8] (for good reason). The internal array is hidden
 anyway, so pretending to be a smart pointer to it doesn't make a lot of
 sense to me. Of course there's a very related issue of whether we see a
 vector as a smart pointer or as an object, so even if str was == ~[u8]
 it would probably still make sense to view it as an object :-)


 No! Read the thread! You need `str and `'static str` for performance as
 well as `~str`.

 Patrick


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


Re: [rust-dev] About owned pointer

2013-11-08 Thread Oren Ben-Kiki
Is there a place where one can see new proposals (is it all in the issues
list in github and/or here, or is there a 3rd place?)

E.g. there's the whole lets-get-rid-of-@, and now is the 1st time I heard
there's a dynamically sized types proposal... well, other than in passing
in this thread, that is.


On Sat, Nov 9, 2013 at 12:09 AM, Patrick Walton pcwal...@mozilla.comwrote:

 On 11/8/13 2:08 PM, Oren Ben-Kiki wrote:


 I don't follow. ~Trait is a pointer, and therefore its size is fixed.
 There are checks in place to prevent using a trait as a type (there's a
 nice error message from the compiler saying using trait as a type
 :-)... So the Trait in ~Trait isn't a _type_, right? :-)


 No, the `Trait` in `~Trait` is a type under the dynamically sized types
 proposal. It is a type, just a dynamically sized one.

 Patrick


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


Re: [rust-dev] About owned pointer

2013-11-08 Thread Oren Ben-Kiki
No need to apologize. You are quite right, this is tricky and there's a
good reason for the current design choices (perhaps there are better, but
they are far from obvious). I wish I could put more time into deep thinking
about this... which, of course, you can :-)


On Sat, Nov 9, 2013 at 12:32 AM, Patrick Walton pcwal...@mozilla.comwrote:

 On 11/8/13 2:19 PM, Brian Anderson wrote:

 This thread is has been running off the rails a bit. Let's all please
 take a step back. This subject is one of the most subtle areas of Rust's
 type system, is in flux, and a lot of our plans about it are scattered
 across various places and passed around through informal conversation.
 It's understandable that there's confusion and debate here.


 Agreed, and again, my apologies.

 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] Help: How to execute the owned method produce_obj?

2013-11-08 Thread Oren Ben-Kiki
It wouldn't be self.something because it doesn't take a self argument.
Try Pool::produce_obj::T(...) ?
Or add a self argument to it and then call it normally.


On Sat, Nov 9, 2013 at 1:31 AM, wuyunlong wuyunl...@msn.com wrote:

 struct PoolT{
 produce_obj : ~fn()-T,
 elements : ~[T]
 }

 implT:Send PoolT{

  fn new_obj(mut self){
   let obj = self. ... ;*// Here ,how to execute method
 produce_obj ?*
   self.elements.push(obj);
  }
 }


 ___
 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


[rust-dev] State of private

2013-11-08 Thread Oren Ben-Kiki
I find that in several cases I would like to have sibling modules access
private members, that is, allow foo::bar::Bar access the private members
of foo::baz::Baz, but disallow any code in qux::* from accessing these
members.

Currently in these cases I am forced to expose as public stuff that really
should be private, or merge too much code into one module.

In a word, is this even possible, or is planned to be possible? I know
there have been some hot debates on visibility and accessibility and
modules and crates, and I don't want to re-open it :-) I just want to know
what the state of affairs is.
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] State of private

2013-11-08 Thread Oren Ben-Kiki
Many thanks for the replies.

My problem is actually in accessing private methods/members of a struct
defined in a different, but very closely related module. It seems @
nikomatsakis https://github.com/nikomatsakis is saying in the final text
comment of https://github.com/mozilla/rust/issues/8215 that it is not
possible to specify methods/members that are only accessible from within a
small set of modules; they are either completely public, or private to a
single module.

Looking at the same thread, I see nobody asked about a possibility of
keeping the existing rules, but also adding a friend keyword at the
module level; that is, if a module foo says friend mod bar, then the
module bar can access any private stuff in the module foo. I'm not very
enamored of the friend keyword in C++, but it seems to me that having it
only in module level greatly simplifies things. Also, in a Rust context, it
seems it would cut down on much of the boilerplate code needed by barrier
modules (which is not to say that re-exporting isn't a very useful feature
as of itself).

I don't want to re-open old discussions - is this something that was
considered and rejected before?
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] State of private

2013-11-08 Thread Oren Ben-Kiki
I added https://github.com/mozilla/rust/issues/10383 in the hope that
enough people would find it useful and it would end up in 1.0 after all :-)

In the meanwhile, I'll have to re-think my design to see if I can package
all the private members in a separate structure, or something like that.

Thanks,

Oren Ben-Kiki

On Fri, Nov 8, 2013 at 10:44 PM, Patrick Walton pcwal...@mozilla.comwrote:

 On 11/8/13 10:43 PM, Oren Ben-Kiki wrote:

 Looking at the same thread, I see nobody asked about a possibility of
 keeping the existing rules, but also adding a friend keyword at the
 module level...


 Nobody has proposed it AFAIK. I personally think it's not likely to be a
 Rust 1.0 feature, but I wouldn't necessarily be opposed in general.

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


Re: [rust-dev] Abandoning segmented stacks in Rust

2013-11-07 Thread Oren Ben-Kiki
Does ditching segmented stacks mean we can start getting a stack trace when
a task `fail!`s? Or is this an unrelated issue?

The lack of stack traces is extremely tedious when debugging failed
assertions...
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Abandoning segmented stacks in Rust

2013-11-07 Thread Oren Ben-Kiki
Good to know! The GDB stack traces leave something to be desired, though -
e.g. the way it reports closures isn't really very useful (adding source
file name and line number would be really good there). But it is certainly
better than nothing. Thanks!


On Fri, Nov 8, 2013 at 8:40 AM, Corey Richardson co...@octayn.net wrote:

 Entirely unrelated. Do note that we have stack traces *now*, as long
 as you're using gdb to get them :). Break on `rust_begin_unwind` or
 catch throw.

 On Fri, Nov 8, 2013 at 1:27 AM, Oren Ben-Kiki o...@ben-kiki.org wrote:
  Does ditching segmented stacks mean we can start getting a stack trace
 when
  a task `fail!`s? Or is this an unrelated issue?
 
  The lack of stack traces is extremely tedious when debugging failed
  assertions...
 
  ___
  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] Abandoning segmented stacks in Rust

2013-11-07 Thread Oren Ben-Kiki
How bad would it be to add another 64 bits to the some data to go along
with it part? I'm assuming 32 bit for file name index in some table and 32
bit for the line number in the file should be enough :-)


On Fri, Nov 8, 2013 at 8:48 AM, Daniel Micay danielmi...@gmail.com wrote:

 On Fri, Nov 8, 2013 at 1:45 AM, Oren Ben-Kiki o...@ben-kiki.org wrote:

 Good to know! The GDB stack traces leave something to be desired, though
 - e.g. the way it reports closures isn't really very useful (adding source
 file name and line number would be really good there). But it is certainly
 better than nothing. Thanks!


 Rust only has boxed (type erased) closures so there's no source data to
 associate with them. They're a function pointer and some data to go along
 with it.

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


Re: [rust-dev] Abandoning segmented stacks in Rust

2013-11-07 Thread Oren Ben-Kiki
Added https://github.com/mozilla/rust/issues/10350 then :-)


On Fri, Nov 8, 2013 at 9:00 AM, Daniel Micay danielmi...@gmail.com wrote:

 On Fri, Nov 8, 2013 at 1:59 AM, Daniel Micay danielmi...@gmail.comwrote:

 On Fri, Nov 8, 2013 at 1:52 AM, Oren Ben-Kiki o...@ben-kiki.org wrote:

 How bad would it be to add another 64 bits to the some data to go along
 with it part? I'm assuming 32 bit for file name index in some table and 32
 bit for the line number in the file should be enough :-)


 In debug builds, no problem at all. It would mean updating all code doing
 transmutes of closures and the code generation for them though.


 On second thought... it does seem like if the debug data can be associated
 with functions, it's available for function pointers to them.

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


Re: [rust-dev] struct def

2013-11-06 Thread Oren Ben-Kiki
I would think:

let mut ps = *Points* {xs:~[1], ys:~[1]};
let mut ps : *Pointsuint* = *Points* {xs:~[1], ys:~[1]};

In Haskell-speak, there is a different between the type and the
constructor, even though by convention they are given the same name.


On Wed, Nov 6, 2013 at 9:46 AM, spir denis.s...@gmail.com wrote:


 I can write this:
 struct Points {xs:~[uint], ys:~[uint]}
 fn main () {
let mut ps = Points{xs:~[1u], ys:~[1u]};
...
 }

 But I cannot write that:
 struct PointsT {xs:~[T], ys:~[T]}
 fn main () {
let mut ps = Pointsuint{xs:~[1u], ys:~[1u]};
...
 }

 In the second case, I get the error:
 sparse_array.rs:106:31: 106:32 error: expected one of `; }` but found `:`
 sparse_array.rs:106let mut ps = Pointsuint{xs:~[1u], ys:~[1u]};
^

 Sorry to bother you with that, I find myself unable to find the right
 syntactic schema (and could not find any example in any doc online). I'm
 blocked, stupidly.

 spir@ospir:~$ rust -v
 rust 0.8
 host: x86_64-unknown-linux-gnu


 Also, I have a general problem with writing struct instances with the type
 apart; meaning, without any type param, I get the same error:
 struct Points {xs:~[uint], ys:~[uint]}

 fn main () {
let mut ps : Points = {xs:~[1], ys:~[1]};
...
 }
 ==
 parse_array.rs:106:28: 106:29 error: expected one of `; }` but found `:`
 sparse_array.rs:106let mut ps : Points = {xs:~[1], ys:~[1]};
 ^

 More generally, I don't know why there are 2 syntactic schemas to define
 vars. I would be happy with the latter alone (despite the additional pair
 of spaces) since it is more coherent and more general in allowing
 temporalily uninitialised declarations.

 Denis
 ___
 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] The let keyword

2013-11-06 Thread Oren Ben-Kiki
I didn't consider that; `pattern := expression` would require infinite
lookahead in the parser, I guess. Good point.

Thanks!

On Wed, Nov 6, 2013 at 8:56 PM, Patrick Walton pcwal...@mozilla.com wrote:

 `let` tells the parser that there's a pattern coming up.

 Languages that do 'x := whatever' can never have destructuring without
 some sort of cover grammar hack.
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Separating heaps from tasks

2013-11-04 Thread Oren Ben-Kiki
ARCs have their place, sure! But letting it leak isn't acceptable in my
case.

Instead, in my use case, no deletes  until the whole heap is released
makes way more sense (heaps are small, grow a bit, and get released). Since
the lifetime of the object becomes == the lifetime of the heap, there's no
issue with cycles. There's only an issue with multiple mutations, which
like I said only needs a bit per pointer (and a non-atomic one at that as
each heap is accessed by one thread - the only thing that gets sent between
tasks is the whole heap!).

So... different use cases, different solutions. ARC is a different
trade-off. I guess the right thing to do would be to implement some
sufficiently smart AppendOnlyHeapT pointer, but this seems hard to do
(same heap can hold objects of multiple types, etc.) so for now I have some
AlmostSafeHeapPointerT instead :-(

Language support for heaps-separate-from-tasks would have solved it (and a
bit more)...


On Mon, Nov 4, 2013 at 8:32 AM, Daniel Micay danielmi...@gmail.com wrote:

 On Mon, Nov 4, 2013 at 1:29 AM, Oren Ben-Kiki o...@ben-kiki.org wrote:

 Even if RC allowed cycles (I don't quite see how...) the whole thing
 wouldn't be send-able, unless one uses ARC. But ARC has even more
 performance penalties than RC... And doing cycle-supporting ARC across
 tasks seems like pushing it - you might as well admit you are doing global
 GC in the 1st place.


 It can't support ownership cycles but it can certainly support cyclic
 links like `std::shared_ptr` + `std::weak_ptr` in C++. The performance
 penalty for supporting sends between tasks is atomic reference counting and
 the price for supporting weak pointers is an extra word per box.

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


Re: [rust-dev] Separating heaps from tasks

2013-11-04 Thread Oren Ben-Kiki
Essentially, yes.


On Mon, Nov 4, 2013 at 11:59 AM, Huon Wilson dbau...@gmail.com wrote:

 On 04/11/13 20:09, Oren Ben-Kiki wrote:

 ARCs have their place, sure! But letting it leak isn't acceptable in my
 case.

 Instead, in my use case, no deletes  until the whole heap is released
 makes way more sense (heaps are small, grow a bit, and get released). Since
 the lifetime of the object becomes == the lifetime of the heap, there's no
 issue with cycles. There's only an issue with multiple mutations, which
 like I said only needs a bit per pointer (and a non-atomic one at that as
 each heap is accessed by one thread - the only thing that gets sent between
 tasks is the whole heap!).

 So... different use cases, different solutions. ARC is a different
 trade-off. I guess the right thing to do would be to implement some
 sufficiently smart AppendOnlyHeapT pointer, but this seems hard to do
 (same heap can hold objects of multiple types, etc.) so for now I have some
 AlmostSafeHeapPointerT instead :-(

 Language support for heaps-separate-from-tasks would have solved it (and
 a bit more)...


 Is this essentially an arena allocator where one can transfer the whole
 arena and all the objects allocated in it into another task?

 ___
 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] Abandoning segmented stacks in Rust

2013-11-04 Thread Oren Ben-Kiki
Note that as memory becomes cheaper and larger there will be more pressure
on 64-bit OS-es to switch to large pages; the number of pages needed to map
several GBs of memory today is already getting out of hand, causing TLB
misses to become a performance issue in some cases - imagine a system with
0.xTBs of memory and it becomes ludicrous.

So playing tricks with MMU and lazy page loading may not work as well as it
does with today's the small 4K page size. Of course, Rust is hardly the
only platform that would be affected :-) and ideally, it would be possible
to have more flexibility than today in choosing which page sizes are used
where in the program's address space... but it remains to be seen how
exactly this would play out.

Just a point to keep in mind...

On Tue, Nov 5, 2013 at 4:21 AM, Brian Anderson bander...@mozilla.comwrote:

 Instead of segmented stacks we're going to rely on the OS and MMU to help
 us map pages lazily. Although the details aren't clear yet, I expect that
 on 64-bit platforms the number of concurrent tasks will be comparable to
 using segmented stacks. On 32-bit platforms, with their limited address
 space, the situation will not be as good, but this is a calculated risk
 that we can live without the same amount of concurrency there.

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


[rust-dev] Separating heaps from tasks

2013-11-03 Thread Oren Ben-Kiki
I am toying with a non-trivial Rust project to get a feel for the language.
There's a pattern I keep seeing in my code which isn't easy to express in
Rust. I wonder what the right thing to do is here.

The pattern is as follows. I have some container, which contains some
components of different types. The container as a whole is send-able . The
components form a complex graph (with cycles).

What I'd like to do is something like this:
- Declare a pool of objects of some types, which is held by the container.
- Declare pointer-to-object whose scope is the container; that is, the
lifetime of the pointer is the lifetime of the container. The pointer can
be freely passed around, cloned, etc. but (for mutable objects), only one
mutable access is allowed at a time.

This calls for something between GC pointers and RC pointers. GC is out,
because it isn't send-able. RC is out, because it doesn't allow for loops.
So right now I use explicit pools and a semi-safe (that is, unsafe...)
smart pointer type. And I don't support dropping objects until the whole
container is done (which is OK in my specific app but isn't really a good
solution).

Ideally what I'd like to see is separating heaps from tasks. That is,
suppose that GC pointers had a heap attribute (like borrowed pointers have
a lifetime attribute). By default, each task has a heap, but it is also
possible to define additional heaps (like we have the static lifetime and
can also define additional lifetimes).

So, the container could hold a heap and then many components with
heap-scoped pointers. The whole thing is send-able and GC is done in the
scope of each heap on its own (like today).

There are implications on the type system (no mixing pointers between
different heaps, unless the heaps are nested) - this seems very similar to
the lifetimes type checking...

Overall this seems very symmetrical with lifetimes. Basically, lifetimes ==
static (compile-time computable) free/malloc; heaps == dynamic (run-time
computable) free/malloc.

One interesting pattern allowed by this is ad-hoc actors (there are others
of course). Currently, if one wants to write actor-style code, one ties in
the GC pointers to one heap of one actor, which means one forces the
parallelization policy to one task per actor. One could argue that the
run-time should be good enough that any aggregation of actor threads to OS
threads would be done optimally (which is a good goal); but in some apps,
to get good performance one would like to control this. If we could
separate heaps from tasks, we could spawn fewer tasks (roughly the number
of OS threads) and use application code to decide which actor runs when and
where (e.g., in combination with thread affinity to ensure better cache
locality).

At any rate - is this something that makes sense in the Rust view?
If so, is there a chance of something like that being added (a completely
separate question :-)?
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Separating heaps from tasks

2013-11-03 Thread Oren Ben-Kiki
Yes, using keys (or indices into a vector) is an option. There are two
problems with this.

It is pretty inefficient; one has to access the pool at any point, which
means doubling the sizes of the pointers (at least), probably more; One
needs a lot of unsafe code to allow mutating the pools; And there's the
issue of keeping multiple pools (one per type)... So it gets complex fast,
though perhaps a sufficiently smart library could still do a good job?



On Mon, Nov 4, 2013 at 8:18 AM, Daniel Micay danielmi...@gmail.com wrote:

 On Mon, Nov 4, 2013 at 1:11 AM, Oren Ben-Kiki o...@ben-kiki.org wrote:

 I am toying with a non-trivial Rust project to get a feel for the
 language. There's a pattern I keep seeing in my code which isn't easy to
 express in Rust. I wonder what the right thing to do is here.

 The pattern is as follows. I have some container, which contains some
 components of different types. The container as a whole is send-able . The
 components form a complex graph (with cycles).


 If there are keys, the path of least resistance is to use a map or a pair
 of maps. Reference counting can allow cyclic links in data structures as
 long as the ownership graph is acyclic, but Rust doesn't offer a type like
 this at the moment.

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


Re: [rust-dev] Separating heaps from tasks

2013-11-03 Thread Oren Ben-Kiki
Even if RC allowed cycles (I don't quite see how...) the whole thing
wouldn't be send-able, unless one uses ARC. But ARC has even more
performance penalties than RC... And doing cycle-supporting ARC across
tasks seems like pushing it - you might as well admit you are doing global
GC in the 1st place.


On Mon, Nov 4, 2013 at 8:20 AM, Patrick Walton pcwal...@mozilla.com wrote:

 On 11/3/13 10:19 PM, Oren Ben-Kiki wrote:

 Because they don't allow cycles.


 Aha. I personally think we should relax this restriction; it's pretty
 onerous.

 Patrick


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


Re: [rust-dev] RFC about std::option and std::result API

2013-11-02 Thread Oren Ben-Kiki
I would love it if '?' was allowed at the end of any identifier, to make it
natural to name boolean variables, methods, constants, etc. Having to say
is_xxx is ugly IMO. A lint option ensuring this is only applied to boolean
typed constructs could help reduce abuse, if this is seen as an issue.
On Nov 2, 2013 8:02 AM, Steve Klabnik st...@steveklabnik.com wrote:

 Would a ruby-style ok?/ok work to replace is_ok/ok?
 ___
 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] This Week in Rust

2013-10-29 Thread Oren Ben-Kiki
Indeed. It is invaluable in helping me decide when to pull a new master and
be prepared for what I need to fix in my code. Many thanks for doing this!


On Tue, Oct 29, 2013 at 10:51 AM, Gaetan gae...@xeberon.net wrote:

 +1 I just subscribed yesterday and I really appreciates this overview :)

 -
 Gaetan



 2013/10/29 Jack Moffitt j...@metajack.im

  I just wanted to thank you for the This Week in Rust notes.  I love
  reading them and I am sure that I am not the only one who appreciates
 the
  effort that you put into each one.

 +1!

 These are great. They are the easiest way for us on the Servo team to
 estimate how much work we'll need to do to upgrade.

 jack.
 ___
 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


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


Re: [rust-dev] recursive types

2013-10-28 Thread Oren Ben-Kiki
I assume the compiler suggests you replace @Expr with RcExpr (Rc is
defined in std::rc). This means you wouldn't be able to create cycles (that
is, expressions must form a tree, or at most a DAG), and that there would
be the overhead of reference counting when you create new expressions,
clone the pointers to them etc.; on the other hand, there wouldn't be any
GC involved.


On Mon, Oct 28, 2013 at 6:40 PM, Ramakrishnan Muthukrishnan 
vu3...@gmail.com wrote:

 Hello rust hackers,

 In section 8.1.7 of the Rust manual (Recursive types), there is an
 example of a List definition which is recursive. Here I define a very
 simple arithmetic expression which consists of numbers and add
 expressions. When I compile it I get errors..

 enum Expr
 {
 Num(int),
 Add(@Expr, @Expr),
 }

 fn eval(e: Expr) - int {
 match e {
 Num(x) = x,
 Add(x, y) = eval(x) + eval(y),
 }
 }

 fn main() {
 println(format!(eval 2 = {:d}, eval(Num(2;
 println(format!(eval 2 + 3 = {:d}, eval(Add(Num(2), Num(3);
 }

 $ rustc arith.rs
 arith.rs:4:8: 4:13 error: The managed box syntax may be replaced by a
 library type, and a garbage collector is not yet implemented. Consider
 using the `std::rc` module as it performs much better as a reference
 counting implementation.
 arith.rs:4 Add(@Expr, @Expr),
^
 arith.rs:4:8: 4:13 note: add #[feature(managed_boxes)] to the crate
 attributes to enable
 arith.rs:4 Add(@Expr, @Expr),
^
 arith.rs:4:15: 4:20 error: The managed box syntax may be replaced by a
 library type, and a garbage collector is not yet implemented. Consider
 using the `std::rc` module as it performs much better as a reference
 counting implementation.
 arith.rs:4 Add(@Expr, @Expr),
   ^
 arith.rs:4:15: 4:20 note: add #[feature(managed_boxes)] to the crate
 attributes to enable
 arith.rs:4 Add(@Expr, @Expr),
   ^
 error: aborting due to 2 previous errors

 I am running rust from master. What exactly is the compiler suggesting
 me to do? How can `std::rc' module help in this situation?

 TIA
 --
   Ramakrishnan
 ___
 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] recursive types

2013-10-28 Thread Oren Ben-Kiki
Right, it would have to be @mut Expr to allow for cycles... and you'd have
to really work hard to construct the cycle. At any rate, this isn't what
you'd want - very probably just using ~Expr would be enough.


On Mon, Oct 28, 2013 at 8:29 PM, Daniel Micay danielmi...@gmail.com wrote:

 On Mon, Oct 28, 2013 at 2:27 PM, Oren Ben-Kiki o...@ben-kiki.org wrote:

 If you use ~Expr instead of @Expr, then the expressions would have to
 form a tree (A = B + C). If you use RcExpr, you could build a DAG (A = B
 + B). With @Expr (if that worked), in principle you could allow for cycles
 (A = B + A), which is probably not what you want.


 You won't actually be able to create cycles with @T unless T is non-Freeze
 because it's immutable and Rust doesn't use laziness.

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


Re: [rust-dev] return type of closure

2013-10-27 Thread Oren Ben-Kiki
Off the top of my head, I'd take out the  in front of the |x|
everywhere, it seems like you are borrowing a pointer out of something that
is already a borrowed pointer to a function (expected , found , you have
one  too many, right? :-).


On Sun, Oct 27, 2013 at 2:15 PM, Ramakrishnan Muthukrishnan 
vu3...@gmail.com wrote:

 I am having a hard time trying to figure out what is going on here.

 fn ntimes(f: fn(int) - int, n: int) - fn(int) - int {
 match n {
 0 = |x| { x },
 _ = |x| { f(x) },
 _ = |x|
 {
 let nf = ntimes(f, n - 1);
 nf(f(x))
 },
 }
 }

 fn double(a: int) - int {
 a * 2
 }

 fn main() {
 let quadruple = ntimes(double, 2);
 println(format!(quad = {:d}, quadruple(2)));
 }

 When I compile it, I get this error message:

 $ rustc --version
 rustc 0.9-pre (950add4 2013-10-26 02:16:08 -0700)
 host: x86_64-apple-darwin

 $ rustc fn1.rs
 fn1.rs:2:4: 10:5 error: mismatched types: expected
 `fnno-bounds(int) - int` but found `fnno-bounds(int) - int`
 (expected fn but found -ptr)
 fn1.rs:2 match n {
 fn1.rs:3 0 = |x| { x },
 fn1.rs:4 _ = |x| { f(x) },
 fn1.rs:5 _ = |x|
 fn1.rs:6 {
 fn1.rs:7 let nf = ntimes(f, n - 1);
  ...
 error: aborting due to previous error
 task 'unnamed' failed at 'explicit failure',
 /Users/rkrishnan/src/rust/src/libsyntax/diagnostic.rs:101
 task 'unnamed' failed at 'explicit failure',
 /Users/rkrishnan/src/rust/src/librustc/rustc.rs:396

 Can someone help me understand what is going on here? I tried omitting
 the return type of ntimes and let compiler try to infer the type. The
 only change is in the first line of the code omitting the return type
 of ntimes. But I then get an error about quadruple function. It says
 that quadruple is a void.

 Thanks.
 --
   Ramakrishnan
 ___
 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] return type of closure

2013-10-27 Thread Oren Ben-Kiki
You got me there...


On Sun, Oct 27, 2013 at 6:04 PM, Ramakrishnan Muthukrishnan 
vu3...@gmail.com wrote:

 On Sun, Oct 27, 2013 at 6:12 PM, Oren Ben-Kiki o...@ben-kiki.org wrote:
  Off the top of my head, I'd take out the  in front of the |x|
  everywhere, it seems like you are borrowing a pointer out of something
 that
  is already a borrowed pointer to a function (expected , found , you
 have
  one  too many, right? :-).

 Yes, I had tried that too but get cannot infer an appropriate
 lifetime due to conflicting requirements errors. Is there some way to
 fix that?

 Ramakrishnan

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


Re: [rust-dev] Trait method self parameter type clashes with lifetime annotation required by the implementation

2013-10-26 Thread Oren Ben-Kiki
This is a good summary of the situation. There's one more twist to it
though; I not only want both ownership and aliasing, I also want
send-ability. That is, it should be possible to send the whole arena to
another task.

I think this rules out option 1 (though I don't know enough about lifetimes
to be sure). It leaves option 2 on the table, though.

The main problem with option 2 is that if one borrows a mutable pointer to
`root.poolOfSomeObjects[someIndex]` then the whole `root` is now considered
to be borrowed-as-mutable, disallowing borrowing a mutable pointer to
`root.poolOfOtherObjects[otherIndex]`. I'm tempted to say that the type
system should be smart enough to allow this, but I'm not 100% certain it
is actually safe to do so without some run-time support.

For now I am going with (3) which is using an UnsafePtr struct and scary
comments :-(


On Fri, Oct 25, 2013 at 7:05 PM, Niko Matsakis n...@alum.mit.edu wrote:

 On Mon, Sep 30, 2013 at 08:10:45PM +0300, Oren Ben-Kiki wrote:
  That's good! But there remains the fact that there's no way to say my
  lifetime is the same as the struct that contains me. If 'self
 specialness
  goes away, perhaps it can be re-introduced to mean that (or a different
  name can be given to it).

 So, I have had this thread on a must read list of e-mails for a while,
 but didn't get around to it until just now. Sorry about that.

 It is true that there is no way to have a lifetime that means as long
 as the current struct -- at least not in a type definition. The
 reason for this is that this is not a well-defined thing; structs can
 be moved, for example. The only place you can get a lifetime like that
 is in a method:

 fn foo'a('a mut self, ...)

 Here, 'a is the lifetime you are looking for (the current lifetime of
 the struct itself).

 We do have a way to express the notion of memory that moves with a
 struct and is freed when the struct is freed: ownership. That's what a
 `~` pointer is for. But of course the `~` pointer is designed for
 recursive ownership and transfers and thus prevents aliasing, which
 may not be what you need.

 Sometimes you want ownership and aliasability: basically you want to
 be able to create a subcomponent tied to a struct that will never
 itself be moved out of the struct into some other container. You can
 imagine doing this by having an arena that moves with the struct, and
 pointers that live as long as that arena. I had originally hoped to
 support this (that was indeed the origin of the 'self name) but it's
 quite complex to do so; that lifetime is a kind of existential
 lifetime and we don't really have a good way to capture it.

 In the meantime, you have two options:

 1. Parameterize the struct with a lifetime, and have it contain the
arena that way. This technique works when there is ultimately some
master stack frame that the struct will not outlive; this master
frame owns the arena, and the struct just borrows it. You can see
an example in this (yet to be landed) code. [1]

 2. Have the struct own a vector or other data structure, and replace
pointers with indices. This works best when the struct will be
moved around. You can see an example in this Graph data
structure. [2]

 While I know that neither technique feels perfect, they are quite
 workable, and I have used both with much rejoicing.



 Niko

 [1] https://gist.github.com/nikomatsakis/7157110
 [2]
 https://github.com/mozilla/rust/blob/master/src/librustc/middle/graph.rs

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


[rust-dev] What does `once fn` mean?

2013-10-21 Thread Oren Ben-Kiki
I have code which (greatly simplified) boiled down to:

```
fn attempt_1T(action: fn() - T) - T {
action()
}

fn call_attempt_1() - ~str {
let mut index = 0;
let string = ~str;
do attempt_1 {
// No problem here. We have a stack closure.
index += 1;
// Error: cannot move out of captured outer variable
// Makes sense. Compiler can't tell the action will only be invoked
// once.
string
}
}
```

So, I heard there are things called `once fn`, which seem to be what I
need. Even though the compiler warned me away from them, I thought I'd give
them a try in the spirit of investigation:

```
fn attempt_2T(action: once fn() - T) - T {
action()
}

fn call_attempt_2() - ~str {
let mut index = 0;
let string = ~str;
do attempt_2 {
// Error: cannot assign to immutable captured outer variable in a
heap closure
// It seems that `once fn` is a _heap_ closure? Makes no sense...
It
// would have made sense if it was an `~once fn`, but there's no way
// that `action_2` should be able to store somewhere a reference to
an
// `once fn`, so a stack closure should be fine!
index += 1;
string
}
}
```

So, obviously `once fn` doesn't do what I expected it to do, which is to
simply assert this fn is only called once. It seems it does that but also
carries some extra baggage of also saying force me to be a heap closure.
It isn't clear to me _why_ these two should be conflated - after all, one
could just say `~once fn` if one wanted a heap closure. Can someone
enlighten me on this?

At any rate, I then resorted to:

```
fn attempt_2T(action: fn() - T) - T {
action()
}

fn call_attempt_2() - ~str {
let mut index = 0;
let string = ~str;
let string_cell = Cell::new(string);
do attempt_1 {
// No problem here. We have a stack closure.
index += 1;
// Dynamic assertion that the action is only invoked once. Costs in
// both extra ugly source code lines and in run-time overhead.
string_cell.take()
}
}
```

So, this works, but boy is it ugly, not to mention inefficient Can someone
suggest a better way to achieve this, and shed some light on the status of
the `once fn` construct in general?

Thanks,

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


Re: [rust-dev] Strange behavior about Writer trait

2013-10-20 Thread Oren Ben-Kiki
I'm not sure I follow.

Assuming that the trait `T` has no method that uses `Self`, then any `impl`
requiring `T` should happily accept an `T` / `@T`. Why penalize
non-self-referential traits (like `Writer`), just because some traits (like
`AdderIncr`) are self-referential?

On Sun, Oct 20, 2013 at 1:10 AM, Steven Blenkinsop steven...@gmail.comwrote:

 Consider this program:

 
 trait AdderIncr {
 fn add(self, x: Self) - Self;
 fn incr(mut self);
 }

 impl AdderIncr for int {
 fn add(self, x: int) - int { *self + x }
 fn incr(mut self) { *self += 1; }
 }

 fn incrAdd(x: mut AdderIncr, y: mut AdderIncr) {
 x.incr();
 x.add(y);
 }

 fn main() {}
 

 It fails to compile:

 
 Documents/test.rs:13:1: 13:10 error: cannot call a method whose type
 contains a self-type through an object
 Documents/test.rs:13x.add(y);
 ^
 

 The Self type is meaningless in object methods, since I have no way to
 ensure that y has the same underlying type as x. Thus, only a subset of the
 methods of a trait are available on the corresponding object, which means
 that objects can't automatically implement their corresponding trait.

 That means any impls that implement a trait for all types that implement
 AdderIncr, for example, won't implement that trait for AdderIncr, since
 AdderIncr doesn't implement AdderIncr.

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


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

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

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

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

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



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

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

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

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

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

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


[rust-dev] Strange behavior about Writer trait

2013-10-19 Thread Oren Ben-Kiki
I run into the following problem (the code below is a toy example).

```
use std::io::Writer; // Makes no difference if added/removed.

trait PrintWithSpice {
fn print(self, writer: Writer, spice: bool);
}

struct Bar {
bar: ~PrintWithSpice,
}

impl Bar {
pub fn print(self, writer: Writer) {
self.bar.print(writer, false);
Bar::print_via_borrowed(writer, self.bar);
}

fn print_via_borrowed(writer: Writer, data: PrintWithSpice) {
// Invoking the `print` function via the borrowed pointer to the
`PrintWithSpice` trait:
// Works fine, as expected..
data.print(writer, true);
}
}

struct Foo {
foo: bool
}

impl PrintWithSpice for Foo {
fn print(self, writer: Writer, spice: bool) {
// Invoking the `write_str` function via the borrowed pointer to
the `Writer` trait:
// error: failed to find an implementation of trait std::io::Writer
for std::io::Writerno-bounds
// What is going on?
writer.write_str(format!(foo: {:b} spice: {:b}, self.foo, spice));
}
}
```

I didn't understand what the compiler is complaining about. failed to find
an implementation of Foo for Foono-bounds? A Foo is a Foo, no? Calling
a function via a borrowed pointer to a trait should just work (it does a
few lines above).

After digging I discovered what the compiler really meant (I think). The
`write_str` method is defined for `WriterUtils` rather than for `Writer`.
So, if I replace `Writer` by `WriterUtil` in the above code, it compiles
fine.

So, I ended up defining `trait MyWriter: Writer + WriterUtil` and I am
using that instead of `Writer` all over my code. I can see doing that as a
workaround, but it doesn't smell right to me.

So:

* Why is the compiler complaining about not finding an implementation for
`Writer` when the method I invoke is from `WriterUtil`?

* Since there is an `implT: Writer for WriterUtil`, shouldn't the
compiler be sufficiently smart to deduce that the code is valid in the
1st place?

* Until the compiler is sufficiently smart (or, if there is a good reason
why it would never be), shouldn't we rename `Writer` to `BasicWriter` and
define `trait Writer: BasicWriter, WriterUtil {}` so `Writer` would become
more usable?
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Strange behavior about Writer trait

2013-10-19 Thread Oren Ben-Kiki
Ugh, I was too optimistic. Yes, I can write my code using `MyWriter`, but I
can't cast any @Writer (such as `io::stdout()`) to it. I guess I should
just use `@Writer` everywhere for now :-(

This raises the question of how come the compiler is smart enough to figure
out a `@Writer` has the trait `WriterUtil`, but isn't smart enough to
figure out a `Writer` has the trait...


On Sat, Oct 19, 2013 at 9:08 AM, Oren Ben-Kiki o...@ben-kiki.org wrote:

 I run into the following problem (the code below is a toy example).

 ```
 use std::io::Writer; // Makes no difference if added/removed.

 trait PrintWithSpice {
 fn print(self, writer: Writer, spice: bool);
 }

 struct Bar {
 bar: ~PrintWithSpice,
 }

 impl Bar {
 pub fn print(self, writer: Writer) {
 self.bar.print(writer, false);
 Bar::print_via_borrowed(writer, self.bar);
 }

 fn print_via_borrowed(writer: Writer, data: PrintWithSpice) {
 // Invoking the `print` function via the borrowed pointer to the
 `PrintWithSpice` trait:
 // Works fine, as expected..
 data.print(writer, true);
 }
 }

 struct Foo {
 foo: bool
 }

 impl PrintWithSpice for Foo {
 fn print(self, writer: Writer, spice: bool) {
 // Invoking the `write_str` function via the borrowed pointer to
 the `Writer` trait:
 // error: failed to find an implementation of trait
 std::io::Writer for std::io::Writerno-bounds
 // What is going on?
 writer.write_str(format!(foo: {:b} spice: {:b}, self.foo,
 spice));
 }
 }
 ```

 I didn't understand what the compiler is complaining about. failed to
 find an implementation of Foo for Foono-bounds? A Foo is a Foo, no?
 Calling a function via a borrowed pointer to a trait should just work (it
 does a few lines above).

 After digging I discovered what the compiler really meant (I think). The
 `write_str` method is defined for `WriterUtils` rather than for `Writer`.
 So, if I replace `Writer` by `WriterUtil` in the above code, it compiles
 fine.

 So, I ended up defining `trait MyWriter: Writer + WriterUtil` and I am
 using that instead of `Writer` all over my code. I can see doing that as a
 workaround, but it doesn't smell right to me.

 So:

 * Why is the compiler complaining about not finding an implementation for
 `Writer` when the method I invoke is from `WriterUtil`?

 * Since there is an `implT: Writer for WriterUtil`, shouldn't the
 compiler be sufficiently smart to deduce that the code is valid in the
 1st place?

 * Until the compiler is sufficiently smart (or, if there is a good
 reason why it would never be), shouldn't we rename `Writer` to
 `BasicWriter` and define `trait Writer: BasicWriter, WriterUtil {}` so
 `Writer` would become more usable?

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


Re: [rust-dev] Strange behavior about Writer trait

2013-10-19 Thread Oren Ben-Kiki
Hmmm That sounds strange. Shouldn't `obj: T` allow me to invoke
`obj.method_of_T()`?

For example, how did I manage to invoke the `data.print(...)` method via
the borrowed `data: PrintWithSpice` pointer? Automatic dereference? And if
so, why didn't it work for `Writer` as well?

On Sat, Oct 19, 2013 at 9:29 AM, Steven Fackler sfack...@gmail.com wrote:

 If T is a trait, its trait objects ~T, @T and T do not implement T. There
 is an implementation of Writer for @Writer, but not for ~Writer or Writer
 which is why you're seeing that error.

 Steven Fackler


 On Fri, Oct 18, 2013 at 11:27 PM, Oren Ben-Kiki o...@ben-kiki.org wrote:

 Ugh, I was too optimistic. Yes, I can write my code using `MyWriter`, but
 I can't cast any @Writer (such as `io::stdout()`) to it. I guess I should
 just use `@Writer` everywhere for now :-(

 This raises the question of how come the compiler is smart enough to
 figure out a `@Writer` has the trait `WriterUtil`, but isn't smart enough
 to figure out a `Writer` has the trait...


 On Sat, Oct 19, 2013 at 9:08 AM, Oren Ben-Kiki o...@ben-kiki.org wrote:

 I run into the following problem (the code below is a toy example).

 ```
 use std::io::Writer; // Makes no difference if added/removed.

 trait PrintWithSpice {
 fn print(self, writer: Writer, spice: bool);
 }

 struct Bar {
 bar: ~PrintWithSpice,
 }

 impl Bar {
 pub fn print(self, writer: Writer) {
 self.bar.print(writer, false);
 Bar::print_via_borrowed(writer, self.bar);
 }

 fn print_via_borrowed(writer: Writer, data: PrintWithSpice) {
 // Invoking the `print` function via the borrowed pointer to the
 `PrintWithSpice` trait:
 // Works fine, as expected..
 data.print(writer, true);
 }
 }

 struct Foo {
 foo: bool
 }

 impl PrintWithSpice for Foo {
 fn print(self, writer: Writer, spice: bool) {
 // Invoking the `write_str` function via the borrowed pointer to
 the `Writer` trait:
 // error: failed to find an implementation of trait
 std::io::Writer for std::io::Writerno-bounds
 // What is going on?
 writer.write_str(format!(foo: {:b} spice: {:b}, self.foo,
 spice));
 }
 }
 ```

 I didn't understand what the compiler is complaining about. failed to
 find an implementation of Foo for Foono-bounds? A Foo is a Foo, no?
 Calling a function via a borrowed pointer to a trait should just work (it
 does a few lines above).

 After digging I discovered what the compiler really meant (I think). The
 `write_str` method is defined for `WriterUtils` rather than for `Writer`.
 So, if I replace `Writer` by `WriterUtil` in the above code, it compiles
 fine.

 So, I ended up defining `trait MyWriter: Writer + WriterUtil` and I am
 using that instead of `Writer` all over my code. I can see doing that as a
 workaround, but it doesn't smell right to me.

 So:

 * Why is the compiler complaining about not finding an implementation
 for `Writer` when the method I invoke is from `WriterUtil`?

 * Since there is an `implT: Writer for WriterUtil`, shouldn't the
 compiler be sufficiently smart to deduce that the code is valid in the
 1st place?

 * Until the compiler is sufficiently smart (or, if there is a good
 reason why it would never be), shouldn't we rename `Writer` to
 `BasicWriter` and define `trait Writer: BasicWriter, WriterUtil {}` so
 `Writer` would become more usable?



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



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


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

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

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

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

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

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

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


Re: [rust-dev] Proposal for macro invocation sugar

2013-10-17 Thread Oren Ben-Kiki
That does make sense. Well, this still leaves the `foo!!` proposal as
viable, and a possible solution for
https://github.com/mozilla/rust/issues/9358 - so, +1 for that.

On Thu, Oct 17, 2013 at 9:29 AM, Marvin Löbel loebel.mar...@gmail.comwrote:

  As I understand it, there is a high incentive to have macros be
 tokenizable and parseable without needing to expand them - it's a
 necessarily if we ever want importable macros (Can't resolve macro imports
 if you can't parse the source).
 Hence the requirement to have explicit brackets and the need to have
 properly nested and paired brackets in them.


 On 10/17/2013 06:30 AM, Oren Ben-Kiki wrote:

 In general I'd favor anything that would help with
 https://github.com/mozilla/rust/issues/9358 - that is, allow more
 eDSL-ish macros. Writing `foo!!(...) { ... }` has the cost of the extra `!`
 but that really isn't too bad.

  That said, I wonder why do macro invocations require the outer set of
 parenthesis? Since a macro is expressed in terms of parser rules
 (expressions, identifiers, tokens, etc.), isn't it unambiguous to allow
 macros to be invoked without the outer `()`? E.g.:

  macro_rules! foo (
 (bar: $expr :: baz: $expr) = ...,
 )

  Today, one would use it as in `f(foo!(1 :: 2), 3)`. But suppose one
 could somehow indicate the outer `()` were never to be used for this macro
 (say writing `syntax_rules!` instead of `macro_rules!`, or by some other
 extension of the `macro_rules!` notation), then parsing `f(foo! 1 :: 2,
 3)` would be unambiguous - assuming we (1) strictly use greedy parsing of
 $expr etc. and (2) always expand a later macro before parsing and expanding
 earlier macros, where later and earlier are in source text order. This
 strategy makes irrelevant the issue of determining the nesting of such
 macros while doing the right thing with a simple deterministic rule.

  This would probably be more complex to implement than the multiple-`!`
 proposal, but would allow for more generic patterns. For example, allowing
 to omit the outer `()` would allow invoking `my_match! pattern = action`;
 if I understand it correctly, using `!!` would only allow for writing
 `my_match!! pattern action`.

  At any rate, this is just as an idea - like I said, I'd like anything
 that would allow me to write `foo!(...) { ... }` (or `foo!!(...) { ... }`,
 or something along these lines). Writing `foo!(..., { ... })` just seems
 ugly to me...


 On Thu, Oct 17, 2013 at 2:10 AM, Marvin Löbel loebel.mar...@gmail.comwrote:

 Hello! I was thinking a bit about macros, and I had an idea for a kind of
 syntactic sugar that might be useful to have. I also posted this to the
 issue tracker at https://github.com/mozilla/rust/issues/9894.

 # Current situation

 Right now, rust knows about two kinds of macro invocation:

 IDENT!(...)
 IDENT! IDENT (...)

 The latter one is just used by `macro_rules!` right now, and seems kinda
 out of place because of that.

 Additionally, just being restricted to `IDENT!(...)` means that, while
 you can define macros just fine, the resulting invocation syntax often
 looks a bit weird because of the need for the outer `()` pair.

 For example, if you want to write some kind of custom `match` macro you
 ideally want a syntax like `macro! EXPR { CASES... }`, but in practice are
 forced to decide between redundant, deeply nested brackets or weird syntax
 if you want to reduce the brackets:

 ~~~
 my_match!(
 foo().bar().baz() {
 case 1 = ...
 case 2 = ...
 ...
 }
 )

 my_match!(foo().bar().baz() cases:
 case 1 = ...
 case 2 = ...
 ...
 )
 ~~~

 # Proposal

 We can't just allow macros to accept different syntax like `IDENT! EXPR (
 ... )`, because it would create ambiguity in the parser, but it occurred to
 me that we _can_ provide syntactic sugar for transforming 'nicer looking'
 variants into the regular `IDENT!(...)` syntax.

 Basically, I'm thinking of leveraging the bang in a macro invocation to
 annotate how many following bracket pairs to group into one regular macro
 invocation:

 ~~~
 IDENT!! (...) (...) = desugaring = IDENT!((...) (...))
 IDENT!!! (...) (...) (...)  = desugaring = IDENT!((...) (...) (...))
 ... etc
 ~~~

 The number of bangs could become confusing fast, but I don't expect that
 macros with more than two bracket groups are going to be common. And
 because it would just be sugar, you could always write it as the regular
 form.

 # Advantages

 There are a number of advantages I see with this proposal:

 1. The two macro invocation forms can be folded into one:
~~~
IDENT!(...)= IDENT!(...)
IDENT! IDENT (...) = IDENT!! (IDENT) (...) == IDENT!((IDENT) (...))
~~~

 2. Custom syntax can become nicer looking, especially for control
 structures.
Looking at the `my_match` example:
~~~
my_match!! (foo().bar().baz()) {
case 1 = ...
case 2 = ...
...
}
~~~
... which looks more natural than any

Re: [rust-dev] what is stable, what is likely to change, in Rust

2013-10-02 Thread Oren Ben-Kiki
Is there any published roadmap for the reasonable time frame? The last
quotes I saw when searching were ancient and optimistically hoped that Rust
will hit 1.0 by the end of this year :-). Is there a goal of reaching 1.0
at some rough time frame or is Rust going for it will be done when it is
done? I'm not pushing for either, they both have their dis/advantages -
but it would be nice to be explicit about it either way.

On Wed, Oct 2, 2013 at 8:10 PM, Alex Crichton a...@crichton.co wrote:

 It is my understanding that there aren't a whole lot of portions of
 the libraries/compiler which are 100% guaranteed to not change from
 here on out. There are still fairly large language changes in flight
 (dynamically sized types, closure reform, etc.) which could have large
 impacts on how the language is used.

 In addition to a the language stabilizing, there's also the factor of
 libraries stabilizing. Huon's recent work on adding stability
 attributes is a fantastic step in this direction though. As Rust moves
 forward, the general strategy for us is to first enforce usage of the
 stability attributes to prevent regressions in terms of stability
 (stable functions calling unstable ones, etc.). After these safeguards
 are in place, the plan is to closely scrutinize the core modules of
 libstd. From the inside out, interfaces will be pruned/refactored and
 flagged as #[stable]. Once an interface is #[stable], the idea is to
 be very reluctant to accept modifications to existing functions, and
 functions/modules flagged as such can be thought of as being
 backwards compatible for the time being at least.

 That being said, I've got a fairly large side project which has been
 compiling just fine (without modifications) for nearly a month now
 which is truly a record for rust. The rate of change in the language
 is far less than it used to be, and library APIs are settling down a
 little but, but they're still predominately in flux. As usual, Rust is
 not currently in a backwards compatible state for nearly its entire
 surface area (except for maybe the program fn main() {}), but it's
 certainly a major goal to achieve this within a reasonable time frame.
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


[rust-dev] The new format!

2013-10-01 Thread Oren Ben-Kiki
I just transitioned my code to use the new format! macros. I was happy to
get rid of all the .to_str() I had all over the place, but this turned out
not quite as I had expected.

I was hoping I'd be able to simply base on the ToStr trait to print
anything with {:s}. It turns out that actually there's a String trait with
an fmt function - Ok, that makes sense, as one can emit stuff piecewise
without having to pay the costs of creating an intermediate complete string.

But it turns out that the standard library hard-wires the implementation of
the String trait to use the Str trait, which has two functions - to_owned
and as_slice. I understand the motivation of as_slice for more efficient
formatting (though I don't see why it needs to provide to_owned, but
anyway). Ok, just a bit more boilerplate, I thought - but then I hit a wall.

The as_slice function requires returning a borrowed pointer whose lifetime
is specified by the caller. If my type has to_str which returns a ~str, I
can't really return a borrowed pointer to it (as the ~str will live too
short).

This problem is unique to the String trait. All the other traits (Bool,
Pointer, ...) just allow specifying the trait directly without getting too
clever with string slices. So... I cheated and added a LowerHex instance my
types instead of String (which conflicts with libstd) or Str (which I can't
implement). I now print my types with {:x} (I think of it as user eXtended
format).

I know, this is pretty horrible... what is the right thing here? Using
{:s} and keep calling .to_str() everywhere?

A second, related problem, is formatting simple enums. It is easy to derive
ToStr for such enums, but this means I still need to say {:s} and
my_enum.to_str() - exactly what I hoped to avoid. And I really don't want
to manually specify a LowerHex or Str instance to each and every enum (it
is bad enough I need to do it for each of the relevant small-struct types).

If there was a, say, {:S} that was automatically available for everything
that had ToStr, then both problems would have been solved. {:s} would
remain a more efficient way to format things that were actually strings,
while {:S} would allow formatting things that could be viewed as strings.

Does that make sense?
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] The new format!

2013-10-01 Thread Oren Ben-Kiki
Ah, so simple. I missed it because it is not listed in the formatting
traits list in the documentation.

This would solve half my problem - I'd no longer need to use {:x} but use
the simpler {}, which is great. Thanks!

But it wouldn't solve the problem for printing enums, though. I guess I'd
still have to litter my code with lots of .to_str() when printing them :-(


On Tue, Oct 1, 2013 at 9:12 AM, Huon Wilson dbau...@gmail.com wrote:

 On 01/10/13 16:13, Oren Ben-Kiki wrote:


 This problem is unique to the String trait. All the other traits (Bool,
 Pointer, ...) just allow specifying the trait directly without getting too
 clever with string slices. So... I cheated and added a LowerHex instance my
 types instead of String (which conflicts with libstd) or Str (which I can't
 implement). I now print my types with {:x} (I think of it as user eXtended
 format).

 I know, this is pretty horrible... what is the right thing here? Using
 {:s} and keep calling .to_str() everywhere?


 There's std::fmt::Default, which corresponds to having no format specifier
 (e.g. {} or {:10} or {a}, etc).


 Huon
 __**_
 Rust-dev mailing list
 Rust-dev@mozilla.org
 https://mail.mozilla.org/**listinfo/rust-devhttps://mail.mozilla.org/listinfo/rust-dev

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


Re: [rust-dev] The new format!

2013-10-01 Thread Oren Ben-Kiki
Perhaps if the type system was smart enough to provide a default
implementation of the Default trait for everything that had the ToStr
trait, and allowing overrides for specific types?

I know that currently this sort of inference is not supported, but it is
intended that it would be possible in the future, right?


On Tue, Oct 1, 2013 at 9:24 AM, Oren Ben-Kiki o...@ben-kiki.org wrote:

 Ah, so simple. I missed it because it is not listed in the formatting
 traits list in the documentation.

 This would solve half my problem - I'd no longer need to use {:x} but use
 the simpler {}, which is great. Thanks!

 But it wouldn't solve the problem for printing enums, though. I guess I'd
 still have to litter my code with lots of .to_str() when printing them :-(


 On Tue, Oct 1, 2013 at 9:12 AM, Huon Wilson dbau...@gmail.com wrote:

 On 01/10/13 16:13, Oren Ben-Kiki wrote:


 This problem is unique to the String trait. All the other traits (Bool,
 Pointer, ...) just allow specifying the trait directly without getting too
 clever with string slices. So... I cheated and added a LowerHex instance my
 types instead of String (which conflicts with libstd) or Str (which I can't
 implement). I now print my types with {:x} (I think of it as user eXtended
 format).

 I know, this is pretty horrible... what is the right thing here? Using
 {:s} and keep calling .to_str() everywhere?


 There's std::fmt::Default, which corresponds to having no format
 specifier (e.g. {} or {:10} or {a}, etc).


 Huon
 __**_
 Rust-dev mailing list
 Rust-dev@mozilla.org
 https://mail.mozilla.org/**listinfo/rust-devhttps://mail.mozilla.org/listinfo/rust-dev



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


Re: [rust-dev] The new format!

2013-10-01 Thread Oren Ben-Kiki
Yes, both suggestions sound very reasonable. It would also eliminate the
need for the Str trait altogether (since the Default fmt function would
avoid the allocation). So there would really be no need for most format
specifiers, except stuff like controlling the base of integers, etc.


On Tue, Oct 1, 2013 at 9:30 AM, Huon Wilson dbau...@gmail.com wrote:

 I think we should just replace ToStr and the #[deriving] with Default and
 a default method .to_str() on that trait, since ToStr's current design
 makes it very allocation-heavy (it has to allocate a new ~str for each
 subfield, rather than just appending to a common buffer as using the new
 format infrastructure would allow).


 Also, not directly related to this exact discussion, but we could probably
 cope with having fewer format specifiers, e.g. format!({:b}, true) could
 just be format!({}, true), and similarly for `c`. (and even `s` itself!)


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


Re: [rust-dev] Trait method self parameter type clashes with lifetime annotation required by the implementation

2013-09-30 Thread Oren Ben-Kiki
Huh, this is _exactly_ my use case. I have data structures which I grow but
never shrink, and I never move anything out of them. This idiom isn't that
uncommon when writing in functional style...

I incrementally build a complex structure that allows quick access to the
same pieces using different criteria (e.g., access a piece by a unique id,
or look it up by a path, or via a direct pointer held by a related piece,
etc.). All accesses are of (possibly mutable) borrowed pointers that live
as long as the whole thing exist. Then when done I can discard the whole
thing.

Sometimes I have a less-complex structure to which I attach a related
view structure. The view holds borrowed pointers to pieces of the
original immutable structure, allowing efficient access in new and
interesting ways. When done I can then discard the view and keep the
original.

So basically, I want something that gives me the freedoms granted to
'static, but only for as long as the main structure provably exists.
Something like 'shadow :-)

I found Rust doesn't like these idioms at all. I some cases, where I was
too tired, performance wasn't an issue, and there was no need to send the
whole thing between tasks, I just used @ pointers. Otherwise, I used RcMut,
though this incurs boilerplate access code and hurts performance for no
real reason. In critical cases I may end up using unsafe pointers...

Using a macro - hmm. Interesting and if possible, would be a great
solution. I'm not certain what such a macro would expand to, though. It
would need to be something that would express the concept of I live only
as long as my container structure _somehow_, and I thought we established
that can't be done...

Thanks,

Oren.

On Mon, Sep 30, 2013 at 4:26 AM, Steven Blenkinsop steven...@gmail.comwrote:

 Yeah, I was trying to come up with a design a while ago to allow
 intrastructural borrowed pointers, and basically the effect this had was
 that you could never move anything out of the datastructure since that
 would leave dangling pointers. Which means you could grow the structure but
 never shrink it, which is sort of not good.

 Now my thought is about whether it would be possible to make a macro which
 allows you to define a safely encapsulated smart node which ensures that
 any intrastructural references meet certain invariants about where they
 point within the structure, but I haven't developed the idea enough to say
 whether you could make something truly general this way.


 On Sun, Sep 29, 2013 at 7:28 PM, Steven Fackler 
 sfack...@andrew.cmu.eduwrote:

 Foo can't really be used safely. Say that we have

 struct Bar {
 baz: BazPartOfBar
 }

 struct Foo {
 bar: Bar,
 baz: 'magic BazPartOfBar
 }

 And let's say we add a `self` syntax to allow field initializers to refer
 to other fields:

 let foo = Foo {
 bar: Bar {
 baz: BazPartOfBar
 },
 baz: self.bar.baz
 };

 We can't really do much with Foo. If we move it, foo.baz is no longer a
 valid reference, so that can't happen. We could modify foo.bar in this
 case, but not if Bar were defined as

 struct Bar {
 baz: ~BazPartOfBar
 }

 since foo.baz would point to deallocated memory if we replace self.bar or
 self.bar.baz.

 Steven Fackler


 On Sun, Sep 29, 2013 at 3:15 PM, Tim Kuehn tku...@cmu.edu wrote:

 Could you use struct methods for quick access? Or is there a reason
 this wouldn't fit your use case? Sorry, I haven't followed the whole thread
 closely.

 struct Owner {
 owned: ~[int],
 }

 impl Owner {
 fn quick_access'a('a mut self) - 'a mut int {
 mut self.owned[0]
 }
 }


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


Re: [rust-dev] Trait method self parameter type clashes with lifetime annotation required by the implementation

2013-09-30 Thread Oren Ben-Kiki
I see what you mean about the macro - it would get quite complex though.

Regardless of macros, neat extensions with GC heaps and arenas and so on...

I still find it surprising that it is flat-out impossible to explicitly
name the default lifetime of a struct, and also that the natural name for
this lifetime ('self) is used for an entirely different purpose.

It would be nice if we could rename the existing 'self to something
(anything :-) else, and allow 'self to be used in struct field types and
elsewhere for the more natural (and currently unavailable) lifetime of the
current struct. Yes, this comes with some limitations, but it is useful
for some interesting cases and its lack of an explicit name seems arbitrary
(it is the default in many cases, after all).

At any rate, I now have a better grasp of what is going on, so I have a
better chance of writing code that actually works :-)

Thanks for the explanations!


On Mon, Sep 30, 2013 at 5:34 PM, Steven Blenkinsop steven...@gmail.comwrote:

 On Monday, 30 September 2013, Oren Ben-Kiki wrote:

 Yes, it is very much like an arena... And yes, the idea is that all the
 pointers are contained in it, so the ~arena as a whole should be safe to
 send, but that contradicts using @ - maybe it could be re-written using
 Rc... hmmm. At any rate, thanks for the pointer - I wasn't aware of arenas
 before.

 Another hmmm... An arena sounds a lot like a weak version of a GC-ed
 heap... So here's a thought: What if @ pointers had a heap associated with
 them, just like  pointers have a lifetime? We have the task-global @ heap,
 and we have the static  lifetime... but we can explicitly manage 
 lifetimes - how about if we could explicitly create a new Gc-heap use it to
 happily muck about with @'my-heap pointers (which would be statically
 prevented from being mixed with @'other-heap pointers), and be able to send
 the whole heap between tasks, etc.? (Not that I necessarily suggest @'heap
 as a syntax, but you get the idea)

 Gc would still run in the context of one heap at a time... but this would
 remove the restriction of one task = one heap.


 This would be neat, yes. In this case, accessing such a heap would be
 conceptually identical to temporarily joining a task, except without the
 overhead of having to schedule it, since it would have no independently
 executing code. Figuring out how to hook it into the GC would be a neat
 trick...

 As for what a macro would expand to, I was thinking more that it would
 expand to the containing structure and some smart references that use
 lifetimes to ensure that the containing structure is pinned during their
 existence and that they don't outlive it. You'd have to interact with it
 using methods which make sure you can't break any of the invariants, such
 as aliasing something and then trying to freeze it. To what extent you
 could do this statically rather than dynamically, I'm not sure, but
 lifetimes are a fairly powerful concept, so it's plausible one could work
 something out. Doing it dynamically would basically mean using Cells
 modified to have lifetimes as the smart references into the structure. It
 would be nice to have a version of the smart references that ensured you
 didn't externally alias something which is also externally mutable, though.

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


Re: [rust-dev] Trait method self parameter type clashes with lifetime annotation required by the implementation

2013-09-30 Thread Oren Ben-Kiki
That's good! But there remains the fact that there's no way to say my
lifetime is the same as the struct that contains me. If 'self specialness
goes away, perhaps it can be re-introduced to mean that (or a different
name can be given to it).


On Mon, Sep 30, 2013 at 7:01 PM, Benjamin Striegel
ben.strie...@gmail.comwrote:

 I've only skimmed this conversation, but note that the specialness of
 the 'self lifetime will be going away in the future.

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


Re: [rust-dev] Trait method self parameter type clashes with lifetime annotation required by the implementation

2013-09-29 Thread Oren Ben-Kiki
Ok, color me confused... perhaps there's somewhere that explains 'self on
more detail? For example, _why_ does the example below not work without the
explicit 'self? It seems like it should.

I have yet to truly understand the whole 'self thing. When I first read
about lifetimes, my naive expectations were that:

- Every struct has a 'self lifetime, which is basically as long as this
struct exists. It doesn't matter if I have a @ of the struct or a ~ of the
struct or just a local variable with the struct... when the struct is
dropped, the lifetime ends.

- It follows there's no need to ever annotate structs as generic with a
'self parameter - it always exists.

- Any  in a struct is either 'self or 'static. A simple  should be
'self as that makes more sense (but if Rust wants me to be explicit, fine).

This were my least surprise expectations, but things don't work this
way... the problem is I don't have a simple mental model to replace the
above with, so I struggle. What _is_ 'self, exactly?

Isn't a function fn foo(self) - T the same as returning a 'self T? Why
would I want to say fn foo'a('a self) in the 1st place - 'a is by
definition the same as 'self? How come David's Foo example fails the
borrow check?

Besides failing (my) least surprise expectations, the current rules also
seem to be a leaky abstraction. If I have a struct that holds a ComplexT
member, it needs no 'self parameter. If I then add a private member to my
struct to hold some 'self PartOfT (say, cached access to an internal
member), then boom, all uses of my struct now have to say 'self, I can no
longer put it in thread-local-storage, etc. I'd expect keeping these sort
of cached borrowed pointers should be an internal implementation detail
which does not affect the users of the struct at all.

I suppose there's a good reason for all this, and a reasonable mental model
I need to put in my head, but digging around the docs I didn't find one...
Any hints would be appreciated :-)


On Sun, Sep 29, 2013 at 5:42 PM, David Renshaw dwrens...@gmail.com wrote:

 Cool! I think that solution is much better than mine.

  But I
  think that polluting traits-interfaces with lifetime annotation is
  wrong. Why the trait should have lifetime annotation? It is
  implementation detail.

 Just in case you want to see a case where it *does* make sense to put
 a 'self lifetime in a trait definition, here is an example:

 https://gist.github.com/dwrensha/db919b8e130e9eb72f0f
 ___
 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] Trait method self parameter type clashes with lifetime annotation required by the implementation

2013-09-29 Thread Oren Ben-Kiki
Thanks for the explanation. You said two key points:
- Basically, every object has a lifetime - from its creation to its
destruction - but a lifetime parameter or argument typically refers to the
lifetime of something else, which the object itself must not or does not
outlive.
And:
- 'self is not special in any way, except that the compiler has historical
baggage such that 'self is the only name it lets you use for a lifetime
parameter on a struct.

So, 'self is indeed very far from what I thought (hoped) it would be.

Taking these together, do I read this right as saying there is no way
whatsoever to say:

struct Foo {
bar: Bar,
baz: 'i-live-as-long-as-the-foo-struct-and-no-more BazPartOfBar,
}

When writing a non-trivial container, I found several user cases to be
extremely problematic. One was the above; a container held a spine or
master or owned or whatever-you-want-to-call-it data structure(s), plus
borrowed pointers that only live as long as the container and allow quick
access to specific parts of it.

Is this impossible in Rust (barring use of @ or unsafe pointers)?


On Sun, Sep 29, 2013 at 8:24 PM, Gábor Lehel illiss...@gmail.com wrote:

 'self is not special in any way, except that the compiler has historical
 baggage such that 'self is the only name it lets you use for a lifetime
 parameter on a struct. But that's a bug. In the ideal platonic Rust in the
 sky, you can have any number of lifetime parameters on a struct with
 whatever names you prefer.

 The way I've found to think about lifetimes is that if you have:

 r_int: 'a int

 then 'a refers to a span of time (a scope, a lifetime) such that
 lifetime_of(r_int) = 'a = lifetime_of(*r_int). (Where *r_int is intended
 metaphorically to refer to the original object r_int was created from, not
 the result of the *r_int expression itself.) So 'a is a kind of stand
 between to ensure that r_int does not outlive the object it refers to.

 If you have

 fn foo'a(r_int: 'a int) - 'a int

 then just like any other generics argument, the lifetime 'a is chosen by
 the caller of `foo` (as inferred by the compiler). Typically the caller
 will have an int object (i: int), then borrow a reference to it (r_int: 'a
 int = i) which it passes to `foo`, and then 'a will be the lifetime of the
 int. `foo` will then have to return a reference to (an int that lives at
 least as long). In practice this could either be the r_int it got as
 argument, or a static int.

 `fn foo(arg: int)` is shorthand for an anonymous lifetime parameter:
 `fn foo'a(arg: 'a int)`

 In the return type position `fn foo() - int` is short for `fn foo'a()
 - 'a int`, meaning `foo` has to return a reference to (an int that lives
 as long as any lifetime the caller could choose), which in practice means
 that it has to be 'static. I believe you are or will be required to write
 'static explicitly in these cases to avoid confusion.

 With a struct it's not much different.

 s: MyStruct'a means lifetime_of(s) = 'a
 s: MyStruct'a, 'b means lifetime_of(s) = 'a  lifetime_of(s) = 'b

 If you have

 struct MyStruct'self {
 r_int: 'self int
 }

 s: MyStruct'a

 then lifetime_of(s) = 'a  lifetime_of(s.r_int) = 'a. (Which is trivial
 because lifetime_of(s) == lifetime_of(s.r_int).)

 Basically, every object has a lifetime - from its creation to its
 destruction - but a lifetime parameter or argument typically refers to the
 lifetime of something else, which the object itself must not or does not
 outlive.

 (Please yell at me if I got any of this wrong.)



 On Sun, Sep 29, 2013 at 5:23 PM, Oren Ben-Kiki o...@ben-kiki.org wrote:

 Ok, color me confused... perhaps there's somewhere that explains 'self on
 more detail? For example, _why_ does the example below not work without the
 explicit 'self? It seems like it should.

 I have yet to truly understand the whole 'self thing. When I first read
 about lifetimes, my naive expectations were that:

 - Every struct has a 'self lifetime, which is basically as long as this
 struct exists. It doesn't matter if I have a @ of the struct or a ~ of the
 struct or just a local variable with the struct... when the struct is
 dropped, the lifetime ends.

 - It follows there's no need to ever annotate structs as generic with a
 'self parameter - it always exists.

 - Any  in a struct is either 'self or 'static. A simple  should be
 'self as that makes more sense (but if Rust wants me to be explicit, fine).

 This were my least surprise expectations, but things don't work this
 way... the problem is I don't have a simple mental model to replace the
 above with, so I struggle. What _is_ 'self, exactly?

 Isn't a function fn foo(self) - T the same as returning a 'self T?
 Why would I want to say fn foo'a('a self) in the 1st place - 'a is by
 definition the same as 'self? How come David's Foo example fails the
 borrow check?

 Besides failing (my) least surprise expectations, the current rules
 also seem to be a leaky abstraction. If I have a struct

Re: [rust-dev] Trait method self parameter type clashes with lifetime annotation required by the implementation

2013-09-29 Thread Oren Ben-Kiki
That's... surprising. Even ignoring the fact the name self means exactly
the opposite (déjà vu from const here)...

I don't suppose there's a chance that something like what I expected 'self
to be like would be supported at some point? Its lack rules out a lot of
reasonable, safe, useful code.



On Mon, Sep 30, 2013 at 12:13 AM, Gábor Lehel illiss...@gmail.com wrote:


 `On Sun, Sep 29, 2013 at 9:21 PM, Oren Ben-Kiki o...@ben-kiki.org wrote:

 Thanks for the explanation. You said two key points:
 - Basically, every object has a lifetime - from its creation to its
 destruction - but a lifetime parameter or argument typically refers to the
 lifetime of something else, which the object itself must not or does not
 outlive.
 And:
 - 'self is not special in any way, except that the compiler has
 historical baggage such that 'self is the only name it lets you use for a
 lifetime parameter on a struct.

 So, 'self is indeed very far from what I thought (hoped) it would be.

 Taking these together, do I read this right as saying there is no way
 whatsoever to say:

 struct Foo {
 bar: Bar,
 baz: 'i-live-as-long-as-the-foo-struct-and-no-more BazPartOfBar,
 }


 Per my understanding, this is correct. Because there is a constraint on
 the lifetime of a part of `Foo`, there must a constraint on the lifetime of
 `Foo`. It has to propagate outwards to make sure the lifetime of the whole
 structure is properly constrained. You basically want to propagate
 inwards. I don't think that's possible, but maybe someone will correct me.



 When writing a non-trivial container, I found several user cases to be
 extremely problematic. One was the above; a container held a spine or
 master or owned or whatever-you-want-to-call-it data structure(s), plus
 borrowed pointers that only live as long as the container and allow quick
 access to specific parts of it.

 Is this impossible in Rust (barring use of @ or unsafe pointers)?


 This sounds similar to the case of a doubly linked list (with forward
 pointers being the spine and backwards the quick access), which is  not
 possible as an 'owned' structure as far as I know without unsafe pointers.




 On Sun, Sep 29, 2013 at 8:24 PM, Gábor Lehel illiss...@gmail.com wrote:

 'self is not special in any way, except that the compiler has historical
 baggage such that 'self is the only name it lets you use for a lifetime
 parameter on a struct. But that's a bug. In the ideal platonic Rust in the
 sky, you can have any number of lifetime parameters on a struct with
 whatever names you prefer.

 The way I've found to think about lifetimes is that if you have:

 r_int: 'a int

 then 'a refers to a span of time (a scope, a lifetime) such that
 lifetime_of(r_int) = 'a = lifetime_of(*r_int). (Where *r_int is intended
 metaphorically to refer to the original object r_int was created from, not
 the result of the *r_int expression itself.) So 'a is a kind of stand
 between to ensure that r_int does not outlive the object it refers to.

 If you have

 fn foo'a(r_int: 'a int) - 'a int

 then just like any other generics argument, the lifetime 'a is chosen by
 the caller of `foo` (as inferred by the compiler). Typically the caller
 will have an int object (i: int), then borrow a reference to it (r_int: 'a
 int = i) which it passes to `foo`, and then 'a will be the lifetime of the
 int. `foo` will then have to return a reference to (an int that lives at
 least as long). In practice this could either be the r_int it got as
 argument, or a static int.

 `fn foo(arg: int)` is shorthand for an anonymous lifetime parameter:
 `fn foo'a(arg: 'a int)`

 In the return type position `fn foo() - int` is short for
 `fn foo'a() - 'a int`, meaning `foo` has to return a reference to (an
 int that lives as long as any lifetime the caller could choose), which in
 practice means that it has to be 'static. I believe you are or will be
 required to write 'static explicitly in these cases to avoid confusion.

 With a struct it's not much different.

 s: MyStruct'a means lifetime_of(s) = 'a
 s: MyStruct'a, 'b means lifetime_of(s) = 'a  lifetime_of(s) = 'b

 If you have

 struct MyStruct'self {
 r_int: 'self int
 }

 s: MyStruct'a

 then lifetime_of(s) = 'a  lifetime_of(s.r_int) = 'a. (Which is
 trivial because lifetime_of(s) == lifetime_of(s.r_int).)

 Basically, every object has a lifetime - from its creation to its
 destruction - but a lifetime parameter or argument typically refers to the
 lifetime of something else, which the object itself must not or does not
 outlive.

 (Please yell at me if I got any of this wrong.)



 On Sun, Sep 29, 2013 at 5:23 PM, Oren Ben-Kiki o...@ben-kiki.orgwrote:

 Ok, color me confused... perhaps there's somewhere that explains 'self
 on more detail? For example, _why_ does the example below not work without
 the explicit 'self? It seems like it should.

 I have yet to truly understand the whole 'self thing. When I first read
 about lifetimes, my naive expectations were

Re: [rust-dev] Some suggestions of Rust language

2013-09-25 Thread Oren Ben-Kiki
On Wed, Sep 25, 2013 at 6:29 PM, Patrick Walton pwal...@mozilla.com wrote:

 On 9/25/13 6:32 AM, Alexander Sun wrote:

 Embedded anonymous structure?

 Embedded anonymous structure in Go is good idea, I think.


 Not the way Go does it, where you can have method conflicts like C++
 multiple inheritance and it can be surprising which method gets called when
 two anonymous fields have a method with the same name. I'm not necessarily
 opposed to anonymous fields, but we should tread carefully.


Can you say a bit more about that? I thought if two anonymous fields
supported a method than it was a conflict and one had to refer to it with
the specific field type (foo.TypeOfFirstField.method or
foo.TypeOfSecondField.method as opposed to foo.method - the latter would be
an error). This sounds pretty reasonable...

Since Rust has no implicit traits anywhere, it seems reasonable to require
an explicit impl Trait for Container, but allow omitting functions that are
obtained from anonymous field(s) - unless one wants to override them, or
when they are in conflict between more than one such field. This ensures
all type checking is done at declaration rather than in code that uses the
traits.

It sounds like something along these lines could work in Rust, and it would
be very useful...
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Should we add a Haskell-like `$` operator?

2013-09-25 Thread Oren Ben-Kiki
Not sure about $ but I sometimes miss the | operator (which takes the
value from the left and inserts it as the 1st argument of the function call
to the right).

foo(a, b) | bar(c, d) | baz(e, f)
== baz(bar(foo(a, b), c, d), e, f)

This allows for easier functional decompsition of chains of operations. I
found it to be very useful when writing Elixir; in Rust there's the OO-like
traits which may make it less useful - it still might be worthwhile for
people writing more functional code.


On Wed, Sep 25, 2013 at 9:40 PM, Marvin Löbel loebel.mar...@gmail.comwrote:

 We don't use the symbol in our syntax, but are using functional paradigm
 that sometimes result in a bit hard to read nested calls.

 I'd propose that it works similar to `do`, in that it allows to move the
 last expression of an function or method call after the parentheses, though
 they would still remain required for ambiguity reasons:

 ~~~
a(b(c(1,d(2,3,4,e()
 == a() $ b() $ c(1) $ d(2,3,4) $ e()

 let v: ~[uint] = from_iter() $ range(0, 100);
 ~~~

 In that sense, it wouldn't really be an operator but syntactic sugar for a
 function call.
 It might even be possible to replace `do` with it, though the now required
 parentheses would make it longer:

 ~~~
 do task::spawn { ... }
 task::spawn() $ || { ... }
 ~~~

 Downside is of course that it adds another symbol, which could alienate
 more potentiall users, and it could mean a shift-away-from or at least an
 inconsistency-with methods and method chaining in general.

 Which would be ironic because I wanted it in some complicated Iterator
 chain. ;)

 It could of course always be implemented as a syntax extension, and in any
 case I don't expect this to get any attention before Rust 2.0. :)
 __**_
 Rust-dev mailing list
 Rust-dev@mozilla.org
 https://mail.mozilla.org/**listinfo/rust-devhttps://mail.mozilla.org/listinfo/rust-dev

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


Re: [rust-dev] Should we add a Haskell-like `$` operator?

2013-09-25 Thread Oren Ben-Kiki
Not sure about $ but I sometimes miss the | operator (which takes the
value from the left and inserts it as the 1st argument of the function call
to the right).

foo(a, b) | bar(c, d) | baz(e, f)
== baz(bar(foo(a, b), c, d), e, f)

This allows for easier functional decompsition of chains of operations. I
found it to be very useful when writing Elixir; in Rust there's the OO-like
traits which may make it less useful - it still might be worthwhile for
people writing more functional code.


On Wed, Sep 25, 2013 at 9:40 PM, Marvin Löbel loebel.mar...@gmail.comwrote:

 We don't use the symbol in our syntax, but are using functional paradigm
 that sometimes result in a bit hard to read nested calls.

 I'd propose that it works similar to `do`, in that it allows to move the
 last expression of an function or method call after the parentheses, though
 they would still remain required for ambiguity reasons:

 ~~~
a(b(c(1,d(2,3,4,e()
 == a() $ b() $ c(1) $ d(2,3,4) $ e()

 let v: ~[uint] = from_iter() $ range(0, 100);
 ~~~

 In that sense, it wouldn't really be an operator but syntactic sugar for a
 function call.
 It might even be possible to replace `do` with it, though the now required
 parentheses would make it longer:

 ~~~
 do task::spawn { ... }
 task::spawn() $ || { ... }
 ~~~

 Downside is of course that it adds another symbol, which could alienate
 more potentiall users, and it could mean a shift-away-from or at least an
 inconsistency-with methods and method chaining in general.

 Which would be ironic because I wanted it in some complicated Iterator
 chain. ;)

 It could of course always be implemented as a syntax extension, and in any
 case I don't expect this to get any attention before Rust 2.0. :)
 __**_
 Rust-dev mailing list
 Rust-dev@mozilla.org
 https://mail.mozilla.org/**listinfo/rust-devhttps://mail.mozilla.org/listinfo/rust-dev

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


Re: [rust-dev] Should we add a Haskell-like `$` operator?

2013-09-25 Thread Oren Ben-Kiki
Not sure about $ but I sometimes miss the | operator (which takes the
value from the left and inserts it as the 1st argument of the function call
to the right).

foo(a, b) | bar(c, d) | baz(e, f)
== baz(bar(foo(a, b), c, d), e, f)

This allows for easier functional decompsition of chains of operations.
I'm not certain it is as useful in an OO-like language like Rust - I cer


On Wed, Sep 25, 2013 at 9:40 PM, Marvin Löbel loebel.mar...@gmail.comwrote:

 We don't use the symbol in our syntax, but are using functional paradigm
 that sometimes result in a bit hard to read nested calls.

 I'd propose that it works similar to `do`, in that it allows to move the
 last expression of an function or method call after the parentheses, though
 they would still remain required for ambiguity reasons:

 ~~~
a(b(c(1,d(2,3,4,e()
 == a() $ b() $ c(1) $ d(2,3,4) $ e()

 let v: ~[uint] = from_iter() $ range(0, 100);
 ~~~

 In that sense, it wouldn't really be an operator but syntactic sugar for a
 function call.
 It might even be possible to replace `do` with it, though the now required
 parentheses would make it longer:

 ~~~
 do task::spawn { ... }
 task::spawn() $ || { ... }
 ~~~

 Downside is of course that it adds another symbol, which could alienate
 more potentiall users, and it could mean a shift-away-from or at least an
 inconsistency-with methods and method chaining in general.

 Which would be ironic because I wanted it in some complicated Iterator
 chain. ;)

 It could of course always be implemented as a syntax extension, and in any
 case I don't expect this to get any attention before Rust 2.0. :)
 __**_
 Rust-dev mailing list
 Rust-dev@mozilla.org
 https://mail.mozilla.org/**listinfo/rust-devhttps://mail.mozilla.org/listinfo/rust-dev

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


Re: [rust-dev] If and pattern match

2013-09-24 Thread Oren Ben-Kiki
I agree that is a macro like your `if_matches` examples were possible, it
would be a reasonable solution, including conferring the right scope for
`a` and `b`.

It is completely unclear to me how to implement it though. What does
use_more_macros line mean?

Thanks,

Oren.



On Mon, Sep 23, 2013 at 2:06 PM, Huon Wilson dbau...@gmail.com wrote:

  On 23/09/13 20:52, Jason Fager wrote:

 Doesn't seem like enough bang for the buck to me.  In your first example you
 save 3 vertical lines but get a really wide one in return, and lose some 
 indentation
 levels but add more syntax and conceptual overhead to the language.

  Might be my lack of imagination, but the feature doesn't seem to expand
 out to many other use cases, either.

  Your second case you could write as:

  let foo = get_option(foo);
 let bar = get_option(bar);
 if foo.is_some()  bar.is_some() {
  use(foo.unwrap(), bar.unwrap());
 }


 It's also possible to write a `matches` macro:

   macro_rules! matches {
   ($e:expr ~ $($p:pat)|*) = {
   match $e {
   $($p)|* = true,
   _ = false
   }
   }
   }

   fn main() {
   let a = Some(1);
   let b = Some(2);

   if matches!((a,b) ~ (Some(_), Some(_))) {
   println(whatever);
   }
   }

 (This has the drawback that accidentally (or otherwise) using a pattern
 that always matches, e.g. `matches!((a,b) ~ (_,_))` gives a error message
 about the `_ = false` arm being unreachable, which isn't particularly
 intuitive.)

 Following the use-more-macros line, one could modify the above to give
 something like

   if_matches!(foo ~ (Some(a), Some(b)) = {
   // use a, b
   })

 by adding an $expr argument to use instead of `true` and replacing the
 false arm with `{}`. Note: this *may* break when match-var-hygiene is
 implemented (https://github.com/mozilla/rust/issues/9384), I'm not sure.

 Huon


 ___
 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


[rust-dev] If and pattern match

2013-09-23 Thread Oren Ben-Kiki
A question / proposed syntax... How about allowing writing something like:

if (Some(foo), Some(bar)) ~~ (get_option(foo), get_option(bar)) {
use(foo, bar);
}

Instead of having to write the more combersome:

match (get_option(foo), get_option(bar)) {
(Some(foo), Some(bar)) = {
use(foo, bar);
},
_otherwise = {},
}

Not to mention:

let foo_bar: bool = (Some(_foo), Some(_bar)) ~~ (get_option(foo),
get_option(bar));

match (get_option(foo), get_option(bar)) {
(Some(foo), Some(bar)) = {
use(foo, bar);
},
_otherwise = {},
}

Instead of the very cumbersome:

let foo_bar: bool =
match (get_option(foo), get_option(bar)) {
(Some(_foo), Some(_bar)) = true,
_otherwise = false,
}
}

So, in general allow `pattern ~~ expression` to be a boolean expression and
if it is used in an if statement allow it to introduce the matched
variables to the then scope.

The operator doesn't have to be ~~, it could be anything unique (though
using ~ for matching has a lot of precedence in other languages).

Thoughts?

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


Re: [rust-dev] rusti - the - repl renovation

2013-09-20 Thread Oren Ben-Kiki
Would running test-to-destruction cases that are expected to fail count as
running in a sandbox? Currently I spawn them to a separate task and catch
its failure, which is probably better practice - but it would be nice if I
were able to access the message given to fail and compare it with the
expected one. If the unsafe catch would allow for that, it may be
worthwhile to switch to it...


On Fri, Sep 20, 2013 at 4:54 PM, Patrick Walton pwal...@mozilla.com wrote:

 On 9/19/13 11:40 PM, Jason E. Aten wrote:

 Agreed. I'm convinced that fail! should result in an almost-magical
 lets pretend that never happened jump back in time.


 I'm personally fine with adding an unsafe catch function or form that
 will stop unwinding if you absolutely have to use it, incidentally. In
 general fail! is not supposed to be used as an exception mechanism, because
 monadic use of Result does that better. But if you're doing special things
 like trying to sandbox Rust code, it seems relatively harmless to me. We
 already have all the low-level infrastructure (DWARF unwinding based C++
 exceptions) necessary to make it work...

 Patrick

 __**_
 Rust-dev mailing list
 Rust-dev@mozilla.org
 https://mail.mozilla.org/**listinfo/rust-devhttps://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 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


Re: [rust-dev] RFC: Syntax for raw string literals

2013-09-19 Thread Oren Ben-Kiki
Just to make sure - how does the C++ syntax behave in the presence of line
breaks? Specifically, what does it do with leading (and trailing) white
space of each line? My guess is that they would be included in the string,
is that correct?

At any rate, having some sort of here documents would be very nice. The C++
syntax is reasonable, though I really don't have a strong preference here.
It might be more Rust-ish to use a macro notation instead:
str!(delimiter.delimiter), or something like that.

BTW, I found myself creating (in several languages) an unindent string
function that would (1) if the string starts with a line break, remove it;
(2) remove the leading white space of the 1st line from all the lines.
Applying this to here documents allows indenting them together with the
code that includes them. In Rust, the downside of this approach is that the
result isn't 'static any more... Not that this warrants making such
complex functionality a built-in of the syntax, of course.

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


Re: [rust-dev] Type parameters in trait bounds

2013-09-09 Thread Oren Ben-Kiki
Rust newbie here as well, trying to develop an intuition for these things
myself :-) Off the top of my head - you are saying the map holds entries
whose lifetime is 'input; but there's no guarantee that the map lifetime
itself wouldn't be longer than that. Try saying 'input M instead of M and
see how it goes.

Oren.


On Fri, Sep 6, 2013 at 10:27 PM, Alex quixop...@googlemail.com wrote:

 Hey Everyone,

 I'm new to rust but enjoying it a lot. I'm having trouble with the
 following code example:


 use std::hashmap::{HashMap, Map};


 fn do_something'input, M: Mapint, 'input str (key: int, map: M){
 match map.find(key){
 Some(result) = println(fmt!(%s, result)),
 None = println(no match)
 };
 }

 fn main(){
 let  map : HashMapint, str = HashMap::new();
 map.insert(1, one);
 do_something(1, map);
 }


 This fails with a compilation error:

 example.rs:4:44: 4:47 error: Illegal lifetime 'input: only 'self is
 allowed as part of a type declaration
 example.rs:4 fn do_something'input, M: Mapint, 'input str (key: int,
 map: M){


 Now, I'm probably misunderstanding a bunch of things here, firstly all the
 example code I've seen out there uses the HashMap type directly rather than
 the Map trait, is this idiomatic? Secondly, I'm still getting my head
 around lifetimes and probably have this all muddled so any pointers there
 would be welcome.

 Thanks
 Alex Good


 ___
 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] RFC: Stealing: lexically-scoped temporary violation of linearity

2013-09-07 Thread Oren Ben-Kiki
Another thought on this. Currently, either the compiler is satisfies that
the code is 100% safe, or we slap an unsafe keyword around the code and
put 100% of the responsibility on the programmer, with no support from the
Rust system.

Wouldn't it make sense to have a not statically safe, but verified at run
time safety as a middle ground?

In the context of the stolen proposal, when one steals a pointer, the
original location could be set to null, and only be restored to a non-null
pointer when the value is put back. This means any access to it would
cause an exception - which is what one would intuitively expect a hold to
behave like.

I have a feeling that there is a non-trivial amount of code which is
actually safe but would impossible to convince the compiler it is
statically safe. Surely having run-time safety in such cases is better
than none at all...?



On Sat, Aug 31, 2013 at 3:50 AM, Patrick Walton pwal...@mozilla.com wrote:

 On 8/30/13 3:39 PM, Patrick Walton wrote:

 Thoughts? Does this seem useful? Are there soundness issues I didn't
 notice?


 Brian pointed out a massive soundness hole in this, unfortunately. The
 problem is that you can read from the original locations; the right to read
 is not shut off during the borrow. I think the fix would have to be to
 replace this with some sort of generalized swap operation.


 Patrick

 __**_
 Rust-dev mailing list
 Rust-dev@mozilla.org
 https://mail.mozilla.org/**listinfo/rust-devhttps://mail.mozilla.org/listinfo/rust-dev

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


Re: [rust-dev] RFC: Stealing: lexically-scoped temporary violation of linearity

2013-09-07 Thread Oren Ben-Kiki
Is there any system in actual use where actually dereferencing a null
pointer will not cause an exception? I mean, _sure_, the C spec says the
result is undefined, but isn't this just a leftover from the bad old
days, like also supporting non-byte-addressible machines (with
non-power-of-two word size!), and other such horribleness?

If in practice on any machine today (X86, ARM, PowerPC, MIPS, SPARC, ...)
every null pointer will fault (which I strongly hope will...), then I'd be
quite happy in saying formally that accessing a hole leads to undefined
behavior and make good use of knowledge that any such access will, in
fact, fault, on any machine I might be coding to today.


On Sat, Sep 7, 2013 at 6:55 PM, Patrick Walton pwal...@mozilla.com wrote:

 On 9/7/13 8:39 AM, Oren Ben-Kiki wrote:

 I have a feeling that there is a non-trivial amount of code which is
 actually safe but would impossible to convince the compiler it is
 statically safe. Surely having run-time safety in such cases is better
 than none at all...?


 I would be fine with this, but one big problem is that null pointer
 dereferences are undefined behavior in LLVM.

 Patrick


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


Re: [rust-dev] RFC: Stealing: lexically-scoped temporary violation of linearity

2013-09-07 Thread Oren Ben-Kiki
I miss-spoke; when I said machine I meant platform (combination of HW
and SW). Is unintentionally dereferencing a null pointer a silent error on
any existing platform?

But isn't a very good question either. A better one would be: Would it be
_useful_ to define `steal` and use it in programs, such that it triggers a
null pointer dereference (undefined behavior and all) if someone tries to
access the hole? This is a softer question and I suspect the answer is
yes - at least until a better way to safely update structures in-place is
found...


On Sat, Sep 7, 2013 at 7:20 PM, Daniel Micay danielmi...@gmail.com wrote:

 On Sat, Sep 7, 2013 at 12:09 PM, Oren Ben-Kiki o...@ben-kiki.org wrote:

 If in practice on any machine today (X86, ARM, PowerPC, MIPS, SPARC, ...)
 every null pointer will fault (which I strongly hope will...), then I'd be
 quite happy in saying formally that accessing a hole leads to undefined
 behavior and make good use of knowledge that any such access will, in
 fact, fault, on any machine I might be coding to today.


 You get a segmentation fault on Linux because the first page is marked
 read-only for userland processes. It's valid on almost any hardware to
 dereference a pointer equal to zero, which is how LLVM defines the null
 pointer. However, LLVM explicitly considers a dereference of the null
 pointer to be undefined behaviour so it doesn't matter how it could or
 couldn't be implemented in hardware.

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


Re: [rust-dev] RFC: Stealing: lexically-scoped temporary violation of linearity

2013-09-07 Thread Oren Ben-Kiki
Alas. So I guess it all depends on someone finding a smart safe way to
generalize the swap operation, or something... as things stand, it is
extremely difficult to efficiently and safely implement complex nested
containers. I will admit I am using the `steal` function for now, it just
makes things so much easier, but I know I'll have to pay for my sins down
the line...



On Sat, Sep 7, 2013 at 11:27 PM, Geoffrey Irving irv...@naml.us wrote:

 To clarify why undefined behavior is really bad in practice: if LLVM ever
 detects that your code performs undefined behavior according to the
 standard, it is *designed* to take full advantage of that fact when making
 optimizations.  In other words, all hell will break lose, in potentially
 very complicated and subtle ways.

 Geoffrey

 On Sep 7, 2013, at 1:22 PM, Daniel Micay danielmi...@gmail.com wrote:

  On Sat, Sep 7, 2013 at 4:15 PM, Oren Ben-Kiki o...@ben-kiki.org wrote:
  I miss-spoke; when I said machine I meant platform (combination of
 HW and SW). Is unintentionally dereferencing a null pointer a silent error
 on any existing platform?
 
  Yes, it's only a segmentation fault in userland code on platforms where
 the kernel is set up to make the lowest page read-only. Rust still needs to
 be memory safe in a kernel.
 
  But isn't a very good question either. A better one would be: Would it
 be _useful_ to define `steal` and use it in programs, such that it triggers
 a null pointer dereference (undefined behavior and all) if someone tries to
 access the hole? This is a softer question and I suspect the answer is
 yes - at least until a better way to safely update structures in-place is
 found...
 
  It would be undefined behaviour, so it wouldn't be useful. Rust is a
 memory safe language and can't allow safe code to generate LLVM IR invoking
 undefined behaviour.
  ___
  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] RFC: Stealing: lexically-scoped temporary violation of linearity

2013-09-01 Thread Oren Ben-Kiki
Since swap seems to have its own problems - would it be possible to tweak
the stealing idea so the compiler would know there's a burrowed mutable
pointer to the hole, effectively preventing further access to it in the
vulnerable block?

I really would like to be able to use this approach, it really improved my
code...


On Sat, Aug 31, 2013 at 3:50 AM, Patrick Walton pwal...@mozilla.com wrote:

 On 8/30/13 3:39 PM, Patrick Walton wrote:

 Thoughts? Does this seem useful? Are there soundness issues I didn't
 notice?


 Brian pointed out a massive soundness hole in this, unfortunately. The
 problem is that you can read from the original locations; the right to read
 is not shut off during the borrow. I think the fix would have to be to
 replace this with some sort of generalized swap operation.


 Patrick

 __**_
 Rust-dev mailing list
 Rust-dev@mozilla.org
 https://mail.mozilla.org/**listinfo/rust-devhttps://mail.mozilla.org/listinfo/rust-dev

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


Re: [rust-dev] RFC: Stealing: lexically-scoped temporary violation of linearity

2013-08-30 Thread Oren Ben-Kiki
I just tested this in my code, it solved a sticky problem I had with
updating owned data nested deep inside a tree-ish container. My original
solution wasn't very nice (it just compromised on efficiency and copied too
much data around). The new code is shorter and more efficient (no copies!
yey!).

So, +1 for usefulness, and thanks!

I wish I could also attest to the correctness, but that is harder to
prove...



On Sat, Aug 31, 2013 at 1:39 AM, Patrick Walton pwal...@mozilla.com wrote:

 Hi everyone,

 I've been tossing around an idea for a library utility designed to make
 unique pointers easier to use, especially for balanced binary search trees
 and the like. The core of the idea is that I conjecture it's safe to
 temporarily violate linearity *while the locations in question are
 borrowed*, as long as linearity is *dynamically* preserved once the borrow
 ends.

 First off, let me motivate this with an example, showing that this
 generalizes swap:

 struct Test {
 a: ~str,
 b: ~str,
 }

 fn main() {
 let mut test = Test {
 a: ~Burma,
 b: ~Shave,
 };
 {
 let (a, a_loc) = steal(mut test.a);
 let (b, b_loc) = steal(mut test.b);
 println(a);   // prints Burma
 println(b);   // prints Shave
 a_loc.put_back(b);
 b_loc.put_back(a);
 }
 println(test.a);  // prints Shave
 println(test.b);  // prints Burma
 }

 Concretely, what steal does is that it takes a mutable borrow and
 returns two things: (1) a shallow copy of the referent, temporarily
 violating linearity; (2) a stolen location which must be filled with a
 value of the same type as the referent via the `put_back` method before the
 scope ends. If the scope ends (i.e. the borrow expires) without calling
 `put_back` on a stolen location, then task failure occurs. For example,
 this program fails (with the above definition of `Test`):

 fn main() {
 let mut test = Test {
 a: ~Burma,
 b: ~Shave,
 };
 {
 let (a, a_loc) = steal(mut test.a);
 let (b, b_loc) = steal(mut test.b);
 a_loc.put_back(b);
 } // dynamic failure: b_loc was not filled
 }

 The idea behind this is to allow complex pointer rewirings such as those
 that self-balancing binary search trees want to be expressed in a natural
 way without a tricky series of swaps.

 The thing that initially seems questionable for soundness is that, while
 borrowed and while linearity is violated, the original value is still
 readable (although not immutably or mutably borrowable). I believe this is
 OK, even in the fact of LLVM alias optimizations, because while something
 is borrowed linearity is no longer guaranteed anyhow.

 The implementation is quite small and simple and fits here:

 struct Stolen'self,T {
 priv location: 'self mut T,
 }

 #[unsafe_destructor]
 impl'self,T Drop for Stolen'self,T {
 fn drop(self) {
 fail!(stolen)
 }
 }

 impl'self,T Stolen'self,T {
 fn put_back(self, value: T) {
 unsafe {
 intrinsics::move_val_init(**self.location, value);
 cast::forget(self)
 }
 }
 }

 fn steal'a,T(value: 'a mut T) - (T, Stolen'a,T) {
 unsafe {
 (cast::transmute_copy(value), Stolen {
 location: value,
 })
 }
 }

 Thoughts? Does this seem useful? Are there soundness issues I didn't
 notice?

 Patrick
 __**_
 Rust-dev mailing list
 Rust-dev@mozilla.org
 https://mail.mozilla.org/**listinfo/rust-devhttps://mail.mozilla.org/listinfo/rust-dev

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


Re: [rust-dev] RFC: Stealing: lexically-scoped temporary violation of linearity

2013-08-30 Thread Oren Ben-Kiki
Sigh, I guess it was too good to be true :-(

I'd settle for the ability to say: update_in_place(foo.owned_pointer,
fn(~T) - ~T) - surely this would be safe?

Speaking of which, a secondary problem I encountered when doing this sort
of thing, is the Once function issue listed in
https://github.com/mozilla/rust/wiki/Doc-under-construction-FAQ.

Wouldn't it be possible to say, for example, that ~fn can only be invoked
once to resolve this issue?


On Sat, Aug 31, 2013 at 3:50 AM, Patrick Walton pwal...@mozilla.com wrote:

 On 8/30/13 3:39 PM, Patrick Walton wrote:

 Thoughts? Does this seem useful? Are there soundness issues I didn't
 notice?


 Brian pointed out a massive soundness hole in this, unfortunately. The
 problem is that you can read from the original locations; the right to read
 is not shut off during the borrow. I think the fix would have to be to
 replace this with some sort of generalized swap operation.


 Patrick

 __**_
 Rust-dev mailing list
 Rust-dev@mozilla.org
 https://mail.mozilla.org/**listinfo/rust-devhttps://mail.mozilla.org/listinfo/rust-dev

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


Re: [rust-dev] Doc comment conventions + straw poll

2013-08-27 Thread Oren Ben-Kiki
I prefer using /// for comments before functions and types, and ///! for
comments following fields:

/// ...
pub struct Foo {
   foo: int, //! ...
}

(BTW, it would be nice to document function arguments:

/// ...
pub fn foo(
foo: int, //! ...
) {
...
}

But rustdoc doesn't have the concept of a doc for an argument. Oh well.)

At any rate, //! allows structs to stay compact but still document the
fields, as opposed to having a /// before each one which takes double the
amount of lines. I actually use /// for struct fields, because rustdoc
doesn't using allow //! this way today (it says expected outer comment).
A bug, I guess? So I only use //! at the top to document the whole module.

The main reason I use //-style everywhere is that this way I can safely use
/* ... */ to comment out chunks of code. I don't comment code chunks a lot,
but when I need to, it is good to know one can just do it without worrying
about nesting /* ... */.

If /* ... */ allowed nesting, I'd probably still prefer //-style - The '*'
seem visually noisy, it takes up extra lines (in multi-line comments), and
I'm never comfortable when I see:

/*!
 * foo
 */

Whether it would end up meaning:
// * foo

Or (more likely):
/// foo
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Dynamic in Rust

2013-08-23 Thread Oren Ben-Kiki
Yes, this would be similar to the `Typeable` type class in Haskell. It
queries the vtable-equivalent, which contains stuff like the name of the
type and allows doing `typeof(x)`, dynamic casts, etc. This is heavily
magical (that is, depends on the hidden internal representation) and
properly belongs in the standard platform and not in a user-level library.


On Fri, Aug 23, 2013 at 4:40 PM, Niko Matsakis n...@alum.mit.edu wrote:

 Currently, this is not directly supported, though downcasting in
 general is something we have contemplated as a feature.  It might be
 possible to create some kind of horrible hack based on objects. A
 trait like:

 trait Dynamic { }
 implT Dynamic for T { }

 would allow any value to be cast to an object. The type descriptor can
 then be extracted from the vtable of the object using some rather
 fragile unsafe code that will doubtless break when we change the
 vtable format. The real question is what you can do with the type
 descriptor; they are not canonicalized, after all. Still, it's
 ... very close.  This is basically how dynamic downcasting would work,
 in any case.


 Niko

 On Fri, Aug 23, 2013 at 07:49:57AM +0300, Oren Ben-Kiki wrote:
  Is it possible to implement something like Haskell's Dynamic value holder
  in Rust? (This would be similar to supporting C++'s dynamic_cast).
  Basically, something like this:
 
  pub struct Dynamic { ... }
  impl Dynamic {
  pub fn put(value: ~T) { ... }
  pub fn get() - OptionT { ... }
  }
 
  I guess this would require unsafe code... even so, it seems to me that
 Rust
  pointers don't carry sufficient meta-data for the above to work. A
 possible
  workaround would be something like:
 
  pub struct Dynamic { type_name: ~str, ... }
  impl Dynamic {
  pub fn put(type_name: str, value: ~T) { Dynamic { type_name:
  type_name, ... } }
  pub fn get('a self, type_name: str) - Option'a T {
  assert_eq!(type_name, self.type_name); ... } }
  }
 
  And placing the burden on the caller to always use the type name int
 when
  putting or getting `int` values, etc. This would still require some sort
 of
  unsafe code to cast the `~T` pointer into something and back, while
  ensuring that the storage for the `T` (whatever its size is) is not
  released until the `Dynamic` itself is.
 
  (Why do I need such a monstrosity? Well, I need it to define a
  `Configuration` container, which holds key/value pairs where whoever
 sets a
  value knows its type, whoever gets the value should ask for the same
 type,
  and the configuration can hold values of any type - not from a
 predefined
  list of types).
 
  Is such a thing possible, and if so, how?
 
  Thanks,
 
  Oren Ben-Kiki

  ___
  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


  1   2   >