100 lines
2.4 KiB
Go
100 lines
2.4 KiB
Go
|
package fun
|
||
|
|
||
|
import (
|
||
|
"reflect"
|
||
|
|
||
|
"github.com/BurntSushi/ty"
|
||
|
)
|
||
|
|
||
|
// Set has a parametric type:
|
||
|
//
|
||
|
// func Set(xs []A) map[A]bool
|
||
|
//
|
||
|
// Set creates a set from a list.
|
||
|
func Set(xs interface{}) interface{} {
|
||
|
chk := ty.Check(
|
||
|
new(func([]ty.A) map[ty.A]bool),
|
||
|
xs)
|
||
|
vxs, tset := chk.Args[0], chk.Returns[0]
|
||
|
|
||
|
vtrue := reflect.ValueOf(true)
|
||
|
vset := reflect.MakeMap(tset)
|
||
|
xsLen := vxs.Len()
|
||
|
for i := 0; i < xsLen; i++ {
|
||
|
vset.SetMapIndex(vxs.Index(i), vtrue)
|
||
|
}
|
||
|
return vset.Interface()
|
||
|
}
|
||
|
|
||
|
// Union has a parametric type:
|
||
|
//
|
||
|
// func Union(a map[A]bool, b map[A]bool) map[A]bool
|
||
|
//
|
||
|
// Union returns the union of two sets, where a set is represented as a
|
||
|
// `map[A]bool`. The sets `a` and `b` are not modified.
|
||
|
func Union(a, b interface{}) interface{} {
|
||
|
chk := ty.Check(
|
||
|
new(func(map[ty.A]bool, map[ty.A]bool) map[ty.A]bool),
|
||
|
a, b)
|
||
|
va, vb, tc := chk.Args[0], chk.Args[1], chk.Returns[0]
|
||
|
|
||
|
vtrue := reflect.ValueOf(true)
|
||
|
vc := reflect.MakeMap(tc)
|
||
|
for _, vkey := range va.MapKeys() {
|
||
|
vc.SetMapIndex(vkey, vtrue)
|
||
|
}
|
||
|
for _, vkey := range vb.MapKeys() {
|
||
|
vc.SetMapIndex(vkey, vtrue)
|
||
|
}
|
||
|
return vc.Interface()
|
||
|
}
|
||
|
|
||
|
// Intersection has a parametric type:
|
||
|
//
|
||
|
// func Intersection(a map[A]bool, b map[A]bool) map[A]bool
|
||
|
//
|
||
|
// Intersection returns the intersection of two sets, where a set is
|
||
|
// represented as a `map[A]bool`. The sets `a` and `b` are not modified.
|
||
|
func Intersection(a, b interface{}) interface{} {
|
||
|
chk := ty.Check(
|
||
|
new(func(map[ty.A]bool, map[ty.A]bool) map[ty.A]bool),
|
||
|
a, b)
|
||
|
va, vb, tc := chk.Args[0], chk.Args[1], chk.Returns[0]
|
||
|
|
||
|
vtrue := reflect.ValueOf(true)
|
||
|
vc := reflect.MakeMap(tc)
|
||
|
for _, vkey := range va.MapKeys() {
|
||
|
if vb.MapIndex(vkey).IsValid() {
|
||
|
vc.SetMapIndex(vkey, vtrue)
|
||
|
}
|
||
|
}
|
||
|
for _, vkey := range vb.MapKeys() {
|
||
|
if va.MapIndex(vkey).IsValid() {
|
||
|
vc.SetMapIndex(vkey, vtrue)
|
||
|
}
|
||
|
}
|
||
|
return vc.Interface()
|
||
|
}
|
||
|
|
||
|
// Difference has a parametric type:
|
||
|
//
|
||
|
// func Difference(a map[A]bool, b map[A]bool) map[A]bool
|
||
|
//
|
||
|
// Difference returns a set with all elements in `a` that are not in `b`.
|
||
|
// The sets `a` and `b` are not modified.
|
||
|
func Difference(a, b interface{}) interface{} {
|
||
|
chk := ty.Check(
|
||
|
new(func(map[ty.A]bool, map[ty.A]bool) map[ty.A]bool),
|
||
|
a, b)
|
||
|
va, vb, tc := chk.Args[0], chk.Args[1], chk.Returns[0]
|
||
|
|
||
|
vtrue := reflect.ValueOf(true)
|
||
|
vc := reflect.MakeMap(tc)
|
||
|
for _, vkey := range va.MapKeys() {
|
||
|
if !vb.MapIndex(vkey).IsValid() {
|
||
|
vc.SetMapIndex(vkey, vtrue)
|
||
|
}
|
||
|
}
|
||
|
return vc.Interface()
|
||
|
}
|