|
Result<(), T> is a legit pattern.
|
# ? Jul 28, 2016 17:10 |
|
|
# ? May 15, 2024 04:03 |
|
taqueso posted:I don't want to panic inside my library for a minor error like this. I'm trying to pass the results all the way out to the API boundary so the calling app can see & handle the errors. I considered using Option here, but didn't use it for 2 reasons - I read somewhere that it was bad form to use None to indicate an error condition, and also so I don't have to convert the Option to a Result in the calling functions. This is pretty analogous to std's use of None when popping from a collection, so it is mostly for the second reason. I agree that panic! is probably too much. But I wasn't advocating None as Error, I was advocating None as the unit result, where you only get something back if you have an error. For the sort of thing you seem to have here, though, I agree that following the Option conventions of std::Vec is probably a good best-practices guideline. Vanadium posted:Result<(), T> is a legit pattern. You see it in std::fmt and the serialzied, and a few other places, but it's never carried very far in those APIs. taqueso's snippet sort of implies that it's going to carry a Result<(), T> through a few layers to "propagate the error", though, and that's going to induce a nasty ok_or chain all the way up the callstack.
|
# ? Jul 28, 2016 19:03 |
|
Here's the library: https://github.com/jdeeny/rust-chip8 And here's the SDL2 emulator application: https://github.com/jdeeny/vipchip The emulator app is pretty bare. cargo run examples/computer.hex will run it. It will run code from a file filled with hex data like you get from Octo or a binary file. Escape to exit. A few weeks ago I had everything working to about the same point as this, but that time it was all one monolithic app with no tests. This is the result of trying to split it into the UI and a library to handle the core chip8 simulation task. I've gone round in circles on more than a few design decisions in the library. I used locks on the state data that I thought the UI would want to have fast access to, and channels for the other stuff. Honestly, I just wanted to try both. It sure seems like locks will be faster, but it intrudes on the code everywhere. Curious about a more ergonomic way to do this. I started with the Operations as classes implementing a trait, but there was a ton of boilerplate so I switched to Enums. I found out about default implementations, so maybe I should switch back. I really don't like how the enums have un-named data. Especially now that I have some operations with flags, it is really ugly. Can I do Src/SrcKind and Dest/DestKind in a better way? Maybe I need a macro. Known problem: SimulatorTask needs a run function that will execute instructions autonomously, without the other thread stepping it. Right now it is sort of pointless.
|
# ? Jul 29, 2016 01:56 |
|
QuantumNinja posted:You see it in std::fmt and the serialzied, and a few other places, but it's never carried very far in those APIs. taqueso's snippet sort of implies that it's going to carry a Result<(), T> through a few layers to "propagate the error", though, and that's going to induce a nasty ok_or chain all the way up the callstack. Yeah that's what try!() is designed around! Putting error results in the Err variant of Result!
|
# ? Jul 29, 2016 08:15 |
|
Is the untyped Arena dead? I seem to only be able to get TypedArena on nightly.
|
# ? Aug 5, 2016 01:00 |
|
Jsor posted:Is the untyped Arena dead? I seem to only be able to get TypedArena on nightly. Looked for the change in github - I think it got moved to the any-arena crate https://github.com/rust-lang/rust/commit/e2ccc4f744b93f89666fe4c8828905297bb76178#diff-d83049850151ade6fa9c57a0545754ad https://crates.io/crates/any-arena
|
# ? Aug 18, 2016 15:53 |
|
I wanted a case-insensitive equivalent of tag_s! from nom, so I wrote this one. Is this efficient? Can it be done in a better way? https://github.com/jdeeny/nom/commit/ef00efa647f77cfd4486c7db50ea2819c81f639d Rust code:
taqueso fucked around with this message at 16:56 on Aug 18, 2016 |
# ? Aug 18, 2016 15:56 |
I'm a little unsure how to clear up this borrowing pattern. I have a Graph object and I want to modify (for the sake of memoization), but I've got a bit match happening in it.code:
Jo fucked around with this message at 06:27 on Aug 19, 2016 |
|
# ? Aug 19, 2016 06:22 |
|
I think it's that you're trying to use self while it's borrowed (which it is because you're borrowing one of its fields). Can you pull out the node as a value whose lifetime isn't dependent on self, so that self can be un-borrowed by the time you want to call a method on it?
|
# ? Aug 19, 2016 06:43 |
rjmccall posted:I think it's that you're trying to use self while it's borrowed (which it is because you're borrowing one of its fields). Can you pull out the node as a value whose lifetime isn't dependent on self, so that self can be un-borrowed by the time you want to call a method on it? Doesn't seem like it. When I pulled the node as a value it just complained about moving out of the indexed context. I guess another way of asking would be, "How the hell do I handle mutable borrows with recursion?" EDIT: I can use separate hashmaps to memoize, but it's not a pretty solution. Jo fucked around with this message at 06:55 on Aug 19, 2016 |
|
# ? Aug 19, 2016 06:49 |
|
In order to appease the borrow-checker, you're going to have to prove that your recursive call can't invalidate nodes or visit the same node re-entrantly. So first you should think: how do I know that that's actually true? And then you should think: how on earth can I convince a relatively simple scope-based static analysis that that's true? If your graph is really arbitrary, your node references are probably reference-counted (or externally owned?), and you probably have some sort of visited set to prevent re-entrance. That visited set is what gives you correctness here, and it makes sense that it should be the thing offering you a mutable reference when it proves that you're not accessing a node re-entrantly. Its internals will probably need to be unsafe to make that work. If this is really a tree, with child nodes held with unique ownership at different places in the tree, then the basic problem is that there's no reason your arbitrary method call on self couldn't invalidate the node's children. Maybe you can just pass the index of the node down to the call instead of trying to pass a reference. The other approach, perhaps more promising, is to try to set up your memoization caches so that they can be modified given just an immutable borrow of a node. I'm pretty sure there are library types designed for that.
|
# ? Aug 19, 2016 07:20 |
|
Jo posted:Doesn't seem like it. When I pulled the node as a value it just complained about moving out of the indexed context. That error happens because indexing technically returns a value, but you can't move out of a reference. (There are a couple of ways to fix that particular error https://is.gd/nj33No ). What I think rjmccall was suggesting was something like: code:
If you're memorizing, it might make sense for get_derivative to borrow self immutably and wrap the hashmap(s) in a RefCell. If the semantic value of the graph isn't changing, interior mutability may be justified. syncathetic fucked around with this message at 07:23 on Aug 19, 2016 |
# ? Aug 19, 2016 07:21 |
|
I went to a Rust meetup a couple days ago. Seven people showed. One guy was a C guy asking questions who seemed to have shown up with no idea what Rust was for. He asked what is it for. He also asked if it had as good a prepocessor system as the C preprocessor. Another seemed to know quite a bit about Rust, and other things. Another guy spent the entire time editing some Medium post. We spent the time doing an exercism.io exercise where an object has a mutable String field. But, as a result, I wrote my actual first self-originated line of Rust code, so there's that! Edit: On that note, is there any way to make a match pattern redundantly declare the type of a variable? Take for example code:
sarehu fucked around with this message at 08:09 on Aug 19, 2016 |
# ? Aug 19, 2016 07:43 |
|
sarehu posted:I went to a Rust meetup a couple days ago. Seven people showed. Where was your meetup? I don't think you can do redundant typing inside the match pattern. At least, I couldn't make it happen the other day.
|
# ? Aug 19, 2016 15:27 |
|
San Diego.
|
# ? Aug 19, 2016 18:12 |
|
sarehu posted:Edit: On that note, is there any way to make a match pattern redundantly declare the type of a variable? Take for example The feature you're looking for is called "type ascription": https://github.com/rust-lang/rfcs/issues/354
|
# ? Aug 21, 2016 15:03 |
|
taqueso posted:Here's the library: https://github.com/jdeeny/rust-chip8 I'm still trying to wrap my head around memory and all that; I'm used to Python and Haskell, and don't know any C or C++, but Rust seems neat (and this emulator project is cool; I've never done anything with systems code at all and it's very educational). I'm sure mine is a monstrosity of non-idiomatic Rust, but oh well. It reads instructions and does things, though I don't have any drawing implemented so if it's actually doing the right things. Can someone answer my extreme noob question? This feels like it should be valid Rust code:
Another question: is there a way to get Cargo to update rustc? They release a new stable every 6 weeks, and so if I want to keep my local updated, how do I do that except uninstall old versions and install the new one (Windows)? Ghost of Reagan Past fucked around with this message at 02:24 on Aug 22, 2016 |
# ? Aug 22, 2016 02:11 |
|
This may be foreign since you're not used to languages with pointer/reference/value distinctions like C++ or Go , but since the function takes a reference to a u32, it can't accept x since it is a u32. You need to give it a reference to a u32. You can do this with the & operator.code:
quote:note: expected type `&mut u32` means. I'm not sure why this was working with a struct, it shouldn't unless the autoreferencing rules on structs are more lenient than I thought (usually auto-(de)referencing only happens in a few places like method calls).
|
# ? Aug 22, 2016 02:17 |
|
Oh I forgot to add the &mut when I passed the function in the example. It was in the original code so I edited it above (this is just a toy example, I just ran against it earlier). This is the error I get code:
Ghost of Reagan Past fucked around with this message at 02:32 on Aug 22, 2016 |
# ? Aug 22, 2016 02:27 |
|
You need to do this:code:
|
# ? Aug 22, 2016 02:35 |
|
It was complaining that I was trying to change a reference (that much I understood). I'm borrowing it via the reference, but if I want to do something to the thing, I gotta make sure I'm talking about the thing, not the reference. This makes sense now.
|
# ? Aug 22, 2016 02:42 |
|
Asymmetrikon posted:It worked on a struct previously because "a.b" can be implicitly dereferenced to "(*a).b" if need be - this is so operations on references to structs aren't needlessly verbose, since they're very common. Auto-(de)referencing can get really silly if you look at its unsugaring closely, I noted in a Stack Overflow answer recently that if you have the type code:
(It's even worse than this because iter() is actually implemented on the slice intrinsic type and Vec merely implements Deref<Target=[T]>, but it wasn't important to the question) Linear Zoetrope fucked around with this message at 02:49 on Aug 22, 2016 |
# ? Aug 22, 2016 02:45 |
|
sarehu posted:I went to a Rust meetup a couple days ago. Seven people showed. I'll be honest, the San Diego Rust meetup is a bit more of a study group at the moment. It's a bit hard to keep the topics both digestible to newbies and neckbeards so we started doing those koan-like exercism-like things to get people off and running faster while letting the more seasoned Rust users being able to give some code review and commentary. It's something I saw from the LA Rust Meetup. Only, they split into two groups and have one be a hack night on their Stockfighter API because their group tends to be larger. If you have some suggestions, we would be happy to hear them.
|
# ? Aug 22, 2016 03:51 |
|
Well I'm going back, which is something I can't say about Haskell or ACCU meetups I went to. Maybe I'll sperg about the mutex API next time.
|
# ? Aug 22, 2016 04:38 |
|
Ghost of Reagan Past posted:Another question: is there a way to get Cargo to update rustc? They release a new stable every 6 weeks, and so if I want to keep my local updated, how do I do that except uninstall old versions and install the new one (Windows)? https://github.com/rust-lang-nursery/rustup.rs/ will be the offical way to deal with this soon enough, i haven't tried it on windows yet though, but it has support for it.
|
# ? Aug 22, 2016 10:56 |
|
tinaun posted:https://github.com/rust-lang-nursery/rustup.rs/ will be the offical way to deal with this soon enough, i haven't tried it on windows yet though, but it has support for it. Just installed it, works fine on Windows but if you have MSVC installed you may or may not want to explicitly tell it you want the gnu compiler depending on what libraries you use. It's also better if you generally use cmd/powershell/msys2 instead of just building everything from VS Code or whatever since it's fundamentally a command line application.
|
# ? Aug 22, 2016 11:26 |
I want to do an SF meetup. How'd you find yours? Meetup.com?
|
|
# ? Aug 22, 2016 22:19 |
|
Looks like they have a bay area meetup once a month or so: https://air.mozilla.org/bay-area-rust-meetup-july-2016/
|
# ? Aug 22, 2016 23:05 |
|
What's the best GUI api for Rust right now? And by "best" I mean "least likely to be broken." On Linux or Windows. Edit: Like all I want to do is paint on a window. Edit: Got gtk-rs examples working so I'll run with that. sarehu fucked around with this message at 00:06 on Aug 26, 2016 |
# ? Aug 25, 2016 23:45 |
|
I went to another Rust meetup. The pizza got delivered early so it was cold, had to be reheated. Some dude showed up with a 1600x1200 T60p, then another dude pulled out some old 4:3 X-series tablet. I had a VPCZ1 Vaio Z, and some other guy had a Dell. A big improvement from the everybody-but-me-uses-Apple situation. crazysim forgot his laptop (self-owned!).
|
# ? Sep 8, 2016 07:06 |
|
Hmm, that reminds me. I should go and check out rustup.rs on Windows. I wonder how well some work Rust CLI utilities will fare in a MinTTY shell.
|
# ? Sep 8, 2016 09:34 |
|
I think Rust's terminal utilities are more targeted for MSYS2 or cmd/Powershell than Cygwin.
|
# ? Sep 8, 2016 09:37 |
|
Day 1 of rustfest was pretty cool but I'm too lazy to go back to day 2 for the workshops, rip.
|
# ? Sep 18, 2016 08:50 |
|
I've been reading that book about Rust and Linked Lists, and they give the following example distinguishingcode:
code:
Is this really true? It doesn't seem like the former should be immune from a null pointer optimization, though it would be more complex to infer.
|
# ? Sep 23, 2016 03:06 |
|
The former is not immune, I think the implementation is just too dumb for it. Another example is that Option<Option<bool>> could use 1 byte.
|
# ? Sep 23, 2016 04:20 |
|
I don't think its possible for the first case to be null-pointer optimized. Consider https://is.gd/HtdE2R . What value/address does list_end return if the final Empty value isn't on the heap? As I understand it, Option<bool> having a size of 1 byte might be a breaking change for unsafe code. It would mean that you can no longer blindly memcpy a value onto a &mut bool for fear of clobbering the Option data in the higher bits. I could be wrong though. The exact rules for what is valid unsafe code aren't exactly clear.
|
# ? Sep 23, 2016 08:36 |
syncathetic posted:I don't think its possible for the first case to be null-pointer optimized. Consider https://is.gd/HtdE2R . What value/address does list_end return if the final Empty value isn't on the heap? Maybe I'm misunderstanding something here, but I think the idea is that you would represent List::Elem as a (i32, non-null address), and List::Empty as (32-bits-of-whatever, null). That way you can avoid having another byte in each List for the enum discriminant, because you can tell whether it is List::Empty or List::Elem by the value of its second field. So to answer your question the final List::Empty value would still be on the heap and you can still take it's address, because all the null-pointer optimization does is make the representation of each List more efficient. As for the unsafe stuff, my guess is that memcpying into non-C-like enums is undefined behavior, because the layout of non-C-like enums is undefined. But I'm not totally sure about that.
|
|
# ? Sep 23, 2016 20:17 |
|
A memcpy into a bool should be well-defined, assuming the source holds a valid bool value. Something like 2 would not be a valid bool value. If you have a single payload, and its representation has what we call in Swift "extra inhabitants" — bit patterns that aren't considered legal values — then you can use those inhabitants for the other cases, so that representations of the payload are exactly representations of the enum. That works for both shared and exclusive access without any impositions on the ABI. For example, if the single payload is a pointer, there are a large number of bit-representations that can be assumed to not be legal (at least in a sufficiently high-level language). The most obvious is 0, the null pointer, but it's probably reasonable to say 1, 2, etc. are also available, up to at least a page; and if the pointer has to be aligned, then everything not aligned is available, too. If you have multiple payloads, even of the same type, that isn't good enough; you really need spare bits in the representation to store a discriminator between those cases. If the ABI for the payload type says that those spare bits have to have some expected value, then you might be in trouble. For example, if you have an enum with two cases that are 2-byte aligned pointers, you can theoretically use the low bit to distinguish cases, but clients handed a pointer will expect those bits to be zero. Now, if everything accessing the case knows exactly what it's working with, then you can be arbitrarily smart about these things; you just generate code to ignore/set the discrimination bits whenever you have an access. Unfortunately, Rust allows you form a reference to a payload and pass it off as a normal reference. Unless we're going to specialize everything that might get that reference — in general not possible — then we really need the reference to refer to memory that follows the normal ABI for the payload type. If we know that we have exclusive access to the enum, then we can form this reference by clearing the discrimination bits and then putting them back when we're done. That might be inefficient, but it would work. But Rust lets you make a shared reference to the payload from a shared reference to the enum, and there could be other references to the enum, so no dice. If the lifetime of the payload reference can be shorter than the lifetime of the enum, then we can just copy to a temporary with the bits cleared and make a reference to that. But that's not the rule in Rust, so no dice again. You can make it part of the ABI for the payload type that you ignore and preserve spare bits. That might be a huge penalty, though. In our pointer example, we'd have to mask on every load of a reference to a pointer, and we'd have to mask when storing a value as well. For bool, we'd have to make sure we always touched exactly the low bit; we couldn't just load the bool and compare it against zero. So probably you're stuck with using a separate tag discriminator. I don't know how close to this ideal Rust gets. I know Swift has limits to its logic that fall well short of it.
|
# ? Sep 25, 2016 01:15 |
|
1.12 is out, and I am irrationally excited about the new compiler errors that are actually understandable: Thanks Elm, for kicking all the other language maintainers in the butt about this.
|
# ? Sep 29, 2016 20:02 |
|
|
# ? May 15, 2024 04:03 |
Arcsech posted:1.12 is out, and I am irrationally excited about the new compiler errors that are actually understandable: Nice! I didn't even know this was in the pipeline.
|
|
# ? Sep 29, 2016 20:18 |