Hacker News new | past | comments | ask | show | jobs | submit login
A taste of Rust (lwn.net)
192 points by edwintorok on April 25, 2013 | hide | past | favorite | 91 comments



In contrast to this, array (or, as Rust calls them, "vector") references do not require the compiler to know that the index is in range before that index is dereferenced. It would presumably be possible to use the type system to ensure that indexes are in range in many cases, and to require explicit tests for cases where the type system cannot be sure — similar to the approach taken for pointers.

Thus, while it is impossible to get a runtime error for a NULL pointer dereference, it is quite possible to get a runtime error for an array bounds error. It is not clear whether this is a deliberate omission, or whether it is something that might be changed later.

I presume that's because the Rust designers didn't want to include a dependent type system. Comments from pcwalton?


Right.


The article doesn't specify what exactly, is permitted by an unsafe vs. safe function. The Rust reference indicates the additional operations permitted by unsafe functions are:

    1. Dereferencing a raw pointer.
    2. Casting a raw pointer to a safe pointer type.
    3. Calling an unsafe function.
I was expecting something more along the lines of Safe Haskell (http://www.haskell.org/ghc/docs/7.4.1/html/users_guide/safe-...) which is more about trust than memory safety and, as such, explicitly restricts IO.

This isn't a value judgment. I just find it an interesting distinction.


Indeed, there's been some discussion regarding forcing users to specify what sort of unsafety they desire when using unsafe blocks. There's no syntax whatsoever yet, but consider something like the following:

  unsafe(no-bounds-checks) {
      ...
  }
or:

  unsafe(raw-pointers) {
      ...
  }
Right now the problem is that once you drop into an unsafe block, everything that is unsafe becomes allowed. Obviously this is bad for correctness and bad for readability.


It seems to me one of the prime difficulties with trying to differentiate types of unsafe behavior, is that often one will imply another. I recall that in C#, there is only one type of Unsafe block and the only unsafe operations it allows is raw pointer manipulation, but since you could theoretically point into the runtime itself, the set of implied consequences of Unsafe blocks is effectively unbounded. If Rust manages to drop its runtime it's not quite so easily susceptible, but even so, returning a pointer to a vtable outside of the unsafe block implies return-oriented programming implies unbounded capabilities.

I guess part of the issue is, what is the goal of marking code as unsafe? The use-case that C# was trying to serve was that you could be consuming a third-party assembly without access to source, and you want to know what are the possible consequences of running it. If Rust's main goal is being able to audit your own code for safety (either by hand or by tools), rather than trusting external binaries, then it makes more sense to take a feature-oriented approach rather than a consequence-oriented one.

Rust's pointer taxonomy might also help with providing degrees of consequences. You could, for example, restrict that raw pointers could only be cast to pointers with non-sendable kind, which would let you circumvent type safety while still controlling the scope of possible data races. Restricting lifetimes might be useful too, but that's too far beyond the limits of my experience.


> I guess part of the issue is, what is the goal of marking code as unsafe?

Basically, it's a way to be able to find the unsafe code by grepping for it. It's a mechanism for security auditors to be able to search for the unsafe code and audit it.

It also serves as some social pressure to avoid unsafe code.


This is similar to the {+ } and {- } blocks offered by Borland Pascal dialect and other systems programming languages in the Pascal family.


The better Haskell analog are the unsafePerformIO and related functions which match up pretty closely with unsafe in rust.


can someone explain why this (of all the flamebaity/controversial comments I make) is getting downvoted?


Okay, since you asked: Your comment doesn't make sense.

The parent comment: "rust unsafe and haskell unsafePerformIO are different!"

Your comment: "You forgot about unsafePerformIO! It's the same as rust unsafe!"


Actually, the OP was talking about Safe Haskell, which is not the same as unsafePerformIO. While the two are related, they are different. While Safe Haskell does not really map to the Rust unsafe functions, unsafePerformIO does.


Saying something different doesn't imply disagreement. He's just adding information.


It's phrased as if he's talking about a different topic, but actually he's talking about the same topic.


Usually strong typed languages for systems programming use the unsafe concept for the usual dirty tricks of low level programming that question language's safety.

You can find this in Ada, Modula-{2,3}, D, Oberon and many others.


In D it usually means "no undefined behavior". For example, you can use the @safe annotation on functions.

http://dlang.org/function.html#function-safety

http://dlang.org/safed.html


If they're really into reducing bugs, they should embed a complete proof system into the language, rather than try to guarantee something as simple as correct memory references - which isn't much of a problem to ensure for anyone serious about the correctness of their code.

Add that if a proof system (that is powerful enough) was available, and people actually used it, the language could do away with the unsafe overrides. It could also be of great help to the compiler to optimize the code, like removing array bounds checks where the programmer has supplied a proof that the index is in range.


I believe this is the programming language you are looking for: http://www.ats-lang.org/


It might be childish but I just can't force myself to swallow the ugly curly braces and semicolons.

Some compromises had to be made, e.g. the lack of tailcalls is a regrettable but nonetheless well justified decision. But why didn't they include a standard indentation style in the language specification itself and get rid of the cruft? They have one for Servo anyway, which is the raison d'etre of the whole language, so it's bewildering to me why it isn't included as a part of the specification.

It just pains me to see a promising new language being burdened with an ugly looking syntax when the language itself is quite elegant.


The use of semicolons and braces was a decision made in the early days to make C++ programmers feel more at home. There are really good arguments both for and against whitespace-oriented syntax. (I actually prefer whitespace-oriented syntax, although I can see the arguments on the other side!) But we had to pick one and disappoint somebody.


I wonder how much surveying you guys did?

As a sometime C++ dev, I fully recognize the utter inanity and burden of typing semicolons where the compiler should know perfectly my intent, and would rejoice in a language that did away with them. In fact, it's one of the features of Go that I really like. Rust's syntax, on the other hand, feels like a step backwards in some ways.

I wrote a bit more here: https://news.ycombinator.com/item?id=5608157.


I personally like semicolons. It's similar in spirit to the period of English. Even languages which didn't traditionally have the period have adopted it in the last couple of centuries.

More practically, it seems to remove a class of errors. Semicolons are optional in Javascript and I've seen posts here about subtle errors that can creep in when you change code a little carelessly.

And even more practically, it allows you to type "one liners" into things like REPLs even if they aren't one liners.

Just my two cents.


The period is necessary in human languages because we write sentences next to each other and we need some way to separate them. Programming languages are line-based and are more akin to recipes or poetry. So that's a bad analogy. Unless you consistently write all your statements on a single line, of course.

Furthermore, you present a false dichotomy here. A semicolon-free language can easily have semicolons as an optional measure if you do want to cram several statements together on the same line. You mention one-liners; a semicolon-free language can support semicolons. Here's a Ruby one-liner:

    >> b = Box.find(3); t = Thing.new; b.add_thing(t)
A class of errors: Well, anecdotally, I have personally never had a single issue with semicolons in JavaScript in all my years developing with it, simply because I always use semicolons. The reason is that JavaScript has a bunch of "semicolon insertion" rules that are not well understood, so dropping the semicolons is a bad idea, as the recent "fiasco" showed, and I just decided very early on not to go that route.

As I understand it, JS is a semicolon-enforced language that allows you to drop them at your convenience, whereas Ruby, for example, is a semicolon-free language that allows you to include them at your convenience. I'm not a parser expert, and I won't swear there is a significant difference except in which rules are defined. But I do know that semicolons are categorically not an issue in Ruby. So I would say that this argument is invalid, too, because it presents a flawed language as the ideal. The Rust guys should not need to base their design on JavaScript.


I've on a few occasions had problems with semicolons in Java: accidently putting a semicolong like this:

if (something()); { somethingOther(); }

The semicolon seemed to shortcut the whole if-block. I don't know why that thing is even allowed by the compiler.


Being able to write if and while loops with am empty body is due to braces being optional if you only have one statement and due to the empty statement being a legal statement (doing so keepsthings simpler).

As for the second {}, its to allow you to create inner scopes where you can declare variables with a more restricted scope without needing to do something silly like "if(true)".

Empty block statements are OK sometimes with while and for loops when the real action that matters is in the condition:

    while(!trySomething()){} //empty body for the loop
And since these language


This error can't happen in Rust. If blocks must be braced.


The semicolon following the conditional is an empty statement; it ends the if statement equivalently to "if (something()) { }". It's not often seen, but sometimes can be found in:

     for (i = 0; a[i] != x; i++) ;
to find the first index equaling x.

Personally, I always use braces in conditional and loop statements, so I'll never have the empty statement semicolon. But that's me.


> Personally, I always use braces in conditional and loop statements, so I'll never have the empty statement semicolon. But that's me.

But if you have

if (something()); { somethingOther(); }

Then you have a new problem: you intended the braced statement to execute iff the if-statement evaluated to true. But since you put the semicolon after if by accident, now the braced part will execute no matter what the if-condition evaluates to.

(my point was about unintentional use of semicolon after if-statement - in which case always using braces doesn't seem to help.)


You should checkout the Nimrod programming language which has a syntax similar to Python, i.e. it gets rid of the semicolons and braces.


What about making it optional, like in Haskell?


Currently, lines with and without semicolons have different semantics, so that doesn't work.

> Basically, ending an expression in Rust with a semicolon ignores the value of that expression. This is kinda weird. I don't know how I feel about it. But it is something you should know about.

http://www.rustforrubyists.com/book/chapter-06.html


You could still make braces optional though, right?


You could do whatever you want. The idea is that `rustc --pretty` reformats code, so you could make the input flexible enough to be whatever you want, really. Or write your own transpiler.


>It might be childish but I just can't force myself to swallow the ugly curly braces and semicolons.

Yes, it's childish. Worse, it's bikeshedding.


Defining a sane syntax while the language is still in its infancy is anything but bikeshedding. You have only one chance to do it right before an entrenched codebase develops or interest in the language fizzles.

MS Research did this right with the experimental hardwhite support while F# was still in alpha. People liked it so much that it became the default style for the compiler and the standard library. It would be impossible to try to make the switch now that the language is widely used.

It might be childish for me to choose one language for a project than another over trivial things like semicolons, but for the language itself it's an irreversible decision once the spec gets set in stone.


To me, one of the most interesting design decisions of Rust is that the creators strongly try to avoid inventing new language features. Instead, they attempt to find the best combination of tried-and-true existing features from a variety of other languages.

I wonder whether language syntax could be considered such a "feature" -- that is, the Rust creators would consciously prefer to combine existing syntaxes (at this point, mainly C++, Haskell, OCaml and Ruby) than invent their own.

An argument could be made that they could just "use Python's syntax", but perhaps a counter-argument would be that Python's syntax would need to be extended so much (for types, pointers, templates, etc.) that the result would effectively be a new invention.


That logic sounds fishy to me. After all, they took C++'s semicolon syntax over Haskell, OCaml and Ruby's semicolon-free syntax, so there must have been a reason for picking one over the others. So the issue is not about inventing syntax, it's about choosing one (existing) syntax over another.

pcwalton says it was to attract C++ devs, which is interesting considering that Go was also designed to attract C++ devs and made the opposite choice. As a sometime C++ dev, I recognize the historical uselessness of semicolons and would love a replacement language that did away with them.


Since when OCaml is semicolon-free? It not only has semicolons, single semicolon (;) means something different than double semicolon (;;). The former is used as an expression separator, like comma in Erlang, and the latter denotes the end of a top-level declaration, like period in Erlang. That's a pain while refactoring, but I can live with it. Anyway, that's just a style, nothing more, you can learn to love it or you can write a "transpiler", it's really a non-issue.


True, Ocaml has semicolons, although it's a little different given that you can construct deeply nested functional expressions without ever using a single one. If I remember correctly the semicolon is a separator, not a terminator, which means that declarations don't need to end with a semicolon, for example, and you pretty much only need it to separate statements.


I'm not sure I prefer 'in' over semicolon in declarations. I mean:

    let x = ref 0 in
    (* something *)
in Ocaml is not much worse/better than

    let mut x = 0;
    // something
in Rust. As I said above, that's really a minor, stylistic issue, one probably would write "let x = mut 0 in" for a week or so (coming from OCaml) and that's it, after a week it becomes as natural to write semicolon as it is to write 'in'.


I agree, I didn't really put OCaml forward as the ideal solution. Ruby and Go solve the semicolon problem in much better ways, in my opinion.


AFAICT, if you were to write in Lisp-like purely-functional style, you wouldn't need any semicolons in your Rust code either.


No, it's actually the opposite of childish: being able to digest new things is exactly what children do and exactly what adults do less.


I think it's reasonable to complain and openly discuss comparatively minor issues when a language hasn't even reached 1.0, since it's at that point a prime time to iron out everything that might be an annoyance later.


I think it would be an exceedingly interesting project to define a Pythonic syntax for Rust, then implement a Cfront-like frontend to translate Pythonic-Rust to brace-and-semicolon Rust before compiling it. (The Rust language spec is gradually reaching a point where there would presumably not be large, disruptive changes.)

You could make it available to the Rust community (and even the broader Rust-interested community on HN and Reddit) and see if it takes off.

If the Python-Rust were to become more popular than brace-and-semicolon Rust, the creators may well be persuaded to adopt it. Or at the very least, you'd have a thriving like-minded Python-Rust community. :)


There already is `rustc --pretty`, but it has some bugs and such. I'm sure you could modify it for that purpose.


I think the syntax decision is a good one. Indentation-based structure is nice, however in some cases it can cause some pains: code generation or embedding code in a document are two common examples. As for requiring semi-colons, I don't really mind them; in fact, I'm less annoyed at having to type semi-colons than having to remember rules for auto-insertion or semi-colons.


Haskell solves this problem by allowing both. In any situation where layout/indentation has meaning, braces and semicolons may be substituted.


I can accept the braces, but the semicolons were a big letdown for me. We should have learned by now from successful languages that the semicolons is obsolete.

If Ruby can do it (and Ruby does it very well with just a few simple rules, even though its lexer admittedly contains parsing logic to deal with the challenge), then Rust can do it.

The other disappointing aspect of Rust is the "line noise" problem. Rust has three types of pointers, and needs a line-noise character for each of them. That, combined with the liberal use of underscore-based identifier names, makes it very noisy. (Ruby also uses underscore-based names, but the relative absence of noise characters keeps it clean.)

In my opinion any new language project ought to have an overriding aesthetics process. Aesthetics is often belittled (as you say, "childish"), but code readability, over time, becomes more important than almost everything else.

I like Rust's design principles, but Go definitely wins the syntax competition for me.


Are you aware that the semicolon is meaningful in Rust because it indicates returning from a block (as well as separating expressions). mitsuhiko (author of Python's flask, jinja2, etc) wrote about why he loves Rust's semicolons: http://lucumr.pocoo.org/2012/10/18/such-a-little-thing/


Yes. And I really dislike that there is a difference. The semicolon is so small and what the block returns is so important, it's a really weird thing to love.


Since I am being downvoted for expressing a technical criticism, let me clarify:

I like explicitness, readability and clear, unambiguous syntax. Two small dots at the end of a line completely changing the entire block's meaning is, to me, a violation of those principles.


My own immediate reaction upon first reading the Rust tutorial was that significant semicolons were completely brain-dead. However, time went on and I was never able to think of a scenario where the compiler wouldn't immediately detect an errant or missing semicolon. Nowadays I completely adore them (though I still recommend that people use an explicit `return` in any expression of nontrivial length).


> Rust has three types of pointers, and needs a line-noise character for each of them.

`~T` and `@T` were felt to be preferable to `std::unique_ptr<T>` and `std::shared_ptr<T>`. You really do type them all the time.


I understand that. That's not the alternative I want.

Go actually gets by with just one type of pointer syntax. Go is what a colleague calls "being stupid simple", which is really its strongest asset at this point. It eschews a lot of complexity by not trying to be clever.

The problem with Go's pointers is that no thought has gone into thinking about goroutines as boundaries of data ownership. It's simple to share mutable data between goroutines, and it's impossible to verify (manually or by any kind of analysis) that a program is not a shared-everything pile of spaghetti. This, plus mutable data, makes it impossible to safely implement things like Erlang-style remote task spawning.

What I would like in my ideal language is a single pointer type: A pointer into the task heap. However, pointers may only be shared between tasks by copying or by transfering ownership, except for immutable data, which can be shared freely with no overhead other than normal GC/refcounting. With some COW magic you could even make the copying really fast, too. Then all you need is a simple syntax for limited references that cannot be stored, only copied, so that you can actually have functions that work on data efficiently without leaking their pointers anywhere.

Maybe I am being naive -- I won't pretend to be a Rust expert. But this model works pretty well for Erlang. I find that while Rust is clever, it falls into the other extreme and becomes too clever; and being too clever is a kind of stupidity. For example, borrowed pointers sound neat on paper, but then you find you have to dick around with declaring pointer lifetimes. That's pretty insane. It results in a kind of syntax that represents everything I hate C++ for. I can understand that it took a while to decide on a syntax for declaring lifetimes. It looks totally weird and arbitrary. (Quotes are for strings, man!)

It's also possible that Rust just is not for me. :-)


I would also like it if we could just copy everything, but for implementing a competitive browser this gets really hard really fast. Erlang's actors are not really designed to squeeze every cycle out of the hardware. Incidentally, you can get this model with Rust's `flatpipes` module, which allows you to send data across Rust.

We experimented with COW designs in the early days. It seemed pretty hard to implement: hardware MMUs operate on page granularity, not on object granularity, so you need (thread-safe!) guards for all objects. That's pretty tough from a performance point of view. Perhaps it can be done, but it seemed less risky to just use uniqueness.


Indeed, the types of programs I write are very different from a web browser.

For what it's worth, I know I speak for at least a couple of other people when I say that we were, for a long time, hoping for a "better Go" -- we are mainly rubyists who want native compilation, a better/safer type system, better concurrent performance, more easily massively parallelizable -- and that Rust's development has been going in a slightly different direction than we were hoping. Perhaps it's time to re-evaluate C++11 or even Haskell.


Aside from the native compilation bit, could Elixir be the language that you're really looking for?

http://elixir-lang.org/

Speaking personally for a moment here, I'm a Python/Javascript/PHP dev by day, and the reason that I'm interested in Rust is precisely because of all the new concepts that it's forced me to learn. I could never get into C because I enjoy having two feet, and I could never get into C++ because I know that there's no escape from that stygian pit. For me, Rust is precisely the right balance of low-level/safety/coherence, semicolons be damned.


Elixir is neat, but it's such a leaky abstraction; you still have to deal with a lot of Erlang stuff that Elixir doesn't cover.

Also, Erlang is slow. Really really slow. It's faster than Ruby, I think, but not much. And It sucks at a lot of things that should be fast in a functional language, such as file I/O.

Erlang itself is also neat, but the syntax is abhorrent (commas and periods instead of semicolons!), performance is awful, and the language has many warts (no Unicode, no structs, etc.).

I see where you're coming from. As for me, I am intimately familiar with everything that Rust provides, and it's frustrating because it's close to what I have been waiting for, but it makes a bunch of design choices I disagree with. Same with Go.

For now, Go is much closer to what I want than Rust, but performance is pretty awful for many things, so I'm not a happy clam.


> Really really slow.

If the goal is simulate n-body problems and solve one instance of sudoku it is not the right tool. If one needs a fault tolerant system to maintain 2M concurrent connections to clients then it is the best tool for the job.

http://www.erlang-factory.com/upload/presentations/558/efsf2...

Think about Erlang as a tank. A cool hipster comes to you says "LOL, my fixie bicycle is sooo much faster than your tank" and he's right because in some cases you just want to go to the nearest coffee shop to pick up an espresso. However a time comes when you need to go into battle and putting a turret and shields on the bike only works so far, then it is time for a serious tool for the job.

> performance is awful

I don't know I wouldn't call something that can handle millions of concurrent connections slow. It is slow if you all you need to do is handle a single connection at a time.

Fault tolerance is actually the main feature of Erlang everything else flows from it. You don't always need it but when you do need it there is nothing like it. Fault tolerance mean paying some performance penalty.

> syntax is abhorrent (commas and periods instead of semicolons!),

Don't those make more sense though? How does a semicolon ending a statement make more sense than a period. And if there are 3 things that are executed then comma seems quite natural as well. On the other hand few languages rival Erlang's pattern matching.

> no structs

Frames/Maps are coming next year as part of R17


Erlang is great, but for me, its problems simply outweigh its benefits.

For example, not every app has a need for Erlang's massive parallelism. I can't write desktop or iOS apps in Erlang. Small utility scripts are cumbersome. There seems to be no kind of strong graphics or game support for it. For web apps the lackluster performance means is not really a step up from Ruby, which I currently use, so in that area there is no reason for me to switch.

In fact, the only area where Erlang is really perfectly suitable is in developing fault-tolerant, concurrent, parallel, distributed systems. And yet when I do need to write such a system, I look to Go instead.

> Don't those [commas and periods] make more sense though?

No, they really are a bad choice. First, any kind of statement terminator/separator should be unnecessary, as I have argued elsewhere. Secondly, distinguishing between two types of terminators is a bad idea because it makes editing harder. If I have

    A,
    B.
and I want to switch the order to:

    B,
    A.
then I can't just use my editor's nifty line-transposing mechanism. I have to edit each line and change the "," into a "." and vice versa. It's incredibly badly thought out.

Really, I like Erlang, but whenever its syntax is discussed, its defenders come out of the woodwork to make arguments without ever really wanting to listen. Syntax does matter. From speaking to lots of people, I know that Erlang's antique and cantankerous syntax is the number one problem preventing people from adopting it. As long as erlangers do nothing about their syntax, it will remain a weird little language that people admire but don't use.

Just look at Elixir -- people actually get excited about it. Because it has a nice syntax.

> few languages rival Erlang's pattern matching

Erlang's pattern matching is cool, but its reliance on ordered lists (which it calls tuples even though the fields are unnamed) makes it less cool again. I vastly prefer Haskell's pattern matching and overall approach to typing.


The characters for the different pointer types remind me a little bit of the Hungarian notation. And I thought this is a bad idea.


It's not Hungarian notation, the sigils are part of the type. Here's how you'd say the same thing in Rust and C++:

  Rust: ~T
  C++: unique_ptr<T>


Python indentantion-as-block definition has many drawbacks, not to mention the lack of semicolons that forces \

you \

to \

write \

so \

many \

backslashes.

They are not the ultimate solution for block definition and line breaking. You must be very used to them, and that's why you find the lack of it irritating, but that's another story.

Disclaimer: I code python every day of my life nowadays, I'm not a python hater.


I type many, many more semicolons in C or C++ than I type line-continuation backslashes in Python, so I prefer the option that requires fewer keypresses and less syntactic noise.

Or to put it another way, I'd much rather have to syntactically announce a line-continuation (which happens rarely, and is thus an atypical event that is worthy of note) than announce the end of a statement (which happens every single statement, and is thus to me much less worthy of note).

My reasons for preferring indentation-as-block over brace block-delimiters are similar: The indentation is a much more subtle, unobtrusive, un-noisy alternative to braces.

Furthermore, when I code in C or C++, I indent (and brace-delimit) everything properly, according to a style guide; so if I'd be indenting the block anyway, why not make the indentation syntactically meaningful, to save me some keypresses and slightly decrease the syntactic noise?

Plus, for bonus points, brace-less blocks mean I never need to play the brace-matching game. ("Have I got an extra/missing brace in there somewhere? Put the cursor on the brace and tap `%` until I work out what's out of place." True, it doesn't happen frequently if you keep your blocks and functions small, but I'm quite happy to avoid it altogether.)


I've written a lot of Python too. When I need to span lines, usually there's an easy way to use parens to do

    blahblah = long().invocation_of.something(with,
                   lots, of, parameters)
which is generally more idiomatic. (Of course one wishes to avoid long lines at all but that's not always possible.)


I found that parnes rule used as an awful hack a lot of times. I use it only when the parens are naturally placed, but there are people that just add two parens to avoid one backslash... completely insane!


How is the backslash better? The parantheses can stay if you join two lines or split them.


Yup, and parens also allow comments.


I prefer Ruby's approach, which is not whitespace-sensitive, but has a very liberal approach to where expressions end.

The general rule is, as with Python and Go, that open braces, brackets, parens or quotes have precedence; and operators or punctuation at the end of a line will continue to the next line.

In addition, there are some complicated parsing internals -- not just for expression-ending sensing, but also for supporting parens-less method calls -- that endow the parser with some compiler knowledge about what tokens are variables and what tokens are methods. In other words, the parser has information that violates the parser/compiler separation of concerns, but it works really well in practice.

The only time I ever use \ in Ruby is for string literals that need to be broken up for readability:

    my_string = "This is a very long string that" \
      " must be wrapped."
You can use + or <<, but this will be evaluated at runtime, whereas \ results in a single string allocation.

Of course, Ruby requires "end" for a lot of constructs, but it could have just as well have used braces.


Ruby can use braces instead of end, both are valid.


Hm? Only for blocks. Not classes, methods, if/unless, while or begin/rescue.


Dang, you're right, I could swear otherwise but yup, just on blocks.


if you put a backslash on every line in Python, check your code, variable names. I rely more on splitting on tuples or dictionary items. So you can actually write like this:

    (forces,
     you,
     to,
      ...
     )


I found the braces and semicolons easy to work with and make reading code much easier. The line continuation (\) in other languages make it ugly.

Complaining about braces and semicolon is like complaining about parenthesis in LISP. Learn to appreciate the strength of a language and move beyond its syntax.


The standard indentation style is four spaces. Rust does have a pretty-printer (think gofmt), but it's not very good right now so it never actually gets used. It's very old and basically needs to be entirely rewritten.


I'm a big fan of rust (hence my username), and would like to know if there have been any non-trivial benchmarks of Rust's compilation time, and the performance of compiled executable.

Last I checked Rust took about 40 minutes to compile itself on my laptop. Is it still the case? (I haven't touched Rust for a month or so.)

Also, is anyone using Rust in non-toy projects? (Except Mozilla's own servo.)


Are these the sort of benchmarks (of compiled executables) you are looking for: http://pcwalton.github.io/blog/2013/04/18/performance-of-seq... ?


Thanks for the link. They're good, but I'd really like to see the comparison of memory safe version and parallel version, compared to languages which compete on those fronts (as the comments on that post have already requested), as that would really be the selling point of Rust IMO.


It's still a little early to be benchmarking the scheduler as it is currently undergoing a large rewrite, I believe.


I would say benchmarking the compiler at this point is a little premature. As far as I know they have not even finalized the language yet.


> Also, is anyone using Rust in non-toy projects?

Since it's not production ready yet: no


You should double-check what kind of projects are being worked on before saying that it isn't being used for non-toy projects :) I can list at least two off the top of my head:

Q^3, which can render Quake 3 maps and will eventually be its own game: https://github.com/Jeaye/q3

Servo, an experimental web browser being written by Mozilla: https://github.com/mozilla/servo


For me, a non-toy project is a project that runs in production, where I can build my business on.


I love rust, but we have not yet finalized the syntax and the semantics yet, so it'd be risky to write mission critical things in it. Our plan is to hit 1.0 by the end of the year.

That said, rust has been written in rust, and every commit is tested against our test suite on Linux, OS X, BSD, and Windows. So while the language itself may be changing, any code you write in it at a given point in time should work. It'll just take some (small) effort to keep that code in sync with the compiler.

So if you are able to handle that risk, we'd love to have you try it out. It'd really help us find the warts in the language/stdlib before we lock in 1.0.


Rust isn't there yet in my opinion. The syntax and semantics are still undergoing development, and the standard library is still in the process of definition.

If you want to rewrite your codebase on a quarterly to cope with the changes, that's up to you, but I wouldn't.

I'm waiting for 1.0 to really start writing code in it.


There is also a Famicom/NES emulator written in rust: https://github.com/pcwalton/sprocketnes


I know there are various pointer type prefixes in Rust (@foo, ~foo, &foo, *foo), 'foo for lifetimes and $foo for macro arguments, but WTH is +foo? https://github.com/mozilla/rust/blob/master/src/librustc/mid...

I haven't seen this in the documentation.


A very old, very very deprecated feature. I believe pcwalton's working on removing the last vestiges of it from the compiler as we speak. The feature was called "argument modes", but it's been deprecated for so long that almost nobody remembers precisely how they were used (very few understood it in the first place). They were quite pervasive in the early 0.0 days, and it's taken this long to remove them completely.

In addition to the +foo forms, there were also others: -foo, &&foo, ++foo, perhaps more. Be glad that they're gone. :)


They're called "modes" and were a way of controlling whether parameters were copied or passed by reference etc (I think). It's been deprecated for a while and there's an (ongoing) effort to remove them from the code base, e.g. the example you give has been removed already: https://github.com/mozilla/rust/blob/incoming/src/librustc/m... (along with most of the modes from the whole source tree, a big patch landed just a few days ago).

(Also, the master branch is not the one to be looking at for the latest changes at the moment: patches are merged into 'incoming', and master hasn't been updated for more than a month.)


+foo is an old deprecated feature called a mode that is finally just about to be removed. Because the compiler is written in rust, it can take some time for deprecated things to be fully removed from the language.

Modes were supposed to give hints to the compiler whether or not to implicitly copy or move a value into a function, but it was buggy and confusing. So we replaced it with always moving for unique types, and always copying for reference counted types.


I actually like Rust's compartmentalized approach to memory allocation. Having task/thread specific heap is very concurrent friendly, great for running programs in multi-processor system.




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: