package core import ( "fmt" "github.com/mediocregopher/ginger/seq" "github.com/mediocregopher/ginger/types" ) type mathReduceFn func(types.Elem, types.Elem) types.Elem func mathReduce(fn mathReduceFn, zero types.Elem, s seq.Seq) types.Elem { reduceFn := func(acc, el types.Elem) (types.Elem, bool) { return fn(acc, el), false } return seq.Reduce(reduceFn, zero, s) } {{range .}}{{$mathOp := .}}{{range .OpTypes}} func {{$mathOp.Private}}{{.CastFn}}(a, b types.Elem) types.Elem { return types.GoType{{`{`}}{{.CastFn}}(a) {{$mathOp.Op}} {{.CastFn}}(b)} } {{end}}{{if $mathOp.IncludeString}} func {{$mathOp.Private}}String(a, b types.Elem) types.Elem { return types.GoType{String(a) {{$mathOp.Op}} String(b)} } {{end}} func {{$mathOp.Public}}(s seq.Seq) types.Elem { var first, zero types.Elem {{if (eq $mathOp.Unit "")}} if seq.Empty(s) { panic("{{$mathOp.Public}} cannot be called with no arguments") } zero, s, _ = s.FirstRest() first = zero {{else}} if seq.Empty(s) { return types.GoType{{`{`}}{{$mathOp.Unit}}} } first, _, _ = s.FirstRest() {{end}} var fn mathReduceFn switch first.(types.GoType).V.(type) { {{range .OpTypes}} case {{.Type}}: fn = {{$mathOp.Private}}{{.CastFn}}{{if (ne $mathOp.Unit "")}} zero = types.GoType{{`{`}}{{.Type}}({{$mathOp.Unit}})}{{end}} {{end}}{{if $mathOp.IncludeString}} case string: fn = {{$mathOp.Private}}String zero = types.GoType{string("")} {{end}} default: panic(fmt.Sprintf("$#v cannot have {{$mathOp.Public}} called on it", first)) } return mathReduce(fn, zero, s) }{{end}}