func (t *Table) MustColumn(name string) Slice {
	if c := t.Column(name); c != nil {
		return c
	}
	panic(fmt.Sprintf("unknown column %q", name))
}
MustColumn is like Column, but panics if there is no such column.
package table
import (
	"fmt"
	"reflect"
	"github.com/aclements/go-gg/generic"
	"github.com/aclements/go-gg/generic/slice"
)
type Table struct {
	cols     map[string]Slice
	consts   map[string]interface{}
	colNames []string
	len      int
}
type Builder struct {
	t Table
}
type Grouping interface {
	Columns() []string
	Tables() []GroupID
	Table(gid GroupID) *Table
}
type GroupingBuilder struct {
	g        groupedTable
	colTypes []reflect.Type
}
type groupedTable struct {
	tables   map[GroupID]*Table
	groups   []GroupID
	colNames []string
}
type Slice interface{}
func reflectSlice(s Slice) reflect.Value {
	rv := reflect.ValueOf(s)
	if rv.Kind() != reflect.Slice {
		panic(&generic.TypeError{rv.Type(), nil, "is not a slice"})
	}
	return rv
}
func NewBuilder(t *Table) *Builder {
	if t == nil {
		return new(Builder)
	}
	b := Builder{Table{
		cols:     make(map[string]Slice),
		consts:   make(map[string]interface{}),
		colNames: append([]string(nil), t.Columns()...),
		len:      t.len,
	}}
	for k, v := range t.cols {
		b.t.cols[k] = v
	}
	for k, v := range t.consts {
		b.t.consts[k] = v
	}
	return &b
}
func (b *Builder) Add(name string, data Slice) *Builder {
	if data == nil {
		if _, ok := b.t.cols[name]; !ok {
			if _, ok := b.t.consts[name]; !ok {
				return b
			}
		}
		delete(b.t.cols, name)
		delete(b.t.consts, name)
		for i, n := range b.t.colNames {
			if n == name {
				copy(b.t.colNames[i:], b.t.colNames[i+1:])
				b.t.colNames = b.t.colNames[:len(b.t.colNames)-1]
				break
			}
		}
		return b
	}
	_, replace := b.t.cols[name]
	if !replace {
		_, replace = b.t.consts[name]
	}
	rv := reflectSlice(data)
	dataLen := rv.Len()
	if len(b.t.cols) == 0 || (replace && len(b.t.cols) == 1) {
		if b.t.cols == nil {
			b.t.cols = make(map[string]Slice)
		}
		b.t.cols[name] = data
		b.t.len = dataLen
	} else if b.t.len != dataLen {
		panic(fmt.Sprintf("cannot add column %q with %d elements to table with %d rows", name, dataLen, b.t.len))
	} else {
		b.t.cols[name] = data
	}
	if replace {
		delete(b.t.consts, name)
	} else {
		b.t.colNames = append(b.t.colNames, name)
	}
	return b
}
func (b *Builder) AddConst(name string, val interface{}) *Builder {
	_, replace := b.t.cols[name]
	if !replace {
		_, replace = b.t.consts[name]
	}
	if b.t.consts == nil {
		b.t.consts = make(map[string]interface{})
	}
	b.t.consts[name] = val
	if replace {
		delete(b.t.cols, name)
	} else {
		b.t.colNames = append(b.t.colNames, name)
	}
	return b
}
func (b *Builder) Has(name string) bool {
	if _, ok := b.t.cols[name]; ok {
		return true
	}
	if _, ok := b.t.consts[name]; ok {
		return true
	}
	return false
}
func (b *Builder) Done() *Table {
	if len(b.t.colNames) == 0 {
		return new(Table)
	}
	t := b.t
	b.t = Table{}
	return &t
}
func (t *Table) Len() int {
	return t.len
}
func (t *Table) Columns() []string {
	return t.colNames
}
func (t *Table) Column(name string) Slice {
	if c, ok := t.cols[name]; ok {
		return c
	}
	if cv, ok := t.consts[name]; ok {
		expanded := slice.Repeat(cv, t.len)
		t.cols[name] = expanded
		return expanded
	}
	return nil
}