Please note that Rust is very alpha alpha alpha at the moment. Syntax evolves constantly. Several concepts don't even exist yet, and many are present only in half-formed nascent states.
The bottom line is that if you're interested in writing applications using Rust, you should really hold off until 0.4 or so (I'd say give it three months), both to give them time to implement all the missing pieces and then to refactor the Rust compiler to use those pieces, thereby shaking out the bugs and annoyances.
But if you're interested in helping out on writing the compiler itself, or proof-of-concept libraries, definitely consider pitching in. The devs greatly appreciate volunteer contributions.
I guess it depends on what you mean by "ready". For instance, Go 1.0 was released just last week, but people have been building useful things with it for a long time now. I suppose it depends on how much instability you're willing to put up with in order to use the shiny new thing.
As someone who follows the project closely, I do think that almost all of the core concepts will be present by 0.4 or 0.5 at the latest (fingers crossed), which would probably be the best time for eager early adopters to dive in. Also consider that Mozilla will be using Rust for experimental prototype browser engine implementations soon, likely even before 0.3 is released.
But if you're looking for some semblance of stability, I'm not sure what advice I can give beyond "wait for 1.0"--which has no definite timeframe. The Rust devs don't even schedule minor releases more than two in advance, so Rust might jump directly from 0.4 to 1.0, or from 0.9 to 1.0, or from 0.367 to 1.0. But don't worry, when they do make the jump, I'm sure you'll hear about it on HN. :P
If you'd prefer to track the project milestones yourself, check out the Github issues page[1] and browse the currently scheduled milestones from the dropdown in the left column.
This is actually really cool in that it occupies a space between Haskell and Python. It seems excessively verbose at the moment but hopefully that will sort itself out in the end.
I feel like I'm beating a dead horse, but I really can not grasp what the catalysts are for creating Rust or Go or Julia or other new languages that want to be safe, reliable, readable, etc.. 30 years ago these problems were solved in a language Ada. Its exact requirements include all of those and more.
The steelman was the end revision of requirements for the original language. There is a comparison of C/C++/Java/Ada wrt the steelman available as well. Ada has become so much more since this document and it's original version one really must see it to be believe it. :o)
As a community we have a tendency to embark on projects on a whim, but the effort, time and money required to bring a language to maturity is enormous. Even then any deficiency a preexisting language may have surely is not so insurmountable as to make it viable to develop a new language in house.
Can we please have some sanity? Can we please look for mature solutions?
Edit: Ada has an amazing GCC frontend developed largely by a successful opensource company (with just massive customers across the globe) and is available across all of its targets: the bsd's, solaris, linux, mac, haiku, android and more. It's a great solution that is hard to ignore.
I don't have any experience with Ada, and I don't intend to refute your points. Nor do I have oodles of experience with either Rust or Go. However, as I see it, the problem with our current language ecosystem isn't "we lack a safe, fast, low-level language in which to implement things"; as you've pointed out, we've long had Ada. Instead, the problem is "people are using C++ to laboriously construct applications that, while not safety-critical, still require a high degree of reliability". This is a social problem rather than a technical one, and it probably has more to do with path dependence and resistance to unfamiliarity than with the technical merits of the modern iterations of either language.
In a perfect world, perhaps we'd be using Ada for all tasks that currently require C++. However, the fact that we're still using C++ over Ada suggests to me that there is still room for new languages in this area. I agree that it's sad to see so much redundancy and duplication of effort. But if the end result of all of this is that future applications are written in a more reliable language, isn't that still a net win for society, regardless of what that language is?
I've used Ada. It was a super major pain in the butt. Go is like an easier to use C, where Ada is like a harder to use C. The solution to "people screw up dynamic allocations" is not "make dynamic allocations brutally difficult".
Ada wants to catch as much as it can before runtime. To that end, it is one strict beast when you're used to all the willy nilly (and unsafe) constructs that we can beat C into doing. Ada absolutely is harder; it's built for hard problems. I don't intend to turn away from the topic of TFA, but Ada is on quite a different plane than C for a number of reasons--reasons that I think are compelling. C is wonderful for creating a foundation for low-level software as it has demonstrated for what seems like an eternity, but beyond that--and I think the crazy things we've done over time to make it a little easier to use reflect this--something with more high-level, safe, readable, yada, yada, yada is desirable if not absolutely needed.
Dynamic allocations in Ada are a cinch by the way. We use the "new" reserved word.
subtype Hacker_News_Article_ID is Natural; -- Numbers 0 .. Integer'Last;
type Article_Handle is access all Hacker_News_Article_ID; -- "all" reserved word used allows access to variables on the stack.
Favorite_Article : aliased Hacker_New_Article_ID := 3793716; -- "aliased" so we can point to this stack variable.
Article_Pointer : Article_Handle := Favorite_Article'Access; -- A sensible default perhaps.
later on...
Article_Pointer := new Hacker_News_Article_ID (Whatever);
What I meant by dynamic allocation was allocating an array of the necessary size. Last I checked, the Ada solution was to always allocate the largest possible array you would ever need every time. Correct me if I'm wrong, but in Ada if two arrays are different sizes, they are completely different types.
In practice, this means your Ada written image viewer can show you 1000 thumbnails, but no more. Or 10000, or some other hard limit. And you can only view images smaller than 2MP. Unless the author made the fixed sizes really large, but now you're burning 10MB of memory per image even if they're all tiny gifs.
This is untrue. This is an Ada declaration for a fixed-size array of Foo
with indices 1 to 10 (inclusive):
type Foo_Array is array (Integer range 1..10) of Foo;
This is an array indexed by an enumeration:
type Foo_Array is array (Some_Enum) of Foo;
But dynamically sized arrays can also be declared:
type Foo_Array is array (Integer range <>) of Foo;
Note that such an array has a dynamic lower bound and a dynamic upper bound. If
I create an instance of such an array and pass it to a procedure:
declare
My_Array: Foo_Array (3..10)
begin
Do_Something (My_Array);
end;
then the procedure Do_Something receives both bounds of the array, 3 and 10,
which it can read with the 'First and 'Last attributes.
A declaration like the one above is typically done on the stack (although it
doesn't have to be). An array can be allocated on the heap with "new", with,
IIRC, the following syntax:
new Foo_Array (3..10)
Yes. What you've written is exactly how to allocate an array of dynamic size on the heap. You can also do:
declare
My_Array: Foo_Array(X..Y);
begin
...
end;
Hmm, I remember it being very hard, but it seems I've lost the specifics. My bad. In any case, Ada is not a language I'm excited to work with, but Go could be one.
Ada 95 is a very different language from Ada 83, cleaning up a bunch of rough edges in the latter. That said I still don't really like it, for aesthetic reasons more than anything else.
You are right with respect ot maturity, and Ada does have some high level concurrency constructs, though I'm not well versed enough to compare them with other language's.
I think a main selling point for Rust is its type system: it's more up to date from the state of the art of... the mid seventies, having Algebraic Data Types and type inference. Though it does seem to lack some of Ada's features, such as its limited support for dependent types in the form of its ranged numeric types and fixed-length array, so it may balance out.
Edit: oh, and Rust has no null.
I guess people still dislike verbose syntax, and you still see people making macho arguments about how they like to throw type-safety over the window for 'power', but Ada without doubt is a seriously underrated language.
Ada's verbosity is one of it's best qualities making it perfectly suited for our large, geographically distant team. There are far less questions about the purpose and meaning of code when its in Ada. Seriously! And to boot the documentation writers have fewer problems determine this either since it's all spelled out in plain language. Of course this applies some to Pascal, Oberon and Modula for example, but they are missing other things that make Ada a great choice.
I'm a C++ systems programmer, so I'm trying to understand some of the issues here. I'm not familiar with either language, please forgive the ignorant questions.
Null: Why is null evil? Doesn't Go use it in the Java sense of releasing a reference to the object?
Global GC: Seems more like a runtime implementation choice?
Shared mutable state: Doesn't seem so bad for someone approaching a systems programming language. I don't always want to make copies and send it over as a message to the other threads?
My higher-level point is that, perhaps these languages could do a better job of selling, differentiating, explaining themselves. I know it's hard, that's why I'm trying to help by posing my stupid questions. Btw. if they're planning to write Firefox in this, maybe the author should maintain a minimal browser written in Rust to show how the language fits its original design goals.
Note that we don't forbid shared mutable state entirely (we don't forbid anything really, as we have an unsafe sublanguage that allows all the pointer tricks that you can do in C++), but we want to contain data races. Basically, as the FAQ says, "you can break the rules, if explicit about where and how".
We've learned that, especially when it comes to concurrency, there really is no one model that supports everything you might want to do. Instead, the idea is to support safe, data-race-free language constructs, and to make those the easiest ones to use. Data races (and memory unsafety) are clearly marked in "unsafe" blocks, with the idea that if you find a concurrency bug in your software, you can grep for that keyword and go over those blocks only, instead of having to crawl through the entire codebase.
The same principle applies to null. You can get nullable pointers (use option<T>), but you have to declare that that's what you want. You also have to declare some strategy for handling the null case every time you use the pointer, or at least communicate your intent to fail on null via the .get() method. The vast majority of pointers in any program aren't nullable, so in practice we've found that this eliminates a lot of bugs.
Null: Null is not evil, but programmers often fail to take it into account. If you see type `string`, it might not be immediately obvious that you can get either a `string` object, or `null`. It could be useful (for preventing bugs and for speed) to have different annotations for nullable and non-nullable variables/parameters (e.g. `string?`, or `string | null`, or `union(string, null)`).
Global GC: It's hard to do GC without stopping the world. If different threads have different heaps, only a single thread needs to be stopped at any given time for the GC to be performed (on this thread's heap). AFAIK, Rust also supports manually managed references.
Shared mutable state: I believe that is more of a language restriction, not VM (i.e. sending messages could be implemented without copying). Simplifies debugging and makes some abstractions much easier (distributed computing in particular).
Null is evil because it forces programmers to constantly check for null when compilers can do that much better. There can be situations when null is handy, but it shouldn't be the default. C++ reference can be used for similar purpose.
Global GC is definitely a language issue. It affects language semantics.
Avoiding shared mutable state does not mean making copies. If you can statically check there is no other reference you can avoid copying. Think advanced move semantics.
Null is evil because any pointer could be null, and the semantics of dereferencing a null pointer are either NullPointerException or just plain undefined.
While that is true, taking an initial look at the rust tutorial it seems to me that the number of syntactic rules in the language for Rust are much more than in Go, which is always a negative sign.
True, Rust has more syntactic rules than Go, but it's still (in my mind) a very small language, especially compared to C++. The developers are very conscious of language complexity and will not introduce new concepts spuriously. The increased complexity is because they're aiming Rust at a different application domain than Go, and for that application domain they feel that programmers require more fine-grained control.
Every language is small compared to C++. And keep in mind that Rust is still very young, and if simplicity is not a goal complexity can skyrocket before Rust reach 1.0 state.
However, the devs are aiming to keep the language simple. They're PL experts (watching them at work is quite intimidating, actually, as someone who doesn't have a PhD in CS), but they absolutely reject the allure of the ivory tower. Note the header on the page linked in this submission:
"a safe, concurrent, practical language"
Note "practical". I've witnessed several exchanges on the mailing list where the developers attempt to excise language features. For example, in Rust, `if` is an expression rather than a statement, and thus is redundant with the `?:` ternary conditional expression syntax familiar to C-like languages (the latter was removed). Alternatively, they often acknowledge that having three types of pointers is suboptimal from a simplicity perspective, but they consistently conclude that the semantics unique to each type of pointer are valuable enough to justify the mental cost.
Simplicity is definitely a goal. These days, not a day goes by on the Rust team in which we don't discuss ways to simplify the language.
My colleague Dave Herman always says that language design goes through cycles: You identify a problem, add solutions to fix it, then discover that these solutions are best merged with some other ideas. The result is that, as a language evolves, complexity goes up and down. I think that we're coming off a peak of complexity and the language is going to evolve toward simplicity in the near term.
Just to name a few simple examples, removing the alias analysis pass and removing "native modules" are some simplifications that mostly have consensus at this point.
One of Rust's primary design goals is safety. This is the source of most of its differences from both Go[1] and C++. Nullable pointers, free pointers, and shared mutable state are common sources of bugs and programmer errors in languages that have those features. Rust tries to address those issues by requiring the program to be explicit about handling such features. E.g., only pointers marked as nullable can have null value, and you are not allowed to dereference such pointers without a null check. This is the so-called "Bondage and Discipline" approach. There are pros and cons to this approach; the main arguments in favor of it revolve around the concepts of design-by-contract, and being able to enforce that contract, which lets you code less defensively.
[1] I get the feeling that Go's main design goal is ease of use, on par with Python.
"Rust is a programming language that's supposed to fit the C++ niche, without the insanity of actual C++. If the project works out, and it's going swimmingly so far, Mozilla will try to apply it to writing a next-generation browser, without the constant danger of buffer overrun exploits and threading bugs that comes with C++. True to Mozilla's spirit, all development on Rust is happening in the open, on github."
Is it more or less ambitious than trying to take an existing large C++ single-threaded codebase and try to multithread it without introducing bugs or running into Amdahl's Law early on?
Graydon's personal preference, and to make C++ programmers feel at home. I personally prefer whitespace-based syntax, but I'm not a die-hard either way. When designing a language, you pretty much have to pick one and disappoint somebody.
Being someone that has only ever programmed in languages that use brackets, I really, really don't get this white space thing .. it appears, to me at least to make reading code very difficult. With brackets I can scan a page of code and see the blocks of related code.
Well it's a personal preference of course but in my opinion it actually makes code much more readable. It forces everyone to use the same conventions for indentation and it gets the 'clutter (brackets)' out of the way so you can focus on what's important, the code.
Blocks easily identified by their indentation. It might take a little getting used to but I find it very pleasant.
I can't think of "forcing everyone to use the same conventions for indentation" as a purely good thing, any more than "forcing everyone to write comments in 18th-century English" would be.
Sure, you make it easier for the random onlooker to be prepared to always immediately understand what is going on, but at the same time, the programmer who writes for his own perusal or that of a small team of known others will find themselves restricted by a totalitarian scheme telling them what they can express and what they can't. The assumption that most code is written for most people to read is simply not true, and code that is intended for the masses has always been able to deal with the problem by imposing style guidelines.
I can't understand how forcing coding convention can result in "being restricted by a totalitarian scheme". We are writing in a formal language instead of English. Style is the last place you want creativity. Use you creativity to express algorithms, not brace styles.
But it's not simply a matter of creativity. Apart from contentious instances pertaining to the complete omission of indentation (if (sdfg) { a; b; }), there are also occasional cases where I'd argue that semantically, you have a block, but syntactically, you don't; for instance, I've always very much favoured the approach when writing OpenGL code to indent everything between a glBegin and glEnd to separate the vertex data from the surrounding code and make it immediately obvious how objects in the scene are grouped. I think several indentation-based languages would ignore the initial indent increase here and consider the indent decrease before the glEnd to be the end of the block containing the group of statements...
Actually, it's not as totalitarian as you imply. It's just a different way to express blocks of code. Languages which mark blocks using whitespace indentation (such as Python or Haskell) often don't force any particular amount of indentation. Consecutive lines with the same amount of whitespace prefix are considered be a part of the same block.
Most projects/companies have indentation/style standards so that code can be communicated across individuals. Once you add in the indentation style, braces look redundant and are just extra noise and chances for error.
I must admit, though, totalitarian systems often help people work together :)
When I look at code I see structure. Before I even see individual squiggles, brackets, semicolons, I see structures and blocks of code. One code-block indented in another, "oh look this is a huge block here", "these are 3 nested ones" and so on. Brackets don't help me there but indentation does.
Let me ask you this, do you already indent your code? If not it is probably a tangled mess and I wouldn't want to continue the conversion with you. But, if you already indent your code, then why do you need brackets? You are wasting space and you are repeating yourself. It is like enforcing that every declaration of "int counter" to be followed by a comment saying "// declaration of counter as an int".
The only reason to use brackets is to minify a piece of code or to appeal to C++ or C programmers. So Javascript benefits from having brackets. I guess Rust does too because it is trying to appeal to C++ programmers.
Brackets and parenthesis help me understand the structure and flow of code at a glance. Indentation helps too, but it doesn't completely subsume structural syntax. It's like commas, semicolons, periods, paragraphs, etc in writing. They're tools to help you convey meaning that isn't apparent from the words themselves.
Minimalism for its own sake is an anti-pattern in language design. I will be very happy once this meme dies.
There is no less structural information in, say, a Python code block than in a C code block. Once you get used to the syntax and language semantics, you will just as easily be able to understand the structure and flow at a glance.
Brackets give your editor the information it needs to automatically infer scoping and to do smart reformatting. Without it you're entirely on your own.
What counts as "good"? By your definition it's one that can provide helps with indentation-based blocks. :-)
I can't depend on having a "good" editor. I have 2 work machines, 2 home machines, ssh to a VPS, ssh to a bunch of machines at work, etc. So as often as not I have to use vim to do quick edits of code. I also am generally forced to use Apple's Xcode for Obj-C applications, but use other editors for anything else. Working on my own toys vs. working at work, vs. being in school instead of a commercial entity with nice software licenses also means I can't depend on having the same text editor available, other than free ones.
I'd prefer to use a programming language that was easy to read and write in just about any text editor. The only requirement I can't easily escape is that the editor must support auto-indent. (So MS Notepad is out.)
> I'd prefer to use a programming language that was easy to read and write in just about any text editor.
Actually you can apply that argument for whitespace only languages, because they produce code that is more consistent. So because the code is more consistent it is also easier to read and write (as opposed to say, dealing with someone's eccentric formatting).
Vim or emacs (the one I use) is available for any modern OS out there. It is free and has outstanding syntax highlighting and works through a terminal as far as I know.
In general it seems like this is a tail wagging the dog problem -- picking a language to work with (what seems to be a broken) editor.
It can't because the indentation is part of the code. If I run a Java source file through a script that removes all whitespace I can get a beautifully formatted file back with a single keypress. This is literally impossible for whitespace languages like Python and Haskell.
My editor (emacs) does a great job at formatting Python code. If your compiler and your eyes get enough information about how code is structures from indentation so should your editor.
Being someone who has only ever programmed in languages that use whitespace or parens, I really, really don't get the curly braces thing. :) White space is very readable and just as obvious a discernment of codeblocks as curly braces.
As someone who uses both constantly,
Whitespace languages and curly braces are the same.
For a good programmer, she can take out the curly brace and it should look like a whitespace language. Likewise, a whitespace language would just have braces inserted everywhere there would be an indent change. '{' for forward indent and '}' for backwards indent.
The problem with significant whitespace is that it makes routine tasks like copy & paste and shifting blocks around a tedious and error prone exercise instead of a trivial editor task. Give me instead a syntax that lets my editor completely and correctly reformat an entire file with a keypress.
Significant indentation is the #1 thing keeping me at a distance from Haskell and Coffeescript.
I find that significant white space is a problem mainly when going between editors, and also mainly because of space vs. tab problems. E.g. if I copy-paste from vim in Terminal into TextWrangler (free BBEdit) then all the tabs have become spaces, which python will throw a fit about. Similarly if I copy-paste code from a website or blog entry.
In languages with () or {} I can hit a key to reformat copy-pasted code. In Python I have to do it manually.
When it comes to moving blocks of Python code around inside one source file, then it's a simple matter to hit the plus/minus indent hotkey.
Using tabs instead of spaces is not a recommended practice for Python, or most white space orientated languages that I'm aware of. Adopting that best-practice would seem to alleviate most of your concerns that you've listed here.
Most editors even let you handle that on a filetype basis, so you can use 4 spaces for Python, and tabs for your C files.
>Why should I even waste my time worrying about supplying spaces or tabs every time I go to a new line while programming.
What are you talking about? Why wouldn't you have your editor just insert the correct number of spaces when you press the tab key? It's worked fine for all my python work.
Anyway, that's tab vs. space flamewar, best practices flame war, etc.
Long story short, I don't like spaces because editors do not make it as easy to navigate back/forward 4 (or 2) spaces as it is to navigate 1 tab. Most annoying instance of this: what combination of keypresses does it take to get from the middle of a line to the beginning of a line? In Notepad++ it's easy, but it Xcode its cmd-left-arrow then hit right-arrow for every space/tab you need to pass. (Or in general for a Mac text editor cmd-left-arrow, then opt-right arrow, then opt-left arrow, but that doesn't always work right. In TextWrangler it's cmd-left + opt-right, which is better but still slightly tricky hopping from cmd to opt key.)
And now I'll introduce the editor flamewar: in vim, moving from anywhere on a line to the first non-whitespace character on that line is just ^, moving to the very first character of the line is 0. In general, navigation in vim is whitespace agnostic (inasmuch as you move around by chunks of text, not character by character)
I worked at a company a few years ago that experienced a site-wide website outage because an engineer hotfixed a python file with an editor that inserted a tab instead of a space. It wasn't easy to pinpoint the problem either.
Well, I dunno, I've never really had issues with it but, like I say, vast majority of my code has been in Python and Clojure. I'm not arguing against braces, btw, it's just another delimiter like whitespace. It's all just about what kinds of things you're willing to train your brain to do, IMO.
IMvHO: Curly braces are like punctuation marks in a language, in that they very clearly mark the beginning, end and so and so forth.
But, yes, it is a very style issue, but to me code without curly braces feels very naked.
Meh... I've written both Python and C/C++/Java, and I disagree that it's possible to reach a point where the indentation completely obviates the need for brackets in identify blocks. That might be true if you always keep blocks extremely short, and if you never have more than a couple of levels of indentation, but in the real world code never quite seems to fit that Platonic ideal.
I'll grant, however, that the Python approach isn't quite as bad as I thought it would be, and that it can come close to matching the readability of "code with braces." But, for me at least, braces (and vertically aligned ones at that, dangit) absolutely make code more readable.
It's like becoming bilingual. When you know only English other languages are completely confusing, but once you learn a second language you can more easily pick out pieces of others.
If all you know is {}, then other code is harder to read. Once you learn either a Lisp-like language or a Python-like language then you learn to see code blocks without {}. This is what happened for me. (I was forced into learning Scheme in school. Only after that did I decide that Python was an OK language after all.)
My guess is because they're primarily trying to appeal to C++ programmers seeking a safer systems language rather than Python programmers seeking a more accessible low-level language.
Incidentally, I'm the latter, and I'm very interested in Rust.
I also find Rust very interesting. For the target of Go, I think it works just fine to use Python for most things and call out to C for performance-critical sections. But I have been annoyed for a long time by how often programs crash on simple errors that should not happen, like null pointers and buffer overflows. I really hope Rust (or something like it) can take off.
There is a lot to like about Rust: immutability as default, pattern matching, destructor, coroutines, uses LLVM, no hierarchy interfaces, no null pointer, built-in testing. Interestingly, the Rust compiler is written in Rust itself. If you use Mac, there is homebrew for Rust. I hope Rust will take off.
The developers behind it have a C++ background. Code style was not the point of the language, and therefore they went with something familiar to the devs working on it.
I know that some PL experts tend to write off syntax as an issue of secondary importance, but for many developers, it's a critical part of code readability. I've spent much too much time trying to untangle masses of ill-written JavaScript with various (or no) levels of indentation, and braces scattered across the screen. I love working with Python, CoffeeScript, and Haskell because the code is almost always very readable because of whitespace (from what I've seen, Ruby is also very readable). I'm intensively interested in Rust as a possible alternative to C or C++ -- Go is a notstarter since I can't even compile as shared object library in it. However, I wish the designers of Rust had taken the arguments for whitespace into serious consideration. There's a large number of Python and Ruby programmers looking for an alternative to C and C++ as a lower-level language to call using an FFI when we need more speed, and for most of us, readability (and therefore syntax) is a major issue. Nonetheless, Rust seems like a very cool language, and I'm looking forward to trying it out.
to be rather unreadable. My solution is to not write it that way.
My observation is that code style is very important to Ruby and Python developers and less important to those from C-family backgrounds. That is, a lot of Ruby developers, for example, refuse to touch anything containing braces whereas few C-family developers require them.
I think the solution is that developers with a Python/Ruby background need to create a systems language, instead of expecting those with different backgrounds to be converted to the Python/Ruby-ists mindset. But in reality it seems that few Python/Ruby developers are all that interested in systems languages whereas those with C-family backgrounds are very interested (hence the situation that presently exists).
Fork Rust and change only the syntax, just to make it use whitespace for blocks. PL experts see syntax as secondary because it is something that can arbitrarily change. Take Racket for example. They built into the language the ability to plug in arbitrary syntaxes and still use the same language tools and API. I got tired of () when I was learning Racket and wrote an alternate syntax that used whitespace indentation and converted to 100% compatible s-exp Racket code.
So, you can have a whitespace-based version of Rust easily.
The practical problem is that then you'd split the community between the two syntaxes since you couldn't copy-paste code examples from one syntax into the other. That could be problematic for building a large base of support. Take D for example where they had fragmentation problems with two standard libraries. Perhaps a split based on syntax would be less? (Since code written in one could be shared with the other.) But it would still cause problems in how the language is marketed to new developers.
have there ever been any successful "skinnable" languages (or any successful language skins)? i'm thinking of things like SPECS for C++, or the way research functional languages sometimes provide both, e.g., a C-ish and a lisp-ish syntax that compile to the same thing.
Meta-comment: It's interesting how the default way changes with time... around 10 years ago it would be "why does ruby use the weird syntax instead of just brackets like c/java/js/...?"
Can anyone explain this, from the first paragraph, to a bog standard PHP-for-the-web programmer please?
"Its design is oriented toward concerns of “programming in the large”, that is, of creating and maintaining boundaries – both abstract and operational – that preserve large-system integrity, availability and concurrency."
- "Programming in the large" - programming produced by lots of people and/or meant to last a long time.
- "creating and maintaining boundaries" - when you have a lot of people working on code, it's very useful to be able to isolate code and define the boundaries between code explicitly. Things like interfaces and type safety tend to help do this (the "abstract" in "abstract and operational"). On the "operational" side, having modules that produce dynamic libraries with good versioning semantics helps.
- "that preserve large-system integrity, availability" - again, type safety, in-built null pointer protection and garbage collection all help make sure that code doesn't fall over as much as it could without those (there are some philosophical arguments in here that I'm not exploring).
- "concurrency" - Consensus appears to be forming around the idea that a good way to manage concurrency is with lightweight processes and message passing rather than threads and shared state. Rust does the former. Rust also encourages the use of immutable state which also helps avoid concurrency issues.
One ofmthe original ideas of oop was that it would be possible to encapsulate how part of anrogram worked from the person who used it. You shouldn't have to care about the inner workings of the storage layer, say, or the gui toolkit.
Unfortunately in reality things are usually not that well encapsulated. Things like threads, integration withe the system, etc often interfere as does things like the desire to test a particular piece of software.
Basically think of it as enabling the same benefits you get from having a general count function over having specific functions for arrays, directories, lists, etc but to an enti system.
Some of the difficulties in large projects include:
1. It's easy to break things accidentally, and it's hard to track down all the usages of something when you change it. This is especially true when functions and types can be aliased under different names, changing a class affects all subclasses, etc. The more complex the application, the more you get pervasive usage of types defined within the application. This is a real change from smaller applications where most of the pervasive types probably come from the language's standard library, which can be trusted to be stable between major releases.
2. A large codebase means that whatever finicky housekeeping the language requires is almost guaranteed to get screwed up somewhere in your application. If this affects the integrity of the whole app, it can be very bad. Invalid memory accesses are an infamous example. It doesn't matter if you have a million lines of awesome, feature-filled code; if one buggy line of code crashes your app every ten minutes by dereferencing an invalid pointer, your app is unusable.
3. Fragmentation of types and libraries. Programmer X adds a Flugelhorn library on one end of the app, programmer Y adds a Flugelhorn library on the other end of the app, and nobody realizes it until incompatible Flugelhorn types start bumping into each other in the middle. This is less of a problem for a community where "programming in the large" means many people writing many small independent projects, but it could be a major annoyance for a language where the goal is to write large, complex applications such as web browsers.
4. Concurrency. Concurrency can be a coupling factor that requires programmers to know too much about global design and global state. It can also destroy performance and stability. Finally, given principle #2 above (every large running application contains screwed-up code somewhere) runaway tasks are a threat to the whole system if not contained. When done well, however, concurrency can reduce coupling and improve stability.
5. It can take a long time to rebuild a large codebase and run its tests.
I don't know much about Rust so far, but here's my stab at matching the features of Rust against those five problems:
1. Compile-time type checking is a big help. Rust also has some ways to enhance types without subclassing.
2. Memory safety, garbage collection, errors that propagate upward by default, isolated tasks. Error handling is unappreciated in this category, I believe. It's important that an application not accidentally suppress an error and continue, because it could corrupt data, return incorrect results, or behave insecurely. A language like C where errors can be swallowed through oversight or programmer laziness is dangerous in that regard. In Rust, errors propagate upward, unwinding the stack until they terminate a task or are explicitly handled.
3. Generic types help, and built-in support for Unicode text is a necessity. It also helps that the organization shepherding the language is likely to be the biggest user of the language. It's important to note that anything that helps with #3 also helps with #1. For example, if the language has a standard string type you can use everywhere, then your tests don't need to protect against Doug down the hall (or across the world) changing the string type and not realizing he broke your code.
4. Immutability, message passing, isolated tasks, per-task GC. It sounds like Rust is trying to make task isolation the default way to firewall errors off from the rest of your app. For a web programmer, this is exactly like the way a Java web container is supposed to work. If one web app in the container goes haywire, the container and all the other web apps should ideally be able to continue running without their stability being compromised.
5. I don't know what techniques are used by Rust to speed up compilation. A compiled language is at a disadvantage on this count, but compiling to object code is necessary for a systems language. Also, static type checking means drastically fewer unit tests (I don't want to start a flamewar about whether this is a good thing; it's just the way people code) so you get a little bit of your lost compile time back when you run tests.
> I don't know what techniques are used by Rust to speed up compilation.
From what I've observed, forcing the developers to compile the language using itself is a great way to keep the programmers mindful of compilation speed. :)
In Rust's case, I believe the bottleneck is LLVM. You can disable optimization if you just care about fast turnaround times, but you're always at the mercy of LLVM to do the actual code generation. To that end, the Rust devs have recently begun an initiative to profile the amount of LLVM IR that they generate in the compiler, and they've made some good strides so far just from picking the low-hanging fruit.
As far as comparisons to other languages go, I'm not sure if Rust's compilation model is set up to be as fast as Go's, although (IIRC) Rust avoids the template-generation step that bogs down C++.
We'll never be as fast as Go in compile speed: just to name a few issues, we do flow analysis (so we check whether your variables are initialized before you use them), our typechecking proceeds by unification (so you can say stuff like [] and the typechecker will figure out what the type of that empty vector is), and we have an extra IR-generating step (so we can take advantage of LLVM optimizations). It's a question of different goals; one of Go's primary goals was to compile quickly (which is a fine goal!), which isn't one of the goals of Rust (although we definitely want to compile fast, of course, and we have continuous integration benchmarks to that effect).
Thank you all for your replies. I'm entirely self taught and attempting to become a 'better coder' in the abstract whenever possible, things like this definitely help along the way.
Out of curiosity, what's Mozilla's motivation for making a new language?
Everything I'm reading here in the comments is talking about how this would be a replacement for c/c++, but wouldn't Mozilla be more interested in a language that's more web focused? As I see it, Rust would NOT be a web language, or am I missing something? Is this something they would try and develop future versions of Firefox in?
This is the whole reason why that language has such a big potential.
It has high level algebraic datatypes with pattern matching, so you can nicely model your control flow (like haskell or ocaml) but still remaining low-level.
rust seems to get compared to go a lot, simply because they are socially similar (open source c-like language developed by large, popular company). i'd like to see some comparisons with languages like clay and ats, both of which seem closer to what rust is trying to be.
Can you please add some more relevant information to your comment? Expand upon why you feel it is similar to ADA, why ADA might be a better (or worse) alternative, if you have any experience working with ADA/Rust, etc. A three word comment does not add anything worthwhile to this thread. If you're on HN and commenting, please refrain from throwing whispers of thoughts down as they come to you, and instead take the opportunity to reply with something meaningful.
I have no real experience, just college classes in ADA. And reading the rust documentation reminded me of ADA. I can't hardly explain more than that is an old feeling I've only had when I studied ADA.
I wasn't sarcastic or trolling, but I understand it's hard to know with a cryptic 3 words sentence.
ps: I gathered some thoughts. It reminded me of ADA because it's designed to be low-level, yet embed high-level concepts and typing (generics).
I have real experience with ADA (also C, C++ and many others), and I have discovered that ADA is brilliant, a way underestimated language. But ADA requires a lot of discipline which is a possible reason why many developers don't like it.
I also like Rust. I haven't tested it yet (will try it) but the first impressions are good. But I think Rust will not be on par with ADA 2012 until it supports range values (like x : Integer Range 1..100) and contracts at least.
Asserts are good for the beginning but a language for really big software should have verification mechanisms which are implemented in SPARK (a subset of ADA).
The way I understand them (and I say this a lot, but I could be wrong) is that it's like a more powerful version of Eiffel's design by contract, which allows the compiler to test whether invariants hold at compile time rather than just throwing assertions at runtime.
Another option (addon) would be to use commented invariants like in SPARK which are tested against the code by an automatic verification system even before compile time. To get an impression what it means, please read:
Interesting. Not sure precisely what you mean by "bounded memory usage", but if you mean array bounds checking then you're correct in that Rust requires a runtime component for that.
no, I mean that in SPARK you are able to state that some program will not grow it's memory usage indefinitely (I believe you also have worst case time analysis).
AFAICT this requires forbidding recursion, unbounded loops and use of heap allocators or types/procedures which in turn have access to such facilities.
Or somewhat equivalently: the SPARK subset of Ada is statically verifiable by not being turing complete, so bits of the code can be verified, and elsewhere the full Ada language can be used.
I am not sure if Rust can emulate this.
(Again, I am not an Ada/SPARK developer so all of what I wrote may be wrong, do not take life decisions based on what I write)
Thanks for the clarification. I can't find the source, but I believe there's a quote somewhere from Graydon (Rust's head designer) stating that complete static verifiability isn't a goal they're aiming for, at least not for the foreseeable future. However, I suppose that doesn't preclude someone else from forking the Rust compiler and devising a non-Turing-complete subset on their own. :)
The bottom line is that if you're interested in writing applications using Rust, you should really hold off until 0.4 or so (I'd say give it three months), both to give them time to implement all the missing pieces and then to refactor the Rust compiler to use those pieces, thereby shaking out the bugs and annoyances.
But if you're interested in helping out on writing the compiler itself, or proof-of-concept libraries, definitely consider pitching in. The devs greatly appreciate volunteer contributions.