I'm pretty sure he did know what you meant, and offered a serious response. I think he's suggesting that perhaps the aesthetics of the ellipsis is what prevented it from being selected.
Haskell doesn't have this feature though. I mean it does, but you can just leave out the ones you don't want matched, you don't have to put in any dots.
`..` and `...` both exist in the language, `..` is exclusive range and `...` is inclusive range. `..` is only in expressions right now, whereas `...` is only in patterns. Eventually, both will be available everywhere, possibly. At very least, `..` in patterns is getting added soon.
Since this is a pattern thing, probably `..` was chosen when `...` was the only range available in patterns, to distinguish this from that range pattern more. However, `..` will now be available in patterns, so its just historical.
(This is a longstanding feature, what's changed is just making it apply to more patterns.)
I've seen the "..." used for matching a range of values, whereas ".." is used in other places where we disregard a value while patter matching.
I'm sure someone from the rust team can give a better answer, but to me this change looks like it was just bringing the pattern matching for structs to be consistent with other uses of ".."
This is such a win for pattern matching! I tried using this exact syntax last month and I was sad to see it didn't exist. It feels so natural to see it now.
Rust is such an awesome language. Every design decision feels so right. Go, Rust, go!
That is the plan, yes. It's not in the beta yet, but will be backported.
(For those of you who don't pay super close attention to Rust development, that means libraries like Serde and Diesel will be as convenient to use on stable as they are on nightly, today.)
Is this the first time a feature stabilization has been made to a version that has already moved into the beta phase? My understanding was that beta was pretty much frozen except for bug fixes.
See the section saying "The initial implementation of librustc_macro is proposed to be incredibly bare bones:" it really is very, very small. So it landed, and while there was some questions that came up, people migrated to it, and it works well.
However, two things happened: one, the Mozilla all-hands in Hawaii, which shook things up, but secondly, that meant a lot of people, including one of the reviewers, took PTO around that time, to actually see some of the islands. That includes someone who was on the reviewers list. So in general, "oh hey this is waiting on one person who forgot to check a box but isn't reachable now" is awkward.
Luckily, in this case, we know that it was just forgetting to check the box; Felix did not have any objections that we were aware of. So we decided to sign off for him, and put it into FCP. This happened so that FCP technically passed the deadline for 1.15, but given how important it is to ship, we're planning on nominating it for a backport, and don't anticipate complaints.
So: tiny feature, code wise. Big win for being stable. Procedural mishap involving awkward scheduling. All these things played into it. Make sense?
Depending on the cargo version, wasm might not actually work in 1.14 (couldn't check which version it uses yet). It's definitely broken in the next release, which is quite unfortunate :/
Historically, that part of a target triple is used to indicate a specific "vendor," so you have "mips-unknown-linux-gnu" vs "mips-debian-linux-gnu", where the former is for all linuxes, but the latter is specific to Debian.
So a target triple is really a target quad (makes perfect sense). Tbh, leaving it out would or using the word "generic" would be far better than unknown.
Harder to parse is one thing, but if it could match the output of config.guess, and/or allow to skip the "unknown" part so that the triples match what's used for GCC prefixes and clang's --target, that would be way nicer.
Maybe this could be documented somewhere on the rustup doc so new users like me aren't puzzled by this strange “unknown” everywhere. Or maybe it is, and I just didn't find it because I was too lazy to look explicitly for it …
Write your Rust app. Compile to a binary on the backend, wasm on the frontend, using asyncio to communicate transparently between the two. Update the DOM directly from wasm, with 60fps rendering from Servo's WebRender.
Totally typesafe and lightening fast.
And it will never happen (ok, maybe "never" is too strong - it will happen 10-15 years from now, at best and even then it will be unstable/unreliable/slow/half baked on some platforms, because reasons). The best we've got is the piece meal approach of HTML/Javascript/CSS.
And before you blame those standards, blame the Unix vendors^W^W, pardon me, the platform owners (Microsoft, Apple, Google).
Why won't it happen? If wasm can talk to the DOM, then you'll still be using HTML and CSS, and wasm in place of JS. There's no reason this couldn't be done already by just compiling to JS, and plenty of languages already do that.
You could also render everything to a canvas to avoid HTML and CSS, but at that point there are a lot of things to re-implement, especially around accessibility.
Well, first of all wasm needs to be implemented in all major browsers on all major platforms for it to be widely adopted. Since the major browser vendors are backing it, that should happen quite soon.
But that's just the initial implementation. It needs to be implemented fully, debugged, optimized and then it needs to trickle down to user devices, including those sold 3-4-5 years ago and still in use.
And then, in the second stage, wasm needs to get DOM access (as far as I know v1 won't have it). See stage 1, all over again.
I'd say that the mass adoption cycle for 1 stage is roughly 5 years (where 80%+ of the browsers out there support a major feature well). So 2 stages x 5 years = 10 years.
Given the history of the web and what I know of the people/companies behind wasm, it seems very likely that there'll be a graceful degradation/shim in the form of a wasm interpreter written in JS/asm.JS (or even a JIT from wasm to one of them), so there'll be no need to wait for all browsers to have implemented it, it just won't live up to its performance on all platforms.
I think you are being too pessimistic about the speed of mass adoption.
On the desktop: Firefox, Chrome and Edge auto-update.
On mobile: Android 4.4+ (over 80% and rising fast) auto-updates its webview component. iOS receives yearly updates that are applied by a very large majority - though Apple's browser development does seem to have stagnated a bit.
So it seems to me that non-updating browsers are going extinct, and that we won't be dealing with another IE6 anytime soon. We're living in the future! :-)
The age of the evergreen-browsers is dawning. Although it will be years before the last corporate holdouts let go of their pinned IE9/IE10/IE11 browsers.
Why is 80% the magic number? 5% would reach more than 100 million people. That's enough to keep a team busy and a product growing while the competition sits on its butt waiting for the next 75%.
I hate JS but replacing it with Rust for front end is a bad idea, Rust is a low level systems programming language, it's very suboptimal for high level front end code from productivity standpoint and it adds no value because it's advantages (mem safety with 0 cost abstractions) don't really matter in frontend (JS is super bad at being optimizable but it's still more than sufficiently fast).
Rust is indeed known for memory safety and zero cost abstractions. But there is another side to Rust which is even more interesting - a type system that is almost as powerful as those of functional languages like OCaml and Haskell, but wrapped in approachable imperative syntax.
With such a type system, it is possible to encode the invariants of your application in types (using generics and algebraic data types). Then you can get very close to "if it compiles, it works".
JS, in particular, is the opposite. I am never really convinced that any JS I have written is "correct". It works, until one day it doesn't. This is such a problem that there have been multiple attempts to retrofit type-systems on top of it.
Rust needn't be the only language that brings strong typing to the frontend (Elm has been around for years now). But I think the prospect of speed and correctness both front and back is pretty exciting.
>But there is another side to Rust which is even more interesting - a type system that is almost as powerful as those of functional languages like OCaml and Haskell, but wrapped in approachable imperative syntax.
That type system is pretty verbose because it's aimed at manual memory management which you don't really care about in front end, and the compile times are huge compared to say TypeScript or something along those lines so yeah - I agree static typing is nice - but saying you should use Rust for front-end because it has static typing is like saying every gardener should have an excavator because digging holes with hands sucks - shovels exist.
I don't necessarily disagree with you, but when wasm is fully established I expect to see (another) step change in the complexity of the web. Fully-featured applications, 3D, VR, AR etc. We are on the brink of it already. And beyond a certain complexity (a relatively small amount of complexity, I would argue), a decent type system is essential.
Rust just happens to be well positioned to take advantage of all this.
It's a design trade off. I don't get why people are so pissy about it - Rust makes design choices that are suited for low level systems programming language - but it has a lot of noise and complicated things from high level language stand point, and compile times + debugging + lack of run time tweak-ability make it very unproductive for front end compared to say TS/JS
But on the backend, not on the client, I presume? If you've really been deploying Rust over the wire via asm.js, then some commendations are in order for your persistence. :P
Yes, of course. But in parallel I write code in TypeScript (frontend) and after few months performance is equivalent in both languages. Only difference - no runtime errors in Rust.
Are you joking ? You can have hot module replacement in TypeScript meaning you don't even have to refresh the page to get new code in browser - and then you can fire up the REPL and prototype stuff - Rust has to go trough rebuild+redeploy on every iteration - you're saying that's the same speed ?
No. I don't use hot module replacement and I don't like this idea. And I don't prototype things often - maybe once or 2 per year - my contracts are usually long enough. It's all personal, as you see.
I'm saying that to implement feature in Rust takes same time as in Typescript or PHP (as PHP is a server side language also and comparison is more illustrative).
0 cost abstractions do matter a bit. In general abstractions let you do high level programming in lower level languages.
The type system matters a lot.
I used to do a lot of scripting. One thing I really missed was having a good static type system. These days I miss ADT enums in all languages.
Scripting is already moving in the direction of being more type safe (typescript, python type annotations), which is awesome, but I'd love to use something like Rust in that sphere.
I love JS (pretty unpopular opinion here on HN) and I love Rust also and I'm not convinced using Rust on front-end tasks would have any benefits. Yet, I strongly disagree with you on this point :
> Rust is a low level systems programming language, it's very suboptimal for high level front end code from productivity standpoint
Rust's type system is wonderful, and it's a real productivity boost. Fortunately people at Facebook developed an equivalent for JavaScript [1] because living without it would be really hard for me now.
Furthermore, Rust offers a lot of syntactic sugar that makes it feel like a really high level language (compared to C, Go or even JavaScript pre-ES6 for instance).
>it's advantages (mem safety with 0 cost abstractions) don't really matter in frontend
It's indeed one of Rust selling point (especially for people coming from a C background) but it's not the only one. My favorite being the data-race free parallelism. I don't know the current status of multi threading in wasm, but being able to take advantage of all the cores of mobile devices could really help front-end frameworks.
[1]: http://flowtype.org, it's not inspired by Rust but inspired by OCaml, which also inspired Rust.
>Rust's type system is wonderful, and it's a real productivity boost.
Rust type system is verbose compared to higher level languages and it lacks a lot of the things that make higher level languages productive. It just focuses on low level code - which is good - but you wouldn't use it in place of C#, you would use it instead of C++, and you don't want to write GUI code in C++ either (even Qt uses JS for the frontend)
>My favorite being the data-race free parallelism.
Also mostly irrelevant in front end since you're dealing with single threaded event loops and doing parallel work that talks to UI thread is easy. Stuff that needs to do work in parallel can be written in Rust and talk to front end via FFI or RPC.
If you don't like it, you don't have to use it. The beauty of WebAssembly is that it can be targeted by so many other things. Finally, we can let JS sink or swim on its own, without being propped by an artificial monopoly on the web frontend scripting...
There doesn't seem to be anything unstable about it, even now. I've compiled tons of Rust code to asm.js over the last few months and there's not a single thing that didn't work. Modifying the DOM also works fairly well (you have to write wrappers though). And the code is 10x to 40x faster than the equivalent JS code. And you can run the exact same code natively on tons of platforms too. So it's already quite amazing.
I'm not 100% sure if I tried it in any of my apps, but I think I did, and can't recall it not working. I'll try again soon and will tell you if it works.
Please fill me in too, possibly filling an issue on the regex repo if there's anything I can do to help. (This is the first I'm hearing of the problem.)
There are benefits even if you aren't sharing the entire back-end. I develop an internal Mojolicious webapp, and there's been quite a few times where I would have loved to just have one or two of the backend libraries I've written available to JS, so I wouldn't have to write it again in JS or pass it to the server. Just knowing that I could write it once and have it be the same in both places, even if I changed it later, would be a real boon.
Exactly. Everytime I write a feature, I have to decide whether it's a backend feature or a frontend feature. Sometimes I get it wrong. I'd like to not lock myself into my choice.
Having attempted this "isomorphism" across Scala and ScalaJS, it is not quite that easy. That goes for all setups (node -> JS, Java -> GWT, etc) that I have tried. There are a lot of what some might call "impedance mismatches" between the two targets especially when it comes to communication and DOM work. IMO only frameworks/middleware built to bridge the gap will make it seamless.
In my experience Scala(.js) works way better than "(node -> JS, Java -> GWT, etc)".
There is a large gap between those and the way Scala _just works_ across platforms.
The huge difference is that you can depend on libraries and have them "just work" regardless of whether they are implemented identical on each platform, or need specific variations to implement the expected features.
There are countless libraries implemented with synchronous I/O, there are countless (good) popular libraries implemented with non-Tokio-based concurrency primitives.
Let me just say it: I really, really like Rust.
But I cannot feasibly use it for network/server-related tasks until a single solution is blessed by the Rust team.
The "let's let the community handle standardizing async IO and concurrency" approach has _never_ worked in the somewhat brief history of programming languages.
A blessed solution though? - Erlang, Golang, Node/JS* All work flawlessly.
I would use Rust full-time for every server-related task if I could, but I've been observing for 3 years and unfortunately haven't seen much development after the abandonment of builtin green threading.
*- codestyles sometimes incompatible, but there was _never_ a litany of sync libraries or otherwise fundamentally incompatible systems.
> just as everyone "rallies" around EventMachine in Ruby.
You can't really compare things this way. Very few people even use EventMachine, as it has significant issues.
You can't just show that rotor and tokio are two different libraries; you've claimed that there's significant ecosystem fragementation. That's a very different claim. The same goes for the other three sets of links below: that you can find a bunch of GitHub repositories does not mean that there's actual fragmentation. Writing a memcached or Redis client is a good way to learn a language, even: I've known two people who independently did so for memcached + Rust, tossed them up on github, and that's it. (one of those is one of the links you've provided above, even.)
> Oh wow, a great redis library - objectively the most popular. Completely incompatible with all of the above AIO implementations.
Because it's synchronous. Once tokio has an actual 0.1 release of the full stack, which is to happen any day now, you'll see more consolidation.
> until a single solution is blessed by the Rust team.
Two of three of tokio's core team members are Rust core team members. We had a full talk on it at RustConf, and it was mentioned in the keynote. Mozilla has sponsored development of it in places.
The "Rust team" isn't picking winners, but they do happen to be contributing to and creating the leading solutions. There is a lot of energy around futures and tokio, very early on in the story of Rust. Sure, Rust has already been around for a while, but 1.0 was only last year.
If you like Rust, and you want to use it for network and server related tasks, get involved. Write the redis, memcache, HTTP clients of your dreams. Rally the people who've solved those problems in Rust (and elsewhere) in the past.
Please try to state your concerns (or better yet, ask questions) in a more thoughtful manner.
It would be better if they would, though, is what some of us are thinking.
Between "totally chaotic third-party libs landscape" and "official lib designed with the language and part of the standard library", picking winners is a great middle ground.
> Twisted, Gevent, Celluloid, EventMachine all did too.
The problem is, they've never reached critical mass, and their respective languages refused to bless them as "official."
At least in the case of Twisted, it probably didn't help that for a long time it was GPL licensed with all community contributions requiring copyright assignment to the lead developer.
Rust is a magnet for creative, intelligent people. There are bound to be lots of implementations for things like low-level I/O because lots of people want to explore the relationship between the OS, the application and the hardware. That is different than fragmentation in the sense you're implying.
The Rust community is pretty unified, esp. as its communication channels are well defined. For asyncio, I am pretty sure that Tokio will be the tool for most applications.
Tokio was only released along with futures like 3 months ago? It takes time to rebuild software on top of that. It definitely took me time to port from directly using MIO to using tokio.
After evaluating others options, I do believe tokio will be the default for most people.
Tokio is already eating the ecosystem, voluntarily. The authors of the only other two competitors, Rotor and GJ, told me at Rust Belt Rust that they're planning on deprecating their projects and throwing in with Tokio (perhaps largely thanks to the fact that the Rust/Mio devs asked them both for their input during the design of Tokio).
>There are bound to be lots of implementations for things like low-level I/O because lots of people want to explore the relationship between the OS, the application and the hardware.
Why wouldn't it be? Let people experiment. As long as there's a standard, go-to library for applications that need to "just-work", I don't see any reason not to explore new ideas and find potentially better solutions for the future.
I agree it's an issue. Java and C# also suffer from it. In Java probably each webserver implements it's own network framework on top of NIO and in the end you have dozens of incompatible event loops runing.
However it's not an easy issue to solve for a general purpose language, unless you want to tie all those IO semantics (and probably a big runtime environment) directly to the language. C++ and Rust don't want to do that, since they want you to be able to use the language even on bare metal with zero runtime.
What you can do as a library developer for these languages is to try to make them as integretable as possible into all kinds of surrounding environments. I normally would try to make my library usable for blocking calls as well as in a nonblocking way within an external eventloop. You can do that by spawning your own thread/eventloop, handle all the library logic in there and provide thread-safe external APIs that communicate with our eventloop.
Framework development (in the sense of Netty/Tokio/etc) is harder. If often won't be possible to develop code that runs in multiple frameworks.
> experimental support for WebAssembly as a target, wasm32-unknown-emscripten [...] check out Tim’s example of the classic TodoMVC project.
On one hand this is really cool and potential for client-side Rust. On the other hand:
let id = node.parent().unwrap().parent().unwrap().data_get("id").unwrap().parse::<usize>().unwrap();
Eh, no thanks. :) If I could get a macro or shorthand for that, I'd welcome all the other benefits of a large scale client-side platform with strong typing.
let id = node.parent()?
.parent()?
.data_get("id")?
.parse::<usize>()
.ok()?;
I'd also expect that someone will write higher level libraries so that you aren't doing raw DOM manipulation. A rust vdom wasm library would probably be blazing fast.
> A rust vdom wasm library would probably be blazing fast.
Most of the cost of vdom is the resulting DOM ops and reflow/restyle the browser needs to do. It may be faster than the fastest today, but you're unlikely to see any kind of performance leap or even anything noticeable.
Small note, we don't _technically have to stabilize Carrier to land this, just implement it for Option. (yay standard library types) However, ? for Option is a bit controversial, so we'll see...
Yes, that's correct. If we make ? go to more than just result, you could implement it for any type, and it's not totally clear that changing it from "error handling" to "general control flow" is a good idea.
Many are in favor of doing it, though. I'm personally against it.
Whether it's ? or something else, having a very concise form of syntactic sugar to unwrap option types is desirable. Most languages that don't have it, eventually acquire it due to demand.
The "?" operator looks like a more specialized, error/success-specific version of monads. Has there been any discussion about generalizing everything into monad-style chaining operators?
I see that there is some discussion here [1], including a suggestion to add a Haskell-style "do" block. But that's just one guy's blog post.
Yes, that was endlessly discussed as part of all of this. The TL;DR is: it's not simple. ? is very straightforward and helps people out a lot today. So if and when (and it is a big if) Rust ever gets do notation, this might be a little redundant, but blocking one of people's largest pain points today is worth the (possible) little bit of redundancy.
Thanks, that makes perfect sense. I haven't followed the internal discussion at all.
It sounds like there are some that would like to move Rust in the direction of becoming more Haskell/ML-like (which is to say more purely functional) rather than the current balance between imperative and functional? Is there any internal tension in that regard?
It's not even a philosophical difference, really, there are technical objections that would have to be addressed somehow before it would even be possible, let alone figure out if it's a feature that's desired. These involve things like "it's still unclear if HKT is going to end up in Rust or not, and how", which is a pre-requirement, as just one example.
I believe one of the biggest obstacles to a general monad system in Rust is that the type system can't actually handle it at the moment - it requires higher-kinded types, which may or may not ever actually be added to the language.
There's another problem too: a monad trait would unify types behind a monadic interface, but many things that in Haskell are types, are traits in Rust. This is because Rust requires a single type to have uniform memory representation and to be statically dispatchable (save for trait objects). So in Rust, there is not just an "iterator type", but multiple types that have the Iterator trait. The same goes for Future trait.
This leads to a situation where, if there were to be a monad trait, that trait should abstract over not only types, but another traits generically.
Not to speak about some other hurdles, like lifetimes. The design space is inherently more convoluted than in languages with boxed, possibly dynamically dispatched types. It may be possible, but it's not easy, and we can't copy the monads straightforwardly from Haskell or Scala.
The semantics of ? are different from monadic bind and fit better to Rust's language context of strictness, imperativeness, and mutability than Monad (which is a problematic type class in Rust for some separate reasons).
> A rust vdom wasm library would probably be blazing fast.
Even regardless of performance, it would be quite nice to have! I've been meaning[1] to build a small prototype to do something clever[2] with it, but didn't have the time yet. Feel free to steal these ideas :)
It's boilerplate in a certain sense. Those are all points where what you've written might not work. Rust makes you deal with possible problems _somehow_. Specifically, this is a replacement for null. If you legitimately don't care, then it can feel boilerplate-y, but it also lets you start by not having to care, and then searching for unwrap and replacing it with better handling.
In other words, it's boilerplate here because this particular operation has many possible failure modes, and Rust is pointing those out to you.
It's repetitive in this particular instance, but doesn't have to be in general.
c) a bad practice since it will make your program crash is a node has no parent.
if the node always having a parent is a invariant of your application, you should use `expect` with a clear error message when the invariant is broken.
if your node can have no parents then you want to handle this case explicitly with a `if let Some(parent) = node.parent() {` pattern.
Some people prefer their languages to be more concise, and the safety of the the option objects (and the requirement of the unwrap() calls in the function chain) feels unwieldy. Moreover, as the unwrap() calls could panic if there's no attribute, the more complete handling of it is even longer (match calls and following the successful path).
This could be a function to isolate just the attribute you need, but seeing the example as it is presented can be off-putting from people used to scripting languages like ruby/python, which are more concise.
You're not ignoring errors with unwrap(): if there is an error, the program will print out a stack trace and exit. If you have some operation that could potentially fail but you know it won't (like if you are sure that node has a parent) what do you do? If the operation actually does return an error, it means what you thought to be true was wrong, and in some cases that means something has gone seriously wrong, and your program should immediately stop so you can debug it. You can try to handle the error yourself, using try! or the ? operator, but unless you plan to be able to recover from that error, or you want to output a more end-user-friendly error message than a stack trace, what's the point?
I'd like to see some sort of macro for DOM navigation that takes a node and an XPATH expression or something, and the macro expands it to the above. Never played around with macros in Rust, so I don't know how involved that would be, or even if it would be possible.
So, I see tons of unwrap() in Rust code I've looked at in the wild. I understand the concept of unwrap() and Option types. What would this type of code look like with proper error handling? It seems like it'd devolve into a ton of if-then statements like in C.
First, you'd use match statements instead of if-then so the worst case scenario already looks much better than in C, especially since Rust has enum decomposition and makes expressions first class (you can do let y = if (...) { y } else { z }). There are a lot of ways of combining control flow and assignment operators to decompose union types like Option and Result (which is Option with error E instead of None). For example, you can do if let, while let, or let x = match(y) { ... } that allow you to handle errors without jumping through hoops like you would with C returns or C++ exceptions. For a library consumer this covers a large number of cases.
Second, most of the time you can use the ? operator to greatly simplify error handling. Any code path that shares the same error type can just pass through errors as if they were an exception. The ? operator is also aware of Into/From trait implementations so in many (or even majority of) cases you can use the ? operator even if the function you're calling has a different error type! If I remember correctly, you can even exploit the module system to provide a per-file Into/From implementation for your custom error type if it doesn't map cleanly across use cases (they just have to be in the same module as the type). Rust's zero cost abstractions and trait system make it really easy to reduce boilerplate without compromising on readibility or discoverability.
Third, the Result type has a number of functional operators for responding to and combining results. You can do Result.and_then(...) with a closure or function call to do something when there is no error and Result.or_else(...) to do something when there is an error. You can use the and or or operators to combine multiple results and there are many other utility functions that are universal to Rust error handling that make the entire experience very pleasant, composable, and readable with a little experience.
It does turn into if-then statements (some implicit, e.g. via try! or ?), if done properly. But I don't understand the objection or calling it "devolving". Errors have to be handled. This way is as efficient as any other. And, in my view, is cleaner than exception handling systems.
This is a highly contentious assertion, and I don't think it's true for most programs, at least not in the way you're suggesting.
Most of the point of exceptions is that errors don't have to be handled; or rather, in most application software, almost all errors should be handled high up in the stack, near the event loop or server request / response dispatcher.
This is the same in rust. Panics end at thread boundaries. So you'd have some event loop with threads / coroutines doing stuff and if they panic you handle it at the top level.
The kind of error that you'd handle high up the stack is, say, a general I/O error reading a file.
But when you look up an item in a collection (or a node in a DOM tree), and it is not found, the only place where you can sensibly handle that is right where the lookup happens, usually.
In a language that doesn't follow this philosophy, what you get instead are random NullPointerExceptions etc. If you go and look at a random C# or Java project on GitHub and check its tracker, you will see that - surprise, surprise! - that is exactly the type of error that shows up most.
Programming errors in production are usually handled by logging and then either exiting the process or going back around the request / response loop again (presuming global state hasn't been polluted, which is unusual in most modern application servers since they're usually stateless).
"feature request": please announce what is new in beta also. Maybe I'm not alone on beta and if I would knew about web-assembly in beta, I'd test it 6 weeks ago :)
We used to do this, but it made release announcements feel redundant, and part of the beta process is making sure that we don't need to back anything out, so we can't even 100% guarantee that beta is absolutely going to have whatever feature.
I have a question for Rust users: let's say I'd want to write a system tool that has to run on multiple platforms (Windows/Linux/Mac) and that would integrate with all sorts of command line utilities.
I'm interested in using Rust, but would Rust be a good fit for this? The tool would be long lived so I'd want a statically typed language with a modern type system and as many safety guarantees as possible. But I'd also want a high level programming language and also libraries that would help with that integration (launching processes, capturing output, monitoring progress, parsing output: text, JSON, XML, etc., etc.). I'd also want a tool that runs quickly but I figure there's no point in mentioning that in a thread about a language that compiles to native code and that has no garbage collector :)
This should be an area of strength in Rust, at least conceptually. If a systems language can't write system utilities, well...
There is at least some degree of support for everything on your list, though it's kinda hard to tell with some of the ways in which you're being vague (not that that's bad, mind you, just recognizing that this answer is also kind of generic because of it.)
I'm not quite sure what you mean when you say "integrate with all sorts of command line utilities", but based on the other things you write I could not think of a better language than Rust.
Since I started to write some Rust code about 6 months ago, Rust has replaced Python as the language I think in. Static typing with a modern typing system is awesome, and not having to think about a GC is also awesome (see also the recent Medium article about all the ways GC's need to be tunable).
Rust sounds perfect for what you want to do. It takes a bit of practice to get used to its parsing, since it's extremely safe, but when you get things running, they run very well. As for cross-platform capabilities, it has fairly mature support across all the mainstream OS platforms, and developing support for others such as ARM. Check out this page (https://forge.rust-lang.org/platform-support.html) for more information on Rust's platform support.
@oblio you should have a look at the “24 days of Rust” blog series[1] which covers a lot of aspect of the Rust ecosystem (serialization, error handling, path management, configuration handling etc.)
Process launching/capturing output/etc is there and very robust across platforms. Most of the other stuff you've mentioned I've seen support for but haven't used it in anger yet.
Bonus: Cross-compiling to other platforms is straightforward so you can build OSX/Linux/Windows all from one box.
For years we actively told people not to use Rust, to run far far away, because we were still breaking things and didn't want anyone mad at us. Now that we're past 1.0, we've got a lot of catching up to do. :)
(But seriously, we're usually quick to tell people when Rust isn't a good fit for their problem domain. It just so happens that the grandparent comment is describing a domain that Rust is really quite suited for.)
> let's say I'd want to write a system tool that has to run
> on multiple platforms (Windows/Linux/Mac) and that would
> integrate with all sorts of command line utilities.
Congratulations and thank you to the Rust team! As always, I've updated my Rust Docker image[0] for 1.14 (both the latest and 1.14.0 tags) for anyone who has Docker installed and wants to try Rust out quickly. Although with how easy Rust is to install via Rustup now, the value of this image is diminished somewhat. :}
Love Rust. That said, I have not figured out the following, and I'm sure that there has to be a canonical solution for this:
I have a Rust application that depends on 1 crate from crates.io. I want to build it on an embedded device over serial that has no networking capabilities. Does Cargo have an 'offline mode' or something that I can use to say "I don't want to depend on the Internet to build this, just fetch this version of the crate and keep it?" Because I have not been able to find anything like that. I'm sure there's a good solution for it because Rust is billed as a systems language.
I read the first and last link, had not seen the second. Looks like what I need, thank you. Surprised that Rust seems to expect people to have Internet access to build.
Is this similar to nuget, if your familiar with that? Ie, do you have "pinned" versions in a project and only need to access the internet when a package is missing?
I haven't used nuget a whole ton, but yes, that sounds like it. Basically, you have two files: Cargo.toml and Cargo.lock. The toml file declares what version ranges you want to use, then after a successful build, the exact versions used were put into the lockfile. After that, nothing will hit the network or change up versions until you either modify the version ranges in the toml file or use the command-line interface to ask to upgrade.
Yes, I considered cross compiling. However I have run into this problem often enough to want a real offline solution and to me it is simply unacceptable for a systems language to depend the Internet for builds involving external packages.
179 comments
[ 3.1 ms ] story [ 146 ms ] threadI like the '..' addition for structs. It definitely improved the pattern matching over structs.
Congrats to the Rust Team for another good release!!Take a look at Fira Code [1]. I use it in Vim and IntelliJ, and it looks great with Rust and other functional languages.
[1] https://github.com/tonsky/FiraCode
In that light, it actually makes sense.
(edit: ok, I see from other replies that it's not that simple)
`..` and `...` both exist in the language, `..` is exclusive range and `...` is inclusive range. `..` is only in expressions right now, whereas `...` is only in patterns. Eventually, both will be available everywhere, possibly. At very least, `..` in patterns is getting added soon.
Since this is a pattern thing, probably `..` was chosen when `...` was the only range available in patterns, to distinguish this from that range pattern more. However, `..` will now be available in patterns, so its just historical.
(This is a longstanding feature, what's changed is just making it apply to more patterns.)
I'm sure someone from the rust team can give a better answer, but to me this change looks like it was just bringing the pattern matching for structs to be consistent with other uses of ".."
Relevant RFC: https://github.com/rust-lang/rfcs/blob/master/text/1492-dotd...
Rust is such an awesome language. Every design decision feels so right. Go, Rust, go!
(For those of you who don't pay super close attention to Rust development, that means libraries like Serde and Diesel will be as convenient to use on stable as they are on nightly, today.)
Let's take a step back. Macros 1.1 is RFC 1681: https://github.com/rust-lang/rfcs/blob/master/text/1681-macr...
See the section saying "The initial implementation of librustc_macro is proposed to be incredibly bare bones:" it really is very, very small. So it landed, and while there was some questions that came up, people migrated to it, and it works well.
22 days ago, it was to be reviewed: https://github.com/rust-lang/rust/issues/35900#issuecomment-...
However, two things happened: one, the Mozilla all-hands in Hawaii, which shook things up, but secondly, that meant a lot of people, including one of the reviewers, took PTO around that time, to actually see some of the islands. That includes someone who was on the reviewers list. So in general, "oh hey this is waiting on one person who forgot to check a box but isn't reachable now" is awkward.
Luckily, in this case, we know that it was just forgetting to check the box; Felix did not have any objections that we were aware of. So we decided to sign off for him, and put it into FCP. This happened so that FCP technically passed the deadline for 1.15, but given how important it is to ship, we're planning on nominating it for a backport, and don't anticipate complaints.
So: tiny feature, code wise. Big win for being stable. Procedural mishap involving awkward scheduling. All these things played into it. Make sense?
but it looks like SDL2 has an official port: https://github.com/emscripten-ports/SDL2
So you'd use regular Rust SDL2 libraries, and it Just Works (hopefully...)
> mips-unknown-linux-gnu > wasm32-unknown-emscripten > arm-unknown-linux-musleabi
What value does that garbage add to it?
See here: http://clang.llvm.org/docs/CrossCompilation.html#target-trip...
"generic" would work too, but this is a long-standing convention, so that ship has probably sailed.
https://github.com/rust-lang/rust/issues/33147
http://wiki.osdev.org/Target_Triplet
The "unknown" is the vendor field. Most linux OSes don't have a "vendor".
Target triples are of the form arch-vendor-kernel, and the -kernel is sometimes in the form -kernel-abi)
So you can have x86_64-pc-windows-gnu or x86_64-pc-windows-msvc or x86_64-apple-darwin with the vendor field set.
Most of the OSes with non-unknown vendors already have Rust binaries, so most new platforms will be unknown.
Maybe this could be documented somewhere on the rustup doc so new users like me aren't puzzled by this strange “unknown” everywhere. Or maybe it is, and I just didn't find it because I was too lazy to look explicitly for it …
It could all be so beautiful.
And before you blame those standards, blame the Unix vendors^W^W, pardon me, the platform owners (Microsoft, Apple, Google).
You could also render everything to a canvas to avoid HTML and CSS, but at that point there are a lot of things to re-implement, especially around accessibility.
But that's just the initial implementation. It needs to be implemented fully, debugged, optimized and then it needs to trickle down to user devices, including those sold 3-4-5 years ago and still in use.
And then, in the second stage, wasm needs to get DOM access (as far as I know v1 won't have it). See stage 1, all over again.
I'd say that the mass adoption cycle for 1 stage is roughly 5 years (where 80%+ of the browsers out there support a major feature well). So 2 stages x 5 years = 10 years.
Maybe I'm too pessimistic...
On the desktop: Firefox, Chrome and Edge auto-update.
On mobile: Android 4.4+ (over 80% and rising fast) auto-updates its webview component. iOS receives yearly updates that are applied by a very large majority - though Apple's browser development does seem to have stagnated a bit.
So it seems to me that non-updating browsers are going extinct, and that we won't be dealing with another IE6 anytime soon. We're living in the future! :-)
With such a type system, it is possible to encode the invariants of your application in types (using generics and algebraic data types). Then you can get very close to "if it compiles, it works".
JS, in particular, is the opposite. I am never really convinced that any JS I have written is "correct". It works, until one day it doesn't. This is such a problem that there have been multiple attempts to retrofit type-systems on top of it.
Rust needn't be the only language that brings strong typing to the frontend (Elm has been around for years now). But I think the prospect of speed and correctness both front and back is pretty exciting.
That type system is pretty verbose because it's aimed at manual memory management which you don't really care about in front end, and the compile times are huge compared to say TypeScript or something along those lines so yeah - I agree static typing is nice - but saying you should use Rust for front-end because it has static typing is like saying every gardener should have an excavator because digging holes with hands sucks - shovels exist.
Rust just happens to be well positioned to take advantage of all this.
Are A and B mutually exclusive per se or is that just an unfounded assumption?
I'm saying that to implement feature in Rust takes same time as in Typescript or PHP (as PHP is a server side language also and comparison is more illustrative).
0 cost abstractions do matter a bit. In general abstractions let you do high level programming in lower level languages.
The type system matters a lot.
I used to do a lot of scripting. One thing I really missed was having a good static type system. These days I miss ADT enums in all languages.
Scripting is already moving in the direction of being more type safe (typescript, python type annotations), which is awesome, but I'd love to use something like Rust in that sphere.
> Rust is a low level systems programming language, it's very suboptimal for high level front end code from productivity standpoint
Rust's type system is wonderful, and it's a real productivity boost. Fortunately people at Facebook developed an equivalent for JavaScript [1] because living without it would be really hard for me now. Furthermore, Rust offers a lot of syntactic sugar that makes it feel like a really high level language (compared to C, Go or even JavaScript pre-ES6 for instance).
>it's advantages (mem safety with 0 cost abstractions) don't really matter in frontend
It's indeed one of Rust selling point (especially for people coming from a C background) but it's not the only one. My favorite being the data-race free parallelism. I don't know the current status of multi threading in wasm, but being able to take advantage of all the cores of mobile devices could really help front-end frameworks.
[1]: http://flowtype.org, it's not inspired by Rust but inspired by OCaml, which also inspired Rust.
Rust type system is verbose compared to higher level languages and it lacks a lot of the things that make higher level languages productive. It just focuses on low level code - which is good - but you wouldn't use it in place of C#, you would use it instead of C++, and you don't want to write GUI code in C++ either (even Qt uses JS for the frontend)
>My favorite being the data-race free parallelism.
Also mostly irrelevant in front end since you're dealing with single threaded event loops and doing parallel work that talks to UI thread is easy. Stuff that needs to do work in parallel can be written in Rust and talk to front end via FFI or RPC.
Only if you use QtQuick. The traditional QWidget API is C++ all the way.
Rust is way too low-level for that imo. It works for Emscripten because of legacy code, but Rust is still ways off in that regard (i.e. adoption).
There is a large gap between those and the way Scala _just works_ across platforms.
The huge difference is that you can depend on libraries and have them "just work" regardless of whether they are implemented identical on each platform, or need specific variations to implement the expected features.
Neither JS/Node nor Java/GWT have that.
Don't hold your breath.
Unfortunately, the community seems to be going the way of Ruby/Python/C++: massive fragmentation.
_Please_ make this so.
> still far too early
I've waited 3 years, more time probably couldn't hurt.
Sure - just as everyone "rallies" around EventMachine in Ruby.
This discussion has been going on for almost 3 years now.
It's great that tokio is making community headwinds, Twisted, Gevent, Celluloid, EventMachine all did too.
The problem is, they've never reached critical mass, and their respective languages refused to bless them as "official."
> What evidence do you have of this?
The issue is inter-library compatibility.
https://github.com/tailhook/rotor
https://github.com/tokio-rs/tokio
Totally incompatible, even though they build on the same low level library.
https://github.com/mitsuhiko/redis-rs
Oh wow, a great redis library - objectively the most popular. Completely incompatible with all of the above AIO implementations.
Let's take it to the extreme:
- Incompatible memcached client implementations: - https://github.com/aisk/rust-memcache (sync) - https://github.com/zonyitoo/memcached-rs (sync) - https://github.com/samphippen/decachedmem (tokio, partially implemented)
- Incompatible redis client implementations: - https://github.com/tokio-rs/tokio-redis (async via tokio) - https://github.com/mitsuhiko/redis-rs (sync) - https://github.com/AsoSunag/redis-client
- Incompatible HTTP client implementations: - https://github.com/matt2xu/async-http-client/ (tokio, new) - https://gitlab.com/imp/requests-rs.git (hyper, sync) - https://crates.io/crates/reqwest (hyper) - https://crates.io/crates/request
The list goes on.
There are countless libraries implemented with synchronous I/O, there are countless (good) popular libraries implemented with non-Tokio-based concurrency primitives.
Let me just say it: I really, really like Rust.
But I cannot feasibly use it for network/server-related tasks until a single solution is blessed by the Rust team.
The "let's let the community handle standardizing async IO and concurrency" approach has _never_ worked in the somewhat brief history of programming languages.
A blessed solution though? - Erlang, Golang, Node/JS* All work flawlessly.
I would use Rust full-time for every server-related task if I could, but I've been observing for 3 years and unfortunately haven't seen much development after the abandonment of builtin green threading.
*- codestyles sometimes incompatible, but there was _never_ a litany of sync libraries or otherwise fundamentally incompatible systems.
You can't really compare things this way. Very few people even use EventMachine, as it has significant issues.
You can't just show that rotor and tokio are two different libraries; you've claimed that there's significant ecosystem fragementation. That's a very different claim. The same goes for the other three sets of links below: that you can find a bunch of GitHub repositories does not mean that there's actual fragmentation. Writing a memcached or Redis client is a good way to learn a language, even: I've known two people who independently did so for memcached + Rust, tossed them up on github, and that's it. (one of those is one of the links you've provided above, even.)
> Oh wow, a great redis library - objectively the most popular. Completely incompatible with all of the above AIO implementations.
Because it's synchronous. Once tokio has an actual 0.1 release of the full stack, which is to happen any day now, you'll see more consolidation.
> until a single solution is blessed by the Rust team.
Two of three of tokio's core team members are Rust core team members. We had a full talk on it at RustConf, and it was mentioned in the keynote. Mozilla has sponsored development of it in places.
If you like Rust, and you want to use it for network and server related tasks, get involved. Write the redis, memcache, HTTP clients of your dreams. Rally the people who've solved those problems in Rust (and elsewhere) in the past.
Please try to state your concerns (or better yet, ask questions) in a more thoughtful manner.
It would be better if they would, though, is what some of us are thinking.
Between "totally chaotic third-party libs landscape" and "official lib designed with the language and part of the standard library", picking winners is a great middle ground.
At least in the case of Twisted, it probably didn't help that for a long time it was GPL licensed with all community contributions requiring copyright assignment to the lead developer.
The Rust community is pretty unified, esp. as its communication channels are well defined. For asyncio, I am pretty sure that Tokio will be the tool for most applications.
It is! But there are a mass of completely incompatible, overwhelmingly popular libraries.
> For asyncio, I am pretty sure that Tokio will be the tool for most applications.
When?
Tokio was only released along with futures like 3 months ago? It takes time to rebuild software on top of that. It definitely took me time to port from directly using MIO to using tokio.
After evaluating others options, I do believe tokio will be the default for most people.
You say it like it's a good thing.
Why wouldn't it be? Let people experiment. As long as there's a standard, go-to library for applications that need to "just-work", I don't see any reason not to explore new ideas and find potentially better solutions for the future.
However it's not an easy issue to solve for a general purpose language, unless you want to tie all those IO semantics (and probably a big runtime environment) directly to the language. C++ and Rust don't want to do that, since they want you to be able to use the language even on bare metal with zero runtime.
What you can do as a library developer for these languages is to try to make them as integretable as possible into all kinds of surrounding environments. I normally would try to make my library usable for blocking calls as well as in a nonblocking way within an external eventloop. You can do that by spawning your own thread/eventloop, handle all the library logic in there and provide thread-safe external APIs that communicate with our eventloop.
Framework development (in the sense of Netty/Tokio/etc) is harder. If often won't be possible to develop code that runs in multiple frameworks.
On one hand this is really cool and potential for client-side Rust. On the other hand:
Eh, no thanks. :) If I could get a macro or shorthand for that, I'd welcome all the other benefits of a large scale client-side platform with strong typing.Most of the cost of vdom is the resulting DOM ops and reflow/restyle the browser needs to do. It may be faster than the fastest today, but you're unlikely to see any kind of performance leap or even anything noticeable.
Because people wouldn't expect it to return due to behaviour of existing languages yet that's what it does in Rust?
Many are in favor of doing it, though. I'm personally against it.
I see that there is some discussion here [1], including a suggestion to add a Haskell-style "do" block. But that's just one guy's blog post.
[1] https://m4rw3r.github.io/rust-questionmark-operator.
It sounds like there are some that would like to move Rust in the direction of becoming more Haskell/ML-like (which is to say more purely functional) rather than the current balance between imperative and functional? Is there any internal tension in that regard?
This leads to a situation where, if there were to be a monad trait, that trait should abstract over not only types, but another traits generically.
Not to speak about some other hurdles, like lifetimes. The design space is inherently more convoluted than in languages with boxed, possibly dynamically dispatched types. It may be possible, but it's not easy, and we can't copy the monads straightforwardly from Haskell or Scala.
Even regardless of performance, it would be quite nice to have! I've been meaning[1] to build a small prototype to do something clever[2] with it, but didn't have the time yet. Feel free to steal these ideas :)
[1]: https://scribbles.pascalhertleif.de/impl-virtual-dom-cli-lib... [2]: https://scribbles.pascalhertleif.de/rich-diffs-of-rendered-h...
? is far easier and faster to type than .unwrap().
So no, there's nothing horrible that I see, there is something horrible that I feel though.
Isn't unwrap():
a) boilerplate
b) repetitive?
In other words, it's boilerplate here because this particular operation has many possible failure modes, and Rust is pointing those out to you.
It's repetitive in this particular instance, but doesn't have to be in general.
if the node always having a parent is a invariant of your application, you should use `expect` with a clear error message when the invariant is broken.
if your node can have no parents then you want to handle this case explicitly with a `if let Some(parent) = node.parent() {` pattern.
This could be a function to isolate just the attribute you need, but seeing the example as it is presented can be off-putting from people used to scripting languages like ruby/python, which are more concise.
Dealing with this case properly without using a single `?`, gets really ugly with a lot of nested
For the cleanest code, I would use `?` and a `From` impl for the error transformation.
If I didn't want to use `From`, I'd use `map_err`, `and_then`, etc. Both the Result and Option types have wonderful interfaces for chaining.
Is there a way to rename / alias methods like that?
edit: I see ? is going to be a trait you can implement to do that, so that'll be nice (probably).
If you don't care about errors, don't use Rust. Use C instead. Simple solution.
Second, most of the time you can use the ? operator to greatly simplify error handling. Any code path that shares the same error type can just pass through errors as if they were an exception. The ? operator is also aware of Into/From trait implementations so in many (or even majority of) cases you can use the ? operator even if the function you're calling has a different error type! If I remember correctly, you can even exploit the module system to provide a per-file Into/From implementation for your custom error type if it doesn't map cleanly across use cases (they just have to be in the same module as the type). Rust's zero cost abstractions and trait system make it really easy to reduce boilerplate without compromising on readibility or discoverability.
Third, the Result type has a number of functional operators for responding to and combining results. You can do Result.and_then(...) with a closure or function call to do something when there is no error and Result.or_else(...) to do something when there is an error. You can use the and or or operators to combine multiple results and there are many other utility functions that are universal to Rust error handling that make the entire experience very pleasant, composable, and readable with a little experience.
This is a highly contentious assertion, and I don't think it's true for most programs, at least not in the way you're suggesting.
Most of the point of exceptions is that errors don't have to be handled; or rather, in most application software, almost all errors should be handled high up in the stack, near the event loop or server request / response dispatcher.
The kind of error that you'd handle high up the stack is, say, a general I/O error reading a file.
But when you look up an item in a collection (or a node in a DOM tree), and it is not found, the only place where you can sensibly handle that is right where the lookup happens, usually.
In a language that doesn't follow this philosophy, what you get instead are random NullPointerExceptions etc. If you go and look at a random C# or Java project on GitHub and check its tracker, you will see that - surprise, surprise! - that is exactly the type of error that shows up most.
An item not found in a collection or tree is not an error.
Null pointer exceptions are little different.
I'm interested in using Rust, but would Rust be a good fit for this? The tool would be long lived so I'd want a statically typed language with a modern type system and as many safety guarantees as possible. But I'd also want a high level programming language and also libraries that would help with that integration (launching processes, capturing output, monitoring progress, parsing output: text, JSON, XML, etc., etc.). I'd also want a tool that runs quickly but I figure there's no point in mentioning that in a thread about a language that compiles to native code and that has no garbage collector :)
There is at least some degree of support for everything on your list, though it's kinda hard to tell with some of the ways in which you're being vague (not that that's bad, mind you, just recognizing that this answer is also kind of generic because of it.)
Since I started to write some Rust code about 6 months ago, Rust has replaced Python as the language I think in. Static typing with a modern typing system is awesome, and not having to think about a GC is also awesome (see also the recent Medium article about all the ways GC's need to be tunable).
@oblio you should have a look at the “24 days of Rust” blog series[1] which covers a lot of aspect of the Rust ecosystem (serialization, error handling, path management, configuration handling etc.)
[1] https://siciarz.net/24-days-of-rust-working-json/
Process launching/capturing output/etc is there and very robust across platforms. Most of the other stuff you've mentioned I've seen support for but haven't used it in anger yet.
Bonus: Cross-compiling to other platforms is straightforward so you can build OSX/Linux/Windows all from one box.
(But seriously, we're usually quick to tell people when Rust isn't a good fit for their problem domain. It just so happens that the grandparent comment is describing a domain that Rust is really quite suited for.)
[0] https://hub.docker.com/r/jimmycuadra/rust/
I have a Rust application that depends on 1 crate from crates.io. I want to build it on an embedded device over serial that has no networking capabilities. Does Cargo have an 'offline mode' or something that I can use to say "I don't want to depend on the Internet to build this, just fetch this version of the crate and keep it?" Because I have not been able to find anything like that. I'm sure there's a good solution for it because Rust is billed as a systems language.