Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
xtal
Jan 9, 2011

by Fluffdaddy

Walh Hara posted:

So, I'm an idiot and need help.

I want to get an array of length 64 of ChessCell objects. This should be really simple but it keeps giving compilation errors.

code:
    
let mut cells: [ChessCell; 64];
for i in 0..64 {
        cells[i] = ChessCell { ... };
    }
Gives the error "error[E0381]: use of possibly uninitialized variable: `cells`". I could make a vector and convert it to an array afterwards or initialise the array with incorrect objects, but both seem really dumb to me? Is there some trick?

I'm kinda used to functional programming so I also tried to:
1) make an array [0,1, 2, ..., 63]
2) apply a function to each value in the array (map)
3) put the result of this .map(f) in an array with the same fixed size
I'd expect this to be possible, but I'm having trouble with each of these three steps.

I don't even know what syntax you're trying to use, but it looks like you're declaring the type of `cells` as a slice of 64 `ChessCell`s. Despite that, you're not declaring the value. Add `= []`.

Adbot
ADBOT LOVES YOU

Walh Hara
May 11, 2012

Eela6 posted:

You've only declared the identifier, not initialized it. Unlike go, rust doesn't assume a default value for an identifier with a type but no initializer.

code:
let mut cells = [ChessCell{...}; 64]

I already knew this, but this seems extremely dumb to me? Do I really need to fill the array with garbage (when I declare the variable) so I can replace this garbage in the for loop with the correct values? I was assuming there must a be better way.

Or should you just never use arrays when working with objects?

quote:

I don't even know what syntax you're trying to use, but it looks like you're declaring the type of `cells` as a slice of 64 `ChessCell`s. Despite that, you're not declaring the value. Add `= []`.

That doesn't work.

Eela6
May 25, 2007
Shredded Hen

Walh Hara posted:

I already knew this, but this seems extremely dumb to me? Do I really need to fill the array with garbage (when I declare the variable) so I can replace this garbage in the for loop with the correct values? I was assuming there must a be better way.

Or should you just never use arrays when working with objects?


That doesn't work.

You're going to do that no matter what, because otherwise your array might use uninitialized memory with arbitrary contents. Generaly speaking, Rust's compiler is smart enough to figure out what you mean, and will skip the 'useless' allocations if your inbetween steps don't affect anything else . You can also use Vec::with_capacity(64) and then convert to an array, as you've mentioned.


I've constructed an example of working with arrays of non-primitive types that might help you. I don't know the details of your types, so it's hard to give more detailed help.

VikingofRock
Aug 24, 2008




Walh Hara posted:

I already knew this, but this seems extremely dumb to me? Do I really need to fill the array with garbage (when I declare the variable) so I can replace this garbage in the for loop with the correct values? I was assuming there must a be better way.

Or should you just never use arrays when working with objects?

You have a few options. Off the top of my head:

  1. Fill the array with garbage, and then mutate it to the correct value. This will probably get optimized away, so it shouldn't be less efficient, although it is maybe less elegant.
  2. Use std::mem::uninitialized. This is unsafe, but if for whatever reason the above isn't getting optimized away, then this will be a little faster.
  3. Use a Vec, and collect() from an iterator over the indices. This is probably the most idiomatic way to handle this, and for a 64-element object you might as well throw it on the heap anyways. You lose the compile-time guarantee that the chess board is exactly 64 elements long, but honestly there's not too much you can do with that guarantee right now anyways because Rust doesn't have C++-style integer generics.

Personally, I'd go with the 3rd option. If you want to see what this looks like in practice, or if you want to play around with it, I wrote up some prototypes on the Rust playground.

Ralith
Jan 12, 2011

I see a ship in the harbor
I can and shall obey
But if it wasn't for your misfortune
I'd be a heavenly person today

Walh Hara posted:

I already knew this, but this seems extremely dumb to me? Do I really need to fill the array with garbage (when I declare the variable) so I can replace this garbage in the for loop with the correct values? I was assuming there must a be better way.

Or should you just never use arrays when working with objects?
You can use mem::uninitialized() here if you want. It's unsafe because you have to ensure that drop never gets called on uninitialized values, but in cases like yours this is trivial. Of course, then you've introduced unsafe code just to perform an optimization that the compiler would have worked out on its own anyway.

tazjin posted:

I've spent the last two evenings looking at how to migrate a reasonably complex Rust system from error_chain to the new failure crate.

The system uses a bunch of external libraries (e.g. r2d2_postgres, rouille, serde of course, ...) and previously we used error_chain's foreign_links functionality to explicitly declare how all the possible errors that could occur would be converted into our error representations.

I considered that one of the major selling points of error handling in Rust: The compiler would be able to point out which foreign errors have not yet been "acknowledged" in the error handling strategy. It was still possible to then proceed to drop the errors on the floor, but dispatching different handling strategies on foreign & internal errors in the same way was trivial to do.

Now with failure everything gets shoved into a single, shared Error-type. Keeping information about what kind of error occured either requires littering the code with verbose .context(...) calls or using runtime reflection (:barf:) and - since almost every error is implicitly convertable to a failure - using ? now feels like working with a method that has throws Exception in its signature in Java.

To make things worse, errors from error_chain can actually not be converted to failures because they aren't Sync. This makes using libraries that have switched to failure somewhat painful from an error_chain based application.

This kind of "lets throw the types away!" dynlang bullshit should stay out of my Rust ecosystem :colbert:
Using failure doesn't mean you need to use failure::Error at all; that's expressly the lazy shortcut approach. Instead, you can define your own Error type, derive Fail for it, and implement From<ForeignError> for whatever errors you want to support. There's been some discussion on whether this exact pattern is actually a good idea, but it is certainly still supported.

Personally, I'm a fan of using .context(...) heavily because it lets you provide informative error messages; if your program does a bunch of IO, a simple "permission denied" error message can be incredibly unhelpful compared to, say, "couldn't open config file /foo/bar: permission denied". You don't necessarily need to scatter these all over your code, though, just at major boundaries.

Subjunctive
Sep 12, 2006

✨sparkle and shine✨

“What does the profiler say?”

tazjin
Jul 24, 2015


Ralith posted:

Using failure doesn't mean you need to use failure::Error at all; that's expressly the lazy shortcut approach. Instead, you can define your own Error type, derive Fail for it, and implement From<ForeignError> for whatever errors you want to support. There's been some discussion on whether this exact pattern is actually a good idea, but it is certainly still supported.

Something like implementing From<ForeignError> for our error types is probably what we'll do if we end up using failure. May in that case even make a macro implementing error_chain's foreign_links functionality for failure.

The fact that failure promotes at least three different ways to use its own error types is also going to be annoying in the future, because crate authors will not do it consistently and suddenly the quality of errors from foreign code will have an additional dimension of "Oh no" to it.

Ralith posted:

Personally, I'm a fan of using .context(...) heavily because it lets you provide informative error messages; if your program does a bunch of IO, a simple "permission denied" error message can be incredibly unhelpful compared to, say, "couldn't open config file /foo/bar: permission denied". You don't necessarily need to scatter these all over your code, though, just at major boundaries.

There's an example somewhere in the docs of failure in which .context(...) is used to add the string "file not found" to an IO-error, but it is in a situation where the error may just as well be something else - like "permission denied".

This leads to a similar issue as people encounter in Go: Layers of misleading error messages, concatenated together, because some programmer thought they could enumerate the possible errors at the point where they provided "context" in their head.

Walh Hara
May 11, 2012
Thanks for the explanations everyone.

Ralith
Jan 12, 2011

I see a ship in the harbor
I can and shall obey
But if it wasn't for your misfortune
I'd be a heavenly person today

tazjin posted:

There's an example somewhere in the docs of failure in which .context(...) is used to add the string "file not found" to an IO-error, but it is in a situation where the error may just as well be something else - like "permission denied".

This leads to a similar issue as people encounter in Go: Layers of misleading error messages, concatenated together, because some programmer thought they could enumerate the possible errors at the point where they provided "context" in their head.
Huh? You're not enumerating anything, you're providing context. That is why the method is called "context". The inner error is still there to be inspected and displayed in turn. If your error messages are misleading, fix them.

HappyHippo
Nov 19, 2003
Do you have an Air Miles Card?
Is there a guide anywhere on downloading crates manually? The firewall at work basically makes cargo unusable, it can't even get the index

Linear Zoetrope
Nov 28, 2011

A hero must cook
You can just clone the repository or download the zip from crates.io, place it in a folder called "vendor" and use a path dependency.

All crates.io really is is a collection of crate zips with some heuristics about which versions are allowed to be used as dependencies.

Linear Zoetrope fucked around with this message at 21:50 on Apr 6, 2018

HappyHippo
Nov 19, 2003
Do you have an Air Miles Card?
Ok between that and the documentation I think I understand. Thanks

Ralith
Jan 12, 2011

I see a ship in the harbor
I can and shall obey
But if it wasn't for your misfortune
I'd be a heavenly person today

HappyHippo posted:

Ok between that and the documentation I think I understand. Thanks
You can also use cargo vendor on an external machine then bring the results into the protected network, if you like.

limaCAT
Dec 22, 2007

il pistone e male
Slippery Tilde
I saw an awesome svg chart today showing graphically what happens to variables when they are borrowed and I think it would be neat to have something that parses your code and shows borrows, moves, copiers and lifetimes graphically.

TalkLittle
Jun 23, 2004

https://hacks.mozilla.org/2018/04/hello-wasm-pack/

Packaging Rust crates as WebAssembly and publishing them to NPM to be consumed by JS.

So the future of the web is moving libraries to Wasm and Rust, and keeping a scripting layer on top for UI and business logic? So like a C-Lua kind of setup. I could get behind that.

xtal
Jan 9, 2011

by Fluffdaddy
The future of the Web is a garbage can

xtal fucked around with this message at 22:55 on Apr 18, 2018

Dominoes
Sep 20, 2007

Yo bros. Trying to do some matrix mult; ref the thread's title. Any wisdom from bros on how to make it compile?

Rust code:
fn project(cam: &Camera, node: &Node) -> Array1<f64> {
    // Project a 4d node onto a 2d plane.
    // [url]https://en.wikipedia.org/wiki/3D_projection[/url]

    let D_1 = array![
        [1., 0., 0.],
        [0., cam.theta[0].cos(), cam.theta[1].sin()],
        [0., -cam.theta[0].sin(), cam.theta[0].cos()]
    ];

    let D_2 = array![
        [cam.theta[1].cos(), 0., -cam.theta[1].sin()],
        [0., 1., 0.],
        [cam.theta[1].sin(), 0., cam.theta[1].cos()]
    ];

    let D_3 = array![
        [cam.theta[2].cos(), cam.theta[2].sin(), 0.],
        [-cam.theta[2].sin(), cam.theta[2].cos(), 0.],
        [0., 0., 1.]
    ];

    let D = D_1.dot(&(D_2.dot(&D_3)));

    //  d is the position of the node a in the coordinate system
    // defined by the camera, wiht origin in C and rotated by theta.
    let d = D.dot(&(node.a - &cam.c));

    let A = array![
        [1., 0., -cam.e[0] / cam.e[2], 0.],
        [0., 1., -cam.e[1] / cam.e[2], 0.],
        [0., 0., 1., 0.],
        [0., 0., -1. / cam.e[2], 1.],
    ];

    let f = A.dot(
        array![&d[0], &d[1], &d[2], 1.]
    );
error:
code:
error[E0308]: mismatched types
  --> src\main.rs:68:9
   |
68 |         array![&d[0], &d[1], &d[2], 1.]
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected reference, found struct `ndarray::ArrayBase`
   |
   = note: expected type `&_`
              found type `ndarray::ArrayBase<ndarray::OwnedRepr<&f64>, ndarray::Dim<[usize; 1]>>`
   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for mor...
If I remove the &s around d, I get:

code:
error[E0308]: mismatched types
  --> src\main.rs:68:9
   |
68 |         array![d[0], d[1], d[2], 1.]
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected reference, found struct `ndarray::ArrayBase`
   |
   = note: expected type `&_`
              found type `ndarray::ArrayBase<ndarray::OwnedRepr<f64>, ndarray::Dim<[usize; 1]>>`
   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-m
Also, anyone know how to hack SA's forum code to make good code syntax highlighting? poo poo's super out of date php and doesn't support rust etc. Basically, I don't get the & stuff and can't even do basic things in Rust. I suck. It's not Haskell-monad-level 'I'm too dumb for this'; more like, I'm missing something fundamental but will eventually get it. I could take the easy way out and do Python where the code just does what you ask, but I really want to learn this.

Dominoes fucked around with this message at 04:48 on Apr 22, 2018

VikingofRock
Aug 24, 2008




Dominoes posted:

Yo bros. Trying to do some matrix mult; ref the thread's title. Any wisdom from bros on how to make it compile?

Rust code:
fn project(cam: &Camera, node: &Node) -> Array1<f64> {
    // Project a 4d node onto a 2d plane.
    // [url]https://en.wikipedia.org/wiki/3D_projection[/url]

    let D_1 = array![
        [1., 0., 0.],
        [0., cam.theta[0].cos(), cam.theta[1].sin()],
        [0., -cam.theta[0].sin(), cam.theta[0].cos()]
    ];

    let D_2 = array![
        [cam.theta[1].cos(), 0., -cam.theta[1].sin()],
        [0., 1., 0.],
        [cam.theta[1].sin(), 0., cam.theta[1].cos()]
    ];

    let D_3 = array![
        [cam.theta[2].cos(), cam.theta[2].sin(), 0.],
        [-cam.theta[2].sin(), cam.theta[2].cos(), 0.],
        [0., 0., 1.]
    ];

    let D = D_1.dot(&(D_2.dot(&D_3)));

    //  d is the position of the node a in the coordinate system
    // defined by the camera, wiht origin in C and rotated by theta.
    let d = D.dot(&(node.a - &cam.c));

    let A = array![
        [1., 0., -cam.e[0] / cam.e[2], 0.],
        [0., 1., -cam.e[1] / cam.e[2], 0.],
        [0., 0., 1., 0.],
        [0., 0., -1. / cam.e[2], 1.],
    ];

    let f = A.dot(
        array![&d[0], &d[1], &d[2], 1.]
    );
[/rust]

error:
[code]
error[E0308]: mismatched types
  --> src\main.rs:68:9
   |
68 |         array![&d[0], &d[1], &d[2], 1.]
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected reference, found struct `ndarray::ArrayBase`
   |
   = note: expected type `&_`
              found type `ndarray::ArrayBase<ndarray::OwnedRepr<&f64>, ndarray::Dim<[usize; 1]>>`
   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for mor...
If I remove the &s around d, I get:

code:
error[E0308]: mismatched types
  --> src\main.rs:68:9
   |
68 |         array![d[0], d[1], d[2], 1.]
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected reference, found struct `ndarray::ArrayBase`
   |
   = note: expected type `&_`
              found type `ndarray::ArrayBase<ndarray::OwnedRepr<f64>, ndarray::Dim<[usize; 1]>>`
   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-m
Also, anyone know how to hack SA's forum code to make good code syntax highlighting? poo poo's super out of date php and doesn't support rust etc. Basically, I don't get the & stuff and can't even do basic things in Rust. I suck. It's not Haskell-monad-level 'I'm too dumb for this'; more like, I'm missing something fundamental but will eventually get it.

I don't have a lot of experience with the ndarray crate, but it looks like dot() takes its argument by reference. So try putting an & in front of the array![...] in the definition of f? If the borrow checker gives you crap about that value not living long enough, take the argument to dot() and give it its own let binding.

Whenever I get errors about the expected type of an argument, I always go and double check exactly what that argument is expecting and the type of what I'm giving it, and usually that solves it.

Dominoes
Sep 20, 2007

Thanks for looking at it dude. getting this now:

code:
error[E0308]: mismatched types
  --> src\main.rs:68:16
   |
68 |         &(arr1([d[0], d[1], d[2], 1.]))
   |                ^^^^^^^^^^^^^^^^^^^^^^
   |                |
   |                expected &[_], found array of 4 elements
   |                help: consider borrowing here: `&[d[0], d[1], d[2], 1.]`
   |
   = note: expected type `&[_]`
              found type `[f64; 4]`
If I follow this warning and do:

code:
   let f = A.dot(
        &(arr1(&[d[0], d[1], d[2], 1.]))
    );
I get:

code:
93 |         .map(|node| project(camera, node)).collect();
   |                             ^^^^^^ cannot move out of captured outer variable in an `FnMut` closure
This is humbling me and I love it. Change &s until it compiles? I don't think I'm doing anything esp weird; just taking some dot products. Sorry dudes; I get that I posted a lot of code and error messages; so lost.

Dominoes fucked around with this message at 05:03 on Apr 22, 2018

Dominoes
Sep 20, 2007

Dudes; got it to compile; I'lll post what happened if you like, but I have no idea and don't think it'll be useful since I just moved &s around rando until it worked.

VikingofRock
Aug 24, 2008




Dominoes posted:

I just moved &s around rando until it worked.

Now you are programming like a true Rust expert!

e: seriously though congrats on getting it to compile! It'll (mostly) click soon, don't worry.

Linear Zoetrope
Nov 28, 2011

A hero must cook
Also don't feel bad because ndarray is really finnicky and not exactly the most ergonomic crate. Rust's type system isn't really built to handle the sorts of things mathematical crates really need right now, and they're not going to be worked on much until next year (given the roadmap and me asking the Rust team about future goals). They're blocked on a few things like type-level numerics.

gonadic io
Feb 16, 2011

>>=
I got it working with (ignore the type annotations, they're not needed)
code:
    let d: Array1<f64> = D.dot(&(&node.a - &cam.c));

    let A: Array2<f64> = array![
        [1., 0., -cam.e[0] / cam.e[2], 0.],
        [0., 1., -cam.e[1] / cam.e[2], 0.],
        [0., 0., 1., 0.],
        [0., 0., -1. / cam.e[2], 1.],
    ];

    let f: Array1<f64> = A.dot(
        &array![d[0], d[1], d[2], 1.]
    );
i.e.
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.

Dominoes
Sep 20, 2007

Thank you - that helps a lot!

Dominoes
Sep 20, 2007

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?

How would you handle this?

Dominoes fucked around with this message at 10:34 on May 21, 2018

Linear Zoetrope
Nov 28, 2011

A hero must cook
You can specify dependencies as optional based on an arbitrary cfg.

So in your Cargo.toml

code:
[target.cfg(not(wasm-unknown-unknown)).dependencies]
my_problematic_dependency = "1"
Then everywhere you use it in the code you can preface it with a #[cfg(not(wasm-unknown-unknown))]

gonadic io
Feb 16, 2011

>>=

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?

How would you handle this?

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.

Dominoes
Sep 20, 2007

Nailed it. Went with the specify-dependencies approach for now; may switch to the separate lib approach later.

Dominoes
Sep 20, 2007

Another one: Is there a way to make Rust's wasm-bindgen work with types other than basic numbers/string, and ones you created in your code? Eg, I can make it accept custom structs with the #[wasm_bindgen] macro, but unable to apply it to say, a HashMap from the standard library, or an Array from the ndarray crate.

Dominoes fucked around with this message at 23:43 on May 21, 2018

repiv
Aug 13, 2009

Yeah, if you enable the "serde-serialize" feature in wasm-bindgen then you can pass anything that serde can serialize to JSON across the WASM boundary. For example you can do

code:
#[wasm_bindgen]
pub fn generate_hashmap() -> JsValue {
    let mut hashmap = HashMap::new();
    hashmap.insert(1, "one");
    hashmap.insert(2, "two");
    hashmap.insert(3, "three");

    JsValue::from_serde(&hashmap).unwrap()
}
and calling this function from JS will give you {1: "one", 2: "two", 3: "three"}. The reverse also works using JsValue::into_serde().

Dominoes
Sep 20, 2007

Thanks; works!

Linear Zoetrope
Nov 28, 2011

A hero must cook
Blugh, the RLS being borked is killing me right now. Can't use old versions because I migrated to some 1.26 features.

gonadic io
Feb 16, 2011

>>=

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.

Horse Inspector
Aug 11, 2005
privacy publicly displayed
Just started learning rust and making crappy little programs to test things. The scala in me wanted to write the following and I wanted to check my understanding of the problem is correct:

code:
// current is a Result<String>

let split = current.map(|k| {
  redisutils::get_field(&k, "name", &conn).map(|f| {
    f.split_at(f.find("vs").unwrap())
  })
}).unwrap()?;

// use split later on
Forgive the ugly unwraps it's just for ease while I'm dicking about. I want to use the tuple from splitting later on but the issue is that "`f` does not live long enough". Having looked at the docs for split_at I see it returns a tuple of two string slice references. My understanding is that those references will be pointing to the heap where 'f's contents are. But f is dropped after the anonf it's declared in so that would leave the split tuple as 2 dangling pointers. Is this a correct understanding?

Vanadium
Jan 8, 2005

I think in this case it doesn't matter that it's in the heap, just that you have references with a lifetime bound to a local in the closure, so they aren't allowed to escape the closure.

tinaun
Jun 9, 2011

                  tell me...
yeah, what you want in this case is split_off, which returns owned strings

VikingofRock
Aug 24, 2008




This is a fun bit of obfuscated rust from reddit:

code:
fn main() {
  println!("{:?}",
    (|&__@_:&'_ _|->_{[(|(_,__,..):(_,_)|__..__)(__)]})({&({||('"');}<=*&(),&[..=..])}));
}
See if you can figure out what it prints! I got a good bit of it, but there was some syntax in there that I was unfamiliar with. I didn't realize that .. is a valid struct which can itself be the endpoint of a range.

Linear Zoetrope
Nov 28, 2011

A hero must cook

VikingofRock posted:

This is a fun bit of obfuscated rust from reddit:

code:
fn main() {
  println!("{:?}",
    (|&__@_:&'_ _|->_{[(|(_,__,..):(_,_)|__..__)(__)]})({&({||('"');}<=*&(),&[..=..])}));
}
See if you can figure out what it prints! I got a good bit of it, but there was some syntax in there that I was unfamiliar with. I didn't realize that .. is a valid struct which can itself be the endpoint of a range.

As with most code like this, it's easier if you add some whitespace, in which case you can start picking at pieces very easily. I wrote an explanation/my notes while deciphering here. Turns out I got it right!:

https://gist.github.com/LinearZoetrope/7e1cf85c74ef4ce813331336fc628593

The part that was surprising to me was that __ is a valid variable name, I knew The Range variants were a structs, but not that they had no restrictions on their input.

luchadornado
Oct 7, 2004

A boombox is not a toy!

Where can I easily figure out the current status for hyper/tokio/reqwest/async/await and best practices? I just want to make an asynchronous HTTP call to something and unstable features / allowing warnings for this simple use case seem kind of annoying:

https://github.com/seanmonstar/reqwest/blob/f48ec85b3c84d24235233875d66a76e3419338a8/examples/async.rs

The Rust Cookbook also uses reqwest for its examples, and I see mention that reqwest provides a simple abstraction on top of hyper, but the examples look identical. Why should I be using reqwest? At this point it almost feels like I should just use some synchronous hyper and move on, since this isn't a super performance critical application.

Adbot
ADBOT LOVES YOU

xtal
Jan 9, 2011

by Fluffdaddy

Helicity posted:

Where can I easily figure out the current status for hyper/tokio/reqwest/async/await and best practices? I just want to make an asynchronous HTTP call to something and unstable features / allowing warnings for this simple use case seem kind of annoying:

https://github.com/seanmonstar/reqwest/blob/f48ec85b3c84d24235233875d66a76e3419338a8/examples/async.rs

The Rust Cookbook also uses reqwest for its examples, and I see mention that reqwest provides a simple abstraction on top of hyper, but the examples look identical. Why should I be using reqwest? At this point it almost feels like I should just use some synchronous hyper and move on, since this isn't a super performance critical application.

I think all of those things are just on the cusp of being usable. You probably want to wait a while or just use sync hyper for now.

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply