icu4x icon indicating copy to clipboard operation
icu4x copied to clipboard

Add explicit cases to `PluralCategory`

Open robertbastian opened this issue 1 year ago • 1 comments
trafficstars

Explicit 0 and 1 cases are required by patterns in multiple components.

robertbastian avatar Aug 21 '24 21:08 robertbastian

  • @robertbastian worried if we don't put in the enum, every caller of PluralElements you will forget to check for the specific cases (if you only handle general cases).
  • @sffc You should have a new enum:
enum PluralCategoryExtended {
    PluralCategory(PluralCategory),
    Explicit0,
    Explicit1,
}

impl PluralRules {
    pub fn select_from_plural_elements<T>(&self, op: PluralOperands, choices: &PluralElements<T>) -> T {
        let category = self.category_for(op);

        if op.is_exactly_one() {
            if let Some(value) = choices.get_explicit1() {
                return value;
            }
        }
        // same for zero
        
        
        choices.get(category)    
    }
    
    /*
    pub fn select_with_explicit(&self, op: PluralOperands) -> (Option<Explicit>, PluralCategory) {
        let category = self.category_for(op);

        if op.is_exactly_one() {
            if let Some(value) = choices.get_explicit1() {
                return (Some(Explicit::One), category);
            }
        }
        // same for zero
        
        (None, category)  
        // ...
    }
    */
}

// in icu::plurals
pub struct PluralElements<'a, T: ?Sized> {
    pub other: &'a T,
    pub zero: Option<&'a T>,
    // ...
}

// in icu::plurals::provider
impl PluralElementsV1<T> {
    pub fn get(&self, op: PluralOperands, rules: &PluralRules) -> &T {
        let category = rules.category_for(op);

        if op.is_exactly_zero() {
            if let Some(value) = self.get_explicit0() {
                return value;
            }
        }
        if op.is_exactly_one() {
            if let Some(value) = self.get_explicit1() {
                return value;
            }
        }
        
        
        self.get(category)   
    }
    
    pub fn new(builder: PluralElements<T>) -> Self where T: PartialEq {}
}

  • @robertbastian I've been working with a new struct named PluralElements; could that be the argument?
  • @robertbastian PluralCategoryExtended would need to be repr(u8)
  • @Manishearth We could make that the public interface and have a repr(u8) internal enum
  • @robertbastian For now it can be private
  • @younies So do we change call sites from PluralCategory to PluralCategoryExtended?
  • @robertbastian We need to change call sites so pass PluralOperands and PluralRules instead of a preresolved PluralCategory
  • @younies I believe in CurrencyCompact, you fallback for other if other doesn't exist. Then you go to the display name
  • @robertbastian - If other doesn't exist, none of the cases exist and you cannot construct a PluralElements
  • @robertbastian for current constructors for PluralElements, you pass in Options for everything
  • @sffc We should make the constructor be non-exhaustive so we can add more explicit cases
  • @robertbastian That's not defined in CLDR, leads to less optimization if it's non exhaustive. This is going to be used everywhere, we should really optimize
  • @sffc May not be the case in the future. It should be just as easy to support 2 as we could support 5 cases. I think we can cap it at 4 bits (16 variants)
  • @sffc Or maybe PluralElementsV1 should just be the VarULE of PluralElements?
  • @robertbastian Is it okay for PluralElementsV1 to deduplicate and not round-trip?
  • @Manishearth Equality?
  • @robertbastian We can write custom Eq impls.
  • @manishearth - then yes
  • @sffc Should it be called PluralElementsBorrowed?
  • @robertbastian I don't think there should be an owned version because it is just a plural arguments bag.

Decision:

  • Create icu::plurals::PluralElements, a non-exhaustive struct with a bunch of Option fields
  • PluralRules gets a function that processes PluralElements
  • Create icu::plurals::provider::PluralElementsV1, a data struct that represents the same data in a more compact way, with private fields
  • We will migrate PluralElementsV1 to https://github.com/unicode-org/icu4x/issues/5378. Unclear whether we will make PluralElementsV1 itself a VarULE or make a separate VarULE.
  • PluralElementsV1 gets a function that takes a &PluralRules and could have a more optimized algorithm, or could internally convert to PluralElements

LGTM: @robertbastian @sffc

sffc avatar Aug 22 '24 16:08 sffc