

The Rust Programming Language - jamii
http://dl.dropbox.com/u/4186469/rust-all-hands-w2011/assets/fallback/index.html

======
mkup
I'm writing this comment in hope that Rust language designers read this
thread.

It's very important to language designers at this time to avoid stop-the-world
GC approach in Rust at any cost.

Google Go is beautiful programming language, but its key limitation is stop-
the-world approach to GC which makes it very difficult to implement highload
web servers, DB engines and other software with strict max-time-to-response
requirements. Recent research [1][2] suggests that "normal" Go program spends
more time collecting garbage than performing actual calculations.

[1] [https://days2011.scala-
lang.org/sites/days2011/files/ws3-1-H...](https://days2011.scala-
lang.org/sites/days2011/files/ws3-1-Hundt.pdf) [2]
<http://www.theregister.co.uk/2011/07/01/go_v_cpluplus_redux/>

Go programming language has gone too far to separate owning and non-owning
pointers at syntactic level, to disallow changeable global variables, to
enforce rules like "each mutable object is accessible from _only one_ thread",
and introduce other means to avoid GC.

But Rust is new and young, already has 2 types of pointers, and it could avoid
GC by RAII and reference counting. Objects linked in cycles with owning
pointers would cause memory leaks, and I think this behaviour may be left as
is, kinda "it's not a bug, it's a feature". Weak pointers could point to
intermediary descriptor which holds owning-refcount and nonowning-refcount.
Weak ptr behaves like a NULL if owning-refcount is zero and target object is
already destroyed. This is to guarantee safe memory model.

In short please take all means to avoid main Go defect "Garbage collection
takes more CPU time than actual computations". Please avoid stop-the-world GC
approach which makes the language almost useless for real applications.

~~~
pcwalton
Garbage collection in Rust is thread-local. We never need concurrent GC; this
invariant is enforced by the type system.

Leaking cycles is not really an option, sorry. At the very least we're going
to have a cycle collector. It's too easy to make cycles, especially when you
have closures (all you need is to close over an object that contains a pointer
to the closure itself; this is very common for e.g. event handlers).

Besides, a lot of the problems you state can be addressed with generational or
incremental garbage collection.

~~~
mkup
If there is no difference on the syntactic level between owning and non-owning
pointers, like in Go programming language, like in Python, then I agree with
you - it's extremely easy to make a cycle.

But if there's a difference between owning and non-owning pointer, then
backlink to parent object in child object could be non-owning and other issues
could handled in similar manner.

Cycle detector which stops the program with references to the source code
where the cycle was created - is a good idea, because in server systems under
heavy load it just could be disabled. Basically it's a debugging tool, once it
was proven by the testing that there are no bugs, these checks can be turned
off in production. Like a C assertion checks.

------
tomp
Sometimes I wonder why do all the programming language designers prefer to
invent several different syntaxes for one concept...

From the third slide: we can see two different function definition syntaxes, a
"normal" style and a "ruby" style. I really like the way of JavaScript,
CoffeeScript and OCaml that have a single unified function syntax.

Also on this slide: why have a special syntax for importing submodules from
modules/crates? Again, CoffeeScript excels here, an import is simply a
variable declaration:

    
    
      {int, vec} = require('std')
    

Furthermore, it has always bothered me why generic types use <> brackets. I
can understand it in Java and C# (where types are declared before
values/functions), but in Rust, it's really unnecessary to introduce the 4th
type of brackets into the language (apparently, they used [], but latter
changed it to <>... I would really like to know why.)

~~~
philh
> {int, vec} = require('std')

I don't know coffeescript, but this looks to me like "std exposes two things,
and I am bringing them into this namespace as int and vec". Whereas the rust
code looks like "std exposes int and vec, which I am bringing into this
namespace, and possibly other things which I am not".

~~~
yesbabyyes
What this means, in CoffeeScript, is that std exposes int and vec, which I am
bringing into this namespace, and possibly other things which I am not. If I
want to use all of std, I would have to write

    
    
      std = require('std')
    

and access std.int, std.vec and so on.

~~~
philh
Thanks for clarifying.

I think I like rust version better: when I see an '=' sign, I assume that the
RHS returns _something_ which is assigned to the LHS, and _something_ doesn't
depend on the LHS. Coffeescript violates that, and it feels much more like
'special syntax'. But without knowing either language, I won't go further than
"this seems weird".

~~~
moomin
Actually, the genius of the coffeescript version is that it's just a use case
of the general destructuring syntax. So

    
    
        { x, y } = { x : 3, y : 5, z : 3 }
    

is perfectly valid as well. Once you get the hang of coffeescript's
destructuring, it's insanely powerful.

------
pcwalton
Slideshare here for those having trouble with the Dropbox-hosted version:
[http://www.slideshare.net/pcwalton/rust-all-hands-
winter-201...](http://www.slideshare.net/pcwalton/rust-all-hands-winter-2011)

~~~
capnrefsmmat
Could you give examples of macros-by-example, as the presentation puts it? I'm
not sure how those would work in a non-Lispy context.

~~~
pcwalton
Check out the macro tests in this directory:
[https://github.com/graydon/rust/tree/master/src/test/run-
pas...](https://github.com/graydon/rust/tree/master/src/test/run-pass)

------
andrewflnr
Maybe I'm just naive, but whenever someone says "systems language", I think
"ooh, something better to write kernels in?" I guess I'm waiting for something
semantically equivalent to C, but with better options for macros and code
generation, and some compile-time guarantees. Just less tedium, more DRY.

I don't actually program C, I just have projects in mind where it seems like
that's the best language, where performance and compatibility with other
languages is important. But C seems like such a pain to program in that I
really wish there was a better option.

~~~
pcwalton
Rust has an unsafe sublanguage you'll probably be interested in.

That said, writing kernels is explicitly not a goal of Rust. It may well work
great with a custom bare-metal runtime, but we aren't letting the needs of OS
kernels constrain our design space at this time.

------
thurn
The typestate concept seems like an incredibly cool tool for enforcing static
guarantees. As far as I'm aware, not even Haskell has anything similar to that
(feel free to correct me!)

~~~
thyrsus
I'm not clear: is typestate a compile time or run time guarantee? [Edit] That
is, is the guarantee implemented at compile time, noting violations similarly
to syntax violations, or does it generate "invisible" code that performs
runtime checks which can throw something similar to exceptions?

~~~
cwp
A bit of both, actually. It's mostly compile-time checking, but you can also
write assertions about the typestate of a particular variable. The compiler
generates code to check the actual values at runtime - if the assertion fails,
the program is aborted. The really cool bit is that the compiler can take the
assertions into account when compiling code that _follows_ the assertions.

~~~
thyrsus
Thanks. When you say "aborted", does that refer to an Erlang-style (micro)
process, or the entire OS-level process?

~~~
pcwalton
Failure only brings down the current task, not the process.

------
LeafStorm
This is probably minor, but one of the things that bugs me is the incredibly
shortened keywords. Is it really that much of a slowdown to type "function" or
even "func" instead of "fn"? Same with "ret" instead of "return".

~~~
BoppreH
The problem is not typing speed, but word size. It fills the screen with
garbage and is typo-prone.

Small reserved words means I don't have another failed compilation because I
typed "fucntion", or the small but significant mental pain of backspacing.

~~~
Wilduck
A huge one for me is that for some reason I can never correctly type the word
"Length". As if to highlight my point to myself, I consciously thought about
how to type it, and still ended up with "lenght" on the screen.

Python's built in function "len()" is a lifesaver in this regard.

------
divtxt
I like the concurrency trend - channels & cheap threads like Erlang and Go.

The concurrency feature that stands out: _... no need for ... concurrent
garbage collection._ (slide 17)

The upside should be amazing performance compared to simple GC.

The cost is developer effort for memory management hints (slide 22). We'll
have to see if it's worth it.

~~~
noj
I'm really looking forward to Rust being somewhat usable, I think it has made
almost all the right choices. This is Google Go done right.

As a C++ developer I find my efforts on "memory management hints" to be
totally worth it, due to the fact that you actually have to think about object
ownership. Which in my mind makes for better designs.

------
icebraining
Older discussion: <http://news.ycombinator.com/item?id=1498528>

------
DanWaterworth
This looks like it's going to be a great language. Compiling to LLVM should
mean that it does tall call optimization, which is great and also means that
integrating with C/C++ should be fairly easy.

The only thing it's missing that I'd like to see is support for CPS conversion
like streamlinejs does. Even if it supports growable stacks that start at 1KB,
with thousands of threads CPS conversion is still more efficient. Having said
that, seeing as they are writing browsers, not servers, I can see why it's not
a priority to do this.

~~~
beagle3
Can you explain how CPS solves the growable stack problem? I haven't heard of
this before.

~~~
ori_b
It essentially lets you turn your stack state into closures on the heap which
are passed to tail recursive functions.

~~~
beagle3
but how is that related to CPS? (or closures for that matter?)

If you're allocating the stack frame on the heap, you can just replace the
prologue (e.g. x86 intel syntax, cdecl calling convention)

    
    
        sub esp, LOCAL_SPACE_NEEDED
    

with

    
    
        push LOCAL_SPACE_NEEDED
        push ARG_SIZE_TO_COPY
        call allocate_frame
    

(where allocate_frame allocates enough space for storing link to previous
stack frame, all args and all locals; then, it copies all arguments, return
address and stack pointer, switches stacks to the new stacks and returns from
the call)

You can modify the return to call "deallocate_frame" (which would switch
stacks back before returning), or you can just make sure the return address on
the new stack points to "deallocate_frame_and_return", and use a regular
return in place.

[Actually, come to think of it, it's an excellent idea for a stack protection
system that can be turned off for speed - the call to "allocate_frame" could
be configured at runtime to patch its caller to just do "sub esp,
LOCAL_SPACE_NEEDED" for maximum speed. Or it could just check stack overflow;
or it could allocate frames on heap for better memory use; and it could
mprotect/virtualprotect the edges of this frame for protection]

~~~
ori_b
That's another option for doing it. However, writing in CPS implies that your
calls are all tail calls, and they all take a continuation closure as an
argument.

~~~
beagle3
I know what CPS is. But Dan states that "CPS is more efficient than growable
stacks", and I can't see how CPS plays a nontrivial part in the stack size
optimization.

------
ynniv
Good call on single threaded language bridging. Multithreading in XPCOM was
either bad or worse depending on the phase of the moon. I almost had an
important project tank because XPCOM "out" parameters (unfortunately used
internally whenever a method had a return value) were not thread-safe. We
ended up using a different threading library and only making synchronous XPCOM
calls.

------
hasenj
I saw the C++ like syntax with std::stuff and stuff<T> and it turned me off.

~~~
loup-vaillant
I saw the ML like syntax with `let r = 42 { stuff };` and it turned me on.

Frankly, your bits of syntax are no worse than `Std.stuff` and `'a stuff` (or
`Stuff a`).

------
madmoose
I only have a tiny bike-shedding comment:

I'd expect the arguments of the map-function in the example on page 3 to be
the other way around. The 'grades' argument gets pushed down several lines in
the current form.

------
cnlwsu
In chrome I am just getting a blank page with some javascript errors. In IE I
only can see the right half of the presentation. Mozilla is supporting FF well
though :)

~~~
pcwalton
I just used Keynote's export feature. I'll upload to slideshare.

~~~
keithpeter
Just dump a pdf of the slides in your dropbox, less hassle.

Works ok in FF on Xubuntu 11.10 but sloooooowwwwwwww

~~~
captaincrowbar
Seconded. Please just give us a plain old PDF that we can read in-browser or
download, instead of making us screw around with all these weird friggin
formats.

~~~
pcwalton
Here you go: <http://dl.dropbox.com/u/4186469/rust-all-hands-w2011.pdf>

------
zobzu
It looks pretty cool and oriented at making a browser engine. (tl;dr version i
guess)

