Rust build Crates.io

degeneric-macros

Quick Start

```rust use degenericmacros::{Degeneric, namedrequirement}; use std::marker::PhantomData;

named_requirement!(FactoryFn: 'static + Send + Sync + Fn() -> T);

[derive(Degeneric)]

struct Container, B> { a: A, b: B, c: u32, _t: PhantomData, }

fn my_fact() -> String { format!("hello world!") }

let c = Container::builder() .witha(myfact) .withb(true) .withc(20) .with__t(Default::default()) .build();

fn dosomething(c: impl ContainerTrait) {} fn accessinnertypes(c: C) { let sameas_a: C::A; } ```

Elevator pitch

The problem

Degeneric is a utility library that solves the common problem of having too many generics. Let's say we want to construct a dependency container like this: ```rust struct Container { logger: Logger, client: HttpClient, // ...and so on... }

let container = Container { logger: String::from("logger"), client: String::from("http"), };

acceptscontainer(container); // now to consume such a container, one needs to write the function like this: fn acceptscontainer(c: Container) {} ```

This creates a problem of ever growing list of generics in all functions that touch the container and pollutes APIs with unnecessary generics.

Degeneric solution

Degeneric proposes solution to this problem by creating a trait and stuffing all of the generic types into the trait as associated types. Instead of the pattern above, you'll end up with this: ```rust use degeneric_macros::Degeneric;

[derive(Degeneric)]

struct Container { logger: Logger, client: HttpClient, }

let c = Container::builder() .withlogger(String::from("logger")) .withclient(String::from("http")) .build();

acceptscontainer(c); fn acceptscontainer(c: impl ContainerTrait) {} ```

How is this different, you ask? Instead of accepting a whole lot of generic arguments, I can now write the function without even using angular brackets and I think that's beautiful. What is even more beautiful is that you can add more generics without having to modify the signature of accepts_container.