
Purging proc from Rust - steveklabnik
http://smallcultfollowing.com/babysteps/blog/2014/11/26/purging-proc/
======
hoelle
> but if it cannot be done for 1.0 then I would expect to see those changes
> shortly thereafter

Why is Rust in such a rush to hit 1.0? Recent improvements have massively
improved it, but I'm afraid it will lock too soon and suffer for it.

Rust holds some promise for me, but things like simple buffer manipulation,
strings, and slices are ugly and torturous in Rust, compared to Go where they
are a pleasure to work with.

~~~
zurn
I don't know about "rush" but they should move quickly because Rust is in a
fleeting sweet spot of the developer attention cycle where lots of people are
eager to jump onboard and it's really good enough for that now.

You are barking up the wrong tree if you are waiting for Go-level simplicity,
like the Rust folks have often said.

~~~
Tuna-Fish
I honestly think that common string handling would be much improved if String
could point to _either_ &'static str or an owned buffer, with allocation on
modification if necessary, and literals coerced to either &'static str or a
String that points to the static buffer depending on type inference.

String would never allocate more than it does currently, but it would do it in
less predictable situations which some people probably wouldn't like. However,
it would basically allow people who don't care that much about short strings
to completely eschew all the .as_slice()s and .to_string()s that are currently
ubiquitous in any rust string handling.

~~~
lawn
Using the experimental slicing syntax x.as_slice() can now be x[] which is a
lot better. I'm not sure what will happen to .to_string() but it's a
recognized problem.

~~~
FreeFull
Alternatively, since String implements Deref<str>, you can do &*x, and that
works without enabling the slicing syntax (although the syntax is likely to be
in 1.0).

------
kibwen
I wish I could give a brief backstory, but the history of closures in Rust is
a long and convoluted one, with many dead ends and failed experiments. :)
Suffice to say, `proc` is a relic from a different era (call it "boxed
closures 3.0") which always felt a bit out of place, and there was much
rejoicing today at its imminent removal.

I think our final design (which might be charitably referred to as "unboxed
closures 2.0") is actually really fantastic, and doesn't leave me with any of
the lingering dissatisfied feelings that our previous designs did (at least,
assuming that all the improved inference mentioned in the OP materializes). I
look forward to playing around with them once they're more polished in a week
or so.

~~~
haberman
> the history of closures in Rust is a long and convoluted one, with many dead
> ends and failed experiments.

I desperately hope that someday, when all the dust settles, someone writes an
account of this and other long and winding paths Rust has taken through its
evolution, so people in the future can get the benefit of this wisdom. An
account of dead ends could make for fascinating reading.

The trick would be putting in just the right amount of detail. Enough so the
reader can truly understand the reasoning behind why things worked (or didn't)
without being so dense as to be unreadable.

~~~
jberryman
Being Lazy With Class is something like that, but for haskell, and is indeed
really interesting to read:

[http://haskell.cs.yale.edu/wp-
content/uploads/2011/02/histor...](http://haskell.cs.yale.edu/wp-
content/uploads/2011/02/history.pdf)

------
rubiquity
I had to read this 2-3 times to figure out what was going on, but I'm still
not entirely sure what lead to proposing this change. I guess I'll write what
I got out of it and hope I'm crazy and get corrected.

It seems to me that we're restricting what a closure can do when it executes
based on the type of closure that it is. Is this in the name of safety? If so,
that seems like a good idea given Rust's goals. Right now it feels like a ton
of mental overhead but I'll try and play around with it and see if I have an
"A-ha!" moment.

Some of the blog post, mainly the part about using a wrapper function so the
compiler can still inline monomorphized functions, makes me feel like this is
a bit half-baked at the moment. I mean, the very nature of closures is that
they give the programmer dynamic abilities.

I really enjoy Rust and the reason I enjoy Rust is the combination of low-
level programming and safety. Maybe experiments like this are what gives us
that. I hope I'm just confused right now.

edit: Oh, one benefit I see already is that since these are "unboxed" there
won't be an allocation.

~~~
kibwen
The implementation is definitely half-baked at the moment, but will be
improving drastically over the next week or two. :)

As for the wrapper function presented in the post, it's only to demonstrate
that closures are implemented via traits and act just like any other trait in
that they can be used to facilitate virtual dispatch (though IMO you shouldn't
strive to use traits in this way if you can help it, given that Rust gives you
many tools to help you prefer static dispatch).

Watching closures evolve in Rust over the past few years has actually been
really interesting. We had an implementation that was "good" a few years ago,
but was ultimately fundamentally inferior to the approach taken by C++
lambdas. The period since has been a fascinating exploration of ways to make
closures safe, usable, and potentially zero-overhead in a language without
garbage collection. For all I know it may be unprecedented.

~~~
rubiquity
Thank you for replying. I do not have any experience with C++ so that's why
this could be so confusing to me. I'm a weekend wannabe systems programmer
(it's therapy after a long week of Web development) and was attracted to Rust
from Ruby because C scares me (this is where Go users laugh that Rust
attracted a Rubyist instead of a C++ user). I'll have to research C++ lambdas
some more but given the safety, usability and performance gains that you
mention this new implementation of closures seems impressive.

~~~
dragonwriter
C doesn't scare me, but having used both dynamic languages like Ruby/Python
and static languages with type inferencing and reasonably robust type systems
(e.g., ML-family languages, Haskell), I find C-like languages that require a
lot of type ceremony despite having fairly anemic type systems (and this is
even more true of the whole C++/C#/Java family of static OO languages) to be
quite annoying -- I don't feel like the type system is working for me, but
that I'm doing extra work to make things easier for the compiler -- while Rust
seems to be in a fairly reasonable place for a statically-typed language.

~~~
FreeFull
It probably helps that Rust's type system is close to what ML-family languages
have (the compiler itself was originally developed in OCaml)

------
arthursilva
This is awesome! It isn't trivial to understand but considering it's a high-
level abstraction in a low-level language it's totally fine. Folks, there's no
GC nor allocation going on there!

~~~
kibwen
Just as importantly, it's also as statically memory-safe as the rest of the
language. :)

~~~
arthursilva
Precisely.

------
thorn
What about us, simple mortals who want to learn this exciting language, which
changes a lot even now? I spent some time writing stuff on Rust. But it is
moving target without no documentation for advanced parts. How do I figure out
advanced stuff on my own? Is there parts of compiler I can use for reference?

What can I do while they "rush" language to the 1.0 stable release?

I mean how to get the best from this situation if I want to be programming in
Rust in future?

~~~
kibwen
There will be a 1.0-beta period where the language will have largely calmed
down and is mostly just hammering out the bugs for a full 1.0 release. This
will be coming within the next few months. If you'd like to learn Rust without
suffering the massive breakage of our last-minute scramble, then I'd suggest
you wait until then. :)

------
cluelessfellow
Is the 'virtual' in virtual dispatch interchangable with 'runtime' or does it
imply something more?

~~~
kibwen
When we say "virtual dispatch" in Rust we mean the same thing as it means in
C++, which is that there exists a vtable in which the function pointer is
looked up at runtime from a known offset. It grants more flexibility and less
binary bloat than static dispatch, but requires an additional pointer
indirection and can present barriers to inlining (though LLVM is impressively
smart with its devirtualization abilities at times).

~~~
cluelessfellow
Thanks for the excellent clarification.

------
gnuvince
So does Rust still "have closures" or are they now just a specific
implementation of a trait? Are there other features that could be implemented
as traits?

~~~
jdpage
Rust has closures, _and_ they are just a specific implementation of a trait.

Many fundamental concepts in Rust, including arithmetic, comparisons,
sendability, and smart pointers are formally traits (though the compiler may
treat some of them specially, particularly arithmetic and comparisons).

~~~
bjz_
This has been a common theme through Rusts's history. Things that were baked-
in language constructs have gradually migrated to become library things with
sugar enabled via traits. This is leading to towards a very simple, extensible
language.

~~~
Sonata
This is something which really excites me about Rust. Having constructs as
fundamental as function application extensible via traits reminds me of
Python's magic methods, but without the runtime overhead.

------
tpaksoy
Hi Steve, the pull request has not been merged yet as tests are failing. The
blog post reads as if it's in master right now, which it does not seem to be.

~~~
steveklabnik
I'm not the author, but I'll let them know. They weren't failing before the
big rollup :)

