コード例 #1
0
ファイル: min_max_sum.go プロジェクト: acsellers/ty
// MinMaxInt has a parametric type:
//
//  func MinMaxInt(f func(A) int64, xs []A) (int64, int64)
//
// MinMaxInt returns the minimum and maximum values returned from f, if the list is
// of length 0, it will return 0 and 0
func MinMaxInt(f, xs interface{}) (int64, int64) {
	chk := ty.Check(
		new(func(func(ty.A) int64, []ty.A)),
		f, xs)
	vp, vxs := chk.Args[0], chk.Args[1]

	xsLen := vxs.Len()
	if xsLen > 0 {
		min := call1(vp, vxs.Index(0)).Int()
		max := min
		for i := 1; i < xsLen; i++ {
			vx := vxs.Index(i)
			local := call1(vp, vx).Int()
			if local < min {
				min = local
			}
			if local > max {
				max = local
			}
		}
		return min, max
	}

	return 0, 0
}
コード例 #2
0
ファイル: list.go プロジェクト: johnvilsack/golang-stuff
// ParMapN has a parametric type:
//
//	func ParMapN(f func(A) B, xs []A, n int) []B
//
// ParMapN is just like Map, except it applies `f` to each element in `xs`
// concurrently using `n` worker goroutines.
//
// It is important that `f` not be a trivial operation, otherwise the overhead
// of executing it concurrently will result in worse performance than using
// a `Map`.
func ParMapN(f, xs interface{}, n int) interface{} {
	chk := ty.Check(
		new(func(func(ty.A) ty.B, []ty.A) []ty.B),
		f, xs)
	vf, vxs, tys := chk.Args[0], chk.Args[1], chk.Returns[0]

	xsLen := vxs.Len()
	ys := reflect.MakeSlice(tys, xsLen, xsLen)

	if n < 1 {
		n = 1
	}
	work := make(chan int, n)
	wg := new(sync.WaitGroup)
	for i := 0; i < n; i++ {
		wg.Add(1)
		go func() {
			for j := range work {
				// Good golly miss molly. Is `reflect.Value.Index`
				// safe to access/set from multiple goroutines?
				// XXX: If not, we'll need an extra wave of allocation to
				// use real slices of `reflect.Value`.
				ys.Index(j).Set(call1(vf, vxs.Index(j)))
			}
			wg.Done()
		}()
	}
	for i := 0; i < xsLen; i++ {
		work <- i
	}
	close(work)
	wg.Wait()
	return ys.Interface()
}
コード例 #3
0
ファイル: sort.go プロジェクト: ngaut/ty
// Sort has a parametric type:
//
//	func Sort(less func(x1 A, x2 A) bool, []A)
//
// Sort uses the standard library `sort` package to sort `xs` in place.
//
// `less` should be a function that returns true if and only if `x1` is less
// than `x2`.
func Sort(less, xs interface{}) {
	chk := ty.Check(
		new(func(func(ty.A, ty.A) bool, []ty.A)),
		less, xs)

	vless, vxs := chk.Args[0], chk.Args[1]
	sort.Sort(&sortable{vless, vxs, swapperOf(vxs.Type().Elem())})
}
コード例 #4
0
ファイル: list.go プロジェクト: johnvilsack/golang-stuff
// Copy has a parametric type:
//
//	func Copy(xs []A) []A
//
// Copy returns a copy of `xs` using Go's `copy` operation.
func Copy(xs interface{}) interface{} {
	chk := ty.Check(
		new(func([]ty.A) []ty.A),
		xs)
	vxs, tys := chk.Args[0], chk.Returns[0]

	xsLen := vxs.Len()
	vys := reflect.MakeSlice(tys, xsLen, xsLen)
	reflect.Copy(vys, vxs)
	return vys.Interface()
}
コード例 #5
0
ファイル: list.go プロジェクト: acsellers/ty
// Each has a parametric type:
//
//  func Each(f func(A), xs []A)
//
// Each runs `f` across each element in `xs`.
func Each(f, xs interface{}) {
	chk := ty.Check(
		new(func(func(ty.A), []ty.A)),
		f, xs)
	vf, vxs := chk.Args[0], chk.Args[1]

	xsLen := vxs.Len()
	for i := 0; i < xsLen; i++ {
		call(vf, vxs.Index(i))
	}
}
コード例 #6
0
ファイル: Slices+Fun.go プロジェクト: ASAPPinc/fun-go
func First(slice interface{}) (elem interface{}) {
	chk := ty.Check(
		new(func([]ty.A) ty.A),
		slice)
	sliceVal, elemTyp := chk.Args[0], chk.Returns[0]

	if sliceVal.IsNil() || sliceVal.Len() == 0 {
		return reflect.Zero(elemTyp).Interface()
	}
	return sliceVal.Index(0).Interface()
}
コード例 #7
0
ファイル: Slices+Fun.go プロジェクト: ASAPPinc/fun-go
func Last(slice interface{}) (elem interface{}) {
	chk := ty.Check(
		new(func([]ty.A) ty.A),
		slice)
	vSlice, tElem := chk.Args[0], chk.Returns[0]

	if vSlice.IsNil() || vSlice.Len() == 0 {
		return reflect.Zero(tElem).Interface()
	}
	return vSlice.Index(vSlice.Len() - 1).Interface()
}
コード例 #8
0
ファイル: map.go プロジェクト: johnvilsack/golang-stuff
// Values has a parametric type:
//
//	func Values(m map[A]B) []B
//
// Values returns a list of the values of `m` in an unspecified order.
func Values(m interface{}) interface{} {
	chk := ty.Check(
		new(func(map[ty.A]ty.B) []ty.B),
		m)
	vm, tvals := chk.Args[0], chk.Returns[0]

	vvals := reflect.MakeSlice(tvals, vm.Len(), vm.Len())
	for i, vkey := range vm.MapKeys() {
		vvals.Index(i).Set(vm.MapIndex(vkey))
	}
	return vvals.Interface()
}
コード例 #9
0
ファイル: list.go プロジェクト: johnvilsack/golang-stuff
// Reverse has a parametric type:
//
//	func Reverse(xs []A) []A
//
// Reverse returns a new slice that is the reverse of `xs`.
func Reverse(xs interface{}) interface{} {
	chk := ty.Check(
		new(func([]ty.A) []ty.A),
		xs)
	vxs, tys := chk.Args[0], chk.Returns[0]

	xsLen := vxs.Len()
	vys := reflect.MakeSlice(tys, xsLen, xsLen)
	for i := 0; i < xsLen; i++ {
		vys.Index(i).Set(vxs.Index(xsLen - 1 - i))
	}
	return vys.Interface()
}
コード例 #10
0
ファイル: cycle.go プロジェクト: acsellers/ty
// CycleEach has a parametric type
//
//  func CycleEach(f func(A), xs []A, n int)
//
// CycleEach calls each element of xs with f in order n times
func CycleEach(f, xs interface{}, n int) {
	chk := ty.Check(
		new(func(func(ty.A), []ty.A, int)),
		f, xs, n)
	vp, vxs := chk.Args[0], chk.Args[1]

	xsLen := vxs.Len()
	for t := 0; t < n; t++ {
		for i := 0; i < xsLen; i++ {
			call(vp, vxs.Index(i))
		}
	}
}
コード例 #11
0
ファイル: list.go プロジェクト: johnvilsack/golang-stuff
// Concat has a parametric type:
//
//	func Concat(xs [][]A) []A
//
// Concat returns a new flattened list by appending all elements of `xs`.
func Concat(xs interface{}) interface{} {
	chk := ty.Check(
		new(func([][]ty.A) []ty.A),
		xs)
	vxs, tflat := chk.Args[0], chk.Returns[0]

	xsLen := vxs.Len()
	vflat := reflect.MakeSlice(tflat, 0, xsLen*3)
	for i := 0; i < xsLen; i++ {
		vflat = reflect.AppendSlice(vflat, vxs.Index(i))
	}
	return vflat.Interface()
}
コード例 #12
0
ファイル: list_checkers.go プロジェクト: acsellers/ty
// Count has a parametric type:
//
//  func Count(f func(A) bool, xs []A) int
//
// Count returns the number of elements of xs for which f
// returns true
func Count(f, xs interface{}) (matches int) {
	chk := ty.Check(
		new(func(func(ty.A) bool, []ty.A)),
		f, xs)
	vp, vxs := chk.Args[0], chk.Args[1]

	xsLen := vxs.Len()
	for i := 0; i < xsLen; i++ {
		if call1(vp, vxs.Index(i)).Bool() {
			matches++
		}
	}
	return
}
コード例 #13
0
ファイル: rand.go プロジェクト: ngaut/ty
// ShuffleGen has a parametric type:
//
//	func ShuffleGen(xs []A, rng *rand.Rand)
//
// ShuffleGen shuffles `xs` in place using the given random number
// generator `rng`.
func ShuffleGen(xs interface{}, rng *rand.Rand) {
	chk := ty.Check(
		new(func([]ty.A, *rand.Rand)),
		xs, rng)
	vxs := chk.Args[0]

	// Implements the Fisher-Yates shuffle: http://goo.gl/Hb9vg
	xsLen := vxs.Len()
	swapper := swapperOf(vxs.Type().Elem())
	for i := xsLen - 1; i >= 1; i-- {
		j := rng.Intn(i + 1)
		swapper.swap(vxs.Index(i), vxs.Index(j))
	}
}
コード例 #14
0
ファイル: list.go プロジェクト: BurntSushi/ty
// In has a parametric type:
//
//	func In(needle A, haystack []A) bool
//
// In returns `true` if and only if `v` can be found in `xs`. The equality test
// used is Go's standard `==` equality and NOT deep equality.
//
// Note that this requires that `A` be a type that can be meaningfully compared.
func In(needle, haystack interface{}) bool {
	chk := ty.Check(
		new(func(ty.A, []ty.A) bool),
		needle, haystack)
	vhaystack := chk.Args[1]

	length := vhaystack.Len()
	for i := 0; i < length; i++ {
		if vhaystack.Index(i).Interface() == needle {
			return true
		}
	}
	return false
}
コード例 #15
0
ファイル: list.go プロジェクト: BurntSushi/ty
// Exists has a parametric type:
//
//	func Exists(p func(A) bool, xs []A) bool
//
// Exists returns `true` if and only if an element in `xs` satisfies `p`.
func Exists(f, xs interface{}) bool {
	chk := ty.Check(
		new(func(func(ty.A) bool, []ty.A) bool),
		f, xs)
	vf, vxs := chk.Args[0], chk.Args[1]

	xsLen := vxs.Len()
	for i := 0; i < xsLen; i++ {
		if call1(vf, vxs.Index(i)).Interface().(bool) {
			return true
		}
	}
	return false
}
コード例 #16
0
ファイル: list_checkers.go プロジェクト: acsellers/ty
// None has a parametric type
//
//  func None(f func(A) bool, xs []A) bool
//
// None returns true if none of the elements in xs caused f to return
// true, false otherwise
func None(f, xs interface{}) bool {
	chk := ty.Check(
		new(func(func(ty.A) bool, []ty.A)),
		f, xs)
	vp, vxs := chk.Args[0], chk.Args[1]

	xsLen := vxs.Len()
	for i := 0; i < xsLen; i++ {
		if call1(vp, vxs.Index(i)).Bool() {
			return false
		}
	}
	return true
}
コード例 #17
0
ファイル: set.go プロジェクト: johnvilsack/golang-stuff
// 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()
}
コード例 #18
0
ファイル: list.go プロジェクト: johnvilsack/golang-stuff
// Map has a parametric type:
//
//	func Map(f func(A) B, xs []A) []B
//
// Map returns the list corresponding to the return value of applying
// `f` to each element in `xs`.
func Map(f, xs interface{}) interface{} {
	chk := ty.Check(
		new(func(func(ty.A) ty.B, []ty.A) []ty.B),
		f, xs)
	vf, vxs, tys := chk.Args[0], chk.Args[1], chk.Returns[0]

	xsLen := vxs.Len()
	vys := reflect.MakeSlice(tys, xsLen, xsLen)
	for i := 0; i < xsLen; i++ {
		vy := call1(vf, vxs.Index(i))
		vys.Index(i).Set(vy)
	}
	return vys.Interface()
}
コード例 #19
0
ファイル: list_checkers.go プロジェクト: acsellers/ty
// Detect has a parametric type:
//
//  func Detect(f func(A) bool, xs []A) A
//
// Detect returns the first element for which f returns
// true, if none are returned it returns nil
func Detect(f, xs interface{}) interface{} {
	chk := ty.Check(
		new(func(func(ty.A) bool, []ty.A)),
		f, xs)
	vp, vxs := chk.Args[0], chk.Args[1]

	xsLen := vxs.Len()
	for i := 0; i < xsLen; i++ {
		if call1(vp, vxs.Index(i)).Bool() {
			return vxs.Index(i).Interface()
		}
	}
	return nil
}
コード例 #20
0
ファイル: min_max_sum.go プロジェクト: acsellers/ty
// SumFloat has a parametric type:
//
//  func SumFloat(f func(A) float64, xs []A) float64
//
// SumFloat returns the sum of the values returned from f
func SumFloat(f, xs interface{}) float64 {
	chk := ty.Check(
		new(func(func(ty.A) float64, []ty.A)),
		f, xs)
	vp, vxs := chk.Args[0], chk.Args[1]

	xsLen := vxs.Len()
	var sum float64
	for i := 0; i < xsLen; i++ {
		vx := vxs.Index(i)
		sum += call1(vp, vx).Float()
	}

	return sum
}
コード例 #21
0
ファイル: set.go プロジェクト: johnvilsack/golang-stuff
// 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()
}
コード例 #22
0
ファイル: ordmap.go プロジェクト: ngaut/ty
// OrderedMap returns a new instance of OrdMap instantiated with the key
// and value types given. Namely, the types should be provided via nil
// pointers, e.g., to create a map from strings to integers:
//
//	omap := OrderedMap(new(string), new(int))
//
// An ordered map maintains the insertion order of all keys in the map.
// Namely, `(*OrdMap).Keys()` returns a slice of keys in the order
// they were inserted. The order of a key can *only* be changed if it is
// deleted and added again.
//
// All of the operations on an ordered map have the same time complexity as
// the built-in `map`, except for `Delete` which is O(n) in the number of
// keys.
func OrderedMap(ktype, vtype interface{}) *OrdMap {
	// A giant hack to get `Check` to do all the type construction work for us.
	chk := ty.Check(
		new(func(*ty.A, *ty.B) (ty.A, ty.B, map[ty.A]ty.B, []ty.A)),
		ktype, vtype)
	tkey, tval := chk.Returns[0], chk.Returns[1]
	tmap, tkeys := chk.Returns[2], chk.Returns[3]

	return &OrdMap{
		m:     reflect.MakeMap(tmap),
		keys:  reflect.MakeSlice(tkeys, 0, 10),
		ktype: tkey,
		vtype: tval,
	}
}
コード例 #23
0
ファイル: list.go プロジェクト: johnvilsack/golang-stuff
// Filter has a parametric type:
//
//	func Filter(p func(A) bool, xs []A) []A
//
// Filter returns a new list only containing the elements of `xs` that satisfy
// the predicate `p`.
func Filter(p, xs interface{}) interface{} {
	chk := ty.Check(
		new(func(func(ty.A) bool, []ty.A) []ty.A),
		p, xs)
	vp, vxs, tys := chk.Args[0], chk.Args[1], chk.Returns[0]

	xsLen := vxs.Len()
	vys := reflect.MakeSlice(tys, 0, xsLen)
	for i := 0; i < xsLen; i++ {
		vx := vxs.Index(i)
		if call1(vp, vx).Bool() {
			vys = reflect.Append(vys, vx)
		}
	}
	return vys.Interface()
}
コード例 #24
0
ファイル: cycle.go プロジェクト: acsellers/ty
// CycleMap has a parametric type
//
//  func CycleMap(f func(A) B, xs []A, n int) []B
//
// CycleMap runs Map n times against xs with f and returns the result
func CycleMap(f, xs interface{}, n int) interface{} {
	chk := ty.Check(
		new(func(func(ty.A) ty.B, []ty.A, int) []ty.B),
		f, xs, n)
	vp, vxs, tys := chk.Args[0], chk.Args[1], chk.Returns[0]

	xsLen := vxs.Len()
	vys := reflect.MakeSlice(tys, xsLen*n, xsLen*n)
	for t := 0; t < n; t++ {
		for i := 0; i < xsLen; i++ {
			vy := call1(vp, vxs.Index(i))
			vys.Index(t*xsLen + i).Set(vy)
		}
	}
	return vys.Interface()
}
コード例 #25
0
ファイル: list_replace.go プロジェクト: acsellers/ty
// Replace has a parametric type
//
//  func Replace(xs, ys []A) []A
//
// Replace changes elements of xs with elements of ys until one array is exhausted
func Replace(xs, ys interface{}) interface{} {
	chk := ty.Check(
		new(func([]ty.A, []ty.A) []ty.A),
		xs, ys)
	vxs, vys, tzs := chk.Args[0], chk.Args[1], chk.Returns[0]

	xsLen, ysLen := vxs.Len(), vys.Len()
	vzs := reflect.MakeSlice(tzs, xsLen, xsLen)
	for i := 0; i < xsLen; i++ {
		if i < ysLen {
			vzs.Index(i).Set(vys.Index(i))
		} else {
			vzs.Index(i).Set(vxs.Index(i))
		}
	}

	return vzs.Interface()
}
コード例 #26
0
ファイル: sort.go プロジェクト: ngaut/ty
// QuickSort has a parametric type:
//
//	func QuickSort(less func(x1 A, x2 A) bool, []A) []A
//
// QuickSort applies the "quicksort" algorithm to return a new sorted list
// of `xs`, where `xs` is not modified.
//
// `less` should be a function that returns true if and only if `x1` is less
// than `x2`.
func QuickSort(less, xs interface{}) interface{} {
	chk := ty.Check(
		new(func(func(ty.A, ty.A) bool, []ty.A) []ty.A),
		less, xs)
	vless, vxs, tys := chk.Args[0], chk.Args[1], chk.Returns[0]

	var qsort func(left, right int)
	var partition func(left, right, pivot int) int
	xsind := Range(0, vxs.Len())

	qsort = func(left, right int) {
		if left >= right {
			return
		}
		pivot := (left + right) / 2
		pivot = partition(left, right, pivot)

		qsort(left, pivot-1)
		qsort(pivot+1, right)
	}
	partition = func(left, right, pivot int) int {
		vpivot := xsind[pivot]
		xsind[pivot], xsind[right] = xsind[right], xsind[pivot]

		ind := left
		for i := left; i < right; i++ {
			if call1(vless, vxs.Index(xsind[i]), vxs.Index(vpivot)).Bool() {
				xsind[i], xsind[ind] = xsind[ind], xsind[i]
				ind++
			}
		}
		xsind[ind], xsind[right] = xsind[right], xsind[ind]
		return ind
	}

	// Sort `xsind` in place.
	qsort(0, len(xsind)-1)

	vys := reflect.MakeSlice(tys, len(xsind), len(xsind))
	for i, xsIndex := range xsind {
		vys.Index(i).Set(vxs.Index(xsIndex))
	}
	return vys.Interface()
}
コード例 #27
0
ファイル: table.go プロジェクト: BurntSushi/intern
// ExpandSquareTable has a parametric type:
//
//	func ExpandSquareTable([]A, int) ([]A, int)
//
// ExpandSquareTable takes any slice holding a square table of data (row-major)
// and expands the length of the table to at least the length provided. A new
// slice is returned (with data from `slice` copied to it) along with the
// length of the table.
//
// This function is exported so that you may use it to build your own dense
// tables (since the Table in this package can only store floats).
func ExpandSquareTable(slice interface{}, leastLen int) (interface{}, int) {
	chk := ty.Check(
		new(func([]ty.A, int) []ty.A),
		slice, leastLen)
	vslice, tslice := chk.Args[0], chk.Returns[0]

	oldLen := int(math.Sqrt(float64(vslice.Cap())))
	newLen := oldLen * 2
	if newLen < leastLen {
		newLen = leastLen
	}
	rslice := reflect.MakeSlice(tslice, newLen*newLen, newLen*newLen)
	for r := 0; r < oldLen; r++ {
		for c := 0; c < oldLen; c++ {
			rslice.Index(r*newLen + c).Set(vslice.Index(r*oldLen + c))
		}
	}
	return rslice.Interface(), newLen
}
コード例 #28
0
ファイル: list.go プロジェクト: johnvilsack/golang-stuff
// Foldr has a parametric type:
//
//	func Foldr(f func(A, B) B, init B, xs []A) B
//
// Foldr reduces a list of A to a single element B using a right fold with
// an initial value `init`.
func Foldr(f, init, xs interface{}) interface{} {
	chk := ty.Check(
		new(func(func(ty.A, ty.B) ty.B, ty.B, []ty.A) ty.B),
		f, init, xs)
	vf, vinit, vxs, tb := chk.Args[0], chk.Args[1], chk.Args[2], chk.Returns[0]

	xsLen := vxs.Len()
	vb := zeroValue(tb)
	vb.Set(vinit)
	if xsLen == 0 {
		return vb.Interface()
	}

	vb.Set(call1(vf, vxs.Index(xsLen-1), vb))
	for i := xsLen - 2; i >= 0; i-- {
		vb.Set(call1(vf, vxs.Index(i), vb))
	}
	return vb.Interface()
}
コード例 #29
0
ファイル: func.go プロジェクト: ngaut/ty
// Memo has a parametric type:
//
//	func Memo(f func(A) B) func(A) B
//
// Memo memoizes any function of a single argument that returns a single value.
// The type `A` must be a Go type for which the comparison operators `==` and
// `!=` are fully defined (this rules out functions, maps and slices).
func Memo(f interface{}) interface{} {
	chk := ty.Check(
		new(func(func(ty.A) ty.B)),
		f)
	vf := chk.Args[0]

	saved := make(map[interface{}]reflect.Value)
	memo := func(in []reflect.Value) []reflect.Value {
		val := in[0].Interface()
		ret, ok := saved[val]
		if ok {
			return []reflect.Value{ret}
		}

		ret = call1(vf, in[0])
		saved[val] = ret
		return []reflect.Value{ret}
	}
	return reflect.MakeFunc(vf.Type(), memo).Interface()
}
コード例 #30
0
ファイル: list.go プロジェクト: acsellers/ty
// Drop has a parametric type:
//
//  func Drop(f func(A) bool, xs []A) []A
//
// Drop calls f on each element of xs until it returns true, then returns
// that element and the remaining elements of xs
func Drop(f, xs interface{}) interface{} {
	chk := ty.Check(
		new(func(func(ty.A) bool, []ty.A) []ty.A),
		f, xs)
	vp, vxs, txs := chk.Args[0], chk.Args[1], chk.Returns[0]

	xsLen := vxs.Len()
	vys := reflect.MakeSlice(txs, 0, xsLen)

	found := false
	for i := 0; i < xsLen; i++ {
		vx := vxs.Index(i)
		if found || call1(vp, vx).Bool() {
			vys = reflect.Append(vys, vx)
			found = true
		}
	}

	return vys.Interface()
}