Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Builder-style type constructors #697

Open
opfromthestart opened this issue Apr 11, 2023 · 9 comments
Open

Builder-style type constructors #697

opfromthestart opened this issue Apr 11, 2023 · 9 comments

Comments

@opfromthestart
Copy link
Contributor

I don't remember where I saw it but I saw an interesting way of making constructors for objects like

let x = Type::new().a(5).b(4);

instead of

let x = Type::new(5,4);

since it allows for adding parameters to a type without breaking an api, as well as being easier to read without relying on an ide. (Having functional constructors may be nice to have for ordinary

I was thinking that this would be useful with some complicated types (like Conv2D) to allow them to have minimal specification
So instead of Conv2D<64, 128, 3, 1, 2> it could be something like Conv2D<64, 128>::K<3>::S<1>::P<2>. This would allow only necessary values (eg Conv2D<64, 128>::K<3>::P<2> would infer a stride of 1) to be entered and allows values to be entered out of order.
I am not entirely sure that this can be done without requiring using traits (which would just make it look worse) but it may make certain types better to create.

It may be able to be done using associated constants and having builders be constants instead of types. This would obviously break everything else but it should allow arbitrary additions with no breaking changes.

@coreylowman
Copy link
Owner

Ahh yes this is the builder pattern. I really like the idea of doing it at type level, might have to play around with that to see how it's possible. Good idea!

@nkoppel
Copy link
Contributor

nkoppel commented Apr 12, 2023

I wonder if this is actually possible, because when try to do Type::Associated1<X>::Associated2<Y>, rust usually makes me do <Type::Associated1<X> as Trait>::Associated2<Y> to disambiguate

@opfromthestart
Copy link
Contributor Author

opfromthestart commented Apr 13, 2023

I was thinking that something like

struct Thing<const A: usize = 0, const B: usize = 0>;
impl<const A_: usize, const B_: usize> Thing<A_, B_> {
    const A::<const A2: usize> : Thing<A2, B_> = Thing::<A2, B_>;
    const B::<const B2: usize> : Thing<A_, B2> = Thing::<A_, B2>;
}

would work but you cant put generics on constants I guess. But it would work without needing traits, which was what I wanted to avoid.
I was looking at https://doc.rust-lang.org/reference/items/associated-items.html#associated-constants in the rust book

@opfromthestart opfromthestart changed the title "Functional" type constructors Builder-style type constructors Apr 13, 2023
@ViliamVadocz
Copy link
Contributor

ViliamVadocz commented Apr 15, 2023

You could have several intermediate types:

struct TypeA;
impl TypeA {
    fn a<const A: usize>() -> TypeB<A> { TypeB }
}
struct TypeB<const A: usize>;
impl<const A: usize> TypeB<A> {
    fn b<const B: usize>() -> TypeC<A, B> { TypeC }
}
struct TypeC<const A: usize, const B: usize>;
// etc.

@opfromthestart
Copy link
Contributor Author

That still isn't very satisfying since it either still requires having all arguments in order, or requires O(n^2) methods between all of the structs.

@opfromthestart
Copy link
Contributor Author

I could see something like that working if the current model system is completely overwritten, and instead of builders being types they are objects, but I don't know if that would work either.

@coreylowman
Copy link
Owner

Might be possible with rewrite in #854

@opfromthestart
Copy link
Contributor Author

It would be some, but my idea for this was to allow builder pattern even for const layers, so you can use the builder pattern on types at compile time instead of at runtime.

@swfsql
Copy link
Contributor

swfsql commented Nov 17, 2023

Somewhat related: It can be useful to see what generic parameters our generic arguments refer to, and there is a related issue on rust-analyzer: rust-lang/rust-analyzer#11091

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants