Help us shape the future of Go! Take the 2026 Go Developer Survey

proto

package module
v0.0.0-...-96b560c Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 19, 2012 License: MIT Imports: 1 Imported by: 0

README

proto

proto gives Go operations like Map, Reduce, Filter, De/Multiplex, etc. without sacrificing idiomatic harmony or speed. It also introduces a convenience type for these functions, Proto, which is a stand-in for the empty interface (interface{}), which is used to box values being sent to these operations.

Documentation

Please see documentation.{txt,html} for the automatically generated documentation - or better yet, just run:

godoc github.com/eblume/proto | less

That's probably a better idea since there's a decent chance the documentation might be lagging behind the current code base, since it has to be run manually (at this moment).

You can also take a look at the *_test.go files for an even better look in to how to use Proto. I will make one disclaimer, which is that code written with Proto has some unavoidable boilerplate in the form of casting to/from the Proto type - this boilerplate is annoying but is much less obvious and significant with larger code bases that use Proto-style channels in chains.

Examples

Double every integer in a slice:

inputs := []Proto{0, 1, 2, 3, 4, 5, 6}
sent := Send(inputs)
doubler := func(a Proto) Proto {
    return a.(int) * 2
}
mapped := Map(doubler, sent)
doubled := Gather(mapped)

Double every integer, chained:

doubled := Gather(Map(func(a Proto) Proto {
    return a.(int) * 2
}, Send([]Proto{0, 1, 2, 3, 4, 5, 6})))

License

Please see COPYING for more details on the licensing of this software.

Documentation

Overview

proto gives Go operations like Map, Reduce, Filter, De/Multiplex, etc. without sacrificing idiomatic harmony or speed.

The `Proto` type is a stand-in approximation for dynamic typing. Due to Go's powerful casting and type inference idioms, we can approximate the flexibility of dynamic typing even though Go is a statically typed language. Doing so sacrifices some of the benefits of static typing AND some of the benefits of dynamic typing, but this sacrifice is fundamentally required by Go until such time as a true 'Generic' type is implemented.

In order to use a Proto-typed variable (from here on out, simply a 'Proto'), you will generally have to cast it to a type that you will know to use based on the semantics of your program.

This package (specifically, the other files in this package) provide operations on Proto variables as well as some that make Proto variables out of 'traditionally typed' variables. Many of the operations will require the use of higher-order functions which you will need to provide, and those functions commonly will need you to manually "unbox" (cast-from-Proto) the variable to perform useful operations.

Examples of the use of this package can be found in the "*_test.go" files, which contain testing code. A good example of a higher-order function which will commonly need manual-unboxing is the `Filter` function, found in "filter.go". `Filter` takes as its first argument a filter-function which will almost certainly require you to un-box the Proto channel values that it receives to perform the filtering action.

Finally, a word on the entire point of this package: while it is named after the Proto type that pervades it and guides its syntax, the true nature of the `proto` package lies in cascading channels, rather than in dynamic typing. In fact this package might be more appropriately named after channels. Maybe `canal` would have been a better name. I wanted to bring the syntax and familiar patterns of functional programming idioms to the power and scalability of Go's goroutines and channels, and found that the syntax made this task very simple.

You may find, as I did, that the majority of the code in this package is very 'obvious'. At first I was concerned by this - much of the code is very trivial - but now I feel pleased by the re-usability and natural 'correctness' of `proto`. Look at this package not as some monumental time-saving framework, but rather as a light scaffold for a useful and idiomatic style of programming within the existing constructs of Go.

Ultimately, though, you're going to be typing the word Proto an awful lot, and thus the type became the eponym.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Demultiplex

func Demultiplex(fn FilterFn, recv chan Proto) (passed chan Proto,
	failed chan Proto)

Separate an input channel in to two output channels by applying a filter function (see `Filter`). The first output channel will get the values that passed the filter, the second will get those that did not.

func Filter

func Filter(fn FilterFn, recv chan Proto) (send chan Proto)

Filter the channel with the given function. `fn` must return true or false for each individual element the channel may receive. If true, the element will be sent on the return channel. As usual, this function does not block beyond the time taken to set up the returned channel.

func Map

func Map(fn MapFn, recv chan Proto) (send chan Proto)

Apply `fn` to each value on `recv`, and send the results on the return channel. Order is preserved. Though `Map` does not block, it is not parallel - for a parallel version, see `PMap`.

func Multiplex

func Multiplex(inputs ...chan Proto) (send chan Proto)

Combine multiple input channels in to one.

func PFilter

func PFilter(fn FilterFn, recv chan Proto) (send chan Proto)

Exactly like `Filter`, but every filter application gets its own goroutine. Order is NOT preserved. As a rule of thumb, `PFilter` is only preferable over `Filter` if `fn` is very expensive or if the consumer of the result channel is very slow and buffering would be preferred (thus keeping up consumption rates of `recv`).

func PMap

func PMap(fn MapFn, recv chan Proto) (send chan Proto)

Parallel version of `Map`. Order is NOT preserved.

func PTrigger

func PTrigger(fn TriggerFn, count int) (send chan Proto)

Exactly like `Trigger`, but each trigger happens in parallel. Order is NOT preserved.

func Reduce

func Reduce(fn ReduceFn, recv chan Proto) (send chan Proto)

Reduce the `recv` channel by repeatedly applying `fn` on pairs of values until only one value remains. The first invocation of `fn` will receive the first two values from `recv`, all subsequent invocations will receive progressive elements from `recv` *in order* - that is, `fn` may or may not be associative. If `recv` receives only one value, `fn` will not be called and the first and only value will be sent as the result. If `recv` receives no values, `nil` will be sent (as a Proto type) as the result. Regardless, `recv` will always receive one value and then be closed.

func Send

func Send(vals []Proto) (send chan Proto)

Given a slice of Proto's, send them on a newly created channel and then close that channel. If the slice is empty, this does the correct thing - it creates the channel, and then closes it promptly. As expected, this function does not block beyond the setup time.

func Splice

func Splice(a chan Proto, b chan Proto)

Sends all items from channel `a` to channel `b`, and then closes `b`. Does not close `a`. Does not block. This function is useful, eg, when trying to create a loop of procedures that return channels - take the output channel of the last element in the chain, create a channel for the input to the first element in the chain, and link them using Splice.

func Trigger

func Trigger(fn TriggerFn, count int) (send chan Proto)

Call `fn` `count` times, passing the result on to the returned channel.

Types

type FilterFn

type FilterFn func(Proto) bool

Filter function type definition. A FilterFn is given a single Proto and must decide whether to return `true` or `false`, meaning "filter" or "don't filter" respectively. The implementer will probably need to unbox the Proto argument to a more useful type manually.

type MapFn

type MapFn func(Proto) Proto

Mapping function type definition.

type Proto

type Proto interface{}

The Proto type. (Get it?)

func Gather

func Gather(recv chan Proto) (result []Proto)

The inverse of `Send`. Given a channel of Proto's, gathers them in to a newly created slice, and then returns that slice. This function DOES BLOCK. If the channel never receives any values, the returned slice will be empty, with length 0, and capacity 1.

type ReduceFn

type ReduceFn func(Proto, Proto) Proto

Reducing function type definition.

type TriggerFn

type TriggerFn func() Proto

Trigger function type deceleration.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL