1package main 2 3import ( 4 "math/rand" 5 "strings" 6) 7 8func first(s, arg string) agg { return &sbinop{s, opfirst} } 9func last(s, arg string) agg { return &sbinop{s, oplast} } 10func prefix(s, arg string) agg { return &sbinop{s, opprefix} } 11func join(s, arg string) agg { return &sbinop{s, opjoin(arg)} } 12func smin(s, arg string) agg { return &sbinop{s, opsmin} } 13func smax(s, arg string) agg { return &sbinop{s, opsmax} } 14 15type sbinop struct { 16 s string 17 f func(a, b string) string 18} 19 20func (o *sbinop) String() string { return o.s } 21 22func (o *sbinop) merge(s string) { o.s = o.f(o.s, s) } 23 24func opfirst(a, b string) string { return a } 25func oplast(a, b string) string { return b } 26 27func opprefix(a, b string) string { 28 for i := range a { 29 if i >= len(b) || a[i] != b[i] { 30 return a[:i] 31 } 32 } 33 return a 34} 35 36func opjoin(sep string) func(a, b string) string { 37 return func(a, b string) string { 38 return a + sep + b // TODO(kr): too slow? maybe strings.Join? 39 } 40} 41 42func opsmin(a, b string) string { 43 if strings.Compare(a, b) <= 0 { 44 return a 45 } 46 return b 47} 48 49func opsmax(a, b string) string { 50 if strings.Compare(a, b) >= 0 { 51 return a 52 } 53 return b 54} 55 56type sampler struct { 57 n int 58 s string 59} 60 61func sample(s, arg string) agg { return &sampler{1, s} } 62func (p *sampler) String() string { return p.s } 63func (p *sampler) merge(s string) { 64 p.n++ 65 if rand.Intn(p.n) == 0 { 66 p.s = s 67 } 68} 69 70type constant string 71 72func constf(init, arg string) agg { return constant(arg) } 73func (c constant) String() string { return string(c) } 74func (c constant) merge(string) {} 75