Rust definitely seems cool as a no-compromises systems language. Why is Mozilla developing it, though? What is the intended use? Supposedly it will be used by Firefox, but for what? Rendering? JavaScript compilation?
Its singular goal is to be an awesome language for writing next-generation browser engines. If it just so happens to also be a really, really exciting systems programming language, that's just a plus.
Then they should use Ada. If it's good enough for high integrity applications in space, transportation, or banking, then it's certainly good enough for browsers. ;)
You know, there are some things that --to me-- absolutely identify a newcomer to this programming/computer thing.
One is the belief that it would be to good to write everything in assembly (from OSs to browsers to games) so that it would be faster. See they heard that assembly is faster and lower-level, so "the more the merrier, right"?
Another (that you don't get much nowadays, but there was a time in the early 90's that was very common) was this fascination with Ada. Mostly because of all the marketing and BS articles at the time. The reasoning here was "well, if they use that for missiles and F16s, it must be the best, right?"
Ada is good because of useful typing (such as the ability to say "apples and oranges are both represented as signed 32 bit integers, the allowable range for apples is 0..5, and you can't mix them"), strong control over data representation, standardized extensions for on-the-metal programming and hard real time, built in synchronous message passing concurrency, and just generally being an awesome language. It's also good because of SPARK Ada, which is an ultra-safe Ada subset plus annotations and supports extensive static checking.
None of this require buying into marketing hype.
It's bad because the language is large and some parts feel out of date, the memory management is more complicated than it ought to be, and compilers are thin on the ground and often expensive. Targeting C at a new machine is much easier than Ada, and this is probably the main reason why it lost.
My personal guesses why Ada lost: In (Western) academia was a massive dislike of Ada because of its DoD roots and NATO applications, so they didn't use it for teaching. And hackers disliked it because it was a committee-designed language and it's pretty restrictive (even paternalistic) and directed toward mediocre programmers (a good decision for systems that run over decades and have big, changing teams assigned to it).
What was meant half-joking (that they should use Ada for the browser) becomes better the more I think about it. When I look at Rust's design goals, I find that Ada 2012 fulfills them (at least superficially). Additionally: if users have to learn Rust as a new language, then they can use Ada anyway (which has a good track record, while there's no experience with Rust's possible quirks).
And I guess if they ask AdaCore to include certain features as add-ons to their GNAT compiler, they'd do it or assist (because for fun and for the publicity that Firefox uses Ada).
In Europe maybe. In the US, hardly. We're talking early nineties, not the sixties. In the IT academia there were hardly any leftists that would oppose a language on the basis of it being used by the DoD.
I don't know why people think Ada is restrictive, it really isn't at all, at least, not since the Ada 95 revision (which added pointer-to-stack and pointer-to-function and OOP). It isn't even verbose, it's just communicative.
I think it comes from the following: Ada was designed to be robust against the average programmer. They prefer to "hack" around and have their program just compiling. Compared to, say, scripting languages Ada ist restrictive. I feel they dislike Haskell for the same reasons.
edit: most complains seem to come from strong typing and static type checking.
"apples and oranges are both represented as signed 32 bit integers, the allowable range for apples is 0..5, and you can't mix them"
While I can't say that I completely understand the underlying concepts, I believe that this is the sort of thing that Rust's typestate mechanism is intended to achieve (the way I seem to understand it, it's sort of like design-by-contract, except invariants may be checked at dozens of places per line rather than just at function boundaries). You should look into it if Ada's safety guarantees excite you.
They want a language that's safe, concurrent, blabla, and good for system programming? Then they should take a look at Ada 2012. But I guess they just want to build something themselves.
They could even make use of Ada's real time capabilities. It was a pleasure when I ran QNX (2005) and everything responded to my actions on spot, even their browser (Voyager). Today I run FF and after a while and with several tabs open it takes (many) seconds until this beast shows some reaction.
BTW I don't use Ada but mostly Haskell since 2001.
Today's web isn't the 2005 web. Go to a geocities archive with both browsers and the results will be much closer. Faculty pages also work, they're almost always free of dynamic bloat.
> Are you going to use this to suddenly rewrite the browser and change everything? Is the Mozilla Corporation trying to force the community to use a new language?
> No. The Mozilla Corporation's involvement is at the labs level: the group concerned with doing experiments. The point is to explore ideas. There is currently no plan to incorporate any Rust-based technology into Firefox.
In a previous post about Rust on HN one of the Mozilla devs claimed that Rust was a result of headaches they've had building Firefox. The language isn't to be used in Firefox, but to (eventually, some day) to be used in whatever supersedes Firefox. They would be starting from scratch. And this is probably very very far in the future. Why else would Mozilla develop a new language if they didn't intend to use it for their products?
I didn't see that post, but every other post I've seen there has been a lot of hand wringing about being forced to use this language or be shut out of Firefox development, which is very clearly not currently even in the long-term plans. They've also been very clear that people should not form indelible opinions about Rust since they expect it to continue evolving at a rapid rate.
You're right that it would be idiotic to spend the money and time to develop this if they didn't intend to use it in their products, but they've gone out of their way to make people understand that the Rust they can see today is not going to be shoved down their throats. Whether some eventual successor Rust that may or may not resemble the one we have today is used for some kind of rewrite is probably a foregone conclusion, but they clearly don't want us deciding whether to support or object based on what exists today.
I sound like I'm making a big deal out of a minor distinction, but I don't like seeing what I saw on Slashdot, which was essentially, A) Rust devs announce Rust 0.1, B) someone submits story to Slashdot saying Mozilla is forcing everyone to abandon C++ and switch to Rust in the near future, C) everyone on Slashdot complains that Rust isn't going to perform and ought to have language features X, Y, Z. This cycle misinformation/non-information is going to persist as long as we emphasize the foregone conclusion that this might be used in some kind of far-distant rewrite ahead of the actual news, which is just that 0.2 of Rust, an experimental language, came out today.
> Now that we have spawned a child task, it would be nice if we could communicate with it. This is done by creating a port with an associated channel.
let port = comm::port::<int>();
let chan = comm::chan::<int>(port);
task::spawn {||
let result = some_expensive_computation();
comm::send(chan, result);
}
some_other_expensive_computation();
let result = comm::recv(port);
Why not let the task have a mailbox and send messages to it like in Erlang? Is it because of the desire to have typed channels? I like everything about Rust so far except this choice. I know Go does the same, but I consider Erlang's approach a lot more elegant and less verbose.
After a couple of years of writing erlang full-time, tying mailboxes to processes is one of the things that really bugs me. It conflates mutable state, addresses and queues into one construct. Using channels allows multiple writers/readers per queue, passing the channel as a first class value and allows transparent task restarting without needing global address registration per task.
I disagree. I think tying both together produces a new abstraction -- the actor. Not having it that way, offers little more than a thread and a bunch of queues.
Presumably you could still use a queue to provide the semantics you want, even now? Or have another actor that acts as the queue. But I think that use case doesn't warrant decomposing actors into channels and tasks.
I believe the idea here is that the language would provide an actor construct as a member of the standard library, built using the concurrency primitives demonstrated above.
It's actually really consistant with the rest of their decisions. Ports channels are much more primitive then mailboxes/messages, and yet, still safe. Mailboxes can then simply be a library built on top. This makes less assumptions.
One can be built on the other, and it being built by the platform rather than the coder would be a big plus. Lets hope mailbox abstraction turn up in the next release.
I think there is a semantic difference. Each actor has one mail box. So when sending a message to it, the message is sent to the pid (address) of the actor. So the actor become the central abstraction without the need for channels.
To emulate that with channels it is like saying you have one default channel created for each task. Instead of sending a message to the task, it is sent to a channel and instead of just a simple receive, the task has to has a reference to the same channel.
Another way of thinking about it, it is like having a graph of components and one model emphasizes the nodes (actors) and the other emphasizes the edge (channels) as the central abstraction.
Making a strong association between tasks and message boxes like erlang does makes too many assumptions. That'd be an apt choice for many languages. But for Rust, as a systems languages, that seems like a poor choice.
> But for Rust, as a systems languages, that seems like a poor choice.
Yeah I can see that I guess. It is a lower level language so it would be the same as asking for closures or garbage collection in assembler?
> Making a strong association between tasks and message boxes like erlang does makes too many assumptions.
It does, and often having good assumptions is nice. One can argue that at some point unless the system is not C then someone can say it is making "assumptions".
In their documentation they do mention how they are trying to emulate Erlang (they even have supervision trees for tasks) so my point was that they left a critical semantic feature out.
Even if a system is C you can say it is making assumptions. The point is to make as few as practical.
I think they are trying to learn from Erlang, not replicate it completely. The key point is that the missing feature can be pretty trivially made up for by libraries and convention. Which again, seems like an apt choice for a systems language.
If you want to play, just play with the toy that looks the most fun. Don't plan for the best route, take the most interesting one. There will be enough occasions in your coding life to be serious and not be given a choice...
It's good to understand the underlying systems concepts in general (such as "what is the difference between heap allocation and stack allocation?"), but you don't necessarily need to know C to grok these concepts. However, C is still a good language to know, or at least be familiar with.
As to Rust, there are still a few essential constructs missing from the language, so if you're looking for a gentle introduction you'd probably be better off waiting for 0.3 (scheduled for release in "about a month") or 0.4 (probably due to be released in three months or so).
I had trouble trying to just read from stdin. Actually I couldn't do it before I got frustrated and gave up. I hope I can do it this time!!! If not, then I'll wait for 0.3!!!
COME ON!!! I literally JUST finished downloading and reading the docs for rust 0.1 an hour ago. I mean a new version is cool, but could it have come a day earlier?
Fortunately, most of the changes in this version were internal rather than user-facing, and the few user-facing changes (classes, regions) are still somewhat half-baked. Not much new to learn at all. :)
Sorta... many types have a more strongly enforced ownership style lifetime scope, but depending on the data you are declaring, the collector may come into action automatically.
Basically, Rust makes it easy to avoid the collector by clear ownership rules, but still provides a collector for the cases where that just won't do.
In previous threads (can't remember if it was here or on reddit), Rust developers noted that Rust currently needs a GC for many things, but part of the Region works is aimed at removing that need (aka unless the efforts fail, you should be able to use Rust 1.0 sans GC)
Rust actually doesn't have tracing GC; it instead uses reference counting and cycle collection. The major things that have stopped us from tracing GC so far are LLVM issues; I'm working on those now and we'd like to introduce optional tracing GC soon.
My personal thinking is that the standard libraries should avoid the GC and use regions, reference counting should be achievable through a "smart pointer" type in the standard library, and GC should be provided if the programmer wants it.
It makes fewer compromises than Go. It'd be more appropriate for concurrent, high performance systems projects, whereas Go is a way to rapid-dev high(er) performance networked services.
The one that everyone complains about is Go not having generics. I think you have to play around with both languages for long enough to know if it's a real issue; people just seem to look at the spec and decide the lack of generics is a dealbreaker.
No parametric polymorphism, which means plenty of casts, runtime checks, and annotations. This sacrifices performance, compile-time guarantees, and programmer productivity for a simpler and slightly faster compiler.
Both Rust and Go have GCs. It is true that Rust has mostly per-thread GC, which should help to curb performance concerns quite a bit. And Rust aims to have more explicit control over where things are allocated. But it's still a GCed language.
Whether GC is acceptable in systems work depends on what you construe as "systems work" (kernels and GC don't mix nicely; browsers and GC is OK if you're careful).
I'm not an expert systems programmer by any means, but I think that Rust makes a distinction between garbage collection, reference counting, and its region system. There are ways to allocate structures in memory using any of those systems depending on your needs.
If you're willing to be unsafe, it should be possible to avoid most (any?) overhead from automatic memory management. Here's a quote from one of the Rust developers:
"So we basically use the runtime for three things: (a) the task system, which features lightweight threads like Go or Erlang; (b) stack checks and growth; (c) garbage collection. We used to use it for more, but lately more and more stuff has been moved out of the runtime to be written in Rust itself.
"I'd like to see a 'runtime-less Rust' myself, because it'd be great if we could implement the Rust runtime in Rust. This might be useful for other things too, such as drivers or libraries to be embedded into other software. (The latter is obviously of interest to us at Mozilla.) Rust programs compiled in this mode would disable the task system, would be vulnerable to stack overflow (although we might be able to mitigate that with guard pages), and would require extra work to avoid leaks, but would be able to run without a runtime.
"If anyone is interested in this project, I'd be happy to talk more about it -- we have a ton of stuff on our plate at the moment, so we aren't working on it right now, but I'd be thrilled if anyone was interested and could help."
Graydon has been adamant that Rust must provide the ability to avoid tracing GC if the programmer wants. I was at first skeptical, but now I'm fully on board. For things like browsers, control over memory management is crucial.
It very much is not. Erlang's primary goal has always been reliability. Not concurrency. Concurrency arose from a subset of the mechanisms Erlang "needed" to implement reliability, but was not a primary focus of the language (just look how long Erlang lived without an SMP-able runtime).
Yet this concurrency is pretty much the only Erlang feature that was ported to Go, in a much less reliable manner.
Now I picked out Erlang because it has ... garbage collection. I was replying to the parent saying that GC is utterly incompatible with a systems language.
Go and Rust are the new Erlangs in that they are the go-to language for system services above kernel level.
Erlang disallows shared memory in favour of per-process gc. Whether or not this is a good tradeoff in general is debatable but it is what makes the gc acceptable in soft-realtime environments. Go makes a different set of tradeoffs (shared mutable memory, whole process gc, no hot code reloading) which place it in a different niche to erlang.
> Wrong. Concurrency is not some accidental bolt-on in Erlang
You might want to read my comment correctly and avoid injecting things which are not in it. I did not say concurrency was "bolted on", I said it was not a primary goal of Erlang's design, it was merely one of the tool deployed to reach the over-arching goal of reliability.
> I was replying to the parent saying that GC is utterly incompatible with a systems language.
Can't say I've ever seen Erlang called a systems language. But in any case Erlang's design and VM structure does make it suitable for soft real-time (per-process shared-nothing[0] heaps independently GC'd with configurable initial heaps, allowing such things as never GC'ing a process at all). Go still's no Erlang.
Yeah, I found "crust" to be rather counter-intuitive. I think one of the reasons that bugs me is that "ret" and "mut" don't have any intrinsic meaning in English, but my brain insists on reading "crust" as if it were a word.
"rustc" is how you invoke the compiler from the command line, that's no good. :)
I do seem to remember that the devs were passively soliciting ideas for a better name for this keyword. The great thing about a language at this stage is that if this really bothers you, then you can petition to have it changed!
I think your first point is valid, but Punctuation has other advantages, the symmetry between {} and the distinctness of the symbols (Taller than most, for instance) provide other advantages for the later.
The problem is many languages are designed on US keyboards. And even engineers who are otherwise mindful of unicode and other internationalization problems, may trivially forget what keys may not be on other keyboards.
I suppose your best bet may be to muck a bit with the key bindings of your particular text editor. IMO, I already swap some keys around to make () and {} more usable.
Yeah, Significant whitespace is why I won't code in Python anymore. Also, the linked article's comparison of Haskell and Python on readability is an awfully poor comparison, Haskell has notoriously terse syntax, In comparison to Python, which is nearly designed with the sole purpose of having good looking syntax.
but that was the very point of comparing Python and Haskell.
FWIW the Haskell crowd were super-defensive and claimed that Haskell is super-readable (by them).
Now in that article I talk about 'curly bracket' languages in general, meaning those that use symbols (words) to denote blocks rather than indent. And I don't like reading them because of that.
The syntax could be made much better by focusing on usability and readability. It seems unimportant at first, but I know people get turned off functional languages because of this, and people go so far as to maintain alternate syntaxes and toolchains for Erlang, OCaml, JavaScript. Take a page from one of the “executable pseudocode” languages and their very clean syntaxes.
Why didn't they do GC per process like Erlang instead of GC per thread?
I thought processes and sub processes are cheaper to spawn then threads? That's the reason why Chrome tabs are in per sub processes right? Instead of threads?
Firstly, while I'm not very familiar with Erlang or its runtime, afaik Erlang processes are not actual OS processes.
Secondly threads were originally created as a cheaper alternative because spawning processes was too expensive (on Windows). The original reason for Chrome using processes was that processes gives you memory protection. But I don't know how much it really helped them in the end, because they quickly noticed that using one process per tab doesn't scale. Thus Chrome (at least originally) limited the maximum number of processes to ten.
Rust actually has multiple heaps with their own lifetime characteristics so that they can avoid GC in many cases, and that the only GCed areas are per-thread.
The costs of threads vs processes are identical if you're prepared to put some stuff in virtual memory (except on Windows, and I don't know if that has improved). Processes default to full isolation, threads are the reverse, but Rust has enough compile-time guarantees that it can do its own isolation for most purposes. I imagine they could go back and forth on this one without breaking source compatibility.
GC per lightweight thread does not imply stop-the-world approach as in Go.
Also process is heavier entity for OS kernel in comparison to thread (address space, file descriptors are all per-process objects, not per-thread, thread is just a unit of processor time scheduling). Chrome tabs are processes for security reasons. Chrome trades speed for security in this context.