let thread : &'static Rust = "The Rust Thread".into()

QuadDamaged

Ars Praefectus
3,955
Subscriptor++
Hi all,

Rust is coming-up often-enough in the perpetual thread, often with interesting questions or bug reports, so it might be a good time to start a dedicated thread for it.

For those that do not know the Rust Programming language:

[url=http://www.rust-lang.org:hqpfrw2n said:
rust-lang.org[/url]":hqpfrw2n]Rust is a systems programming language that runs blazingly fast, prevents segfaults, and guarantees thread safety.

There are also other perks like an insanely good type inference system, a growing collection of quality modules (see crates.io), and a very handy web playground ( play.rust-lang.org)
 

QuadDamaged

Ars Praefectus
3,955
Subscriptor++

QuadDamaged

Ars Praefectus
3,955
Subscriptor++
Are there any big-name apps or websites written in Rust? Eg Github uses Ruby and Erlang, and pandoc uses Haskell.

Off the top of my head:

I believe Facebook is working in a VCS written in Rust - there are quite a few job ads for those in the London area, but don't know what the name of the project is.

Here's a list of Rust users: https://www.rust-lang.org/en-US/friends.html
 

koala

Ars Tribunus Angusticlavius
7,579
Oranging!

I finally deployed my first "production" Rust project:

https://github.com/alexpdp7/ragent

I have some internal infra and I'd remade my monitoring, but didn't want to use NRPE, so I implemented my own monitoring agent and Nagios check. I also wanted to deploy it as a .rpm/.deb

I like Rust. RLS on stable has still some pain points (IIRC, function parameters don't get type information and thus don't get autocomplete), but it works in Eclipse (Corrosion) and Visual Studio Code. Coming from Eclipse for Java (which compiles in the background and running is instantaneous) and Python, compile times are a big jarring.

The biggest difference from me, besides the borrow checker (where the compiler is so helpful I still don't know what I'm doing a lot of ties), is Result/Option, which I'm not completely convinced is completely superior to exceptions, but it doesn't feel bad at all.
 

Drizzt321

Ars Legatus Legionis
28,408
Subscriptor++
Oranging.

Definitely interested in rust, been meaning to take the time for months to sit down and go through and get some coding under my belt, do it badly, and then start over and do it better with TDD. Sadly a lots of stuff has been going on on the weekends so I haven't managed to.

I'm tempted to take weekends and go camping with my laptop, a good chair and camping table. Be out in the middle of nowhere, disconnect (have my documentation of course), do WiFi tethering if I _actually_ need some libs/docs and drink all day while coding. And then drink all night with a small camp fire :)
 

koala

Ars Tribunus Angusticlavius
7,579
In my case, I wrote an n-queens solver and a terminal minesweeper, but I didn't get into the mood seriously until I had a real itch to scratch.

For me that was difficult, because most of the side projects I want to do are pretty well covered by Python and Java. But I wanted to ditch NRPE- Python would have been fine, but I think Rust is a better fit. A minimal Flask app I have eats 20mb, while my agent is 3mb- plus it's nice not to have to worry about a Python runtime.
 

Drizzt321

Ars Legatus Legionis
28,408
Subscriptor++
Had a coding interview in Rust yesterday, the catch was that it was done on coderpad.io which does not let you use crates :eek:

Parsing strings using std only is not fun. I ended-up emailing the nom-based version to the interviewers the next day, it's half as long and much more legible.

What kind of MONSTERS won't let you use crates? That's just crazy! Unless there's some kind of very strange, strict need for no external crates it makes no sense to do an interview coding test that way. And if so, they should have warned you ahead of time.
 

QuadDamaged

Ars Praefectus
3,955
Subscriptor++
CLion has the edge for me as it allows you to run a debugger in the rare cases you need one. I managed to track down this issue using clion on windows with its remote debugger feature.

This is the only time I had felt the need to use gdb for some Rust code, and of course, it's related to unsafe sections of the code (I am seriously considering forking pyo3 and getting rid of all this ridiculous pointer magick )
 

Drizzt321

Ars Legatus Legionis
28,408
Subscriptor++
I've tried VS Code but moved into Eclipse Corrosion. They both use the same underlying RLS; it was just a matter of me being already used to Eclipse. I just tried debugging and it works OOB. Code completion has some gaps.

The IntelliJ Rust support I think has its own engine.

I use IntelliJ for work (Java), so was considering that. Hm. I'd rather not be using a separate RLS engine, but the same one as everything else. For my first baby steps I've been using vim/SublimeText. Probably end up using SublimeText with whatever RLS modules that people have put together, but for my baby steps vim with the syntax highlighting is sufficient.
 

QuadDamaged

Ars Praefectus
3,955
Subscriptor++
Thinking about the “I don’t know what to say” incident. I have a couple of unpinned versions in my cargo.toml files, but as I am enforcing cargo.lock to be commited, it seems I am only going to be vulnerable when adding new crates or running cargo update.

Crates.io will enforce stricter authentication for publishers come feb 1st but I can see how the JS world got itself in trouble with easy to consume packages and I feel Rust is on the same path.
 

QuadDamaged

Ars Praefectus
3,955
Subscriptor++
@Koala: Just checked your project, it is very neat, the code reads quite well.

Nitpick: https://github.com/alexpdp7/ragent/blob ... tems.rs#L7 you could replace iter().map().flatten() with iter.flat_map()

I personally tend to not use match when dealing with Result/Option-returning methods, and instead chain calls to Option::eek:k, (Option|Result)::and_then, (Option|Result)::map but I guess that's due to C#'s Linq damaging my brain all these years.
 

koala

Ars Tribunus Angusticlavius
7,579
@Koala: Just checked your project, it is very neat, the code reads quite well.

Thank you! Of course now every time I look at it I think it's crap :D

Shame it now really does everything I want it to, and maybe I won't need improvements. I still need to create Ubuntu packages, but probably I will have no good excuse to work on it. The natural step would be to add testing, but it doesn't offer much value to me right now...

Nitpick: https://github.com/alexpdp7/ragent/blob ... tems.rs#L7 you could replace iter().map().flatten() with iter.flat_map()

Noted! If I had testing I'd ask for a PR :p

I personally tend to not use match when dealing with Result/Option-returning methods, and instead chain calls to Option::eek:k, (Option|Result)::and_then, (Option|Result)::map but I guess that's due to C#'s Linq damaging my brain all these years.

You mean https://github.com/alexpdp7/ragent/blob ... ems.rs#L31 or something else? My gut dislikes chaining calls for error handling (while I abuse chaining filter/map/reduce/etc.).
 

QuadDamaged

Ars Praefectus
3,955
Subscriptor++
Yes, this last match arm. It's a matter of style, re-reading my code, I tend to use
Code:
if let Some(foo)=bar(){
  foo,stuff()
};
over
Code:
match bar(){
  Some(foo)=>foo.stuff(),
  _=>()
}
when Some(foo) is optional, but when it's mandatory I write
Code:
  bar()
  .map(|foo|foo.stuff())
  .ok_or_else(||MyError::NoFoo)?;

I think this might also be driven by IntelliRust's suggestions. My code can compile with warnings, but I'll be damned if there's any squigglies left in my editor! :judge:
 

QuadDamaged

Ars Praefectus
3,955
Subscriptor++
The first London meetups were just workshops with people bringing their projects and a bunch of nerds trying to patch something together.

I remember building a basic AAC parser from the innards of mp4-rs from FF Quantum over a couple of beers with other of cool nerds, and every now and then someone would ask the room 'What's the API to read a file' or 'How do I go from Result to Option?'

The meetup is much more structured now, but you can start with a very unstructured approach.
 

tb12939

Ars Tribunus Militum
1,797
I've an odd problem with a combination of traits and generics, and could do with some hivemind input. It seems to comes down to using a type parameter as a constraint on trait implementation not counting as a valid usage of that type, but the type is still needed.

A brutally simplified example is:

Code:
pub trait Getter<A>
{
   fn get(&self) -> A;
}

struct TestWrapper1<I: Getter<A>, A> // Use A directly - Ok
{
   imp: Box<I>,
   val: A
}

struct TestWrapper2<I: Getter<A>, A> // error[E0392]: parameter `A` is never used
{
   imp: Box<I>
}

struct TestWrapper3<I: Getter<A>> // error[E0412]: cannot find type `A` in this scope
{
   imp: Box<I>
}

struct TestWrapper4<I: Getter<A>, A> // Fake use of A - Ok
{
   imp: Box<I>,
   dummy: Option<Box<Getter<A>>>
}

Am i doing something stupid here?

Anyone have a better idea than the fake approach, where i can just init the dummy field to "None"?
 

tuffy

Ars Scholae Palatinae
863
Am i doing something stupid here?

Anyone have a better idea than the fake approach, where i can just init the dummy field to "None"?
Sounds like you're looking for PhantomData, which is a zero-sized type use to hold dummy fields. Try using it like:
Code:
struct TestWrapper2<I: Getter<A>, A>
{
   imp: Box<I>,
   phantom: PhantomData<A>,
}
as a way to hold on to that type without actually using it for anything.
 

tb12939

Ars Tribunus Militum
1,797
Sounds like you're looking for PhantomData, which is a zero-sized type use to hold dummy fields. Try using it like:
Code:
struct TestWrapper2<I: Getter<A>, A>
{
   imp: Box<I>,
   phantom: PhantomData<A>,
}
as a way to hold on to that type without actually using it for anything.
Yup, that also works - still feels like it shouldn't be needed though. I am already using the type A, to constrain type I.
 

tb12939

Ars Tribunus Militum
1,797
Depending on the cardinality of impls for the Getter<A> trait you could use an associated type and get rid of PhantomData alltogether.

better link to the playground

Ah yes, associated types - the chapter 19 voodoo strikes again (as in, you don't often need the stuff in that chapter, but if you need it, you _really_ need it).

They are perfect for this scenario, since the cardinality is 1:1 (actually 1:1:1:1 in the real code), and linking a generic type to an associated type of the trait keeps everything happy.

Works perfectly - Thanks
 

QuadDamaged

Ars Praefectus
3,955
Subscriptor++
Thanks. Now that I read your comment about stuff you need once in a lifetime... you can get even more fancy (and reduce wrapper to a single generic argument) at the cost of introducing virtual dispatch when calling imp.get
Code:
struct WrapperDynamicDispatch<A>{
    imp: Box<dyn Getter<Item=A>
}

And since we are here, we can - in the case where we have both type parameters - get rid of the box and dynamic dispatch.:
Code:
struct WrapperInline<A, G:Getter<Item=A> + Sized>{
  imp:G
}

Where we ask that G be a struct with a known compile time size that implements Getter of Item A. This would be the most efficient implementation I believe as everything can live on the stack.
Code:
</bikeshed>
 

tb12939

Ars Tribunus Militum
1,797
And since we are here, we can - in the case where we have both type parameters - get rid of the box and dynamic dispatch.:
Code:
struct WrapperInline<A, G:Getter<Item=A> + Sized>{
  imp:G
}
That is quite a nice trick - in this case, i won't be able to put everything on the stack, since the wrapper is shared between threads via an Arc, but i can still remove one of the layers of indirection. Sweeeet
 

koala

Ars Tribunus Angusticlavius
7,579
So I've been doing a more involved Rust exercise over the weekend, which has been a bit of a struggle- it involved writing:

  • A scraper: I used html5ever which seems to be a bit low-level, as it doesn't seem to do (or I didn't find how) searching of elements via CSS selectors and stuff like most scraping libs do. I guess I should have spent more time finding a higher-level library, but writing a recursive walk of the DOM was not so problematic (if unnecessary)
  • HTTP requests. reqwest is nice, but I felt I should have gone full-async, but I was wary of that being a time sink
  • An HTTP server exposing a simple-ish API. Went with Actix Web on a random, lone Reddit documentation. It actually looks nice, but documentation is so-so. I feel like integrating the Actix actor framework into my requests/scraper would have been very nice, but again I felt like I could have spent hours there digging and understanding the documentation.

I also did some integration tests where I missed some higher-level process control features, as I settled on doing:

Code:
... spawn web server to serve as a scraper target...
... spawn my server ...
... do a couple of requests to my server ...
... stop the spawned servers ...
... do the assertions ...

Which is a bit messy because I had to push the assertions to the end of the test, as a panic would mean my spawned process are leaked- that still happens if I get panics doing the test requests.

I also reached into "python3 -m http.server" to have my mock target server- that's a useful Python thing where I'd love to have a simple crate to do that.

...

It's fun writing Rust, but as a non C/C++ coder, I feel like a noob- I could have written this much more quickly in Java/Python- it's still hard for me to find scenarios where Rust is really the best tool for the job, as the problems I normally face don't usually require tight perf requirements and I can deploy a runtime. But it feels good :D
 

Lt_Storm

Ars Praefectus
16,294
Subscriptor++
More specifically: low level programming. Rust is basically a replacement for C. Any time you would use C, Rust is probably a better choice. It was basically designed to make many of the mistakes which people make when writing C programs impossible while maintaining a similar level of machine affinity and speed. It's effectively an OS or at least systems language.
 

koala

Ars Tribunus Angusticlavius
7,579
More specifically: low level programming. Rust is basically a replacement for C. Any time you would use C, Rust is probably a better choice. It was basically designed to make many of the mistakes which people make when writing C programs impossible while maintaining a similar level of machine affinity and speed. It's effectively an OS or at least systems language.

Yes, of course- but I never need to write C. I'm finding excuses to write Rust, basically. It's probably going to be some old school arcade clones at some point or maybe some CLI tool...