Skip to content

[Feat]: Add default types for Either variants, as well as adding OneOfExt trait on impl View #4320

@jquesada2016

Description

@jquesada2016

Is your feature request related to a problem? Please describe.

Currently, when returning different views from, say a match expression, we must use EitherOfN enum to unify the types. This absolutely works, but I think we can make it a bit better.

The roughness I've encountered is one with the following workflow:

  1. I start with the following enum:
enum Example {
  A,
  B,
}
  1. I start with a match:
match ex {
  Example::A => Either::A(view_1),
  Example::B => Either::B(view_2),
}
  1. I add a new variant:
enum Example {
  A,
  B,
  C,
}
  1. ...now I have to update my imports to use EitherOf3 rather than `EitherOf2``
    and I try the following:
match ex {
  Example::A => EitherOf3::A(view_1),
  Example::B => EitherOf3::A(view_2),
  Example::C => todo!(),
}
  1. ...which of course won't compile because EitherOf3 is missing a type annotation.

To get around this specific issue, we can add a default generic type of () to all the Either enums.

Now, this would definitly improve the todo!() issue I often run into, but it still doesn't help that in all my match arms, I need to either wrap the view! {} in an Either directly, or assign the view to a variable and return it wrapped in an Either variant. This is quite frankly annoyingggggg.

I propose introducing a new enum, called OneOf that should have an arbitrarily large number of variants, say 128, with all default generics set to () as well as introducing an IntoOneOf trait that can be added to any view to wrap it in postfix notation.

Example:

enum OneOf<_0 = (), _1 = (), _2 = (), _3, /* ... */ _127 = ()> {
  A(_0),
  B(_1),
  C(_2),
  D(_3),
  /* ... */
  DX(_127),
}

trait IntoOneOf</* ... */> {
  fn a(self, a: _1) -> OneOf</* ... */>;
  fn b(self, b: _2) -> OneOf</* ... */>;
  /* ... */
  fn dx(self, dx: _127: _127) -> OneOf</* ... */>;
}

impl</* ... */> IntoOneOf</* ... */> for V
where 
  // Only ristrict V here so users don't get intellisense where it's not applicable.
  V: IntoView,
{
  /* ... */
}

Given this, the above match arm can be written as:

match ex {
  Example::A => view_2.a(),
  Example::B => view_2.b(),
  Example::C => todo!(),
}

The above should compile just fine.

To be honest, after writing this, I definitely wouldn't name the functions a(), b(), etc. Perhaps .one_of_a(), or .into_one_of_a().

Also, the reason for using OneOf with a large number of variants is just to avoid needing to import a different EitherN enum for the respective cardinality I need. This also would not replace Either, as it's still very useful for matching on a specific number of children, or similar. I just think this would be a bit nicer DX.

Let me know what you think!

Describe the solution you'd like

Lol I always struggle to seperate my problems from my solutions. Please see above.

Describe alternatives you've considered

The alternative would be to stick to using the any view extension function, at the cost of the fancy dandy view types used currently.

Additional context

N/A

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions