Skip to main content

graphix_package_array/
lib.rs

1#![doc(
2    html_logo_url = "https://graphix-lang.github.io/graphix/graphix-icon.svg",
3    html_favicon_url = "https://graphix-lang.github.io/graphix/graphix-icon.svg"
4)]
5use anyhow::{bail, Result};
6use compact_str::format_compact;
7use graphix_compiler::{
8    expr::ExprId,
9    node::genn,
10    typ::{FnType, Type},
11    Apply, BindId, BuiltIn, Event, ExecCtx, LambdaId, Node, Refs, Rt, UserEvent,
12};
13use graphix_package_core::{
14    deftype, CachedArgs, CachedVals, EvalCached, FoldFn, FoldQ, MapFn, MapQ, Slot,
15};
16use graphix_rt::GXRt;
17use netidx::{publisher::Typ, subscriber::Value, utils::Either};
18use netidx_value::ValArray;
19use smallvec::{smallvec, SmallVec};
20use std::{collections::VecDeque, fmt::Debug, iter};
21
22#[derive(Debug, Default)]
23struct MapImpl;
24
25impl<R: Rt, E: UserEvent> MapFn<R, E> for MapImpl {
26    type Collection = ValArray;
27
28    const NAME: &str = "array_map";
29    deftype!("fn(Array<'a>, fn('a) -> 'b throws 'e) -> Array<'b> throws 'e");
30
31    fn finish(&mut self, slots: &[Slot<R, E>], _: &ValArray) -> Option<Value> {
32        Some(Value::Array(ValArray::from_iter_exact(
33            slots.iter().map(|s| s.cur.clone().unwrap()),
34        )))
35    }
36}
37
38type Map<R, E> = MapQ<R, E, MapImpl>;
39
40#[derive(Debug, Default)]
41struct FilterImpl;
42
43impl<R: Rt, E: UserEvent> MapFn<R, E> for FilterImpl {
44    type Collection = ValArray;
45
46    const NAME: &str = "array_filter";
47    deftype!("fn(Array<'a>, fn('a) -> bool throws 'e) -> Array<'a> throws 'e");
48
49    fn finish(&mut self, slots: &[Slot<R, E>], a: &ValArray) -> Option<Value> {
50        Some(Value::Array(ValArray::from_iter(slots.iter().zip(a.iter()).filter_map(
51            |(p, v)| match p.cur {
52                Some(Value::Bool(true)) => Some(v.clone()),
53                _ => None,
54            },
55        ))))
56    }
57}
58
59type Filter<R, E> = MapQ<R, E, FilterImpl>;
60
61#[derive(Debug, Default)]
62struct FlatMapImpl;
63
64impl<R: Rt, E: UserEvent> MapFn<R, E> for FlatMapImpl {
65    type Collection = ValArray;
66
67    const NAME: &str = "array_flat_map";
68    deftype!("fn(Array<'a>, fn('a) -> ['b, Array<'b>] throws 'e) -> Array<'b> throws 'e");
69
70    fn finish(&mut self, slots: &[Slot<R, E>], _: &ValArray) -> Option<Value> {
71        Some(Value::Array(ValArray::from_iter(slots.iter().flat_map(|s| {
72            match s.cur.as_ref().unwrap() {
73                Value::Array(a) => Either::Left(a.clone().into_iter()),
74                v => Either::Right(iter::once(v.clone())),
75            }
76        }))))
77    }
78}
79
80type FlatMap<R, E> = MapQ<R, E, FlatMapImpl>;
81
82#[derive(Debug, Default)]
83struct FilterMapImpl;
84
85impl<R: Rt, E: UserEvent> MapFn<R, E> for FilterMapImpl {
86    type Collection = ValArray;
87
88    const NAME: &str = "array_filter_map";
89    deftype!("fn(Array<'a>, fn('a) -> Option<'b> throws 'e) -> Array<'b> throws 'e");
90
91    fn finish(&mut self, slots: &[Slot<R, E>], _: &ValArray) -> Option<Value> {
92        Some(Value::Array(ValArray::from_iter(slots.iter().filter_map(|s| {
93            match s.cur.as_ref().unwrap() {
94                Value::Null => None,
95                v => Some(v.clone()),
96            }
97        }))))
98    }
99}
100
101type FilterMap<R, E> = MapQ<R, E, FilterMapImpl>;
102
103#[derive(Debug, Default)]
104struct FindImpl;
105
106impl<R: Rt, E: UserEvent> MapFn<R, E> for FindImpl {
107    type Collection = ValArray;
108
109    const NAME: &str = "array_find";
110    deftype!("fn(Array<'a>, fn('a) -> bool throws 'e) -> Option<'a> throws 'e");
111
112    fn finish(&mut self, slots: &[Slot<R, E>], a: &ValArray) -> Option<Value> {
113        let r = slots
114            .iter()
115            .enumerate()
116            .find(|(_, s)| match s.cur.as_ref() {
117                Some(Value::Bool(true)) => true,
118                _ => false,
119            })
120            .map(|(i, _)| a[i].clone())
121            .unwrap_or(Value::Null);
122        Some(r)
123    }
124}
125
126type Find<R, E> = MapQ<R, E, FindImpl>;
127
128#[derive(Debug, Default)]
129struct FindMapImpl;
130
131impl<R: Rt, E: UserEvent> MapFn<R, E> for FindMapImpl {
132    type Collection = ValArray;
133
134    const NAME: &str = "array_find_map";
135    deftype!("fn(Array<'a>, fn('a) -> Option<'b> throws 'e) -> Option<'b> throws 'e");
136
137    fn finish(&mut self, slots: &[Slot<R, E>], _: &ValArray) -> Option<Value> {
138        let r = slots
139            .iter()
140            .find_map(|s| match s.cur.as_ref().unwrap() {
141                Value::Null => None,
142                v => Some(v.clone()),
143            })
144            .unwrap_or(Value::Null);
145        Some(r)
146    }
147}
148
149type FindMap<R, E> = MapQ<R, E, FindMapImpl>;
150
151#[derive(Debug)]
152struct FoldImpl;
153
154impl<R: Rt, E: UserEvent> FoldFn<R, E> for FoldImpl {
155    type Collection = ValArray;
156
157    const NAME: &str = "array_fold";
158    deftype!("fn(Array<'a>, 'b, fn('b, 'a) -> 'b throws 'e) -> 'b throws 'e");
159}
160
161type Fold<R, E> = FoldQ<R, E, FoldImpl>;
162
163#[derive(Debug, Default)]
164struct ConcatEv(SmallVec<[Value; 32]>);
165
166impl EvalCached for ConcatEv {
167    const NAME: &str = "array_concat";
168    deftype!("fn(Array<'a>, @args: Array<'a>) -> Array<'a>");
169
170    fn eval(&mut self, from: &CachedVals) -> Option<Value> {
171        let mut present = true;
172        for v in from.0.iter() {
173            match v {
174                Some(Value::Array(a)) => {
175                    for v in a.iter() {
176                        self.0.push(v.clone())
177                    }
178                }
179                Some(v) => self.0.push(v.clone()),
180                None => present = false,
181            }
182        }
183        if present {
184            let a = ValArray::from_iter_exact(self.0.drain(..));
185            Some(Value::Array(a))
186        } else {
187            self.0.clear();
188            None
189        }
190    }
191}
192
193type Concat = CachedArgs<ConcatEv>;
194
195#[derive(Debug, Default)]
196struct PushBackEv(SmallVec<[Value; 32]>);
197
198impl EvalCached for PushBackEv {
199    const NAME: &str = "array_push_back";
200    deftype!("fn(Array<'a>, @args: 'a) -> Array<'a>");
201
202    fn eval(&mut self, from: &CachedVals) -> Option<Value> {
203        let mut present = true;
204        match &from.0[..] {
205            [Some(Value::Array(a)), tl @ ..] => {
206                self.0.extend(a.iter().map(|v| v.clone()));
207                for v in tl {
208                    match v {
209                        Some(v) => self.0.push(v.clone()),
210                        None => present = false,
211                    }
212                }
213            }
214            [] | [None, ..] | [Some(_), ..] => present = false,
215        }
216        if present {
217            let a = ValArray::from_iter_exact(self.0.drain(..));
218            Some(Value::Array(a))
219        } else {
220            self.0.clear();
221            None
222        }
223    }
224}
225
226type PushBack = CachedArgs<PushBackEv>;
227
228#[derive(Debug, Default)]
229struct PushFrontEv(SmallVec<[Value; 32]>);
230
231impl EvalCached for PushFrontEv {
232    const NAME: &str = "array_push_front";
233    deftype!("fn(Array<'a>, @args: 'a) -> Array<'a>");
234
235    fn eval(&mut self, from: &CachedVals) -> Option<Value> {
236        let mut present = true;
237        match &from.0[..] {
238            [Some(Value::Array(a)), tl @ ..] => {
239                for v in tl {
240                    match v {
241                        Some(v) => self.0.push(v.clone()),
242                        None => present = false,
243                    }
244                }
245                self.0.extend(a.iter().map(|v| v.clone()));
246            }
247            [] | [None, ..] | [Some(_), ..] => present = false,
248        }
249        if present {
250            let a = ValArray::from_iter_exact(self.0.drain(..));
251            Some(Value::Array(a))
252        } else {
253            self.0.clear();
254            None
255        }
256    }
257}
258
259type PushFront = CachedArgs<PushFrontEv>;
260
261#[derive(Debug, Default)]
262struct WindowEv(SmallVec<[Value; 32]>);
263
264impl EvalCached for WindowEv {
265    const NAME: &str = "array_window";
266    deftype!("fn(#n:i64, Array<'a>, @args: 'a) -> Array<'a>");
267
268    fn eval(&mut self, from: &CachedVals) -> Option<Value> {
269        let mut present = true;
270        match &from.0[..] {
271            [Some(Value::I64(window)), Some(Value::Array(a)), tl @ ..] => {
272                let window = *window as usize;
273                let total = a.len() + tl.len();
274                if total <= window {
275                    self.0.extend(a.iter().cloned());
276                    for v in tl {
277                        match v {
278                            Some(v) => self.0.push(v.clone()),
279                            None => present = false,
280                        }
281                    }
282                } else if a.len() >= (total - window) {
283                    self.0.extend(a[(total - window)..].iter().cloned());
284                    for v in tl {
285                        match v {
286                            Some(v) => self.0.push(v.clone()),
287                            None => present = false,
288                        }
289                    }
290                } else {
291                    for v in &tl[tl.len() - window..] {
292                        match v {
293                            Some(v) => self.0.push(v.clone()),
294                            None => present = false,
295                        }
296                    }
297                }
298            }
299            [] | [_] | [_, None, ..] | [None, _, ..] | [Some(_), Some(_), ..] => {
300                present = false
301            }
302        }
303        if present {
304            let a = ValArray::from_iter_exact(self.0.drain(..));
305            Some(Value::Array(a))
306        } else {
307            self.0.clear();
308            None
309        }
310    }
311}
312
313type Window = CachedArgs<WindowEv>;
314
315#[derive(Debug, Default)]
316struct LenEv;
317
318impl EvalCached for LenEv {
319    const NAME: &str = "array_len";
320    deftype!("fn(Array<'a>) -> i64");
321
322    fn eval(&mut self, from: &CachedVals) -> Option<Value> {
323        match &from.0[0] {
324            Some(Value::Array(a)) => Some(Value::I64(a.len() as i64)),
325            Some(_) | None => None,
326        }
327    }
328}
329
330type Len = CachedArgs<LenEv>;
331
332#[derive(Debug, Default)]
333struct FlattenEv(SmallVec<[Value; 32]>);
334
335impl EvalCached for FlattenEv {
336    const NAME: &str = "array_flatten";
337    deftype!("fn(Array<Array<'a>>) -> Array<'a>");
338
339    fn eval(&mut self, from: &CachedVals) -> Option<Value> {
340        match &from.0[0] {
341            Some(Value::Array(a)) => {
342                for v in a.iter() {
343                    match v {
344                        Value::Array(a) => self.0.extend(a.iter().map(|v| v.clone())),
345                        v => self.0.push(v.clone()),
346                    }
347                }
348                let a = ValArray::from_iter_exact(self.0.drain(..));
349                Some(Value::Array(a))
350            }
351            Some(_) | None => None,
352        }
353    }
354}
355
356type Flatten = CachedArgs<FlattenEv>;
357
358#[derive(Debug, Default)]
359struct SortEv(SmallVec<[Value; 32]>);
360
361impl EvalCached for SortEv {
362    const NAME: &str = "array_sort";
363    deftype!("fn(?#dir:Direction, ?#numeric:bool, Array<'a>) -> Array<'a>");
364
365    fn eval(&mut self, from: &CachedVals) -> Option<Value> {
366        fn cn(v: &Value) -> Value {
367            v.clone().cast(Typ::F64).unwrap_or_else(|| v.clone())
368        }
369        match &from.0[..] {
370            [Some(Value::String(dir)), Some(Value::Bool(numeric)), Some(Value::Array(a))] => {
371                match &**dir {
372                    "Ascending" => {
373                        self.0.extend(a.iter().cloned());
374                        if *numeric {
375                            self.0.sort_by(|v0, v1| cn(v0).cmp(&cn(v1)))
376                        } else {
377                            self.0.sort();
378                        }
379                        Some(Value::Array(ValArray::from_iter_exact(self.0.drain(..))))
380                    }
381                    "Descending" => {
382                        self.0.extend(a.iter().cloned());
383                        if *numeric {
384                            self.0.sort_by(|a0, a1| cn(a1).cmp(&cn(a0)))
385                        } else {
386                            self.0.sort_by(|a0, a1| a1.cmp(a0));
387                        }
388                        Some(Value::Array(ValArray::from_iter_exact(self.0.drain(..))))
389                    }
390                    _ => None,
391                }
392            }
393            _ => None,
394        }
395    }
396}
397
398type Sort = CachedArgs<SortEv>;
399
400#[derive(Debug, Default)]
401struct EnumerateEv;
402
403impl EvalCached for EnumerateEv {
404    const NAME: &str = "array_enumerate";
405    deftype!("fn(Array<'a>) -> Array<(i64, 'a)>");
406
407    fn eval(&mut self, from: &CachedVals) -> Option<Value> {
408        if let Some(Value::Array(a)) = &from.0[0] {
409            let a = ValArray::from_iter_exact(
410                a.iter().enumerate().map(|(i, v)| (i, v.clone()).into()),
411            );
412            return Some(Value::Array(a));
413        }
414        None
415    }
416}
417
418type Enumerate = CachedArgs<EnumerateEv>;
419
420#[derive(Debug, Default)]
421struct ZipEv;
422
423impl EvalCached for ZipEv {
424    const NAME: &str = "array_zip";
425    deftype!("fn(Array<'a>, Array<'b>) -> Array<('a, 'b)>");
426
427    fn eval(&mut self, from: &CachedVals) -> Option<Value> {
428        match &from.0[..] {
429            [Some(Value::Array(a0)), Some(Value::Array(a1))] => {
430                Some(Value::Array(ValArray::from_iter_exact(
431                    a0.iter().cloned().zip(a1.iter().cloned()).map(|p| p.into()),
432                )))
433            }
434            _ => None,
435        }
436    }
437}
438
439type Zip = CachedArgs<ZipEv>;
440
441#[derive(Debug, Default)]
442struct UnzipEv {
443    t0: Vec<Value>,
444    t1: Vec<Value>,
445}
446
447impl EvalCached for UnzipEv {
448    const NAME: &str = "array_unzip";
449    deftype!("fn(Array<('a, 'b)>) -> (Array<'a>, Array<'b>)");
450
451    fn eval(&mut self, from: &CachedVals) -> Option<Value> {
452        match &from.0[..] {
453            [Some(Value::Array(a))] => {
454                for v in a {
455                    if let Value::Array(a) = v {
456                        match &a[..] {
457                            [v0, v1] => {
458                                self.t0.push(v0.clone());
459                                self.t1.push(v1.clone());
460                            }
461                            _ => (),
462                        }
463                    }
464                }
465                let v0 = Value::Array(ValArray::from_iter_exact(self.t0.drain(..)));
466                let v1 = Value::Array(ValArray::from_iter_exact(self.t1.drain(..)));
467                Some(Value::Array(ValArray::from_iter_exact([v0, v1].into_iter())))
468            }
469            _ => None,
470        }
471    }
472}
473
474type Unzip = CachedArgs<UnzipEv>;
475
476#[derive(Debug)]
477struct Group<R: Rt, E: UserEvent> {
478    queue: VecDeque<Value>,
479    buf: SmallVec<[Value; 16]>,
480    pred: Node<R, E>,
481    ready: bool,
482    pid: BindId,
483    nid: BindId,
484    xid: BindId,
485}
486
487impl<R: Rt, E: UserEvent> BuiltIn<R, E> for Group<R, E> {
488    const NAME: &str = "array_group";
489    deftype!("fn('a, fn(i64, 'a) -> bool throws 'e) -> Array<'a> throws 'e");
490
491    fn init<'a, 'b, 'c>(
492        ctx: &'a mut ExecCtx<R, E>,
493        typ: &'a FnType,
494        scope: &'b graphix_compiler::Scope,
495        from: &'c [Node<R, E>],
496        top_id: ExprId,
497    ) -> Result<Box<dyn Apply<R, E>>> {
498        match from {
499            [_, _] => {
500                let scope =
501                    scope.append(&format_compact!("fn{}", LambdaId::new().inner()));
502                let n_typ = Type::Primitive(Typ::I64.into());
503                let etyp = typ.args[0].typ.clone();
504                let mftyp = match &typ.args[1].typ {
505                    Type::Fn(ft) => ft.clone(),
506                    t => bail!("expected function not {t}"),
507                };
508                let (nid, n) =
509                    genn::bind(ctx, &scope.lexical, "n", n_typ.clone(), top_id);
510                let (xid, x) = genn::bind(ctx, &scope.lexical, "x", etyp.clone(), top_id);
511                let pid = BindId::new();
512                let fnode = genn::reference(ctx, pid, Type::Fn(mftyp.clone()), top_id);
513                let pred = genn::apply(fnode, scope, vec![n, x], &mftyp, top_id);
514                Ok(Box::new(Self {
515                    queue: VecDeque::new(),
516                    buf: smallvec![],
517                    pred,
518                    ready: true,
519                    pid,
520                    nid,
521                    xid,
522                }))
523            }
524            _ => bail!("expected two arguments"),
525        }
526    }
527}
528
529impl<R: Rt, E: UserEvent> Apply<R, E> for Group<R, E> {
530    fn update(
531        &mut self,
532        ctx: &mut ExecCtx<R, E>,
533        from: &mut [Node<R, E>],
534        event: &mut Event<E>,
535    ) -> Option<Value> {
536        macro_rules! set {
537            ($v:expr) => {{
538                self.ready = false;
539                self.buf.push($v.clone());
540                let len = Value::I64(self.buf.len() as i64);
541                ctx.cached.insert(self.nid, len.clone());
542                event.variables.insert(self.nid, len);
543                ctx.cached.insert(self.xid, $v.clone());
544                event.variables.insert(self.xid, $v);
545            }};
546        }
547        if let Some(v) = from[0].update(ctx, event) {
548            self.queue.push_back(v);
549        }
550        if let Some(v) = from[1].update(ctx, event) {
551            ctx.cached.insert(self.pid, v.clone());
552            event.variables.insert(self.pid, v);
553        }
554        if self.ready && self.queue.len() > 0 {
555            let v = self.queue.pop_front().unwrap();
556            set!(v);
557        }
558        loop {
559            match self.pred.update(ctx, event) {
560                None => break None,
561                Some(v) => {
562                    self.ready = true;
563                    match v {
564                        Value::Bool(true) => {
565                            break Some(Value::Array(ValArray::from_iter_exact(
566                                self.buf.drain(..),
567                            )))
568                        }
569                        _ => match self.queue.pop_front() {
570                            None => break None,
571                            Some(v) => set!(v),
572                        },
573                    }
574                }
575            }
576        }
577    }
578
579    fn typecheck(
580        &mut self,
581        ctx: &mut ExecCtx<R, E>,
582        _from: &mut [Node<R, E>],
583    ) -> anyhow::Result<()> {
584        self.pred.typecheck(ctx)
585    }
586
587    fn refs(&self, refs: &mut Refs) {
588        self.pred.refs(refs)
589    }
590
591    fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
592        ctx.cached.remove(&self.nid);
593        ctx.cached.remove(&self.pid);
594        ctx.cached.remove(&self.xid);
595        self.pred.delete(ctx);
596    }
597
598    fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
599        self.pred.sleep(ctx);
600    }
601}
602
603#[derive(Debug)]
604struct Iter(BindId, ExprId);
605
606impl<R: Rt, E: UserEvent> BuiltIn<R, E> for Iter {
607    const NAME: &str = "array_iter";
608    deftype!("fn(Array<'a>) -> 'a");
609
610    fn init<'a, 'b, 'c>(
611        ctx: &'a mut ExecCtx<R, E>,
612        _typ: &'a FnType,
613        _scope: &'b graphix_compiler::Scope,
614        _from: &'c [Node<R, E>],
615        top_id: ExprId,
616    ) -> Result<Box<dyn Apply<R, E>>> {
617        let id = BindId::new();
618        ctx.rt.ref_var(id, top_id);
619        Ok(Box::new(Iter(id, top_id)))
620    }
621}
622
623impl<R: Rt, E: UserEvent> Apply<R, E> for Iter {
624    fn update(
625        &mut self,
626        ctx: &mut ExecCtx<R, E>,
627        from: &mut [Node<R, E>],
628        event: &mut Event<E>,
629    ) -> Option<Value> {
630        if let Some(Value::Array(a)) = from[0].update(ctx, event) {
631            for v in a.iter() {
632                ctx.rt.set_var(self.0, v.clone());
633            }
634        }
635        event.variables.get(&self.0).map(|v| v.clone())
636    }
637
638    fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
639        ctx.rt.unref_var(self.0, self.1)
640    }
641
642    fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
643        ctx.rt.unref_var(self.0, self.1);
644        self.0 = BindId::new();
645        ctx.rt.ref_var(self.0, self.1);
646    }
647}
648
649#[derive(Debug)]
650struct IterQ {
651    triggered: usize,
652    queue: VecDeque<(usize, ValArray)>,
653    id: BindId,
654    top_id: ExprId,
655}
656
657impl<R: Rt, E: UserEvent> BuiltIn<R, E> for IterQ {
658    const NAME: &str = "array_iterq";
659    deftype!("fn(#clock:Any, Array<'a>) -> 'a");
660
661    fn init<'a, 'b, 'c>(
662        ctx: &'a mut ExecCtx<R, E>,
663        _typ: &'a FnType,
664        _scope: &'b graphix_compiler::Scope,
665        _from: &'c [Node<R, E>],
666        top_id: ExprId,
667    ) -> Result<Box<dyn Apply<R, E>>> {
668        let id = BindId::new();
669        ctx.rt.ref_var(id, top_id);
670        Ok(Box::new(IterQ { triggered: 0, queue: VecDeque::new(), id, top_id }))
671    }
672}
673
674impl<R: Rt, E: UserEvent> Apply<R, E> for IterQ {
675    fn update(
676        &mut self,
677        ctx: &mut ExecCtx<R, E>,
678        from: &mut [Node<R, E>],
679        event: &mut Event<E>,
680    ) -> Option<Value> {
681        if from[0].update(ctx, event).is_some() {
682            self.triggered += 1;
683        }
684        if let Some(Value::Array(a)) = from[1].update(ctx, event) {
685            if a.len() > 0 {
686                self.queue.push_back((0, a));
687            }
688        }
689        while self.triggered > 0 && self.queue.len() > 0 {
690            let (i, a) = self.queue.front_mut().unwrap();
691            while self.triggered > 0 && *i < a.len() {
692                ctx.rt.set_var(self.id, a[*i].clone());
693                *i += 1;
694                self.triggered -= 1;
695            }
696            if *i == a.len() {
697                self.queue.pop_front();
698            }
699        }
700        event.variables.get(&self.id).cloned()
701    }
702
703    fn delete(&mut self, ctx: &mut ExecCtx<R, E>) {
704        ctx.rt.unref_var(self.id, self.top_id)
705    }
706
707    fn sleep(&mut self, ctx: &mut ExecCtx<R, E>) {
708        ctx.rt.unref_var(self.id, self.top_id);
709        self.id = BindId::new();
710        self.queue.clear();
711        self.triggered = 0;
712    }
713}
714
715graphix_derive::defpackage! {
716    builtins => [
717        Concat,
718        Filter as Filter<GXRt<X>, X::UserEvent>,
719        FilterMap as FilterMap<GXRt<X>, X::UserEvent>,
720        Find as Find<GXRt<X>, X::UserEvent>,
721        FindMap as FindMap<GXRt<X>, X::UserEvent>,
722        FlatMap as FlatMap<GXRt<X>, X::UserEvent>,
723        Enumerate,
724        Zip,
725        Unzip,
726        Flatten,
727        Fold as Fold<GXRt<X>, X::UserEvent>,
728        Group as Group<GXRt<X>, X::UserEvent>,
729        Iter,
730        IterQ,
731        Len,
732        Map as Map<GXRt<X>, X::UserEvent>,
733        PushBack,
734        PushFront,
735        Sort,
736        Window,
737    ],
738}