Go泛型编程库:gen

jopen 11年前

gen 项目目的是为 Go 语言带来了类似泛型的函数,灵感来自 C# 的 LinQ 和 JavaScript 的 Array methods 以及 underscore 库。操作包括过滤、分组、排序等等。

Where

Returns a new slice (plural type) whose elements return true for passed func. Comparable to Linq’s Where and JavaScript’s filter.

func (rcv Things) Where(fn func(*Thing) bool) Things

Example:

shiny := func(p *Product) bool {      return p.Manufacturer == "Apple"  }  wishlist := products.Where(shiny)

Count

Returns an int representing the number of elements which return true for passed func. Comparable to Linq’s Count.

func (rcv Things) Count(fn func(*Thing) bool) int

Example:

countDracula := monsters.Count(func(m *Monster) bool {      return m.HasFangs()  })

Any

Returns true if one or more elements returns true for passed func. Comparable to Linq’s Any or underscore’s some.

func (rcv Things) Any(fn func(*Thing) bool) bool

Example:

bueller := func(s *Student) bool {      return s.IsTruant  }  willBeHijinks := students.Any(bueller)

All

Returns true if every element returns true for passed func. Comparable to Linq’s All or underscore’s every.

func (rcv Things) All(fn func(*Thing) bool) bool

Example:

mustPass := func(t *Thing) bool {      return !t.IsEternal  }  cliché := things.All(mustPass)

First

Returns first element which returns true for passed func. Comparable to Linq’s First or underscore’s find.

func (rcv Things) First(fn func(*Thing) bool) (*Thing, error)

Example:

come := func(c *Customer) bool {      return c.IsHere  }  served, err := people.First(come)

Returns error if no elements satisfy the func.

Single

Returns unique element which returns true for passed func. Comparable to Linq’s Single.

func (rcv Things) Single(fn func(*Thing) bool) (*Thing, error)

Example:

id := request.Id  byId := func(t *Thing) bool {      return t.Id == id  }  item, err := things.Single(byId)

Returns error if multiple or no elements satisfy the func.

Each

Invokes passed func on every element. Comparable to underscore’s each.

func (rcv Things) Each(fn func(*Thing))

Example:

update := func(s *Score) {      s.Recalc()  }  scores.Each(update)

Sort

Returns a new slice (plural type) whose elements are sorted based on a func defining ‘less’. The less func takes two elements, and returns true if the first element is less than the second element.

func (rcv Things) Sort(less func(*Thing, *Thing) bool) Things

Example:

byRank := func(a, b *Player) bool {      return a.Rank < b.Rank  }  leaderboard := player.Sort(byRank)

SortDesc works similarly, returning the elements in reverse order. Its implementation negates ‘less’, so is effectively Sort(equalOrGreater).

IsSorted(Desc) uses a similar idiom, returning true if the elements are sorted according to the ‘less’ comparer.

Distinct

Returns a new slice (plural type) representing unique elements. Comparable to Linq’s Distinct or underscore’s uniq.

func (rcv Things) Distinct() Things

Example:

snowflakes := hipsters.Distinct()

Keep in mind that pointers and values have different notions of equality, and therefore distinctness.

DistinctBy

Returns a new slice (plural type) representing unique elements, where equality is defined by a passed func.

func (rcv Things) DistinctBy(func(*Thing, *Thing) bool) Things

Example:

hairstyle := func(a *Fashionista, b *Fashionista) bool {      a.Hairstyle == b.Hairstyle  }  trendsetters := fashionistas.DistinctBy(hairstyle)

Min

func (rcv Things) Min(less func(*Thing, *Thing) bool) (*Thing, error)

Returns the element containing the minimum value, when compared to other elements using a passed func defining ‘less’. Returns an error when invoked on an empty slice, considered an invalid operation.

Example:

byPrice := func(a, b *Product) bool {      return a.Price < b.Price  }  cheapest, err := products.Min(byPrice)

In the case of multiple items being equally minimal, the first such element is returned.

Max

func (rcv Things) Max(less func(*Thing, *Thing) bool) (*Thing, error)

Returns the element containing the maximum value, when compared to other elements using a passed func defining ‘less’. Returns an error when invoked on an empty slice, considered an invalid operation.

Example:

byArea := func(a, b *House) bool {      return a.Area() < b.Area()  }  roomiest, err := houses.Max(byArea)

Subsetting

By default, all of the above standard methods are created when you gen a type. If you would prefer only to generate specific methods, you can include a specially-formatted “tag” comment, which follows the convention of struct tags.

// gen:"Count,Where,Sort"  type Thing struct {      Name  string      Year  int        Sales float64  }

Give the comment its own line adjacent to the type defintion as you would with (or in addition to) godocs, and avoid spaces.

(Note: previous versions of gen put the comment within the type definition.)

Custom methods

Note: Custom methods are likely to be deprecated in favor of more-flexible “projection methods”. See this GitHub issue for details.

Custom methods use struct tags to project fields of a struct.

Given an example type:

type Thing struct {      Name  string  `gen:"Select,Aggregate"`      Year  int     `gen:"GroupBy,Select,Min"`      Sales float64 `gen:"Sum,Max,Average"`  }

You can infer the format from above. (Avoid spaces between methods.)

Below, {{Name}} and {{Type}} represent the name and type of a tagged field. The actual name will be substituted when you gen.

Select

func (rcv Things) Select{{Name}}() []string

Returns a slice of a specific field. Comparable to Linq’s Select or underscore’s pluck.

Example:

names := myThings.SelectName() // => ["Thing One", "Thing Two"]

GroupBy

func (rcv Things) GroupBy{{Name}}() map[{{Type}}]Things

Groups elements into a map keyed by the tagged field’s value. Comparable to Linq’s GroupBy or underscore’s groupBy.

Example:

report := myThings.GroupByYear() // => { 1995: ['Thing One', 'Thing Two'], 2007: ['Thing Three', 'Thing Four'] }

Sum

func (rcv Things) Sum{{Name}}() {{Type}}

Sums a field over all elements of Things. Comparable to Linq’s Sum.

Example:

revenue := myThings.SumSales() // => 68885.74

Average

func (rcv Things) Average{{Name}}() {{Type}}

Sums a field over all elements and divides by len(Things). Comparable to Linq’s Average.

Example:

avg := myThings.AverageSales() // => 30005.74

Max

func (rcv Things) Max{{Name}}() {{Type}}

Selects the largest value of a field in Things. Comparable to Linq’s Max.

Example:

bigmoney := myThings.MaxSales() // => 685698.99

Min

func (rcv Things) Min{{Name}}() {{Type}}

Selects the least value of a field in Things. Comparable to Linq’s Min.

Example:

earliest := myThings.MinYear() // => 1995

Aggregate

func (rcv Things) Aggregate{{Name}}(fn func({{Type}}, {{Type}}) {{Type}}) {{Type}}

Iterates over Things, operating on each element while maintaining ‘state’. Comparable to Linq’s Aggregate or underscore’s reduce.

Example:

var join = func(state string, value string) string {      if state != "" {          state += ", "      }      return state + value  }  list := myThings.AggregateName(join) // => "Title One, Title Two, etc"

Go泛型编程库:gen

项目主页:http://www.open-open.com/lib/view/home/1389580392476