fn match_collapse_ddd<'a, S: Clone, NewT: Clone>(
        lhs: &'a Rc<Vec<EnvMBE<T>>>,
        lhs_ddd: &'a Option<usize>,
        rhs: &'a Rc<Vec<EnvMBE<S>>>,
        rhs_ddd: &'a Option<usize>,
        f: &dyn Fn(&T, &S) -> NewT,
        col: &dyn Fn(Vec<NewT>) -> NewT,
        red: &dyn Fn(NewT, NewT) -> NewT,
        base: NewT,
    ) -> NewT
    {
        let len_diff = lhs.len() as i32 - (rhs.len() as i32);

        // The RHS can have a DDD if it's exactly the same (subtyping only goes the one way)
        // TODO: if the user is rebuilding MBEs using `map_collapse_reduce_with`, they'll lose
        // the DDDs they should keep; how do we get that information back in? (I assume we pass
        // a bool to one of the function arguments.)
        if rhs_ddd.is_some() && lhs_ddd != rhs_ddd {
            panic!("RHS must match LHS exactly if it uses DDD")
        }

        let mut reduced = base.clone();
        // Unpack the DDD ... unless the RHS is a DDD also.
        if let (&Some(ddd_idx), false) = (lhs_ddd, rhs_ddd.is_some()) {
            if len_diff - 1 > 0 {
                panic!("abstract MBE LHS too long")
            }

            for i in 0..ddd_idx {
                reduced = red(
                    reduced,
                    lhs[i].map_collapse_reduce_with(&rhs[i], f, col, red, base.clone()),
                );
            }

            let mut ddd_rep = vec![];
            for rep in 0..((1 - len_diff) as usize) {
                ddd_rep.push(lhs[ddd_idx].map_collapse_reduce_with(
                    &rhs[ddd_idx + rep],
                    f,
                    col,
                    red,
                    base.clone(),
                ));
            }
            reduced = red(reduced, col(ddd_rep));

            for i in (ddd_idx + 1)..lhs.len() {
                let rhs_i = (i as i32 - len_diff) as usize;

                reduced = red(
                    reduced,
                    lhs[i].map_collapse_reduce_with(&rhs[rhs_i], f, col, red, base.clone()),
                );
            }
        } else {
            if len_diff != 0 {
                panic!("mismatched MBE lengths {} vs. {}", lhs.len(), rhs.len())
            }
            for i in 0..lhs.len() {
                reduced = red(
                    reduced,
                    lhs[i].map_collapse_reduce_with(&rhs[i], f, col, red, base.clone()),
                );
            }
        }
        reduced
    }
// The LHS must be the side with the DDD.
// TODO: try just using `reduced` instead of `base.clone()`
// TODO #15: `Result` instead of panicing
The LHS must be the side with the DDD.
The LHS must be the side with the DDD .
fn match_collapse_ddd<'a, S: Clone, NewT: Clone>(
        lhs: &'a Rc<Vec<EnvMBE<T>>>,
        lhs_ddd: &'a Option<usize>,
        rhs: &'a Rc<Vec<EnvMBE<S>>>,
        rhs_ddd: &'a Option<usize>,
        f: &dyn Fn(&T, &S) -> NewT,
        col: &dyn Fn(Vec<NewT>) -> NewT,
        red: &dyn Fn(NewT, NewT) -> NewT,
        base: NewT,
    ) -> NewT
    {
        let len_diff = lhs.len() as i32 - (rhs.len() as i32);
        // The RHS can have a DDD if it's exactly the same (subtyping only goes the one way)
        // TODO: if the user is rebuilding MBEs using `map_collapse_reduce_with`, they'll lose
        // the DDDs they should keep; how do we get that information back in? (I assume we pass
        // a bool to one of the function arguments.)
        if rhs_ddd.is_some() && lhs_ddd != rhs_ddd {
            panic!("RHS must match LHS exactly if it uses DDD")
        }
        let mut reduced = base.clone();
        // Unpack the DDD ... unless the RHS is a DDD also.
        if let (&Some(ddd_idx), false) = (lhs_ddd, rhs_ddd.is_some()) {
            if len_diff - 1 > 0 {
                panic!("abstract MBE LHS too long")
            }
            for i in 0..ddd_idx {
                reduced = red(
                    reduced,
                    lhs[i].map_collapse_reduce_with(&rhs[i], f, col, red, base.clone()),
                );
            }
            let mut ddd_rep = vec![];
            for rep in 0..((1 - len_diff) as usize) {
                ddd_rep.push(lhs[ddd_idx].map_collapse_reduce_with(
                    &rhs[ddd_idx + rep],
                    f,
                    col,
                    red,
                    base.clone(),
                ));
            }
            reduced = red(reduced, col(ddd_rep));
            for i in (ddd_idx + 1)..lhs.len() {
                let rhs_i = (i as i32 - len_diff) as usize;
                reduced = red(
                    reduced,
                    lhs[i].map_collapse_reduce_with(&rhs[rhs_i], f, col, red, base.clone()),
                );
            }
        } else {
            if len_diff != 0 {
                panic!("mismatched MBE lengths {} vs. {}", lhs.len(), rhs.len())
            }
            for i in 0..lhs.len() {
                reduced = red(
                    reduced,
                    lhs[i].map_collapse_reduce_with(&rhs[i], f, col, red, base.clone()),
                );
            }
        }
        reduced
    }
fn match_collapse_ddd < ' a , S : Clone , NewT : Clone > ( lhs : & ' a Rc < Vec < EnvMBE < T > > > , lhs_ddd : & ' a Option < usize > , rhs : & ' a Rc < Vec < EnvMBE < S > > > , rhs_ddd : & ' a Option < usize > , f : & dyn Fn ( & T , & S ) -> NewT , col : & dyn Fn ( Vec < NewT > ) -> NewT , red : & dyn Fn ( NewT , NewT ) -> NewT , base : NewT , ) -> NewT { let len_diff = lhs . len ( ) as i32 - ( rhs . len ( ) as i32 ) ; // The RHS can have a DDD if it's exactly the same (subtyping only goes the one way) // TODO: if the user is rebuilding MBEs using `map_collapse_reduce_with`, they'll lose // the DDDs they should keep; how do we get that information back in? (I assume we pass // a bool to one of the function arguments.) if rhs_ddd . is_some ( ) && lhs_ddd != rhs_ddd { panic ! ( " " ) } let mut reduced = base . clone ( ) ; // Unpack the DDD ... unless the RHS is a DDD also. if let ( & Some ( ddd_idx ) , false ) = ( lhs_ddd , rhs_ddd . is_some ( ) ) { if len_diff - 1 > 0 { panic ! ( " " ) } for i in 0 .. ddd_idx { reduced = red ( reduced , lhs [ i ] . map_collapse_reduce_with ( & rhs [ i ] , f , col , red , base . clone ( ) ) , ) ; } let mut ddd_rep = vec ! [ ] ; for rep in 0 .. ( ( 1 - len_diff ) as usize ) { ddd_rep . push ( lhs [ ddd_idx ] . map_collapse_reduce_with ( & rhs [ ddd_idx + rep ] , f , col , red , base . clone ( ) , ) ) ; } reduced = red ( reduced , col ( ddd_rep ) ) ; for i in ( ddd_idx + 1 ) .. lhs . len ( ) { let rhs_i = ( i as i32 - len_diff ) as usize ; reduced = red ( reduced , lhs [ i ] . map_collapse_reduce_with ( & rhs [ rhs_i ] , f , col , red , base . clone ( ) ) , ) ; } } else { if len_diff != 0 { panic ! ( " " lhs len ( ) rhs len ( ) ) } for i in 0 .. lhs . len ( ) { reduced = red ( reduced , lhs [ i ] . map_collapse_reduce_with ( & rhs [ i ] , f , col , red , base . clone ( ) ) , ) ; } } reduced }
The LHS must be the side with the DDD.
The LHS must be the side with the DDD .
lhs
&'a Rc<Vec<EnvMBE<T>>>
lhs_ddd
&'a Option<usize>
rhs
&'a Rc<Vec<EnvMBE<S>>>
rhs_ddd
&'a Option<usize>
f
&dyn Fn(&T, &S) -> NewT
col
&dyn Fn(Vec<NewT>) -> NewT
red
&dyn Fn(NewT, NewT) -> NewT
base
NewT
lhs
&'a Rc<Vec<EnvMBE<T>>>
lhs_ddd
&'a Option<usize>
rhs
&'a Rc<Vec<EnvMBE<S>>>
rhs_ddd
&'a Option<usize>
f
&dyn Fn(&T, &S) -> NewT
col
&dyn Fn(Vec<NewT>) -> NewT
red
&dyn Fn(NewT, NewT) -> NewT
base
NewT