Rust for the Web
thefullsnack.com
thefullsnack.com
It seems that the older frameworks like Iron and Nickel.rs are not (yet) catching the async train.
And that's just at the language level. You then need pervasive library support. And then you need more GHC work on optimisation, work out how you interoperate with levity polymorphism and so on and so on.
And _after_ all this work is done, I seriously doubt you'll be able to control memory usage as well as Rust does now.
I love Haskell to bits, but there's no way it's going to beat Rust at what Rust's good at for a long time to come.
Which might be totally irrelevant in most use cases, if it is within the desired application bounds.
I have replaced more C++ systems with Java and .NET solutions than the other way around.
I wasn't clear to me if haskellandchill was claiming that Haskell will be better, or if Haskell is more complicated. I assumed they meant it's more complicated than Rust, but now I'm not sure.
Rust has a comparable amount of runtime as C, here it is: https://github.com/rust-lang/rust/blob/master/src/libstd/rt....
wasm/asmjs does bring in some stuff, because it's mostly in a "it works" state than a "this is as good as it gets" state; our initial implementations didn't even do much optimization at all. Last I checked (last November), an example TodoMVC was to ~650K total, and given that the smallest known Rust binary is 151 bytes, I'd imagine that only gets smaller into the future.
https://cryze.github.io/advent-of-code-2016/ has a bunch of Advent of Code programs in Rust, compiled this way; Day 1 is weighing in at 300kb, it looks like.
asmjs is also much larger than wasm, day 3 is showing 1.4 MB for asm, but 69kb for wasm.
In my case I'm writing a Web app to expose the functionality of a library that's written in Rust, and Rocket was a natural choice for that—it would make little sense to use some other language and go over the FFI. On the client side, I've found that TypeScript 2.x in strict mode goes nicely with Rust on the server, as both Rust and TS 2.x have comparably feature-rich and expressive type systems (generics, tuples, discriminated unions, a distinct null/option type, etc.)
As I recall, there is another bit of research that claims that the number of bugs written in all languages is about the same, except C++ which produces way more.
Of course, different tools work well for different projects and different people's styles. If you needed me to write a CRUD Web app as quickly as possible I'd probably use Rails. After learning Rust and working with Rocket, though, I think most programmers will find the development experience enjoyable for lots of Web apps. I was pleasantly surprised at how elegant Rocket is.
It should be substantially less surprising when it's got non-lexical lifetimes, though.
Rust seems to me eminently suited to write high-performance web applications.
Also just because they have a GC doesn't mean all allocations have to go through the heap.
Rust killer area is the low level C stuff, resource constrained embedded devices, device drivers, codecs, ....
Lifetime annotations (which are the other feature needed by Rust's memory management) are sometime annoying though.
I had lots of fun going through the Idris and Rust books, but I don't see the average enterprise programmer wanting to deal with it.
Surely not the ones that I know, that don't have any idea what Idris, Rust or even HN are all about.
Which is why D, Swift, C++, Pony designers are looking into Rust, taking some of its ideas, and blending them with GC + dataflow analysis.
Ease of learning and productivity are two different things. Rust is indeed harder to learn than JavaScript, but IMHO it's more productive in a day-to-day use thanks to its powerful type system (caveat, the ecosystem is still pretty young).
Swift is harder to use than Rust in my opinion since you have to deal with cyclic references to avoid memory leak with ARC.
I share the opinion of the current thread going on Reddit and Rust forum, that the use cases of C and C++ should be the ones being targeted by Rust.
Everyone else is quite happy using GC based languages, specially on web development.
> Everyone else is quite happy using GC based languages
The huge amount of rustaceans coming from language with GC (including myself) isn't really in favor of your argument.
As a web dev currently using rust for cli tools, I'd be really happy to do my web stuff in Rust also once the web story for rust has matured. And seeing what happened since last year in this field, I'm really optimistic for the future.
I understand that not everybody thinks the way I do, but we exist though ;).
C++ has a GC API since C++11 and there are extensions like C++/CLI or Unreal C++ that make use of a GC.
The amount of people doing production web development in Rust won't be more than a single digit, when one takes the whole web community into account.
I surely don't want to think about affine types when doing UI design in Storyboards, Android designer, WPF/UWP Blend designer.
Well, I'm pretty sure a few people at INRIA would be really happy if OCaml was used by a single digit percentage of the whole web community. If Rust reached this stage I think we could talk about its success in this field. Go is considered a pretty sucessful language for web back-end stuf and I'm pretty sure it's not used by more than a single digit percentage of web devs.
> I surely don't want to think about affine types when doing UI design in Storyboards, Android designer, WPF/UWP Blend designer.
I don't understand your point, affine type is something that helps you write more maintainable code : you can't have two different sections of your code mutating the same piece of data without you knowing it. It makes me think less actually. And if you need to have two owners for a given piece of data, you can opt-out the ownership system with reference counting and interior mutability. Those rules and mechanisms are difficult to learn and internalize, but once that's done it helps you and makes you more productive.
Simple exercise, imagine a GUI builder regardless of for web or native code, for pumping out plain CRUD frontends, dragging components from a toolbox into the UI designer.
Components, of course, have a property designer that allows setting properties like database connections or data grid paging.
Now try to fit affine types into this kind of workflow, without forcing people to manually create some kind of auxiliary types and deduction helper functions like described on the Idris book.
Very basic example,
1 - Drag component into the form, variable could be declared as owned
2 - Edit a relationship between the component and another one on the property editor, either generate code with borrows or update the owned declaration into a Rc one, Arc instead, or Rc with RefCell, Arc with RefCell,....?
The GUI editor needs heuristics to create declarations with the right set of affine types, or to update existing ones when the developer clicks around changing the document tree and relations among them.
Oh and the current state of the borrow checker in Rust doesn't handle closures for self in callbacks, which makes it a royal pain to write GUI event handlers.
How about using move by default, if the compiler complains about moving the data, falls back to Rc<RefCell<T>>, and if the compiler complains about `Send` use Arc<Mutex<T>>. Or you could even use the later for everything in your UI designer, this way you get a memory management scheme which is like Swift's. (In first approximation at least, since Swift has CoW for some kind of things, but you could definitely copy the exact Swift behavior in Rust if you wanted).
As I said earlier, the affine type system is opt-out in Rust, so you can do whatever you need without it(including your GUI stuff) and still be able to benefit from it when writing your business logic, and being more productive thanks to it.
There is a lot to like about Rust, but here are some things that I think make rust hard (and I think the difficulty of these features outweigh any productivity granted by the safety features).
First, the affine type system--I don't understand the use case for pushing ownership deeper into the stack by default, and it seems crazy that I have to know how all instances of a given type will be passed at definition time. It doesn't seem to facilitate safety, or at least it seems like the most flat-footed approach to preventing double-frees (never let two functions access the same memory, even those that can be trivially proven to run sequentially). I literally never want to move--I always want to shallow copy (or reference). Further, you can't call most pass-by-value functions from inside a pass by reference function because the former usually wants to destroy the value. Copy works around this in the simplest cases, but for the most part you end up with two categories of classes that can't be mixed. This is especially bad for open traits, where the trait definition has to decide how all implementations will pass and receive their arguments.
Beyond that, when defining a struct type that holds a reference, you have to know at definition time the lifetime of that reference, even it may vary from instance to instance (sometimes I want the struct to own the reference, but sometimes I don't). Maybe there's a way to express this in Rust, but it seems like the default is to assume that lifetimes are part of the type. This creates another dichotomy in types: those that own their data and references to data (String vs STR, vec vs slice, etc).
I like Rust. I love that it's an ML with a sane syntax, or a C-family language with decent functional features and sum types. I just can't justify these impediments. :(
This might just be a case of needing non-lexical lifetimes. I'm not sure about that, because I don't know the details of what issues you ran into.
> Beyond that, when defining a struct type that holds a reference, you have to know at definition time the lifetime of that reference, even it may vary from instance to instance (sometimes I want the struct to own the reference, but sometimes I don't).
The main issue I run into is when I want a struct to own a value, and for that struct to also include a reference into that value.
I don't think the issue is about lexical lifetimes, but I don't have a very good understanding of what that means, either. My issue is that I frequently want to take some data and pass it into two separate functions, but I can't do this unless those functions are designed to take the value by reference. Even if those values contain owned references into the heap, the programs can be trivially proven to be correct. I can work around this by always passing references, but it seems strange to use reference semantics when all I really want is to not destroy the original value.
Another common case is that I have a borrowed reference that points to data I would like to pass (by value) into another function: `fn foo(bar: &Bar) { baz(bar.x) }`.
I don't think that's true. Passing data to a function when it's not a reference means that you're giving ownership to that function. How could you then pass it to another function (unless the first returned it again)? Once a function has ownership, it means nothing else has ownership of the data.
Basically, if you write a function that just takes a value, and doesn't take a reference, then you're telling your callers to give you ownership. If you don't want to take ownership, then just always accept a reference.
Maybe I'm misunderstanding the problem you're having. Do you have an example of another language that lets you do what you want?
Only in Rust, but there's no apparent reason to move ownership. If Rust didn't move ownership during pass-by-value, it would still be trivial to prove the following code correct:
fn main() {
let x = String::new();
foo(x);
bar(x);
// x is destroyed
}
> Maybe I'm misunderstanding the problem you're having. Do you have an example of another language that lets you do what you want?Here's the equivalent in C++:
int main() {
std::string x = "";
foo(x);
bar(x);
// x is destroyed
} int main() {
std::string x = "";
foo(x);
bar(x);
// x is destroyed
}
Doesn't C++ do a copy in this case?But Rust is more explicit about copying in general, to make it harder for the performance cost to be hidden.
If a function only needs to use some data for a bit, it should borrow it i.e. pass by reference.
And if you need to give ownership of some data to a function, and you also need that data for something else, you have to copy it, so that you can give one copy to a function to do what it wants with, and keep the other one for your own purposes.
I've been trying to isolate it down to a reproducible sample but haven't nailed down exactly what's causing it yet.
Even with that issue it's been great to work with. I find myself so much more productive with Rust compared to C/C++.
Alternatively, since setting up/running creduce can be bit fiddly, if the code is open source, I suspect that someone would do it for you if you filed a bug against Rust pointing to an exact commit that demonstrates the problem with `cargo build --target=...` (or xargo) and requested/suggested creduce.
Is this vulnerable to the classic "../../../../../../../etc/passwd"?
EDIT: I opened the documentation and found https://api.rocket.rs/rocket/request/trait.FromSegments.html I don't fully understand if the checking they do on '..' fixes the attack vector here.
ValidDir/../../../../../../../etc/passwdAnd on Japanese and Korean windows? It uses the yen symbol as path separator. Depending on how the path is read or interpreted, filtering the yen may be necessary.
https://msdn.microsoft.com/en-us/library/dd374047(v=vs.85).a...
More on-topic: I just recently started a new web app using Rust on the backend. Though there is definitely a lot still missing, it's amazing how far the language and its ecosystem have come in the past year or so. I expect that within a couple years, Rust will be a viable alternative to Python and Ruby for backend web development.
EDIT: what is going on here with the downvotes? Care to explain?
I like Rust, but I don't see this happening. Python, Ruby and PHP/Node.js languages became popular (and thus useful) because their learning curve is not steep - which is not something one can say about Rust. I consider myself capable developer but I struggled with many concepts. It's true that I didn't use it for a real project though, it might have been easier if I had clear goal in my mind.
It's going to be glorious!
there is an official Chrome plugin that lets you meddle with a site's contrast these days if you're having trouble (like me) with this awful trend that's approaching white-on-white: https://chrome.google.com/webstore/detail/high-contrast/djcf...
It's way better than last summer though, rocket and the recently announced gotham framework look great, and I'm really excited to see how it evolves in the next few months.