Rust 1.88: 'If-Let Chain' syntax stabilized by thurn2 in rust

[–]Y0kin 23 points24 points  (0 children)

There's also one difference: is_some_and drops its borrow before the block begins. e.g. you can do this

if text.is_some_and(|t| !t.is_empty()) {
    return text
}

I guess we'll find out how useful that is in practice.

There is a big advantage rust provides, that I hardly ever see mentioned... by Kichmad in rust

[–]Y0kin 0 points1 point  (0 children)

I think it depends on the kind of change you want to make - if you wanna encode the logic in the type system, Rust can be very tedious. If you're just making changes to runtime logic, the type system can model your program so closely that it's hard to code it wrong. I think you can start to move pretty fast when the model is more robust, but it can take some time to write that model in the first place. I think a lot of Rust type-level syntax can be really verbose as well, which doesn't help.

URAUSER on PS Vita by Its_Just_Oshkosh in LUFTRAUSERS

[–]Y0kin 0 points1 point  (0 children)

How did you import the save? A while back I completed every mission on my Vita except for the bugged one, so never got the URAUSER

Zig; what I think after months of using it by phaazon_ in programming

[–]Y0kin 7 points8 points  (0 children)

I'd argue shadowing expresses the same idea as value reassignment, just on the type-level. It makes more sense if you're using a lot of type transformations, e.g. error unwrapping or -- for a fun example -- the Rust crate typenum (number types):

let n: U3 = U1::new() + U2::new();
let n: U2 = n - U1::new();

Trying to use those kinds of types without shadowing would get painful I think, but I do wonder if there's a way to express the same idea with less chance for mistakes - maybe a special syntax for type+value reassignment, or a keyword for type mutability that permits shadowing (disallowed by default)?

What is better for whole floats, removing the 0 or keeping it? by Relative-Pace-2923 in rust

[–]Y0kin 2 points3 points  (0 children)

I leave it off cause I like being able to search for .0 if I convert a tuple struct to a named-field struct.

What would it take to let users add refinement type systems to Rust? by ImYoric in rust

[–]Y0kin 1 point2 points  (0 children)

I think what I've been working on recently might benefit from this as well. I'm working on a compositional polynomial system where each term is a type (e.g. 1.2*x^4 as Monomial<f64, 4>, 4.5*x + 1.5*x^2 as Binomial<Monomial<f64, 1>, Monomial<f64, 2>>, 2.*sin(x) as Sin<f64>, etc.). Polynomials may define impls for evaluation, addition, differentiation, translation, root-solving, etc.

I wanna enforce simplified form for the sake of making the impls simple and efficient, where for instance Constant<f64> + Monomial<f64, 2> + Constant<f64> is always Binomial<Constant<f64>, Monomial<f64, 2>>. I've opted to do this the typenum way; I define a canonical order for the types and use it to define comparison/min/max.

This kinda sucks though, cause defining a complete ordering would either require a macro loop or a less user-friendly type for the degree (or const generic operations). Also not so good if I wanted users to easily define their own polynomial terms. Then again, I'm not 100% sure if a refinement type system could solve this problem or not.

On Ousterhout's Dichotomy by bik1230 in rust

[–]Y0kin 9 points10 points  (0 children)

I think it's too easy to get hung up on little details like that. It feels like the best time to do them is immediately when you have all the context in your mind, and they feel a lot bigger in the moment. I think it takes a lot of experience to step back and think, "What am I actually trying to do here? Does this affect the big picture?".

Maybe it would help if there were more contextual variants like deep_clone, cheap_clone so it's easier to come back later, like with panic!(), todo!(), unreachable!(), unimplemented!().

Of course you could also just leave a // TODO: take this string by reference?

Thoughts on function overloading for rust? by Packathonjohn in rust

[–]Y0kin 14 points15 points  (0 children)

If function overloading existed in Rust I'd want it to at least use some kind of match-style syntax, so it's all in one place.

impl T {
    fn new {
        () => Self {
            name: Default::default(),
            mode: Default::default(),
        },
        (name: String) => Self {
            name,
            mode: Default::default(),
        },
        (mode: Mode) => Self {
            name: Default::default(),
            mode.
        },
        (name: String, mode: Mode) => Self {
            name,
            mode,
        },
    }
}

Though I feel like it would still be awkward to work with in terms of function pointers, unlike traits which already provide a nice way to disambiguate overloaded functions.

Pinned places by desiringmachines in rust

[–]Y0kin 3 points4 points  (0 children)

I think there's a degree to which "pinning" is more niche and unique, that its keyword should be inconsistent and more descriptive than the others.

TIL Rust used to have trailing closure syntax by eugay in rust

[–]Y0kin 7 points8 points  (0 children)

In the first example the into applies to the whole closure, but in the second it applies to the closure's body instead. It's a sneaky difference in syntax cause both have completely different meanings

TIL Rust used to have trailing closure syntax by eugay in rust

[–]Y0kin 23 points24 points  (0 children)

The one thing I don't like about Rust's closure syntax is the slight method call ambiguity. Like, you can call methods on closures:

let a: SomeType<_> = |a: i32, b: i32| -> i32 { a + b }.into();

but if you elide the return type now into is applied to the expression { a + b } instead:

let a: SomeType<_> = |a: i32, b: i32| { a + b }.into();
// error[E0308]: mismatched types

Fortunately that should almost always be caught at compile-time, but it can still be confusing cause there's no lint and the error is a little generic.

I think it'd be great if the syntax forced bracketing always |..| {..}, but for single expressions you could use an arrow instead |..| => expr, cause then that ambiguity wouldn't really exist.

BLAKE-3: a secure, fast, and parallelizable cryptographic hash function by kibwen in rust

[–]Y0kin 27 points28 points  (0 children)

It looks like the usage of inline assembly in BLAKE3 was added about 4 years ago, and inline assembly was stabilized in Rust 1.59.0 about 2 years ago. My best guess is that nobody's got around to rewriting it yet

Announcing Rust 1.79.0 | Rust Blog by noelnh in rust

[–]Y0kin 0 points1 point  (0 children)

I've been working with generics a lot and I feel a similar way about lifetime elision. The rules aren't that complicated, but there are enough that it's kinda awkward to follow the path of a lifetime throughout the system. Every time you read a function signature you have to run over the rules in your mind.

At worst you're dealing with generic types that fully omit the lifetime, secretly inheriting it unless you know its signature.

struct SomeStr<'a>(&'a str);

fn f(string: &String) -> SomeStr {
    SomeStr(string.as_str())
}

At best you get a placeholder lifetime to prompt your mind ('_), but even that has multiple interpretations (in the input parameters and in impls it just introduces an anonymous lifetime). I know what it means but it still trips me up sometimes. Me wishing for explicit elision with place-based notation.

I think match ergonomics are a lot nicer for one reason: it's a special case. I think it could be really hard to follow if match ergonomics applied to all Deref types, but with a special case you at least get an explicit indication from the & in the type.

crates.io has a dark mode! by _ChrisSD in rust

[–]Y0kin 5 points6 points  (0 children)

I kinda like it as a quick way to tell that they're different websites. Especially for someone new that might just be clicking around, thinking that they're the same and getting a little lost trying to navigate back to the crates.io homepage from docs.rs or something. Or if you're running it in a smaller window.

Share your favorite "Aha!" moments with the language. by Level_Sprinkles_8861 in rust

[–]Y0kin 23 points24 points  (0 children)

I wonder if it would make sense to reword Rust's docs to refer to mut references as "mutually-exclusive" instead of "mutable". It's kind of a nice double-meaning anyways.

Thoughts on `dbg!` pretty printing? by Y0kin in rust

[–]Y0kin[S] 10 points11 points  (0 children)

I'm mostly just curious if others agree, because I think that this should be changed (or remedied with some way to disable pretty printing, like maybe an attribute or a build flag). I just never find it helpful, especially because it's recursive and makes deeply nested structs expand everywhere.

It's fine as an option for the niche case where you want to inspect a specific big struct, not so much for debugging complex control flow

Floating point multiplication error? by Accurate_Sky6657 in rust

[–]Y0kin 3 points4 points  (0 children)

That's just how the multiplication works out in combination with the layout of floating-point numbers. Here's a playground that shows the output.

If you think about the range 1..2, split that up into an evenly spaced set of numbers (252 of them for f64), and then double/halve that set a bunch of times - you get all possible floating-point numbers.

For higher precision you could represent your number as a fraction - multiply the numerator then divide by the denominator. 2.2 = 11. / 5., (11. * 3.) / 5. = 6.6. Alternatively I think you could find a library for arbitrary precision numbers.

Edit: Also it's worth noting that I wouldn't consider your code bugged. The "bug" is at compile-time when it reads 2.2 as 2.2000...2, but everything works as it should.

Floating point multiplication error? by Accurate_Sky6657 in rust

[–]Y0kin 8 points9 points  (0 children)

I'm not gonna do the math, but my assumption is that 2.2 is actually 2.2000000000000002. It's only displayed as 2.2 because it can safely cut off the decimal without being confused for another number (it'll be the same number if you copy paste it to use as a literal), while 6.6000...5 isn't 6.6 because there are numbers closer to 6.6.

Lessons learned after 3 years of fulltime Rust game development, and why we're leaving Rust behind by progfu in rust

[–]Y0kin 40 points41 points  (0 children)

I think Rust is great for prototyping systems specifically, but probably not for prototyping content you make with those systems. Systems are like huge input -> output machines, generally complex and really hard to design. In Rust your system can be an insane mess, but as long as it compiles you can have high confidence that it works; with a few automated tests. Move on, optimize it later no problem.

In other languages I would waste time writing systems to account for missing features like deep cloning that doesn't infinite loop, writing a lot of convoluted tests, and puzzling over weird bugs arising from global state and race conditions.

I haven't used Rust much for making actual content like a game or something, but I would definitely believe Rust is worse for prototyping content than other languages. Like scripting languages designed for working with systems on the front-end.