16 ms·
I've been using Rust to process a large text corpus, and as Armin suggests, it's a really interesting experience. Here are a few things I've noticed so far: 1.
by ekidd 12y ago
I've been using Rust to process a large text corpus, and as Armin suggests, it's a really interesting experience. Here are a few things I've noticed so far:
1. Writing Rust code definitely takes more time than Python or Ruby, but it's not bad in practice. I can't measure the productivity difference yet, partly because I'm still learning Rust. I do spend more time thinking about how to write zero-allocation and zero-copy algorithms, and trying to get my code to compile (but see 3, below).
2. It's possible to write very fast code without compromising memory safety. It's great to see key parsing operations happening in ~100 nanoseconds, with no allocations.
3. Rust is one of those languages where I need to work to make the compiler happy, but once I manage that, the code generally works on the first try.
4. The tooling is very good: library management, unit testing, benchmarking, documentation, error messages etc., all work very nicely.
Overall, it lacks the instant gratification of a really good scripting language. But I keep finding myself back in Emacs, writing more Rust code for the fun of it. And I really enjoy the combination of low-level code, memory safety, and a useful selection of functional programming features. I'm glad to see a new language in this niche.
- kibwen 12y agoThis is great feedback, thanks. And if there's anything that you don't like about Rust, please let us know now while we still have a chance to possibly fix it! Only a few short months left until all of our mistakes are forever entombed in Rust 1.0. :)
- saosebastiao 12y agoTwo things that come to my mind: 1) General concurrency/parallelism ease of use. It would be nice to have Async/Await a la C#, as well as some easier to use channels and synchronization primitives/functions along the lines of Go or Core.Async. And 2) use of <> for type annotations instead of [], which is much easier to parse when nested.
- kibwen 12y agoServo is definitely demanding a wide variety of approaches to both concurrency and parallelism, so I expect the facilities for such in Rust to mature very quickly (but faster with more help and feedback!). It's a very important issue that is seeing work from full-time developers as we speak. As for the second point, we've gone beyond the bikeshed (<> and [] are both exactly as ambiguous to the grammar, so it's just an argument of preference by this point) and addressed the root issue with `where` clauses, which prevent you from needing to nest <> at all for a majority (or perhaps plurality, I haven't measured) of function signatures where you previously needed to.
- yen223 12y agoI've been using Rust for toy projects for a while, and I gotta say Rust is one of the nicest languages out there. Kudos to the Rust team. As a relative newbie to Rust, one of the biggest hurdles I faced was that of poor documentation. A lot of "rust xxx" searches would link to outdated articles or to stale links in the Rust official docs. I understand that Rust is a young language, and documentation is probably the last thing on the core devs' to-do list (and rightly so), but I think it would greatly help drive adoption rates if we could proper docs in place.
- masklinn 12y ago> A lot of "rust xxx" searches would link to outdated articles or to stale links in the Rust official docs. Or to an old mirror of the official doc, http://web.mit.edu/rust-lang_v0.9 http://web.mit.edu/rust-lang_v0.9 is the bane of my rustperience.
- yen223 12y agoIt doesn't help that there's a game called Rust out there!
- masklinn 12y agoI feared that, but overall combined with programmatic context (e.g. iter, array or whatever) I've had the game come up very rarely.
- broodbucket 12y agoIt gets a bit annoying that a lot of Rust libraries are named something rust-themed. I was looking at which web framework I should use (between Nickel and Iron) and so searching "rust nickel vs iron" returned absolutely nothing of relevance. I did learn something about metals, though, so there's that.
- masklinn 12y ago
- tomp 12y agoI think that mutability should also be recorded in types (i.e. even a &mut would not allow you to modify an immutable type). Then, programmers could control whether variants/enums are "fat" (use the maximum amount of memory of any variant in the same type) or "thin" (use the minimum amount of memory for the given variant) by changing the mutability of fields they are stored in. But I totally understand that you probably have other, well thought-out reasons not to do that.
- kibwen 12y agoOff the top of my head this seems like it would allow the amount of memory taken up by an enum to vary dynamically, which would prohibit stack allocation and require heap allocation instead. It would also be impossible to realize this optimization for any array of enums, since they would all need to be the same size for efficient indexing, and further it would wreak havoc with structs containing enums by making it impossible to statically compute field offsets. However, we have considered elevating the position of mutability in the type system for other reasons--specifically, to make it possible to write a function that is generic with respect to mutability. But there's never been a huge amount of enthusiasm for that, so I wouldn't expect any changes of that sort. But thanks for the feedback anyway! :) It's definitely valuable to know that people do care about the size of enums. We have various optimizations required by the language spec to shrink them down wherever we can do so while preserving semantics, and we welcome people to concoct more.
- tomp 12y agoWell, it would definitely need to be special-cased, i.e. only use it when (1) the field containing the enum is immutable, and (2) it's the last field in the structure (it would then make the structure a Dynamically Sized Type). I only care about the size of enums inasmuch as I find it wasteful to allocate a 10 words long Box to hold a 2 words long enum. Of course, the optimization would only make sense if the Box was immutable (even with a unique reference). I mostly mentioned the enum size issue because I read somewhere not too long ago that Servo people were having problems with memory usage because of that (and that they also want objects/records with inheritance of fields - that would bring all the issues you speak about above).
- Symmetry 12y agoThe ability to evaluate functions at compile time would be really nice. I was sort of looking at writing a macro in Rust to mirror Nimrod/Nim's 'when' statements but gave sort of gave up when I saw that. But of course that's probably an entirely unreasonable thing to request in the remaining time you have and it might be incompatible with having a borrow checker anyways. The borrow checker looks really valuable though, and something that might have a big influence on language design going forward.
- kibwen 12y agoLightweight compile-time evaluation is definitely a weakness of ours. A full-fledged syntax extension can get you pretty far, but those are a terror to write and ugly to import. While I don't know of any proposals in the air at the moment, I expect the developers will treat this with great importance post-1.0.
- saosebastiao 12y agoInteresting. From what I understand, this was what BurntSushi's regex macro was intended to accomplish: an efficiently compiled regex that optimized away all unneeded functionality for regex literals. With CTFE, would this get rid of the need for a macro entirely?
- kibwen 12y agoSadly I'm not enough of an expert to say for sure. It would certainly depend on the specific form that it took, and there are a multitude of options in this space. Of the current contributors who are willing and able to push the boundaries here, I believe that quasiquotation is the preferred approach (motivated by use cases for compile-time codegen in Servo).
- burntsushi 12y ago> I believe that quasiquotation is the preferred approach Oh yes yes yes. Quasiquotation makes writing syntax extensions almost easy. It can't cover everything though. For those cases, dropping down into AstBuilder (or the raw AST) isn't completely terrible, but it's a big step down from quasiquoting.
- MichaelGG 12y agoHi! I use F# for most tasks (from websites/JS generation, to packet capture and indexing, call routing and billing processing), and some C where required. Rust looks fantastic, and would give me the memory control I need when I need extra performance. A LOT of it comes down to simply being able to stack-allocate things; in F# I'm essentially forced to use the GC heap for even the most trivial things. Rust looks fantastic, and I'm very excited about using it. When I found out about it and started reading how it worked, it was almost exactly what I had been wanting, on almost every count. I really wish it had existed a few years ago. My comments are from someone that's just been playing around with the getting started guide of Rust. -- Lack of custom operators limits expressiveness. For instance, look at Parsec or FParsec. Why shouldn't they be allowed to exist in Rust? But if custom operators are totally out of the question, then what about user-defined infix functions? (And then, why not functions with nearly arbitrary codepoints as identifiers?) -- It seems that currying, partial application, and function composition are sorta cumbersome in Rust. Is this a conscious decision, that idiomatic Rust shouldn't be doing such things? Like " add >> inc >> print " being equivalent to "|a,b| -> print(inc(add(a,b)))" ? In F# I use this kind of stuff all the time, especially when processing lists. -- It seems there's a difference between function types. Like if I do "fn foo(a:int, f:proc(int)->int)", I can call it with foo(1i, inc) if inc is a fn. But if I first do "let f = inc; foo(i1, f)", that's an error. Offhand, I'd assume this is due to lifetime management, but it feels a bit strange. When writing HoFs, do I need to implement a version for each kind of function? Or am I totally misunderstanding things? -- Sorta related, does Rust allow something like: let inc = let x = ~0 || { let res = *x; *x += 1; res } The idea is to expose a function that contains some private state. I remember hearing that Rust changed the ownership stuff around a few times, but the basic idea is to create a globally-accessible closure. Is this impossible, requiring us to use statics to store the global state? -- Why doesn't Rust warn when discarding the result of a function if not unit? Is it idiomatic Rust to return values that are often ignored? -- Even without higher kinded types, monadic syntax is useful. Is Rust planning any sort of syntax that'd let users implement Option or Async? How does Rust avoid callback hell? Or is this quite possible today with macros and syntax extensions? -- Has Rust considered Active Patterns (ala F#)? With that, I can define arbitrary patterns and use them with matching syntax. E.g. define a Regex pattern, then "match s { Regex("\d") => ... , Regex("\D") => ... , _ => ... }" -- Consider allowing trailing commas in declarations; why special-case the last item? -- And last but not least: Please, please, please, reconsider type inference. It's baffling why "fn" requires type annotations, but a closure does not. What's more, why is there even different function syntax in the first place? I've heard the reason that "top level items should have types documented", but that's a very personal decision to make. It certainly isn't something the Rust compiler should force me to do in all my code. Why do ya gotta limit my expressiveness? (Same argument I'd use for custom operators.) Statics/consts should also have type inference. And note that these items aren't necessarily public or exposed - but a private fn on a module still requires type annotations.
- burntsushi 12y ago> Rust is one of those languages where I need to work to make the compiler happy, but once I manage that, the code generally works on the first try. I can confirm this. I have a CSV parser[1] that is maybe twice as fast as Python's CSV parser (which is written in C)+. There's nothing magical going on: with Rust, I can expose a safe iterator over fields in a record without allocating. [1] - https://github.com/BurntSushi/rust-csv https://github.com/BurntSushi/rust-csv The docs explain the different access patterns (start with convenience and move toward performance): http://burntsushi.net/rustdoc/csv/#iteratoring-over-records http://burntsushi.net/rustdoc/csv/#iteratoring-over-records + - Still working on gathering evidence...
- moron4hire 12y agoI don't understand. What more do you need out of CSV parsing that any standard regex library doesn't provide?
- eridius 12y agoI don't understand; why would you try and parse CSV with a regex? Note: CSV is actually much more complicated in practice than just splitting on commas.
- moron4hire 12y agoregex is much more capable than splitting on commas
- pselbert 12y agoThere are plenty of values in a purpose built CSV parser. Several important features, depending on the CSVs you'll be working with are: 1. Sometimes you want to actually write files, in which case you'll want help escaping quoting. 2. Shortcuts for using header information to provide more convenient access into a particular column, rather than always doing it by index. 3. Conveniently slurp in only parts of a file, or only particular columns in a file, without loading everything into memory.
- rz2k 12y agoOver the past few days I have been trying Julia. While I don't have much of an idea what I'm doing yet, and I'm probably doing a lot of unproductive premature optimization for the sake of exploring, I see a similar type of difference compared to R and Python where I have more experience. What I am curious about is why you chose Rust rather than Julia. As I've understood the chatter so far, Rust is great for low level programming, and can work well as a replacement for other system level programming languages. Julia on the other hand is supposedly tailored for the type of task you are talking about, and like Rust, the chatter says Julia can be similar to C and Fortan in terms of speed. My understanding of Rust was as a low-level general-purpose language and Julia as a technical or scientific programming language that is similarly fast. Anyway, I'm just curious about the trade offs.
- callcongressnow 12y agoAs far as I am aware, Julia isn't that fast for string operations yet. The language has been optimized for numerical calculations but they haven't done much work on making working with strings as fast as they could. I remember reading this on a github issue at some point but I can't find the issue at the moment.