func (m *Matcher) matchWithBindingss(bss []Bindings, pattern interface{}, fact interface{}) ([]Bindings, error) {
	acc := make([]Bindings, 0, len(bss))
	for _, bs := range bss {
		matches, err := m.Match(pattern, fact, bs)
		if nil != err {
			return nil, err
		}
		if nil != matches {
			acc = append(acc, matches...)
		}
	}
	return acc, nil
}
matchWithBindings attempts to extend the given bindingss 'bss' from
matches of the fact against the pattern.

Ths function mostly just calls 'Match()'.
package match
import (
	"errors"
	"strings"
)
type Matcher struct {
	AllowPropertyVariables bool
	CheckForBadPropertyVariables bool
	Inequalities bool
}
var DefaultMatcher = &Matcher{
	AllowPropertyVariables:       true,
	CheckForBadPropertyVariables: true,
	Inequalities:                 true,
}
func (m *Matcher) checkForBadPropertyVariables(pattern map[string]interface{}) error {
	if !m.CheckForBadPropertyVariables {
		return nil
	}
	if len(pattern) <= 1 {
		return nil
	}
	for k := range pattern {
		if m.IsVariable(k) {
			return errors.New(`can't have a variable as a key ("` + k + `") with other keys`)
		}
	}
	return nil
}
// Bindings is a map from variables (strings starting with a '?') to
// their values.
type Bindings map[string]interface{}
func NewBindings() Bindings {
	return make(Bindings, 8)
}
// Extends adds the property; modifies and returns the Bindings.
//
// The Bindings are modified.
func (bs Bindings) Extend(p string, v interface{}) Bindings {
	bs[p] = v
	return bs
}
// Extends adds the properties; modifies and returns the Bindings.
//
// The Bindings are modified.
func (bs Bindings) Extendm(pairs ...interface{}) (Bindings, error) {
	for i := 0; i < len(pairs); i += 2 {
		x := pairs[i]
		p, is := x.(string)
		if !is {
			return nil, errors.New("Bindings.Entendm given a non-string key")
		}
		if len(pairs) <= i+1 {
			return nil, errors.New("odd args to Bindings.Extendm")
		}
		bs[p] = pairs[i+1]
	}
	return bs, nil
}
// Remove removes the given keys.
//
// The Bindings are modified.
func (bs Bindings) Remove(ps ...string) Bindings {
	for _, p := range ps {
		delete(bs, p)
	}
	return bs
}
// DeleteExcept removes all but the given properties.
//
// Does not copy.
func (bs Bindings) DeleteExcept(keeps ...string) Bindings {
REM:
	for p := range bs {
		for _, keep := range keeps {
			if keep == p {
				continue REM
			}
		}
		delete(bs, p)
	}
	return bs
}
// Copy makes a shallow copy of the Bindings.
func (bs Bindings) Copy() Bindings {
	acc := make(Bindings, len(bs))
	for k, v := range bs {
		acc[k] = v
	}
	return acc
}
// IsVariable reports if the string represents a pattern variable.
//
// All pattern variables start with a '?".
func (m *Matcher) IsVariable(s string) bool {
	return strings.HasPrefix(s, "?")
}
func (m *Matcher) IsOptionalVariable(x interface{}) bool {
	if s, is := x.(string); is {
		return strings.HasPrefix(s, "??")
	}
	return false
}
// IsAnonymousVariable detects a variable of the form '?'.  An binding
// for an anonymous variable shouldn't ever make it into bindins.
func (m *Matcher) IsAnonymousVariable(s string) bool {
	return s == "?"
}
// IsConstant reports if the string represents a constant (and not a
// pattern variable).
func (m *Matcher) IsConstant(s string) bool {
	return !m.IsVariable(s)
}
// mapcatMatch attempts to extend the given bindingss 'bss' based on
// pair-wise matching of the pattern to the fact.
func (m *Matcher) mapcatMatch(bss []Bindings, pattern map[string]interface{}, fact map[string]interface{}) ([]Bindings, error) {
	if err := m.checkForBadPropertyVariables(pattern); err != nil {
		return nil, err
	}
	for k, v := range pattern {
		if m.IsVariable(k) {
			if m.AllowPropertyVariables {
				if len(pattern) == 1 {
					// Iterate over the fact keys and collect match results.
					gather := make([]Bindings, 0, 0)
					for fk, fv := range fact {
						ext := copyBindingss(bss)
						// Try to match keys.
						ext, err := m.matchWithBindingss(ext, k, fk)
						if err != nil {
							return nil, err
						}
						if 0 == len(ext) {
							// Didn't match keys.
							continue
						}
						// Matched keys.  Now check values.
						ext, err = m.matchWithBindingss(ext, v, fv)
						if err != nil {
							return nil, err
						}
						if 0 == len(ext) {
							// Didn't match values.
							continue
						}
						gather = append(gather, ext...)
					}
					bss = gather
					// Since we know we have only one key, the outer loop will terminate.
					// Probably should make that termination explicit.
					return bss, nil
				} else {
					return nil, errors.New(`can't have a variable as a key ("` + k + `") with other keys`)
				}
			} else {
				return nil, errors.New(`can't have a variable as a key ("` + k + `")`)
			}
		} else {
			fv, found := fact[k]
			if !found {
				if m.IsOptionalVariable(v) {
					continue
				}
				return nil, nil
			}
			acc, err := m.matchWithBindingss(bss, v, fv)
			if nil != err {
				return nil, err
			}
			if 0 == len(acc) {
				return nil, nil
			}
			bss = acc
		}
	}
	return bss, nil
}
func (m *Matcher) arraycatMatch(bsss [][]Bindings, pattern interface{}, fxas []map[int]interface{}) ([][]Bindings, []map[int]interface{}, error) {
	var nbsss [][]Bindings
	var nfxas []map[int]interface{}
	for i, bss := range bsss {
		mm := fxas[i]
		for j, fact := range mm {
			acc, err := m.matchWithBindingss(copyBindingss(bss), pattern, fact)
			if nil != err {
				return nil, nil, err
			}
			if 0 != len(acc) {
				nbsss = append(nbsss, acc)
				copy := copyMap(mm)
				delete(copy, j)
				nfxas = append(nfxas, copy)
			}
		}
	}
	return nbsss, nfxas, nil
}
func copyMap(source map[int]interface{}) map[int]interface{} {
	target := make(map[int]interface{})
	for p, v := range source {
		target[p] = v
	}
	return target
}