No description
Find a file
Ruidy a1943556b4
fix: add explicit panic for Max/Min on empty slices
Adds length checks to Max and Min functions to provide clear,
explicit panic messages when called with empty slices, rather
than allowing confusing index-out-of-bounds panics.

Changes:
- Max: Added check for empty slice with "underscore.Max: empty slice" panic
- Min: Added check for empty slice with "underscore.Min: empty slice" panic
- Updated doc comments to document panic behavior
- Added TestMaxEmpty and TestMinEmpty to verify panic behavior

Impact:
- Better error messages for debugging
- Documented behavior prevents user surprises
- Non-breaking change (still panics, just with clearer message)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-14 13:51:35 +01:00
.github update codecov action version 2024-11-01 10:13:44 +01:00
docs feat: add ParallelFilter and UniqueInPlace functions 2025-09-01 18:16:59 -04:00
examples Pipe (#26) 2022-03-31 17:37:02 +02:00
maps feat: add Chunk, ContainsBy, UniqueBy, ParallelMap, map helpers 2025-09-01 18:03:38 -04:00
.dockerignore Pipe (#26) 2022-03-31 17:37:02 +02:00
.gitignore Adding some new funky functions (#32) 2022-09-04 09:21:31 +02:00
.golangci.yml refactor: migrate to Go 1.22 slices/cmp, update linters 2025-09-01 23:08:10 -04:00
all.go refactor: rename Every to All 2022-01-03 11:16:01 -04:00
all_test.go refactor: rename Every to All 2022-01-03 11:16:01 -04:00
any.go refactor: migrate to Go 1.22 slices/cmp, update linters 2025-09-01 23:08:10 -04:00
any_test.go refactor: rename Some to Any 2022-01-03 11:20:36 -04:00
chunk.go feat: add Chunk, ContainsBy, UniqueBy, ParallelMap, map helpers 2025-09-01 18:03:38 -04:00
chunk_test.go feat: add Chunk, ContainsBy, UniqueBy, ParallelMap, map helpers 2025-09-01 18:03:38 -04:00
contains.go feat: add Chunk, ContainsBy, UniqueBy, ParallelMap, map helpers 2025-09-01 18:03:38 -04:00
contains_test.go feat: add ParallelFilter and UniqueInPlace functions 2025-09-01 18:16:59 -04:00
CONTRIBUTING.md docs: improve README 2021-12-30 11:52:18 -04:00
count.go Updating Count function (#36) 2023-06-13 14:21:56 +02:00
count_test.go Updating Count function (#36) 2023-06-13 14:21:56 +02:00
difference.go U 21 diff (#23) 2022-03-24 17:30:01 +01:00
difference_test.go U 21 diff (#23) 2022-03-24 17:30:01 +01:00
Dockerfile [CHORE] bump docker golang version and dependencies (#40) 2025-07-14 17:13:22 +02:00
Dockerfile.doc [CHORE] bump docker golang version and dependencies (#40) 2025-07-14 17:13:22 +02:00
drop.go drop (#18) 2022-03-21 18:04:38 +01:00
drop_test.go refactor: migrate to Go 1.22 slices/cmp, update linters 2025-09-01 23:08:10 -04:00
each.go Pipe (#26) 2022-03-31 17:37:02 +02:00
each_test.go each (#10) 2022-01-28 12:51:42 -04:00
filter.go perf: pre-allocate Filter result slice 2025-11-14 13:44:07 +01:00
filter_test.go perf: pre-allocate Filter result slice 2025-11-14 13:44:07 +01:00
find.go doc: find 2021-12-29 13:07:40 -04:00
find_test.go refactor: migrate to Go 1.22 slices/cmp, update linters 2025-09-01 23:08:10 -04:00
flatmap.go add flatmap (#31) 2022-08-10 17:01:43 +02:00
flatmap_test.go refactor: migrate to Go 1.22 slices/cmp, update linters 2025-09-01 23:08:10 -04:00
go.mod [CHORE] bump docker golang version and dependencies (#40) 2025-07-14 17:13:22 +02:00
go.sum [CHORE] bump docker golang version and dependencies (#40) 2025-07-14 17:13:22 +02:00
groupby.go add groupBy function (#28) 2022-04-20 22:23:59 +02:00
groupby_test.go add groupBy function (#28) 2022-04-20 22:23:59 +02:00
intersection.go add intersection (#25) 2022-03-27 06:34:09 +02:00
intersection_test.go refactor: migrate to Go 1.22 slices/cmp, update linters 2025-09-01 23:08:10 -04:00
join.go refactor: migrate to Go 1.22 slices/cmp, update linters 2025-09-01 23:08:10 -04:00
join_test.go perf: pre-allocate Filter result slice 2025-11-14 13:44:07 +01:00
last.go last function (#17) 2022-03-21 18:04:30 +01:00
last_test.go last function (#17) 2022-03-21 18:04:30 +01:00
LICENSE.md docs: improve README 2021-12-30 11:52:18 -04:00
Makefile test: add coverage for ParallelMap and ParallelFilter workers 2025-09-01 22:54:03 -04:00
map.go doc: add documentation 2021-12-29 10:33:00 -04:00
map_test.go feat: map 2021-12-28 19:26:42 -04:00
max.go fix: add explicit panic for Max/Min on empty slices 2025-11-14 13:51:35 +01:00
max_test.go fix: add explicit panic for Max/Min on empty slices 2025-11-14 13:51:35 +01:00
min.go fix: add explicit panic for Max/Min on empty slices 2025-11-14 13:51:35 +01:00
min_test.go fix: add explicit panic for Max/Min on empty slices 2025-11-14 13:51:35 +01:00
orderBy.go perf: replace bubble sort with slices.SortFunc in OrderBy 2025-11-14 13:46:22 +01:00
orderBy_test.go perf: replace bubble sort with slices.SortFunc in OrderBy 2025-11-14 13:46:22 +01:00
parallel_filter.go feat: add ParallelFilter and UniqueInPlace functions 2025-09-01 18:16:59 -04:00
parallel_filter_test.go test: add coverage for ParallelMap and ParallelFilter workers 2025-09-01 22:54:03 -04:00
parallel_map.go feat: add Chunk, ContainsBy, UniqueBy, ParallelMap, map helpers 2025-09-01 18:03:38 -04:00
parallel_map_test.go test: add coverage for ParallelMap and ParallelFilter workers 2025-09-01 22:54:03 -04:00
partition.go perf: pre-allocate Partition result slices 2025-11-14 13:48:28 +01:00
partition_test.go feat: partition 2021-12-29 22:48:57 -04:00
pipe.go refactor: migrate to Go 1.22 slices/cmp, update linters 2025-09-01 23:08:10 -04:00
pipe_test.go Pipe (#26) 2022-03-31 17:37:02 +02:00
pointers.go Refresh documentation (#39) 2024-12-03 09:29:53 +01:00
pointers_test.go adding support for quick pointer conversion (#38) 2024-11-01 10:24:53 +01:00
range.go Refresh documentation (#39) 2024-12-03 09:29:53 +01:00
range_test.go Adding some new funky functions (#32) 2022-09-04 09:21:31 +02:00
README.md docs(readme): update usage, API, and utilities sections 2025-11-14 13:36:51 +01:00
reduce.go doc: add documentation 2021-12-29 10:33:00 -04:00
reduce_test.go feat: reduce 2021-12-28 19:47:05 -04:00
result.go refactor: migrate to Go 1.22 slices/cmp, update linters 2025-09-01 23:08:10 -04:00
result_internal_test.go test: add coverage for ParallelMap and ParallelFilter workers 2025-09-01 22:54:03 -04:00
result_test.go Add Result type (#16) 2022-03-18 18:32:41 +01:00
slices.go refactor: migrate to Go 1.22 slices/cmp, update linters 2025-09-01 23:08:10 -04:00
slices_test.go Adding support for Slice sorting (Asc & Desc) (#37) 2024-11-01 10:18:33 +01:00
sum.go refactor: migrate to Go 1.22 slices/cmp, update linters 2025-09-01 23:08:10 -04:00
sum_test.go Adding some new funky functions (#32) 2022-09-04 09:21:31 +02:00
ternary.go Refresh documentation (#39) 2024-12-03 09:29:53 +01:00
ternary_test.go ternary op function (#29) 2022-06-08 09:14:03 +02:00
tuple.go Refresh documentation (#39) 2024-12-03 09:29:53 +01:00
unique.go Refresh documentation (#39) 2024-12-03 09:29:53 +01:00
unique_by.go feat: add Chunk, ContainsBy, UniqueBy, ParallelMap, map helpers 2025-09-01 18:03:38 -04:00
unique_by_test.go feat: add Chunk, ContainsBy, UniqueBy, ParallelMap, map helpers 2025-09-01 18:03:38 -04:00
unique_in_place.go feat: add ParallelFilter and UniqueInPlace functions 2025-09-01 18:16:59 -04:00
unique_in_place_test.go feat: add ParallelFilter and UniqueInPlace functions 2025-09-01 18:16:59 -04:00
unique_test.go unique function (#27) 2022-04-12 23:32:13 +02:00
zip.go Refresh documentation (#39) 2024-12-03 09:29:53 +01:00
zip_test.go Adding some new funky functions (#32) 2022-09-04 09:21:31 +02:00

_Underscore

License Go version Go report test coverage OpenSSF Best Practices

underscore

underscore is a Go library providing useful functional programming helpers without extending any built-in objects.

It is mostly a port from the underscore.js library based on generics brought by Go 1.18.

Usage

📚 Follow this link for the documentation.

Install the library using

go get github.com/rjNemo/underscore@latest

Please check out the examples to see how to use the library.

package main

import (
 "fmt"
 u "github.com/rjNemo/underscore"
)

func main() {
 numbers := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
 // filter even numbers from the slice
 evens := u.Filter(numbers, func(n int) bool { return n%2 == 0 })
 // square every number in the slice
 squares := u.Map(evens, func(n int) int { return n * n })
 // reduce to the sum
 res := u.Reduce(squares, func(n, acc int) int { return n + acc }, 0)

 fmt.Println(res) // 120
}

Getting Started

These instructions will get you a copy of the project up and running on your local machine for development and testing purposes.

Prerequisites

You need at least go1.24 for development. The project is shipped with a Dockerfile based on go1.24.

If you prefer local development, navigate to the official download page and install version 1.24 or beyond.

Installing

First clone the repository

git clone https://github.com/rjNemo/underscore.git

Install dependencies

go mod download

And that's it.

Tests

To run the unit tests, you can simply run:

make test

Functions

underscore provides many of functions that support your favorite functional helpers

Collections

  • All
  • Any
  • Chunk
  • Contains
  • ContainsBy
  • Count
  • Difference
  • Drop
  • Each
  • Filter
  • Find
  • Flatmap
  • GroupBy
  • Intersection
  • Join / JoinProject
  • Last
  • Map
  • Max
  • Min
  • OrderBy
  • Partition
  • Range
  • Reduce
  • Sum / SumMap
  • Unique
  • UniqueBy
  • UniqueInPlace
  • Zip

Pipe

Calling NewPipe will cause all future method calls to return wrapped values. When you've finished the computation, call Value to retrieve the final value.

Methods not returning a slice such as Reduce, All, Any, will break the Chain and return Value instantly.

Concurrency

  • ParallelMap(ctx, values, workers, fn): apply a function concurrently while preserving order and supporting context cancellation.
  • ParallelFilter(ctx, values, workers, fn): filter concurrently with order preserved and context support.
package main

import (
 "context"
 "fmt"
 u "github.com/rjNemo/underscore"
)

func main() {
 out, err := u.ParallelMap(context.Background(), []int{1, 2, 3, 4}, 4,
  func(ctx context.Context, n int) (int, error) { return n * n, nil },
 )
 fmt.Println(out, err) // [1 4 9 16] <nil>
}
// ParallelFilter example
package main

import (
 "context"
 "fmt"
 u "github.com/rjNemo/underscore"
)

func main() {
 out, err := u.ParallelFilter(context.Background(), []int{1,2,3,4,5}, 3,
  func(ctx context.Context, n int) (bool, error) { return n%2==0, nil },
 )
 fmt.Println(out, err) // [2 4] <nil>
}

Utilities

  • Ternary: conditional expression helper
  • ToPointer: convert values to pointers
  • SortSliceASC / SortSliceDESC: sort slices in ascending or descending order
  • Result, Ok, Err, ToResult: Result type for error handling
  • Tuple: generic tuple type for paired values

Subpackages

  • maps.Keys(m) / maps.Values(m): extract keys or values from maps
  • maps.Map(m, fn): transform map entries

Built With

  • Go - Build fast, reliable, and efficient software at scale

Contributing

Please read CONTRIBUTING.md for details on our code of conduct, and the process for submitting pull requests to us.

Versioning

We use SemVer for versioning. For the versions available, see the tags on this repository.

Authors

  • Ruidy - Initial work - Ruidy

See also the list of contributors who participated in this project.

License

This project is licensed under the MIT License - see the LICENSE.md file for details

Acknowledgments

This project is largely inspired by Underscore.js library. Check out the original project if you don't already know it.