|
That's absolutely perfect then, entirely what I want. Now I just need to decide is this is a good idea or not:
|
# ¿ Mar 22, 2017 23:59 |
|
|
# ¿ May 16, 2024 00:03 |
|
Or even better I could make a macro that's invoked like:code:
gonadic io fucked around with this message at 00:16 on Mar 23, 2017 |
# ¿ Mar 23, 2017 00:14 |
|
gonadic io posted:Got my Arduino's ADC working in Rust! i'm p happy not going to lie Now to give it a decent and safe interface as opposed to casting a u32 constant to a memory address to a pointer to a struct . gonadic io fucked around with this message at 14:07 on Apr 4, 2017 |
# ¿ Apr 4, 2017 13:58 |
|
If anybody was interested in my arduino rust project, there's a new amazing guide on the best toola/libraries to use for it: http://blog.japaric.io/quickstart/ I'm busy rewriting all of my manual cludges to use this stuff.
|
# ¿ May 1, 2017 21:29 |
|
QuietMisdreavus posted:How long have you been out? Here's the full list of changes by version, but picking some highlights from the last several versions: I think impl trait is my favourite of the new features, just because it makes working with unboxed closures and iterators so much easier.
|
# ¿ Jun 29, 2017 07:50 |
|
Ralith posted:I don't think that's stable yet. Is it close? Not at all. There's still implementation bugs and lots of open design questions. However my Rust is entirely playing around with hobby projects, so I am fine with always using nightly.
|
# ¿ Jun 29, 2017 20:38 |
|
Ralith posted:I don't have any experience with Rocket, but I hardly ever find myself reaching for macros when writing Rust. First-class functions, closures, traits, and polymorphism go a long way. Which is good, because macros 1.0 really do suck for any but the most trivial uses. Custom derive (stable, demonstrated nicely by serde) and the upcoming macros 2.0 (which gives you full-powered source-to-source transforms) are a lot nicer, fortunately. The only things that I define my own macros for are 1) early returns, like: code:
code:
gonadic io fucked around with this message at 23:38 on Jul 2, 2017 |
# ¿ Jul 2, 2017 23:35 |
|
Generalising the return type of main just got merged: https://github.com/rust-lang/rfcs/blob/master/text/1937-ques-in-main.md
|
# ¿ Jul 18, 2017 07:33 |
|
xtal posted:The cost of calling unwrap or expect once is not worth this oddity which is unique across all programming languages I've used. If you keep defining main() { then nothing will change.
|
# ¿ Jul 18, 2017 17:59 |
|
I think the need for macros will go down a bit once const_fn is stable. Certainly that's what I mostly use them for myself.
|
# ¿ Aug 14, 2017 11:47 |
|
I've loved intellij's support but it's not entirely cargo free no. Still a million times better than vs code and RLS though.
|
# ¿ Feb 12, 2018 10:14 |
|
I got it working with (ignore the type annotations, they're not needed)code:
1) the array! macro in f needs its arguments to NOT be references (it's an array of floats, not an array of references to floats). Note that you copy d's members here for that to be the case. 2) the argument to dot always needs to be a reference (that's how it's defined, so that you don't need to copy or own stuff), 3) the arguments to subtract need to both be references since they both come from the borrowed function parameters. You could instead do "D.dot(&(node.a.clone() - cam.c.clone())) OR make the function own its arguments like "fn project(cam: Camera, node: Node)" if you don't use them again after passing to this function. I think ".map(move |node| project(camera, node)).collect()" would let you make this function take its arguments by value if you don't use the camera anywhere else. In short ndarray wants everything by reference except when constructing an array initially. This is done because ideally you want each float to be allocated once somewhere and then manipulated with read-only references. Doesn't make much difference for f64's but would with bigger types.
|
# ¿ Apr 22, 2018 17:14 |
|
Dominoes posted:Any advice on separating dependencies for WASM and binaries? I have a project that both runs locally with main.rs, and can be used as a library for WASM/JS using lib.rs. When I try to compile WASM, one or more of the dependencies that I need to run locally, but not web, prevents the WASM compilation. If I remove the crashing lib from Cargo.TOML temporarily, main.rs can't find it, which then prevents the compile. It appears that renaming main.rs, and commenting out the failing dependency works. Is there a more elegant solution? Another option would be to split the main.rs file into a tiny new crate - you have a library that works with both and a binary that only works locally. If you make one crate that's only the library and one that's only the binary then you stop mixing up your concerns. There are two downsides: more boilerplate since you now have two crates to maintain, and your main now can't access internal stuff from the lib.
|
# ¿ May 21, 2018 13:11 |
|
Linear Zoetrope posted:Blugh, the RLS being borked is killing me right now. Can't use old versions because I migrated to some 1.26 features. Use intellij with its builtin rust support, the RLS was never good. Maybe in the future it will be.
|
# ¿ May 24, 2018 20:57 |
|
Most language features in all languages would require workarounds if they didn't exist
|
# ¿ Sep 27, 2018 23:29 |
|
Dick Nipples posted:I mean sure.... but then you have to pass it around. Lazy_static is usually a last ditch effort thing. And regular global mut statics exist for this exact reason.
|
# ¿ Sep 28, 2018 11:34 |
|
Beamed posted:Anyone give the RLS a shot recently? Some of CLion's weirdness has begun getting to me. It has not improved since the 1.0 release. I tried it when vscode's remote and docker stuff came to insider. The biggest issue, by far, that I have with it is: https://github.com/rust-lang/rls/issues/352 i.e. code completion only works on projects which type check on things which have type annotations - there is zero type inference. Although you're right in clion, I'm unable to use any IDE support on structs/functions defined in declarative macros even on the new macro engine. I'm not sure what's going on, I'm sure it used to work before. E: I figured out why this was happening, jetbrains' rust plug can't handle path dependences. Bring on Rls 2.0 gonadic io fucked around with this message at 15:52 on Jul 12, 2019 |
# ¿ Jul 9, 2019 21:29 |
|
mystes posted:OK, I think I may actually hate rust now. I have resorted to replacing lines of code with unimplemented!() and seeing which was invisibly holding onto a borrow, I agree. FWIW if you open an issue complaining that this error message isn't clear it'll be taken seriously. e: and/or just replacing all usages with a clone. Life's too short to zero copy.
|
# ¿ Jul 13, 2019 09:18 |
|
I made https://crates.io/crates/form and https://crates.io/crates/arduino_mkrzero when I was working on embedded stuff, but that's fallen a little down to the wayside compared to messing around with utilities for Dominions 5: a discord bot and then a few other assorted bits here and there. I tried making a twitter app thing, that you'd log into and it'd block people for you but got a bit too turned around. I got oauth2 working, just about, but then got too paralysed about persistency and scaling This is as far as I got: https://github.com/djmcgill/de-list-server gonadic io fucked around with this message at 17:56 on Jul 13, 2019 |
# ¿ Jul 13, 2019 17:53 |
|
ewe2 posted:Just starting to teach myself Rust in VS code but I'm slightly confused by (I'm assuming here) RLS deciding that braces () in a macro are bad and they should be {} ?! Any ideas where to configure that behaviour? What do you mean? I've not seen that before, can you post a snippet or two showing the behavior?
|
# ¿ Jul 18, 2019 14:02 |
|
ewe2 posted:Sure, here's some example code That's pretty loving weird, not at all idiomatic - normal parens are typical there.
|
# ¿ Jul 18, 2019 21:00 |
|
Ralith posted:My comaintainer set up dependabot for Quinn, which has been decently handy for keeping on top of updates. It's free for open source projects on github. rjmccall posted:I know nothing about this specific library, but to guess: the implementation type of a parser either is or is not erased. If it's erased, then at every step you have a Parser that parses a T, and that's all you know; now combinators just take an arbitrary Parser<T>, which is a concrete type which presumably has to have a concrete layout, so producing it for a particular parser implementation might require allocation. If it's not erased, then at every step you have a type P that implements a Parser that produces a T; now combinators have to be parameterized over that type P, which means that the result of applying a ton of combinators basically fully reflects the tree of combinator applications and so grows with the size of the expression. (As I understand it, in Rust this cost can be largely ameliorated with opaque trait types.) This is exactly it yes. If you have a combination of 30 parsers then your type will have 30 parsers (OptP<AltP<CharP, IntP>, ...> etc) in if you don't erase at any step. The "impl trait" feature might help in some cases but it doesn't affect the underlying representation so you still get slowdowns like in this issue: https://github.com/rust-lang/rust/issues/61324 Boxing adds a runtime cost so is not the default, even if it's more convenient.
|
# ¿ Jul 27, 2019 18:25 |
|
Progressive JPEG posted:If anyone needs to do Rust cross-builds, use cross. It has Docker as a prerequisite, but it only took 5-10 minutes to be up and running with building arm7 binaries for a raspberry pi. I found cross was a good starting point, but its docker images are pretty out of date. Did a bunch of building for windows at work and had to customise it a bit
|
# ¿ Oct 6, 2019 10:39 |
|
In my experience the error messages usually tell you which trait to pull in, was it not doing it for you? I still use jetbrains myself, rust analyser is a whole lot better than RLS 1.0 but still not yet there IMO.
|
# ¿ Dec 7, 2019 10:08 |
|
drainpipe posted:I'm starting to learn Rust, and I have a question about using async with threads. I'm writing a program that has multiple threads, each making different http requests. I'm using the reqwest crate for this, which uses async functions. If I try to spawn a thread, I'd need something like an async closure, which is apparently still unstable. Should I just turn the threads to async tasks? There's no reason why I couldn't, but I just wanted to touch on a greater variety of stuff in Rust. Do you specifically need closures or can you make normal async functions and then pass those? I know rust (and futures 0.1) reasonably well but I haven't had the opportunity to spend too much time on futures 0.3 or async proper yet unfortunately.
|
# ¿ Feb 24, 2020 01:02 |
|
You could also just use tokio::spawn with a threaded executor and call it a day if you don't care about having exact control.
|
# ¿ Feb 24, 2020 09:25 |
|
Progressive JPEG posted:How interchangeable is Tokio with other Rust async stuff? Been using Tokio types so far but every so often I encounter something that doesnt, and it ends up being a huge pita to try integrating across them. Sounds like you answered your own question tbh. Async-std and tokio are generally incompatible (and competing) ecosystems. Both ecosystems are based on the same Future type (so that part IS compatible) but all the stuff built on top like streams and timers and stuff isn't. So of the 3 crates you listed, 1) is incompatible with tokio, 2) is async-std itself, 3) is the futures crate which is used for both tokio and async-std
|
# ¿ Feb 29, 2020 00:23 |
|
If a type implements the trait std::marker::Send then it's safe to send between threads i.e. contains no thread local state. Your async function's error is Box<dyn std::error::Error> i.e. the only thing we know about it is that it implements std::error::Error so there's no indication that it is Send. Tokio's spawn uses a threaded executor so any futures it executes must implement Send - a future that returns a Result<(), Box<dyn std::error::Error>> is not Send and so you get the compile error. A few possible fixes, from easiest to hardest: 1) change your error type to Box<dyn std::error::Error + Send>. This way you inform the compiler that the errors you're producing are thread safe. This is what you should do for a little test/toy program. Here's your snippet with just that one change working. 2) putting Box<dyn std::error::Error + Send + Debug + Clone + Sync + 'static> everywhere starts to get annoying real fast so consider using a error library. Anyhow is currently the best one for executables (everything gets cast into an anyhow::Error supertype which you can log/print as needed and downcast if you really need) and ThisError is the best one for libraries (your functions return an enum that you can pattern match on easily) 3) use tokio's single threaded local executor. Probably don't do this unless you really do have a non-thread-safe error. e: and the reason that "If I replace line 9 with let _ = bar().await or let x = bar.await().ok(), then it's fine" worked was because you were no longer propagating that non-Send error type through the Future and were instead discarding it or converting it to None. gonadic io fucked around with this message at 02:22 on Mar 12, 2020 |
# ¿ Mar 12, 2020 02:15 |
|
drainpipe posted:Ok, if I remove the foo call afterwards, it compiles fine. From reading what you've written, I'm thinking that since there is no Future to be executed afterwards, it knows that the possible non-Send error will not be propagated, so it's fine. So basically I can't have any async function return a non-Send value unless it's at the end of a block? code:
I guess my answer is: So basically you can't have any async function return a non-Send value unless it's at the end of a block and it's not returned from the block (or as long as it is otherwise discarded). In practice like I said you're unlikely to actually have non-Send errors. As for why the rules are slightly inconsistent and you are allowed non-Send errors as long as you never put yourself in a position where you might be able to look at it, well it's complicated but it's due to how async functions are compiled into state machines - as long as the state machine's states never have to hold a non-Send value it's fine. You can have non-Send values appear during transitions if they're not retained in the state. gonadic io fucked around with this message at 03:17 on Mar 12, 2020 |
# ¿ Mar 12, 2020 03:13 |
|
drainpipe posted:I'm running into another borrow checker problem. I have a struct that owns two receivers (using Tokio still), and I'd like to use select to poll both of them and react accordingly. However, checking a receiver is a mutable borrow of self so the borrow checker isn't allowing me to do this. This seems like a pretty basic thing to want to do, but I can't see a way to sidestep this without arranging my code so that the struct does not own the receivers. Is that the only solution? If you have a mutable borrow (or just by-value) to a struct you're allowed to mutably borrow each of its fields independently and simultaneously. Plus there's tokio select macro designed to do this so I'm not really sure what you mean. The rust playground has tokio if you want to try putting together a minimal example.
|
# ¿ Mar 14, 2020 18:23 |
|
drainpipe posted:Oh, I see. I actually had one of them checked via a method since I wanted to do some postprocessing. Calling the method caused it to borrow the entire struct, which must be what tripped the borrow checker. A fix would then be to put it in a struct of its own. Thanks! Yes, wanting to mutably borrow only one field of a struct and then pass the rest of the struct somewhere else is a common scenario but is unfortunately impossible* to reuse the struct itself. The easiest way is to make all the grouped fields in a second struct so you have like code:
*: well you can start messing around with Rc and Arc and Cell and Refcell etc but that's not what I'm talking about gonadic io fucked around with this message at 21:29 on Mar 14, 2020 |
# ¿ Mar 14, 2020 21:17 |
|
I don't believe stream.read can be reset half way through like that - since my understanding of how select! works is it calls poll on its futures and then if one returns Ok(value) then it executes that branch. If rx.recv returns a value then steam.read.poll is never called and any incoming bytes stay in the buffer. If stream.read.poll is called, starting the read, then in the next iteration recv finishes quickly, then stream.read.poll will either finish its future or still not be ready. As for fixing this problem, could you get a minimal working example? There's too little context to make too much sense of it for me.
|
# ¿ Mar 23, 2020 21:48 |
|
Consider something like https://docs.rs/tokio-util/0.3.1/tokio_util/codec/struct.Framed.html
|
# ¿ Mar 23, 2020 23:37 |
|
Do you actually need the trait Display specifically? I often just make a write_foo method which, as a standalone function that just takes an SocketAddr as a parameter, doesn't care about orphan rules.
|
# ¿ Apr 17, 2020 10:12 |
|
To make a Display wrapper is probably the "better" approach so I would still use it e.g. in a big codebase with lots of coworkers who might accidentally use the display impl. And then there's stuff like Eq, Ord, and Hash that you usually do just have to make wrappers for. And as for (De)Serialise...
|
# ¿ Apr 18, 2020 13:08 |
|
Just as a quick answer, self-referential structs are only possible with the newish Pin infrastructure: https://doc.rust-lang.org/std/pin/index.html I don't really know how it works but if you try and fail I could take a look. It is a bit complicated though, so maybe indices is just an easier quicker bet. Also another way to do similar stuff is to not own the objs yourself but to store that somewhere else using e.g. a central memory arena or something. I believe this is the approach that e.g. the Specs entity container system (used by the Amethyst game engine) does to allow you to push and pull data while having lots of references to them in different places.
|
# ¿ May 25, 2020 19:55 |
|
code:
This prints true and true. The answer is that what you're actually matching on is (Foo::Bar(ref p1), Foo::Bar(ref p2)) i.e. references to p1 and p2, which are references to a. You can't move p1 and p2 directly into your ptr::eq when you're matching on the references of b and c (but explicitly dereferencing the outer pointer copies them in). Rust used to not insert refs into matches for you, then people got a bunch of errors and threw ref into odd places until it worked. So now rust does implicitly insert them in for you leading to situations like this. e: you can make things even clearer by changing your printlns to e.g. code:
gonadic io fucked around with this message at 20:10 on May 27, 2020 |
# ¿ May 27, 2020 20:06 |
|
I would really recommend avoid using raw pointers for your memory arena thing. Better to use std::rc::Rc imo, way WAY less chance of your unsafe blocks being incorrect and invoking UB. (because there won't be unsafe blocks)
gonadic io fucked around with this message at 20:15 on May 27, 2020 |
# ¿ May 27, 2020 20:11 |
|
It's a common tale. People, myself included, often feel like they're "doing it wrong" but as you say, it's rarely actually needed. Having said that, god I love nom's zero copy stuff. Turning a flat file into a complex AST, all the strings only references into the original one. Luckily my files are small enough I can just read them into memory and don't have to figure out the streaming api.
|
# ¿ Dec 29, 2020 16:57 |
|
|
# ¿ May 16, 2024 00:03 |
|
Gaukler posted:nom is real good. I’m converting a thing from using hand-rolled parsers (because “I’m only going to need to parse a couple things!”) I'm just going off the latest docs.rs docs which are all updated. The functions are significantly better to use than the macros (with one caveat) but they mostly have a 1-to-1 relationship so if somebody recommends one of the macro parsers (except named!()) there's probably a function parser that's the same name and semantics. If you have a specific question just pop it here, not that I'm an expert or anything. The main downside I've found with the function parsers is that you have to write out the type signature which, especially if you're trying to be generic over your error type, can be quite involved. I just gave up for now and monomorphised my errors which is Fine. gonadic io fucked around with this message at 11:46 on Dec 30, 2020 |
# ¿ Dec 30, 2020 10:36 |