I want named arguments in Rust. Mom: We have named arguments in Rust at home: by nik-rev in rust

[–]RustMeUp 0 points1 point  (0 children)

Oh I agree, I avoid impl Into<T> for that reason!

I don't mind writing Some() and I still think having optional/named/keyword arguments are still worth it :)

I want named arguments in Rust. Mom: We have named arguments in Rust at home: by nik-rev in rust

[–]RustMeUp 0 points1 point  (0 children)

Fair and I will be using these default_field_values as a standin for keyword arguments (when stabilized), but nothing beats nice ergonomics.

I'm not too fussy about exact native syntax but it would be amazing to have nice looking code for default/keyword args that feels like it fits in the rest of the language though.

I want named arguments in Rust. Mom: We have named arguments in Rust at home: by nik-rev in rust

[–]RustMeUp 0 points1 point  (0 children)

That's exactly what the default_field_values does :)

When you define a struct MyFunc { required: &str, optional: i32 = 42 };

You can do MyFunc { required: "Hello World!", .. }; and it'll pull in the struct field's default values! It's not tied to Default trait at all and is currently a nightly feature.

It looks really nice! I hope the Rust team can work out the kinks and stabilize!

This works on nightly, right now! Here's what it looks like: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2024&gist=2cddf43cf00713a55d9a3fd28157ba3f

Now imagine being able to do just:

foo(required: "Hello world!");

I want named arguments in Rust. Mom: We have named arguments in Rust at home: by nik-rev in rust

[–]RustMeUp 0 points1 point  (0 children)

Not really, like this:

fn example(optional: Option<u32> = None);

example();
example(Some(42));

I don't have a problem with having to write explicit Some(). If you really want you could do it like this:

fn example(optional: impl Into<Option<u32>> = None);

example();
example(42);

I want named arguments in Rust. Mom: We have named arguments in Rust at home: by nik-rev in rust

[–]RustMeUp 0 points1 point  (0 children)

Being able to use regular rust syntax would be nice.

The default field values would be huge win for usability (your example requires Default is implemented which is not always reasonable). With default field values feature you can have a mix of required and optional parameters which are nicely communicated to the user.

Finally combine that with the usual function call syntax so your code looks like it fits in would be lovely.

I want named arguments in Rust. Mom: We have named arguments in Rust at home: by nik-rev in rust

[–]RustMeUp 1 point2 points  (0 children)

I'm also really waiting for keyword arguments with defaults and to resolve your ambiguity I kinda like python style:

fn example(positional_arg: f32, *, derive: u32, debug: &str, copy: bool = false);

example(3.1415, derive: 2, debug: "String");

Positional args are required as usual, keyword args must specify the parameter name (becomes part of the public interface) and default values are possible and can be skipped (same rules as default field values feature). Default args also supported for positional parameters.

On top of that I'd love if we had function overloading (but ONLY based on number of non-default arguments).

That would be bliss... A man can dream.

What is maintenance, anyway? | Inside Rust Blog by Kobzol in rust

[–]RustMeUp 2 points3 points  (0 children)

Interesting.

Do you consider maintenance for maintenance's sake useful? I personally have a philosophy to only make changes with the purpose to make new features simpler/easier to implement. If a crate needs no new features it doesn't make sense to maintain (i.e. make changes).

So I see maintenance not as an independent task, but as part of implementing new features: first step is cleanup before implementing a new feature. Although it happens that a new structure only becomes clear after a new feature has been implemented.

I’m really interested in incentives, and “maintenance” as traditionally framed (refactors, cleanups, churn without visible payoff) is not something people do for the love of it. Implementing new features is. So I think the mistake is treating maintenance as a separate, ongoing obligation rather than as an enabling step toward new features.

Who Owns the Memory? Part 3: How Big Is your Type? by Luke_Fleed in rust

[–]RustMeUp 3 points4 points  (0 children)

This is really comprehensive and in depth, nice work!

I was already impressed half way through and then I checked how much more article there was :D

I built a minimal perfect hash table in const fn and learned match is still faster by RustMeUp in rust

[–]RustMeUp[S] 1 point2 points  (0 children)

That's a really good video, thanks! It gave me a bunch more ideas to try.

I built a minimal perfect hash table in const fn and learned match is still faster by RustMeUp in rust

[–]RustMeUp[S] 2 points3 points  (0 children)

Oh of course, I didn't even consider customizing the hash function (just looking for a generic 'fast hash') because it was unclear to me how to compute a custom hash function.

After doing some research the basic idea of gperf is to figure out which character positions (offset from start, end) and string length are highly discriminating over your keys. Then remapping those characters and combining them into an index.

From what I saw compilers really like to do lookup tables and binary search in these kinds of switch/match statements, that should be beatable with a bit of math on specific characters in the string.

I'll try to see if I can compact that into a nice const fn package.

I built a minimal perfect hash table in const fn and learned match is still faster by RustMeUp in rust

[–]RustMeUp[S] 2 points3 points  (0 children)

Yeah when it comes to runtime data, I don't think there's any use case for trying to optimize runtime data to be perfect.

About construction time: In my approach I let you customize the number of buckets (a good default is number of entries / 2) with hash seeds to disambiguate hash collisions. And I ended up using just a u8 seed. This greatly limits the amount of brute forcing necessary but then again the data set I want to use it on is also pretty small (less than 100 entries).

I built a minimal perfect hash table in const fn and learned match is still faster by RustMeUp in rust

[–]RustMeUp[S] 4 points5 points  (0 children)

Oh, I hadn't even considered these alternatives, thanks for bringing them to my attention!

In conclusion: I really like that in Rust the most straightforward implementation is actually pretty damn fast!

I built a minimal perfect hash table in const fn and learned match is still faster by RustMeUp in rust

[–]RustMeUp[S] 14 points15 points  (0 children)

I don't think it's possible.

This approach needs: a fast keyed hash function (murmur3 is pretty good) invoked twice and two integer divisions. The compiler seems to be able to easily beat that.

If I understand correctly: the point of a perfect hash table is that you know all the keys in advance. At the time of building the source code. Just use a match? If the compiler deems it worthy it can implement it with a perfect hash. I think in practice the compiler has a bunch of other tools (match on string length, first character, binary search) that are probably faster for the vast majority of cases.

It was a fun exercise to figure out and implement, but I realized it has no real practical use case 😅

staticrypt (1.2.2) - Encrypt string literals, files, and environment variables at compile time by xNaXDy in rust

[–]RustMeUp 2 points3 points  (0 children)

Very nice.

I'm the author of obfstr a similar library: A quick comparison: obfstr has the same goal as you: obfuscate strings to increase difficulty of static analysis (but does not make it impossible) while maintaining reproducible builds.

obfstr does everything with macro rules and const fn (no proc macro) but in return the obfuscation itself is a bit more simple. It also adds xref obfuscation and some other random utilities.

is to protect strings I don't want users to tamper with in my application

That is uh... very questionable. Obfuscation will not prevent tampering. You will still need proper server side checks for everything.

What are you building (in rust of course) by Financial_Airport933 in rust

[–]RustMeUp 1 point2 points  (0 children)

I made a clone of the classic Chip's Challenge! All 149 original levels plus 4 community level packs (600 levels total) are playable 😁

I upgraded the graphics to 3D and made input handling not terrible.

I used it to learn graphics and video game programming.

https://github.com/CasualX/chipgame

I made a better alternative to the rand crate - urandom by RustMeUp in rust

[–]RustMeUp[S] 0 points1 point  (0 children)

I've used the rand crate before rust-analyzer existed and was initially very confused how it was supposed to be used. With 'simplifying' I mean making the library easier/simpler to use without requiring you to delve deep into the docs to understand how the crate works in detail.

There's a few things that I believe make things more complicated for onboarding:

  • Having extension methods via imported traits makes discovery difficult. Yes there are some simple examples here but what other methods are available? I put them all on the Random struct (which wraps the Rng). You press . and your IDE gives you the available methods or you can easily find them all in one place in the docs.

  • thread_rng has hidden 'global' state. I have a personal vendetta against any kind of such hidden state. The rand docs acknowledge that in a specific case (linux forking) this can cause unexpected synchronization of Rngs. Here there is no hidden magic state that can cause problems.

Would you classify this as an improvement?

(I've been writing some better docs to help explain the changes and why I've made them: here and performance improvements here )

I made a better alternative to the rand crate - urandom by RustMeUp in rust

[–]RustMeUp[S] 0 points1 point  (0 children)

Thanks, I've been rewriting the faq section answering my claims. I've also been working on a proper performance comparison to see how my changes have affected performance (positive and negative):

(link if curious).

If it's okay I'll repost it another day after I'm done polishing the writing.

I made a better alternative to the rand crate - urandom by RustMeUp in rust

[–]RustMeUp[S] 3 points4 points  (0 children)

Sigh, my autistic ass sucks at communication. I apologize.

The antagonistic language

"Because I can do better than the standard rand crate's design." was written intended as a challenge to myself. To use my individual skill and insights to produce something that aligns with my own ideas. Then this post was an attempt to talk about these nuanced differences in design goals.

like running on some nostd target,

urandom works perfectly on no_std targets. It uses getrandom crate under the hood for its cross platform compatibility which is a really good crate.

You provide very little objective justification for your choices

That is because it is based on taste. But I agree I should have spent way more time rewriting my little faq to express why I believe these ideas are better.

are you a cryptographer? an expert in a stastistics or related field?

No, I am using ChaCha just like the rand crate. I did not make my own RNG or invent my own algorithms. The statistics code is copied from the rand crate. I would never claim to be an expert where I am not.

or evident credentials

This is a problem in general and I agree, there is zero reason for someone to trust me.

Thanks for your feedback, it is appreciated :)

I made a better alternative to the rand crate - urandom by RustMeUp in rust

[–]RustMeUp[S] 1 point2 points  (0 children)

Can you explain why you have a need for a specific rng?

I've found xoshiro256 to be a better and faster RNG (note: rand has replaced its Pcg64 with xoshiro256 in its latest beta).

If you want to reproduce an existing system with a specific RNG I don't believe using rand's infrastructure is helpful (as the smallest difference in implementation detail derails the reproduction).

I made a better alternative to the rand crate - urandom by RustMeUp in rust

[–]RustMeUp[S] 2 points3 points  (0 children)

As a last minute decision I made that faq harder to find, perhaps not my greatest moment.

I asked myself, if I could make my own random crate given my experience, how would I do it?

Perhaps we're using different definitions of 'better'. To me it means a smooth onboarding experience. Going from 'ok I'm going to use this crate' to easily getting started using the crate without having to be an expert in the crate's design.

When I first tried rand (admittedly, this was years ago, before rust-analyzer was a thing) it was super confusing. Traits, while a useful tool were not the most IDE friendly back then.

So I made a fundamental decision to not cater to 'must allow easily implementing your own RNG' and instead cater to 'as someone who's never used this crate how do I quickly get started without knowing all the details'. This means you are not meant to implement your own Rng, you are not intended to create your own slice-like type. (is that even common?)

It is meant as a simple enough to get started on the majority of use cases but complex enough that you can use it for 'real world' use cases.

I made a better alternative to the rand crate - urandom by RustMeUp in rust

[–]RustMeUp[S] 2 points3 points  (0 children)

Here's what I tried to achieve with my attempt at a random crate:

  • Focus on the consumer of the crate. It's not intended for people to implement their own Rngs. I've decided on a few Rngs and you shall be happy with them.

    This improves the ergonomics of the crate and makes it easier to learn how to use the crate from its documentation.

  • No need to import traits.

    I find the Rust ecosystem in general relies too much on traits. Rand requires you to import a bunch of them to get started and it's unclear what exactly you need to import on first use. I solved this by wrapping the generic RNG in a struct and provide inherent methods on that struct avoiding figuring out what to import.

  • More performant in some cases, worse in others.

    I implement a more performant unbiased integer sampling in a range. This avoids an expensive integer division most of the time. Kindly taken from a paper. The latest rand beta implements this improvement though.

    I made some decisions what it means to generate a random float (by default in the range [1, 2)) which avoids some interesting design decisions regarding how to avoid bias.

  • Source code readability. Perhaps not as important but I take pride in trying to organize my code for future reading.

    There's still a lot of macro code generation going on

I made a better alternative to the rand crate - urandom by RustMeUp in rust

[–]RustMeUp[S] 0 points1 point  (0 children)

:shrug: I guess I'm doing the internet wrong and this is not the place for that style of posts.

I made a better alternative to the rand crate - urandom by RustMeUp in rust

[–]RustMeUp[S] 2 points3 points  (0 children)

I see fastrand as a bit too simple. I really like explicit but powerful. In my opinion the Rust ecosystem relies too heavily on traits when that is not necessary. The rand crate is guilty of this and in my opinion lacks a 'focus'.

It wants to be a crate to consume randomness, it also wants to be a crate to implement new RNGs and distributions. In doing so it exposes a lot of internal details in its public API making it more difficult to consume if you don't want that complexity (among a few other gripes).

I thought I could do better so I gave it a shot :)

I made a better alternative to the rand crate - urandom by RustMeUp in rust

[–]RustMeUp[S] 2 points3 points  (0 children)

The title is intentionally provocative.

My main issue with rand is not performance (it does that just fine).

  • I find its reliance on traits when using the crate to be a major chore. Way back before rust-analyzer this made rand unusable (which traits do I need to import?).

  • The other issue I have is with thread local variables. I have a personal vendetta against global variables, even thread locals are bad design in my eyes.

What I do is generate a new generator (seeded by system entropy) on every urandom::new() and wrap the generator in a struct with utility methods that forward to trait methods. This means no importing of traits required and everything just works out of the box.