func Len(key string, length int) Exp {
	return expLen{key, length}
}
Len evalates to true if the length of the string pointed to by key is equal
to length.
package exp
import "strings"
type expMatch struct {
	key, str string
}
func (e expMatch) Eval(p Params) bool {
	return p.Get(e.key) == e.str
}
func (e expMatch) String() string {
	return sprintf("[%s==%s]", e.key, e.str)
}
func Match(key, str string) Exp {
	return expMatch{key, str}
}
func MatchAny(key string, strs ...string) Exp {
	exp := make([]Exp, len(strs))
	for i, str := range strs {
		exp[i] = Match(key, str)
	}
	return Or(exp...)
}
type expContains struct {
	key, substr string
}
func (e expContains) Eval(p Params) bool {
	return strings.Contains(p.Get(e.key), e.substr)
}
func (e expContains) String() string {
	return sprintf("[%s∋%s]", e.key, e.substr)
}
func Contains(key, substr string) Exp {
	return expContains{key, substr}
}
type expContainsAny struct {
	key, chars string
}
func (e expContainsAny) Eval(p Params) bool {
	return strings.ContainsAny(p.Get(e.key), e.chars)
}
func (e expContainsAny) String() string {
	return sprintf("[%s∋%s]", e.key, e.chars)
}
func ContainsAny(key, chars string) Exp {
	return expContainsAny{key, chars}
}
type expContainsRune struct {
	key string
	r   rune
}
func (e expContainsRune) Eval(p Params) bool {
	return strings.ContainsRune(p.Get(e.key), e.r)
}
func (e expContainsRune) String() string {
	return sprintf("[%s∋%c]", e.key, e.r)
}
func ContainsRune(key string, r rune) Exp {
	return expContainsRune{key, r}
}
type expLen struct {
	key    string
	length int
}
func (e expLen) Eval(p Params) bool {
	return len(p.Get(e.key)) == e.length
}
func (e expLen) String() string {
	return sprintf("[len(%s)==%d]", e.key, e.length)
}