otter icon indicating copy to clipboard operation
otter copied to clipboard

Add a constructor which accepts some number of option functions

Open sammy-hughes opened this issue 8 months ago • 1 comments

Clarification and motivation

I want to configure new instances of Cache using the functional options pattern instead of chained methods.

cache, err := NewWithOptions(
    otter.WithDeletionListener(func(key string, value string, reason otter.DeletionCause) {
	    fmt.Printf("eviction %d -- %s: %s", reason, key, value)
    }),
    otter.WithInitialCapacityAt10k,
    otter.WithStatistics,
)

The above example supposes an API implemented as sugared calls to the existing builder pattern. Such a constructor may be implemented by first creating an instance of Builder, then applying each option in turn. The above is imagined as being implemented like so:

func NewWithOptions[K comparable, V any](options ...CacheOption[K, V]) (otter.Cache[K, V], error) {
	builder, err := otter.NewBuilder[K, V](100000)
	if err != nil {
		return otter.Cache[K, V]{}, err
	}

	for i := range options {
		err = options[i](builder)
		if err != nil {
			return otter.Cache[K, V]{}, err
		}
	}

	return builder.Build()
}

type CacheOption[K comparable, V any] func(builder *otter.Builder[K, V]) error

func WithStatistics[K comparable, V any](builder *otter.Builder[K, V]) error {
	builder.CollectStats()

	return nil
}

func WithInitialCapacityAt10k[K comparable, V any](builder *otter.Builder[K, V]) error {
    builder.InitialCapacity(10000)
    
    return nil
}

type DeletionListener[K comparable, V any] func(K, V, otter.DeletionCause)

func WithDeletionListener[K comparable, V any](listener DeletionListener[K, V]) CacheOption[K, V] {
	return func(builder *otter.Builder[K, V]) error {
		builder.DeletionListener(listener)

		return nil
	}
}

Acceptance criteria

  1. Define a variadic constructor for an instance of Cache, taking zero to many parameters as functions of the signature described below.
  2. Declare a type describing a function which takes an argument of *Builder[K comparable, V any] and returning an error.
  3. Add functions with at least a 1-to-1 correspondence to the current set of methods available on the Builder type but which return the same instance of Builder.

sammy-hughes avatar Jun 20 '24 04:06 sammy-hughes