package main import ( "math/rand" "strings" ) func first(s, arg string) agg { return &sbinop{s, opfirst} } func last(s, arg string) agg { return &sbinop{s, oplast} } func prefix(s, arg string) agg { return &sbinop{s, opprefix} } func join(s, arg string) agg { return &sbinop{s, opjoin(arg)} } func smin(s, arg string) agg { return &sbinop{s, opsmin} } func smax(s, arg string) agg { return &sbinop{s, opsmax} } type sbinop struct { s string f func(a, b string) string } func (o *sbinop) String() string { return o.s } func (o *sbinop) merge(s string) { o.s = o.f(o.s, s) } func opfirst(a, b string) string { return a } func oplast(a, b string) string { return b } func opprefix(a, b string) string { for i := range a { if i >= len(b) || a[i] != b[i] { return a[:i] } } return a } func opjoin(sep string) func(a, b string) string { return func(a, b string) string { return a + sep + b // TODO(kr): too slow? maybe strings.Join? } } func opsmin(a, b string) string { if strings.Compare(a, b) <= 0 { return a } return b } func opsmax(a, b string) string { if strings.Compare(a, b) >= 0 { return a } return b } type sampler struct { n int s string } func sample(s, arg string) agg { return &sampler{1, s} } func (p *sampler) String() string { return p.s } func (p *sampler) merge(s string) { p.n++ if rand.Intn(p.n) == 0 { p.s = s } } type constant string func constf(init, arg string) agg { return constant(arg) } func (c constant) String() string { return string(c) } func (c constant) merge(string) {}