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