Re: [rust-dev] Do I need to watch out for memory fragmentation?

2014-04-15 Thread Matthieu Monrocq
On Mon, Apr 14, 2014 at 10:32 PM, Daniel Micay danielmi...@gmail.comwrote:

 On 14/04/14 12:41 PM, Matthieu Monrocq wrote:
  Memory fragmentation is a potential issue in all languages that not use
  a Compacting GC, so yes.

 It's much less of an issue than people make it out to be on 32-bit, and
 it's a non-issue on 64-bit with a good allocator (jemalloc, tcmalloc).

 Small dynamic memory allocations are tightly packed in arenas, with a
 very low upper bound on fragmentation and metadata overhead. At a
 certain cutoff point, allocations begin to fall through directly to mmap
 instead of using the arenas. On 64-bit, the address space is enormous so
 fragmenting it is only a problem when it comes to causing TLB misses.


By the way, do you have any idea how this is going to pan out on processors
like the Mill CPU where the address space is shared among processes ?



  There are some attenuating circumstances in Rust, notably the fact that
  unless you use a ~ pointer the memory is allocated in a task private
  heap which is entirely recycled at the death of the task, but memory
  fragmentation is always a  potential issue.

 All dynamic memory allocations are currently done with the malloc family
 of functions, whether you use sendable types like `VecT`, `ArcT` and
 `~T` or task-local types like `RcT`. Using a task-local heap for types
 like `RcT` would only serve to *increase* the level of fragmentation
 by splitting it up more.

 For example, jemalloc implements thread-local caching, and then
 distributes the remaining workload across a fixed number of arenas.
 Increasing the level of thread-local caching has a performance benefit
 but by definition increases the level of fragmentation due to more
 unused capacity assigned to specific threads.


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


Re: [rust-dev] Do I need to watch out for memory fragmentation?

2014-04-15 Thread Daniel Micay
On 15/04/14 12:46 PM, Matthieu Monrocq wrote:

 By the way, do you have any idea how this is going to pan out on
 processors like the Mill CPU where the address space is shared among
 processes ?

x86_64 and ARM64 really have a 48-bit address space (cut down to 47-bit
by Linux to separate the kernel/userspace) while the Mill has a 60-bit
address space so it doesn't seem like a problem. It's an enormous amount
of usable virtual memory.



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


Re: [rust-dev] Do I need to watch out for memory fragmentation?

2014-04-14 Thread Matthieu Monrocq
Memory fragmentation is a potential issue in all languages that not use a
Compacting GC, so yes.

There are some attenuating circumstances in Rust, notably the fact that
unless you use a ~ pointer the memory is allocated in a task private heap
which is entirely recycled at the death of the task, but memory
fragmentation is always a  potential issue.


On Mon, Apr 14, 2014 at 6:19 PM, Zach Moazeni zach.li...@gmail.com wrote:

 Hello,

 I'm starting to explore Rust, and as someone who has primarily worked in
 GC'd languages I'm curious if I need to watch out for anything related to
 memory fragmentation. Or if Rust or LLVM is doing something under the
 covers where this is less of an issue.

 Kind regards,
 Zach

 ___
 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 I need to watch out for memory fragmentation?

2014-04-14 Thread Zach Moazeni
Thanks Matthieu.

I thought that might be the case.

I'll keep a look out as I work with Rust and ping the mailing list if I
need to cross that bridge.

Kind Regards,
Zach




On Mon, Apr 14, 2014 at 12:41 PM, Matthieu Monrocq 
matthieu.monr...@gmail.com wrote:

 Memory fragmentation is a potential issue in all languages that not use a
 Compacting GC, so yes.

 There are some attenuating circumstances in Rust, notably the fact that
 unless you use a ~ pointer the memory is allocated in a task private heap
 which is entirely recycled at the death of the task, but memory
 fragmentation is always a  potential issue.


 On Mon, Apr 14, 2014 at 6:19 PM, Zach Moazeni zach.li...@gmail.comwrote:

 Hello,

 I'm starting to explore Rust, and as someone who has primarily worked in
 GC'd languages I'm curious if I need to watch out for anything related to
 memory fragmentation. Or if Rust or LLVM is doing something under the
 covers where this is less of an issue.

 Kind regards,
 Zach

 ___
 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 I need to watch out for memory fragmentation?

2014-04-14 Thread Daniel Micay
On 14/04/14 12:41 PM, Matthieu Monrocq wrote:
 Memory fragmentation is a potential issue in all languages that not use
 a Compacting GC, so yes.

It's much less of an issue than people make it out to be on 32-bit, and
it's a non-issue on 64-bit with a good allocator (jemalloc, tcmalloc).

Small dynamic memory allocations are tightly packed in arenas, with a
very low upper bound on fragmentation and metadata overhead. At a
certain cutoff point, allocations begin to fall through directly to mmap
instead of using the arenas. On 64-bit, the address space is enormous so
fragmenting it is only a problem when it comes to causing TLB misses.

 There are some attenuating circumstances in Rust, notably the fact that
 unless you use a ~ pointer the memory is allocated in a task private
 heap which is entirely recycled at the death of the task, but memory
 fragmentation is always a  potential issue.

All dynamic memory allocations are currently done with the malloc family
of functions, whether you use sendable types like `VecT`, `ArcT` and
`~T` or task-local types like `RcT`. Using a task-local heap for types
like `RcT` would only serve to *increase* the level of fragmentation
by splitting it up more.

For example, jemalloc implements thread-local caching, and then
distributes the remaining workload across a fixed number of arenas.
Increasing the level of thread-local caching has a performance benefit
but by definition increases the level of fragmentation due to more
unused capacity assigned to specific threads.



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


Re: [rust-dev] do

2013-12-02 Thread Alex Bradbury
On 1 December 2013 03:54, Daniel Micay danielmi...@gmail.com wrote:
 I don't understand the point of `do` beyond making zero-parameter
 closures look a bit better. If it doesn't even do that, why bother? If
 an editor isn't indenting it properly, that's an editor issue. As far
 as I can tell, the vim indent file now handles it fine.

I agree, I feel do should be considered for removal - I feel the
amount of sugar it provides is minimal yet it complicates the language
unnecessarily. Supposing that Rust did not have the `do` syntax
already, I tend to think there would be resistance to adding it for
these reasons. Is there currently an issue open regarding the future
of `do`?

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


Re: [rust-dev] do

2013-12-02 Thread Gaetan
if do makes the code more readable or more beautiful, I higly recommend
keeping this sugar syntax. If there are corner cases where do doesn't do
the job, the developer should not use it in these cases.

It's still the same debat, when GIMP had this ugly multi panels system,
developers was saying it is a window manager issue to handle them
correctly. Yet, the GIMP software was a nightmare to use on almost
everybody's desktop. Now they solved with a single window application, it
is much more acceptable.

It will be the same here. If you rely on special feature of the editor to
indent properly. if is was only curly brace, most editor would do
indentation properly, but here you have || and other exotic syntax most
editor doesn't understand until a proper extension is written (which can
take year for some editors).

I personnally will always find much more readable (and maintainable):

do function { someotherFunction() };

than

function(|| someotherFunction());


-
Gaetan



2013/12/2 Alex Bradbury a...@asbradbury.org

 On 1 December 2013 03:54, Daniel Micay danielmi...@gmail.com wrote:
  I don't understand the point of `do` beyond making zero-parameter
  closures look a bit better. If it doesn't even do that, why bother? If
  an editor isn't indenting it properly, that's an editor issue. As far
  as I can tell, the vim indent file now handles it fine.

 I agree, I feel do should be considered for removal - I feel the
 amount of sugar it provides is minimal yet it complicates the language
 unnecessarily. Supposing that Rust did not have the `do` syntax
 already, I tend to think there would be resistance to adding it for
 these reasons. Is there currently an issue open regarding the future
 of `do`?

 Alex
 ___
 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-12-01 Thread Vadim
Not sure what you mean by `self` on `T`.   I thought traits can
take self by-value?


On Dec 1, 2013, at 1:22 PM, Patrick Walton pcwal...@mozilla.com wrote:

 On 12/1/13 7:42 AM, Vadim wrote:
 Once fn()'s should consume their environment, perhaps it should be
 simply self, where Self is non-copyable, so it gets moved out?

 Doesn't work unless we have unboxed closures, as you can't call a method that 
 takes `self` on `T`.

 Patrick

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


Re: [rust-dev] do

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

Patrick 

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

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

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

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

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

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

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

 (a) Kill ``do``

...

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

...




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

-- 
Sent from my Android phone with K-9 Mail. Please excuse my brevity.___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] do

2013-11-30 Thread Patrick Walton
The main reason for do's existence is to make task spawning look nice. The 
closure inference was removed throughout the language because it masked 
allocation and doesn't work well with custom smart pointers. If do is still 
causing confusion, I'd rather just remove it entirely.

Patrick

Chris Morgan m...@chrismorgan.info wrote:
(Do I win the prize for the shortest thread name yet?)

 error: last argument in `do` call has non-procedure type: ||

In the past three or four days I've seen at least as many enquiries in
#rust about this error, and I'm sure there have been at least several
others while I haven't been monitoring it. This is evidently causing
quite a bit of confusion.

Here's a summary of the change. The syntax is the same as it was
before::

do expr { block }
do expr |args| { block }
do expr(args) { block }
do expr(args) |args| { block }

These used to desugar to the following, respectively::

expr(|| { block })
expr(|args| { block })
expr(args, || { block })
expr(args, |args| { block })

These now desugar to the following, respectively::

expr(proc() { block })
expr(proc(args) { block })
expr(args, proc() { block })
expr(args, proc(args) { block })

The change is that it now accepts a procedure rather than a closure.
No syntax change, just a semantics change which breaks a lot of code.

Closure: a stack function; used to be ``fn(..) - _``, is now ``|..|
- _``. Can be called multiple times, requires no allocations and is
not Send.

Procedure: a heap function; used to be ``~once fn(..) - _``, is now
``proc(..) - _``. Can be called once, requires heap allocation and is
Send.

Procedures are good for sending cross-task; things like the task body
are a good match. Still, I think there are a few problems with how
things are at present (i.e. after the do semantics change):

1. ``do`` is still using the syntax of a closure (``|..| { .. }``),
despite it now being a procedure.

2. All of a sudden, things using closures need to shift away from
using ``do`` or use procedures; this is causing confusion and may
cause bad design decisions where nice sugar triumphs over what is
actually needed; often the best solution may not be clear. (I, for
example, had not thought about the fact that ``proc`` was going to
allocate; the ``~once fn`` name was clearer about that. I'll speak
about ``once fn`` another time. Don't mention it now, this thread is
just about ``do``.)

I have two solutions that I think could answer these concerns. Leaving
it as it is seems a bad idea to me.

(a) Kill ``do``
---

I've had mixed feelings about ``do``. Overall, it's pretty trivial
syntax sugar, but it's sugar of a dubious sort, because it changes
something that looks like a function call with N arguments to be a
function call with N+1 arguments. That's just a matter of learning it.

Still, ``do`` *is* nice sugar in the way it gets rid of parentheses at
the end. Overall, is it worth it? I don't know.

Once ``do`` is gone, there's no problem left: just remove the sugar
*everywhere* it was used and everything works and will do for the
foreseeable future.

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


The syntax of ``do`` can be clearly seen to include the closure
syntax. We could easily extend it to support both closures and
procedures.

Here is a proposed ``do`` using closures once more, keeping the syntax
it had last week::

do expr || { block }
do expr(args) || { block }
do expr |args| { block }
do expr(args) |args| { block }

Here is a proposed ``do`` using procedures as the current behaviour
is, but with new syntax which is clearly a procedure::

do expr proc() { block }
do expr(args) proc() { block }
do expr proc(args) { block }
do expr(args) proc(args) { block }

This does leave these cases which are currently valid unclear::

do expr { block }
do expr(args) { block }

The options for this are (a) disallowing it; (b) making it always of
the function types; and (c) inferring the type. I generally prefer the
last solution but it is the most difficult. I'm not sure how it all
fits into the function traits stuff at all.

Incidentally, all this leaves the possibility open of making ``do``
work for *any* argument type, where ``do expr1 expr2`` simply desugars
to ``expr1(expr2)`` and ``do expr1(args) expr2`` to ``do expr1(args,
expr2)``. I don't know if that would be a good thing or not; it's
probably best to avoid discussion of that at present.

Summary
===

Leaving ``do`` in its present form seems to me a distinctly bad idea,
with the syntax of one form of function while it uses another form of
function. I think we need to redo ``do`` very soon. (I'd save this
joke for later in the thread, but I'm afraid someone else might steal
it. I expect all responses to indicate they're in favour of this by
using the title Re: do :P.)

For myself, I have no preference to indicate; I 

Re: [rust-dev] do

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

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

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



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

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

 Patrick

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

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

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

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

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

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

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

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

 (a) Kill ``do``

 ...

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

 ...

 --

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


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

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


Re: [rust-dev] do

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


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

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

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

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

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

 -benh


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


Re: [rust-dev] do

2013-11-30 Thread Benjamin Striegel
 If do is still causing confusion, I'd rather just remove it entirely.

I rather like `do`. I agree that if it's confusing it should be considered
for removal, but IMO the confusion here stems from familiarity with the
prior, obsolete semantics rather than any inherent problem with the
construct itself. I say we should wait for people to familiarize themselves
with the new closure types before thinking about giving it the axe.


On Sat, Nov 30, 2013 at 3:26 AM, Patrick Walton pwal...@mozilla.com wrote:

 The main reason for do's existence is to make task spawning look nice.
 The closure inference was removed throughout the language because it masked
 allocation and doesn't work well with custom smart pointers. If do is
 still causing confusion, I'd rather just remove it entirely.

 Patrick

 Chris Morgan m...@chrismorgan.info wrote:

 (Do I win the prize for the shortest thread name yet?)

 error: last argument in `do` call has non-procedure type: ||


 In the past three or four days I've seen at least as many enquiries in
 #rust about this error, and I'm sure there have been at least several
 others while I haven't been monitoring it. This is evidently causing

 quite a bit of confusion.

 Here's a summary of the change. The syntax is the same as it was before::

 do expr { block }
 do expr |args| { block }
 do expr(args) { block }
 do expr(args) |args| { block }

 These used to desugar to the following, respectively::

 expr(|| { block })
 expr(|args| { block })
 expr(args, || { block })
 expr(args, |args| { block })

 These now desugar to the following, respectively
  ::

 expr(proc() { block })
 expr(proc(args) { block })
 expr(args, proc() { block })
 expr(args, proc(args) { block })

 The change is that it now accepts a procedure rather than a closure.
 No syntax change, just a semantics change which breaks a lot of code.

 Closure: a stack function; used to be ``fn(..) - _``, is now ``|..|
 - _``. Can be called multiple times, requires no allocations and is
 not Send.

 Procedure: a heap function; used to be ``~once fn(..) - _``, is now

 ``proc(..) - _``. Can be called once, requires heap allocation and is
 Send.

 Procedures are good for sending cross-task; things like the task body
 are a good match. Still, I think there are a few problems with how

 things are at present (i.e. after the do semantics change):

 1. ``do`` is still using the syntax of a closure (``|..| { .. }``),
 despite it now being a procedure.


  2. All
 of a sudden, things using closures need to shift away from
 using ``do`` or use procedures; this is causing confusion and may
 cause bad design decisions where nice sugar triumphs over what is
 actually needed; often the best solution may not be clear. (I, for

 example, had not thought about the fact that ``proc`` was going to
 allocate; the ``~once fn`` name was clearer about that. I'll speak
 about ``once fn`` another time. Don't mention it now, this thread is

 just about ``do``.)

 I have two solutions that I think could answer these concerns. Leaving
 it as it is seems a bad idea to me.

 (a) Kill ``do``
 ---

 I've had mixed feelings about ``do``. Overall, it's pretty trivial

 syntax sugar, but it's sugar of a dubious sort, because it changes
 something that looks like a function call with N arguments to be a
 function call with N+1 arguments. That's just a matter of learning it.
  br
 /

 Still, ``do`` *is* nice sugar in the way it gets rid of parentheses at
 the end. Overall, is it worth it? I don't know.

 Once ``do`` is gone, there's no problem left: just remove the sugar

 *everywhere* it was used and everything works and will do for the
 foreseeable future.

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


 The syntax of ``do`` can be clearly seen to include the closure

 syntax. We could easily extend it to support both closures and
 procedures.

 Here is a proposed ``do`` using closures once more, keeping the syntax
 it had last week::

 do expr || { block }
 do expr(args) || { block }

 do expr |args| { block }
 do expr(args) |args| { block }

 Here is a proposed ``do`` using procedures as the current behaviour
 is, but with new syntax which is clearly a procedure::

 do expr proc() { block }
 do expr(args) proc() { block }
  br /do
 expr proc(args) { block }

 do expr(args) proc(args) { block }

 This does leave these cases which are currently valid unclear::

 do expr { block }
 do expr(args) { block }

 The options for this are (a) disallowing it; (b) making it always of

 the function types; and (c) inferring the type. I generally prefer the
 last solution but it is the most difficult. I'm not sure how it all
 fits into the function traits stuff at all.

 Incidentally, all this leaves the possibility open of making ``do``

 work for *any* argument type, where ``do expr1 expr2`` simply desugars
 to ``expr1(expr2)`` and ``do expr1(args) expr2`` to ``do expr1(args,
 expr2)``. I don't know if that would be a 

Re: [rust-dev] do

2013-11-30 Thread Tiffany Bennett
On Sat, Nov 30, 2013 at 9:34 AM, Oren Ben-Kiki o...@ben-kiki.org wrote:

 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.


I agree, having annotations so that the type system can enforce safety is a
better idea than hacking around it with alternate versions of every
function for taking closures only used once.
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] do

2013-11-30 Thread Patrick Walton

On 11/30/13 3:25 AM, Oren Ben-Kiki wrote:

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.


You can use the with pattern, as discussed elsewhere in the thread.


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


That doesn't work if `Option` is to actually implement the container 
traits, since it has to have the same signature. And if it doesn't 
implement those traits, the with pattern works.


Patrick

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


Re: [rust-dev] do

2013-11-30 Thread Kevin Cantu
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.

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

 On 11/30/13 8:32 AM, Tiffany Bennett wrote:


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

 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.


 I agree, having annotations so that the type system can enforce safety
 is a better idea than hacking around it with alternate versions of every
 function for taking closures only used once.


 You don't need alternate versions: you just need one version that passes
 arguments through.

 I don't agree in general that the right solution for every problem that
 can be solved through the type system is in the type system. Every type
 system feature has a cost; when something can be done via what's already
 present in the language then it becomes difficult to justify adding more
 features to what is already a quite complex type system by industry
 standards.

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

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.

Patrick

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


Re: [rust-dev] do

2013-11-30 Thread Ziad Hatahet
Should an issue for this be filed then?

--
Ziad


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

 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.


 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 Kevin Ballard
On Nov 30, 2013, at 10:02 AM, Patrick Walton pcwal...@mozilla.com wrote:

 I don't agree in general that the right solution for every problem that can 
 be solved through the type system is in the type system. Every type system 
 feature has a cost; when something can be done via what's already present in 
 the language then it becomes difficult to justify adding more features to 
 what is already a quite complex type system by industry standards.

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.

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


Re: [rust-dev] do

2013-11-30 Thread Kevin Ballard
On Nov 30, 2013, at 10:20 AM, Patrick Walton pcwal...@mozilla.com wrote:

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

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

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

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


Re: [rust-dev] do

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

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

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

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

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

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

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


Re: [rust-dev] do

2013-11-30 Thread Benjamin Striegel
 (I forget the name, sadly)

This is usually referred to as Tennet's Correspondence Principle:

http://gafter.blogspot.com/2006/08/tennents-correspondence-principle-and.html

...though it is sometimes debated whether or not the modern interpretation
of this principle is actually what Tennet intended (the book in which it
appeared is apparently quite hard to get a hold of).


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

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

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

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

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

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

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


Re: [rust-dev] do

2013-11-30 Thread Patrick Walton

On 11/30/13 6:34 AM, Oren Ben-Kiki wrote:

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.


As I mentioned before, most of those in the library can be turned into 
RAII. (I made informal measurements of the number of them that could be 
RAII-ified when I was removing do; the vast majority would be better 
as RAII.) Some of those that can't are generic container traits that 
wouldn't benefit from `once fn` anyway. For the remainder, adding the 
tuples doesn't seem much of a burden to me.


If it is, we can always add `once fn` if we have to, but we haven't 
really tried not having it.



And then there's the possibility of modifying
variables...


Can you elaborate? You can already use mut on individual pattern 
bindings, including individual elements of destructured tuples.


Patrick

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


Re: [rust-dev] do

2013-11-30 Thread Patrick Walton

On 11/30/13 12:04 PM, Oren Ben-Kiki wrote:

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


If you decompose into a lambda plus the tupled set of upvars which it's 
moving out of, then this respects TCP.


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


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

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

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


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

 Patrick


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

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


Re: [rust-dev] do

2013-11-30 Thread Patrick Walton

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

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


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


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

Patrick

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


Re: [rust-dev] do

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


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

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

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


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

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

 Patrick


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


Re: [rust-dev] do

2013-11-30 Thread Patrick Walton
It's also not clear to me how once fn can decompose into a trait in the 
future. The goal in the future is to make fn() a type of trait, to allow for 
C++-like zero-indirection closures. The different types of functions that we 
have today correspond to different self parameters: |A|-B corresponds to 
mut self and proc() corresponds to ~self. But I don't see where once 
fn fits in.

Perhaps the right thing is to gate once fn on by-value anonymous closures. I 
think once functions may be able to be made to work as function trait bounds. 
But implementing once fn right now seems to close off our ability to have 
closures with the same efficiency as C++11 in the future, unless there's 
something I'm missing.

Patrick 

Patrick Walton pcwal...@mozilla.com wrote:
On 11/30/13 12:04 PM, Oren Ben-Kiki wrote:
 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 :-)

If you decompose into a lambda plus the tupled set of upvars which it's

moving out of, then this respects TCP.

Patrick

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

-- 
Sent from my Android phone with K-9 Mail. Please excuse my brevity.___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] do

2013-11-30 Thread Tony Arcieri
On Fri, Nov 29, 2013 at 11:34 PM, Oren Ben-Kiki o...@ben-kiki.org wrote:

 I find `do` syntax form is vital for DSL-ish code.


 On Sat, Nov 30, 2013 at 12:26 AM, Patrick Walton pwal...@mozilla.com
 wrote:

 The main reason for do's existence is to make task spawning look nice.


I've got to say that the do syntax is one of the things that appeals to
me about Rust, and will probably appeal to the people that Steve Klabnik is
drawing to the language with Rust for Rubyists.

It might seem like a small thing but the effects on the type of programs
you can write, it actually has a pretty profound effect, IMO.

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


Re: [rust-dev] do

2013-11-30 Thread Michael Letterle
On Sat, Nov 30, 2013 at 7:55 PM, Tony Arcieri basc...@gmail.com wrote:

 On Fri, Nov 29, 2013 at 11:34 PM, Oren Ben-Kiki o...@ben-kiki.org wrote:

 I find `do` syntax form is vital for DSL-ish code.


  On Sat, Nov 30, 2013 at 12:26 AM, Patrick Walton pwal...@mozilla.com
  wrote:

 The main reason for do's existence is to make task spawning look nice.


 I've got to say that the do syntax is one of the things that appeals to
 me about Rust, and will probably appeal to the people that Steve Klabnik is
 drawing to the language with Rust for Rubyists.

 It might seem like a small thing but the effects on the type of programs
 you can write, it actually has a pretty profound effect, IMO.

 --
 Tony Arcieri


I agree actually, I was using do to implement some convenience logic and my
code went from:

do function { someotherFunction() };

to

function(|| someotherFunction());

Maybe I'm abusing something here, but I found the first format more
intuitive and elegant...

I know there's rumblings about io conditions going away, but the change
also makes that more awkward... :/
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] do

2013-11-30 Thread Patrick Walton

On 11/30/13 7:25 PM, Michael Letterle wrote:

I've got to say that the do syntax is one of the things that
appeals to me about Rust, and will probably appeal to the people
that Steve Klabnik is drawing to the language with Rust for Rubyists.

It might seem like a small thing but the effects on the type of
programs you can write, it actually has a pretty profound effect, IMO.

--
Tony Arcieri


I agree actually, I was using do to implement some convenience logic and
my code went from:

 do function { someotherFunction() };

to

 function(|| someotherFunction());

Maybe I'm abusing something here, but I found the first format more
intuitive and elegant...

I know there's rumblings about io conditions going away, but the change
also makes that more awkward... :/


The point of this change was to got rid of closure type inference. With 
the old rules it was not possible to see whether you were allocating 
without looking at the type signature of the function you're calling. 
Moreover the capture rules are extremely different depending on the type 
of closure it is. It's too much magic for Rust.


Patrick

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


Re: [rust-dev] do

2013-11-30 Thread Brendan Zabarauskas
On 30 Nov 2013, at 5:34 pm, Oren Ben-Kiki o...@ben-kiki.org wrote:

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

This really is an important point. I would recommend folks look at Shoes 
(http://shoesrb.com/) for an example of how Ruby’s block syntax can help create 
beautiful APIs.

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


Re: [rust-dev] do

2013-11-30 Thread Patrick Walton

On 11/30/13 7:35 PM, Brendan Zabarauskas wrote:

On 30 Nov 2013, at 5:34 pm, Oren Ben-Kiki o...@ben-kiki.org wrote:


I find `do` syntax form is vital for DSL-ish code. Getting rid of
it

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


This really is an important point. I would recommend folks look at

Shoes (http://shoesrb.com/) for an example of how Ruby’s block syntax
can help create beautiful APIs.

Ruby is a totally different language without two kinds of closures. The 
problem is not the sugar, it's the inference.


Patrick

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


Re: [rust-dev] do

2013-11-30 Thread Corey Richardson
On Sat, Nov 30, 2013 at 10:28 PM, Patrick Walton pcwal...@mozilla.com wrote:
 On 11/30/13 7:25 PM, Michael Letterle wrote:

 I've got to say that the do syntax is one of the things that
 appeals to me about Rust, and will probably appeal to the people
 that Steve Klabnik is drawing to the language with Rust for Rubyists.

 It might seem like a small thing but the effects on the type of
 programs you can write, it actually has a pretty profound effect, IMO.

 --
 Tony Arcieri


 I agree actually, I was using do to implement some convenience logic and
 my code went from:

  do function { someotherFunction() };

 to

  function(|| someotherFunction());

 Maybe I'm abusing something here, but I found the first format more
 intuitive and elegant...

 I know there's rumblings about io conditions going away, but the change
 also makes that more awkward... :/


 The point of this change was to got rid of closure type inference. With the
 old rules it was not possible to see whether you were allocating without
 looking at the type signature of the function you're calling. Moreover the
 capture rules are extremely different depending on the type of closure it
 is. It's too much magic for Rust.


Maybe `do` can just change from procs to closures. I can't really say
how often I've actually wanted a proc. Task bodies are a far minority
compared to other uses of do, from the backlash, and I don't find
`spawn(proc() { ... })` that unappealing.
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] do

2013-11-30 Thread Patrick Walton

On 11/30/13 7:43 PM, Corey Richardson wrote:

Maybe `do` can just change from procs to closures. I can't really say
how often I've actually wanted a proc. Task bodies are a far minority
compared to other uses of do, from the backlash, and I don't find
`spawn(proc() { ... })` that unappealing.


I really don't see do for stack closures as something that makes sense 
in current Rust. It made sense back when we used it for loops and didn't 
use RAII (as Ruby does), but the experiment of using blocks in place of 
RAII for stuff like with_c_str or unkillable has failed: it leads to 
too much rightward drift.


Patrick

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


Re: [rust-dev] do

2013-11-30 Thread Kevin Ballard
On Nov 30, 2013, at 7:28 PM, Patrick Walton pcwal...@mozilla.com wrote:

 On 11/30/13 7:25 PM, Michael Letterle wrote:
I've got to say that the do syntax is one of the things that
appeals to me about Rust, and will probably appeal to the people
that Steve Klabnik is drawing to the language with Rust for Rubyists.
 
It might seem like a small thing but the effects on the type of
programs you can write, it actually has a pretty profound effect, IMO.
 
--
Tony Arcieri
 
 
 I agree actually, I was using do to implement some convenience logic and
 my code went from:
 
 do function { someotherFunction() };
 
 to
 
 function(|| someotherFunction());
 
 Maybe I'm abusing something here, but I found the first format more
 intuitive and elegant...
 
 I know there's rumblings about io conditions going away, but the change
 also makes that more awkward... :/
 
 The point of this change was to got rid of closure type inference. With the 
 old rules it was not possible to see whether you were allocating without 
 looking at the type signature of the function you're calling. Moreover the 
 capture rules are extremely different depending on the type of closure it is. 
 It's too much magic for Rust.

Can we not simply allow `do` to work with both stack closures and heap 
closures? With the current proc() stuff that would be

do spawn proc() {
..
}

And yes, I know do originally existed to make spawning nicer, but that's not 
really that ugly, and allows for using `do` with stack closures (which, in code 
I've seen, has been by far the majority of use-cases for `do`). Also, IMO 
making the existence of a proc more obvious seems like a good idea (given the 
effect it has on captured values). Similarly, if this change were made, then a 
nullary stack closure would be called like

do some_func || {
..
}

which I think is fine, as it makes the stack closure obvious, although the 
potential confusion of the || with the logical-OR operator is very slightly 
worrisome (but not terribly so, especially because pushing RAII should mean 
that functions that take nullary stack closures in tail position shouldn't be 
common).

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


Re: [rust-dev] do

2013-11-30 Thread Patrick Walton

On 11/30/13 7:50 PM, Kevin Ballard wrote:

do spawn proc() {
 ..
}


That's essentially just as verbose as not having do.



And yes, I know do originally existed to make spawning nicer, but
that's not really that ugly, and allows for using `do` with stack
closures (which, in code I've seen, has been by far the majority of
use-cases for `do`).


That's because, in the vast majority of cases:

(1) We don't use RAII enough. This should be fixed.

(2) `do` was being used for stuff like `do v.map { ... }`, which I've 
always considered something of an abuse. map is a higher order 
function; it should look like a higher order function and not an iterator.


Patrick

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


Re: [rust-dev] do

2013-11-30 Thread Daniel Micay
On Sat, Nov 30, 2013 at 10:50 PM, Kevin Ballard ke...@sb.org wrote:
 On Nov 30, 2013, at 7:28 PM, Patrick Walton pcwal...@mozilla.com wrote:

 On 11/30/13 7:25 PM, Michael Letterle wrote:
I've got to say that the do syntax is one of the things that
appeals to me about Rust, and will probably appeal to the people
that Steve Klabnik is drawing to the language with Rust for Rubyists.

It might seem like a small thing but the effects on the type of
programs you can write, it actually has a pretty profound effect, IMO.

--
Tony Arcieri


 I agree actually, I was using do to implement some convenience logic and
 my code went from:

 do function { someotherFunction() };

 to

 function(|| someotherFunction());

 Maybe I'm abusing something here, but I found the first format more
 intuitive and elegant...

 I know there's rumblings about io conditions going away, but the change
 also makes that more awkward... :/

 The point of this change was to got rid of closure type inference. With the 
 old rules it was not possible to see whether you were allocating without 
 looking at the type signature of the function you're calling. Moreover the 
 capture rules are extremely different depending on the type of closure it 
 is. It's too much magic for Rust.

 Can we not simply allow `do` to work with both stack closures and heap 
 closures? With the current proc() stuff that would be

 do spawn proc() {
 ..
 }

 And yes, I know do originally existed to make spawning nicer, but that's not 
 really that ugly, and allows for using `do` with stack closures (which, in 
 code I've seen, has been by far the majority of use-cases for `do`). Also, 
 IMO making the existence of a proc more obvious seems like a good idea (given 
 the effect it has on captured values). Similarly, if this change were made, 
 then a nullary stack closure would be called like

 do some_func || {
 ..
 }

 which I think is fine, as it makes the stack closure obvious, although the 
 potential confusion of the || with the logical-OR operator is very slightly 
 worrisome (but not terribly so, especially because pushing RAII should mean 
 that functions that take nullary stack closures in tail position shouldn't be 
 common).

 -Kevin

I don't understand the point of `do` beyond making zero-parameter
closures look a bit better. If it doesn't even do that, why bother? If
an editor isn't indenting it properly, that's an editor issue. As far
as I can tell, the vim indent file now handles it fine.
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] do

2013-11-30 Thread Brendan Zabarauskas

On 1 Dec 2013, at 1:45 pm, Patrick Walton pcwal...@mozilla.com wrote:

 the experiment of using blocks in place of RAII for stuff like with_c_str 
 or unkillable has failed: it leads to too much rightward drift.
 
 Patrick

I guess I can agree with that. I remember when I first started with Rust doing: 
`some_c_func(“hi”.with_c_str(|s| s))`, which completely negates the safety 
guarantees of the closure. How would this look with RAII?

By ‘rightward drift’ do you mean in terms of multiple nested closures?

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


Re: [rust-dev] do

2013-11-30 Thread Kevin Ballard
On Nov 30, 2013, at 7:54 PM, Daniel Micay danielmi...@gmail.com wrote:

 On Sat, Nov 30, 2013 at 10:50 PM, Kevin Ballard ke...@sb.org wrote:
 On Nov 30, 2013, at 7:28 PM, Patrick Walton pcwal...@mozilla.com wrote:
 
 On 11/30/13 7:25 PM, Michael Letterle wrote:
   I've got to say that the do syntax is one of the things that
   appeals to me about Rust, and will probably appeal to the people
   that Steve Klabnik is drawing to the language with Rust for Rubyists.
 
   It might seem like a small thing but the effects on the type of
   programs you can write, it actually has a pretty profound effect, IMO.
 
   --
   Tony Arcieri
 
 
 I agree actually, I was using do to implement some convenience logic and
 my code went from:
 
do function { someotherFunction() };
 
 to
 
function(|| someotherFunction());
 
 Maybe I'm abusing something here, but I found the first format more
 intuitive and elegant...
 
 I know there's rumblings about io conditions going away, but the change
 also makes that more awkward... :/
 
 The point of this change was to got rid of closure type inference. With the 
 old rules it was not possible to see whether you were allocating without 
 looking at the type signature of the function you're calling. Moreover the 
 capture rules are extremely different depending on the type of closure it 
 is. It's too much magic for Rust.
 
 Can we not simply allow `do` to work with both stack closures and heap 
 closures? With the current proc() stuff that would be
 
 do spawn proc() {
..
 }
 
 And yes, I know do originally existed to make spawning nicer, but that's not 
 really that ugly, and allows for using `do` with stack closures (which, in 
 code I've seen, has been by far the majority of use-cases for `do`). Also, 
 IMO making the existence of a proc more obvious seems like a good idea 
 (given the effect it has on captured values). Similarly, if this change were 
 made, then a nullary stack closure would be called like
 
 do some_func || {
..
 }
 
 which I think is fine, as it makes the stack closure obvious, although the 
 potential confusion of the || with the logical-OR operator is very slightly 
 worrisome (but not terribly so, especially because pushing RAII should mean 
 that functions that take nullary stack closures in tail position shouldn't 
 be common).
 
 -Kevin
 
 I don't understand the point of `do` beyond making zero-parameter
 closures look a bit better. If it doesn't even do that, why bother? If
 an editor isn't indenting it properly, that's an editor issue. As far
 as I can tell, the vim indent file now handles it fine.

At this point, given that stack closures no longer work with do, it seems to me 
that do is just Rust's attempt at providing a syntactical nicety analogous to 
Go's `go` operator.

If we can't have `do` working with stack closures, my feeling is we should just 
remove it. Keeping around special syntax purely for the case of heap closures 
seems like unnecessary complexity. Although my preference is still for 
restoring `do`'s ability to work with stack closures.

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


Re: [rust-dev] do

2013-11-30 Thread Patrick Walton

On 11/30/13 8:06 PM, Brendan Zabarauskas wrote:


On 1 Dec 2013, at 1:45 pm, Patrick Walton pcwal...@mozilla.com wrote:


the experiment of using blocks in place of RAII for stuff like with_c_str or 
unkillable has failed: it leads to too much rightward drift.

Patrick


I guess I can agree with that. I remember when I first started with Rust doing: 
`some_c_func(“hi”.with_c_str(|s| s))`, which completely negates the safety 
guarantees of the closure. How would this look with RAII?


Just return a package consisting of either an owned string (if 
allocation needed to be done) or a borrowed pointer to the original 
string (if no allocation needed to be done). Then you can put a method 
on that enum yielding the raw C pointer. Voila, no rightward drift :)



By ‘rightward drift’ do you mean in terms of multiple nested closures?


Right. I've seen with_c_str six levels deep :(

RAII also has the advantage that you can more precisely control the 
scope of the effect that you're delimiting: you can move it around, 
destruct it early, and so on. For example, an RAII'd version of 
task::unkillable would not only have no rightward drift, but the token 
that makes you killable again could also be destructed on some code 
paths but not others, moved to other functions, etc.


Patrick

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


Re: [rust-dev] do

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

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

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

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

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

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

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

 (a) Kill ``do``

...

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

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


[rust-dev] Do we have shared ports?

2013-05-28 Thread Alexander Stavonin
Hi!

As I know, As I know, we have SharedChan mechanism which can be used for
many clients - server communications. But how can I send response from
server to many clients? This is not commonly used case, and looks like
there is no such mechanism or I've missed something?

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


Re: [rust-dev] Do we have shared ports?

2013-05-28 Thread Matthieu Monrocq
Hi,

I am not quite sure whether you are asking for a multi-cast feature (all
clients receive a copy of the message) or for a send-to-one-among feature
(in which one of the available client would pick up the message).

Could you elaborate ?

-- Matthieu


On Tue, May 28, 2013 at 11:45 AM, Alexander Stavonin
a.stavo...@gmail.comwrote:

 Hi!

 As I know, As I know, we have SharedChan mechanism which can be used for
 many clients - server communications. But how can I send response from
 server to many clients? This is not commonly used case, and looks like
 there is no such mechanism or I've missed something?

 Best regards,
 Alexander.

 ___
 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 we have shared ports?

2013-05-28 Thread Brian Anderson

On 05/28/2013 02:45 AM, Alexander Stavonin wrote:

Hi!

As I know, As I know, we have SharedChan mechanism which can be used 
for many clients - server communications. But how can I send 
response from server to many clients? This is not commonly used case, 
and looks like there is no such mechanism or I've missed something?


There isn't a type defined for this currently.
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


[rust-dev] Do-notation?

2013-05-23 Thread Ziad Hatahet
Say we want to implement the following function:

fn add(x: Optionint, y: Optionint) - Optionint { ... }

Some functional languages, like Haskell and Scala offer some sort of a do
notation to make unwrapping multiple Option type values easier.

add :: Maybe Int - Maybe Int - Maybe Int
add mx my = do
  x - mx
  y - my
  return (x + y)

Is there an equivalent construct in Rust?

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


Re: [rust-dev] Do-notation?

2013-05-23 Thread Masklinn
On 2013-05-23, at 14:28 , Benjamin Striegel wrote:

 There's no generalized notation, but a while ago I overloaded the +
 operator on Option such that it automatically unwraps them, adds the
 contained elements together (for any two types that implement Add), and
 returns a wrapped result.
 
let foo = Some(1) + Some(4);
error!(foo);  // Some(5)
 
 
 This behavior seems mostly innocuous, but there's some question as to
 whether the behavior is correct (and also whether we want to support this
 sort of overloading at all): https://github.com/mozilla/rust/issues/6002
 
 If this sort of thing is useful, it's feasible that we could overload the
 other operators as well.

I think that's way too specialized and repetitive for the general case.
A form of zip/map_zip for option would be better as it'd allow applying
arbitrary operations cleanly, something along the lines of fn zipT,
U(t: OptionT, u: OptionU) - Option(T, U)

And thus you would write something along the lines of:

let foo = option::zip(Some(1), Some(2)).map(|(a, b)| { a + b })

zip would be something along the lines of:

match (t, u) {
(Some t1, Some v1) = Some (t1, v1),
_ = None
}

(well it would require pointer and lifetime powder thing, but you get the idea)
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Do-notation?

2013-05-23 Thread Huon Wilson

On 23/05/13 16:13, Ziad Hatahet wrote:

Say we want to implement the following function:

fn add(x: Optionint, y: Optionint) - Optionint { ... }

Some functional languages, like Haskell and Scala offer some sort of a 
do notation to make unwrapping multiple Option type values easier.


add :: Maybe Int - Maybe Int - Maybe Int
add mx my = do
  x - mx
  y - my
  return (x + y)

Is there an equivalent construct in Rust?

--
Ziad



I just whipped up a very basic do-notation syntax extension[1] (it can't 
be called do! unfortunately), it was much easier than I was expecting. 
The following compiles fine:


fn main () {
let x = do_!(bind a = Some(1);
 bind b = None;
 let res = a + b;
 Some(res));

println(fmt!(%?, x))
}

and prints None (or Some(3), if you change the None to Some(2)). It 
works for anything that defines a method called chain (e.g. Result), 
but there's no generic return equivalent yet, so that has to be changed 
for each type. (I chose to use bind rather than - (or similar) for 
parsing ease.)



Huon

[1]: https://github.com/huonw/rust/tree/do-notation
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Do-notation?

2013-05-23 Thread Ziad Hatahet
Thanks all for the replies.

Niko, could you point out where in the code you defined the macro you
mention?

Thanks

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


Re: [rust-dev] Do-notation?

2013-05-23 Thread Niko Matsakis
I was thinking of the if_ok! macro, which is intended for use with the Result 
type:

```
macro_rules! if_ok(
($inp: expr) = (
match $inp {
Ok(v) = { v }
Err(e) = { return Err(e); }
}
)
)
```

It is used like:

```
let foo = if_ok!(something_that_yields_a_result());
```

Niko

On Thu, May 23, 2013 at 09:48:28AM -0700, Ziad Hatahet wrote:
 Thanks all for the replies.
 
 Niko, could you point out where in the code you defined the macro you
 mention?
 
 Thanks
 
 --
 Ziad
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] do we need lambda?

2011-12-05 Thread Marijn Haverbeke
If bind is staying (there was talk of removing it in favour of lambda
at some point), I think we can do without lambda. But the concept of
shared closures (which is what bind creates) would still be there.
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] do we need lambda?

2011-12-05 Thread David Rajchenbach-Teller
On Mon Dec  5 14:27:18 2011, Marijn Haverbeke wrote:
 If bind is staying (there was talk of removing it in favour of lambda
 at some point), I think we can do without lambda. But the concept of
 shared closures (which is what bind creates) would still be there.
 ___
 Rust-dev mailing list
 Rust-dev@mozilla.org
 https://mail.mozilla.org/listinfo/rust-dev

What would be removed exactly? I strongly believe that we need a form of
closures, e.g. for registering event callback, whether to a GUI, or for
network or system events.

Now, of course, as long as we have some ability to pair a data structure
and a function pointer, and a standard way to represent functions
expecting this kind of data structure, we can always fallback to manual
closure conversion, at the expense of some readability.

I wonder, what exactly would be gained by removing lambdas?

Cheers,
 David



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


Re: [rust-dev] do we need lambda?

2011-12-05 Thread Niko Matsakis
Ah, I see now that nested functions cannot access upvars.  I was under 
the impression this limitation had been removed.  I did not intend to 
take away access to upvars (as you and Graydon said, crucial to event 
callbacks) but just the anonymous function syntax.


However, I've been thinking it over more since last night and now I 
think that this is not a very good idea.  It'll make the language feel 
heavy and we want it to feel light.  What might be nice, then, is a less 
ponderous syntax than lambda syntax.


In any case, I am still toying with what unique closures ought to be.  
One problem I have uncovered (and it's already a bug today) is that a 
unique closure must be very careful what it does with its unique, 
closed-over state.  The problem is that a unique closure can be invoked 
multiple times.  Not so good if you are moving or dropping unique 
variables.


For example, this code crashes today:

fn foo(-x: ~int) { }
fn main() {
let b = bind foo(~3);
b();
b();
}
The error is that bind needs to re-copy the ~3 each time `b()` is 
invoked, but it doesn't. In other words, that bind code is equivalent to 
`let x = ~3 in fn () - foo(x)` (in some weird O'Caml/Rust hybrid) but 
it would need to be `fn() - let x = ~3 in foo(x)` to be safe.


This problem can be addressed in many ways and I am not sure what is 
best.  One option is to say that unique closures cannot move or dispose 
of their upvars (here, bind is moving its upvar, essentially).  
Essentially upvars become like a field of a record or other immutable 
location, which must be accessed via swap.  This is safe but somewhat 
disappointing, because most unique closures will be used to spawn a task 
and therefore executed only once.


Another option is to specify that a unique closure can be invoked only 
once (calling it consumes itself).  This is also limiting if that's not 
what you want, but it probably is.  In particular it does not allow 
unique closures to become the foundation for a map/reduce library.


All in all, I am just not sure that unique closures are the right tool 
for a user-friendly, simple parallelism API, which I understood to be 
one of their goals.  In other words, if you want to fork off a bunch of 
tasks to process the various elements in your array and then pull them 
back in, unique closures don't really give you the guarantees you want.


On the other hand, unique closures do serve a useful purpose for 
spawning off a task and handing it data.  This could also be simulated 
today using a wrapper that creates a channel, starts a new task, passes 
the value over the channel, and finally invokes your function.  Of 
course this adds overhead for something that (may?) be a common case.  
But I am not sure if moving one-off data like that *is* a common case.



Niko

On 12/5/11 8:33 AM, David Rajchenbach-Teller wrote:

On Mon Dec  5 14:27:18 2011, Marijn Haverbeke wrote:

If bind is staying (there was talk of removing it in favour of lambda
at some point), I think we can do without lambda. But the concept of
shared closures (which is what bind creates) would still be there.
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev

What would be removed exactly? I strongly believe that we need a form of
closures, e.g. for registering event callback, whether to a GUI, or for
network or system events.

Now, of course, as long as we have some ability to pair a data structure
and a function pointer, and a standard way to represent functions
expecting this kind of data structure, we can always fallback to manual
closure conversion, at the expense of some readability.

I wonder, what exactly would be gained by removing lambdas?

Cheers,
  David



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


[rust-dev] do we need lambda?

2011-12-04 Thread Niko Matsakis

Hello,

I wanted to do a quick straw poll to ask whether we still need a lambda 
expression, given that we have blocks and named functions?  Searching 
the rust code base, I found that *every* use of lambda was of the form: 
|let foo = lambda(...) {...}| which would (in my opinion) be better 
written: |fn foo(...) {...}|.


I am not asking because I like stripping out unused expression forms, 
though I do, but rather because I am thinking about the precise design 
for unique closures (separate e-mail coming soon) and the fewer ways to 
declare closures the simpler the job becomes.



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