Hacker News new | past | comments | ask | show | jobs | submit login
Rust for Web (medium.com/eugeniyoz)
136 points by EugeneOZ on Jan 31, 2016 | hide | past | favorite | 94 comments



I'm continually delighted to see so many programmers with backgrounds in dynamic languages feeling at home in Rust, given that that's my trajectory as well. :) I'm giving a three-hour Rust tutorial at OSCON this year and I'm honestly torn over whether I should tailor it towards people coming from dynamic langs or people coming from C/C++. I feel like I might end up just having to write two tutorials and take a survey as people come in to determine which to focus on.


The creators of Go assumed that their primary audience would be disgruntled C++ devs, and were surprised to find instead that it's mostly Ruby and Node.js people.

Despite all of the "systems language" talk, it would not shock me in the least to see the same thing happen with Rust (or whatever new language comes along next year).

I don't intend for this to be a slight, but the plain fact of the matter is that "dynamic" languages come in and out of fashion every 5 years or so. Those people are accustomed to that cycle. They get bored easily and PREFER that cycle. The senior ones are usually on their second or third language cycle (or beyond).

In contrast, C++ and Java are ENTRENCHED in their areas (systems programming and business applications, respectively). Whatever ultimately displaces them someday... it will have to be an order of magnitude better, and it would still take years.

By all means, market your favorite new language(s) to all possible demographics. Just understand that the "PHP/Python/Ruby/Node/Go/Elixir/Swift" crowd are going to be your primary adopters (and conversely, the first to grow bored and leave when the next thing comes along).


> Whatever ultimately displaces them someday... it will have to be an order of magnitude better, and it would still take years.

I actually think there's no room for any language to displace C++ in that way, ever.

The biggest reason that people give for bouncing off Rust is that the novel aspects of the language--lifetimes and borrowing--are too unfamiliar and/or hard to learn. Any language that is to be an "order of magnitude better" than C++ will necessarily have aspects that are unfamiliar and hard to learn. Long-time C++ users will bounce off that language for the same reasons they're bouncing off Rust.

No non-C++ language will ever appeal to C++ users who don't want to learn new concepts. C++ is very good at being C++, and for that reason it's immortal. Rather, new languages will continue to chip away at the uses of C++, making its use more and more marginal. This is a process that has been going on since the '90s--remember that in the '90s practically all software was written in C++, whereas in 2016 most new programmers aren't even learning it anymore. C++ has been declining not because it's being replaced but because its domains have become smaller and smaller. Rust is just a continuation of that trend: now there's a better option for security-critical software that can't be written in a GC language for performance and/or flexibility reasons (to name Rust's strongest domain), which has reduced the domain of C++ just as Java did 15 years ago for the server space and the rise of the iPhone App Store did in 2008 for the consumer app space. The continuation of this trend is what will gradually make C++ more and more niche going into the future.


This seems like the opposite of what I would expect. I'd think any good C or C++ programmer would reason about lifetimes in their programs on a regular basis. When I first came across Rust I was so happy to see a language codify the conventions around ownership and mutation that had previously been relegated to comments, naming patterns, and a rough consensus around what "const" meant.

I would expect the people bouncing off of borrowck to be those coming from GC'd languages where where and how long a value lives aren't things most programmers think about. Programmers coming to Rust from this environment have to learn about the fundamental concepts of lifetimes and in-memory representation/storage at the same time as they learn the limitations and reasoning model of borrowck. Without having seen the mistakes they're being prevented from making, I can imagine trying to fix borrow errors would feel more like a game of appease-the-adversarial-checker than a safety harness catching you when you slip up.

The only reason I see to keep writing C++ is the impedance gap between Rust and C++ making it less than pleasant to convert a large C++ codebase to Rust gradually. On top of name-mangling/linking concerns, Rust encourages composition and static method dispatch whereas it's rare to find a large C++ project not using inheritance and vtables extensively. You'd probably just end up going through the C ABI for all interop which is hard to argue would increase code quality compared to simply sticking to pure C++.


I'd hope so, but in practice I see a lot of C++ people bouncing off Rust's memory management for two reasons:

(1) The most common one: They think that they can write C++ safely with no memory management issues, and that people who don't are just bad programmers. This has been empirically refuted over and over again and I think there's no successful way to defend this idea, but it's a very appealing position on the face of it, so it's something I hear a lot.

(2) The less commonly expressed, but much more legitimate one: Memory management problems just aren't the biggest issues they deal with. I hear this from game developers from time to time (e.g. Jonathan Blow, though he's not by any means the only one). This is, in my mind, a totally legitimate position. Viewed in this light, C++'s memory management primitives are simple ways to eliminate the most obvious errors, which helps prevent some (not all) crashes and vulnerabilities from reaching production. Rust is entirely a move in the wrong direction for these projects, because it adds nontrivial cognitive overhead.

Interestingly, people rarely ever describe reason (2) in those words, probably because the idea that you would opt in to less safety makes people queasy. But that doesn't make sense to me; it's legitimate to want less safety if your app doesn't require it. (I do think, of course, that reason (2) is not legitimate if less safety makes your app vulnerable to e.g. remote code execution by network attackers and RCE would result in the leak of sensitive data or other game-over scenarios.)

I've actually been a proponent of solving (2) by adding easier ways to write unsafe code in Rust. But (2) is not a commonly-expressed position, so there's been little community interest in solving it (which I'm fine with).


My only gripe with Rust is that they should have taken a page out of Python's book in making a langugage syntax both stringent and beautiful. Not only is PEP-8 the greatest thing when dealing with a community project ever, but the syntax is designed around human readability in such a great way.

I think syntax like fn foo(bar: int) -> string {}; is a step backwards. More glyphs, more arcane nomenclature, and I just get a ting of change for the sake of change or "I want to be a functional hipster".

What is wrong with rettype name<templates>(argtype argname): ?

Why am I still writing all these damn semicolons and curly braces? I'm already intending the code and newlining every statement.

Why are there so many damn macros when C++ is realizing having language features rather than preprocessor macros is a huge usability gain?

I still think Rust is the best language out there today, but the failures in my view drive me insane that its not perfect. Its so close!

I guess I kind of just want a native compiled statically typed Python, though.


> My only gripe with Rust is that they should have taken a page out of Python's book in making a langugage syntax both stringent and beautiful.

I prefer Rust's syntax to whitespace-sensitive languages.

> I think syntax like fn foo(bar: int) -> string {}; is a step backwards. More glyphs, more arcane nomenclature, and I just get a ting of change for the sake of change or "I want to be a functional hipster".

No, Rust's type syntax is the way it is to avoid the lexer hack, which causes real problems in C++ (typename qualification, in particular).

> What is wrong with rettype name<templates>(argtype argname): ?

The lexer hack.

> Why are there so many damn macros when C++ is realizing having language features rather than preprocessor macros is a huge usability gain?

Rust macros are not preprocessor macros, not even close. Macros are language features.



What is the lexical hack in relation to the syntax I proposed?

I'm not arguing it, I'm just curious why Rust is using the prefix var pointer syntax when you are almost never supposed to use those in language.

I guess my point is more you could start from a clean unambiguous syntax (when is "rettype name<templates>(argtype argname):" ambiguous?) and rather than just verbatim copy C's glyphic syntax append vocabulary to the language to describe ill-used features.

One thing I have always considered a reasonable design choice going forward would be to start* with somethking akin to ptr(foo) rather than foo to denote dereferencing. In general I would like to see languages in this field start* with vocabulary and transition to glyphic grammar only on the most frequently used language features.

That would mean you could start with a language that does things like this:

   int foo(5)
   short bar(3)
   long res(foo.plus(bar))
   bar.equals(foo)
And then you could have just int, short, long etc classes that have operator overloads for =, +, etc and systemically avoid glyphic overload ambiguity because you are forced to handle that ambiguity in the operator descriptions.

With modern compilers (particularly LLVM) this could probably work very well, because the optimizers are so good even if you start defining your primitives in object notation and handing off really ugly bytecode that is treating everything as a non-dynamic object the backend llvm equivalent asembly generator will almost certainly be able to strip all the overhead out and return you back to optimized platform specific math operators onregister-sized words.

I'm not a language designer (obviously). I'm just a developer frustrated with how every language but Python is so much harder for my uncle to read (who is not a programmer) and thus makes me spend more brain energy deciphering it than if it were less verbose and more plaintext. And after writing a few of the Rust tutorials on the weekend a few months ago and giving a crack at writing a webrtc library for it I was really frustrated with how much extraneous glyphic grammar I had to learn and deal with in the language, since it seems so much worse than C++ from my perspective.


(Note that your comment is a bit difficult to read because Hacker News turns asterisks into italics.)

Putting the type name before the variable name can grossly complicate your tooling (the aforementioned lexer hack, https://en.m.wikipedia.org/wiki/The_lexer_hack ), which is part of the reason why tooling for C and C++ is so relatively rudimentary despite thirty years of time to address it.

There are also semantic difficulties that can arise from putting the type name before the variable name. For example, C++ recently added a return-type syntax that resembles what you see in Rust:

  auto multiply (int x, int y) -> int;  // this is valid C++
The reason why this syntax exists is because, well... it's a bit complicated to explain here, read http://www.cprogramming.com/c++11/c++11-auto-decltype-return... instead. :)

Furthermore, the `name: type` syntax is simplest solution when your language supports both patterns and type inference, as Rust does. IMO it also reads more nicely because when scanning code I care more about what a value's name is than its type (which may only be because Rust's type system is relatively strong, and I count on it to catch me if any types are out of place).

There's also the emerging historical trend: AFAICT, every language designed in the past ten years has put the type after the variable name. Rust, Go, Swift, TypeScript, Nim, Crystal, Pony... even Python 3 (https://www.python.org/dev/peps/pep-0484/). All the proposals that I've seen for optional types in Ruby and Javascript put the type after the name as well. And this syntax has roots in a much older language, ML, and is generally shared by ML's descendants (such as OCaml, and also possibly Rust).


For someone who uses Reddit and HN too much I sure can forget about markdown.

The function syntax C++ has seems more like a bandaid around the broken scoping rules inherited by C more than anything. If you were writing a replacement it seems like it would be one of your first considerations to make each statement scope limited to the scope of the declaration. I mean, that is what auto is effectively doing in C++ nowadays - you have to evaluate the whole statement to resolve what auto is supposed to be at compile time.

I would take consistency of using postfix typing as a sign there is legitimacy and simplicity in compiler design to do so, but I don't think the Python example is particularly fair, since it (and the C++ ->) are both extending a language that already had declaration syntax and thus the kind of glyphic overhead imposed by colons and arrows is less condemnable because they had to maintain backwards compatibility.

My gripe boils down to the difference between "August 5th" and "5th of August". The latter can convey the information in a more meaingful sense (you usually care about the day more than the month if you are using both) but it comes with a grammatical overhead "of" that, if were writing and reading a lot of dates of this form, would have a tangible impact on overall reading and writing efficiency. It would of course be minor - that is why its a gripe, and I still love Rust from what I've done with it - but it nags on you like it could have been done better.

And I also can understand the concept of name over type, but as someone who strongly favors static typing over dynamic after about five years of Python and three of C++, I think just conceptually "Canister Bob" is easier to parse than "Bob the canister". It is almost certainly just habit, but I justify my appreciation of the habit because it doesn't need to involve those damn conditional constructs (be they the, if, or a colon) that clutter up my reading and writing.


Rust uses the same static anylasis syntax then Python. This is valid Python `def f(x: int) -> str:`, semicolons and brackets are better syntax for languages that need high control and verboseness to accomplish there goals. Often functions declerations are going to take 2,3.. lines, you need this grammar control.

I am saying this has a maily, Python programmer. The syntax is fine..... once you get what it does, until then it was hair ripping.


Unfortunatelly the trade is full magpie developers.

> I've often thought that software developers were akin to Magpies, birds notorious for stealing shiny items to decorate their complex nests. Like Magpies, software developers are unusually smart and curious creatures, almost by definition. But we are too easily distracted by shiny new toys and playthings.

http://blog.codinghorror.com/the-magpie-developer/


Do you think the "bored" and "move on" story could be driven by more than just a "shiny" new language perhaps? Economics maybe?

Perhaps some developers in the "PHP/Python/Ruby/Node/Go/Elixir/Swift" crowd are trying to gain credibility in the OSS/Github world by making a not-yet-developed but vital library in the new language. If github is your resume, this could be a large win for their portfolio/resume.

Another take... For Python, there are dozens of projects that do the same manipulations, but are implemented slightly differently. People can, of course, contribute(patches, issues, etc.) to libraries they use the most... or they can make the 25th iteration. A new language presents a way to tickle the brain in a not-so-tedious manner by eliminating the technical debt in the other language's implementation while providing new paradigms to code around. I call that tickling the brain and it can be addicting.


This is only supposition, but I believe that the vast majority of idle programming discussion on the Internet is non-professional.

If you go to a site like StackOverflow, that is related to getting actual work done... the questions for Java, .NET, C++, and PHP absolutely dwarf those for Ruby, Python, and other fashionable dynamic languages (JavaScript being a notable exception). If you look at the number of GitHub repos by language, you find a similar pattern.

However, you go to sites like Hacker News and others that are more about idle discussion, and it's hard to find people who will even admit to working with non-sexy industry standard languages. If you didn't know better, you would get the impression that there are more Nim and Forth programmers in the world than PHP ones.

I believe that is because most such discussion comes either from students, who haven't started a career yet, or from professionals who enjoy discussing the "side" languages that they learn in their personal time (yet are not using professionally).

I don't mean this in a negative way. I myself wrote OBSESSIVELY about Scala for years, even though my actual day jobs had me writing vanilla Java. But online discussion does create a bit of a "reality distortion field", that confuses young people just starting out. The #haskell channel on FreeNode is the most popular programming channel in all of IRC... yet the entire world's population of non-academic professional Haskell developers could hold a conference at the airport Holiday Inn. Rust is a fascinating language to learn and dabble with, but almost none of us will ever have a job working with it professionally. Etc.

People get "bored" and "move on" from these languages not due to economics, but due to lack of economics. They are playing with them for fun, not because they're getting paid to do professional work with them. Hence the constant search for newer shiny things.


http://stackoverflow.com/tags

Doesn't support what you said. C++, for example, is smaller than Python.

Ruby has about a 1/4 of the questions of Java.

They're certainly not "absolutely dwarfed".

Python is overwhelmingly the language of choice for scientists afaik.


You are writing it as comment to article, where demonstrated commercial usage of Rust and explained benefits of this usage. I do it not because Rust is a new shiny thing, but because I LOVE key ideas of errors handling, results returning and memory safety (RAII is awesome thing). I use it not because "oh, I can finally play with it", but because "finally I see language where things are done right so I can write code effectively, customers will be served without failures and I will not spend so many time in debugging stage anymore" - time is the most valuable resource. In usage Rust is not so cute and shiny (in first month). It's only pragmatic decision. And I'm glad I was able to convince my employer.


Is that really a single crowd? It would seem like "PHP/Python/Ruby/Node" are separate from Swift (which is much more strict and is type/null-safe). Not sure where Go and Elixir would be sorted, but they feel less interchangeable than the first four.


Swift is not safe at all, it's written in documentation - you can easily do race conditions errors, fail on unwrapping null value, and compiler will not notice it. It's declared honestly in their docs.


As a Rust-curious C++ user, I've actually been frustrated about the lack of C++ to Rust material. It seems easier to find a "Rust for Rubyists" or "Rust from Golang" articles than a "Modern C++ to Rust" guide. In fact the two languages are almost exclusively discussed in a competitive context. This results in a lot of information that isn't really useful to those not emotionally invested in Rust's success.

It's as if folks coming from C++ are supposed to "just get it". It's supposed to be "obvious" why Rust is a better choice than C++, yet I don't see it. Maybe if I was writing some sort of mission-critical software I would look into Rust. But I use C++ for cross-platform mobile applications. I've had trouble finding a compelling reason to invest my precious free time time in learning Rust over furthering my C++14 knowledge.


The main things that Rust offers over C++ are memory safety and better concurrency via data race freedom. There are other nice things too, like better macros, strongly typed generics, and pattern matching, but those two are the main highlights.

That being said, some projects are legitimately OK with some memory management errors and/or races creeping into production, in exchange for a lower learning curve in that area. If this describes your project, and you're happy with C++, then keep using C++.

(Note that I don't believe that "I write modern C++ so I never make memory management errors" is virtually ever true. Every large C++ app I've ever seen has fallen to some memory error or another. I think "I don't care (enough) about the errors" is a legitimate reason to use C++, but "I don't have to care" isn't.)


> Every large C++ app I've ever seen has fallen to some memory error or another. I think "I don't care about the errors" is a legitimate reason to use C++, but "I don't have to care" isn't.

I very much agree. Although few people would say "I don't care about the errors", out loud, even if that sentiment is valid in certain contexts.

In that light, I have a question for you: What other concurrency features does Rust offer over C++ outside of data race freedom guarantees?


Does C++ have the ability to safely share stack data without copying? I don't think so, but I'm not an expert.

Rust has a few libraries that enable stack-scoped threads that are safe by virtue of ensuring that all threads created in the scope terminate before the data they reference is dropped (EDIT: and by preventing mutation of shared state without guarantees about atomic operations).

For example, I'm working on a project that uses crossbeam:

https://aturon.github.io/crossbeam-doc/crossbeam/

And there's a good blog post explaining some other things the library does:

https://aturon.github.io/blog/2015/08/27/epoch/


> Does C++ have the ability to safely share stack data without copying? I don't think so, but I'm not an expert.

It does in the same sense that it's safe to do anything in C++. Virtually nothing in C++ is safe, but you can pretty easily do it.


Make the stack data const or wrap it in a mutex. That is what you end up having to do internally in Rust anyway, or being more sophisticated and having page locks.


You can safely pass mutable pointers to stack data to scoped threads.


Which requires the language to perform some kind of synchronization around the data access or you will have races between threads.

Just because you don't have to be explicit about it doesn't mean you don't need to have some mechanism to handle it somewhere, its just automatic instead.


It does not, actually, if you're accessing disjointed parts of your data: http://aturon.github.io/crossbeam-doc/crossbeam/struct.Scope...


> In that light, I have a question for you: What other concurrency features does Rust offer over C++ outside of data race freedom guarantees?

I would say that the biggest win of Rust, once you get past the data race freedom, is that Rust's overall design puts the CSP model front and center like Erlang and Go do, while C++ is built on mutexes, locks, and futures. The way to get started with concurrent programming in Rust is thread::spawn, Sender, and Receiver, which will take you far. But C++ doesn't even have channels in the standard library; it encourages you to dive headfirst into shared memory, which makes simple concurrency needlessly difficult.

Rust doesn't restrict you from using shared memory when you need to (and verifies that it's safe when you do). But Rust's libraries and ecosystem encourage you to design your apps in shared-nothing fashion first, and only to introduce memory sharing when you need it for performance. That's a much friendlier way to deal with concurrency than mutexes, locks, and futures.


You can find a few pointers (heh) here: https://github.com/nrc/r4cppp

(I'm not sure how active that is worked on, though, I think I've seen basically the same version back in September.)


> As a Rust-curious C++ user, I've actually been frustrated about the lack of C++ to Rust material.

Which C++ subset should someone choose? All of it? What about the people who don't use exceptions? What about the people who don't use templates?

It's the same problem as writing a Perl to XXXX tutorial. The surface area of the source language is so huge that it's just not worth the undertaking.


> Which C++ subset should someone choose?

Easy. The subset outlined in Effective Modern C++

> What about the people who don't use exceptions?

Rust doesn't have exceptions.

> What about the people who don't use templates?

Rust doesn't have templates.


> Rust doesn't have exceptions.

So, C++ does. You asked about a tutorial for idiomatic Rust coming from C++, and then specified the full C++ set.

So, you have to give the Rust-y equivalents to exceptions, RAII, templates, reference types, virtual classes, etc.

Personally, I'd rather have a C to Rust equivalent--it's a lot easier. Especially a tutorial and primer on making Rust work in an embedded toolchain.

Being able to have a compiled, modern language actually work on embedded hardware would be excessively useful.


Not sure whether this is relevant for your talk, but I rarely see these introductory talks address a language that a lot of people write and which intended to provide several of the same guarantees that Rust does: Java. Java has statically typed "safety" (which is something most Rust talks pitch to dynamic lang devs), decent performance approaching C/C++ for long-running tasks, etc.

I think Rust does way better at most of Java's strong and weak points (aside from maybe ecosystem and current deployments), but it would be good at some point for Rust to have a good story to present to Java devs. Its type system is much better, its safety guarantees stronger, it has pretty good cache locality, its concurrency is approaching the ease of use of the JVM's and has always been safer, and its use of memory is far more reasonable and isn't prone to GC pause.


I'm in the same boat (web developer learning rust for fun), but I do fear a bit about losing the "soul" of rust if it caters too much to us. I still see rust first and foremost as a C++ replacement, for things like making my web browser more secure. I don't personally program in C++ but it's my hope that those who do will consider rust.

I've lately sort of been looking askance at how prevalent we dynamic language users are in the rust community, and I worry that we may skew the perception of how rust should evolve due to our potentially greater numbers on /r/rust, in the RFC process, on IRC, etc.


I'm continually delighted to see so many programmers with backgrounds in dynamic languages feeling at home in Rust,

It would be nice to get some statistics, because it would be quite unexpected. Still, it seems like some major Rust contributors are coming from the dynamic programming fold. Also, we shouldn't compare Go and Rust, but Go seems to have influx primarily from dynamic languages as well.

(I come from a C/C++/Java/Prolog/some Haskell background, dabbling with Rust now.)


I vote for dynamic. I left C many a year ago for dynamic languages, mostly to avoid C++. Now I'm back with Rust for a while now, thoroughly enjoying it.


I don't necessarily think that it's an either/or situation. I started out with dynamic languages, then did a mix of dynamic languages and C++ for a while (C++ engine with Scheme based scripting language), then went back to dynamic languages, and am now getting into Rust.

You are likely to have a mixed audience as well; even if not everyone has that mixed experience like I do, there will probably be a mix of people in the audience. So, it would probably be a good idea to have some examples and descriptions tailored towards those with a C++ background, and some towards those with dynamic language backgrounds.


Or you can do one with examples from both worlds for key areas of the language. It would seem that 80+% of each tutorial would be the same anyway. A slight detour into one side shouldn't irritate other part of audience so long as each example isn't too long and you explain it so they can mentally follow the discussion.


"<...> but I don’t understand why I need to write code for both cases, error and success, when I only need value from successful case and I can completely ignore Err or None results."

Have you considered `if let`? Seems like the exact thing you need here. https://doc.rust-lang.org/book/if-let.html


That page illustrates an important distinction between expression based languages and procedural ones. You couldn't do that in an expression, as it wouldn't type check without a value for the None case.

When I first saw Option it seems like a great way to force handling of the None case, either explicitly in place, or by passing on a mapped option as a return value (monadic composition make this a nice thing).

This resembles how exceptions are handled in most procedural languages, either you catch it and handle it, or you don't, and someone else gets to do it further up the call stack.

The example on that page looks like the equivalent of an empty catch block. It's almost certainly a bad idea that will bite you in the ass some day.


Maybe I'm misunderstanding you, but why wouldn't it work in an expression based language?

Isn't

  if let pat = expr1 { expr2 }
just syntactic sugar for

  match expr1 {
    pat => { expr2 }
    _ => { }
meaning the type of expr2 must be unit, and thusly if let is always of unit type?


Granted. But a unit expression is only useful for its side effect so I guess I put that in the gray area between paradigms, not really in the spirit of only evaluating expressions. Which brings us back the point of my comment: It's almost certainly a bad idea.


The unhandled case is explicitly mentioned in the latter though.


> You couldn't do that in an expression, as it wouldn't type check without a value for the None case.

Of course you could. If there is no `else` (which there can be, fwiw, just as the else case is optional in a regular if/else expression), the value of the None case is Unit: http://is.gd/Zdgc3D


This is not accurate. Rust is an expression based language, and `if let`s are expressions. If an `if` or `if let` returns (), it does not need an else.


> Rust is an expression based language

I initially considered writing that, but it depends on what the original poster means by "expression-based language" and they haven't made that clear: in Rust, a function is a sequence of statements. An assignment is a statement for instance, not an expression. To me an expression-based language is something like Haskell or Elm, not only do you have ubiquitous expressions (which Rust does have) there's really no such thing as a statement, a program (or function) simply is an expression (possibly with multiple components) this Rust:

    let a = 1;
    let b = 2;
    a + b
is 3 statements. The equivalent Elm or Haskell is a single expression:

    let
        a = 1
        b = 2
    in
        a + b


Everything at the function level that isn't `let` is an expression. And that `let` is not an expression is just an aspect of Rust that reduces boilerplate and rightward drift; the block containing those three statements in your example is still an expression which evaluates to the same thing as the Haskell below.

The original commenter seems to mean 'purely functional' rather than 'expression based'. OCaml uses `let in`, but still has side effects.


Perhaps a better world would be referentially transparent. Thought I'd avoid a debate about what constitute functional. But here we are...


The issue you're talking about is purity (not having side effects). Many expression based languages have side effects, such as Rust, OCaml, or Common Lisp.


Oops, it's exactly what I need. Thank you very much, I'll strike out this text in article.



The Result type also has a bunch of methods like `map` and `and_then` that you can use to write code against only the success case. Take a look at https://doc.rust-lang.org/std/result/enum.Result.html


I wish there were more articles like this as I'm genuinely curious of people's experiences using Rust as a backend to their API's or websites. The only example I had known of before this was Rust's own crates.io [1].

[1] https://crates.io


I've been considering Rust (or Swift) for webapp backend, but these cons are spot on: Named parameters are missing, and one can't build natural looking JSON validation if one can't nest them nicely.

Swift looks promising though, if a bit in flux.

I've been ramming my head against Scala lately, and while it's nice at times I would like to have compiled language.


Could you show an example of what you mean by "natural looking JSON validation"? I am not sure I have seen what you are referring to.


I think succint is the word I want. Nested validation logic that looks like the object you are validating.

Unfortunately Play docs are not succint, but you may get the idea from here: https://www.playframework.com/documentation/2.3.x/ScalaJsonC...

I tried to implement similar (typesafe) myself using TypeScript: https://github.com/Ciantic/model-validation there are certain problems I hit with TypeScript, and also I don't want my backend to be JavaScript so I've stopped working on it.


Did you check out D (http://dlang.org) yet?


Not seriously, maybe I should. I know it has some crazy good macro support if I'm correct, this should allow some nice libraries.

Though my first problem with any language is: Does it have type safe SQL builder? Scala has Slick and Quill, and lesser extent JOOQ. Rust has Diesel (not sure how good).

It's pointless to start stringly type the database, when pretty much every backend call needs to access it.


There's Clojure too, if you are into that. Check this out http://codahale.com/a-small-nice-thing/


Good write-up and experience summary. Nice to see that people from dynamic language backgrounds are able to pick it up.


I tried Rust with Iron as the article mentions but JSON parsing and writing wacky match expressions turned me off to Rust early on.


Out of curiosity, how long ago was that? I've found that over the last 2-3 months (I started tinkering around 1.4), the ecosystem has already become quite a bit better.


About 6 months ago I think. It was pre-1.0 and yes some things weren't fully mature. Maybe I'll give it a whirl again soon.

I was initially excited about Rust because it appeared to achieve system programming language performance and stability with application programming language expressiveness.

The nature of static typed languages doesn't allow for things like first class lazy JSON serde. Java, C, C++, C# all have the same issue.

In the grand scheme of things it's not a huge deal if performance is #1 but I value my enjoyment level while coding.


Is it just me, or is using Rust for web apps kinda odd?


I don't really see why it would be odd, other than the ecosystem not having quite caught up yet with some other languages. It's an expressive, high level language, which makes being explicit about error handling very easy, the type system makes it a lot easier to guarantee at compile time that a number of errors possible in dynamic languages will never happen, and it's quite efficient.

The efficiency and explicit memory ownership in Rust makes it a lot easier to avoid some of the scalability problems you run into in dynamic languages. The amount of material you can find online on people discussing hunting down memory leaks in Rails, or discussing how they just scale up by throwing gobs of RAM and extra servers at the problem or restarting their app every day or two, is all stuff that is much easier to avoid in a language like Rust. It is possible to leak memory in Rust, but due to how explicit you are about how memory is owned, it's less likely and more likely to be easier to track down if you do.

It is a bit more conceptual overhead to learn Rust than many dynamic languages, but I think that overhead is well spent as it can pay off in performance, stability, and maintainability later on.


It's unfortunate that the ecosystem is such a strong point for so many people.

Sure I might need 250mb of RAM for a Rails app but there's 10+ years of real life thought and care put into the framework and about the same in external gems/blog posts/etc..

I'm ok with spending $5/month on an instance to serve a Rails app for 95% of use cases and I'm a load balancer away from multiplying my throughput if I need to scale out.

If I could snap my fingers and have the same ecosystem in Rust I would switch instantly but it's not the world we live in.

I'm not sure if even 5 years will be enough because Go 1.0 has been out almost 4 years and it's still not even in the same galaxy as Rails in terms of ecosystem.


Of course, now that increasingly more work is being done on the client side, or by communicating with microservices, Rust makes more sense for a pure API backend. There's a lot less ecosystem needed there; mostly just bindings to whatever database you need to talk to, possibly some other stuff.

So if you're just going to be exposing a RESTful API backend for a JavaScript based frontend, or even for a Rails app frontend to talk to, Rust makes a lot more sense.

Also, the only way an ecosystem gets bootstrapped up is by people scratching their own itches. By starting to write web services in Rust now, and implementing those things that aren't yet implemented, you can help to bootstrap it up. Of course, that only works if you have the extra time to spare to do so, but for those things that only need one or two extra things that don't yet exist, it may pay off due to the lower chances of having to debug runtime errors, less time and complexity spent trying to make it scale out, etc.


I would still prefer to use ActiveRecord and a whole lot of other pieces of Rails for an app that's purely an API backend.

Ex: http://edgeguides.rubyonrails.org/api_app.html

On the Python side of things, I'd use tools like SQLAlchemy and a few other packages.

Every web application I've built can still be efficiently modeled with a relational database. An ORM that lets me model things quickly and allows me to avoid shooting myself in the foot by easily monitoring raw queries is going to win in my book when it comes to picking a tech stack to work with.

The major ecosystem problem is that no one can just wake up and be like... I'm going to spend the next year making a Rust version of Rails. These features and ideas need to come from real life use cases, that's really 99% of Rails' success.

It can be done in any language of course, but you're 10 years behind the curve.


The current maintainer of ActiveRecord is writing an ORM in Rust: diesel. It's not a port, but still, you might be interested in checking it out.


Definitely interested on keeping tabs on it. Thanks for the heads up.

In a perfect world, it wouldn't be a port, but something that meshes really well with real world use cases while taking advantage of what Rust has to offer.

I don't mind change (I embrace it), but it needs to be for a REALLY good reason.


Why should it be odd?

It should be perfectly natural to use compiled languages to serve web requests.

Rust is a very expressive language, and with its focus on safety a very good candidate for distributed systems.

I for one, given my experience using Tcl for an application server, find odd to use scripting languages for web.


I don't think there's anything inherently wrong with Rust the language in this context, but an API server doesn't really let Rust play to its relative strengths. Response times are more likely to be DB or I/O bound than anything else, so you'reprobably not improving response time much compared to Ruby or Python (of course, that's not always true though). Also, the ecosystem seems immature enough still that you'd inevitably have to reinvent at least a few wheels.

That said, I think it's great to do things like this. Someone has to pave the way. And, if a good API/web ecosystem builds up in Rust there's no reason _not_ to use it.

At the moment though, I think a more _natural_ fit for Rust would be for something a little lower level than an API server.


Static linking i.e. having one single binary to drop onto a server, and most likely lower memory consumption(more concurrent users served by a single box). These two could probably be added to a list of reasons.


That is a huge reason I'm interested in Rust for backend web programming. I love the ease of use NPM provides when it comes to installing dependencies. Installing libraries is definitely a pain point in something like a C++ project. Cargo is like NPM but the end result is a native executable.

And if you have a lot of users, Rust can help lower your monthly bill by requiring fewer resources. The safer memory guarantees from the compiler is a great bonus on top of all that.


No more odd than using Java. There's the huge difference in libraries and tooling but I don't think any inherent feature of Rust makes it less suitable for web backends than Java. I wouldn't pitch this project at work today but somebody has to go first.

Rust makes the most sense to me in a GraphQL/Falcor type backend. The lower number of endpoints combined with Rust's perf and focus on correctness seem like a better fit than templating out web pages.


The main downside to using Rust for web apps - at least in my opinion: is having to learn and use a type system which includes affine types: lifetimes, borrowing etc. But if you've already put in the effort to get to grips with this part of the language, that's not as big a drawback. Then you get all the other positives of the language, like its strong type system, fast speed, sensible package manager, lack of GC pauses etc.


I'm in full agreement with this. The learning curve (and the compilation speed I guess--but that's improving quickly) is the main drawback to writing Web apps in Rust. If you've already learned it, though, then it's basically just down to the typical static vs. dynamic typing tradeoff, with Rust just being like any other statically typed language.


Rust's errors handling and memory safety are important differences too.


> Then you get all the other positives of the language, like [...] lack of GC pauses etc.

One thing I've been curious about: is it the case that there are no pauses, or that you know when they happen?

I know one of the concerns with GC is it can just kind of happen whenever and pause whatever else you've got going on. It also has to do extra work to track down what sort of memory is reachable or not.

Now is rust's RAII-style approach actually faster or do you just have more control over it? It doesn't have to trace reachable memory from the roots like a GC, but it still does have to do some work, right?


It's both faster and you have more control over it; the two are linked in this case. This system lets the compiler do the hard work to figure out when it's ok to deallocate some piece of memory, unlike a GC, which figures it out at runtime. One you've determined that some memory can be deallocated, the actual process is very quick, usually just updating a list of free blocks in the memory allocator and maybe some statistics.

Rust does also support reference counting when you want it, which can bring its own set of performance issues in certain circumstances. Think more about general slowness due to constantly incrementing and decrementing references in an atomic fashion when you pass RC-ed data between functions, rather than the pauses seen with garbage collection. But how bad that is depends greatly on how and where you're using reference counted variables, and the addition of the lifetime/borrow system makes it easier to avoid some of the more egregious cases here.

Additionally, some people are doing work on GCs that work with Rust. The two links below have some good descriptions of the progress and challenges related to that.

http://blog.pnkfx.org/blog/2015/10/27/gc-and-rust-part-0-how... http://manishearth.github.io/blog/2015/09/01/designing-a-gc-...


It's not just you, it is kind of odd. It is -doable-, but outside of having some really specific requirements wouldn't be my go to. The overhead for web stuff in other languages is just so much lower.


It wouldn't be my first choice (or second, or third), but I would say that Rust could be well-suited for APIs. So, if your web app is a single page app that is simply communicating with an API, it starts to make a little more sense, if your primary motivation is doing something "new" or challenging for the sake of it.

That being said, I don't think that should be anybody's primary motivation for a production application. :)


I didn't get the impression from the article that they just wanted to do something new, they wanted a language/compiler that provided a lot of guarantees before they ever started debugging. That seems like a perfectly reasonable motivation for using a new technology in production.


Adding the cognitive overhead of memory management for a web app is rarely going to be worth it. Unfortunately there are there a certain class of devs who are always going to chase the latest shiny thing (and they are predominately web developers, for some reason).


The more i code over the full stack, the more i realize many technics on the backend are similar to the ones you find on Single Page Application or native apps.

The flow is this : an event comes in, you need to answer to it very quickly by doing synchronous tasks, and sometimes you also need to trigger asynchronous tasks in parallel, wait for their result, and assemble it before sending the result ( / upadte the gui).

Basically, synchronous algorithls are solved by any language. The core issue that remains both on the client and the server is handling shared state and parallelism.


You never know when something is going to really click.

One thing that's really cool about rust is that it can choose a conversion function based on the type of thing you are assigning to.

In other words, in "let x = foo()", foo() can do a different thing depending on the type of x.

I found that out working on a simple rust program interacting with postgresql.

Not saying that one feature makes all the difference, but you find nice advantages like that all around. Taken together, they might lead you to a more creative overall solution, and it might be a game changer.


At the moment it is because the ecosystem isn't quite there, yet. Fundamentally though there are quite a few advantages when it comes to performance and safety.


My feeling too.

Don't know how safety claim of Rust ensures on server side, here seems more on the application layer.

However, if just writing some apis, then any language will do, I don't see Rust is particular odd in that sense, if you are willing to forget about ecosystem, while at the same time I don't believe it has a edge over other language.


This is for the backend, not the frontend, so it's perfectly fine.


Using Go for web servers is Ok (ask Google), Rust is in (almost) same field (just much better), so there are not so many differences.


I was wondering how you would test web apps written in rust. In particular the api you're building. Right now as my first rust project I'm trying to implement an HTTP protocol with hyper but I'm not really sure how to test it properly next to just creating a client connection and throwing requests at it. Btw my final idea is to have it as a library that gives you a handler to use with what ever rust framework you choose to use. Not really sure how to do that though, I'm using a lot of hyper stuff.


http://arewewebyet.com/ - (You can use Rust for web stuff, but the ecosystem isn’t mature yet.)


This website is quite out of date. It hasn't been updated in 9 months.

Related: https://github.com/teepee/arewewebyet/issues/24




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

Search: