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
rufius
Feb 27, 2011

Clear alcohols are for rich women on diets.

xtal posted:

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.

Pretty much this. By October, we should start to see a lot of this settle down since async/await got merged into nightly sometime in August or late July I believe. Right now the pattern is clunky and awkward to use since you have to provide the boilerplate yourself.

Alternatively, run the nightly compiler like I do because YOLO. (Seriously, nightly is actually quite stable - I originally started running it to get access to cargo clippy but I believe that's in stable now.)

Adbot
ADBOT LOVES YOU

QuietMisdreavus
May 12, 2013

I'm fine. Nothing to worry about.

Helicity posted:

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?

Reqwest is basically like "sync hyper plus a couple extra goodies". I haven't looked at it in a while, but things like easier methods to perform requests with less boilerplate, automatically plugging in HTTPS support, stuff like that. Hyper is one of those things that is built to be really "extensible", but that effectively means that you have to build a lot of convenience stuff yourself. Reqwest was the author's idea of one of these convenience wrappers.

EDIT: Unrelated, but the videos for (almost all of) the talks from RustConf last month have been uploaded. I didn't get the chance to see most of them while i was there, but the closing keynote was really interesting. (Also one of them is mine, i guess.)

QuietMisdreavus fucked around with this message at 18:11 on Sep 10, 2018

Seat Safety Switch
May 27, 2008

MY RELIGION IS THE SMALL BLOCK V8 AND COMMANDMENTS ONE THROUGH TEN ARE NEVER LIFT.

Pillbug
I use reqwest for web scraping and stuff like that. It was the easiest thing to get working at the time.

Beamed
Nov 26, 2010

Then you have a responsibility that no man has ever faced. You have your fear which could become reality, and you have Godzilla, which is reality.


Dick Nipples posted:

Alternatively, run the nightly compiler like I do because YOLO. (Seriously, nightly is actually quite stable - I originally started running it to get access to cargo clippy but I believe that's in stable now.)

Juuust enough breaks or has random errors that I don't like to play this, unfortunately.

rufius
Feb 27, 2011

Clear alcohols are for rich women on diets.

Beamed posted:

Juuust enough breaks or has random errors that I don't like to play this, unfortunately.

Interestingly. What sort of stuff have you run into?

I ask because I haven't seen any while working with it for the last 6 or 7 months at work. I've got a fairly sizable code base I work in (~10k lines) so I always worry something subtle is gonna screw me over.

Generally speaking, I iterate with nightly and then do my release compiles with stable. Only reason to use nightly is for me to do cargo clippy and rustfmt. I don't actually use the nightly features so I suppose that's one big area I'm not taking on risk (new/unstable features).

Do you find existing features to be unstable? Or just the new stuff they drop in?

spiritual bypass
Feb 19, 2008

Grimey Drawer
While experimenting with webass a few weeks ago, I found that my program worked fine on my desktop but wouldn't compile on my laptop. It'd fail with a useless error message after cranking for a while. They were running nightly versions only a few days apart. Updating my laptop fixed it.

Beamed
Nov 26, 2010

Then you have a responsibility that no man has ever faced. You have your fear which could become reality, and you have Godzilla, which is reality.


Dick Nipples posted:

Interestingly. What sort of stuff have you run into?

I ask because I haven't seen any while working with it for the last 6 or 7 months at work. I've got a fairly sizable code base I work in (~10k lines) so I always worry something subtle is gonna screw me over.

Part of it is the result of libraries I used - Rocket and crypto crate,s for example, are incompatible for ?? reasons. But more importantly, beyond this frustration, are when things like the RLS breaks, and very rarely when cargo check just sort of..implodes on more complicated crate building.

I think a lot (most) of that is mitigated if you don't need to pull in a lot of crates, but since I spent so long writing a web API on nightly, well, :v:

Dick Nipples posted:

Generally speaking, I iterate with nightly and then do my release compiles with stable. Only reason to use nightly is for me to do cargo clippy and rustfmt. I don't actually use the nightly features so I suppose that's one big area I'm not taking on risk (new/unstable features).

Do you find existing features to be unstable? Or just the new stuff they drop in?

Both. Things have been better since around February, when they started really making guards around the nightly being pushed if it breaks a core feature. I don't mind things breaking when I'm on nightly - since it's nightly, after all - but the 2 hours or so I spend trying to solve the problem, when I only have about 2-3 hours of free time a day, is just too much of a time sink for me to justify anymore.

I'd say if I had to list my frustrations, it would be:

1.) Obscure compiler errors that are resolved by switching to the previous nightly.
2.) RLS randomly breaking, but I basically switched to IntelliJ now that they decided the current state of RLS is 1.0.
3.) The libraries which require nightly are .. not really stable, which is less a knock on nightly and more a knock on the maintainers, but you know.

I've never had instability pop up if my code did compile, so honestly I would agree with you that if you avoid issues with a nightly, it's not an inherent problem. But if you use stable to release, then no problem anyway :v:

mystes
May 31, 2006

I just tried using quick-xml for parsing rss, and I guess this isn't rust specific really, but I've managed to never do event based xml parsing before so I have to ask: do you just always have to make your own lovely bespoke state machine or is there some secret to this?

rufius
Feb 27, 2011

Clear alcohols are for rich women on diets.

mystes posted:

I just tried using quick-xml for parsing rss, and I guess this isn't rust specific really, but I've managed to never do event based xml parsing before so I have to ask: do you just always have to make your own lovely bespoke state machine or is there some secret to this?

Not sure what you mean by event based. Do you mean how the elements in an <item> node can be in any order? Then ya, XML parsing is basically one giant match statement.

Alternatively, you deserialize into a property bag via serde so that you can query by key name.

There’s also this crate which is pretty thorough: https://crates.io/crates/rss

mystes
May 31, 2006

Dick Nipples posted:

Not sure what you mean by event based. Do you mean how the elements in an <item> node can be in any order? Then ya, XML parsing is basically one giant match statement.

Alternatively, you deserialize into a property bag via serde so that you can query by key name.

There’s also this crate which is pretty thorough: https://crates.io/crates/rss
I think we may be saying the same thing, but by event based I mean SAX/StAX style parsing, where you either use callbacks (SAX), or call a function to get the next event (StAX, like quck-xml), but either way the only information you get is "events" like a certain tag starting or ending .You don't have access to information on parent/child nodes at this point, so you have to keep track of what element you are in to the extent it matters to you.

In my case I had an instance of a struct containing the current element and then added it to a list whenever an item element ended, replacing it with a new instance (to avoid having to use an option), and when I hit the elements that are supposed to be within an item I updated the current element.

I guess this sort of thing used to be the standard way to parse xml, but 1) it just seems really ugly to manually keep track of all this state and also 2) the xml could be completely wrong (like elements nested in the wrong order) and it would just blithely continue without noticing, so it seems a bit weird.

Obviously using a dom based xml parser will take a lot more memory, but it just seems a lot more sane. I guess in non-garbage collected languages SAX/StAX style parsing may still be the standard though?

Dominoes
Sep 20, 2007

Hey dudes. How do you enter values in scientific notation?

Rust code:
const ELECTRON_MASS: f64 = 9.109390 * (10.).powi(-31);

quote:

error[E0599]: no method named `powi` found for type `{float}` in the current scope

Linear Zoetrope
Nov 28, 2011

A hero must cook
I don't believe Rust has scientific notation literals, and you can't do things like that until const fn stabilizes. The workaround right now would be the lazy_static crate.

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

Dominoes posted:

Hey dudes. How do you enter values in scientific notation?

Rust code:
const ELECTRON_MASS: f64 = 9.109390 * (10.).powi(-31);
The syntax is the same as in most programming languages, e.g. 9.109390e-31.

Linear Zoetrope
Nov 28, 2011

A hero must cook
Is that recent? It's not in the Rust Reference or the book afaict.

E: I was looking at the 1.7 Reference...

It's in the current one
https://doc.rust-lang.org/reference/tokens.html?highlight=literals#number-literals

Linear Zoetrope fucked around with this message at 22:31 on Sep 27, 2018

Dominoes
Sep 20, 2007

Ralith posted:

The syntax is the same as in most programming languages, e.g. 9.109390e-31.
Thanks dude; that worked.


Re: Linear's comment: It's interesting that a workaround would have been required if it were not for this shorthand.

gonadic io
Feb 16, 2011

>>=
Most language features in all languages would require workarounds if they didn't exist :shrug:

Dominoes
Sep 20, 2007

I'm referring to why the code I initially posted isn't also a valid solution. I don't understand what's going on, since const test: f64 = 1. * 10.; works.

Dominoes fucked around with this message at 23:56 on Sep 27, 2018

pseudorandom name
May 6, 2007

const test: f64 = 1. * 10.; works because you aren't trying to call a method on an unknown type.

const ELECTRON_MASS: f64 = 9.109390 * (10.).powi(-31); fails because you're trying to do a method lookup on some kind of floating point type, but the compiler doesn't know which one yet, hence the error.

If you change it to something that isn't ambiguous, like const ELECTRON_MASS: f64 = 9.109390 * 10.0f64.powi(-31);, the error becomes
code:
error[E0015]: calls in constants are limited to tuple structs and tuple variants
 --> src/lib.rs:1:39
  |
1 | const ELECTRON_MASS: f64 = 9.109390 * 10.0f64.powi(-31);
  |                                       ^^^^^^^^^^^^^^^^^
  |
note: a limited form of compile-time function evaluation is available on a nightly compiler via `const fn`
 --> src/lib.rs:1:39
  |
1 | const ELECTRON_MASS: f64 = 9.109390 * 10.0f64.powi(-31);
  |                                       ^^^^^^^^^^^^^^^^^

error: aborting due to previous error
For more information about this error, try `rustc --explain E0015`.

mystes
May 31, 2006

Dominoes posted:

I'm referring to why the code I initially posted isn't also a valid solution. I don't understand what's going on, since const test: f64 = 1. * 10.; works.
I guess there are two problems with what you originally head:
1) There's no powi method for float, so I guess you would have to use type ascription or whatever to make 10. be f64
2) You can't call powi at compile time so you can't assign it to a const currently. I think there are proposals to improve this sort of thing, but I don't know what the status is.

Dominoes
Sep 20, 2007

Thanks dudes.

Linear Zoetrope
Nov 28, 2011

A hero must cook
Basically, Rust does untyped infinite-precision arithmetic on literals, but this is limited to the built in operators (+, -, *, /, and for ints, %, |, ^, &, <<, >>).

code:
let mut x = 5;
x = x + 12;

let y: () = x;
Will tell you x is of type {integer} which is an infinite-precision int. The variable will remain this pseudo-type until x is coerced into a type implicitly by assigning it, calling a function, etc. All of these operations on these pseudo-types are done at compile time, hence why they're limited to built-in operators. You're not allowed to call functions like powi until the exact runtime sized type is known (f64). There's an argument that since you're assigning to an f64, the compiler's type inference should be able to work out you mean f64, but there's also an argument for explicitness that fits with Rust's general philosophy (such as requiring you to manually type convert from an f32 to an f64 if you're doing let result: f64 = my_f64 + (my_f32 as f64)).

It's on the roadmap for Rust to eventually allow compile time functions, const fn which signals a function contains an algorithm that may (but not must) be run at compile/startup time. These are usually basic math and initialization functions (such as building a new global Mutex), but there hasn't been agreement on exactly how it should work and what the restrictions should be. See the tracking issue here.

Until then, the lazy_static crate provides a macro that sorta does that. Instead of a const it declares a static wrapped in a function that's called automatically the first time the variable is read. This theoretically has some minor runtime overhead, but it works in most cases. There may be an argument against using a number declared in lazy_static in a hot loop, but I'd need to see benchmarks before saying that. The compiler may be able to optimize around call_once properly since I think it's a core intrinsic of FnOnce.

Linear Zoetrope fucked around with this message at 03:24 on Sep 28, 2018

luchadornado
Oct 7, 2004

A boombox is not a toy!

Would it be more idiomatic to do something like compiling the regex within an Impl on a struct ? lazy_static feels wonky.

rufius
Feb 27, 2011

Clear alcohols are for rich women on diets.

Helicity posted:

Would it be more idiomatic to do something like compiling the regex within an Impl on a struct ? lazy_static feels wonky.

I mean sure.... but then you have to pass it around. Lazy_static is usually a last ditch effort thing.

It should really only be used in cases where you have a static const thing that needs to be globally available. If you’re squirreling away state in it that you later modify, you’re a bad person.

gonadic io
Feb 16, 2011

>>=

Dick Nipples posted:

I mean sure.... but then you have to pass it around. Lazy_static is usually a last ditch effort thing.

It should really only be used in cases where you have a static const thing that needs to be globally available. If you’re squirreling away state in it that you later modify, you’re a bad person.

And regular global mut statics exist for this exact reason.

luchadornado
Oct 7, 2004

A boombox is not a toy!

Dick Nipples posted:

I mean sure.... but then you have to pass it around. Lazy_static is usually a last ditch effort thing.

Yep, and that sucks. For a simple use case like "I want to compile all my regexes once", it sucks that I either need to Impl something like a MyParser struct and pass that around, or use lazy_static. It looks like at least a useful subset of that const fn stuff might stabilize relatively soon, which would be very welcome.

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

Linear Zoetrope posted:

Basically, Rust does untyped infinite-precision arithmetic on literals, but this is limited to the built in operators (+, -, *, /, and for ints, %, |, ^, &, <<, >>).

code:
let mut x = 5;
x = x + 12;

let y: () = x;
Will tell you x is of type {integer} which is an infinite-precision int. The variable will remain this pseudo-type until x is coerced into a type implicitly by assigning it, calling a function, etc. All of these operations on these pseudo-types are done at compile time, hence why they're limited to built-in operators. You're not allowed to call functions like powi until the exact runtime sized type is known (f64). There's an argument that since you're assigning to an f64, the compiler's type inference should be able to work out you mean f64, but there's also an argument for explicitness that fits with Rust's general philosophy (such as requiring you to manually type convert from an f32 to an f64 if you're doing let result: f64 = my_f64 + (my_f32 as f64)).

It's on the roadmap for Rust to eventually allow compile time functions, const fn which signals a function contains an algorithm that may (but not must) be run at compile/startup time. These are usually basic math and initialization functions (such as building a new global Mutex), but there hasn't been agreement on exactly how it should work and what the restrictions should be. See the tracking issue here.

Until then, the lazy_static crate provides a macro that sorta does that. Instead of a const it declares a static wrapped in a function that's called automatically the first time the variable is read. This theoretically has some minor runtime overhead, but it works in most cases. There may be an argument against using a number declared in lazy_static in a hot loop, but I'd need to see benchmarks before saying that. The compiler may be able to optimize around call_once properly since I think it's a core intrinsic of FnOnce.
Where are you getting this idea that anything is infinite-precision? {integer} is an unknown integer type. It doesn't have magic unique semantics, and it doesn't get coerced because it isn't a specific type to begin with. Arithmetic operators on certain types work in const contexts because they're special-cased to be const fns, and are not special in any other way.

Linear Zoetrope
Nov 28, 2011

A hero must cook

Ralith posted:

Where are you getting this idea that anything is infinite-precision? {integer} is an unknown integer type. It doesn't have magic unique semantics, and it doesn't get coerced because it isn't a specific type to begin with. Arithmetic operators on certain types work in const contexts because they're special-cased to be const fns, and are not special in any other way.

I think I got it confused with Go, which does do infinite precision arithmetic on literals.

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

Linear Zoetrope posted:

I think I got it confused with Go, which does do infinite precision arithmetic on literals.
So "1 + x" in Go can give different results for the same types depending on whether x is a literal or a variable? Whose idea was that?

Dylan16807
May 12, 2010

Ralith posted:

So "1 + x" in Go can give different results for the same types depending on whether x is a literal or a variable? Whose idea was that?
No, "integer constant" and "floating-point constant" are their own types.

It actually makes things more consistent, because you know that (5 << 40) >> 40 is always 5.

VikingofRock
Aug 24, 2008




Dylan16807 posted:

No, "integer constant" and "floating-point constant" are their own types.

It actually makes things more consistent, because you know that (5 << 40) >> 40 is always 5.

I guess that makes some sense, but it's pretty wild to me that this
code:
func foo(x float32) {
	var result_var float32 = (x - (1.0 - 1e-5)) * 1e5
	var result_lit float32 = (1.0 - (1.0 - 1e-5)) * 1e5
	fmt.Printf("result_var: %v\n", result_var)
	fmt.Printf("result_lit: %v\n", result_lit)
}
when called with x = 1.0, prints
code:
result_var: 1.001358
result_lit: 1
(go playground link) (rust playground comparison)

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

Dylan16807 posted:

No, "integer constant" and "floating-point constant" are their own types.
So it's weak numeric types, where seemingly cosmetic syntatic changes lead to different semantics. Did we learn nothing from C?

Dylan16807 posted:

It actually makes things more consistent, because you know that (5 << 40) >> 40 is always 5.
Until any of those values gets refactored into a variable, at which point who knows!

Dylan16807
May 12, 2010

Ralith posted:

So it's weak numeric types, where seemingly cosmetic syntatic changes lead to different semantics. Did we learn nothing from C?

Until any of those values gets refactored into a variable, at which point who knows!
Is it really that much weirder than getting different results when x is uint8?

Sheep
Jul 24, 2003
Anyone familiar with the openssl crate? I spent about four hours today trying to get a simple server going with very little luck. Complicating matters is the fact that all of the documentation I could find for the crate is entirely incorrect regarding SslAcceptor/etc. so I had to do a ton of source diving just to get things building (and then failing with no ciphers available).

Trying to keep dependencies light so not really interested in using tokio/native-tls/whatever else. I've got the client side written in Rust using openssl with no issues talking to a Python-based server so halfway there, in some sense.

Sheep fucked around with this message at 22:11 on Oct 22, 2018

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

Dylan16807 posted:

Is it really that much weirder than getting different results when x is uint8?
Is it weird that Boat::launch and Missiles::launch do different things? No, because they're different types, and their operations are distinct.

Sheep posted:

Anyone familiar with the openssl crate? I spent about four hours today trying to get a simple server going with very little luck. Complicating matters is the fact that all of the documentation I could find for the crate is entirely incorrect regarding SslAcceptor/etc. so I had to do a ton of source diving just to get things building (and then failing with no ciphers available).

Trying to keep dependencies light so not really interested in using tokio/native-tls/whatever else. I've got the client side written in Rust using openssl with no issues talking to a Python-based server so halfway there, in some sense.
If you found the documentation to be incorrect, you should report a bug; the crate is actively maintained. Though if you really want light dependencies, rustls might be better since you don't have to worry about foreign libraries.

Sheep
Jul 24, 2003

Ralith posted:

If you found the documentation to be incorrect, you should report a bug; the crate is actively maintained. Though if you really want light dependencies, rustls might be better since you don't have to worry about foreign libraries.

Once docs.rs came back up I was able to get it sorted out in ~30 seconds. Turns out that every mirror of docs.rs is out of date with regard to that crate and I just happened to be unlucky enough to be poking at a recently(?) changed portion of it on the day docs.rs was down.

I will look into rustls though, thanks.

crazysim
May 23, 2004
I AM SOOOOO GAY

Sheep posted:

Once docs.rs came back up I was able to get it sorted out in ~30 seconds. Turns out that every mirror of docs.rs is out of date with regard to that crate and I just happened to be unlucky enough to be poking at a recently(?) changed portion of it on the day docs.rs was down.

I will look into rustls though, thanks.

You should run "cargo doc --open". Docs.rs is really convenient but "cargo doc" will generate documentation for the versions of the crates in your project locally and let you "cross-link" the types and stuff as well.

Dylan16807
May 12, 2010

Ralith posted:

Is it weird that Boat::launch and Missiles::launch do different things? No, because they're different types, and their operations are distinct.
Does that mean you're agreeing with me now?

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

Dylan16807 posted:

Does that mean you're agreeing with me now?
The problem with go's approach is the weak typing, if that wasn't clear. If their compiletime-only bigint implementation was strongly typed, that would still be gratuitously weird, but comparatively harmless.

luchadornado
Oct 7, 2004

A boombox is not a toy!

When does the borrow checker stop kicking me in the dick? It feels like since Rust emphasizes "correctness", what I'm trying to do, and have done in programs for years, is broken. I already had imposter syndrome - I don't need a language to tell me I suck.

Adbot
ADBOT LOVES YOU

Dominoes
Sep 20, 2007

Helicity posted:

When does the borrow checker stop kicking me in the dick? It feels like since Rust emphasizes "correctness", what I'm trying to do, and have done in programs for years, is broken. I already had imposter syndrome - I don't need a language to tell me I suck.
Write code. Let the compiler tell you what you did wrong. If it hasn't already proposed the solution (which it often does!), move &s around until it works. Eventually you'll gain intuition about where to put them yourself.

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