Repository: pola-rs/polars
File: crates/polars-expr/src/expressions/binary.rs (Rust)

Code before:
        Operator::EqValidity => left.equal_missing(right).map(|ca| ca.into_column()),
        Operator::NotEqValidity => left.not_equal_missing(right).map(|ca| ca.into_column()),
    }
}

impl BinaryExpr {
    fn apply_elementwise<'a>(
        &self,
        mut ac_l: AggregationContext<'a>,
        mut ac_r: AggregationContext<'a>,
        aggregated: bool,
    ) -> PolarsResult<AggregationContext<'a>> {
        // At this stage, there is no combination of AggregatedList and NotAggregated ACs.

        // Check group lengths in case of all AggList
        if [&ac_l, &ac_r]
            .iter()
            .all(|ac| matches!(ac.state, AggState::AggregatedList(_)))
        {
            ac_l.groups().check_lengths(ac_r.groups())?;
        }

        // The first non-LiteralScalar AC will be used as the base AC to retain the context
        let left_is_literal = ac_l.is_literal();

        match if !left_is_literal {
            ac_l.agg_state()
        } else {
            ac_r.agg_state()
        } {
            AggState::AggregatedList(s) => {
                let ca = s.list().unwrap();
                let cols = [&ac_l, &ac_r]
                    .iter()
                    .map(|ac| ac.flat_naive().into_owned())
                    .collect::<Vec<_>>();

                let out = ca.apply_to_inner(&|_| {
                    apply_operator(&cols[0], &cols[1], self.op)
                        .map(|c| c.take_materialized_series())
                })?;
                let out = out.into_column();

                if ac_l.is_literal() {
                    std::mem::swap(&mut ac_l, &mut ac_r);
                }

                ac_l.with_values(out.into_column(), true, Some(&self.expr))?;
                Ok(ac_l)
            },


Review comment (suggestion):
I would usually consider this quite an anti-pattern.

What you probably want is:

```rust
match (ac_l.agg_state(), ac_r.agg_state()) {
    (AggState::Literal(lit), AggState::AggregatedList(lst)) | (AggState::AggregatedList(lst), AggState::Literal(lit)) => {
        // ...
    },
    _ => {
    },
}
```

Code after:
        Operator::EqValidity => left.equal_missing(right).map(|ca| ca.into_column()),
        Operator::NotEqValidity => left.not_equal_missing(right).map(|ca| ca.into_column()),
    }
}

impl BinaryExpr {
    fn apply_elementwise<'a>(
        &self,
        mut ac_l: AggregationContext<'a>,
        mut ac_r: AggregationContext<'a>,
        aggregated: bool,
    ) -> PolarsResult<AggregationContext<'a>> {
        // At this stage, there is no combination of AggregatedList and NotAggregated ACs.

        // Check group lengths in case of all AggList
        if [&ac_l, &ac_r]
            .iter()
            .all(|ac| matches!(ac.state, AggState::AggregatedList(_)))
        {
            ac_l.groups().check_lengths(ac_r.groups())?;
        }

        match (ac_l.agg_state(), ac_r.agg_state()) {
            (_, AggState::AggregatedList(s)) | (AggState::AggregatedList(s), _) => {
                let ca = s.list().unwrap();
                let [col_l, col_r] = [&ac_l, &ac_r].map(|ac| ac.flat_naive().into_owned());

                let out = ca.apply_to_inner(&|_| {
                    apply_operator(&col_l, &col_r, self.op).map(|c| c.take_materialized_series())
                })?;
                let out = out.into_column();

                if ac_l.is_literal() {
                    std::mem::swap(&mut ac_l, &mut ac_r);
                }

                ac_l.with_values(out.into_column(), true, Some(&self.expr))?;
                Ok(ac_l)
            },

            _ => {
                // We want to be able to mutate in place, so we take the lhs to make sure that we drop.
                let lhs = ac_l.get_values().clone();
                let rhs = ac_r.get_values().clone();

                let out = apply_operator_owned(lhs, rhs, self.op)?;

                if ac_l.is_literal() {
                    std::mem::swap(&mut ac_l, &mut ac_r);
                }