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

2014-03-11 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  wrote:

> By the way, I didn't see any discussion of the HasPrefix/Coercible
> proposal<https://github.com/mozilla/rust/issues/9912#issuecomment-36073562>in 
> the workweek minutes.  Did anybody bring it up at all?
>
> Vadim
>
>
> On Tue, Mar 11, 2014 at 2:30 PM, Oren Ben-Kiki  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 
>> wrote:
>>
>>> 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 wrote:

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

> 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 `Fn` there will be something like `OnceFn`:
>
> trait OnceFn {
> 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] 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 wrote:

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

> On Tue, Dec 31, 2013 at 9:15 AM, Oren Ben-Kiki  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
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  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] 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 wrote:

>
> On 7 Dec 2013, at 10:47 am, Simon Sapin  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
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 wrote:

> 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_? <>). 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-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_? <>). It really just begs for
stack-allocated-once-closures.


On Sat, Nov 30, 2013 at 11:28 PM, Patrick Walton wrote:

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

> On Nov 30, 2013, at 10:20 AM, Patrick Walton  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
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  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
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 wrote:

> 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  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 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
>>
>>
> --
> 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-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  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
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  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] 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  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 Index { 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] 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  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 Vector (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 : Vector = [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] "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  wrote:

> On Fri, Nov 15, 2013 at 6:54 AM, Oren Ben-Kiki  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] "Implementation Inheritance" / mixins

2013-11-15 Thread Oren Ben-Kiki
On Fri, Nov 15, 2013 at 11:47 AM, Huon Wilson  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-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  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-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] The future of M:N threading

2013-11-13 Thread Oren Ben-Kiki
On Wed, Nov 13, 2013 at 10:51 PM, james wrote:

>  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-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  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] 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  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
The call isn't statically dispatched when I invoke a method via a trait
pointer. So it seems when I invoke any trait function, I pay double the
cost of a virtual function call instead of one... I suppose it isn't _too_
bad, but it still hurts.



On Wed, Nov 13, 2013 at 12:21 PM, Eric Reed wrote:

> I'm not clear on why LLVM wouldn't be able to inline super() calls. It's
> static dispatch, so it knows exactly what function is being called.
>
>
> On Wed, Nov 13, 2013 at 1:25 AM, Oren Ben-Kiki  wrote:
>
>> 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 wrote:
>>
>>> 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 DerivingTrait : 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 DerivingTrait for Single {
>>> fn super(&self) -> Base { self.parent }
>>> }
>>>
>>> // Overriding behavior
>>> struct Override {
>>> parent: Base,
>>> otherData: u8,
>>> }
>>>
>>> impl DerivingTrait 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 Derivi

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

> 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 DerivingTrait : 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 DerivingTrait for Single {
> fn super(&self) -> Base { self.parent }
> }
>
> // Overriding behavior
> struct Override {
> parent: Base,
> otherData: u8,
> }
>
> impl DerivingTrait 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 DerivingTrait for MultipleAsSingle {
> fn super(&self) -> Single { self.single }
> }
>
> impl DerivingTrait 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  wrote:
>
>> On Nov 12, 2013, at 10:26 PM, Kevin Ballard  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 combine

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

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


On Tue, Nov 12, 2013 at 4:06 PM, spir  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] 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 Rc for read-only access
and Rc> for mutable access? How does this protect against multiple
mutations "at once"?

On Tue, Nov 12, 2013 at 3:13 PM, Patrick Walton wrote:

>
>> 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] 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 Rc
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 Rc (keep in
mind this will change to Gc or something in the future).

If sending the whole thing is an issue, you are pretty much forced to use
Arc (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  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] "Implementation Inheritance" / mixins

2013-11-12 Thread Oren Ben-Kiki
It does force one to repeat all the members and all the function
signatures, which is (1) pretty tedious and (2) fragile, as making change
to the base would require making the same changes "everywhere".

The reuse-as-macro idea is to automate this process, so changes would
propagate without changing all the places in the code that use the mixin.

Another difference is that if f1 invokes f2, in the manual method, f1 will
invoke the original f2, while in the reuse-as-macro approach, it would
invoke the new f2.

Otherwise, this is basically the same thing, only manual.

Oren.



On Tue, Nov 12, 2013 at 12:46 PM, spir  wrote:

> On 11/11/2013 09:16 PM, Oren Ben-Kiki wrote:
>
>> 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).
>>
>
> My preferred approach is explicite derivation. May look like:
>
> struct S1 {
> x1 : uint,
> x2 : uint,
> x3 : uint = 1,
> x4 : uint = 1,
>
> fn f1 () {...},
> fn f2 () {...},
> }
>
> struct S2 [: S1] {  // optional subtyping for polymorphism
> x1 : uint,  // same field
> x2 : uint = 2,  // same field, with std value
> x3 : uint = 1,  // same field, same std value
> x4 : uint = 2,  // same field, diff std value
> x5 : uint,  // new field
> x6 : uint = 2,  // new field,  with std value
>
> fn f1 () = S1.f1,   // same func,  same value (reuse)
> fn f2 () {...}, // same func,  diff value (override)
> fn f3 () {...}, // new func
> }
>
> // more structs derived from S1
>
> An advantage is that each new type is completely defined on place; except
> for the body of reused functions, but one still has the signature and knows
> where the body is to be found.
>
> This apparently brings no novel issue and avoids a few know problems due
> to conventional "inductive" or "recursive" inheritance. All methods are
> right here. In theory and practice, I guess, one can well reuse from
> various existing types any suitable method; or more generally any role,
> trait, in ordinary sense of the terms. In case of conflict, the user
> explicitely states which one is intended, and there is no diamond problem.
>
> But the main gain in my view is that this scheme provides very good
> auto-documentation, I guess. I have however no idea of how to implement
> that in a static lang, esp the subtyping aspect (but do think it's no more
> complicated, maybe even less) (I implemented it in Lua, rather easy).
>
> 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
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 wrote:

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

2013-11-11 Thread Oren Ben-Kiki
"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.

Put another way, there's no difference for member access from within and
from outside the trait; both are interpreted as normal data member access
given the concrete struct (which includes the reused data members somewhere
in it).

pub struct FooS { member: int; }

pub struct BarS { ... reuse FooS::*; ... }
// Gets expanded to:
pub struct BarS { ... member: int; ... }
// Then compiled normally

/* Either inside or outside any trait, doesn't matter */ {
bar: BarS = ...;
bar.member; // Just a normal data member access
}
impl AnyTraitAtAll for BarS {
... {
self.member; // Still just a normal data member access
}
reuse SomeMixin::*; // Doesn't matter, `member` is still just a normal
data member
}



On Tue, Nov 12, 2013 at 9:43 AM, Patrick Walton wrote:

> On 11/12/13 4:32 PM, Oren Ben-Kiki wrote:
>
>> 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...?
>>
>
> 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.
>
> We don't want single inheritance because we're enamored with Java or
> anything, we want it because nothing that we've been able to come up with
> matches the performance that the prefix property on fields buys you. C++
> code can be very fast for a reason.
>
> We considered Go's anonymous fields but rejected them because they don't
> support virtual methods at the same time as field embedding.
>
> Patrick
>
>
___
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 wrote:

> 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


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


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

>
> On Sat, Nov 9, 2013 at 7:43 AM, Oren Ben-Kiki  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] 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 wrote:

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


[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] 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::(...) ?
Or add a self argument to it and then call it normally.


On Sat, Nov 9, 2013 at 1:31 AM, wuyunlong  wrote:

> struct Pool{
> produce_obj : ~fn()->T,
> elements : ~[T]
> }
>
> impl Pool{
>
>  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


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

> 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] 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 wrote:

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

> 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
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? :-)

On Sat, Nov 9, 2013 at 12:04 AM, Patrick Walton wrote:

> On 11/8/13 2:00 PM, Oren Ben-Kiki wrote:
>
>> 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.
>>
>
> You're arguing that we shouldn't have dynamically sized types, but I ask
> what your solution to `~Trait` is then.
>
> 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
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 wrote:

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

> On 11/08/2013 07:50 PM, Igor Bukanov wrote:
>
>> On 8 November 2013 18:35, Patrick Walton  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] 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  wrote:

> On Fri, Nov 8, 2013 at 1:59 AM, Daniel Micay wrote:
>
>> On Fri, Nov 8, 2013 at 1:52 AM, Oren Ben-Kiki  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] 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  wrote:

> On Fri, Nov 8, 2013 at 1:45 AM, Oren Ben-Kiki  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
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  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  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
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] 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  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


[rust-dev] The let keyword

2013-11-06 Thread Oren Ben-Kiki
Coming from Haskell, I realize some of the background of using this syntax
form. But looking at my code, I sometimes wish I could just write `x: Foo
:= foo();` instead of `let x: Foo = foo();`. All these `let`s in the code
seem noisy. I suppose this was an explicit design decision - I wonder if
anyone can say something about why one form was used over the other?
___
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 : *Points* = *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  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 Points {xs:~[T], ys:~[T]}
> fn main () {
>let mut ps = Points{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 = Points{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] 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 wrote:

> 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


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  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" AppendOnlyHeap pointer, but this seems hard to do
>> (same heap can hold objects of multiple types, etc.) so for now I have some
>> AlmostSafeHeapPointer 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] 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" AppendOnlyHeap pointer, but this seems hard to do
(same heap can hold objects of multiple types, etc.) so for now I have some
AlmostSafeHeapPointer 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  wrote:

> On Mon, Nov 4, 2013 at 1:29 AM, Oren Ben-Kiki  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-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  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] 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  wrote:

> On Mon, Nov 4, 2013 at 1:11 AM, Oren Ben-Kiki  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
On Mon, Nov 4, 2013 at 8:13 AM, Patrick Walton  wrote:

> On 11/3/13 10:11 PM, Oren Ben-Kiki wrote:
>
>> 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 :-)?
>>
>
> Two questions:
>
> (1) In your proposal, do the cross-thread GC pointers have mutable
> contents? If so, how do you prevent data races?
>

There are no cross-task data races because a heap can only be accessed by
one task at a time. This is actually tricky. The container of the heap +
components can be sent; separate components are not. I admit I'm not 100%
sure how to address that.

Preventing mutable aliasing requires an extra bit per pointer, but no
atomic operations or reference counting.


> (2) Why were ARC and RWarc not sufficient?
>

Because they don't allow cycles.
___
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] 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"  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  wrote:

> +1 I just subscribed yesterday and I really appreciates this overview :)
>
> -
> Gaetan
>
>
>
> 2013/10/29 Jack Moffitt 
>
>> > 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
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  wrote:

> On Mon, Oct 28, 2013 at 2:27 PM, Oren Ben-Kiki  wrote:
>
>> If you use ~Expr instead of @Expr, then the expressions would have to
>> form a tree (A = B + C). If you use Rc, 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] recursive types

2013-10-28 Thread Oren Ben-Kiki
If you use ~Expr instead of @Expr, then the expressions would have to form
a tree (A = B + C). If you use Rc, 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.


On Mon, Oct 28, 2013 at 8:25 PM, Steve Klabnik wrote:

> Yes, Oren is right here. You probably want to be using ~s rather than @s.
>
___
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 Rc (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] 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  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] 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
> `&fn(int) -> int` but found `&&fn(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 '' failed at 'explicit failure',
> /Users/rkrishnan/src/rust/src/libsyntax/diagnostic.rs:101
> task '' 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] 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  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_1(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_2(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_2(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] 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  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


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

> 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-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] Strange behavior about Writer trait

2013-10-18 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  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  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  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::Writer
>>> // 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 &Foo"? 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 `impl 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] Strange behavior about Writer trait

2013-10-18 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  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::Writer
> // 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 &Foo"? 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 `impl 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] Strange behavior about Writer trait

2013-10-18 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::Writer
// 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 &Foo"? 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 `impl 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] 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 wrote:

>  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 wrote:
>
>> 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 confusi

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

2013-10-16 Thread Oren Ben-Kiki
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 wrote:

> 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 the two options outlined above.
>
> 3. It's pure syntactic sugar, which means it's easy to implement and
> reason about.
>All `libsyntax` needs to do is to consume a list of bracket-counted
> token trees
>equal to the number of bangs, and introduce an artificial outer bracket
> pair if
>the number is higher than one.
>
> 4. It's just invocation sugar, which means there is no difference between
> defining a
>macro that uses this vs one that doesn't - you just declare them all
> assuming the
>explicit outer `()` pair.
>
> # Potential iss

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


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  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] The new format!

2013-09-30 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  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  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-dev<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 new format!

2013-09-30 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  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-dev<https://mail.mozilla.org/listinfo/rust-dev>
>
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


[rust-dev] The new format!

2013-09-30 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] 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
wrote:

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

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



On Mon, Sep 30, 2013 at 1:17 PM, Gábor Lehel  wrote:

> On Mon, Sep 30, 2013 at 8:31 AM, Oren Ben-Kiki  wrote:
>
>> 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.
>>
>
> Just a thought, but when you write "incrementally build a complex
> structure ... discard the whole thing", I think "arena allocation". That
> /might/ solve your borrowed pointer woes by letting you pervasively use
> borrowed pointers which all live at-most-as-long-as the arena (and hence
> the structure) itself. The borrow checker in my head is not advanced enough
> to let me really think it through though. And I don't think the compiler
> will let you send anything if there are borrowed pointers involved. There's
> an `arena` module[1] in libextra, but I've never tried it, and it uses `@`
> pointers internally which also precludes sending.
>
> (I wonder if there's any way to safely encode the idea that if all
> pointers are internal to the arena (there's nothing pointing in or out),
> then sending an ~arena should be safe, because its location in memory
> doesn't change. Presumably you would also need to move-send a pointer to
> the beginning of the structure inside of the arena alongside it. Maybe
> borrowed pointers are not the best fit here, or maybe they are, I dunno.)
>
> [1]: http://static.rust-lang.org/doc/master/extra/arena/struct.Arena.html
>
>
>
>>
>> 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 
>> wrote:
>>
>>> 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
>>> wo

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

2013-09-29 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 wrote:

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

>
> `On Sun, Sep 29, 2013 at 9:21 PM, Oren Ben-Kiki  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  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 ex

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

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  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] Should we add a Haskell-like `$` operator?

2013-09-26 Thread Oren Ben-Kiki
Right, the simple left-to-right chaining is why I thought that |> might be
a good fit for Rust - foo |> bar means exactly do foo and then bar.
On Sep 26, 2013 7:21 PM, "Jeff Petkau"  wrote:

> I don't think the problem with '$' is that it's infix; it's that it makes
> the data flow read right-to-left. The '|>' operator from F# is just "swap
> ($)", but it tends to make code much more readable.
>
> In fact, I think the whole appeal for object oriented style dot.method
> notation is that it makes things tend to read more consistently
> left-to-right. "I have a foo, and I do baz and blah and bar to it" vs. "I
> do bar to the result of doing blah to the result of doing baz to a foo."
>
> Jeff
>
>
> On Thu, Sep 26, 2013 at 8:37 AM, Tim Chevalier wrote:
>
>> FWIW, Haskellers often complain about the readability of code that
>> uses the `$` operator a lot. I've heard such complaints both from
>> people new to Haskell and more experienced Haskell programmers. In
>> general in Rust, we avoid infix operators (we have a fixed of them and
>> -- unlike Haskell -- no way for users to define new ones), and given
>> the history of `$` in Haskell, I don't see a particular reason to make
>> an exception.
>>
>> Cheers,
>> Tim
>>
>>
>>
>> --
>> Tim Chevalier * http://catamorphism.org/ * Often in error, never in doubt
>> "Being queer is not about a right to privacy; it is about the freedom
>> to be public, to just be who we are." -- anonymous, June 1990
>> ___
>> 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] 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 wrote:

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

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

> 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-dev
>
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


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  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] 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  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] 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"  wrote:

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


  1   2   >