Experiments with Go generics

Related tags

Utilities generics
Overview

generics

Quick experiments with Go generics

  • algebra, a generic square root function for float, complex and and rational.
  • future, a concurrent cache ("future cache").
  • mapreduce, parallel Map, Reduce, and ForEach utilities
  • maps, a map with sorted keys based on a binary tree.
  • metric, a streamz-style multidimensional variable for production monitoring.
  • number, generic functions related to numbers (min, max, abs) and a user-defined complex type.
  • oddities, bugs and quirks.
  • pq, a priority queue
  • slices, generic slice utilities, and a user-defined Slice type.
  • stream, a streams library.
  • striped, a concurrency-safe map using lock striping, and also a custom hash/eq relation.

First impression:

This is really nice. It addresses the main things I miss about generics, namely

  • being able to change the equivalence relation of map;
  • better APIs for data structures like trees, graphs, and priority queues; and
  • the ability to generate efficient specialized code for a range of data types (though I understand that's not guaranteed);

and does so without overwhelming complexity.

By comparison, C++'s templates are extremely powerful, but syntactically and semantically quite complex, and historically the error messages have been both confusing and too late. (Templates also lead to considerable bloat in the text segment, but that may be a risk of the Go approach too.) Java's generics are limited to reference types, and thus are no use for efficient algorithms on (say) arrays of integers. Somehow the Go approach seems to do most of what I need while still feeling simple and easy to use.

Observations:

  • Slices can now be implemented in the language, but not without unsafe pointer arithmetic. The generic slice algorithms work nicely. So does sorting with a custom order.

  • unsafe.Sizeof is disallowed on type parameters, yet it can be simulated using pointer arithmetic (though not as a constant expression). Why?

  • I often need a hash table with an alternative hash function, for

    • comparing non-canonical pointers (e.g. *big.Int, go/types.Type) by their referent;
    • comparing non-comparable values (such as slices) under the obvious relation;
    • using an alternative comparator (e.g. case insensitive, absolute value) for simple types. However, the custom hash function often wants to be at least partly defined in terms of the standard hash function, so the latter needs to be exposed somehow; see hacks.RuntimeHash. I imagine that could be problematic.
  • min, max, abs work nicely.

  • Go's built-in complex numbers could be satisfactorily replaced by a library.

  • The abstract algebraic ring generates pretty good code. One can imagine writing some numerical analysis routines this way when the algorithm is sufficiently complex that it is best not duplicated.

  • I couldn't find a way to achieve ad-hoc polymorphism, that is, defining a generic function by cases specialized to each possible type. For example, I don't know how to write a generic version of all the math/bits.OnesCount functions that uses the most efficient implementation. (Typeswitch doesn't handle named variants of built-in types; and using reflect is cheating.)

  • In practice I suspect concurrent loop abstractions will nearly always want additional parameters such as: a limit on parallelism; a context; cancellation; control over errors (e.g. ignore, choose first, choose arbitrarily, or combine all).

Users will no doubt build generic libraries of collections, of stream processing functions, and of numeric analysis routines. The design space for each is large, and I imagine arriving at simple, efficient, and coherent APIs worthy of the standard library will be an arduous task. But there is no need to hurry.

My experiments have tended to parameterize over built-in types, or "any". I should probably spend more time investigating interface-constrained types.

You might also like...
Experimenting with golang generics to implement functional favorites like filter, map, && reduce.

funcy Experimenting with golang generics to implement functional favorites like filter, map, && reduce. 2021-12 To run the tests, you need to install

A collection of functional operators for golang with generics

fn fn is a collection of go functional operators with generics Getting Started P

Benchmarks to compare Go Generics

This is a collection of various sorts implemnted both as []int only and as const

Utility library that uses Go generics mechanism

golang-generics-util Utility library that explores Go generics (1.18) xsync Sync

CDN-like in-memory cache with shielding, and Go 1.18 Generics

cache CDN-like, middleware memory cache for Go applications with integrated shielding and Go 1.18 Generics. Usage package main import ( "context" "

Go 1.18 generics based slice and sorts.

genfuncs import "github.com/nwillc/genfuncs" Package genfuncs implements various functions utilizing Go's Generics to help avoid writing boilerplate c

F - Experimenting with Go 1.18 generics to write more functional Go code

f f is a simple library that leverages the new generics in Golang to create a tools for functional style of code. Pipe like '|' in Elixir or Elm. inp

A hands-on approach for getting started with Go generics.

Go Generics the Hard Way This repository is a hands-on approach for getting started with Go generics: Prerequisites: how to install the prerequisites

Optional type using Go 1.18 generics.

go.eth-p.dev/goptional Generic Optional (or Go Optional, if you prefer) goptional is a package that provides an implementation of an Optional[T] monad

Owner
Alan Donovan
Software engineer at GitHub; ex-Googler; co-author of https://gopl.io.
Alan Donovan
Code Generation for Functional Programming, Concurrency and Generics in Golang

goderive goderive derives mundane golang functions that you do not want to maintain and keeps them up to date. It does this by parsing your go code fo

Walter Schulze 1.1k Dec 25, 2022
Example code for Go generics

go-generics-example Example code for Go generics. Usage $ go build -gcflags=-G=3 Requirements Go 1.17 or later Advertise Go 言語にやってくる Generics は我々に何をも

mattn 1.3k Dec 30, 2022
Collection of unusual generics usecases in Go

Unusual Generics Type parameters or Generics in Go designed to reduce boilerplate for container data types like lists, graphs, etc. and functions like

Vladimir Stolyarov 54 Dec 14, 2022
Package truthy provides truthy condition testing with Go generics

Truthy Truthy is a package which uses generics (Go 1.18+) to create useful boolean tests and helper functions. Examples // truthy.Value returns the tr

Carl Johnson 32 Nov 11, 2022
Go Library for Competitive Programming with Generics

Go Library for Competitive Programming with Generics Go used to be a difficult language to use for competitive programming. However, with the introduc

Katsuyuki Tateishi 6 Dec 21, 2022
Extended library functions using generics in Go.

Just few extended standard library functions for Golang using generics.

null 1 Dec 16, 2021
A library that provides Go Generics friendly "optional" features.

go-optional A library that provides Go Generics friendly "optional" features. Synopsis some := optional.Some[int](123) fmt.Printf("%v\n", some.IsSome(

moznion 52 Dec 20, 2022
experimental promises in go1.18 with generics

async go a prototype of "promises" in go1.18. note: this is just an experiment used to test alternate patterns for dealing with asynchronous code in g

nick comer 63 Dec 23, 2022
Go 1.18 generics use cases and examples

Go 1.18 generics use cases What are generics? See Type Parameters Proposal. How to run the examples? As of today, gotip is the simplest way to run the

Vladimir Varankin 3 Jan 10, 2022
Functional tools in Go 1.18 using newly introduced generics

functools functools is a simple Go library that brings you your favourite functi

Rakeeb Hossain 173 Dec 5, 2022