Announcing Rust 1.14
blog.rust-lang.org
blog.rust-lang.org
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.
> their respective languages refused to bless them as
> "official."
Tokio is literally developed by 1) the Rust developers and 2) contractors paid by Mozilla to work on Tokio. It's as official as Cargo is. :PIf 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.
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.)
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.)
> 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.
Sounds like you'd enjoy taking a closer look at ripgrep, which is exactly what you describe: http://blog.burntsushi.net/ripgrep/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.
[dependencies.somepackage]
path = "./somepackage"
Sorted.I like the '..' addition for structs. It definitely improved the pattern matching over structs.
let p = Point { x: 0, y: 1, z: 2 };
match p {
Point { x, .. } => println!("x is {}", x),
}
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.
In that light, it actually makes sense.
(edit: ok, I see from other replies that it's not that simple)
1 ... 10`..` 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!
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.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.
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...
let id = node.parent().unwrap()
.parent().unwrap()
.data_get("id").unwrap()
.parse::<usize>().unwrap();
If there is something horrible about that I don't see it.? 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
if let Some(parent) = node.parent() {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.
(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.
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 …