6 releases (breaking)
new 0.10.0 | Nov 22, 2024 |
---|---|
0.9.0 | Nov 21, 2024 |
0.8.0 | Nov 21, 2024 |
0.7.0 | Nov 21, 2024 |
0.1.0 | Nov 17, 2024 |
#27 in #randomness
85 downloads per month
Used in rhyme-type
36KB
431 lines
rand-construct
rand-construct
is a Rust crate that provides a derive macro to automatically implement traits for generating random instances of your types. It allows you to easily generate random enums and structs, with customizable probabilities for enum variants, and supports custom environments to influence randomness.
Features
- Automatic Trait Implementation: Derive
RandConstruct
for your enums and structs. - Customizable Probabilities: Specify default unnormalized probabilities for enum variants using attributes.
- Custom Environments: Create environments to alter probabilities for random generation.
- Easy Integration: Seamlessly integrates with the
rand
crate for randomness.
Getting Started
Add Dependency
Add the following to your Cargo.toml
:
[dependencies]
rand-construct = "0.6.0" # Replace with the latest version
Import the Crate
In your Rust file, import the necessary traits and macros:
use rand_construct::{RandConstruct, RandConstructEnvironment};
Usage
Deriving RandConstruct
for Enums
You can automatically implement random construction for your enums by using the #[derive(RandConstruct)]
macro. You can also specify default unnormalized probabilities for each variant using the #[rand_construct(p = value)]
attribute.
use rand_construct::RandConstruct;
#[derive(RandConstruct, Debug)]
enum Weather {
#[rand_construct(p = 5.0)]
Sunny,
#[rand_construct(p = 2.0)]
Rainy,
#[rand_construct(p = 1.0)]
Cloudy,
#[rand_construct(p = 0.5)]
Snowy,
}
fn main() {
let random_weather = Weather::random();
println!("Random Weather: {:?}", random_weather);
}
Explanation
#[derive(RandConstruct)]
: Automatically implements random construction forWeather
.#[rand_construct(p = value)]
: Sets the default weight for each variant.Weather::random()
: Generates a random instance ofWeather
based on the specified probabilities.
Deriving RandConstruct
for Structs
For structs, you can derive RandConstruct
, and the macro will automatically implement the trait by generating random instances of each field.
use rand_construct::RandConstruct;
#[derive(RandConstruct, Debug)]
struct Dimensions {
width: u32,
height: u32,
}
fn main() {
let random_dimensions = Dimensions::random();
println!("Random Dimensions: {:?}", random_dimensions);
}
Note
- All fields in the struct must implement
RandConstruct
. - For primitive types like
u32
,RandConstruct
is implemented by default.
Creating and Using Environments
You can define custom environments to alter the probabilities of random generation. This is useful when you want different contexts to influence the randomness.
Defining an Environment
First, derive RandConstructEnvironment
for your environment struct:
use rand_construct::RandConstructEnvironment;
#[derive(RandConstructEnvironment)]
struct DesertEnvironment;
Then, use the rand_construct_env!
macro to define custom probabilities for your enums within this environment:
use rand_construct::{rand_construct_env, RandConstruct};
#[derive(RandConstruct, Debug)]
enum Animal {
#[rand_construct(p = 1.0)]
Camel,
#[rand_construct(p = 1.0)]
Scorpion,
#[rand_construct(p = 1.0)]
FennecFox,
}
rand_construct_env! {
DesertEnvironment => Animal {
Camel => 5.0,
Scorpion => 3.0,
FennecFox => 2.0,
}
}
Using the Environment
You can now generate random instances using the custom environment:
fn main() {
let desert_animal = Animal::random_with_env::<DesertEnvironment>();
println!("Desert Animal: {:?}", desert_animal);
}
Explanation
#[derive(RandConstructEnvironment)]
: MarksDesertEnvironment
as a custom environment.rand_construct_env!
: Defines custom probabilities forAnimal
variants withinDesertEnvironment
.Animal::random_with_env::<DesertEnvironment>()
: Generates a randomAnimal
using the probabilities defined inDesertEnvironment
.
Full Example with Environment
use rand_construct::{RandConstruct, RandConstructEnvironment, rand_construct_env};
#[derive(RandConstruct, Debug)]
enum Terrain {
#[rand_construct(p = 1.0)]
Sand,
#[rand_construct(p = 1.0)]
Rock,
#[rand_construct(p = 1.0)]
Oasis,
}
rand_construct_env! {
DesertEnvironment => Terrain {
Sand => 8.0,
Rock => 2.0,
Oasis => 1.0,
}
}
fn main() {
let random_terrain = Terrain::random_with_env::<DesertEnvironment>();
println!("Random Terrain in Desert: {:?}", random_terrain);
}
Output
Random Terrain in Desert: Sand
Attributes
#[rand_construct(p = value)]
- Applies to: Enum variants.
- Purpose: Sets the default weight (unnormalized probability) for the variant.
- Default: If not specified, the default weight is
1.0
.
Example
#[derive(RandConstruct, Debug)]
enum Beverage {
#[rand_construct(p = 3.0)]
Water,
#[rand_construct(p = 1.0)]
Soda,
#[rand_construct(p = 0.5)]
Juice,
Coffee, // Default weight is 1.0
}
Advanced Usage
Generating Uniform Random Instances
You can generate random instances with uniform probabilities using the uniform
method:
use rand_construct::RandConstruct;
fn main() {
let uniform_weather = Weather::uniform();
println!("Uniform Weather: {:?}", uniform_weather);
}
Using a Custom Random Number Generator
You can generate random instances using a custom random number generator:
use rand::rngs::StdRng;
use rand::SeedableRng;
use rand_construct::RandConstruct;
fn main() {
let mut rng = StdRng::seed_from_u64(42);
let random_weather = Weather::random_with_rng(&mut rng);
println!("Random Weather with Custom RNG: {:?}", random_weather);
}
Limitations
- Enums with Non-Unit Variants: The derive macro for enums currently supports only unit variants (variants without associated data).
- Field Types: All fields in structs must implement
RandConstruct
.
Integration with the rand
Crate
rand-construct
integrates seamlessly with the rand
crate. It uses rand
under the hood to generate random values.
License
This project is licensed under the Apache 2.0 License. See the LICENSE file for details.
Contribution
Contributions are welcome! Please open an issue or submit a pull request on GitHub.
Acknowledgments
- Inspired by the need to simplify random instance generation for Rust types.
- Utilizes procedural macros to reduce boilerplate.
Dependencies
~2.5MB
~54K SLoC