|
Don't think there's a great way. In C you'd just take an out-pointer and then just return a flag, but that's not gonna look particularly nice in either Rust or C#.
|
# ? Mar 13, 2016 23:36 |
|
|
# ? May 15, 2024 03:37 |
gonadic io posted:Is this a reasonable way to pass an optional value over a FFI boundary? Passing a (nullable) pointer and then having the C# code calling another function to free it seems like lots of pain. That seems pretty reasonable to me--in fact, I think that that's how an Option would be laid out if you put #[repr(C)] on it. (The piece I'm not sure about is whether it would use a bool as the discriminant.)
|
|
# ? Mar 14, 2016 02:15 |
|
I have a weird and pretty gross function that I can't help but think "surely there must be a better way!" about :code:
As ever, the context is here.
|
# ? Mar 19, 2016 01:31 |
|
Why not this?code:
|
# ? Mar 19, 2016 05:41 |
|
Perfect, thanks. e: is there a better way to represent once-assignable nullable variables than Cell<Option<_>>? The type allows for re-assignation but I will never do that. I suppose I could always just put a wrapper around it. gonadic io fucked around with this message at 11:26 on Mar 19, 2016 |
# ? Mar 19, 2016 10:52 |
gonadic io posted:Perfect, thanks. Well if you really want to get fancy, you could do something like what hyper (an http library) does for Responses, and verify this at type level at compile time. Here's an example of what that might look like for this case. edit: To be a bit more explicit (and maybe save you some reading), the idea is to make a Variable type, which is parameterized over a type that can be either Unassigned or Assigned. Then you implement an assign() function for Variable<Unassigned>, which consumes the Variable<Unassigned> and returns a Variable<Assigned>. Because of this consuming, you can guarantee that a Variable can be assigned at most once, and because there is no assign() function for Variable<Assigned>, you can guarantee that you can't re-assign a variable once it has been assigned. VikingofRock fucked around with this message at 07:04 on Mar 21, 2016 |
|
# ? Mar 21, 2016 06:49 |
Actually now that I think about it a little more, you probably want this to work at run-time, not compile time. You can either use the above approach and Any to do run-time type checking, or you could just write a wrapper around an Option (which is a lot simpler, but loses the ability to do compile-time checking). I guess it depends on your use case (I haven't really read through your code).
|
|
# ? Mar 22, 2016 00:39 |
|
VikingofRock posted:Well if you really want to get fancy, you could do something like what hyper (an http library) does for Responses, and verify this at type level at compile time. Here's an example of what that might look like for this case. Though the immediately obvious problem that jumps out at me with this scheme is it makes loops problematic if you need to assign in those. code:
|
# ? Mar 22, 2016 02:21 |
Jsor posted:Though the immediately obvious problem that jumps out at me with this scheme is it makes loops problematic if you need to assign in those. It's not just in loops--you can't modify x in place because when you assign you change the type. So when you modify it you need to do something like what I did in my linked example code on like 42. That will work in loops (so long as you only assign once), but yeah it's pretty awkward. So maybe writing a wrapper is nicer anyways. It is a neat trick though--I was blown away when I saw it in hyper. edit: slightly better example of loops: http://is.gd/6i8ELg VikingofRock fucked around with this message at 04:19 on Mar 22, 2016 |
|
# ? Mar 22, 2016 04:14 |
|
Oh yeah, you can do that. But I mentioned loops specifically because for most other constructs you can use a let rebind pattern:code:
I don't know if it's a good pattern, but I use it semi-frequently to create an "x prime" variable where you're deriving a value from some earlier value that's never going to be used again. Linear Zoetrope fucked around with this message at 04:37 on Mar 22, 2016 |
# ? Mar 22, 2016 04:33 |
Jsor posted:Oh yeah, you can do that. But I mentioned loops specifically because for most other constructs you can use a let rebind pattern: I often do something similar to "freeze" a variable. It's useful when there is some non-trivial initialization to a variable, but then the variable will not be mutated after the initialization. Like this: code:
|
|
# ? Mar 22, 2016 05:05 |
|
Hi all, thanks loads for your previous help. I'm having another fight with the borrow checker again though. In short, what I want to do is this: code:
Full context is here. gonadic io fucked around with this message at 23:47 on Mar 22, 2016 |
# ? Mar 22, 2016 23:29 |
|
I think your problem comes from Iterator::map being lazy. If the the code in your post could be executed, the code inside the closure would never run. If you want to append something to vec after the closure is evaluated and still use its result, you need to do something like:code:
|
# ? Mar 23, 2016 00:15 |
|
Yep, that was exactly it thanks. So even though the closure is lexically out of scope, because the iterator hasn't been evaluated yet the compiler still considers it to be in scope for the purposes of borrowing? E: I think I get it now - the iterator borrows the reference because the closure does, and the iterator is still in scope (regardless of how much it was evaluated) which is causing the problem. gonadic io fucked around with this message at 10:24 on Mar 23, 2016 |
# ? Mar 23, 2016 09:39 |
Yup, you got it (in your edit).
|
|
# ? Mar 23, 2016 18:35 |
|
Are people happy for me to continue asking this stuff here? I don't want to dominate the thread, I guess I could go to the terrible programmers yospos thread or the rust IRC instead. Speaking of, I'm running into a situation with the FFI that I'm pretty sure is down to me using it incorrectly. My Rust code looks like: code:
test deregister start from unity deregistering 0 test deregister end However in other FFI functions, i.e. code:
about to deregister in other function rust callback deregister_voxel 0 <end of log> So from what I can see the callback works fine when called initially, but when the address is called again later it crashes with Thread 0 Crashed:: CrBrowserMain Dispatch queue: com.apple.main-thread 0 ??? 0x00007fff5fbfc860 0 + 140734799792224 1 libcarved_rust.bundle 0x000000011eeef77c svo_set_block + 28 I must say that debugging FFI is really quite frustrating because Unity just crashes with no message, the "send to Apple?" window contains the message above and then the Unity log contains the tracing statements. So how should I keep these functions around and allow them to be called just given the pointer to the ExternalSVO. Full context (including the definition of ExternalSVO) is on my github. gonadic io fucked around with this message at 20:40 on Mar 27, 2016 |
# ? Mar 27, 2016 20:23 |
|
I think the Box is getting dropped as soon as svo_create exits, meaning the memory is freed. This is why it's working the first time -- there's really no guarantee how many times it will work, but you're probably getting lucky and then suddenly the memory gets corrupted and everything is terrible. You probably also need to do something like:code:
code:
Linear Zoetrope fucked around with this message at 20:51 on Mar 27, 2016 |
# ? Mar 27, 2016 20:42 |
|
Edit: The box doesn't get dropped because transmute takes it by value, and then internally forgets it. deregister_voxel is a reference to a closure that closes over the deregister_voxel_extern pointer on the stack, borrowing it. So the closure reference and also the closure itself are basically broken once you return from svo_create. I assume you hide the lifetime problems from the borrow checker by transmuting to something with 'static lifetime. If you want to use closures here, they should capture all their state by move (move |foo| { ... }), and then you probably gotta box them into a Box<Fn(...) -> ...>. Alternatively maybe you can store all the relevant state in that struct you return, including those function pointers you take, and just impl methods on the struct instead of putting closures in? I dunno. I'm happy to see Rust chatter somewhere on CoC even if I can't answer questions very well.
|
# ? Mar 27, 2016 20:47 |
|
Oh yeah, it's definitely the closure, I didn't even notice he was closing over anything, I thought he was using the &Fn as a straight up alias for extern fn.
|
# ? Mar 27, 2016 21:00 |
gonadic io posted:Are people happy for me to continue asking this stuff here? I don't want to dominate the thread, I guess I could go to the terrible programmers yospos thread or the rust IRC instead. Definitely keep posting here, I'm learning a lot from thinking about the issues that you are presenting and people's responses to them. Also the Rust IRC is a fantastic resource. If you post a question here and no one answers it, you should ask IRC (and then post their response here so we can learn from it too).
|
|
# ? Mar 27, 2016 22:18 |
|
I moved the closure to the internal function like so:code:
I tried a few times without the intermediate (seemingly no-op) closure there by casting the extern "stdcall" fn to both &Fn(...) -> u32 and Box<Fn(...) -> u32> and then passing them directly to set_blocks which expects a &Fn but neither worked. I got either carved_rust.rs:43:13: 43:35 error: the trait `core::ops::Fn<(nalgebra::structs::vec::Vec3<f32>, i32, svo::VoxelData)>` is not implemented for the type `extern "stdcall" fn(nalgebra::structs::vec::Vec3<f32>, i32, svo::VoxelData) -> u32` [E0277] or carved_rust.rs:45:9: 45:44 error: the trait `core::ops::Fn<(nalgebra::structs::vec::Vec3<f32>, i32, svo::VoxelData)>` is not implemented for the type `Box<core::ops::Fn(nalgebra::structs::vec::Vec3<f32>, i32, svo::VoxelData) -> u32>` [E0277] Is the Fn trait implemented for extern "stdcall" fn? Or is it something to do with the missing "-> u32"?
|
# ? Mar 27, 2016 22:56 |
|
I'm surprised that the Fn traits aren't implemented or non-Rust ABI fns, but it looks like that's it. The missing -> u32 is baffling, that frankly looks like a bug in the error message. Edit: Dude says it's because it's an associated type. Ugh. (fwiw people tend to pass closures by value when possible and I don't recall having seen &|...|) Vanadium fucked around with this message at 00:36 on Mar 28, 2016 |
# ? Mar 28, 2016 00:30 |
|
VikingofRock posted:Definitely keep posting here, I'm learning a lot from thinking about the issues that you are presenting and people's responses to them. Also the Rust IRC is a fantastic resource. If you post a question here and no one answers it, you should ask IRC (and then post their response here so we can learn from it too). I definitely like having some activity in this thread, and these are great little discussions/examples to look at.
|
# ? Mar 28, 2016 00:45 |
|
Vanadium posted:(fwiw people tend to pass closures by value when possible and I don't recall having seen &|...|) The reason I'm doing this is that inside set_blocks they get cloned and passed around a whole bunch and so references are needed. I have at least made it so that the public function takes them by value. Honestly I'm hoping that the compiler will optimise away passing the references to every invocation of set_voxel_from. The way I'd do this in Haskell would be to define the sub-function as a closure inside the top-level function which just uses the register and deregister functions in scope but apparently in Rust you can't define recursive closures or fns inside another fn. code:
gonadic io fucked around with this message at 11:00 on Mar 28, 2016 |
# ? Mar 28, 2016 09:55 |
|
I'm trying to install rust nightly on a new VM. The download from static.rust-lang.org is going incredibly slowly - about 0.1% per five minutes. Is there a mirror? If so, how do I specify the mirror for the rustup script? e: Just tried again and it is fixed now. taqueso fucked around with this message at 06:00 on Apr 3, 2016 |
# ? Apr 2, 2016 21:07 |
|
I have lot of fixed sized arrays. Functions that return [T; 8] etc. Working with them is a real pain since neither FromIterator nor ToIterator are implemented for them. I feel that things like map and collect should be available but it's pretty cumbersome converting between slices in order to use these functions. Is there a recommended way for working with arrays rather than slices or should I not bother? e: for a concrete example I have code:
code:
I tried at first to use some flat_maps, but couldn't figure that out and instead am now trying to do it explicitly with pattern matching but still haven't managed yet. Is there a nice way to do this? Should I just use slices and forgo the compile-time guarantees? gonadic io fucked around with this message at 20:18 on Apr 4, 2016 |
# ? Apr 4, 2016 20:13 |
|
Presented without comment:code:
|
# ? Apr 4, 2016 20:46 |
gonadic io posted:I have lot of fixed sized arrays. Functions that return [T; 8] etc. In my experience, working with arrays in Rust totally sucks and will likely continue to suck until they add dependent typing (which is planned, but which seems somewhat far-off). For now, I'd just use slices and save yourself the headache.
|
|
# ? Apr 4, 2016 22:22 |
|
VikingofRock posted:In my experience, working with arrays in Rust totally sucks and will likely continue to suck until they add dependent typing (which is planned, but which seems somewhat far-off). For now, I'd just use slices and save yourself the headache. Wait, what? I thought Dependent Typing was a No Go for Rust. I mentioned it a few times in discussions on the issue tracker, and people mentioned they abandoned the idea because it wasn't a "good fit". Which is a shame because I'd really love it. Especially because first-class dependent typing isn't much work away from a full-on theorem prover which means you can prove some pretty strong guarantees for your implementations. (Unless Dependent Typing is a consequence of HKTs? I feel like people wouldn't have vehemently denied plans for dependent types if that were the case though, given that HKTs are very much in the works, though they don't think they can get it done in 2016). Anyway, I have some questions about traits. Or rather, a few trait requirements: 1. Why does Fn require FnMut require FnOnce? Having FnOnce be the base type almost seems backwards to me, especially since this is roughly akin to Take By Immutable Reference -> Take By Mutable Reference -> Take By Move. It feels like taking by reference should be the "least onerous" to implement. But regardless it feels like all these traits should be disjoint, rather than extensions of each other. (Not that you generally implement the Fn traits yourself anyway). 2. Is there any case where you'd have Sync but not Send? It feels like it would have to be a pretty drat wonky scenario, like some of the OS X Cocoa weirdness where certain calls HAVE to be made on the main thread, but sync wouldn't fix that problem. Linear Zoetrope fucked around with this message at 08:40 on Apr 5, 2016 |
# ? Apr 5, 2016 08:38 |
|
Jsor posted:1. Why does Fn require FnMut require FnOnce? Having FnOnce be the base type almost seems backwards to me, especially since this is roughly akin to Take By Immutable Reference -> Take By Mutable Reference -> Take By Move. It feels like taking by reference should be the "least onerous" to implement. But regardless it feels like all these traits should be disjoint, rather than extensions of each other. (Not that you generally implement the Fn traits yourself anyway). I dunno, this makes sense to me? FnOnce leaves the most freedom to the implementer (can consume environment), FnMut slightly less (can only mutate, not consume) and Fn the least (can only look, not touch). If you have a function that can work by immutable reference, it'll also work if you let it mutate the environment, but not the other way around, so FnMut requiring Fn would make zero sense because then a function can only mutate its environment if it can also work without mutating it. I'm not sure about the Sync/Send thing, I always get confused there.
|
# ? Apr 5, 2016 18:54 |
|
Vanadium posted:I'm not sure about the Sync/Send thing, I always get confused there. On this note, if anyone has a link to a good explanation of Send & Sync besides the official docs, could you post it? Like I get it in theory (Send means it's safe to transfer between threads, Sync means it's safe to access from multiple threads), but I haven't yet quite wrapped my head around it in practice. Like, I see the Arc<Mutex<ActualThing>> pattern a fair bit, but I'd like somewhere that does a deeper dive on an/a few examples. My interpretation of that is that Mutex makes it Sync, and Arc makes it Send, but I'm still not confident I'd know how to use it myself (especially Arc). And I'm coming up on a point in the project I'm working on where that would be super helpful.
|
# ? Apr 5, 2016 19:01 |
Jsor posted:Wait, what? I thought Dependent Typing was a No Go for Rust. I mentioned it a few times in discussions on the issue tracker, and people mentioned they abandoned the idea because it wasn't a "good fit". Which is a shame because I'd really love it. Especially because first-class dependent typing isn't much work away from a full-on theorem prover which means you can prove some pretty strong guarantees for your implementations. (Unless Dependent Typing is a consequence of HKTs? I feel like people wouldn't have vehemently denied plans for dependent types if that were the case though, given that HKTs are very much in the works, though they don't think they can get it done in 2016). Okay so I looked into this a little more, and it seems like full-on dependent typing is pretty controversial, but there is at least a push for type-level numerics (which would make arrays much nicer to work with). Here is the most recent issue about it AFAIK.
|
|
# ? Apr 5, 2016 19:12 |
|
Arcsech posted:On this note, if anyone has a link to a good explanation of Send & Sync besides the official docs, could you post it? Mutexes are both Send and Sync. If you're doing a fork/join where your data will never go out of scope, you can just create a Mutex and send a reference to each thread. The Arc<Mutex<T>> pattern is so you can send a reference to a bunch of threads, return, and continue doing other stuff in the thread that spawned the other threads.
|
# ? Apr 7, 2016 05:12 |
|
gonadic io posted:
I had a chance to try and combine these two functions tonight and am still fighting the borrow checker. SubImage implements Copy and Clone, so why I'm getting reference not living long enough errors even when I tried to clone() everything is beyond me. I get that quads goes out of scope at the end of the closure so any references to it would be invalid, but I'm copying all of the SubImages right? Making it a move closure doesn't help either. Honestly I feel that this entire thing could be done as a few flat_maps but I've yet to get it to compile even 1) doing a bunch of manual indexing and 2) pretending that split_threshold can never fail. code:
reference must be valid for the anonymous lifetime #1 defined on the block at 63:45... (the entire function octs) ...but borrowed value is only valid for the scope of parameters for function at 64:37 (the closure)
|
# ? Apr 7, 2016 23:00 |
|
It has something to do with your implementation of split_threshold, quads, or the definition of SubImage, because the trivial version works on the Playground:code:
|
# ? Apr 7, 2016 23:16 |
|
I see now, it's because SubImage contains a reference to a byte buffer.code:
I tried adding 'a lifetimes everywhere to all the references and SubImage but I guess that was being done implicitly by the compiler anyway. e: when I next get internet I'll push to github so you can see the whole code e2: https://github.com/djmcgill/carved/blob/master/carved_rust/src/svo/generator/height_map.rs gonadic io fucked around with this message at 09:44 on Apr 8, 2016 |
# ? Apr 8, 2016 08:44 |
|
Here's the problem:code:
code:
code:
I'm probably explaining this very poorly because I don't 100% grasp the intricacies myself. E: You probably want to make this change for the other functions too, but they don't cause this specific function to fail. Linear Zoetrope fucked around with this message at 10:27 on Apr 8, 2016 |
# ? Apr 8, 2016 10:23 |
|
I was able to get it to compile making the following changes:code:
|
# ? Apr 8, 2016 10:24 |
|
That makes perfect sense, thanks all. I'll sort it out tonight. Of course, given how much of a pain using map with arrays is I might just stick with my manual indexing. That or write a map_8 function.
|
# ? Apr 8, 2016 11:31 |
|
|
# ? May 15, 2024 03:37 |
|
I own a [T; 8] and would like to access the Ts out of it without copying (this is important). Then I'd like to call a FnOnce(T) -> T on each one and package them back up in an array. I managed to cobble together a working version thanks to SO: code:
However I have the function: code:
code:
I get the error error: cannot borrow data mutably in a captured outer variable in an `Fn` closure [E0387]. Is there any way I can 1) bypass needing a mutable pointer to an outer variable in the closure, or 2) have a mutable pointer to an outer variable in the closure? Full context is here: https://github.com/djmcgill/carved/blob/master/carved_rust/src/svo/mod.rs gonadic io fucked around with this message at 19:44 on Apr 20, 2016 |
# ? Apr 20, 2016 19:41 |