[
  {
    "path": ".github/FUNDING.yml",
    "content": "github: [samber]\n"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE/config.yml",
    "content": "template_chooser:\n  enabled: true\n  default: \"other.md\"\n  choices:\n    - name: \"New Helper\"\n      file: \"new_helper.md\"\n    - name: \"Other Changes\"\n      file: \"other.md\"\n"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE/new_helper.md",
    "content": "\n## Describe your changes\n\n...\n\n## Checklist before requesting a review\n\n- [ ] 👓 I have performed a self-review of my code\n- [ ] 👶 This helper does not already exist\n- [ ] 🧪 This helper is tested\n- [ ] 🏎️ My code limits memory allocation and is fast\n- [ ] 🧞‍♂️ This helper is immutable and my tests prove it\n- [ ] ✍️ I implemented the parallel, iterator and mutable variants\n- [ ] 🔬 An example has been added to lo_example_test.go\n- [ ] ⛹️ An example has been created on https://go.dev/play and added in comments\n- [ ] 📖 My helper has been added to documentation\n  - [ ] in README.md\n  - [ ] in docs/data/*.md\n  - [ ] in docs/static/llms.txt\n\n## Conventions\n\n- Returning `(ok bool)` is often better than `(err error)`\n- `panic(...)` must be limited\n- Helpers should receive variadic arguments when relevent\n- Add variants of your helper when relevant:\n  - Variable number of arguments: `lo.Must0`, `lo.Must1`, `lo.Must2`, ...\n  - Predicate with index: `lo.SliceToMap` vs `lo.SliceToMapI` \n  - With lazy callback: `lo.Ternary` vs `lo.TernaryF`\n  - ...\n"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE/other.md",
    "content": ""
  },
  {
    "path": ".github/dependabot.yml",
    "content": "version: 2\nupdates:\n  - package-ecosystem: github-actions\n    directory: /\n    schedule:\n      interval: monthly\n\n  - package-ecosystem: gomod\n    directory: /\n    schedule:\n      interval: weekly\n\n  - package-ecosystem: npm\n    directory: /docs\n    schedule:\n      interval: monthly\n    ignore:\n      - dependency-name: '*'\n        update-types: [\"version-update:semver-patch\"]\n    groups:\n      docusaurus:\n        patterns:\n          - \"@docusaurus/*\"\n      react:\n        patterns:\n          - \"react\"\n          - \"react-dom\""
  },
  {
    "path": ".github/workflows/doc.yml",
    "content": "name: Documentation\n\non:\n  pull_request:\n    paths:\n      - 'docs/**'\n  push:\n    paths:\n      - 'docs/**'\n\njobs:\n  build-doc:\n    runs-on: ubuntu-latest\n    defaults:\n      run:\n        working-directory: ./docs\n\n    steps:\n      - name: Checkout repository\n        uses: actions/checkout@v6\n\n      - name: Setup Node.js\n        uses: actions/setup-node@v6\n\n      - name: Install dependencies\n        run: npm i\n\n      - name: Build Docusaurus project\n        run: npm run build\n\n\n  # validate-doc:\n  #   runs-on: ubuntu-latest\n  #   defaults:\n  #     run:\n  #       working-directory: ./docs\n\n  #   steps:\n  #     - name: Checkout repository\n  #       uses: actions/checkout@v6\n\n  #     - name: Setup Node.js\n  #       uses: actions/setup-node@v6\n\n  #     - name: Install dependencies\n  #       run: npm i\n\n  #     - name: Run docs helpers checks\n  #       run: |\n  #         node docs/scripts/check-duplicates-in-category.js\n  #         node docs/scripts/check-similar-exists.js\n  #         node docs/scripts/check-filename-matches-frontmatter.js\n  #         node docs/scripts/check-similar-keys-exist-in-directory.js\n  #         node docs/scripts/check-cross-references.js\n\n  #     - name: Sync function signatures\n  #       run: npm run sync:function-signatures\n  #     - name: Commit and push changes\n  #       uses: stefanzweifel/git-auto-commit-action@v5\n  #       with:\n  #         commit_message: 'docs: sync function signatures from source'\n  #         commit_user_name: github-actions[bot]\n  #         commit_user_email: github-actions[bot]@users.noreply.github.com\n  #         file_pattern: docs/data/*.md"
  },
  {
    "path": ".github/workflows/lint.yml",
    "content": "name: Lint\n\non:\n  push:\n    branches:\n      - master\n  pull_request:\n  schedule:\n    - cron: '0 3 * * 1'\n\njobs:\n  analyze:\n    name: lint\n    runs-on: ubuntu-latest\n    strategy:\n      fail-fast: false\n\n    permissions:\n      # required for codeql analysis\n      security-events: write\n\n    steps:\n      - uses: actions/checkout@v6\n      - uses: actions/setup-go@v6\n        with:\n          go-version: 'stable'\n      - name: golangci-lint\n        uses: golangci/golangci-lint-action@v9\n        with:\n          args: --timeout 120s --max-same-issues 50\n\n      - name: Bearer\n        uses: bearer/bearer-action@v2\n        with:\n          skip-path: 'docs/'\n\n      - name: Initialize CodeQL\n        uses: github/codeql-action/init@v4\n        with:\n          languages: go\n      - name: Autobuild\n        uses: github/codeql-action/autobuild@v4\n      - name: Perform CodeQL Analysis\n        uses: github/codeql-action/analyze@v4\n\n      # - name: Install mdsf\n      #   uses: hougesen/mdsf@main\n      # - name: Run mdsf\n      #   run: mdsf --debug --log-level warn docs/\n"
  },
  {
    "path": ".github/workflows/release.yml",
    "content": "name: Release\n\non:\n  workflow_dispatch:\n    inputs:\n      semver:\n        type: string\n        description: 'Semver (eg: v1.2.3)'\n        required: true\n\njobs:\n  release:\n    if: github.triggering_actor == 'samber'\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@v6\n\n    - name: Set up Go\n      uses: actions/setup-go@v6\n      with:\n        go-version-file: 'go.mod'\n\n    - name: Test\n      run: make test\n\n    # remove tests to clean dependencies\n    - name: Remove xxx_test.go files\n      run: rm -rf $(find . -type f -name \"*_test.go\" ! -name \"*_example_test.go\") docs/ benchmark/\n\n    # cleanup test dependencies\n    - name: Cleanup dependencies\n      run: go mod tidy\n\n    - name: List files\n      run: tree -Cfi\n    - name: Write new go.mod into logs\n      run: cat go.mod\n    - name: Write new go.sum into logs\n      run: cat go.sum\n\n    - name: Create tag\n      run: |\n          git config --global user.name '${{ github.triggering_actor }}'\n          git config --global user.email \"${{ github.triggering_actor}}@users.noreply.github.com\"\n\n          git add .\n          git commit --allow-empty -m 'bump ${{ inputs.semver }}'\n          git tag ${{ inputs.semver }}\n          git push origin ${{ inputs.semver }}\n\n    - name: Release\n      uses: softprops/action-gh-release@v2\n      with:\n        name: ${{ inputs.semver }}\n        tag_name: ${{ inputs.semver }}\n"
  },
  {
    "path": ".github/workflows/test.simd.yml",
    "content": "name: Tests (SIMD)\n\non:\n  push:\n    branches:\n      - master\n    paths:\n      - 'exp/simd/**'\n  pull_request:\n    paths:\n      - 'exp/simd/**'\n\nenv:\n  GOEXPERIMENT: simd\n\njobs:\n  test-simd:\n    # GitHub hosted runners run on several architectures.\n    # Using Ubicloud ensures we run on AVX512.\n    runs-on: ubicloud-standard-2\n    strategy:\n      fail-fast: false\n      matrix:\n        go:\n          - \"stable\"\n\n    steps:\n      - uses: actions/checkout@v6\n\n      - name: Set up Go\n        uses: actions/setup-go@v6\n        with:\n          go-version: ${{ matrix.go }}\n\n      - name: Test\n        run: make test\n\n      - name: Benchmark\n        run: |\n          cd exp/simd/\n          GOEXPERIMENT=simd go test -run=^Benchmark -benchmem -bench ./...\n"
  },
  {
    "path": ".github/workflows/test.yml",
    "content": "name: Tests\n\non:\n  push:\n    branches:\n      - master\n  pull_request:\n\njobs:\n  test:\n    runs-on: ubuntu-latest\n    strategy:\n      fail-fast: false\n      matrix:\n        go:\n          - \"1.18\"\n          - \"1.19\"\n          - \"1.20\"\n          - \"1.21\"\n          - \"1.22\"\n          - \"1.23\"\n          - \"1.24\"\n          - \"1.25\"\n          - \"1.26\"\n          - \"stable\"\n\n    steps:\n      - uses: actions/checkout@v6\n\n      - name: Set up Go\n        uses: actions/setup-go@v6\n        with:\n          go-version: ${{ matrix.go }}\n\n      - name: Build\n        run: make build\n\n      - name: Test\n        run: make test\n\n      - name: Test coverage\n        run: make coverage\n        if: matrix.go == 'stable'\n\n      - name: Codecov\n        uses: codecov/codecov-action@v5\n        with:\n          token: ${{ secrets.CODECOV_TOKEN }}\n          flags: unittests\n          verbose: true\n        if: matrix.go == 'stable'\n"
  },
  {
    "path": ".gitignore",
    "content": "\n# Created by https://www.toptal.com/developers/gitignore/api/go\n# Edit at https://www.toptal.com/developers/gitignore?templates=go\n\n### Go ###\n# If you prefer the allow list template instead of the deny list, see community template:\n# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore\n#\n# Binaries for programs and plugins\n*.exe\n*.exe~\n*.dll\n*.so\n*.dylib\n\n# Test binary, built with `go test -c`\n*.test\n\n# Output of the go coverage tool, specifically when used with LiteIDE\n*.out\n\n# Dependency directories (remove the comment below to include it)\n# vendor/\n\n# Go workspace file\ngo.work\n\n### Go Patch ###\n/vendor/\n/Godeps/\n\n# End of https://www.toptal.com/developers/gitignore/api/go\n\ncover.out\ncover.html\n.vscode\n\n.idea/\n"
  },
  {
    "path": ".golangci.yml",
    "content": "version: \"2\"\nrun:\n  concurrency: 4\n  # also lint _test.go files\n  tests: true\n  timeout: 5m\nlinters:\n  enable:\n    - govet\n    - staticcheck\n    - unused\n    - errcheck\n    - gocritic\n    - gocyclo\n    - revive\n    - ineffassign\n    - unconvert\n    - goconst\n    # - depguard\n    - prealloc\n    # - dupl\n    - misspell\n    - bodyclose\n    - sqlclosecheck\n    - nilerr\n    - nestif\n    - forcetypeassert\n    - exhaustive\n    - funlen\n    # - wsl_v5\n    - testifylint\n    - whitespace\n    - perfsprint\n    - nolintlint\n    - godot\n    - thelper\n    - tparallel\n    - paralleltest\n    - predeclared\n    - modernize\n\n  # disable noisy/controversial ones which you might enable later\n  disable:\n    - lll          # line length — handled by gofmt/gofumpt\n\n  settings:\n    dupl:\n      threshold: 20  # lower => stricter (tokens)\n    errcheck:\n      check-type-assertions: true\n    funlen:\n      lines: 120\n      statements: 80\n    goconst:\n      min-len: 2\n      min-occurrences: 3\n    gocyclo:\n      min-complexity: 15 # strict; lower => stricter\n    wsl_v5:\n      allow-first-in-block: true\n      allow-whole-block: false\n      branch-max-lines: 2\n    testifylint:\n      disable:\n        - require-error\n        - float-compare\n\n  exclusions:\n    generated: lax\n    paths:\n      - examples$\n    rules:\n      - linters:\n          - revive\n        text: \"^unused-parameter:\"\n      - linters:\n          - revive\n        text: \"^package-comments:\"\n      - linters:\n          - errcheck\n        text: \"Error return value of `.*\\\\.Body\\\\.Close` is not checked\"\n      # linters disabled in tests\n      - linters:\n          - dupl\n          - goconst\n          - funlen\n        path: \"_test\\\\.go$\"\n\nissues:\n  max-issues-per-linter: 0  # 0 = unlimited (we want ALL issues)\n  max-same-issues: 100\n\nformatters:\n  enable:\n    - gofmt\n    - gofumpt\n  settings:\n    gofumpt:\n      extra-rules: true\n  exclusions:\n    generated: lax\n    paths:\n      - third_party$\n      - builtin$\n      - examples$\n"
  },
  {
    "path": "Dockerfile",
    "content": "\nFROM golang:1.23.1\n\nWORKDIR /go/src/github.com/samber/lo\n\nCOPY Makefile go.* ./\n\nRUN make tools\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2022-2025 Samuel Berthe\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "Makefile",
    "content": "# Only build/test/lint exp/simd when Go version is >= 1.26 (requires goexperiment.simd)\nGO_VERSION := $(shell go version 2>/dev/null | sed -n 's/.*go\\([0-9]*\\)\\.\\([0-9]*\\).*/\\1.\\2/p')\nGO_SIMD_SUPPORT := $(shell ver=\"$(GO_VERSION)\"; [ -n \"$$ver\" ] && [ \"$$(printf '%s\\n1.26\\n' \"$$ver\" | sort -V | tail -1)\" = \"$$ver\" ] && echo yes)\n\nbuild:\n\tgo build -v ./...\n\t@if [ -n \"$(GO_SIMD_SUPPORT)\" ]; then cd ./exp/simd && GOEXPERIMENT=simd go build -v ./; fi\n\ntest:\n\tgo test -race ./...\n\t@if [ -n \"$(GO_SIMD_SUPPORT)\" ]; then cd ./exp/simd && GOEXPERIMENT=simd go test -race ./; fi\nwatch-test:\n\treflex -t 50ms -s -- sh -c 'gotest -race ./...'\n\nbench:\n\tgo test -v -run=^Benchmark -benchmem -count 3 -bench ./...\nwatch-bench:\n\treflex -t 50ms -s -- sh -c 'go test -v -run=^Benchmark -benchmem -count 3 -bench ./...'\n\ncoverage:\n\tgo test -v -coverprofile=cover.out -covermode=atomic ./...\n\tgo tool cover -html=cover.out -o cover.html\n\ntools:\n\tgo install github.com/cespare/reflex@latest\n\tgo install github.com/rakyll/gotest@latest\n\tgo install github.com/psampaz/go-mod-outdated@latest\n\tgo install github.com/jondot/goweight@latest\n\tgo install github.com/golangci/golangci-lint/cmd/golangci-lint@latest\n\tgo get -t -u golang.org/x/tools/cmd/cover\n\tgo install github.com/sonatype-nexus-community/nancy@latest\n\tgo install golang.org/x/perf/cmd/benchstat@latest\n\tgo install github.com/cespare/prettybench@latest\n\tgo mod tidy\n\n\t# brew install hougesen/tap/mdsf\n\nlint:\n\tgolangci-lint run --timeout 60s --max-same-issues 50 ./...\n\t@if [ -n \"$(GO_SIMD_SUPPORT)\" ]; then cd ./exp/simd && golangci-lint run --timeout 60s --max-same-issues 50 ./; fi\n\t# mdsf verify --debug --log-level warn docs/\nlint-fix:\n\tgolangci-lint run --timeout 60s --max-same-issues 50 --fix ./...\n\t@if [ -n \"$(GO_SIMD_SUPPORT)\" ]; then cd ./exp/simd && golangci-lint run --timeout 60s --max-same-issues 50 --fix ./; fi\n\t# mdsf format --debug --log-level warn docs/\n\naudit:\n\tgo list -json -m all | nancy sleuth\n\noutdated:\n\tgo list -u -m -json all | go-mod-outdated -update -direct\n\nweight:\n\tgoweight\n\ndoc:\n\tcd docs && npm install && npm start\n"
  },
  {
    "path": "README.md",
    "content": "\n# lo - Iterate over slices, maps, channels...\n\n[![tag](https://img.shields.io/github/tag/samber/lo.svg)](https://github.com/samber/lo/releases)\n![Go Version](https://img.shields.io/badge/Go-%3E%3D%201.18-%23007d9c)\n[![GoDoc](https://godoc.org/github.com/samber/lo?status.svg)](https://pkg.go.dev/github.com/samber/lo)\n![Build Status](https://github.com/samber/lo/actions/workflows/test.yml/badge.svg)\n[![Go report](https://goreportcard.com/badge/github.com/samber/lo)](https://goreportcard.com/report/github.com/samber/lo)\n[![Coverage](https://img.shields.io/codecov/c/github/samber/lo)](https://codecov.io/gh/samber/lo)\n[![Contributors](https://img.shields.io/github/contributors/samber/lo)](https://github.com/samber/lo/graphs/contributors)\n[![License](https://img.shields.io/github/license/samber/lo)](./LICENSE)\n\n✨ **`samber/lo` is a Lodash-style Go library based on Go 1.18+ Generics.**\n\nA utility library based on Go 1.18+ generics that makes it easier to work with slices, maps, strings, channels, and functions. It provides dozens of handy methods to simplify common coding tasks and improve code readability. It may look like [Lodash](https://github.com/lodash/lodash) in some aspects.\n\n5 to 10 helpers may overlap with those from the Go standard library, in packages `slices` and `maps`. I feel this library is legitimate and offers many more valuable abstractions.\n\n**See also:**\n\n- [samber/ro](https://github.com/samber/ro): Reactive Programming for Go: declarative and composable API for event-driven applications\n- [samber/do](https://github.com/samber/do): A dependency injection toolkit based on Go 1.18+ Generics\n- [samber/mo](https://github.com/samber/mo): Monads based on Go 1.18+ Generics (Option, Result, Either...)\n\nWhat makes it different from **samber/ro**?\n- lo: synchronous helpers across finite sequences (maps, slices...)\n- ro: processing of infinite data streams for event-driven scenarios\n\n----\n\n<div align=\"center\">\n  <sup><b>💖 Sponsored by:</b></sup>\n  <br>\n  <a href=\"https://www.dbos.dev/?utm_campaign=gh-smbr\">\n    <div>\n\t  <img width=\"200\" alt=\"dbos\" src=\"https://github.com/user-attachments/assets/d583cb62-7735-4d3c-beb7-e6ef1a5faf49\" />\n    </div>\n    <div>\n      DBOS - Durable workflow orchestration library for Go\n    </div>\n  </a>\n</div>\n\n----\n\n**Why this name?**\n\nI wanted a **short name**, similar to \"Lodash\", and no Go package uses this name.\n\n![lo](docs/static/img/logo-full.png)\n\n## 🚀 Install\n\n```sh\ngo get github.com/samber/lo@v1\n```\n\nThis library is v1 and follows SemVer strictly.\n\nNo breaking changes will be made to exported APIs before v2.0.0, except for experimental packages under `exp/`.\n\nThis library has no dependencies outside the Go standard library.\n\n## 💡 Usage\n\nYou can import `lo` using:\n\n```go\nimport (\n    \"github.com/samber/lo\"\n    lop \"github.com/samber/lo/parallel\"\n    lom \"github.com/samber/lo/mutable\"\n    loi \"github.com/samber/lo/it\"\n)\n```\n\nThen use one of the helpers below:\n\n```go\nnames := lo.Uniq([]string{\"Samuel\", \"John\", \"Samuel\"})\n// []string{\"Samuel\", \"John\"}\n```\n\n### Tips for lazy developers\n\nI cannot recommend it, but in case you are too lazy for repeating `lo.` everywhere, you can import the entire library into the namespace.\n\n```go\nimport (\n    . \"github.com/samber/lo\"\n)\n```\n\nI take no responsibility for this junk. 😁 💩\n\n## 🤠 Spec\n\nGoDoc: [godoc.org/github.com/samber/lo](https://godoc.org/github.com/samber/lo)\n\nDocumentation: [lo.samber.dev](https://lo.samber.dev/docs/about)\n\nSupported helpers for slices:\n\n- [Filter](#filter)\n- [Map](#map)\n- [UniqMap](#uniqmap)\n- [FilterMap](#filtermap)\n- [FlatMap](#flatmap)\n- [Reduce](#reduce)\n- [ReduceRight](#reduceright)\n- [ForEach](#foreach)\n- [ForEachWhile](#foreachwhile)\n- [Times](#times)\n- [Uniq](#uniq)\n- [UniqBy](#uniqby)\n- [GroupBy](#groupby)\n- [GroupByMap](#groupbymap)\n- [Chunk](#chunk)\n- [Window](#window)\n- [Sliding](#sliding)\n- [PartitionBy](#partitionby)\n- [Flatten](#flatten)\n- [Concat](#concat)\n- [Interleave](#interleave)\n- [Shuffle](#shuffle)\n- [Reverse](#reverse)\n- [Fill](#fill)\n- [Repeat](#repeat)\n- [RepeatBy](#repeatby)\n- [KeyBy](#keyby)\n- [SliceToMap / Associate](#slicetomap-alias-associate)\n- [FilterSliceToMap](#filterslicetomap)\n- [Keyify](#keyify)\n- [Take](#take)\n- [TakeWhile](#takewhile)\n- [TakeFilter](#takefilter)\n- [Drop](#drop)\n- [DropRight](#dropright)\n- [DropWhile](#dropwhile)\n- [DropRightWhile](#droprightwhile)\n- [DropByIndex](#DropByIndex)\n- [Reject](#reject)\n- [RejectMap](#rejectmap)\n- [FilterReject](#filterreject)\n- [Count](#count)\n- [CountBy](#countby)\n- [CountValues](#countvalues)\n- [CountValuesBy](#countvaluesby)\n- [Subset](#subset)\n- [Slice](#slice)\n- [Replace](#replace)\n- [ReplaceAll](#replaceall)\n- [Clone](#clone)\n- [Compact](#compact)\n- [IsSorted](#issorted)\n- [IsSortedBy](#issortedby)\n- [Splice](#Splice)\n- [Cut](#Cut)\n- [CutPrefix](#CutPrefix)\n- [CutSuffix](#CutSuffix)\n- [Trim](#Trim)\n- [TrimLeft](#TrimLeft)\n- [TrimPrefix](#TrimPrefix)\n- [TrimRight](#TrimRight)\n- [TrimSuffix](#TrimSuffix)\n\nSupported helpers for maps:\n\n- [Keys](#keys)\n- [UniqKeys](#uniqkeys)\n- [HasKey](#haskey)\n- [ValueOr](#valueor)\n- [Values](#values)\n- [UniqValues](#uniqvalues)\n- [PickBy](#pickby)\n- [PickByKeys](#pickbykeys)\n- [PickByValues](#pickbyvalues)\n- [OmitBy](#omitby)\n- [OmitByKeys](#omitbykeys)\n- [OmitByValues](#omitbyvalues)\n- [Entries / ToPairs](#entries-alias-topairs)\n- [FromEntries / FromPairs](#fromentries-alias-frompairs)\n- [Invert](#invert)\n- [Assign (merge of maps)](#assign)\n- [ChunkEntries](#chunkentries)\n- [MapKeys](#mapkeys)\n- [MapValues](#mapvalues)\n- [MapEntries](#mapentries)\n- [MapToSlice](#maptoslice)\n- [FilterMapToSlice](#FilterMapToSlice)\n- [FilterKeys](#FilterKeys)\n- [FilterValues](#FilterValues)\n\nSupported math helpers:\n\n- [Range / RangeFrom / RangeWithSteps](#range--rangefrom--rangewithsteps)\n- [Clamp](#clamp)\n- [Sum](#sum)\n- [SumBy](#sumby)\n- [Product](#product)\n- [ProductBy](#productby)\n- [Mean](#mean)\n- [MeanBy](#meanby)\n- [Mode](#mode)\n\nSupported helpers for strings:\n\n- [RandomString](#randomstring)\n- [Substring](#substring)\n- [ChunkString](#chunkstring)\n- [RuneLength](#runelength)\n- [PascalCase](#pascalcase)\n- [CamelCase](#camelcase)\n- [KebabCase](#kebabcase)\n- [SnakeCase](#snakecase)\n- [Words](#words)\n- [Capitalize](#capitalize)\n- [Ellipsis](#ellipsis)\n\nSupported helpers for tuples:\n\n- [T2 -> T9](#t2---t9)\n- [Unpack2 -> Unpack9](#unpack2---unpack9)\n- [Zip2 -> Zip9](#zip2---zip9)\n- [ZipBy2 -> ZipBy9](#zipby2---zipby9)\n- [Unzip2 -> Unzip9](#unzip2---unzip9)\n- [UnzipBy2 -> UnzipBy9](#unzipby2---unzipby9)\n- [CrossJoin2 -> CrossJoin2](#crossjoin2---crossjoin9)\n- [CrossJoinBy2 -> CrossJoinBy2](#crossjoinby2---crossjoinby9)\n\nSupported helpers for time and duration:\n\n- [Duration](#duration)\n- [Duration0 -> Duration10](#duration0---duration10)\n\nSupported helpers for channels:\n\n- [ChannelDispatcher](#channeldispatcher)\n- [SliceToChannel](#slicetochannel)\n- [ChannelToSlice](#channeltoslice)\n- [Generator](#generator)\n- [Buffer](#buffer)\n- [BufferWithContext](#bufferwithcontext)\n- [BufferWithTimeout](#bufferwithtimeout)\n- [FanIn](#fanin)\n- [FanOut](#fanout)\n\nSupported intersection helpers:\n\n- [Contains](#contains)\n- [ContainsBy](#containsby)\n- [Every](#every)\n- [EveryBy](#everyby)\n- [Some](#some)\n- [SomeBy](#someby)\n- [None](#none)\n- [NoneBy](#noneby)\n- [Intersect](#intersect)\n- [IntersectBy](#intersectby)\n- [Difference](#difference)\n- [Union](#union)\n- [Without](#without)\n- [WithoutBy](#withoutby)\n- [WithoutEmpty](#withoutempty)\n- [WithoutNth](#withoutnth)\n- [ElementsMatch](#ElementsMatch)\n- [ElementsMatchBy](#ElementsMatchBy)\n\nSupported search helpers:\n\n- [IndexOf](#indexof)\n- [LastIndexOf](#lastindexof)\n- [HasPrefix](#hasprefix)\n- [HasSuffix](#hassuffix)\n- [Find](#find)\n- [FindIndexOf](#findindexof)\n- [FindLastIndexOf](#findlastindexof)\n- [FindOrElse](#findorelse)\n- [FindKey](#findkey)\n- [FindKeyBy](#findkeyby)\n- [FindUniques](#finduniques)\n- [FindUniquesBy](#finduniquesby)\n- [FindDuplicates](#findduplicates)\n- [FindDuplicatesBy](#findduplicatesby)\n- [Min](#min)\n- [MinIndex](#minindex)\n- [MinBy](#minby)\n- [MinIndexBy](#minindexby)\n- [Earliest](#earliest)\n- [EarliestBy](#earliestby)\n- [Max](#max)\n- [MaxIndex](#maxindex)\n- [MaxBy](#maxby)\n- [MaxIndexBy](#maxindexby)\n- [Latest](#latest)\n- [LatestBy](#latestby)\n- [First](#first)\n- [FirstOrEmpty](#FirstOrEmpty)\n- [FirstOr](#FirstOr)\n- [Last](#last)\n- [LastOrEmpty](#LastOrEmpty)\n- [LastOr](#LastOr)\n- [Nth](#nth)\n- [NthOr](#nthor)\n- [NthOrEmpty](#nthorempty)\n- [Sample](#sample)\n- [SampleBy](#sampleby)\n- [Samples](#samples)\n- [SamplesBy](#samplesby)\n\nConditional helpers:\n\n- [Ternary](#ternary)\n- [TernaryF](#ternaryf)\n- [If / ElseIf / Else](#if--elseif--else)\n- [Switch / Case / Default](#switch--case--default)\n\nType manipulation helpers:\n\n- [IsNil](#isnil)\n- [IsNotNil](#isnotnil)\n- [ToPtr](#toptr)\n- [Nil](#nil)\n- [EmptyableToPtr](#emptyabletoptr)\n- [FromPtr](#fromptr)\n- [FromPtrOr](#fromptror)\n- [ToSlicePtr](#tosliceptr)\n- [FromSlicePtr](#fromsliceptr)\n- [FromSlicePtrOr](#fromsliceptror)\n- [ToAnySlice](#toanyslice)\n- [FromAnySlice](#fromanyslice)\n- [Empty](#empty)\n- [IsEmpty](#isempty)\n- [IsNotEmpty](#isnotempty)\n- [Coalesce](#coalesce)\n- [CoalesceOrEmpty](#coalesceorempty)\n- [CoalesceSlice](#coalesceslice)\n- [CoalesceSliceOrEmpty](#coalescesliceorempty)\n- [CoalesceMap](#coalescemap)\n- [CoalesceMapOrEmpty](#coalescemaporempty)\n\nFunction helpers:\n\n- [Partial](#partial)\n- [Partial2 -> Partial5](#partial2---partial5)\n\nConcurrency helpers:\n\n- [Attempt](#attempt)\n- [AttemptWhile](#attemptwhile)\n- [AttemptWithDelay](#attemptwithdelay)\n- [AttemptWhileWithDelay](#attemptwhilewithdelay)\n- [Debounce](#debounce)\n- [DebounceBy](#debounceby)\n- [Throttle](#throttle)\n- [ThrottleWithCount](#throttle)\n- [ThrottleBy](#throttle)\n- [ThrottleByWithCount](#throttle)\n- [Synchronize](#synchronize)\n- [Async](#async)\n- [Async{0->6}](#async0-6)\n- [Transaction](#transaction)\n- [WaitFor](#waitfor)\n- [WaitForWithContext](#waitforwithcontext)\n\nError handling:\n\n- [Validate](#validate)\n- [Must](#must)\n- [Try](#try)\n- [Try1 -> Try6](#try0-6)\n- [TryOr](#tryor)\n- [TryOr1 -> TryOr6](#tryor0-6)\n- [TryCatch](#trycatch)\n- [TryWithErrorValue](#trywitherrorvalue)\n- [TryCatchWithErrorValue](#trycatchwitherrorvalue)\n- [ErrorsAs](#errorsas)\n- [Assert](#assert)\n- [Assertf](#assertf)\n\nConstraints:\n\n- Clonable\n\n### Filter\n\nIterates over a collection and returns a slice of all the elements the predicate function returns `true` for.\n\n```go\neven := lo.Filter([]int{1, 2, 3, 4}, func(x int, index int) bool {\n    return x%2 == 0\n})\n// []int{2, 4}\n```\n\n```go\n// Use FilterErr when the predicate can return an error\neven, err := lo.FilterErr([]int{1, 2, 3, 4}, func(x int, _ int) (bool, error) {\n    if x == 3 {\n        return false, fmt.Errorf(\"number 3 is not allowed\")\n    }\n    return x%2 == 0, nil\n})\n// []int(nil), error(\"number 3 is not allowed\")\n```\n\n[[play](https://go.dev/play/p/Apjg3WeSi7K)]\n\nMutable: like `lo.Filter()`, but the slice is updated in place.\n\n```go\nimport lom \"github.com/samber/lo/mutable\"\n\nlist := []int{1, 2, 3, 4}\nnewList := lom.Filter(list, func(x int) bool {\n    return x%2 == 0\n})\n\nlist\n// []int{2, 4, 3, 4}\n\nnewList\n// []int{2, 4}\n```\n\n### Map\n\nManipulates a slice of one type and transforms it into a slice of another type:\n\n```go\nimport \"github.com/samber/lo\"\n\nlo.Map([]int64{1, 2, 3, 4}, func(x int64, index int) string {\n    return strconv.FormatInt(x, 10)\n})\n// []string{\"1\", \"2\", \"3\", \"4\"}\n```\n\n```go\n// Use MapErr when the transform function can return an error\nresult, err := lo.MapErr([]int{1, 2, 3, 4}, func(x int, _ int) (string, error) {\n    if x == 3 {\n        return \"\", fmt.Errorf(\"number 3 is not allowed\")\n    }\n    return strconv.Itoa(x), nil\n})\n// []string(nil), error(\"number 3 is not allowed\")\n```\n\n[[play](https://go.dev/play/p/OkPcYAhBo0D)]\n\nParallel processing: like `lo.Map()`, but the transform function is called in a goroutine. Results are returned in the same order.\n\n```go\nimport lop \"github.com/samber/lo/parallel\"\n\nlop.Map([]int64{1, 2, 3, 4}, func(x int64, _ int) string {\n    return strconv.FormatInt(x, 10)\n})\n// []string{\"1\", \"2\", \"3\", \"4\"}\n```\n\n[[play](https://go.dev/play/p/sCJaB3quRMC)]\n\nMutable: like `lo.Map()`, but the slice is updated in place.\n\n```go\nimport lom \"github.com/samber/lo/mutable\"\n\nlist := []int{1, 2, 3, 4}\nlom.Map(list, func(x int) int {\n    return x*2\n})\n// []int{2, 4, 6, 8}\n```\n\n[[play](https://go.dev/play/p/0jY3Z0B7O_5)]\n\n### UniqMap\n\nManipulates a slice and transforms it to a slice of another type with unique values.\n\n```go\ntype User struct {\n    Name string\n    Age  int\n}\nusers := []User{{Name: \"Alex\", Age: 10}, {Name: \"Alex\", Age: 12}, {Name: \"Bob\", Age: 11}, {Name: \"Alice\", Age: 20}}\n\nnames := lo.UniqMap(users, func(u User, index int) string {\n    return u.Name\n})\n// []string{\"Alex\", \"Bob\", \"Alice\"}\n```\n\n[[play](https://go.dev/play/p/fygzLBhvUdB)]\n\n### FilterMap\n\nReturns a slice obtained after both filtering and mapping using the given callback function.\n\nThe callback function should return two values: the result of the mapping operation and whether the result element should be included or not.\n\n```go\nmatching := lo.FilterMap([]string{\"cpu\", \"gpu\", \"mouse\", \"keyboard\"}, func(x string, _ int) (string, bool) {\n    if strings.HasSuffix(x, \"pu\") {\n        return \"xpu\", true\n    }\n    return \"\", false\n})\n// []string{\"xpu\", \"xpu\"}\n```\n\n[[play](https://go.dev/play/p/-AuYXfy7opz)]\n\n### FlatMap\n\nManipulates a slice and transforms and flattens it to a slice of another type. The transform function can either return a slice or a `nil`, and in the `nil` case no value is added to the final slice.\n\n```go\nlo.FlatMap([]int64{0, 1, 2}, func(x int64, _ int) []string {\n    return []string{\n        strconv.FormatInt(x, 10),\n        strconv.FormatInt(x, 10),\n    }\n})\n// []string{\"0\", \"0\", \"1\", \"1\", \"2\", \"2\"}\n```\n\n```go\n// Use FlatMapErr when the transform function can return an error\nresult, err := lo.FlatMapErr([]int64{0, 1, 2, 3}, func(x int64, _ int) ([]string, error) {\n    if x == 2 {\n        return nil, fmt.Errorf(\"number 2 is not allowed\")\n    }\n    return []string{strconv.FormatInt(x, 10), strconv.FormatInt(x, 10)}, nil\n})\n// []string(nil), error(\"number 2 is not allowed\")\n```\n\n[[play](https://go.dev/play/p/YSoYmQTA8-U)]\n\n### Reduce\n\nReduces a collection to a single value. The value is calculated by accumulating the result of running each element in the collection through an accumulator function. Each successive invocation is supplied with the return value returned by the previous call.\n\n```go\nsum := lo.Reduce([]int{1, 2, 3, 4}, func(agg int, item int, _ int) int {\n    return agg + item\n}, 0)\n// 10\n```\n\n```go\n// Use ReduceErr when the accumulator function can return an error\nresult, err := lo.ReduceErr([]int{1, 2, 3, 4}, func(agg int, item int, _ int) (int, error) {\n    if item == 3 {\n        return 0, fmt.Errorf(\"number 3 is not allowed\")\n    }\n    return agg + item, nil\n}, 0)\n// 0, error(\"number 3 is not allowed\")\n```\n\n[[play](https://go.dev/play/p/R4UHXZNaaUG)]\n\n### ReduceRight\n\nLike `lo.Reduce` except that it iterates over elements of collection from right to left.\n\n```go\nresult := lo.ReduceRight([][]int{{0, 1}, {2, 3}, {4, 5}}, func(agg []int, item []int, _ int) []int {\n    return append(agg, item...)\n}, []int{})\n// []int{4, 5, 2, 3, 0, 1}\n```\n\n```go\n// Use ReduceRightErr when the accumulator function can return an error\nresult, err := lo.ReduceRightErr([]int{1, 2, 3, 4}, func(agg int, item int, _ int) (int, error) {\n    if item == 2 {\n        return 0, fmt.Errorf(\"number 2 is not allowed\")\n    }\n    return agg + item, nil\n}, 0)\n// 0, error(\"number 2 is not allowed\")\n```\n\n[[play](https://go.dev/play/p/Fq3W70l7wXF)]\n\n### ForEach\n\nIterates over elements of a collection and invokes the function over each element.\n\n```go\nimport \"github.com/samber/lo\"\n\nlo.ForEach([]string{\"hello\", \"world\"}, func(x string, _ int) {\n    println(x)\n})\n// prints \"hello\\nworld\\n\"\n```\n\n[[play](https://go.dev/play/p/oofyiUPRf8t)]\n\nParallel processing: like `lo.ForEach()`, but the callback is called as a goroutine.\n\n```go\nimport lop \"github.com/samber/lo/parallel\"\n\nlop.ForEach([]string{\"hello\", \"world\"}, func(x string, _ int) {\n    println(x)\n})\n// prints \"hello\\nworld\\n\" or \"world\\nhello\\n\"\n```\n\n### ForEachWhile\n\nIterates over collection elements and invokes iteratee for each element collection return value decide to continue or break, like do while().\n\n```go\nlist := []int64{1, 2, -42, 4}\n\nlo.ForEachWhile(list, func(x int64, _ int) bool {\n\tif x < 0 {\n\t\treturn false\n\t}\n\tfmt.Println(x)\n\treturn true\n})\n// 1\n// 2\n```\n\n[[play](https://go.dev/play/p/QnLGt35tnow)]\n\n### Times\n\nTimes invokes the iteratee n times, returning a slice of the results of each invocation. The iteratee is invoked with index as argument.\n\n```go\nimport \"github.com/samber/lo\"\n\nlo.Times(3, func(i int) string {\n    return strconv.FormatInt(int64(i), 10)\n})\n// []string{\"0\", \"1\", \"2\"}\n```\n\n[[play](https://go.dev/play/p/vgQj3Glr6lT)]\n\nParallel processing: like `lo.Times()`, but callback is called in goroutine.\n\n```go\nimport lop \"github.com/samber/lo/parallel\"\n\nlop.Times(3, func(i int) string {\n    return strconv.FormatInt(int64(i), 10)\n})\n// []string{\"0\", \"1\", \"2\"}\n```\n\n### Uniq\n\nReturns a duplicate-free version of a slice, in which only the first occurrence of each element is kept. The order of result values is determined by the order they occur in the slice.\n\n```go\nuniqValues := lo.Uniq([]int{1, 2, 2, 1})\n// []int{1, 2}\n```\n\n[[play](https://go.dev/play/p/DTzbeXZ6iEN)]\n\n### UniqBy\n\nReturns a duplicate-free version of a slice, in which only the first occurrence of each element is kept. The order of result values is determined by the order they occur in the slice. It accepts `iteratee` which is invoked for each element in the slice to generate the criterion by which uniqueness is computed.\n\n```go\nuniqValues := lo.UniqBy([]int{0, 1, 2, 3, 4, 5}, func(i int) int {\n    return i%3\n})\n// []int{0, 1, 2}\n```\n\n```go\n// Use UniqByErr when the iteratee function can return an error\nresult, err := lo.UniqByErr([]int{0, 1, 2, 3, 4, 5}, func(i int) (int, error) {\n    if i == 3 {\n        return 0, fmt.Errorf(\"number 3 is not allowed\")\n    }\n    return i % 3, nil\n})\n// []int(nil), error(\"number 3 is not allowed\")\n```\n\n[[play](https://go.dev/play/p/g42Z3QSb53u)]\n\n### GroupBy\n\nReturns an object composed of keys generated from the results of running each element of collection through iteratee.\n\n```go\nimport lo \"github.com/samber/lo\"\n\ngroups := lo.GroupBy([]int{0, 1, 2, 3, 4, 5}, func(i int) int {\n    return i%3\n})\n// map[int][]int{0: []int{0, 3}, 1: []int{1, 4}, 2: []int{2, 5}}\n```\n\n```go\n// Use GroupByErr when the iteratee function can return an error\nresult, err := lo.GroupByErr([]int{0, 1, 2, 3, 4, 5}, func(i int) (int, error) {\n    if i == 3 {\n        return 0, fmt.Errorf(\"number 3 is not allowed\")\n    }\n    return i % 3, nil\n})\n// map[int][]int(nil), error(\"number 3 is not allowed\")\n```\n\n[[play](https://go.dev/play/p/XnQBd_v6brd)]\n\nParallel processing: like `lo.GroupBy()`, but callback is called in goroutine.\n\n```go\nimport lop \"github.com/samber/lo/parallel\"\n\nlop.GroupBy([]int{0, 1, 2, 3, 4, 5}, func(i int) int {\n    return i%3\n})\n// map[int][]int{0: []int{0, 3}, 1: []int{1, 4}, 2: []int{2, 5}}\n```\n\n### GroupByMap\n\nReturns an object composed of keys generated from the results of running each element of collection through iteratee.\n\n```go\nimport lo \"github.com/samber/lo\"\n\ngroups := lo.GroupByMap([]int{0, 1, 2, 3, 4, 5}, func(i int) (int, int) {\n    return i%3, i*2\n})\n// map[int][]int{0: []int{0, 6}, 1: []int{2, 8}, 2: []int{4, 10}}\n```\n\n```go\n// Use GroupByMapErr when the transform function can return an error\nresult, err := lo.GroupByMapErr([]int{0, 1, 2, 3, 4, 5}, func(i int) (int, int, error) {\n    if i == 3 {\n        return 0, 0, fmt.Errorf(\"number 3 is not allowed\")\n    }\n    return i % 3, i * 2, nil\n})\n// map[int][]int(nil), error(\"number 3 is not allowed\")\n```\n\n[[play](https://go.dev/play/p/iMeruQ3_W80)]\n\n### Chunk\n\nReturns a slice of elements split into groups of length size. If the slice can't be split evenly, the final chunk will be the remaining elements.\n\n```go\nlo.Chunk([]int{0, 1, 2, 3, 4, 5}, 2)\n// [][]int{{0, 1}, {2, 3}, {4, 5}}\n\nlo.Chunk([]int{0, 1, 2, 3, 4, 5, 6}, 2)\n// [][]int{{0, 1}, {2, 3}, {4, 5}, {6}}\n\nlo.Chunk([]int{}, 2)\n// [][]int{}\n\nlo.Chunk([]int{0}, 2)\n// [][]int{{0}}\n```\n\n[[play](https://go.dev/play/p/kEMkFbdu85g)]\n\n### Window\n\nCreates a slice of sliding windows of a given size. Each window shares size-1 elements with the previous one. This is equivalent to `Sliding(collection, size, 1)`.\n\n```go\nlo.Window([]int{1, 2, 3, 4, 5}, 3)\n// [][]int{{1, 2, 3}, {2, 3, 4}, {3, 4, 5}}\n\nlo.Window([]float64{20, 22, 21, 23, 24}, 3)\n// [][]float64{{20, 22, 21}, {22, 21, 23}, {21, 23, 24}}\n```\n\n### Sliding\n\nCreates a slice of sliding windows of a given size with a given step. If step is equal to size, windows have no common elements (similar to Chunk). If step is less than size, windows share common elements.\n\n```go\n// Windows with shared elements (step < size)\nlo.Sliding([]int{1, 2, 3, 4, 5, 6}, 3, 1)\n// [][]int{{1, 2, 3}, {2, 3, 4}, {3, 4, 5}, {4, 5, 6}}\n\n// Windows with no shared elements (step == size, like Chunk)\nlo.Sliding([]int{1, 2, 3, 4, 5, 6}, 3, 3)\n// [][]int{{1, 2, 3}, {4, 5, 6}}\n\n// Step > size (skipping elements)\nlo.Sliding([]int{1, 2, 3, 4, 5, 6, 7, 8}, 2, 3)\n// [][]int{{1, 2}, {4, 5}, {7, 8}}\n```\n\n### PartitionBy\n\nReturns a slice of elements split into groups. The order of grouped values is determined by the order they occur in collection. The grouping is generated from the results of running each element of collection through iteratee.\n\n```go\nimport lo \"github.com/samber/lo\"\n\npartitions := lo.PartitionBy([]int{-2, -1, 0, 1, 2, 3, 4, 5}, func(x int) string {\n    if x < 0 {\n        return \"negative\"\n    } else if x%2 == 0 {\n        return \"even\"\n    }\n    return \"odd\"\n})\n// [][]int{{-2, -1}, {0, 2, 4}, {1, 3, 5}}\n```\n\n```go\n// Use PartitionByErr when the iteratee function can return an error\nresult, err := lo.PartitionByErr([]int{-2, -1, 0, 1, 2}, func(x int) (string, error) {\n    if x == 0 {\n        return \"\", fmt.Errorf(\"zero is not allowed\")\n    }\n    if x < 0 {\n        return \"negative\", nil\n    } else if x%2 == 0 {\n        return \"even\", nil\n    }\n    return \"odd\", nil\n})\n// [][]int(nil), error(\"zero is not allowed\")\n```\n\n[[play](https://go.dev/play/p/NfQ_nGjkgXW)]\n\nParallel processing: like `lo.PartitionBy()`, but callback is called in goroutine. Results are returned in the same order.\n\n```go\nimport lop \"github.com/samber/lo/parallel\"\n\npartitions := lop.PartitionBy([]int{-2, -1, 0, 1, 2, 3, 4, 5}, func(x int) string {\n    if x < 0 {\n        return \"negative\"\n    } else if x%2 == 0 {\n        return \"even\"\n    }\n    return \"odd\"\n})\n// [][]int{{-2, -1}, {0, 2, 4}, {1, 3, 5}}\n```\n\n### Flatten\n\nReturns a slice a single level deep.\n\n```go\nflat := lo.Flatten([][]int{{0, 1}, {2, 3, 4, 5}})\n// []int{0, 1, 2, 3, 4, 5}\n```\n\n[[play](https://go.dev/play/p/rbp9ORaMpjw)]\n\n### Concat\n\nReturns a new slice containing all the elements in collections. Concat conserves the order of the elements.\n\n```go\nslice := lo.Concat([]int{1, 2}, []int{3, 4})\n// []int{1, 2, 3, 4}\n\nslice := lo.Concat(nil, []int{1, 2}, nil, []int{3, 4}, nil)\n// []int{1, 2, 3, 4}\n\nslice := lo.Concat[int]()\n// []int{}\n```\n### Interleave\n\nRound-robin alternating input slices and sequentially appending value at index into result.\n\n```go\ninterleaved := lo.Interleave([]int{1, 4, 7}, []int{2, 5, 8}, []int{3, 6, 9})\n// []int{1, 2, 3, 4, 5, 6, 7, 8, 9}\n\ninterleaved := lo.Interleave([]int{1}, []int{2, 5, 8}, []int{3, 6}, []int{4, 7, 9, 10})\n// []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}\n```\n\n[[play](https://go.dev/play/p/-RJkTLQEDVt)]\n\n### Shuffle\n\nReturns a slice of shuffled values. Uses the Fisher-Yates shuffle algorithm.\n\n⚠️ This helper is **mutable**.\n\n```go\nimport lom \"github.com/samber/lo/mutable\"\n\nlist := []int{0, 1, 2, 3, 4, 5}\nlom.Shuffle(list)\n\nlist\n// []int{1, 4, 0, 3, 5, 2}\n```\n\n[[play](https://go.dev/play/p/2xb3WdLjeSJ)]\n\n### Reverse\n\nReverses a slice so that the first element becomes the last, the second element becomes the second to last, and so on.\n\n⚠️ This helper is **mutable**.\n\n```go\nimport lom \"github.com/samber/lo/mutable\"\n\nlist := []int{0, 1, 2, 3, 4, 5}\nlom.Reverse(list)\n\nlist\n// []int{5, 4, 3, 2, 1, 0}\n```\n\n[[play](https://go.dev/play/p/O-M5pmCRgzV)]\n\n### Fill\n\nFills elements of a slice with `initial` value.\n\n```go\ntype foo struct {\n  bar string\n}\n\nfunc (f foo) Clone() foo {\n  return foo{f.bar}\n}\n\ninitializedSlice := lo.Fill([]foo{foo{\"a\"}, foo{\"a\"}}, foo{\"b\"})\n// []foo{foo{\"b\"}, foo{\"b\"}}\n```\n\n[[play](https://go.dev/play/p/VwR34GzqEub)]\n\n### Repeat\n\nBuilds a slice with N copies of initial value.\n\n```go\ntype foo struct {\n  bar string\n}\n\nfunc (f foo) Clone() foo {\n  return foo{f.bar}\n}\n\nslice := lo.Repeat(2, foo{\"a\"})\n// []foo{foo{\"a\"}, foo{\"a\"}}\n```\n\n[[play](https://go.dev/play/p/g3uHXbmc3b6)]\n\n### RepeatBy\n\nBuilds a slice with values returned by N calls of callback.\n\n```go\nslice := lo.RepeatBy(0, func (i int) string {\n    return strconv.FormatInt(int64(math.Pow(float64(i), 2)), 10)\n})\n// []string{}\n\nslice := lo.RepeatBy(5, func(i int) string {\n    return strconv.FormatInt(int64(math.Pow(float64(i), 2)), 10)\n})\n// []string{\"0\", \"1\", \"4\", \"9\", \"16\"}\n```\n\n[[play](https://go.dev/play/p/ozZLCtX_hNU)]\n\nWith error handling:\n\n```go\nslice, err := lo.RepeatByErr(5, func(i int) (string, error) {\n    if i == 3 {\n        return \"\", fmt.Errorf(\"index 3 is not allowed\")\n    }\n    return fmt.Sprintf(\"item-%d\", i), nil\n})\n// []string(nil), error(\"index 3 is not allowed\")\n```\n\n### KeyBy\n\nTransforms a slice or a slice of structs to a map based on a pivot callback.\n\n```go\nm := lo.KeyBy([]string{\"a\", \"aa\", \"aaa\"}, func(str string) int {\n    return len(str)\n})\n// map[int]string{1: \"a\", 2: \"aa\", 3: \"aaa\"}\n\ntype Character struct {\n  dir  string\n  code int\n}\ncharacters := []Character{\n    {dir: \"left\", code: 97},\n    {dir: \"right\", code: 100},\n}\nresult := lo.KeyBy(characters, func(char Character) string {\n    return string(rune(char.code))\n})\n//map[a:{dir:left code:97} d:{dir:right code:100}]\n```\n\n```go\nresult, err := lo.KeyByErr([]string{\"a\", \"aa\", \"aaa\", \"\"}, func(str string) (int, error) {\n    if str == \"\" {\n        return 0, fmt.Errorf(\"empty string not allowed\")\n    }\n    return len(str), nil\n})\n// map[int]string(nil), error(\"empty string not allowed\")\n```\n\n[[play](https://go.dev/play/p/mdaClUAT-zZ)]\n\n### SliceToMap (alias: Associate)\n\nReturns a map containing key-value pairs provided by transform function applied to elements of the given slice.\nIf any of two pairs have the same key the last one gets added to the map.\n\nThe order of keys in returned map is not specified and is not guaranteed to be the same from the original slice.\n\n```go\nin := []*foo{{baz: \"apple\", bar: 1}, {baz: \"banana\", bar: 2}}\n\naMap := lo.SliceToMap(in, func (f *foo) (string, int) {\n    return f.baz, f.bar\n})\n// map[string][int]{ \"apple\":1, \"banana\":2 }\n```\n\n[[play](https://go.dev/play/p/WHa2CfMO3Lr)]\n\n### FilterSliceToMap\n\nReturns a map containing key-value pairs provided by transform function applied to elements of the given slice.\n\nIf any of two pairs have the same key the last one gets added to the map.\n\nThe order of keys in returned map is not specified and is not guaranteed to be the same from the original slice.\n\nThe third return value of the transform function is a boolean that indicates whether the key-value pair should be included in the map.\n\n```go\nlist := []string{\"a\", \"aa\", \"aaa\"}\n\nresult := lo.FilterSliceToMap(list, func(str string) (string, int, bool) {\n    return str, len(str), len(str) > 1\n})\n// map[string][int]{\"aa\":2 \"aaa\":3}\n```\n\n[[play](https://go.dev/play/p/2z0rDz2ZSGU)]\n\n### Keyify\n\nReturns a map with each unique element of the slice as a key.\n\n```go\nset := lo.Keyify([]int{1, 1, 2, 3, 4})\n// map[int]struct{}{1:{}, 2:{}, 3:{}, 4:{}}\n```\n\n[[play](https://go.dev/play/p/RYhhM_csqIG)]\n\n### Take\n\nTakes the first n elements from a slice.\n\n```go\nl := lo.Take([]int{0, 1, 2, 3, 4, 5}, 3)\n// []int{0, 1, 2}\n\nl := lo.Take([]int{0, 1, 2}, 5)\n// []int{0, 1, 2}\n```\n\n### TakeWhile\n\nTakes elements from the beginning while the predicate returns true.\n\n```go\nl := lo.TakeWhile([]int{0, 1, 2, 3, 4, 5}, func(val int) bool {\n    return val < 3\n})\n// []int{0, 1, 2}\n\nl := lo.TakeWhile([]string{\"a\", \"aa\", \"aaa\", \"aa\"}, func(val string) bool {\n    return len(val) <= 2\n})\n// []string{\"a\", \"aa\"}\n```\n\n### TakeFilter\n\nFilters elements and takes the first n elements that match the predicate. Equivalent to calling Take(Filter(...)), but more efficient as it stops after finding n matches.\n\n```go\nl := lo.TakeFilter([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 3, func(val int, index int) bool {\n    return val%2 == 0\n})\n// []int{2, 4, 6}\n\nl := lo.TakeFilter([]string{\"a\", \"aa\", \"aaa\", \"aaaa\"}, 2, func(val string, index int) bool {\n    return len(val) > 1\n})\n// []string{\"aa\", \"aaa\"}\n```\n\n### Drop\n\nDrops n elements from the beginning of a slice.\n\n```go\nl := lo.Drop([]int{0, 1, 2, 3, 4, 5}, 2)\n// []int{2, 3, 4, 5}\n```\n\n[[play](https://go.dev/play/p/JswS7vXRJP2)]\n\n### DropRight\n\nDrops n elements from the end of a slice.\n\n```go\nl := lo.DropRight([]int{0, 1, 2, 3, 4, 5}, 2)\n// []int{0, 1, 2, 3}\n```\n\n[[play](https://go.dev/play/p/GG0nXkSJJa3)]\n\n### DropWhile\n\nDrop elements from the beginning of a slice while the predicate returns true.\n\n```go\nl := lo.DropWhile([]string{\"a\", \"aa\", \"aaa\", \"aa\", \"aa\"}, func(val string) bool {\n    return len(val) <= 2\n})\n// []string{\"aaa\", \"aa\", \"aa\"}\n```\n\n[[play](https://go.dev/play/p/7gBPYw2IK16)]\n\n### DropRightWhile\n\nDrop elements from the end of a slice while the predicate returns true.\n\n```go\nl := lo.DropRightWhile([]string{\"a\", \"aa\", \"aaa\", \"aa\", \"aa\"}, func(val string) bool {\n    return len(val) <= 2\n})\n// []string{\"a\", \"aa\", \"aaa\"}\n```\n\n[[play](https://go.dev/play/p/3-n71oEC0Hz)]\n\n### DropByIndex\n\nDrops elements from a slice by the index. A negative index will drop elements from the end of the slice.\n\n```go\nl := lo.DropByIndex([]int{0, 1, 2, 3, 4, 5}, 2, 4, -1)\n// []int{0, 1, 3}\n```\n\n[[play](https://go.dev/play/p/JswS7vXRJP2)]\n\n### Reject\n\nThe opposite of Filter, this method returns the elements of collection that predicate does not return true for.\n\n```go\nodd := lo.Reject([]int{1, 2, 3, 4}, func(x int, _ int) bool {\n    return x%2 == 0\n})\n// []int{1, 3}\n```\n\n```go\n// Use RejectErr when the predicate can return an error\nodd, err := lo.RejectErr([]int{1, 2, 3, 4}, func(x int, _ int) (bool, error) {\n    if x == 3 {\n        return false, fmt.Errorf(\"number 3 is not allowed\")\n    }\n    return x%2 == 0, nil\n})\n// []int(nil), error(\"number 3 is not allowed\")\n```\n\n[[play](https://go.dev/play/p/YkLMODy1WEL)]\n\n### RejectMap\n\nThe opposite of FilterMap, this method returns a slice obtained after both filtering and mapping using the given callback function.\n\nThe callback function should return two values:\n\n- the result of the mapping operation and\n- whether the result element should be included or not.\n\n```go\nitems := lo.RejectMap([]int{1, 2, 3, 4}, func(x int, _ int) (int, bool) {\n    return x*10, x%2 == 0\n})\n// []int{10, 30}\n```\n\n### FilterReject\n\nMixes Filter and Reject, this method returns two slices, one for the elements of collection that predicate returns true for and one for the elements that predicate does not return true for.\n\n```go\nkept, rejected := lo.FilterReject([]int{1, 2, 3, 4}, func(x int, _ int) bool {\n    return x%2 == 0\n})\n// []int{2, 4}\n// []int{1, 3}\n```\n\n### Count\n\nCounts the number of elements in the collection that equal value.\n\n```go\ncount := lo.Count([]int{1, 5, 1}, 1)\n// 2\n```\n\n[[play](https://go.dev/play/p/Y3FlK54yveC)]\n\n### CountBy\n\nCounts the number of elements in the collection for which predicate is true.\n\n```go\ncount := lo.CountBy([]int{1, 5, 1}, func(i int) bool {\n    return i < 4\n})\n// 2\n```\n\n```go\n// Use CountByErr when the predicate can return an error\ncount, err := lo.CountByErr([]int{1, 5, 1}, func(i int) (bool, error) {\n    if i == 5 {\n        return false, fmt.Errorf(\"5 not allowed\")\n    }\n    return i < 4, nil\n})\n// 0, error(\"5 not allowed\")\n```\n\n[[play](https://go.dev/play/p/ByQbNYQQi4X)]\n\n### CountValues\n\nCounts the number of each element in the collection.\n\n```go\nlo.CountValues([]int{})\n// map[int]int{}\n\nlo.CountValues([]int{1, 2})\n// map[int]int{1: 1, 2: 1}\n\nlo.CountValues([]int{1, 2, 2})\n// map[int]int{1: 1, 2: 2}\n\nlo.CountValues([]string{\"foo\", \"bar\", \"\"})\n// map[string]int{\"\": 1, \"foo\": 1, \"bar\": 1}\n\nlo.CountValues([]string{\"foo\", \"bar\", \"bar\"})\n// map[string]int{\"foo\": 1, \"bar\": 2}\n```\n\n[[play](https://go.dev/play/p/-p-PyLT4dfy)]\n\n### CountValuesBy\n\nCounts the number of each element in the collection. It is equivalent to chaining lo.Map and lo.CountValues.\n\n```go\nisEven := func(v int) bool {\n    return v%2==0\n}\n\nlo.CountValuesBy([]int{}, isEven)\n// map[bool]int{}\n\nlo.CountValuesBy([]int{1, 2}, isEven)\n// map[bool]int{false: 1, true: 1}\n\nlo.CountValuesBy([]int{1, 2, 2}, isEven)\n// map[bool]int{false: 1, true: 2}\n\nlength := func(v string) int {\n    return len(v)\n}\n\nlo.CountValuesBy([]string{\"foo\", \"bar\", \"\"}, length)\n// map[int]int{0: 1, 3: 2}\n\nlo.CountValuesBy([]string{\"foo\", \"bar\", \"bar\"}, length)\n// map[int]int{3: 3}\n```\n\n[[play](https://go.dev/play/p/2U0dG1SnOmS)]\n\n### Subset\n\nReturns a copy of a slice from `offset` up to `length` elements. Like `slice[start:start+length]`, but does not panic on overflow.\n\n```go\nin := []int{0, 1, 2, 3, 4}\n\nsub := lo.Subset(in, 2, 3)\n// []int{2, 3, 4}\n\nsub := lo.Subset(in, -4, 3)\n// []int{1, 2, 3}\n\nsub := lo.Subset(in, -2, math.MaxUint)\n// []int{3, 4}\n```\n\n[[play](https://go.dev/play/p/tOQu1GhFcog)]\n\n### Slice\n\nReturns a copy of a slice from `start` up to, but not including `end`. Like `slice[start:end]`, but does not panic on overflow.\n\n```go\nin := []int{0, 1, 2, 3, 4}\n\nslice := lo.Slice(in, 0, 5)\n// []int{0, 1, 2, 3, 4}\n\nslice := lo.Slice(in, 2, 3)\n// []int{2}\n\nslice := lo.Slice(in, 2, 6)\n// []int{2, 3, 4}\n\nslice := lo.Slice(in, 4, 3)\n// []int{}\n```\n\n[[play](https://go.dev/play/p/8XWYhfMMA1h)]\n\n### Replace\n\nReturns a copy of the slice with the first n non-overlapping instances of old replaced by new.\n\n```go\nin := []int{0, 1, 0, 1, 2, 3, 0}\n\nslice := lo.Replace(in, 0, 42, 1)\n// []int{42, 1, 0, 1, 2, 3, 0}\n\nslice := lo.Replace(in, -1, 42, 1)\n// []int{0, 1, 0, 1, 2, 3, 0}\n\nslice := lo.Replace(in, 0, 42, 2)\n// []int{42, 1, 42, 1, 2, 3, 0}\n\nslice := lo.Replace(in, 0, 42, -1)\n// []int{42, 1, 42, 1, 2, 3, 42}\n```\n\n[[play](https://go.dev/play/p/XfPzmf9gql6)]\n\n### ReplaceAll\n\nReturns a copy of the slice with all non-overlapping instances of old replaced by new.\n\n```go\nin := []int{0, 1, 0, 1, 2, 3, 0}\n\nslice := lo.ReplaceAll(in, 0, 42)\n// []int{42, 1, 42, 1, 2, 3, 42}\n\nslice := lo.ReplaceAll(in, -1, 42)\n// []int{0, 1, 0, 1, 2, 3, 0}\n```\n\n[[play](https://go.dev/play/p/a9xZFUHfYcV)]\n\n### Clone\n\nReturns a shallow copy of the collection.\n\n```go\nin := []int{1, 2, 3, 4, 5}\ncloned := lo.Clone(in)\n// Verify it's a different slice by checking that modifying one doesn't affect the other\nin[0] = 99\n// cloned is []int{1, 2, 3, 4, 5}\n```\n\n[[play](https://go.dev/play/p/hgHmoOIxmuH)]\n\n### Compact\n\nReturns a slice of all non-zero elements.\n\n```go\nin := []string{\"\", \"foo\", \"\", \"bar\", \"\"}\n\nslice := lo.Compact(in)\n// []string{\"foo\", \"bar\"}\n```\n\n[[play](https://go.dev/play/p/tXiy-iK6PAc)]\n\n### IsSorted\n\nChecks if a slice is sorted.\n\n```go\nslice := lo.IsSorted([]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9})\n// true\n```\n\n[[play](https://go.dev/play/p/mc3qR-t4mcx)]\n\n### IsSortedBy\n\nChecks if a slice is sorted by iteratee.\n\n```go\nslice := lo.IsSortedBy([]string{\"a\", \"bb\", \"ccc\"}, func(s string) int {\n    return len(s)\n})\n// true\n```\n\n[[play](https://go.dev/play/p/wiG6XyBBu49)]\n\n### Splice\n\nSplice inserts multiple elements at index i. A negative index counts back from the end of the slice. The helper is protected against overflow errors.\n\n```go\nresult := lo.Splice([]string{\"a\", \"b\"}, 1, \"1\", \"2\")\n// []string{\"a\", \"1\", \"2\", \"b\"}\n\n// negative\nresult = lo.Splice([]string{\"a\", \"b\"}, -1, \"1\", \"2\")\n// []string{\"a\", \"1\", \"2\", \"b\"}\n\n// overflow\nresult = lo.Splice([]string{\"a\", \"b\"}, 42, \"1\", \"2\")\n// []string{\"a\", \"b\", \"1\", \"2\"}\n```\n\n[[play](https://go.dev/play/p/G5_GhkeSUBA)]\n\n### Cut\n\nSlices collection around the first instance of separator, returning the part of collection before and after separator. The found result reports whether separator appears in collection. If separator does not appear in s, cut returns collection, empty slice of []T, false.\n\n```go\nactualLeft, actualRight, result = lo.Cut([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, []string{\"b\", \"c\", \"d\"})\n// actualLeft: []string{\"a\"}\n// actualRight: []string{\"e\", \"f\", \"g\"}\n// result: true\n\nresult = lo.Cut([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, []string{\"z\"})\n// actualLeft: []string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}\n// actualRight: []string{}\n// result: false\n\nresult = lo.Cut([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, []string{\"a\", \"b\"})\n// actualLeft: []string{}\n// actualRight: []string{\"c\", \"d\", \"e\", \"f\", \"g\"}\n// result: true\n```\n\n[[play](https://go.dev/play/p/GiL3qhpIP3f)]\n\n### CutPrefix\n\nReturns collection without the provided leading prefix []T and reports whether it found the prefix. If s doesn't start with prefix, CutPrefix returns collection, false. If prefix is the empty []T, CutPrefix returns collection, true.\n\n```go\nactualRight, result = lo.CutPrefix([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, []string{\"a\", \"b\", \"c\"})\n// actualRight: []string{\"d\", \"e\", \"f\", \"g\"}\n// result: true\n\nresult = lo.CutPrefix([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, []string{\"b\"})\n// actualRight: []string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}\n// result: false\n\nresult = lo.CutPrefix([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, []string{})\n// actualRight: []string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}\n// result: true\n```\n\n[[play](https://go.dev/play/p/7Plak4a1ICl)]\n\n### CutSuffix\n\nReturns collection without the provided ending suffix []T and reports whether it found the suffix. If it doesn't end with suffix, CutSuffix returns collection, false. If suffix is the empty []T, CutSuffix returns collection, true.\n\n```go\nactualLeft, result = lo.CutSuffix([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, []string{\"f\", \"g\"})\n// actualLeft: []string{\"a\", \"b\", \"c\", \"d\", \"e\"}\n// result: true\n\nactualLeft, result = lo.CutSuffix([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, []string{\"b\"})\n// actualLeft: []string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}\n// result: false\n\nactualLeft, result = lo.CutSuffix([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, []string{})\n// actualLeft: []string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}\n// result: true\n```\n\n[[play](https://go.dev/play/p/7FKfBFvPTaT)]\n\n### Trim\n\nRemoves all the leading and trailing cutset from the collection.\n\n```go\nresult := lo.Trim([]int{0, 1, 2, 0, 3, 0}, []int{1, 0})\n// []int{2, 0, 3}\n\nresult := lo.Trim([]string{\"hello\", \"world\", \" \"}, []string{\" \", \"\"})\n// []string{\"hello\", \"world\"}\n```\n\n[[play](https://go.dev/play/p/1an9mxLdRG5)]\n\n### TrimLeft\n\nRemoves all the leading cutset from the collection.\n\n```go\nresult := lo.TrimLeft([]int{0, 1, 2, 0, 3, 0}, []int{1, 0})\n// []int{2, 0, 3, 0}\n\nresult := lo.TrimLeft([]string{\"hello\", \"world\", \" \"}, []string{\" \", \"\"})\n// []string{\"hello\", \"world\", \" \"}\n```\n\n[[play](https://go.dev/play/p/74aqfAYLmyi)]\n\n### TrimPrefix\n\nRemoves all the leading prefix from the collection.\n\n```go\nresult := lo.TrimPrefix([]int{1, 2, 1, 2, 3, 1, 2, 4}, []int{1, 2})\n// []int{3, 1, 2, 4}\n\nresult := lo.TrimPrefix([]string{\"hello\", \"world\", \"hello\", \"test\"}, []string{\"hello\"})\n// []string{\"world\", \"hello\", \"test\"}\n```\n\n[[play](https://go.dev/play/p/SHO6X-YegPg)]\n\n### TrimRight\n\nRemoves all the trailing cutset from the collection.\n\n```go\nresult := lo.TrimRight([]int{0, 1, 2, 0, 3, 0}, []int{0, 3})\n// []int{0, 1, 2}\n\nresult := lo.TrimRight([]string{\"hello\", \"world\", \"  \"}, []string{\" \", \"\"})\n// []string{\"hello\", \"world\", \"\"}\n```\n\n[[play](https://go.dev/play/p/MRpAfR6sf0g)]\n\n### TrimSuffix\n\nRemoves all the trailing suffix from the collection.\n\n```go\nresult := lo.TrimSuffix([]int{1, 2, 3, 1, 2, 4, 2, 4, 2, 4}, []int{2, 4})\n// []int{1, 2, 3, 1}\n\nresult := lo.TrimSuffix([]string{\"hello\", \"world\", \"hello\", \"test\"}, []string{\"test\"})\n// []string{\"hello\", \"world\", \"hello\"}\n```\n\n[[play](https://go.dev/play/p/IjEUrV0iofq)]\n\n### Keys\n\nCreates a slice of the map keys.\n\nUse the UniqKeys variant to deduplicate common keys.\n\n```go\nkeys := lo.Keys(map[string]int{\"foo\": 1, \"bar\": 2})\n// []string{\"foo\", \"bar\"}\n\nkeys := lo.Keys(map[string]int{\"foo\": 1, \"bar\": 2}, map[string]int{\"baz\": 3})\n// []string{\"foo\", \"bar\", \"baz\"}\n\nkeys := lo.Keys(map[string]int{\"foo\": 1, \"bar\": 2}, map[string]int{\"bar\": 3})\n// []string{\"foo\", \"bar\", \"bar\"}\n```\n\n[[play](https://go.dev/play/p/Uu11fHASqrU)]\n\n### UniqKeys\n\nCreates a slice of unique map keys.\n\n```go\nkeys := lo.UniqKeys(map[string]int{\"foo\": 1, \"bar\": 2}, map[string]int{\"baz\": 3})\n// []string{\"foo\", \"bar\", \"baz\"}\n\nkeys := lo.UniqKeys(map[string]int{\"foo\": 1, \"bar\": 2}, map[string]int{\"bar\": 3})\n// []string{\"foo\", \"bar\"}\n```\n\n[[play](https://go.dev/play/p/TPKAb6ILdHk)]\n\n### HasKey\n\nReturns whether the given key exists.\n\n```go\nexists := lo.HasKey(map[string]int{\"foo\": 1, \"bar\": 2}, \"foo\")\n// true\n\nexists := lo.HasKey(map[string]int{\"foo\": 1, \"bar\": 2}, \"baz\")\n// false\n```\n\n[[play](https://go.dev/play/p/aVwubIvECqS)]\n\n### Values\n\nCreates a slice of the map values.\n\nUse the UniqValues variant to deduplicate common values.\n\n```go\nvalues := lo.Values(map[string]int{\"foo\": 1, \"bar\": 2})\n// []int{1, 2}\n\nvalues := lo.Values(map[string]int{\"foo\": 1, \"bar\": 2}, map[string]int{\"baz\": 3})\n// []int{1, 2, 3}\n\nvalues := lo.Values(map[string]int{\"foo\": 1, \"bar\": 2}, map[string]int{\"bar\": 2})\n// []int{1, 2, 2}\n```\n\n[[play](https://go.dev/play/p/nnRTQkzQfF6)]\n\n### UniqValues\n\nCreates a slice of unique map values.\n\n```go\nvalues := lo.UniqValues(map[string]int{\"foo\": 1, \"bar\": 2})\n// []int{1, 2}\n\nvalues := lo.UniqValues(map[string]int{\"foo\": 1, \"bar\": 2}, map[string]int{\"baz\": 3})\n// []int{1, 2, 3}\n\nvalues := lo.UniqValues(map[string]int{\"foo\": 1, \"bar\": 2}, map[string]int{\"bar\": 2})\n// []int{1, 2}\n```\n\n[[play](https://go.dev/play/p/nf6bXMh7rM3)]\n\n### ValueOr\n\nReturns the value of the given key or the fallback value if the key is not present.\n\n```go\nvalue := lo.ValueOr(map[string]int{\"foo\": 1, \"bar\": 2}, \"foo\", 42)\n// 1\n\nvalue := lo.ValueOr(map[string]int{\"foo\": 1, \"bar\": 2}, \"baz\", 42)\n// 42\n```\n\n[[play](https://go.dev/play/p/bAq9mHErB4V)]\n\n### PickBy\n\nReturns same map type filtered by given predicate.\n\n```go\nm := lo.PickBy(map[string]int{\"foo\": 1, \"bar\": 2, \"baz\": 3}, func(key string, value int) bool {\n    return value%2 == 1\n})\n// map[string]int{\"foo\": 1, \"baz\": 3}\n```\n\n```go\n// Use PickByErr when the predicate can return an error\nm, err := lo.PickByErr(map[string]int{\"foo\": 1, \"bar\": 2, \"baz\": 3}, func(key string, value int) (bool, error) {\n    if key == \"bar\" {\n        return false, fmt.Errorf(\"bar not allowed\")\n    }\n    return value%2 == 1, nil\n})\n// map[string]int(nil), error(\"bar not allowed\")\n```\n\n[[play](https://go.dev/play/p/kdg8GR_QMmf)]\n\n### PickByKeys\n\nReturns same map type filtered by given keys.\n\n```go\nm := lo.PickByKeys(map[string]int{\"foo\": 1, \"bar\": 2, \"baz\": 3}, []string{\"foo\", \"baz\"})\n// map[string]int{\"foo\": 1, \"baz\": 3}\n```\n\n[[play](https://go.dev/play/p/R1imbuci9qU)]\n\n### PickByValues\n\nReturns same map type filtered by given values.\n\n```go\nm := lo.PickByValues(map[string]int{\"foo\": 1, \"bar\": 2, \"baz\": 3}, []int{1, 3})\n// map[string]int{\"foo\": 1, \"baz\": 3}\n```\n\n[[play](https://go.dev/play/p/1zdzSvbfsJc)]\n\n### OmitBy\n\nReturns same map type filtered by given predicate.\n\n```go\nm := lo.OmitBy(map[string]int{\"foo\": 1, \"bar\": 2, \"baz\": 3}, func(key string, value int) bool {\n    return value%2 == 1\n})\n// map[string]int{\"bar\": 2}\n```\n\n```go\n// Use OmitByErr when the predicate can return an error\nm, err := lo.OmitByErr(map[string]int{\"foo\": 1, \"bar\": 2, \"baz\": 3}, func(key string, value int) (bool, error) {\n    if key == \"bar\" {\n        return false, fmt.Errorf(\"bar not allowed\")\n    }\n    return value%2 == 1, nil\n})\n// map[string]int(nil), error(\"bar not allowed\")\n```\n\n[[play](https://go.dev/play/p/EtBsR43bdsd)]\n\n### OmitByKeys\n\nReturns same map type filtered by given keys.\n\n```go\nm := lo.OmitByKeys(map[string]int{\"foo\": 1, \"bar\": 2, \"baz\": 3}, []string{\"foo\", \"baz\"})\n// map[string]int{\"bar\": 2}\n```\n\n[[play](https://go.dev/play/p/t1QjCrs-ysk)]\n\n### OmitByValues\n\nReturns same map type filtered by given values.\n\n```go\nm := lo.OmitByValues(map[string]int{\"foo\": 1, \"bar\": 2, \"baz\": 3}, []int{1, 3})\n// map[string]int{\"bar\": 2}\n```\n\n[[play](https://go.dev/play/p/9UYZi-hrs8j)]\n\n### Entries (alias: ToPairs)\n\nTransforms a map into a slice of key/value pairs.\n\n```go\nentries := lo.Entries(map[string]int{\"foo\": 1, \"bar\": 2})\n// []lo.Entry[string, int]{\n//     {\n//         Key: \"foo\",\n//         Value: 1,\n//     },\n//     {\n//         Key: \"bar\",\n//         Value: 2,\n//     },\n// }\n```\n\n[[play](https://go.dev/play/p/_t4Xe34-Nl5)]\n\n### FromEntries (alias: FromPairs)\n\nTransforms a slice of key/value pairs into a map.\n\n```go\nm := lo.FromEntries([]lo.Entry[string, int]{\n    {\n        Key: \"foo\",\n        Value: 1,\n    },\n    {\n        Key: \"bar\",\n        Value: 2,\n    },\n})\n// map[string]int{\"foo\": 1, \"bar\": 2}\n```\n\n[[play](https://go.dev/play/p/oIr5KHFGCEN)]\n\n### Invert\n\nCreates a map composed of the inverted keys and values. If map contains duplicate values, subsequent values overwrite property assignments of previous values.\n\n```go\nm1 := lo.Invert(map[string]int{\"a\": 1, \"b\": 2})\n// map[int]string{1: \"a\", 2: \"b\"}\n\nm2 := lo.Invert(map[string]int{\"a\": 1, \"b\": 2, \"c\": 1})\n// map[int]string{1: \"c\", 2: \"b\"}\n```\n\n[[play](https://go.dev/play/p/rFQ4rak6iA1)]\n\n### Assign\n\nMerges multiple maps from left to right.\n\n```go\nmergedMaps := lo.Assign(\n    map[string]int{\"a\": 1, \"b\": 2},\n    map[string]int{\"b\": 3, \"c\": 4},\n)\n// map[string]int{\"a\": 1, \"b\": 3, \"c\": 4}\n```\n\n[[play](https://go.dev/play/p/VhwfJOyxf5o)]\n\n### ChunkEntries\n\nSplits a map into a slice of elements in groups of length equal to its size. If the map cannot be split evenly, the final chunk will contain the remaining elements.\n\n```go\nmaps := lo.ChunkEntries(\n    map[string]int{\n        \"a\": 1,\n        \"b\": 2,\n        \"c\": 3,\n        \"d\": 4,\n        \"e\": 5,\n    },\n    3,\n)\n// []map[string]int{\n//    {\"a\": 1, \"b\": 2, \"c\": 3},\n//    {\"d\": 4, \"e\": 5},\n// }\n```\n[[play](https://go.dev/play/p/X_YQL6mmoD-)]\n\n### MapKeys\n\nManipulates map keys and transforms it to a map of another type.\n\n```go\nm2 := lo.MapKeys(map[int]int{1: 1, 2: 2, 3: 3, 4: 4}, func(_ int, v int) string {\n    return strconv.FormatInt(int64(v), 10)\n})\n// map[string]int{\"1\": 1, \"2\": 2, \"3\": 3, \"4\": 4}\n```\n\n```go\n// Use MapKeysErr when the iteratee can return an error\nm2, err := lo.MapKeysErr(map[int]int{1: 1, 2: 2, 3: 3}, func(_ int, v int) (string, error) {\n    if v == 2 {\n        return \"\", fmt.Errorf(\"even number not allowed\")\n    }\n    return strconv.FormatInt(int64(v), 10), nil\n})\n// map[string]int(nil), error(\"even number not allowed\")\n```\n\n[[play](https://go.dev/play/p/9_4WPIqOetJ)]\n\n### MapValues\n\nManipulates map values and transforms it to a map of another type.\n\n```go\nm1 := map[int]int64{1: 1, 2: 2, 3: 3}\n\nm2 := lo.MapValues(m1, func(x int64, _ int) string {\n    return strconv.FormatInt(x, 10)\n})\n// map[int]string{1: \"1\", 2: \"2\", 3: \"3\"}\n```\n\n```go\n// Use MapValuesErr when the iteratee can return an error\nm1 := map[int]int64{1: 1, 2: 2, 3: 3}\nm2, err := lo.MapValuesErr(m1, func(x int64, _ int) (string, error) {\n    if x == 2 {\n        return \"\", fmt.Errorf(\"even number not allowed\")\n    }\n    return strconv.FormatInt(x, 10), nil\n})\n// map[int]string(nil), error(\"even number not allowed\")\n```\n\n[[play](https://go.dev/play/p/T_8xAfvcf0W)]\n\n### MapEntries\n\nManipulates map entries and transforms it to a map of another type.\n\n```go\nin := map[string]int{\"foo\": 1, \"bar\": 2}\n\nout := lo.MapEntries(in, func(k string, v int) (int, string) {\n    return v,k\n})\n// map[int]string{1: \"foo\", 2: \"bar\"}\n```\n\n```go\n// Use MapEntriesErr when the iteratee can return an error\nin := map[string]int{\"foo\": 1, \"bar\": 2, \"baz\": 3}\nout, err := lo.MapEntriesErr(in, func(k string, v int) (int, string, error) {\n    if k == \"bar\" {\n        return 0, \"\", fmt.Errorf(\"bar not allowed\")\n    }\n    return v, k, nil\n})\n// map[int]string(nil), error(\"bar not allowed\")\n```\n\n[[play](https://go.dev/play/p/VuvNQzxKimT)]\n\n### MapToSlice\n\nTransforms a map into a slice based on specified iteratee.\n\n```go\nm := map[int]int64{1: 4, 2: 5, 3: 6}\n\ns := lo.MapToSlice(m, func(k int, v int64) string {\n    return fmt.Sprintf(\"%d_%d\", k, v)\n})\n// []string{\"1_4\", \"2_5\", \"3_6\"}\n```\n\n```go\n// Use MapToSliceErr when the iteratee can return an error\nm := map[int]int64{1: 4, 2: 5, 3: 6}\ns, err := lo.MapToSliceErr(m, func(k int, v int64) (string, error) {\n    if k == 2 {\n        return \"\", fmt.Errorf(\"key 2 not allowed\")\n    }\n    return fmt.Sprintf(\"%d_%d\", k, v), nil\n})\n// []string(nil), error(\"key 2 not allowed\")\n```\n\n[[play](https://go.dev/play/p/ZuiCZpDt6LD)]\n\n### FilterMapToSlice\n\nTransforms a map into a slice based on specified iteratee. The iteratee returns a value and a boolean. If the boolean is true, the value is added to the result slice.\n\nIf the boolean is false, the value is not added to the result slice. The order of the keys in the input map is not specified and the order of the keys in the output slice is not guaranteed.\n\n```go\nkv := map[int]int64{1: 1, 2: 2, 3: 3, 4: 4}\n\nresult := lo.FilterMapToSlice(kv, func(k int, v int64) (string, bool) {\n    return fmt.Sprintf(\"%d_%d\", k, v), k%2 == 0\n})\n// []{\"2_2\", \"4_4\"}\n```\n\n```go\nkv := map[int]int64{1: 1, 2: 2, 3: 3, 4: 4}\n\nresult, err := lo.FilterMapToSliceErr(kv, func(k int, v int64) (string, bool, error) {\n    if k == 3 {\n        return \"\", false, fmt.Errorf(\"key 3 not allowed\")\n    }\n    return fmt.Sprintf(\"%d_%d\", k, v), k%2 == 0, nil\n})\n// []string(nil), error(\"key 3 not allowed\")\n```\n\n### FilterKeys\n\nTransforms a map into a slice based on predicate returns true for specific elements. It is a mix of `lo.Filter()` and `lo.Keys()`.\n\n```go\nkv := map[int]string{1: \"foo\", 2: \"bar\", 3: \"baz\"}\n\nresult := FilterKeys(kv, func(k int, v string) bool {\n    return v == \"foo\"\n})\n// [1]\n```\n\n```go\n// Use FilterKeysErr when the predicate can return an error\nresult, err := lo.FilterKeysErr(map[int]string{1: \"foo\", 2: \"bar\", 3: \"baz\"}, func(k int, v string) (bool, error) {\n    if k == 3 {\n        return false, fmt.Errorf(\"key 3 not allowed\")\n    }\n    return v == \"foo\", nil\n})\n// []int(nil), error(\"key 3 not allowed\")\n```\n\n[[play](https://go.dev/play/p/OFlKXlPrBAe)]\n\n### FilterValues\n\nTransforms a map into a slice based on predicate returns true for specific elements. It is a mix of `lo.Filter()` and `lo.Values()`.\n\n```go\nkv := map[int]string{1: \"foo\", 2: \"bar\", 3: \"baz\"}\n\nresult := FilterValues(kv, func(k int, v string) bool {\n    return v == \"foo\"\n})\n// [\"foo\"]\n```\n\n```go\n// Use FilterValuesErr when the predicate can return an error\nresult, err := lo.FilterValuesErr(map[int]string{1: \"foo\", 2: \"bar\", 3: \"baz\"}, func(k int, v string) (bool, error) {\n    if k == 3 {\n        return false, fmt.Errorf(\"key 3 not allowed\")\n    }\n    return v == \"foo\", nil\n})\n// []string(nil), error(\"key 3 not allowed\")\n```\n\n[[play](https://go.dev/play/p/YVD5r_h-LX-)]\n\n### Range / RangeFrom / RangeWithSteps\n\nCreates a slice of numbers (positive and/or negative) progressing from start up to, but not including end.\n\n```go\nresult := lo.Range(4)\n// [0, 1, 2, 3]\n\nresult := lo.Range(-4)\n// [0, -1, -2, -3]\n\nresult := lo.RangeFrom(1, 5)\n// [1, 2, 3, 4, 5]\n\nresult := lo.RangeFrom[float64](1.0, 5)\n// [1.0, 2.0, 3.0, 4.0, 5.0]\n\nresult := lo.RangeWithSteps(0, 20, 5)\n// [0, 5, 10, 15]\n\nresult := lo.RangeWithSteps[float32](-1.0, -4.0, -1.0)\n// [-1.0, -2.0, -3.0]\n\nresult := lo.RangeWithSteps(1, 4, -1)\n// []\n\nresult := lo.Range(0)\n// []\n```\n\n[[play](https://go.dev/play/p/0r6VimXAi9H)]\n\n### Clamp\n\nClamps number within the inclusive lower and upper bounds.\n\n```go\nr1 := lo.Clamp(0, -10, 10)\n// 0\n\nr2 := lo.Clamp(-42, -10, 10)\n// -10\n\nr3 := lo.Clamp(42, -10, 10)\n// 10\n```\n\n[[play](https://go.dev/play/p/RU4lJNC2hlI)]\n\n### Sum\n\nSums the values in a collection.\n\nIf collection is empty 0 is returned.\n\n```go\nlist := []int{1, 2, 3, 4, 5}\nsum := lo.Sum(list)\n// 15\n```\n\n[[play](https://go.dev/play/p/upfeJVqs4Bt)]\n\n### SumBy\n\nSummarizes the values in a collection using the given return value from the iteration function.\n\nIf collection is empty 0 is returned.\n\n```go\nstrings := []string{\"foo\", \"bar\"}\nsum := lo.SumBy(strings, func(item string) int {\n    return len(item)\n})\n// 6\n```\n\nWith error handling:\n\n```go\nstrings := []string{\"foo\", \"bar\", \"baz\"}\nsum, err := lo.SumByErr(strings, func(item string) (int, error) {\n    if item == \"bar\" {\n        return 0, fmt.Errorf(\"invalid item: %s\", item)\n    }\n    return len(item), nil\n})\n// sum: 3, err: invalid item: bar\n```\n\n### Product\n\nCalculates the product of the values in a collection.\n\nIf collection is empty 0 is returned.\n\n```go\nlist := []int{1, 2, 3, 4, 5}\nproduct := lo.Product(list)\n// 120\n```\n\n[[play](https://go.dev/play/p/2_kjM_smtAH)]\n\n### ProductBy\n\nCalculates the product of the values in a collection using the given return value from the iteration function.\n\nIf collection is empty 0 is returned.\n\n```go\nstrings := []string{\"foo\", \"bar\"}\nproduct := lo.ProductBy(strings, func(item string) int {\n    return len(item)\n})\n// 9\n```\n\n```go\n// Use ProductByErr when the transform function can return an error\nstrings := []string{\"foo\", \"bar\", \"baz\"}\nproduct, err := lo.ProductByErr(strings, func(item string) (int, error) {\n    if item == \"bar\" {\n        return 0, fmt.Errorf(\"bar is not allowed\")\n    }\n    return len(item), nil\n})\n// 3, error(\"bar is not allowed\")\n```\n\n[[play](https://go.dev/play/p/wadzrWr9Aer)]\n\n### Mean\n\nCalculates the mean of a collection of numbers.\n\nIf collection is empty 0 is returned.\n\n```go\nmean := lo.Mean([]int{2, 3, 4, 5})\n// 3\n\nmean := lo.Mean([]float64{2, 3, 4, 5})\n// 3.5\n\nmean := lo.Mean([]float64{})\n// 0\n```\n\n### MeanBy\n\nCalculates the mean of a collection of numbers using the given return value from the iteration function.\n\nIf collection is empty 0 is returned.\n\n```go\nlist := []string{\"aa\", \"bbb\", \"cccc\", \"ddddd\"}\nmapper := func(item string) float64 {\n    return float64(len(item))\n}\n\nmean := lo.MeanBy(list, mapper)\n// 3.5\n\nmean := lo.MeanBy([]float64{}, mapper)\n// 0\n```\n\n```go\n// Use MeanByErr when the transform function can return an error\nlist := []string{\"aa\", \"bbb\", \"cccc\", \"ddddd\"}\nmean, err := lo.MeanByErr(list, func(item string) (float64, error) {\n    if item == \"cccc\" {\n        return 0, fmt.Errorf(\"cccc is not allowed\")\n    }\n    return float64(len(item)), nil\n})\n// 0, error(\"cccc is not allowed\")\n```\n\n[[play](https://go.dev/play/p/j7TsVwBOZ7P)]\n\n### Mode\n\nCalculates the mode (most frequent value) of a collection of numbers.\n\nIf multiple values have the same highest frequency, then multiple values are returned.\n\nIf the collection is empty, the zero value of `T[]` is returned.\n\n```go\nmode := lo.Mode([]int{2, 2, 3, 4})\n// [2]\n\nmode := lo.Mode([]float64{2, 2, 3, 3})\n// [2, 3]\n\nmode := lo.Mode([]float64{})\n// []\n\nmode := lo.Mode([]int{1, 2, 3, 4, 5, 6, 7, 8, 9})\n// [1, 2, 3, 4, 5, 6, 7, 8, 9]\n```\n\n### RandomString\n\nReturns a random string of the specified length and made of the specified charset.\n\n```go\nstr := lo.RandomString(5, lo.LettersCharset)\n// example: \"eIGbt\"\n```\n\n[[play](https://go.dev/play/p/rRseOQVVum4)]\n\n### Substring\n\nReturn part of a string.\n\n```go\nsub := lo.Substring(\"hello\", 2, 3)\n// \"llo\"\n\nsub := lo.Substring(\"hello\", -4, 3)\n// \"ell\"\n\nsub := lo.Substring(\"hello\", -2, math.MaxUint)\n// \"lo\"\n```\n\n[[play](https://go.dev/play/p/TQlxQi82Lu1)]\n\n### ChunkString\n\nReturns a slice of strings split into groups of length size. If the string can't be split evenly, the final chunk will be the remaining characters.\n\n```go\nlo.ChunkString(\"123456\", 2)\n// []string{\"12\", \"34\", \"56\"}\n\nlo.ChunkString(\"1234567\", 2)\n// []string{\"12\", \"34\", \"56\", \"7\"}\n\nlo.ChunkString(\"\", 2)\n// []string{\"\"}\n\nlo.ChunkString(\"1\", 2)\n// []string{\"1\"}\n```\n\nNote: `lo.ChunkString` and `lo.Chunk` functions behave inconsistently for empty input: `lo.ChunkString(\"\", n)` returns `[\"\"]` instead of `[]`. See [#788](https://github.com/samber/lo/issues/788).\n\n[[play](https://go.dev/play/p/__FLTuJVz54)]\n\n### RuneLength\n\nAn alias to utf8.RuneCountInString which returns the number of runes in string.\n\n```go\nsub := lo.RuneLength(\"hellô\")\n// 5\n\nsub := len(\"hellô\")\n// 6\n```\n\n[[play](https://go.dev/play/p/tuhgW_lWY8l)]\n\n### PascalCase\n\nConverts string to pascal case.\n\n```go\nstr := lo.PascalCase(\"hello_world\")\n// HelloWorld\n```\n\n[[play](https://go.dev/play/p/Dy_V_6DUYhe)]\n\n### CamelCase\n\nConverts string to camel case.\n\n```go\nstr := lo.CamelCase(\"hello_world\")\n// helloWorld\n```\n\n[[play](https://go.dev/play/p/Go6aKwUiq59)]\n\n### KebabCase\n\nConverts string to kebab case.\n\n```go\nstr := lo.KebabCase(\"helloWorld\")\n// hello-world\n```\n\n[[play](https://go.dev/play/p/96gT_WZnTVP)]\n\n### SnakeCase\n\nConverts string to snake case.\n\n```go\nstr := lo.SnakeCase(\"HelloWorld\")\n// hello_world\n```\n\n[[play](https://go.dev/play/p/ziB0V89IeVH)]\n\n### Words\n\nSplits string into a slice of its words.\n\n```go\nstr := lo.Words(\"helloWorld\")\n// []string{\"hello\", \"world\"}\n```\n\n[[play](https://go.dev/play/p/-f3VIQqiaVw)]\n\n### Capitalize\n\nConverts the first character of string to upper case and the remaining to lower case.\n\n```go\nstr := lo.Capitalize(\"heLLO\")\n// Hello\n```\n\n[[play](https://go.dev/play/p/uLTZZQXqnsa)]\n\n### Ellipsis\n\nTrims and truncates a string to a specified length in runes (Unicode code points) and appends an ellipsis if truncated. Multi-byte characters such as emoji or CJK ideographs are never split in the middle.\n\n```go\nstr := lo.Ellipsis(\"  Lorem Ipsum  \", 5)\n// Lo...\n\nstr := lo.Ellipsis(\"Lorem Ipsum\", 100)\n// Lorem Ipsum\n\nstr := lo.Ellipsis(\"Lorem Ipsum\", 3)\n// ...\n\nstr := lo.Ellipsis(\"hello 世界! 你好\", 8)\n// hello...\n\nstr := lo.Ellipsis(\"🏠🐶🐱🌟\", 4)\n// 🏠🐶🐱🌟\n```\n\n[[play](https://go.dev/play/p/qE93rgqe1TW)]\n\n### T2 -> T9\n\nCreates a tuple from a list of values.\n\n```go\ntuple1 := lo.T2(\"x\", 1)\n// Tuple2[string, int]{A: \"x\", B: 1}\n\nfunc example() (string, int) { return \"y\", 2 }\ntuple2 := lo.T2(example())\n// Tuple2[string, int]{A: \"y\", B: 2}\n```\n\n[[play](https://go.dev/play/p/IllL3ZO4BQm)]\n\n### Unpack2 -> Unpack9\n\nReturns values contained in a tuple.\n\n```go\nr1, r2 := lo.Unpack2(lo.Tuple2[string, int]{\"a\", 1})\n// \"a\", 1\n```\n\nUnpack is also available as a method of TupleX.\n\n```go\ntuple2 := lo.T2(\"a\", 1)\na, b := tuple2.Unpack()\n// \"a\", 1\n```\n\n[[play](https://go.dev/play/p/xVP_k0kJ96W)]\n\n### Zip2 -> Zip9\n\nZip creates a slice of grouped elements, the first of which contains the first elements of the given slices, the second of which contains the second elements of the given slices, and so on.\n\nWhen collections are different sizes, the Tuple attributes are filled with zero value.\n\n```go\ntuples := lo.Zip2([]string{\"a\", \"b\"}, []int{1, 2})\n// []Tuple2[string, int]{{A: \"a\", B: 1}, {A: \"b\", B: 2}}\n```\n\n[[play](https://go.dev/play/p/jujaA6GaJTp)]\n\n### ZipBy2 -> ZipBy9\n\nZipBy creates a slice of transformed elements, the first of which contains the first elements of the given slices, the second of which contains the second elements of the given slices, and so on.\n\nWhen collections are different sizes, the Tuple attributes are filled with zero value.\n\n```go\nitems := lo.ZipBy2([]string{\"a\", \"b\"}, []int{1, 2}, func(a string, b int) string {\n    return fmt.Sprintf(\"%s-%d\", a, b)\n})\n// []string{\"a-1\", \"b-2\"}\n```\n\nWith error handling:\n\n```go\nitems, err := lo.ZipByErr2([]string{\"a\", \"b\"}, []int{1, 2}, func(a string, b int) (string, error) {\n    if b == 2 {\n        return \"\", fmt.Errorf(\"number 2 is not allowed\")\n    }\n    return fmt.Sprintf(\"%s-%d\", a, b), nil\n})\n// []string(nil), error(\"number 2 is not allowed\")\n```\n\n### Unzip2 -> Unzip9\n\nUnzip accepts a slice of grouped elements and creates a slice regrouping the elements to their pre-zip configuration.\n\n```go\na, b := lo.Unzip2([]Tuple2[string, int]{{A: \"a\", B: 1}, {A: \"b\", B: 2}})\n// []string{\"a\", \"b\"}\n// []int{1, 2}\n```\n\n[[play](https://go.dev/play/p/ciHugugvaAW)]\n\n### UnzipBy2 -> UnzipBy9\n\nUnzipBy2 iterates over a collection and creates a slice regrouping the elements to their pre-zip configuration.\n\n```go\na, b := lo.UnzipBy2([]string{\"hello\", \"john\", \"doe\"}, func(str string) (string, int) {\n    return str, len(str)\n})\n// []string{\"hello\", \"john\", \"doe\"}\n// []int{5, 4, 3}\n```\n\n```go\na, b, err := lo.UnzipByErr2([]string{\"hello\", \"error\", \"world\"}, func(str string) (string, int, error) {\n    if str == \"error\" {\n        return \"\", 0, fmt.Errorf(\"error string not allowed\")\n    }\n    return str, len(str), nil\n})\n// []string{}\n// []int{}\n// error string not allowed\n```\n\n### CrossJoin2 -> CrossJoin9\n\nCombines every item from one list with every item from others. It is the cartesian product of lists received as arguments. Returns an empty list if a list is empty.\n\n```go\nresult := lo.CrossJoin2([]string{\"hello\", \"john\", \"doe\"}, []int{1, 2})\n// lo.Tuple2{\"hello\", 1}\n// lo.Tuple2{\"hello\", 2}\n// lo.Tuple2{\"john\", 1}\n// lo.Tuple2{\"john\", 2}\n// lo.Tuple2{\"doe\", 1}\n// lo.Tuple2{\"doe\", 2}\n```\n\n### CrossJoinBy2 -> CrossJoinBy9\n\nCombines every item from one list with every item from others. It is the cartesian product of lists received as arguments. The transform function is used to create the output values. Returns an empty list if a list is empty.\n\n```go\nresult := lo.CrossJoinBy2([]string{\"hello\", \"john\", \"doe\"}, []int{1, 2}, func(a A, b B) string {\n    return fmt.Sprintf(\"%s - %d\", a, b)\n})\n// \"hello - 1\"\n// \"hello - 2\"\n// \"john - 1\"\n// \"john - 2\"\n// \"doe - 1\"\n// \"doe - 2\"\n```\n\nWith error handling:\n\n```go\nresult, err := lo.CrossJoinByErr2([]string{\"hello\", \"john\"}, []int{1, 2}, func(a string, b int) (string, error) {\n    if a == \"john\" {\n        return \"\", fmt.Errorf(\"john not allowed\")\n    }\n    return fmt.Sprintf(\"%s - %d\", a, b), nil\n})\n// []string(nil), error(\"john not allowed\")\n```\n\n### Duration\n\nReturns the time taken to execute a function.\n\n```go\nduration := lo.Duration(func() {\n    // very long job\n})\n// 3s\n```\n\n[[play](https://go.dev/play/p/HQfbBbAXaFP)]\n\n### Duration0 -> Duration10\n\nReturns the time taken to execute a function.\n\n```go\nduration := lo.Duration0(func() {\n    // very long job\n})\n// 3s\n\nerr, duration := lo.Duration1(func() error {\n    // very long job\n    return errors.New(\"an error\")\n})\n// an error\n// 3s\n\nstr, nbr, err, duration := lo.Duration3(func() (string, int, error) {\n    // very long job\n    return \"hello\", 42, nil\n})\n// hello\n// 42\n// nil\n// 3s\n```\n\n### ChannelDispatcher\n\nDistributes messages from input channels into N child channels. Close events are propagated to children.\n\nUnderlying channels can have a fixed buffer capacity or be unbuffered when cap is 0.\n\n```go\nch := make(chan int, 42)\nfor i := 0; i <= 10; i++ {\n    ch <- i\n}\n\nchildren := lo.ChannelDispatcher(ch, 5, 10, DispatchingStrategyRoundRobin[int])\n// []<-chan int{...}\n\nconsumer := func(c <-chan int) {\n    for {\n        msg, ok := <-c\n        if !ok {\n            println(\"closed\")\n\n            break\n        }\n\n        println(msg)\n    }\n}\n\nfor i := range children {\n    go consumer(children[i])\n}\n```\n\n[[play](https://go.dev/play/p/UZGu2wVg3J2)]\n\nMany distributions strategies are available:\n\n- [lo.DispatchingStrategyRoundRobin](./channel.go): Distributes messages in a rotating sequential manner.\n- [lo.DispatchingStrategyRandom](./channel.go): Distributes messages in a random manner.\n- [lo.DispatchingStrategyWeightedRandom](./channel.go): Distributes messages in a weighted manner.\n- [lo.DispatchingStrategyFirst](./channel.go): Distributes messages in the first non-full channel.\n- [lo.DispatchingStrategyLeast](./channel.go): Distributes messages in the emptiest channel.\n- [lo.DispatchingStrategyMost](./channel.go): Distributes to the fullest channel.\n\nSome strategies bring fallback, in order to favor non-blocking behaviors. See implementations.\n\nFor custom strategies, just implement the `lo.DispatchingStrategy` prototype:\n\n```go\ntype DispatchingStrategy[T any] func(message T, messageIndex uint64, channels []<-chan T) int\n```\n\nEg:\n\n```go\ntype Message struct {\n    TenantID uuid.UUID\n}\n\nfunc hash(id uuid.UUID) int {\n    h := fnv.New32a()\n    h.Write([]byte(id.String()))\n    return int(h.Sum32())\n}\n\n// Routes messages per TenantID.\ncustomStrategy := func(message string, messageIndex uint64, channels []<-chan string) int {\n    destination := hash(message) % len(channels)\n\n    // check if channel is full\n    if len(channels[destination]) < cap(channels[destination]) {\n        return destination\n    }\n\n    // fallback when child channel is full\n    return utils.DispatchingStrategyRoundRobin(message, uint64(destination), channels)\n}\n\nchildren := lo.ChannelDispatcher(ch, 5, 10, customStrategy)\n...\n```\n\n### SliceToChannel\n\nReturns a read-only channel of collection elements. Channel is closed after last element. Channel capacity can be customized.\n\n```go\nlist := []int{1, 2, 3, 4, 5}\n\nfor v := range lo.SliceToChannel(2, list) {\n    println(v)\n}\n// prints 1, then 2, then 3, then 4, then 5\n```\n\n[[play](https://go.dev/play/p/lIbSY3QmiEg)]\n\n### ChannelToSlice\n\nReturns a slice built from channel items. Blocks until channel closes.\n\n```go\nlist := []int{1, 2, 3, 4, 5}\nch := lo.SliceToChannel(2, list)\n\nitems := ChannelToSlice(ch)\n// []int{1, 2, 3, 4, 5}\n```\n\n### Generator\n\nImplements the generator design pattern. Channel is closed after last element. Channel capacity can be customized.\n\n```go\ngenerator := func(yield func(int)) {\n    yield(1)\n    yield(2)\n    yield(3)\n}\n\nfor v := range lo.Generator(2, generator) {\n    println(v)\n}\n// prints 1, then 2, then 3\n```\n\n### Buffer\n\nCreates a slice of n elements from a channel. Returns the slice, the slice length, the read time and the channel status (opened/closed).\n\n```go\nch := lo.SliceToChannel(2, []int{1, 2, 3, 4, 5})\n\nitems1, length1, duration1, ok1 := lo.Buffer(ch, 3)\n// []int{1, 2, 3}, 3, 0s, true\nitems2, length2, duration2, ok2 := lo.Buffer(ch, 3)\n// []int{4, 5}, 2, 0s, false\n```\n\nExample: RabbitMQ consumer 👇\n\n```go\nch := readFromQueue()\n\nfor {\n    // read 1k items\n    items, length, _, ok := lo.Buffer(ch, 1000)\n\n    // do batching stuff\n\n    if !ok {\n        break\n    }\n}\n```\n\n### BufferWithContext\n\nCreates a slice of n elements from a channel, with timeout. Returns the slice, the slice length, the read time and the channel status (opened/closed).\n\n```go\nctx, cancel := context.WithCancel(context.TODO())\ngo func() {\n    ch <- 0\n    time.Sleep(10*time.Millisecond)\n    ch <- 1\n    time.Sleep(10*time.Millisecond)\n    ch <- 2\n    time.Sleep(10*time.Millisecond)\n    ch <- 3\n    time.Sleep(10*time.Millisecond)\n    ch <- 4\n    time.Sleep(10*time.Millisecond)\n    cancel()\n}()\n\nitems1, length1, duration1, ok1 := lo.BufferWithContext(ctx, ch, 3)\n// []int{0, 1, 2}, 3, 20ms, true\nitems2, length2, duration2, ok2 := lo.BufferWithContext(ctx, ch, 3)\n// []int{3, 4}, 2, 30ms, false\n```\n\n### BufferWithTimeout\n\nCreates a slice of n elements from a channel, with timeout. Returns the slice, the slice length, the read time and the channel status (opened/closed).\n\n```go\ngenerator := func(yield func(int)) {\n    for i := 0; i < 5; i++ {\n        yield(i)\n        time.Sleep(35*time.Millisecond)\n    }\n}\n\nch := lo.Generator(0, generator)\n\nitems1, length1, duration1, ok1 := lo.BufferWithTimeout(ch, 3, 100*time.Millisecond)\n// []int{1, 2}, 2, 100ms, true\nitems2, length2, duration2, ok2 := lo.BufferWithTimeout(ch, 3, 100*time.Millisecond)\n// []int{3, 4, 5}, 3, 75ms, true\nitems3, length3, duration2, ok3 := lo.BufferWithTimeout(ch, 3, 100*time.Millisecond)\n// []int{}, 0, 10ms, false\n```\n\nExample: RabbitMQ consumer 👇\n\n```go\nch := readFromQueue()\n\nfor {\n    // read 1k items\n    // wait up to 1 second\n    items, length, _, ok := lo.BufferWithTimeout(ch, 1000, 1*time.Second)\n\n    // do batching stuff\n\n    if !ok {\n        break\n    }\n}\n```\n\nExample: Multithreaded RabbitMQ consumer 👇\n\n```go\nch := readFromQueue()\n\n// 5 workers\n// prefetch 1k messages per worker\nchildren := lo.ChannelDispatcher(ch, 5, 1000, lo.DispatchingStrategyFirst[int])\n\nconsumer := func(c <-chan int) {\n    for {\n        // read 1k items\n        // wait up to 1 second\n        items, length, _, ok := lo.BufferWithTimeout(ch, 1000, 1*time.Second)\n\n        // do batching stuff\n\n        if !ok {\n            break\n        }\n    }\n}\n\nfor i := range children {\n    go consumer(children[i])\n}\n```\n\n### FanIn\n\nMerge messages from multiple input channels into a single buffered channel. Output messages have no priority. When all upstream channels reach EOF, downstream channel closes.\n\n```go\nstream1 := make(chan int, 42)\nstream2 := make(chan int, 42)\nstream3 := make(chan int, 42)\n\nall := lo.FanIn(100, stream1, stream2, stream3)\n// <-chan int\n```\n\n### FanOut\n\nBroadcasts all the upstream messages to multiple downstream channels. When upstream channel reaches EOF, downstream channels close. If any downstream channels is full, broadcasting is paused.\n\n```go\nstream := make(chan int, 42)\n\nall := lo.FanOut(5, 100, stream)\n// [5]<-chan int\n```\n\n### Contains\n\nReturns true if an element is present in a collection.\n\n```go\npresent := lo.Contains([]int{0, 1, 2, 3, 4, 5}, 5)\n// true\n```\n\n[[play](https://go.dev/play/p/W1EvyqY6t9j)]\n\n### ContainsBy\n\nReturns true if the predicate function returns `true`.\n\n```go\npresent := lo.ContainsBy([]int{0, 1, 2, 3, 4, 5}, func(x int) bool {\n    return x == 3\n})\n// true\n```\n\n### Every\n\nReturns true if all elements of a subset are contained in a collection or if the subset is empty.\n\n```go\nok := lo.Every([]int{0, 1, 2, 3, 4, 5}, []int{0, 2})\n// true\n\nok := lo.Every([]int{0, 1, 2, 3, 4, 5}, []int{0, 6})\n// false\n```\n\n### EveryBy\n\nReturns true if the predicate returns true for all elements in the collection or if the collection is empty.\n\n```go\nb := EveryBy([]int{1, 2, 3, 4}, func(x int) bool {\n    return x < 5\n})\n// true\n```\n\n[[play](https://go.dev/play/p/dn1-vhHsq9x)]\n\n### Some\n\nReturns true if at least 1 element of a subset is contained in a collection.\nIf the subset is empty Some returns false.\n\n```go\nok := lo.Some([]int{0, 1, 2, 3, 4, 5}, []int{0, 6})\n// true\n```\n\n[[play](https://go.dev/play/p/Lj4ceFkeT9V)]\n\nok := lo.Some([]int{0, 1, 2, 3, 4, 5}, []int{-1, 6})\n// false\n```\n\n### SomeBy\n\nReturns true if the predicate returns true for any of the elements in the collection.\nIf the collection is empty SomeBy returns false.\n\n```go\nb := SomeBy([]int{1, 2, 3, 4}, func(x int) bool {\n    return x < 3\n})\n// true\n```\n\n### None\n\nReturns true if no element of a subset is contained in a collection or if the subset is empty.\n\n```go\nb := None([]int{0, 1, 2, 3, 4, 5}, []int{0, 2})\n// false\nb := None([]int{0, 1, 2, 3, 4, 5}, []int{-1, 6})\n// true\n```\n\n[[play](https://go.dev/play/p/fye7JsmxzPV)]\n\n### NoneBy\n\nReturns true if the predicate returns true for none of the elements in the collection or if the collection is empty.\n\n```go\nb := NoneBy([]int{1, 2, 3, 4}, func(x int) bool {\n    return x < 0\n})\n// true\n```\n\n[[play](https://go.dev/play/p/O64WZ32H58S)]\n\n### Intersect\n\nReturns the intersection between collections.\n\n```go\nresult1 := lo.Intersect([]int{0, 1, 2, 3, 4, 5}, []int{0, 2})\n// []int{0, 2}\n\nresult2 := lo.Intersect([]int{0, 1, 2, 3, 4, 5}, []int{0, 6})\n// []int{0}\n\nresult3 := lo.Intersect([]int{0, 1, 2, 3, 4, 5}, []int{-1, 6})\n// []int{}\n\nresult4 := lo.Intersect([]int{0, 3, 5, 7}, []int{3, 5}, []int{0, 1, 2, 0, 3, 0})\n// []int{3}\n```\n\n### IntersectBy\n\nReturns the intersection between two collections using a custom key selector function.\n\n```go\ntransform := func(v int) string {\n    return strconv.Itoa(v)\n}\n\nresult1 := lo.IntersectBy(transform, []int{0, 1, 2, 3, 4, 5}, []int{0, 2})\n// []int{0, 2}\n\nresult2 := lo.IntersectBy(transform, []int{0, 1, 2, 3, 4, 5}, []int{0, 6})\n// []int{0}\n\nresult3 := lo.IntersectBy(transform, []int{0, 1, 2, 3, 4, 5}, []int{-1, 6})\n// []int{}\n\nresult4 := lo.IntersectBy(transform, []int{0, 3, 5, 7}, []int{3, 5}, []int{0, 1, 2, 0, 3, 0})\n// []int{3}\n```\n\n### Difference\n\nReturns the difference between two collections.\n\n- The first value is the collection of elements absent from list2.\n- The second value is the collection of elements absent from list1.\n\n```go\nleft, right := lo.Difference([]int{0, 1, 2, 3, 4, 5}, []int{0, 2, 6})\n// []int{1, 3, 4, 5}, []int{6}\n\nleft, right := lo.Difference([]int{0, 1, 2, 3, 4, 5}, []int{0, 1, 2, 3, 4, 5})\n// []int{}, []int{}\n```\n\n[[play](https://go.dev/play/p/pKE-JgzqRpz)]\n\n### Union\n\nReturns all distinct elements from given collections. Result will not change the order of elements relatively.\n\n```go\nunion := lo.Union([]int{0, 1, 2, 3, 4, 5}, []int{0, 2}, []int{0, 10})\n// []int{0, 1, 2, 3, 4, 5, 10}\n```\n\n### Without\n\nReturns a slice excluding all given values.\n\n```go\nsubset := lo.Without([]int{0, 2, 10}, 2)\n// []int{0, 10}\n\nsubset := lo.Without([]int{0, 2, 10}, 0, 1, 2, 3, 4, 5)\n// []int{10}\n```\n\n### WithoutBy\n\nFilters a slice by excluding elements whose extracted keys match any in the exclude list.\n\nReturns a new slice containing only the elements whose keys are not in the exclude list.\n\n```go\ntype User struct {\n    ID int\n    Name string\n}\n\n// original users\nusers := []User{\n    {ID: 1, Name: \"Alice\"},\n    {ID: 2, Name: \"Bob\"},\n    {ID: 3, Name: \"Charlie\"},\n}\n\n// extract function to get the user ID\ngetID := func(user User) int {\n    return user.ID\n}\n\n// exclude users with IDs 2 and 3\nexcludedIDs := []int{2, 3}\n\n// filtering users\nfilteredUsers := lo.WithoutBy(users, getID, excludedIDs...)\n// []User[{ID: 1, Name: \"Alice\"}]\n```\n\n```go\n// Use WithoutByErr when the iteratee can return an error\ntype struct User {\n    ID int\n    Name string\n}\n\nusers := []User{\n    {ID: 1, Name: \"Alice\"},\n    {ID: 2, Name: \"Bob\"},\n    {ID: 3, Name: \"Charlie\"},\n}\n\ngetID := func(user User) (int, error) {\n    if user.ID == 2 {\n        return 0, fmt.Errorf(\"Bob not allowed\")\n    }\n    return user.ID, nil\n}\n\nfilteredUsers, err := lo.WithoutByErr(users, getID, 2, 3)\n// []User(nil), error(\"Bob not allowed\")\n```\n\n### WithoutEmpty\n\nReturns a slice excluding zero values.\n\n```go\nsubset := lo.WithoutEmpty([]int{0, 2, 10})\n// []int{2, 10}\n```\n\n### WithoutNth\n\nReturns a slice excluding the nth value.\n\n```go\nsubset := lo.WithoutNth([]int{-2, -1, 0, 1, 2}, 3, -42, 1)\n// []int{-2, 0, 2}\n```\n\n### ElementsMatch\n\nReturns true if lists contain the same set of elements (including empty set).\n\nIf there are duplicate elements, the number of occurrences in each list should match.\n\nThe order of elements is not checked.\n\n```go\nb := lo.ElementsMatch([]int{1, 1, 2}, []int{2, 1, 1})\n// true\n```\n\n### ElementsMatchBy\n\nReturns true if lists contain the same set of elements' keys (including empty set).\n\nIf there are duplicate keys, the number of occurrences in each list should match.\n\nThe order of elements is not checked.\n\n```go\nb := lo.ElementsMatchBy(\n    []someType{a, b},\n    []someType{b, a},\n    func(item someType) string { return item.ID() },\n)\n// true\n```\n\n### IndexOf\n\nReturns the index at which the first occurrence of a value is found in a slice or -1 if the value cannot be found.\n\n```go\nfound := lo.IndexOf([]int{0, 1, 2, 1, 2, 3}, 2)\n// 2\n\nnotFound := lo.IndexOf([]int{0, 1, 2, 1, 2, 3}, 6)\n// -1\n```\n\n[[play](https://go.dev/play/p/Eo7W0lvKTky)]\n\n### LastIndexOf\n\nReturns the index at which the last occurrence of a value is found in a slice or -1 if the value cannot be found.\n\n```go\nfound := lo.LastIndexOf([]int{0, 1, 2, 1, 2, 3}, 2)\n// 4\n\nnotFound := lo.LastIndexOf([]int{0, 1, 2, 1, 2, 3}, 6)\n// -1\n```\n\n### HasPrefix\n\nReturns true if the collection has the prefix.\n\n```go\nok := lo.HasPrefix([]int{1, 2, 3, 4}, []int{42})\n// false\n\nok := lo.HasPrefix([]int{1, 2, 3, 4}, []int{1, 2})\n// true\n```\n\n[[play](https://go.dev/play/p/SrljzVDpMQM)]\n\n### HasSuffix\n\nReturns true if the collection has the suffix.\n\n```go\nok := lo.HasSuffix([]int{1, 2, 3, 4}, []int{42})\n// false\n\nok := lo.HasSuffix([]int{1, 2, 3, 4}, []int{3, 4})\n// true\n```\n\n[[play](https://go.dev/play/p/bJeLetQNAON)]\n\n### Find\n\nSearches for an element in a slice based on a predicate. Returns element and true if element was found.\n\n```go\nstr, ok := lo.Find([]string{\"a\", \"b\", \"c\", \"d\"}, func(i string) bool {\n    return i == \"b\"\n})\n// \"b\", true\n\nstr, ok := lo.Find([]string{\"foobar\"}, func(i string) bool {\n    return i == \"b\"\n})\n// \"\", false\n```\n\n```go\n// Use FindErr when the predicate can return an error\nstr, err := lo.FindErr([]string{\"a\", \"b\", \"c\", \"d\"}, func(i string) (bool, error) {\n    if i == \"c\" {\n        return false, fmt.Errorf(\"c is not allowed\")\n    }\n    return i == \"b\", nil\n})\n// \"b\", nil\n\nstr, err = lo.FindErr([]string{\"a\", \"b\", \"c\"}, func(i string) (bool, error) {\n    if i == \"b\" {\n        return false, fmt.Errorf(\"b is not allowed\")\n    }\n    return i == \"b\", nil\n})\n// \"\", error(\"b is not allowed\")\n```\n\n[[play](https://go.dev/play/p/Eo7W0lvKTky)]\n\n### FindIndexOf\n\nFindIndexOf searches for an element in a slice based on a predicate and returns the index and true. Returns -1 and false if the element is not found.\n\n```go\nstr, index, ok := lo.FindIndexOf([]string{\"a\", \"b\", \"a\", \"b\"}, func(i string) bool {\n    return i == \"b\"\n})\n// \"b\", 1, true\n\nstr, index, ok := lo.FindIndexOf([]string{\"foobar\"}, func(i string) bool {\n    return i == \"b\"\n})\n// \"\", -1, false\n```\n\n[[play](https://go.dev/play/p/XWSEM4Ic_t0)]\n\n### FindLastIndexOf\n\nFindLastIndexOf searches for the last element in a slice based on a predicate and returns the index and true. Returns -1 and false if the element is not found.\n\n```go\nstr, index, ok := lo.FindLastIndexOf([]string{\"a\", \"b\", \"a\", \"b\"}, func(i string) bool {\n    return i == \"b\"\n})\n// \"b\", 4, true\n\nstr, index, ok := lo.FindLastIndexOf([]string{\"foobar\"}, func(i string) bool {\n    return i == \"b\"\n})\n// \"\", -1, false\n```\n\n[[play](https://go.dev/play/p/dPiMRtJ6cUx)]\n\n### FindOrElse\n\nSearches for an element in a slice based on a predicate. Returns the element if found or a given fallback value otherwise.\n\n```go\nstr := lo.FindOrElse([]string{\"a\", \"b\", \"c\", \"d\"}, \"x\", func(i string) bool {\n    return i == \"b\"\n})\n// \"b\"\n\nstr := lo.FindOrElse([]string{\"foobar\"}, \"x\", func(i string) bool {\n    return i == \"b\"\n})\n// \"x\"\n```\n\n### FindKey\n\nReturns the key of the first value matching.\n\n```go\nresult1, ok1 := lo.FindKey(map[string]int{\"foo\": 1, \"bar\": 2, \"baz\": 3}, 2)\n// \"bar\", true\n\nresult2, ok2 := lo.FindKey(map[string]int{\"foo\": 1, \"bar\": 2, \"baz\": 3}, 42)\n// \"\", false\n\ntype test struct {\n    foobar string\n}\nresult3, ok3 := lo.FindKey(map[string]test{\"foo\": test{\"foo\"}, \"bar\": test{\"bar\"}, \"baz\": test{\"baz\"}}, test{\"foo\"})\n// \"foo\", true\n```\n\n### FindKeyBy\n\nReturns the key of the first element predicate returns true for.\n\n```go\nresult1, ok1 := lo.FindKeyBy(map[string]int{\"foo\": 1, \"bar\": 2, \"baz\": 3}, func(k string, v int) bool {\n    return k == \"foo\"\n})\n// \"foo\", true\n\nresult2, ok2 := lo.FindKeyBy(map[string]int{\"foo\": 1, \"bar\": 2, \"baz\": 3}, func(k string, v int) bool {\n    return false\n})\n// \"\", false\n```\n\n### FindUniques\n\nReturns a slice with all the elements that appear in the collection only once. The order of result values is determined by the order they occur in the slice.\n\n```go\nuniqueValues := lo.FindUniques([]int{1, 2, 2, 1, 2, 3})\n// []int{3}\n```\n\n### FindUniquesBy\n\nReturns a slice with all the elements that appear in the collection only once. The order of result values is determined by the order they occur in the slice. It accepts `iteratee` which is invoked for each element in the slice to generate the criterion by which uniqueness is computed.\n\n```go\nuniqueValues := lo.FindUniquesBy([]int{3, 4, 5, 6, 7}, func(i int) int {\n    return i%3\n})\n// []int{5}\n```\n\n### FindDuplicates\n\nReturns a slice with the first occurrence of each duplicated element in the collection. The order of result values is determined by the order they occur in the slice.\n\n```go\nduplicatedValues := lo.FindDuplicates([]int{1, 2, 2, 1, 2, 3})\n// []int{1, 2}\n```\n\n### FindDuplicatesBy\n\nReturns a slice with the first occurrence of each duplicated element in the collection. The order of result values is determined by the order they occur in the slice. It accepts `iteratee` which is invoked for each element in the slice to generate the criterion by which uniqueness is computed.\n\n```go\nduplicatedValues := lo.FindDuplicatesBy([]int{3, 4, 5, 6, 7}, func(i int) int {\n    return i%3\n})\n// []int{3, 4}\n```\n\nWith error handling:\n\n```go\nduplicatedValues, err := lo.FindDuplicatesByErr([]int{3, 4, 5, 6, 7}, func(i int) (int, error) {\n    if i == 5 {\n        return 0, fmt.Errorf(\"number 5 is not allowed\")\n    }\n    return i % 3, nil\n})\n// []int(nil), error(\"number 5 is not allowed\")\n```\n\n### Min\n\nSearch the minimum value of a collection.\n\nReturns zero value when the collection is empty.\n\n```go\nmin := lo.Min([]int{1, 2, 3})\n// 1\n\nmin := lo.Min([]int{})\n// 0\n\nmin := lo.Min([]time.Duration{time.Second, time.Hour})\n// 1s\n```\n\n[[play](https://go.dev/play/p/r6e-Z8JozS8)]\n\n### MinIndex\n\nSearch the minimum value of a collection and the index of the minimum value.\n\nReturns (zero value, -1) when the collection is empty.\n\n```go\nmin, index := lo.MinIndex([]int{1, 2, 3})\n// 1, 0\n\nmin, index := lo.MinIndex([]int{})\n// 0, -1\n\nmin, index := lo.MinIndex([]time.Duration{time.Second, time.Hour})\n// 1s, 0\n```\n\n### MinBy\n\nSearch the minimum value of a collection using the given comparison function.\n\nIf several values of the collection are equal to the smallest value, returns the first such value.\n\nReturns zero value when the collection is empty.\n\n```go\nmin := lo.MinBy([]string{\"s1\", \"string2\", \"s3\"}, func(item string, min string) bool {\n    return len(item) < len(min)\n})\n// \"s1\"\n\nmin := lo.MinBy([]string{}, func(item string, min string) bool {\n    return len(item) < len(min)\n})\n// \"\"\n```\n\n```go\n// Use MinByErr when the comparison function can return an error\nmin, err := lo.MinByErr([]string{\"s1\", \"string2\", \"s3\"}, func(item string, min string) (bool, error) {\n    if item == \"string2\" {\n        return false, fmt.Errorf(\"string2 is not allowed\")\n    }\n    return len(item) < len(min), nil\n})\n// \"s1\", error(\"string2 is not allowed\")\n```\n\n### MinIndexBy\n\nSearch the minimum value of a collection using the given comparison function and the index of the minimum value.\n\nIf several values of the collection are equal to the smallest value, returns the first such value.\n\nReturns (zero value, -1) when the collection is empty.\n\n```go\nmin, index := lo.MinIndexBy([]string{\"s1\", \"string2\", \"s3\"}, func(item string, min string) bool {\n    return len(item) < len(min)\n})\n// \"s1\", 0\n\nmin, index := lo.MinIndexBy([]string{}, func(item string, min string) bool {\n    return len(item) < len(min)\n})\n// \"\", -1\n```\n\n```go\nmin, index, err := lo.MinIndexByErr([]string{\"s1\", \"string2\", \"s3\"}, func(item string, min string) (bool, error) {\n    if item == \"s2\" {\n        return false, fmt.Errorf(\"s2 is not allowed\")\n    }\n    return len(item) < len(min), nil\n})\n// \"s1\", 0, error(\"s2 is not allowed\")\n```\n\n### Earliest\n\nSearch the minimum time.Time of a collection.\n\nReturns zero value when the collection is empty.\n\n```go\nearliest := lo.Earliest(time.Now(), time.Time{})\n// 0001-01-01 00:00:00 +0000 UTC\n```\n\n### EarliestBy\n\nSearch the minimum time.Time of a collection using the given iteratee function.\n\nReturns zero value when the collection is empty.\n\n```go\ntype foo struct {\n    bar time.Time\n}\n\nearliest := lo.EarliestBy([]foo{{time.Now()}, {}}, func(i foo) time.Time {\n    return i.bar\n})\n// {bar:{2023-04-01 01:02:03 +0000 UTC}}\n```\n\n```go\n// Use EarliestByErr when the iteratee function can return an error\nearliest, err := lo.EarliestByErr([]foo{{time.Now()}, {}}, func(i foo) (time.Time, error) {\n    if i.bar.IsZero() {\n        return time.Time{}, fmt.Errorf(\"zero time not allowed\")\n    }\n    return i.bar, nil\n})\n// {bar:{...}}, error(\"zero time not allowed\")\n```\n\n### Max\n\nSearch the maximum value of a collection.\n\nReturns zero value when the collection is empty.\n\n```go\nmax := lo.Max([]int{1, 2, 3})\n// 3\n\nmax := lo.Max([]int{})\n// 0\n\nmax := lo.Max([]time.Duration{time.Second, time.Hour})\n// 1h\n```\n\n### MaxIndex\n\nSearch the maximum value of a collection and the index of the maximum value.\n\nReturns (zero value, -1) when the collection is empty.\n\n```go\nmax, index := lo.MaxIndex([]int{1, 2, 3})\n// 3, 2\n\nmax, index := lo.MaxIndex([]int{})\n// 0, -1\n\nmax, index := lo.MaxIndex([]time.Duration{time.Second, time.Hour})\n// 1h, 1\n```\n\n### MaxBy\n\nSearch the maximum value of a collection using the given comparison function.\n\nIf several values of the collection are equal to the greatest value, returns the first such value.\n\nReturns zero value when the collection is empty.\n\n```go\nmax := lo.MaxBy([]string{\"string1\", \"s2\", \"string3\"}, func(item string, max string) bool {\n    return len(item) > len(max)\n})\n// \"string1\"\n\nmax := lo.MaxBy([]string{}, func(item string, max string) bool {\n    return len(item) > len(max)\n})\n// \"\"\n```\n\n```go\n// Use MaxByErr when the comparison function can return an error\nmax, err := lo.MaxByErr([]string{\"string1\", \"s2\", \"string3\"}, func(item string, max string) (bool, error) {\n    if item == \"s2\" {\n        return false, fmt.Errorf(\"s2 is not allowed\")\n    }\n    return len(item) > len(max), nil\n})\n// \"string1\", error(\"s2 is not allowed\")\n```\n\n[[play](https://go.dev/play/p/JW1qu-ECwF7)]\n\n### MaxIndexBy\n\nSearch the maximum value of a collection using the given comparison function and the index of the maximum value.\n\nIf several values of the collection are equal to the greatest value, returns the first such value.\n\nReturns (zero value, -1) when the collection is empty.\n\n```go\nmax, index := lo.MaxIndexBy([]string{\"string1\", \"s2\", \"string3\"}, func(item string, max string) bool {\n    return len(item) > len(max)\n})\n// \"string1\", 0\n\nmax, index := lo.MaxIndexBy([]string{}, func(item string, max string) bool {\n    return len(item) > len(max)\n})\n// \"\", -1\n```\n\n```go\n// Use MaxIndexByErr when the comparison function can return an error\nmax, index, err := lo.MaxIndexByErr([]string{\"string1\", \"s2\", \"string3\"}, func(item string, max string) (bool, error) {\n    if item == \"s2\" {\n        return false, fmt.Errorf(\"s2 is not allowed\")\n    }\n    return len(item) > len(max), nil\n})\n// \"string1\", 0, error(\"s2 is not allowed\")\n```\n\n[[play](https://go.dev/play/p/uaUszc-c9QK)]\n\n### Latest\n\nSearch the maximum time.Time of a collection.\n\nReturns zero value when the collection is empty.\n\n```go\nlatest := lo.Latest(time.Now(), time.Time{})\n// 2023-04-01 01:02:03 +0000 UTC\n```\n\n### LatestBy\n\nSearch the maximum time.Time of a collection using the given iteratee function.\n\nReturns zero value when the collection is empty.\n\n```go\ntype foo struct {\n    bar time.Time\n}\n\nlatest := lo.LatestBy([]foo{{time.Now()}, {}}, func(i foo) time.Time {\n    return i.bar\n})\n// {bar:{2023-04-01 01:02:03 +0000 UTC}}\n```\n\n```go\n// Use LatestByErr when the iteratee function can return an error\nresult, err := lo.LatestByErr([]foo{{time.Now()}, {}}, func(i foo) (time.Time, error) {\n    if i.bar.IsZero() {\n        return time.Time{}, fmt.Errorf(\"zero time not allowed\")\n    }\n    return i.bar, nil\n})\n// foo{}, error(\"zero time not allowed\")\n```\n\n### First\n\nReturns the first element of a collection and check for availability of the first element.\n\n```go\nfirst, ok := lo.First([]int{1, 2, 3})\n// 1, true\n\nfirst, ok := lo.First([]int{})\n// 0, false\n```\n\n### FirstOrEmpty\n\nReturns the first element of a collection or zero value if empty.\n\n```go\nfirst := lo.FirstOrEmpty([]int{1, 2, 3})\n// 1\n\nfirst := lo.FirstOrEmpty([]int{})\n// 0\n```\n\n### FirstOr\n\nReturns the first element of a collection or the fallback value if empty.\n\n```go\nfirst := lo.FirstOr([]int{1, 2, 3}, 245)\n// 1\n\nfirst := lo.FirstOr([]int{}, 31)\n// 31\n```\n\n### Last\n\nReturns the last element of a collection or error if empty.\n\n```go\nlast, ok := lo.Last([]int{1, 2, 3})\n// 3\n// true\n\nlast, ok := lo.Last([]int{})\n// 0\n// false\n```\n\n### LastOrEmpty\n\nReturns the last element of a collection or zero value if empty.\n\n```go\nlast := lo.LastOrEmpty([]int{1, 2, 3})\n// 3\n\nlast := lo.LastOrEmpty([]int{})\n// 0\n```\n\n### LastOr\n\nReturns the last element of a collection or the fallback value if empty.\n\n```go\nlast := lo.LastOr([]int{1, 2, 3}, 245)\n// 3\n\nlast := lo.LastOr([]int{}, 31)\n// 31\n```\n\n### Nth\n\nReturns the element at index `nth` of collection. If `nth` is negative, the nth element from the end is returned. An error is returned when nth is out of slice bounds.\n\n```go\nnth, err := lo.Nth([]int{0, 1, 2, 3}, 2)\n// 2\n\nnth, err := lo.Nth([]int{0, 1, 2, 3}, -2)\n// 2\n```\n\n### NthOr\n\nReturns the element at index `nth` of the collection. If `nth` is negative, it returns the `nth` element from the end. If `nth` is out of slice bounds, it returns the provided fallback value\n```go\nnth := lo.NthOr([]int{10, 20, 30, 40, 50}, 2, -1)\n// 30\n\nnth := lo.NthOr([]int{10, 20, 30, 40, 50}, -1, -1)\n// 50\n\nnth := lo.NthOr([]int{10, 20, 30, 40, 50}, 5, -1)\n// -1 (fallback value)\n```\n\n### NthOrEmpty\n\nReturns the element at index `nth` of the collection. If `nth` is negative, it returns the `nth` element from the end. If `nth` is out of slice bounds, it returns the zero value for the element type (e.g., 0 for integers, \"\" for strings, etc).\n``` go\nnth := lo.NthOrEmpty([]int{10, 20, 30, 40, 50}, 2)\n// 30\n\nnth := lo.NthOrEmpty([]int{10, 20, 30, 40, 50}, -1)\n// 50\n\nnth := lo.NthOrEmpty([]int{10, 20, 30, 40, 50}, 5)\n// 0 (zero value for int)\n\nnth := lo.NthOrEmpty([]string{\"apple\", \"banana\", \"cherry\"}, 2)\n// \"cherry\"\n\nnth := lo.NthOrEmpty([]string{\"apple\", \"banana\", \"cherry\"}, 5)\n// \"\" (zero value for string)\n```\n\n### Sample\n\nReturns a random item from collection.\n\n```go\nlo.Sample([]string{\"a\", \"b\", \"c\"})\n// a random string from []string{\"a\", \"b\", \"c\"}\n\nlo.Sample([]string{})\n// \"\"\n```\n\n[[play](https://go.dev/play/p/FYA45LcpfM2)]\n\n### SampleBy\n\nReturns a random item from collection, using a given random integer generator.\n\n```go\nimport \"math/rand\"\n\nr := rand.New(rand.NewSource(42))\nlo.SampleBy([]string{\"a\", \"b\", \"c\"}, r.Intn)\n// a random string from []string{\"a\", \"b\", \"c\"}, using a seeded random generator\n\nlo.SampleBy([]string{}, r.Intn)\n// \"\"\n```\n\n### Samples\n\nReturns N random unique items from collection.\n\n```go\nlo.Samples([]string{\"a\", \"b\", \"c\"}, 3)\n// []string{\"a\", \"b\", \"c\"} in random order\n```\n\n### SamplesBy\n\nReturns N random unique items from collection, using a given random integer generator.\n\n```go\nr := rand.New(rand.NewSource(42))\nlo.SamplesBy([]string{\"a\", \"b\", \"c\"}, 3, r.Intn)\n// []string{\"a\", \"b\", \"c\"} in random order, using a seeded random generator\n```\n\n### Ternary\n\nA single line if/else statement.\n\n```go\nresult := lo.Ternary(true, \"a\", \"b\")\n// \"a\"\n\nresult := lo.Ternary(false, \"a\", \"b\")\n// \"b\"\n```\n\nTake care to avoid dereferencing potentially nil pointers in your A/B expressions, because they are both evaluated. See TernaryF to avoid this problem.\n\n[[play](https://go.dev/play/p/t-D7WBL44h2)]\n\n### TernaryF\n\nA single line if/else statement whose options are functions.\n\n```go\nresult := lo.TernaryF(true, func() string { return \"a\" }, func() string { return \"b\" })\n// \"a\"\n\nresult := lo.TernaryF(false, func() string { return \"a\" }, func() string { return \"b\" })\n// \"b\"\n```\n\nUseful to avoid nil-pointer dereferencing in initializations, or avoid running unnecessary code\n\n```go\nvar s *string\n\nsomeStr := TernaryF(s == nil, func() string { return uuid.New().String() }, func() string { return *s })\n// ef782193-c30c-4e2e-a7ae-f8ab5e125e02\n```\n\n[[play](https://go.dev/play/p/AO4VW20JoqM)]\n\n### If / ElseIf / Else\n\n```go\nresult := lo.If(true, 1).\n    ElseIf(false, 2).\n    Else(3)\n// 1\n\nresult := lo.If(false, 1).\n    ElseIf(true, 2).\n    Else(3)\n// 2\n\nresult := lo.If(false, 1).\n    ElseIf(false, 2).\n    Else(3)\n// 3\n```\n\nUsing callbacks:\n\n```go\nresult := lo.IfF(true, func () int {\n        return 1\n    }).\n    ElseIfF(false, func () int {\n        return 2\n    }).\n    ElseF(func () int {\n        return 3\n    })\n// 1\n```\n\nMixed:\n\n```go\nresult := lo.IfF(true, func () int {\n        return 1\n    }).\n    Else(42)\n// 1\n```\n\n[[play](https://go.dev/play/p/WSw3ApMxhyW)]\n\n### Switch / Case / Default\n\n```go\nresult := lo.Switch(1).\n    Case(1, \"1\").\n    Case(2, \"2\").\n    Default(\"3\")\n// \"1\"\n\nresult := lo.Switch(2).\n    Case(1, \"1\").\n    Case(2, \"2\").\n    Default(\"3\")\n// \"2\"\n\nresult := lo.Switch(42).\n    Case(1, \"1\").\n    Case(2, \"2\").\n    Default(\"3\")\n// \"3\"\n```\n\nUsing callbacks:\n\n```go\nresult := lo.Switch(1).\n    CaseF(1, func() string {\n        return \"1\"\n    }).\n    CaseF(2, func() string {\n        return \"2\"\n    }).\n    DefaultF(func() string {\n        return \"3\"\n    })\n// \"1\"\n```\n\nMixed:\n\n```go\nresult := lo.Switch(1).\n    CaseF(1, func() string {\n        return \"1\"\n    }).\n    Default(\"42\")\n// \"1\"\n```\n\n[[play](https://go.dev/play/p/TGbKUMAeRUd)]\n\n### IsNil\n\nChecks if a value is nil or if it's a reference type with a nil underlying value.\n\n```go\nvar x int\nlo.IsNil(x)\n// false\n\nvar k struct{}\nlo.IsNil(k)\n// false\n\nvar i *int\nlo.IsNil(i)\n// true\n\nvar ifaceWithNilValue any = (*string)(nil)\nlo.IsNil(ifaceWithNilValue)\n// true\nifaceWithNilValue == nil\n// false\n```\n\n### IsNotNil\n\nChecks if a value is not nil or if it's not a reference type with a nil underlying value.\n\n```go\nvar x int\nlo.IsNotNil(x)\n// true\n\nvar k struct{}\nlo.IsNotNil(k)\n// true\n\nvar i *int\nlo.IsNotNil(i)\n// false\n\nvar ifaceWithNilValue any = (*string)(nil)\nlo.IsNotNil(ifaceWithNilValue)\n// false\nifaceWithNilValue == nil\n// true\n```\n\n### ToPtr\n\nReturns a pointer copy of the value.\n\n```go\nptr := lo.ToPtr(\"hello world\")\n// *string{\"hello world\"}\n```\n\n[[play](https://go.dev/play/p/P2sD0PMXw4F)]\n\n### Nil\n\nReturns a nil pointer of type.\n\n```go\nptr := lo.Nil[float64]()\n// nil\n```\n\n### EmptyableToPtr\n\nReturns a pointer copy of value if it's nonzero.\nOtherwise, returns nil pointer.\n\n```go\nptr := lo.EmptyableToPtr(nil)\n// nil\n\nptr := lo.EmptyableToPtr(\"\")\n// nil\n\nptr := lo.EmptyableToPtr([]int{})\n// *[]int{}\n\nptr := lo.EmptyableToPtr(\"hello world\")\n// *string{\"hello world\"}\n```\n\n### FromPtr\n\nReturns the pointer value or empty.\n\n```go\nstr := \"hello world\"\nvalue := lo.FromPtr(&str)\n// \"hello world\"\n\nvalue := lo.FromPtr(nil)\n// \"\"\n```\n\n### FromPtrOr\n\nReturns the pointer value or the fallback value.\n\n```go\nstr := \"hello world\"\nvalue := lo.FromPtrOr(&str, \"empty\")\n// \"hello world\"\n\nvalue := lo.FromPtrOr(nil, \"empty\")\n// \"empty\"\n```\n\n### ToSlicePtr\n\nReturns a slice of pointers to each value.\n\n```go\nptr := lo.ToSlicePtr([]string{\"hello\", \"world\"})\n// []*string{\"hello\", \"world\"}\n```\n\n### FromSlicePtr\n\nReturns a slice with the pointer values.\nReturns a zero value in case of a nil pointer element.\n\n```go\nstr1 := \"hello\"\nstr2 := \"world\"\n\nptr := lo.FromSlicePtr[string]([]*string{&str1, &str2, nil})\n// []string{\"hello\", \"world\", \"\"}\n\nptr := lo.Compact(\n    lo.FromSlicePtr[string]([]*string{&str1, &str2, nil}),\n)\n// []string{\"hello\", \"world\"}\n```\n\n### FromSlicePtrOr\n\nReturns a slice with the pointer values or the fallback value.\n\n```go\nstr1 := \"hello\"\nstr2 := \"world\"\n\nptr := lo.FromSlicePtrOr([]*string{&str1, nil, &str2}, \"fallback value\")\n// []string{\"hello\", \"fallback value\", \"world\"}\n```\n\n[[play](https://go.dev/play/p/CuXGVzo9G65)]\n\n### ToAnySlice\n\nReturns a slice with all elements mapped to `any` type.\n\n```go\nelements := lo.ToAnySlice([]int{1, 5, 1})\n// []any{1, 5, 1}\n```\n\n### FromAnySlice\n\nReturns a slice with all elements mapped to a type. Returns false in case of type conversion failure.\n\n```go\nelements, ok := lo.FromAnySlice([]any{\"foobar\", 42})\n// []string{}, false\n\nelements, ok := lo.FromAnySlice([]any{\"foobar\", \"42\"})\n// []string{\"foobar\", \"42\"}, true\n```\n\n### Empty\n\nReturns the [zero value](https://go.dev/ref/spec#The_zero_value).\n\n```go\nlo.Empty[int]()\n// 0\nlo.Empty[string]()\n// \"\"\nlo.Empty[bool]()\n// false\n```\n\n### IsEmpty\n\nReturns true if argument is a zero value.\n\n```go\nlo.IsEmpty(0)\n// true\nlo.IsEmpty(42)\n// false\n\nlo.IsEmpty(\"\")\n// true\nlo.IsEmpty(\"foobar\")\n// false\n\ntype test struct {\n    foobar string\n}\n\nlo.IsEmpty(test{foobar: \"\"})\n// true\nlo.IsEmpty(test{foobar: \"foobar\"})\n// false\n```\n\n### IsNotEmpty\n\nReturns true if argument is a zero value.\n\n```go\nlo.IsNotEmpty(0)\n// false\nlo.IsNotEmpty(42)\n// true\n\nlo.IsNotEmpty(\"\")\n// false\nlo.IsNotEmpty(\"foobar\")\n// true\n\ntype test struct {\n    foobar string\n}\n\nlo.IsNotEmpty(test{foobar: \"\"})\n// false\nlo.IsNotEmpty(test{foobar: \"foobar\"})\n// true\n```\n\n### Coalesce\n\nReturns the first non-empty arguments. Arguments must be comparable.\n\n```go\nresult, ok := lo.Coalesce(0, 1, 2, 3)\n// 1 true\n\nresult, ok := lo.Coalesce(\"\")\n// \"\" false\n\nvar nilStr *string\nstr := \"foobar\"\nresult, ok := lo.Coalesce(nil, nilStr, &str)\n// &\"foobar\" true\n```\n\n### CoalesceOrEmpty\n\nReturns the first non-empty arguments. Arguments must be comparable.\n\n```go\nresult := lo.CoalesceOrEmpty(0, 1, 2, 3)\n// 1\n\nresult := lo.CoalesceOrEmpty(\"\")\n// \"\"\n\nvar nilStr *string\nstr := \"foobar\"\nresult := lo.CoalesceOrEmpty(nil, nilStr, &str)\n// &\"foobar\"\n```\n\n### CoalesceSlice\n\nReturns the first non-zero slice.\n\n```go\nresult, ok := lo.CoalesceSlice([]int{1, 2, 3}, []int{4, 5, 6})\n// [1, 2, 3]\n// true\n\nresult, ok := lo.CoalesceSlice(nil, []int{})\n// []\n// true\n\nresult, ok := lo.CoalesceSlice([]int(nil))\n// []\n// false\n```\n\n### CoalesceSliceOrEmpty\n\nReturns the first non-zero slice.\n\n```go\nresult := lo.CoalesceSliceOrEmpty([]int{1, 2, 3}, []int{4, 5, 6})\n// [1, 2, 3]\n\nresult := lo.CoalesceSliceOrEmpty(nil, []int{})\n// []\n```\n\n### CoalesceMap\n\nReturns the first non-zero map.\n\n```go\nresult, ok := lo.CoalesceMap(map[string]int{\"1\": 1, \"2\": 2, \"3\": 3}, map[string]int{\"4\": 4, \"5\": 5, \"6\": 6})\n// {\"1\": 1, \"2\": 2, \"3\": 3}\n// true\n\nresult, ok := lo.CoalesceMap(nil, map[string]int{})\n// {}\n// true\n\nresult, ok := lo.CoalesceMap(map[string]int(nil))\n// {}\n// false\n```\n\n### CoalesceMapOrEmpty\n\nReturns the first non-zero map.\n\n```go\nresult := lo.CoalesceMapOrEmpty(map[string]int{\"1\": 1, \"2\": 2, \"3\": 3}, map[string]int{\"4\": 4, \"5\": 5, \"6\": 6})\n// {\"1\": 1, \"2\": 2, \"3\": 3}\n\nresult := lo.CoalesceMapOrEmpty(nil, map[string]int{})\n// {}\n```\n\n### Partial\n\nReturns new function that, when called, has its first argument set to the provided value.\n\n```go\nadd := func(x, y int) int { return x + y }\nf := lo.Partial(add, 5)\n\nf(10)\n// 15\n\nf(42)\n// 47\n```\n\n[[play](https://go.dev/play/p/Sy1gAQiQZ3v)]\n\n### Partial2 -> Partial5\n\nReturns new function that, when called, has its first argument set to the provided value.\n\n```go\nadd := func(x, y, z int) int { return x + y + z }\nf := lo.Partial2(add, 42)\n\nf(10, 5)\n// 57\n\nf(42, -4)\n// 80\n```\n\n[[play](https://go.dev/play/p/-xiPjy4JChJ)]\n\n### Attempt\n\nInvokes a function N times until it returns valid output. Returns either the caught error or nil.\n\nWhen the first argument is less than `1`, the function runs until a successful response is returned.\n\n```go\niter, err := lo.Attempt(42, func(i int) error {\n    if i == 5 {\n        return nil\n    }\n\n    return errors.New(\"failed\")\n})\n// 6\n// nil\n\niter, err := lo.Attempt(2, func(i int) error {\n    if i == 5 {\n        return nil\n    }\n\n    return errors.New(\"failed\")\n})\n// 2\n// error \"failed\"\n\niter, err := lo.Attempt(0, func(i int) error {\n    if i < 42 {\n        return errors.New(\"failed\")\n    }\n\n    return nil\n})\n// 43\n// nil\n```\n\nFor more advanced retry strategies (delay, exponential backoff...), please take a look at [cenkalti/backoff](https://github.com/cenkalti/backoff).\n\n[[play](https://go.dev/play/p/3ggJZ2ZKcMj)]\n\n### AttemptWithDelay\n\nInvokes a function N times until it returns valid output, with a pause between each call. Returns either the caught error or nil.\n\nWhen the first argument is less than `1`, the function runs until a successful response is returned.\n\n```go\niter, duration, err := lo.AttemptWithDelay(5, 2*time.Second, func(i int, duration time.Duration) error {\n    if i == 2 {\n        return nil\n    }\n\n    return errors.New(\"failed\")\n})\n// 3\n// ~ 4 seconds\n// nil\n```\n\nFor more advanced retry strategies (delay, exponential backoff...), please take a look at [cenkalti/backoff](https://github.com/cenkalti/backoff).\n\n[[play](https://go.dev/play/p/tVs6CygC7m1)]\n\n### AttemptWhile\n\nInvokes a function N times until it returns valid output. Returns either the caught error or nil, along with a bool value to determine whether the function should be invoked again. It will terminate the invoke immediately if the second return value is false.\n\nWhen the first argument is less than `1`, the function runs until a successful response is returned.\n\n```go\ncount1, err1 := lo.AttemptWhile(5, func(i int) (error, bool) {\n    err := doMockedHTTPRequest(i)\n    if err != nil {\n        if errors.Is(err, ErrBadRequest) { // let's assume ErrBadRequest is a critical error that needs to terminate the invoke\n            return err, false // flag the second return value as false to terminate the invoke\n        }\n\n        return err, true\n    }\n\n    return nil, false\n})\n```\n\nFor more advanced retry strategies (delay, exponential backoff...), please take a look at [cenkalti/backoff](https://github.com/cenkalti/backoff).\n\n[[play](https://go.dev/play/p/1VS7HxlYMOG)]\n\n### AttemptWhileWithDelay\n\nInvokes a function N times until it returns valid output, with a pause between each call. Returns either the caught error or nil, along with a bool value to determine whether the function should be invoked again. It will terminate the invoke immediately if the second return value is false.\n\nWhen the first argument is less than `1`, the function runs until a successful response is returned.\n\n```go\ncount1, time1, err1 := lo.AttemptWhileWithDelay(5, time.Millisecond, func(i int, d time.Duration) (error, bool) {\n    err := doMockedHTTPRequest(i)\n    if err != nil {\n        if errors.Is(err, ErrBadRequest) { // let's assume ErrBadRequest is a critical error that needs to terminate the invoke\n            return err, false // flag the second return value as false to terminate the invoke\n        }\n\n        return err, true\n    }\n\n    return nil, false\n})\n```\n\nFor more advanced retry strategies (delay, exponential backoff...), please take a look at [cenkalti/backoff](https://github.com/cenkalti/backoff).\n\n[[play](https://go.dev/play/p/mhufUjJfLEF)]\n\n### Debounce\n\n`NewDebounce` creates a debounced instance that delays invoking functions given until after wait milliseconds have elapsed, until `cancel` is called.\n\n```go\nf := func() {\n    println(\"Called once after 100ms when debounce stopped invoking!\")\n}\n\ndebounce, cancel := lo.NewDebounce(100 * time.Millisecond, f)\nfor j := 0; j < 10; j++ {\n    debounce()\n}\n\ntime.Sleep(1 * time.Second)\ncancel()\n```\n\n[[play](https://go.dev/play/p/mz32VMK2nqe)]\n\n### DebounceBy\n\n`NewDebounceBy` creates a debounced instance for each distinct key, that delays invoking functions given until after wait milliseconds have elapsed, until `cancel` is called.\n\n```go\nf := func(key string, count int) {\n    println(key + \": Called once after 100ms when debounce stopped invoking!\")\n}\n\ndebounce, cancel := lo.NewDebounceBy(100 * time.Millisecond, f)\nfor j := 0; j < 10; j++ {\n    debounce(\"first key\")\n    debounce(\"second key\")\n}\n\ntime.Sleep(1 * time.Second)\ncancel(\"first key\")\ncancel(\"second key\")\n```\n\n[[play](https://go.dev/play/p/d3Vpt6pxhY8)]\n\n### Throttle\n\nCreates a throttled instance that invokes given functions only once in every interval.\n\nThis returns 2 functions, First one is throttled function and Second one is a function to reset interval.\n\n```go\nf := func() {\n\tprintln(\"Called once in every 100ms\")\n}\n\nthrottle, reset := lo.NewThrottle(100 * time.Millisecond, f)\n\nfor j := 0; j < 10; j++ {\n\tthrottle()\n\ttime.Sleep(30 * time.Millisecond)\n}\n\nreset()\nthrottle()\n```\n\n`NewThrottleWithCount` is NewThrottle with count limit, throttled function will be invoked count times in every interval.\n\n```go\nf := func() {\n\tprintln(\"Called three times in every 100ms\")\n}\n\nthrottle, reset := lo.NewThrottleWithCount(100 * time.Millisecond, f)\n\nfor j := 0; j < 10; j++ {\n\tthrottle()\n\ttime.Sleep(30 * time.Millisecond)\n}\n\nreset()\nthrottle()\n```\n\n`NewThrottleBy` and `NewThrottleByWithCount` are NewThrottle with sharding key, throttled function will be invoked count times in every interval.\n\n```go\nf := func(key string) {\n\tprintln(key, \"Called three times in every 100ms\")\n}\n\nthrottle, reset := lo.NewThrottleByWithCount(100 * time.Millisecond, f)\n\nfor j := 0; j < 10; j++ {\n\tthrottle(\"foo\")\n\ttime.Sleep(30 * time.Millisecond)\n}\n\nreset()\nthrottle()\n```\n\n### Synchronize\n\nWraps the underlying callback in a mutex. It receives an optional mutex.\n\n```go\ns := lo.Synchronize()\n\nfor i := 0; i < 10; i++ {\n    go s.Do(func () {\n        println(\"will be called sequentially\")\n    })\n}\n```\n\nIt is equivalent to:\n\n```go\nmu := sync.Mutex{}\n\nfunc foobar() {\n    mu.Lock()\n    defer mu.Unlock()\n\n    // ...\n}\n```\n\n### Async\n\nExecutes a function in a goroutine and returns the result in a channel.\n\n```go\nch := lo.Async(func() error { time.Sleep(10 * time.Second); return nil })\n// chan error (nil)\n```\n\n### Async{0->6}\n\nExecutes a function in a goroutine and returns the result in a channel.\nFor functions with multiple return values, the results will be returned as a tuple inside the channel.\nFor functions without return, struct{} will be returned in the channel.\n\n```go\nch := lo.Async0(func() { time.Sleep(10 * time.Second) })\n// chan struct{}\n\nch := lo.Async1(func() int {\n  time.Sleep(10 * time.Second);\n  return 42\n})\n// chan int (42)\n\nch := lo.Async2(func() (int, string) {\n  time.Sleep(10 * time.Second);\n  return 42, \"Hello\"\n})\n// chan lo.Tuple2[int, string] ({42, \"Hello\"})\n```\n\n### Transaction\n\nImplements a Saga pattern.\n\n```go\ntransaction := NewTransaction().\n    Then(\n        func(state int) (int, error) {\n            fmt.Println(\"step 1\")\n            return state + 10, nil\n        },\n        func(state int) int {\n            fmt.Println(\"rollback 1\")\n            return state - 10\n        },\n    ).\n    Then(\n        func(state int) (int, error) {\n            fmt.Println(\"step 2\")\n            return state + 15, nil\n        },\n        func(state int) int {\n            fmt.Println(\"rollback 2\")\n            return state - 15\n        },\n    ).\n    Then(\n        func(state int) (int, error) {\n            fmt.Println(\"step 3\")\n\n            if true {\n                return state, errors.New(\"error\")\n            }\n\n            return state + 42, nil\n        },\n        func(state int) int {\n            fmt.Println(\"rollback 3\")\n            return state - 42\n        },\n    )\n\n_, _ = transaction.Process(-5)\n\n// Output:\n// step 1\n// step 2\n// step 3\n// rollback 2\n// rollback 1\n```\n\n### WaitFor\n\nRuns periodically until a condition is validated.\n\n```go\nalwaysTrue := func(i int) bool { return true }\nalwaysFalse := func(i int) bool { return false }\nlaterTrue := func(i int) bool {\n    return i > 5\n}\n\niterations, duration, ok := lo.WaitFor(alwaysTrue, 10*time.Millisecond, 2 * time.Millisecond)\n// 1\n// 1ms\n// true\n\niterations, duration, ok := lo.WaitFor(alwaysFalse, 10*time.Millisecond, time.Millisecond)\n// 10\n// 10ms\n// false\n\niterations, duration, ok := lo.WaitFor(laterTrue, 10*time.Millisecond, time.Millisecond)\n// 7\n// 7ms\n// true\n\niterations, duration, ok := lo.WaitFor(laterTrue, 10*time.Millisecond, 5*time.Millisecond)\n// 2\n// 10ms\n// false\n```\n\n[[play](https://go.dev/play/p/t_wTDmubbK3)]\n\n### WaitForWithContext\n\nRuns periodically until a condition is validated or context is invalid.\n\nThe condition receives also the context, so it can invalidate the process in the condition checker\n\n```go\nctx := context.Background()\n\nalwaysTrue := func(_ context.Context, i int) bool { return true }\nalwaysFalse := func(_ context.Context, i int) bool { return false }\nlaterTrue := func(_ context.Context, i int) bool {\n    return i >= 5\n}\n\niterations, duration, ok := lo.WaitForWithContext(ctx, alwaysTrue, 10*time.Millisecond, 2 * time.Millisecond)\n// 1\n// 1ms\n// true\n\niterations, duration, ok := lo.WaitForWithContext(ctx, alwaysFalse, 10*time.Millisecond, time.Millisecond)\n// 10\n// 10ms\n// false\n\niterations, duration, ok := lo.WaitForWithContext(ctx, laterTrue, 10*time.Millisecond, time.Millisecond)\n// 5\n// 5ms\n// true\n\niterations, duration, ok := lo.WaitForWithContext(ctx, laterTrue, 10*time.Millisecond, 5*time.Millisecond)\n// 2\n// 10ms\n// false\n\nexpiringCtx, cancel := context.WithTimeout(ctx, 5*time.Millisecond)\niterations, duration, ok := lo.WaitForWithContext(expiringCtx, alwaysFalse, 100*time.Millisecond, time.Millisecond)\n// 5\n// 5.1ms\n// false\n```\n\n[[play](https://go.dev/play/p/t_wTDmubbK3)]\n\n### Validate\n\nHelper function that creates an error when a condition is not met.\n\n```go\nslice := []string{\"a\"}\nval := lo.Validate(len(slice) == 0, \"Slice should be empty but contains %v\", slice)\n// error(\"Slice should be empty but contains [a]\")\n\nslice := []string{}\nval := lo.Validate(len(slice) == 0, \"Slice should be empty but contains %v\", slice)\n// nil\n```\n\n[[play](https://go.dev/play/p/vPyh51XpCBt)]\n\n### Must\n\nWraps a function call and panics if second argument is `error` or `false`, returns the value otherwise.\n\n```go\nval := lo.Must(time.Parse(\"2006-01-02\", \"2022-01-15\"))\n// 2022-01-15\n\nval := lo.Must(time.Parse(\"2006-01-02\", \"bad-value\"))\n// panics\n```\n\n[[play](https://go.dev/play/p/TMoWrRp3DyC)]\n\n### Must{0->6}\n\nMust\\* has the same behavior as Must but returns multiple values.\n\n```go\nfunc example0() (error)\nfunc example1() (int, error)\nfunc example2() (int, string, error)\nfunc example3() (int, string, time.Date, error)\nfunc example4() (int, string, time.Date, bool, error)\nfunc example5() (int, string, time.Date, bool, float64, error)\nfunc example6() (int, string, time.Date, bool, float64, byte, error)\n\nlo.Must0(example0())\nval1 := lo.Must1(example1())    // alias to Must\nval1, val2 := lo.Must2(example2())\nval1, val2, val3 := lo.Must3(example3())\nval1, val2, val3, val4 := lo.Must4(example4())\nval1, val2, val3, val4, val5 := lo.Must5(example5())\nval1, val2, val3, val4, val5, val6 := lo.Must6(example6())\n```\n\nYou can wrap functions like `func (...) (..., ok bool)`.\n\n```go\n// math.Signbit(float64) bool\nlo.Must0(math.Signbit(v))\n\n// bytes.Cut([]byte,[]byte) ([]byte, []byte, bool)\nbefore, after := lo.Must2(bytes.Cut(s, sep))\n```\n\nYou can give context to the panic message by adding some printf-like arguments.\n\n```go\nval, ok := lo.Find(myString, func(i string) bool {\n    return i == requiredChar\n})\nlo.Must0(ok, \"'%s' must always contain '%s'\", myString, requiredChar)\n\nlist := []int{0, 1, 2}\nitem := 5\nlo.Must0(lo.Contains(list, item), \"'%s' must always contain '%s'\", list, item)\n...\n```\n\n[[play](https://go.dev/play/p/TMoWrRp3DyC)]\n\n### Try\n\nCalls the function and returns false in case of error and panic.\n\n```go\nok := lo.Try(func() error {\n    panic(\"error\")\n    return nil\n})\n// false\n\nok := lo.Try(func() error {\n    return nil\n})\n// true\n\nok := lo.Try(func() error {\n    return errors.New(\"error\")\n})\n// false\n```\n\n[[play](https://go.dev/play/p/mTyyWUvn9u4)]\n\n### Try{0->6}\n\nThe same behavior as `Try`, but the callback returns 2 variables.\n\n```go\nok := lo.Try2(func() (string, error) {\n    panic(\"error\")\n    return \"\", nil\n})\n// false\n```\n\n[[play](https://go.dev/play/p/mTyyWUvn9u4)]\n\n### TryOr\n\nCalls the function and return a default value in case of error and on panic.\n\n```go\nstr, ok := lo.TryOr(func() (string, error) {\n    panic(\"error\")\n    return \"hello\", nil\n}, \"world\")\n// world\n// false\n\nstr, ok := lo.TryOr(func() error {\n    return \"hello\", nil\n}, \"world\")\n// hello\n// true\n\nstr, ok := lo.TryOr(func() error {\n    return \"hello\", errors.New(\"error\")\n}, \"world\")\n// world\n// false\n```\n\n[[play](https://go.dev/play/p/B4F7Wg2Zh9X)]\n\n### TryOr{0->6}\n\nThe same behavior as `TryOr`, but the callback returns `X` variables.\n\n```go\nstr, nbr, ok := lo.TryOr2(func() (string, int, error) {\n    panic(\"error\")\n    return \"hello\", 42, nil\n}, \"world\", 21)\n// world\n// 21\n// false\n```\n\n[[play](https://go.dev/play/p/B4F7Wg2Zh9X)]\n\n### TryWithErrorValue\n\nThe same behavior as `Try`, but also returns the value passed to panic.\n\n```go\nerr, ok := lo.TryWithErrorValue(func() error {\n    panic(\"error\")\n    return nil\n})\n// \"error\", false\n```\n\n[[play](https://go.dev/play/p/Kc7afQIT2Fs)]\n\n### TryCatch\n\nThe same behavior as `Try`, but calls the catch function in case of error.\n\n```go\ncaught := false\n\nok := lo.TryCatch(func() error {\n    panic(\"error\")\n    return nil\n}, func() {\n    caught = true\n})\n// false\n// caught == true\n```\n\n[[play](https://go.dev/play/p/PnOON-EqBiU)]\n\n### TryCatchWithErrorValue\n\nThe same behavior as `TryWithErrorValue`, but calls the catch function in case of error.\n\n```go\ncaught := false\n\nok := lo.TryCatchWithErrorValue(func() error {\n    panic(\"error\")\n    return nil\n}, func(val any) {\n    caught = val == \"error\"\n})\n// false\n// caught == true\n```\n\n[[play](https://go.dev/play/p/8Pc9gwX_GZO)]\n\n### ErrorsAs\n\nA shortcut for:\n\n```go\nerr := doSomething()\n\nvar rateLimitErr *RateLimitError\nif ok := errors.As(err, &rateLimitErr); ok {\n    // retry later\n}\n```\n\nsingle line `lo` helper:\n\n```go\nerr := doSomething()\n\nif rateLimitErr, ok := lo.ErrorsAs[*RateLimitError](err); ok {\n    // retry later\n}\n```\n\n[[play](https://go.dev/play/p/8wk5rH8UfrE)]\n\n### Assert\n\nDoes nothing when the condition is `true`, otherwise it panics with an optional message.\n\nThink twice before using it, given that [Go intentionally omits assertions from its standard library](https://go.dev/doc/faq#assertions).\n\n```go\nage := getUserAge()\n\nlo.Assert(age >= 15)\n```\n\n```go\nage := getUserAge()\n\nlo.Assert(age >= 15, \"user age must be >= 15\")\n```\n\n[[play](https://go.dev/play/p/Xv8LLKBMNwI)]\n\n### Assertf\n\nLike `Assert`, but with `fmt.Printf`-like formatting.\n\nThink twice before using it, given that [Go intentionally omits assertions from its standard library](https://go.dev/doc/faq#assertions).\n\n```go\nage := getUserAge()\n\nlo.Assertf(age >= 15, \"user age must be >= 15, got %d\", age)\n```\n\n[[play](https://go.dev/play/p/TVPEmVcyrdY)]\n\n## 🛩 Benchmark\n\nWe executed a simple benchmark with a dead-simple `lo.Map` loop:\n\nSee the full implementation [here](./map_benchmark_test.go).\n\n```go\n_ = lo.Map[int64](arr, func(x int64, i int) string {\n    return strconv.FormatInt(x, 10)\n})\n```\n\n**Result:**\n\nHere is a comparison between `lo.Map`, `lop.Map`, `go-funk` library and a simple Go `for` loop.\n\n```shell\n$ go test -benchmem -bench ./...\ngoos: linux\ngoarch: amd64\npkg: github.com/samber/lo\ncpu: Intel(R) Core(TM) i5-7267U CPU @ 3.10GHz\ncpu: Intel(R) Core(TM) i7 CPU         920  @ 2.67GHz\nBenchmarkMap/lo.Map-8         \t       8\t 132728237 ns/op\t39998945 B/op\t 1000002 allocs/op\nBenchmarkMap/lop.Map-8        \t       2\t 503947830 ns/op\t119999956 B/op\t 3000007 allocs/op\nBenchmarkMap/reflect-8        \t       2\t 826400560 ns/op\t170326512 B/op\t 4000042 allocs/op\nBenchmarkMap/for-8            \t       9\t 126252954 ns/op\t39998674 B/op\t 1000001 allocs/op\nPASS\nok  \tgithub.com/samber/lo\t6.657s\n```\n\n- `lo.Map` is way faster (x7) than `go-funk`, a reflection-based Map implementation.\n- `lo.Map` has the same allocation profile as `for`.\n- `lo.Map` is 4% slower than `for`.\n- `lop.Map` is slower than `lo.Map` because it implies more memory allocation and locks. `lop.Map` is useful for long-running callbacks, such as i/o bound processing.\n- `for` beats other implementations for memory and CPU.\n\n## 🤝 Contributing\n\n- Ping me on Twitter [@samuelberthe](https://twitter.com/samuelberthe) (DMs, mentions, whatever :))\n- Fork the [project](https://github.com/samber/lo)\n- Fix [open issues](https://github.com/samber/lo/issues) or request new features\n\nDon't hesitate ;)\n\nHelper naming: helpers must be self-explanatory and respect standards (other languages, libraries...). Feel free to suggest many names in your contributions.\n\n```bash\n# Install some dev dependencies\nmake tools\n\n# Run tests\nmake test\n# or\nmake watch-test\n```\n\n## 👤 Contributors\n\n![Contributors](https://contrib.rocks/image?repo=samber/lo)\n\n## 💫 Show your support\n\nGive a ⭐️ if this project helped you!\n\n[![GitHub Sponsors](https://img.shields.io/github/sponsors/samber?style=for-the-badge)](https://github.com/sponsors/samber)\n\n## 📝 License\n\nCopyright © 2022 [Samuel Berthe](https://github.com/samber).\n\nThis project is under [MIT](./LICENSE) license.\n"
  },
  {
    "path": "benchmark/CLAUDE.md",
    "content": "# Benchmark Guidelines\n\n## File Organization\n\nBenchmark files follow the naming convention:\n\n```\nbenchmark/{package}_{category}_bench_test.go\n```\n\n- **package**: `core`, `it`, `mutable`, `parallel`\n- **category**: `slice`, `map`, `find`, `intersect`, `math`, `string`, `type_manipulation`, `condition`, `tuples`\n\nShared data generators live in `helpers_test.go` (and `it_helpers_test.go` for `go1.23` iter helpers).\n\n## Performance PRs\n\nEvery performance improvement PR **must** include a `benchstat` comparison in the PR description. Without before/after numbers, the PR will not be merged.\n\n### How to produce a benchstat report\n\n1. Check out `master` and run the \"before\" benchmarks:\n   ```bash\n   git stash && git switch master\n   go test ./benchmark/... -bench=BenchmarkXxx -benchmem -count=6 -cpu=1 | tee /tmp/before.txt\n   ```\n\n2. Switch to your branch and run the \"after\" benchmarks:\n   ```bash\n   git switch my-branch && git stash pop\n   go test ./benchmark/... -bench=BenchmarkXxx -benchmem -count=6 -cpu=1 | tee /tmp/after.txt\n   ```\n\n3. Compare with `benchstat`:\n   ```bash\n   benchstat /tmp/before.txt /tmp/after.txt\n   ```\n\n4. Paste the full `benchstat` output in the PR description.\n\n### What to include in the PR description\n\n- The optimization technique (pre-allocation, direct indexing, value receivers, etc.)\n- The `benchstat` table showing time/op, allocs/op, and bytes/op deltas\n- An explanation of **why** the change is faster, not just **what** changed\n\n### When NOT to submit a performance PR\n\n- If `benchstat` shows no statistically significant improvement (p >= 0.05)\n- If the improvement is < 5% and adds code complexity\n- If the change regresses other benchmarks — always run the full suite, not just the targeted benchmark\n\n## Adding New Benchmarks\n\nWhen adding a new helper function to the library, add a corresponding benchmark in the appropriate `{package}_{category}_bench_test.go` file. Use the standard parametric pattern:\n\n```go\nfunc BenchmarkMyFunc(b *testing.B) {\n    for _, n := range lengths {\n        data := genSliceInt(n)\n        b.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n            for i := 0; i < b.N; i++ {\n                _ = lo.MyFunc(data, ...)\n            }\n        })\n    }\n}\n```\n\nUse shared generators from `helpers_test.go` — do not create local generator functions.\n"
  },
  {
    "path": "benchmark/core_condition_bench_test.go",
    "content": "package benchmark\n\nimport (\n\t\"testing\"\n\n\t\"github.com/samber/lo\"\n)\n\nfunc BenchmarkIf(b *testing.B) {\n\tfor i := 0; i < b.N; i++ {\n\t\t_ = lo.If(i%2 == 0, \"even\").Else(\"odd\")\n\t}\n}\n\nfunc BenchmarkIfElseIf(b *testing.B) {\n\tfor i := 0; i < b.N; i++ {\n\t\t_ = lo.If(i%3 == 0, \"fizz\").\n\t\t\tElseIf(i%3 == 1, \"buzz\").\n\t\t\tElse(\"none\")\n\t}\n}\n\nfunc BenchmarkIfElseIfChain(b *testing.B) {\n\tfor i := 0; i < b.N; i++ {\n\t\t_ = lo.If(i%5 == 0, \"a\").\n\t\t\tElseIf(i%5 == 1, \"b\").\n\t\t\tElseIf(i%5 == 2, \"c\").\n\t\t\tElseIf(i%5 == 3, \"d\").\n\t\t\tElse(\"e\")\n\t}\n}\n\nfunc BenchmarkSwitch(b *testing.B) {\n\tfor i := 0; i < b.N; i++ {\n\t\t_ = lo.Switch[int, string](i%3).\n\t\t\tCase(0, \"zero\").\n\t\t\tCase(1, \"one\").\n\t\t\tDefault(\"other\")\n\t}\n}\n\nfunc BenchmarkSwitchChain(b *testing.B) {\n\tfor i := 0; i < b.N; i++ {\n\t\t_ = lo.Switch[int, string](i%5).\n\t\t\tCase(0, \"zero\").\n\t\t\tCase(1, \"one\").\n\t\t\tCase(2, \"two\").\n\t\t\tCase(3, \"three\").\n\t\t\tDefault(\"other\")\n\t}\n}\n"
  },
  {
    "path": "benchmark/core_find_bench_test.go",
    "content": "package benchmark\n\nimport (\n\t\"strconv\"\n\t\"testing\"\n\n\t\"github.com/samber/lo\"\n)\n\nfunc BenchmarkIndexOf(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\ttarget := ints[n-1] // worst case: last element\n\t\tb.Run(strconv.Itoa(n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.IndexOf(ints, target)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkLastIndexOf(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\ttarget := ints[0]\n\t\tb.Run(strconv.Itoa(n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.LastIndexOf(ints, target)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkHasPrefix(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tprefix := ints[:n/10+1]\n\t\tb.Run(strconv.Itoa(n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.HasPrefix(ints, prefix)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkHasSuffix(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tsuffix := ints[n-n/10-1:]\n\t\tb.Run(strconv.Itoa(n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.HasSuffix(ints, suffix)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkFind(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\ttarget := ints[n-1]\n\t\tb.Run(strconv.Itoa(n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_, _ = lo.Find(ints, func(v int) bool { return v == target })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkFindIndexOf(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\ttarget := ints[n-1]\n\t\tb.Run(strconv.Itoa(n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_, _, _ = lo.FindIndexOf(ints, func(v int) bool { return v == target })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkFindLastIndexOf(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\ttarget := ints[0]\n\t\tb.Run(strconv.Itoa(n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_, _, _ = lo.FindLastIndexOf(ints, func(v int) bool { return v == target })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkFindOrElse(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tb.Run(strconv.Itoa(n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.FindOrElse(ints, -1, func(v int) bool { return v == -999 })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkFindKey(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tm := genMap(n)\n\t\tb.Run(strconv.Itoa(n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_, _ = lo.FindKey(m, n/2)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkFindKeyBy(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tm := genMap(n)\n\t\tb.Run(strconv.Itoa(n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_, _ = lo.FindKeyBy(m, func(_ string, v int) bool { return v == n/2 })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkFindUniques(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tb.Run(strconv.Itoa(n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.FindUniques(ints)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkFindUniquesBy(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tb.Run(strconv.Itoa(n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.FindUniquesBy(ints, func(v int) int { return v % 50 })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkFindDuplicates(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tb.Run(strconv.Itoa(n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.FindDuplicates(ints)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkFindDuplicatesBy(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tb.Run(strconv.Itoa(n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.FindDuplicatesBy(ints, func(v int) int { return v % 50 })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkMin(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tb.Run(strconv.Itoa(n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.Min(ints)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkMinIndex(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tb.Run(strconv.Itoa(n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_, _ = lo.MinIndex(ints)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkMinBy(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tb.Run(strconv.Itoa(n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.MinBy(ints, func(a, b int) bool { return a < b })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkMinIndexBy(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tb.Run(strconv.Itoa(n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_, _ = lo.MinIndexBy(ints, func(a, b int) bool { return a < b })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkMax(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tb.Run(strconv.Itoa(n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.Max(ints)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkMaxIndex(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tb.Run(strconv.Itoa(n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_, _ = lo.MaxIndex(ints)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkMaxBy(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tb.Run(strconv.Itoa(n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.MaxBy(ints, func(a, b int) bool { return a > b })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkMaxIndexBy(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tb.Run(strconv.Itoa(n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_, _ = lo.MaxIndexBy(ints, func(a, b int) bool { return a > b })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkFirst(b *testing.B) {\n\tints := genSliceInt(100)\n\tfor i := 0; i < b.N; i++ {\n\t\t_, _ = lo.First(ints)\n\t}\n}\n\nfunc BenchmarkFirstOrEmpty(b *testing.B) {\n\tints := genSliceInt(100)\n\tfor i := 0; i < b.N; i++ {\n\t\t_ = lo.FirstOrEmpty(ints)\n\t}\n}\n\nfunc BenchmarkLast(b *testing.B) {\n\tints := genSliceInt(100)\n\tfor i := 0; i < b.N; i++ {\n\t\t_, _ = lo.Last(ints)\n\t}\n}\n\nfunc BenchmarkLastOrEmpty(b *testing.B) {\n\tints := genSliceInt(100)\n\tfor i := 0; i < b.N; i++ {\n\t\t_ = lo.LastOrEmpty(ints)\n\t}\n}\n\nfunc BenchmarkNth(b *testing.B) {\n\tints := genSliceInt(100)\n\tfor i := 0; i < b.N; i++ {\n\t\t_, _ = lo.Nth(ints, 50)\n\t}\n}\n\nfunc BenchmarkSample(b *testing.B) {\n\tints := genSliceInt(100)\n\tfor i := 0; i < b.N; i++ {\n\t\t_ = lo.Sample(ints)\n\t}\n}\n\nfunc BenchmarkSamples(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tb.Run(strconv.Itoa(n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.Samples(ints, n/4)\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "benchmark/core_intersect_bench_test.go",
    "content": "package benchmark\n\nimport (\n\t\"strconv\"\n\t\"testing\"\n\n\t\"github.com/samber/lo\"\n)\n\nfunc BenchmarkContains(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\ttarget := ints[n-1]\n\t\tb.Run(strconv.Itoa(n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.Contains(ints, target)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkContainsBy(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\ttarget := ints[n-1]\n\t\tb.Run(strconv.Itoa(n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.ContainsBy(ints, func(v int) bool { return v == target })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkEvery(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tsubset := ints[:n/2]\n\t\tb.Run(strconv.Itoa(n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.Every(ints, subset)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkEveryBy(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tb.Run(strconv.Itoa(n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.EveryBy(ints, func(v int) bool { return v >= 0 })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkSome(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tsubset := []int{ints[n-1]}\n\t\tb.Run(strconv.Itoa(n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.Some(ints, subset)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkSomeBy(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tb.Run(strconv.Itoa(n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.SomeBy(ints, func(v int) bool { return v < 0 })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkNone(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tsubset := []int{-1, -2, -3}\n\t\tb.Run(strconv.Itoa(n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.None(ints, subset)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkNoneBy(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tb.Run(strconv.Itoa(n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.NoneBy(ints, func(v int) bool { return v < 0 })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkIntersect(b *testing.B) {\n\tfor _, n := range lengths {\n\t\ta := genSliceInt(n)\n\t\tc := genSliceInt(n)\n\t\tb.Run(strconv.Itoa(n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.Intersect(a, c)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkIntersectBy(b *testing.B) {\n\tfor _, n := range lengths {\n\t\ta := genSliceInt(n)\n\t\tc := genSliceInt(n)\n\t\tb.Run(strconv.Itoa(n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.IntersectBy(func(v int) int { return v }, a, c)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkUnion(b *testing.B) {\n\tfor _, n := range lengths {\n\t\ta := genSliceInt(n)\n\t\tc := genSliceInt(n)\n\t\tb.Run(strconv.Itoa(n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.Union(a, c)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkWithout(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tb.Run(strconv.Itoa(n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.Without(ints, 1, 2, 3, 4, 5)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkWithoutBy(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tb.Run(strconv.Itoa(n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.WithoutBy(ints, func(v int) int { return v % 100 }, 1, 2, 3, 4, 5)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkWithoutEmpty(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\t// sprinkle some zeroes\n\t\tfor j := 0; j < n/10; j++ {\n\t\t\tints[j*10] = 0\n\t\t}\n\t\tb.Run(strconv.Itoa(n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.WithoutEmpty(ints) //nolint:staticcheck\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkWithoutNth(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tb.Run(strconv.Itoa(n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.WithoutNth(ints, 0, n/2, n-1)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkElementsMatch(b *testing.B) {\n\tfor _, n := range lengths {\n\t\ta := genSliceInt(n)\n\t\tc := make([]int, n)\n\t\tcopy(c, a)\n\t\tb.Run(strconv.Itoa(n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.ElementsMatch(a, c)\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "benchmark/core_map_bench_test.go",
    "content": "package benchmark\n\nimport (\n\t\"strconv\"\n\t\"testing\"\n\n\t\"github.com/samber/lo\"\n\tlop \"github.com/samber/lo/parallel\"\n\t\"github.com/thoas/go-funk\"\n)\n\nfunc BenchmarkKeys(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tm := genMap(n)\n\t\tb.Run(strconv.Itoa(n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.Keys(m)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkUniqKeys(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tm1 := genMap(n)\n\t\tm2 := genMap(n)\n\t\tb.Run(strconv.Itoa(n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.UniqKeys(m1, m2)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkHasKey(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tm := genMap(n)\n\t\tkey := strconv.Itoa(n / 2)\n\t\tb.Run(strconv.Itoa(n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.HasKey(m, key)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkValues(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tm := genMap(n)\n\t\tb.Run(strconv.Itoa(n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.Values(m)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkUniqValues(b *testing.B) {\n\tm := []map[int64]int64{\n\t\tmapGenerator(1000),\n\t\tmapGenerator(1000),\n\t\tmapGenerator(1000),\n\t}\n\tb.Run(\"lo.UniqValues\", func(b *testing.B) {\n\t\tfor n := 0; n < b.N; n++ {\n\t\t\t_ = lo.UniqValues(m...)\n\t\t}\n\t})\n}\n\nfunc BenchmarkValueOr(b *testing.B) {\n\tm := genMap(100)\n\tb.Run(\"hit\", func(b *testing.B) {\n\t\tfor i := 0; i < b.N; i++ {\n\t\t\t_ = lo.ValueOr(m, \"50\", -1)\n\t\t}\n\t})\n\tb.Run(\"miss\", func(b *testing.B) {\n\t\tfor i := 0; i < b.N; i++ {\n\t\t\t_ = lo.ValueOr(m, \"missing\", -1)\n\t\t}\n\t})\n}\n\nfunc BenchmarkPickBy(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tm := genMap(n)\n\t\tb.Run(strconv.Itoa(n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.PickBy(m, func(_ string, v int) bool { return v%2 == 0 })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkPickByKeys(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tm := genMap(n)\n\t\tkeys := make([]string, n/2)\n\t\tfor i := range keys {\n\t\t\tkeys[i] = strconv.Itoa(i * 2)\n\t\t}\n\t\tb.Run(strconv.Itoa(n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.PickByKeys(m, keys)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkPickByValues(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tm := genMap(n)\n\t\tvals := make([]int, n/2)\n\t\tfor i := range vals {\n\t\t\tvals[i] = i * 2\n\t\t}\n\t\tb.Run(strconv.Itoa(n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.PickByValues(m, vals)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkOmitBy(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tm := genMap(n)\n\t\tb.Run(strconv.Itoa(n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.OmitBy(m, func(_ string, v int) bool { return v%2 == 0 })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkOmitByKeys(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tm := genMap(n)\n\t\tkeys := make([]string, n/4)\n\t\tfor i := range keys {\n\t\t\tkeys[i] = strconv.Itoa(i)\n\t\t}\n\t\tb.Run(strconv.Itoa(n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.OmitByKeys(m, keys)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkOmitByValues(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tm := genMap(n)\n\t\tvals := make([]int, n/4)\n\t\tfor i := range vals {\n\t\t\tvals[i] = i\n\t\t}\n\t\tb.Run(strconv.Itoa(n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.OmitByValues(m, vals)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkEntries(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tm := genMap(n)\n\t\tb.Run(strconv.Itoa(n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.Entries(m)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkFromEntries(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tentries := make([]lo.Entry[string, int], n)\n\t\tfor i := 0; i < n; i++ {\n\t\t\tentries[i] = lo.Entry[string, int]{Key: strconv.Itoa(i), Value: i}\n\t\t}\n\t\tb.Run(strconv.Itoa(n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.FromEntries(entries)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkInvert(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tm := genMap(n)\n\t\tb.Run(strconv.Itoa(n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.Invert(m)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkAssign(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tm1 := genMap(n)\n\t\tm2 := genMap(n)\n\t\tb.Run(strconv.Itoa(n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.Assign(m1, m2)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkChunkEntries(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tm := genMap(n)\n\t\tb.Run(strconv.Itoa(n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.ChunkEntries(m, 5)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkMapKeys(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tm := genMap(n)\n\t\tb.Run(strconv.Itoa(n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.MapKeys(m, func(_ int, k string) string { return k + \"_x\" })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkMapValues(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tm := genMap(n)\n\t\tb.Run(strconv.Itoa(n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.MapValues(m, func(v int, _ string) int { return v * 2 })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkMapEntries(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tm := genMap(n)\n\t\tb.Run(strconv.Itoa(n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.MapEntries(m, func(k string, v int) (string, int) { return k, v * 2 })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkMapToSlice(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tm := genMap(n)\n\t\tb.Run(strconv.Itoa(n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.MapToSlice(m, func(k string, v int) string { return k + \"=\" + strconv.Itoa(v) })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkFilterMapToSlice(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tm := genMap(n)\n\t\tb.Run(strconv.Itoa(n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.FilterMapToSlice(m, func(k string, v int) (string, bool) { return k, v%2 == 0 })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkFilterKeys(b *testing.B) {\n\tm := mapGenerator(1000)\n\tb.Run(\"lo.FilterKeys\", func(b *testing.B) {\n\t\tfor n := 0; n < b.N; n++ {\n\t\t\t_ = lo.FilterKeys(m, func(k, v int64) bool { return k%2 == 0 })\n\t\t}\n\t})\n}\n\nfunc BenchmarkFilterValues(b *testing.B) {\n\tm := mapGenerator(1000)\n\tb.Run(\"lo.FilterValues\", func(b *testing.B) {\n\t\tfor n := 0; n < b.N; n++ {\n\t\t\t_ = lo.FilterValues(m, func(k, v int64) bool { return v%2 == 0 })\n\t\t}\n\t})\n}\n\n// ---------------------------------------------------------------------------\n// Comparison benchmarks (lo vs lop vs go-funk vs manual loop)\n// ---------------------------------------------------------------------------\n\nfunc BenchmarkMapComparison(b *testing.B) {\n\tarr := sliceGenerator(1000000)\n\n\tb.Run(\"lo.Map\", func(b *testing.B) {\n\t\tfor n := 0; n < b.N; n++ {\n\t\t\t_ = lo.Map(arr, func(x int64, i int) string {\n\t\t\t\treturn strconv.FormatInt(x, 10)\n\t\t\t})\n\t\t}\n\t})\n\n\tb.Run(\"lop.Map\", func(b *testing.B) {\n\t\tfor n := 0; n < b.N; n++ {\n\t\t\t_ = lop.Map(arr, func(x int64, i int) string {\n\t\t\t\treturn strconv.FormatInt(x, 10)\n\t\t\t})\n\t\t}\n\t})\n\n\tb.Run(\"reflect\", func(b *testing.B) {\n\t\tfor n := 0; n < b.N; n++ {\n\t\t\t_ = funk.Map(arr, func(x int64) string {\n\t\t\t\treturn strconv.FormatInt(x, 10)\n\t\t\t})\n\t\t}\n\t})\n\n\tb.Run(\"for\", func(b *testing.B) {\n\t\tfor n := 0; n < b.N; n++ {\n\t\t\tresults := make([]string, len(arr))\n\n\t\t\tfor i, item := range arr {\n\t\t\t\tresult := strconv.FormatInt(item, 10)\n\t\t\t\tresults[i] = result\n\t\t\t}\n\t\t}\n\t})\n}\n"
  },
  {
    "path": "benchmark/core_math_bench_test.go",
    "content": "package benchmark\n\nimport (\n\t\"strconv\"\n\t\"testing\"\n\n\t\"github.com/samber/lo\"\n)\n\nfunc BenchmarkRange(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tb.Run(strconv.Itoa(n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.Range(n)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkRangeFrom(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tb.Run(strconv.Itoa(n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.RangeFrom(0, n)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkRangeWithSteps(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tb.Run(strconv.Itoa(n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.RangeWithSteps(0, n, 1)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkClamp(b *testing.B) {\n\tfor i := 0; i < b.N; i++ {\n\t\t_ = lo.Clamp(15, 0, 10)\n\t}\n}\n\nfunc BenchmarkSum(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tb.Run(strconv.Itoa(n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.Sum(ints)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkSumBy(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tb.Run(strconv.Itoa(n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.SumBy(ints, func(v int) int { return v })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkProduct(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tfloats := make([]float64, n)\n\t\tfor j := range floats {\n\t\t\tfloats[j] = 1.0001\n\t\t}\n\t\tb.Run(strconv.Itoa(n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.Product(floats)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkProductBy(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tb.Run(strconv.Itoa(n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.ProductBy(ints, func(v int) float64 { return float64(v) * 0.001 })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkMean(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tb.Run(strconv.Itoa(n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.Mean(ints)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkMeanBy(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tb.Run(strconv.Itoa(n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.MeanBy(ints, func(v int) int { return v })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkMode(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tb.Run(strconv.Itoa(n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.Mode(ints)\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "benchmark/core_slice_bench_test.go",
    "content": "package benchmark\n\nimport (\n\t\"fmt\"\n\t\"sort\"\n\t\"strconv\"\n\t\"testing\"\n\n\t\"github.com/samber/lo\"\n)\n\nfunc BenchmarkChunk(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tstrs := genSliceString(n)\n\t\tb.Run(fmt.Sprintf(\"strings_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.Chunk(strs, 5)\n\t\t\t}\n\t\t})\n\t}\n\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tb.Run(fmt.Sprintf(\"ints%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.Chunk(ints, 5)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkFlatten(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := make([][]int, 0, n)\n\t\tfor i := 0; i < n; i++ {\n\t\t\tints = append(ints, genSliceInt(n))\n\t\t}\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.Flatten(ints)\n\t\t\t}\n\t\t})\n\t}\n\n\tfor _, n := range lengths {\n\t\tstrs := make([][]string, 0, n)\n\t\tfor i := 0; i < n; i++ {\n\t\t\tstrs = append(strs, genSliceString(n))\n\t\t}\n\t\tb.Run(fmt.Sprintf(\"strings_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.Flatten(strs)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkDrop(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tstrs := genSliceString(n)\n\t\tb.Run(fmt.Sprintf(\"strings_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.Drop(strs, n/4)\n\t\t\t}\n\t\t})\n\t}\n\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tb.Run(fmt.Sprintf(\"ints%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.Drop(ints, n/4)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkDropRight(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tstrs := genSliceString(n)\n\t\tb.Run(fmt.Sprintf(\"strings_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.DropRight(strs, n/4)\n\t\t\t}\n\t\t})\n\t}\n\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tb.Run(fmt.Sprintf(\"ints%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.DropRight(ints, n/4)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkDropWhile(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tstrs := genSliceString(n)\n\t\tb.Run(fmt.Sprintf(\"strings_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.DropWhile(strs, func(v string) bool { return len(v) < 4 })\n\t\t\t}\n\t\t})\n\t}\n\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tb.Run(fmt.Sprintf(\"ints%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.DropWhile(ints, func(v int) bool { return i < 10_000 })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkDropRightWhile(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tstrs := genSliceString(n)\n\t\tb.Run(fmt.Sprintf(\"strings_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.DropRightWhile(strs, func(v string) bool { return len(v) < 4 })\n\t\t\t}\n\t\t})\n\t}\n\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tb.Run(fmt.Sprintf(\"ints%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.DropRightWhile(ints, func(v int) bool { return i < 10_000 })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkDropByIndex(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tfor _, indexes := range [][]int{\n\t\t\t{0},\n\t\t\t{0, n / 2, n / 4, n - 1},\n\t\t\tlo.Range(n),\n\t\t} {\n\t\t\tname := fmt.Sprintf(\"size_%d/indexes_%d/\", n, len(indexes))\n\n\t\t\tstrs := genSliceString(n)\n\t\t\tb.Run(name+\"strings\", func(b *testing.B) {\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = lo.DropByIndex(strs, indexes...)\n\t\t\t\t}\n\t\t\t})\n\n\t\t\tints := genSliceInt(n)\n\t\t\tb.Run(name+\"ints\", func(b *testing.B) {\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = lo.DropByIndex(ints, indexes...)\n\t\t\t\t}\n\t\t\t})\n\n\t\t\theavy := genSliceHeavy(n)\n\t\t\tb.Run(name+\"heavy\", func(b *testing.B) {\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = lo.DropByIndex(heavy, indexes...)\n\t\t\t\t}\n\t\t\t})\n\t\t}\n\t}\n}\n\nfunc BenchmarkReplace(b *testing.B) {\n\tlengths := []int{1_000, 10_000, 100_000}\n\tfor _, n := range lengths {\n\t\tstrs := genSliceString(n)\n\t\tb.Run(fmt.Sprintf(\"strings_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.Replace(strs, strs[n/4], \"123123\", 10)\n\t\t\t}\n\t\t})\n\t}\n\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tb.Run(fmt.Sprintf(\"ints%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.Replace(ints, ints[n/4], 123123, 10)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkReject(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tstrs := genSliceString(n)\n\t\tb.Run(fmt.Sprintf(\"strings_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.Reject(strs, func(v string, _ int) bool { return len(v) < 3 })\n\t\t\t}\n\t\t})\n\t}\n\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.Reject(ints, func(v, _ int) bool { return v < 50000 })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkRejectErr(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tstrs := genSliceString(n)\n\t\tb.Run(fmt.Sprintf(\"strings_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_, _ = lo.RejectErr(strs, func(v string, _ int) (bool, error) { return len(v) < 3, nil })\n\t\t\t}\n\t\t})\n\t}\n\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_, _ = lo.RejectErr(ints, func(v, _ int) (bool, error) { return v < 50000, nil })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkRejectMap(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tstrs := genSliceString(n)\n\t\tb.Run(fmt.Sprintf(\"strings_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.RejectMap(strs, func(v string, _ int) (string, bool) { return v, len(v) < 3 })\n\t\t\t}\n\t\t})\n\t}\n\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.RejectMap(ints, func(v, _ int) (int, bool) { return v, v < 50000 })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkUniqMap(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.UniqMap(ints, func(v, _ int) int { return v % 50 })\n\t\t\t}\n\t\t})\n\t}\n\n\tfor _, n := range lengths {\n\t\tstrs := genSliceString(n)\n\t\tb.Run(fmt.Sprintf(\"strings_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.UniqMap(strs, func(v string, _ int) string { return v })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkRepeatBy(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.RepeatBy(n, func(index int) int { return index * 2 })\n\t\t\t}\n\t\t})\n\t}\n\n\tfor _, n := range lengths {\n\t\tb.Run(fmt.Sprintf(\"strings_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.RepeatBy(n, strconv.Itoa)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkFill(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tcollection := make([]clonableString, n)\n\t\tfor i := range collection {\n\t\t\tcollection[i] = clonableString{strconv.Itoa(i)}\n\t\t}\n\t\tb.Run(fmt.Sprintf(\"size_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.Fill(collection, clonableString{\"hello\"})\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkRepeat(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tb.Run(fmt.Sprintf(\"size_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.Repeat(n, clonableString{\"hello\"})\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkFilter(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.Filter(ints, func(v, _ int) bool { return v%2 == 0 })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkFilterErr(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_, _ = lo.FilterErr(ints, func(v, _ int) (bool, error) { return v%2 == 0, nil })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkSliceMap(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.Map(ints, func(v, _ int) int { return v * 2 })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkMapErr(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_, _ = lo.MapErr(ints, func(v, _ int) (int, error) { return v * 2, nil })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkFilterMap(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.FilterMap(ints, func(v, _ int) (int, bool) { return v * 2, v%2 == 0 })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkFlatMap(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.FlatMap(ints, func(v, _ int) []int { return []int{v, v + 1} })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkReduce(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.Reduce(ints, func(agg, item, _ int) int { return agg + item }, 0)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkReduceRight(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.ReduceRight(ints, func(agg, item, _ int) int { return agg + item }, 0)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkForEach(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\tlo.ForEach(ints, func(_, _ int) {})\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkForEachWhile(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\tlo.ForEachWhile(ints, func(_, _ int) bool { return true })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkTimes(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.Times(n, func(i int) int { return i })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkUniq(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.Uniq(ints)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkUniqBy(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.UniqBy(ints, func(v int) int { return v % 100 })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkGroupBy(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.GroupBy(ints, func(v int) int { return v % 10 })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkGroupByMap(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.GroupByMap(ints, func(v int) (int, string) { return v % 10, strconv.Itoa(v) })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkPartitionBy(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.PartitionBy(ints, func(v int) int { return v % 5 })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkConcat(b *testing.B) {\n\tfor _, n := range lengths {\n\t\ta := genSliceInt(n)\n\t\tc := genSliceInt(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.Concat(a, c)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkWindow(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.Window(ints, 5)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkSliding(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.Sliding(ints, 5, 2)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkInterleave(b *testing.B) {\n\tfor _, n := range lengths {\n\t\ta := genSliceInt(n)\n\t\tc := genSliceInt(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.Interleave(a, c)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkShuffle(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.Shuffle(ints) //nolint:staticcheck\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkReverse(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.Reverse(ints) //nolint:staticcheck\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkRepeatByErr(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_, _ = lo.RepeatByErr(n, func(index int) (int, error) { return index * 2, nil })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkKeyBy(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tstrs := genSliceString(n)\n\t\tb.Run(fmt.Sprintf(\"strings_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.KeyBy(strs, func(v string) string { return v })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkAssociate(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.Associate(ints, func(v int) (int, string) { return v, strconv.Itoa(v) })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkSliceToMap(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.SliceToMap(ints, func(v int) (int, string) { return v, strconv.Itoa(v) })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkFilterSliceToMap(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.FilterSliceToMap(ints, func(v int) (int, string, bool) { return v, strconv.Itoa(v), v%2 == 0 })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkKeyify(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.Keyify(ints)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkTake(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.Take(ints, n/4)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkTakeWhile(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.TakeWhile(ints, func(v int) bool { return v < 50000 })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkTakeFilter(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.TakeFilter(ints, 5, func(v, _ int) bool { return v%2 == 0 })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkFilterReject(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_, _ = lo.FilterReject(ints, func(v, _ int) bool { return v%2 == 0 })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkCount(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.Count(ints, 42)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkCountBy(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.CountBy(ints, func(v int) bool { return v%2 == 0 })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkCountValues(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.CountValues(ints)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkCountValuesBy(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.CountValuesBy(ints, func(v int) int { return v % 100 })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkSubset(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.Subset(ints, n/4, uint(n/2))\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkSlice(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.Slice(ints, n/4, n*3/4)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkReplaceAll(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.ReplaceAll(ints, ints[n/4], 123123)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkClone(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.Clone(ints)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkCompact(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.Compact(ints)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkIsSorted(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.IsSorted(ints)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkIsSortedBy(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.IsSortedBy(ints, func(v int) int { return v })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkIsSortedBySorted(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tdata := genSliceInt(n)\n\t\tsort.Ints(data)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\tlo.IsSortedBy(data, func(v int) int { return v })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkSplice(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\textra := []int{1, 2, 3}\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.Splice(ints, n/2, extra...)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkCut(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tsep := ints[n/4 : n/4+3]\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_, _, _ = lo.Cut(ints, sep)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkCutPrefix(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tprefix := ints[:3]\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_, _ = lo.CutPrefix(ints, prefix)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkCutSuffix(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tsuffix := ints[n-3:]\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_, _ = lo.CutSuffix(ints, suffix)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkTrim(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tcutset := ints[:3]\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.Trim(ints, cutset)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkTrimLeft(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tcutset := ints[:3]\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.TrimLeft(ints, cutset)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkTrimRight(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tcutset := ints[n-3:]\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.TrimRight(ints, cutset)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkTrimPrefix(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tprefix := ints[:3]\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.TrimPrefix(ints, prefix)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkTrimSuffix(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tsuffix := ints[n-3:]\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.TrimSuffix(ints, suffix)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkFilterTakeVsFilterAndTake(b *testing.B) {\n\tn := 1000\n\tints := genSliceInt(n)\n\n\tb.Run(\"lo.TakeFilter\", func(b *testing.B) {\n\t\tfor i := 0; i < b.N; i++ {\n\t\t\t_ = lo.TakeFilter(ints, 5, func(v, _ int) bool {\n\t\t\t\treturn v%2 == 0\n\t\t\t})\n\t\t}\n\t})\n\n\tb.Run(\"lo.Filter+lo.Take\", func(b *testing.B) {\n\t\tfor i := 0; i < b.N; i++ {\n\t\t\t_ = lo.Take(lo.Filter(ints, func(v, _ int) bool { return v%2 == 0 }), 5)\n\t\t}\n\t})\n\n\tb.Run(\"lo.Filter+native_slice\", func(b *testing.B) {\n\t\tfor i := 0; i < b.N; i++ {\n\t\t\tfiltered := lo.Filter(ints, func(v, _ int) bool { return v%2 == 0 })\n\t\t\ttakeN := 5\n\t\t\tif takeN > len(filtered) {\n\t\t\t\t_ = filtered\n\t\t\t} else {\n\t\t\t\t_ = filtered[:takeN]\n\t\t\t}\n\t\t}\n\t})\n\n\tb.Run(\"manual_loop\", func(b *testing.B) {\n\t\tfor i := 0; i < b.N; i++ {\n\t\t\tresult := make([]int, 0, 5)\n\t\t\tcount := 0\n\t\t\tfor _, v := range ints {\n\t\t\t\tif v%2 == 0 {\n\t\t\t\t\tresult = append(result, v)\n\t\t\t\t\tcount++\n\t\t\t\t\tif count >= 5 {\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t_ = result\n\t\t}\n\t})\n}\n\nfunc BenchmarkDifference(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints1 := genSliceInt(n)\n\t\tints2 := genSliceInt(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_, _ = lo.Difference(ints1, ints2)\n\t\t\t}\n\t\t})\n\t}\n\n\tfor _, n := range lengths {\n\t\tstrs1 := genSliceString(n)\n\t\tstrs2 := genSliceString(n)\n\t\tb.Run(fmt.Sprintf(\"strings_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_, _ = lo.Difference(strs1, strs2)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkFromSlicePtr(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tptrs := lo.ToSlicePtr(genSliceInt(n))\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.FromSlicePtr(ptrs)\n\t\t\t}\n\t\t})\n\t}\n\n\tfor _, n := range lengths {\n\t\tptrs := lo.ToSlicePtr(genSliceString(n))\n\t\tb.Run(fmt.Sprintf(\"strings_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.FromSlicePtr(ptrs)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkFromSlicePtrOr(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tptrs := lo.ToSlicePtr(genSliceInt(n))\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.FromSlicePtrOr(ptrs, -1)\n\t\t\t}\n\t\t})\n\t}\n\n\tfor _, n := range lengths {\n\t\tptrs := lo.ToSlicePtr(genSliceString(n))\n\t\tb.Run(fmt.Sprintf(\"strings_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.FromSlicePtrOr(ptrs, \"default\")\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "benchmark/core_string_bench_test.go",
    "content": "package benchmark\n\nimport (\n\t\"testing\"\n\n\t\"github.com/samber/lo\"\n)\n\nfunc BenchmarkRandomString(b *testing.B) {\n\tfor i := 0; i < b.N; i++ {\n\t\t_ = lo.RandomString(64, lo.AlphanumericCharset)\n\t}\n}\n\nfunc BenchmarkSubstring(b *testing.B) {\n\ts := lo.RandomString(1000, lo.LettersCharset)\n\tfor i := 0; i < b.N; i++ {\n\t\t_ = lo.Substring(s, 100, 200)\n\t}\n}\n\nfunc BenchmarkChunkString(b *testing.B) {\n\ts := lo.RandomString(1000, lo.LettersCharset)\n\tfor i := 0; i < b.N; i++ {\n\t\t_ = lo.ChunkString(s, 10)\n\t}\n}\n\nfunc BenchmarkRuneLength(b *testing.B) {\n\ts := lo.RandomString(1000, lo.LettersCharset)\n\tfor i := 0; i < b.N; i++ {\n\t\t_ = lo.RuneLength(s)\n\t}\n}\n\nfunc BenchmarkPascalCase(b *testing.B) {\n\tfor i := 0; i < b.N; i++ {\n\t\t_ = lo.PascalCase(\"some_long_variable_name\")\n\t}\n}\n\nfunc BenchmarkCamelCase(b *testing.B) {\n\tfor i := 0; i < b.N; i++ {\n\t\t_ = lo.CamelCase(\"some_long_variable_name\")\n\t}\n}\n\nfunc BenchmarkKebabCase(b *testing.B) {\n\tfor i := 0; i < b.N; i++ {\n\t\t_ = lo.KebabCase(\"someLongVariableName\")\n\t}\n}\n\nfunc BenchmarkSnakeCase(b *testing.B) {\n\tfor i := 0; i < b.N; i++ {\n\t\t_ = lo.SnakeCase(\"someLongVariableName\")\n\t}\n}\n\nfunc BenchmarkWords(b *testing.B) {\n\tfor i := 0; i < b.N; i++ {\n\t\t_ = lo.Words(\"someLongVariableName\")\n\t}\n}\n\nfunc BenchmarkCapitalize(b *testing.B) {\n\tfor i := 0; i < b.N; i++ {\n\t\t_ = lo.Capitalize(\"hello world\")\n\t}\n}\n\nfunc BenchmarkEllipsis(b *testing.B) {\n\ts := lo.RandomString(200, lo.LettersCharset)\n\tfor i := 0; i < b.N; i++ {\n\t\t_ = lo.Ellipsis(s, 50)\n\t}\n}\n"
  },
  {
    "path": "benchmark/core_tuples_bench_test.go",
    "content": "package benchmark\n\nimport (\n\t\"fmt\"\n\t\"testing\"\n\n\t\"github.com/samber/lo\"\n)\n\nfunc BenchmarkZip2_Equal(b *testing.B) {\n\tfor _, n := range lengths {\n\t\ta := genSliceInt(n)\n\t\ts := genSliceString(n)\n\t\tb.Run(fmt.Sprintf(\"n_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\tlo.Zip2(a, s)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkZip2_Unequal(b *testing.B) {\n\tfor _, n := range lengths {\n\t\ta := genSliceInt(n)\n\t\ts := genSliceString(n / 2)\n\t\tb.Run(fmt.Sprintf(\"n_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\tlo.Zip2(a, s)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkUnzip2(b *testing.B) {\n\tfor _, n := range lengths {\n\t\ttuples := make([]lo.Tuple2[int, string], n)\n\t\tfor i := range tuples {\n\t\t\ttuples[i] = lo.Tuple2[int, string]{A: i, B: \"x\"}\n\t\t}\n\t\tb.Run(fmt.Sprintf(\"n_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\tlo.Unzip2(tuples)\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "benchmark/core_type_manipulation_bench_test.go",
    "content": "package benchmark\n\nimport (\n\t\"strconv\"\n\t\"testing\"\n\n\t\"github.com/samber/lo\"\n)\n\nfunc BenchmarkToPtr(b *testing.B) {\n\tfor i := 0; i < b.N; i++ {\n\t\t_ = lo.ToPtr(42)\n\t}\n}\n\nfunc BenchmarkFromPtr(b *testing.B) {\n\tp := lo.ToPtr(42)\n\tfor i := 0; i < b.N; i++ {\n\t\t_ = lo.FromPtr(p)\n\t}\n}\n\nfunc BenchmarkFromPtrOr(b *testing.B) {\n\tvar p *int\n\tfor i := 0; i < b.N; i++ {\n\t\t_ = lo.FromPtrOr(p, 99)\n\t}\n}\n\nfunc BenchmarkToSlicePtr(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tb.Run(strconv.Itoa(n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.ToSlicePtr(ints)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkToAnySlice(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tints := genSliceInt(n)\n\t\tb.Run(strconv.Itoa(n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lo.ToAnySlice(ints)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkFromAnySlice(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tanys := lo.ToAnySlice(genSliceInt(n))\n\t\tb.Run(strconv.Itoa(n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_, _ = lo.FromAnySlice[int](anys)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkIsEmpty(b *testing.B) {\n\tfor i := 0; i < b.N; i++ {\n\t\t_ = lo.IsEmpty(0)\n\t}\n}\n\nfunc BenchmarkIsNotEmpty(b *testing.B) {\n\tfor i := 0; i < b.N; i++ {\n\t\t_ = lo.IsNotEmpty(42)\n\t}\n}\n\nfunc BenchmarkCoalesce(b *testing.B) {\n\tfor i := 0; i < b.N; i++ {\n\t\t_, _ = lo.Coalesce(0, 0, 0, 42, 99)\n\t}\n}\n"
  },
  {
    "path": "benchmark/helpers_test.go",
    "content": "package benchmark\n\nimport (\n\t\"math/rand\"\n\t\"strconv\"\n\t\"time\"\n)\n\nvar lengths = []int{10, 100, 1000}\n\nfunc genSliceString(n int) []string {\n\tres := make([]string, 0, n)\n\tfor i := 0; i < n; i++ {\n\t\tres = append(res, strconv.Itoa(rand.Intn(100_000)))\n\t}\n\treturn res\n}\n\nfunc genSliceInt(n int) []int {\n\tres := make([]int, 0, n)\n\tfor i := 0; i < n; i++ {\n\t\tres = append(res, rand.Intn(100_000))\n\t}\n\treturn res\n}\n\ntype heavy = [100]int\n\nfunc genSliceHeavy(n int) []heavy {\n\tresult := make([]heavy, n)\n\tfor i := range result {\n\t\tfor j := range result[i] {\n\t\t\tresult[i][j] = i + j\n\t\t}\n\t}\n\treturn result\n}\n\nfunc genMap(n int) map[string]int {\n\tm := make(map[string]int, n)\n\tfor i := 0; i < n; i++ {\n\t\tm[strconv.Itoa(i)] = i\n\t}\n\treturn m\n}\n\ntype clonableString struct {\n\tval string\n}\n\nfunc (c clonableString) Clone() clonableString {\n\treturn clonableString{c.val}\n}\n\n// sliceGenerator creates a random int64 slice (used by comparison benchmarks).\nfunc sliceGenerator(size uint) []int64 {\n\tr := rand.New(rand.NewSource(time.Now().Unix()))\n\n\tresult := make([]int64, size)\n\n\tfor i := uint(0); i < size; i++ {\n\t\tresult[i] = r.Int63()\n\t}\n\n\treturn result\n}\n\n// mapGenerator creates a random int64 map (used by comparison benchmarks).\nfunc mapGenerator(size uint) map[int64]int64 {\n\tr := rand.New(rand.NewSource(time.Now().Unix()))\n\n\tresult := make(map[int64]int64, size)\n\n\tfor i := uint(0); i < size; i++ {\n\t\tresult[int64(i)] = r.Int63()\n\t}\n\n\treturn result\n}\n"
  },
  {
    "path": "benchmark/it_find_bench_test.go",
    "content": "//go:build go1.23\n\npackage benchmark\n\nimport (\n\t\"fmt\"\n\t\"math/rand/v2\"\n\t\"testing\"\n\n\t\"github.com/samber/lo/it\"\n)\n\nfunc BenchmarkItFind(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tints := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\t_, _ = it.Find(ints, func(x int) bool { return x == 0 })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItContains(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tints := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\t_ = it.Contains(ints, 42)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItContainsBy(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tints := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\ttarget := rand.IntN(100_000)\n\t\t\tfor range b.N {\n\t\t\t\t_ = it.ContainsBy(ints, func(x int) bool { return x == target })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItEvery(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tints := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\t_ = it.Every(ints, 1, 2, 3)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItEveryBy(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tints := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\t_ = it.EveryBy(ints, func(x int) bool { return x >= 0 })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItSome(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tints := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\t_ = it.Some(ints, 1, 2, 3)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItSomeBy(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tints := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\ttarget := rand.IntN(100_000)\n\t\t\tfor range b.N {\n\t\t\t\t_ = it.SomeBy(ints, func(x int) bool { return x == target })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItNone(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tints := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\t_ = it.None(ints, -1, -2, -3)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItNoneBy(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tints := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\ttarget := rand.IntN(100_000)\n\t\t\tfor range b.N {\n\t\t\t\t_ = it.NoneBy(ints, func(x int) bool { return x == target })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItIntersect(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\ta := genInts(n)\n\t\tc := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\tfor range it.Intersect(a, c) { //nolint:revive\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItUnion(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\ta := genInts(n)\n\t\tc := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\tfor range it.Union(a, c) { //nolint:revive\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItWithout(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tints := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\tfor range it.Without(ints, 1, 2, 3, 4, 5) { //nolint:revive\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItWithoutNth(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tints := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\tfor range it.WithoutNth(ints, 0, n/2, n-1) { //nolint:revive\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItIndexOf(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tints := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\t_ = it.IndexOf(ints, -1)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItLastIndexOf(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tints := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\t_ = it.LastIndexOf(ints, -1)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItHasPrefix(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tints := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\t_ = it.HasPrefix(ints, -1, -2, -3)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItHasSuffix(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tints := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\t_ = it.HasSuffix(ints, -1, -2, -3)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItFindIndexOf(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tints := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\t_, _, _ = it.FindIndexOf(ints, func(x int) bool { return x == -1 })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItFindOrElse(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tints := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\t_ = it.FindOrElse(ints, -1, func(x int) bool { return x == -1 })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItFindUniques(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tints := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\tfor range it.FindUniques(ints) { //nolint:revive\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItFindDuplicates(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tints := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\tfor range it.FindDuplicates(ints) { //nolint:revive\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItMin(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tints := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\t_ = it.Min(ints)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItMax(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tints := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\t_ = it.Max(ints)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItMinBy(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tints := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\t_ = it.MinBy(ints, func(a, b int) bool { return a < b })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItMaxBy(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tints := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\t_ = it.MaxBy(ints, func(a, b int) bool { return a > b })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItFirst(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tints := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\t_, _ = it.First(ints)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItLast(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tints := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\t_, _ = it.Last(ints)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItNth(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tints := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\t_, _ = it.Nth(ints, n/2)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItSample(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tints := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\t_ = it.Sample(ints)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItSamples(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tints := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\tfor range it.Samples(ints, 5) { //nolint:revive\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "benchmark/it_helpers_test.go",
    "content": "//go:build go1.23\n\npackage benchmark\n\nimport (\n\t\"iter\"\n\t\"math/rand/v2\"\n\t\"strconv\"\n)\n\nvar itLengths = []int{10, 100, 1000}\n\nfunc genStrings(n int) iter.Seq[string] {\n\treturn func(yield func(string) bool) {\n\t\tfor range n {\n\t\t\tif !yield(strconv.Itoa(rand.IntN(100_000))) {\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc genInts(n int) iter.Seq[int] {\n\treturn func(yield func(int) bool) {\n\t\tfor range n {\n\t\t\tif !yield(rand.IntN(100_000)) {\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc genIntPtrSeq(n int) iter.Seq[*int] {\n\treturn func(yield func(*int) bool) {\n\t\tfor range n {\n\t\t\tv := rand.IntN(100_000)\n\t\t\tif !yield(&v) {\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc genMapStringInt(n int) map[string]int {\n\tm := make(map[string]int, n)\n\tfor i := range n {\n\t\tm[strconv.Itoa(i)] = rand.IntN(100_000)\n\t}\n\treturn m\n}\n\nfunc genMapSeq(n int) iter.Seq[map[string]int] {\n\treturn func(yield func(map[string]int) bool) {\n\t\tfor range n {\n\t\t\tm := map[string]int{strconv.Itoa(rand.IntN(100_000)): rand.IntN(100_000)}\n\t\t\tif !yield(m) {\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "benchmark/it_map_bench_test.go",
    "content": "//go:build go1.23\n\npackage benchmark\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/samber/lo/it\"\n)\n\nfunc BenchmarkItKeys(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tm := genMapStringInt(n)\n\t\tb.Run(fmt.Sprintf(\"map_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\tfor range it.Keys(m) { //nolint:revive\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItUniqKeys(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tm := genMapStringInt(n)\n\t\tb.Run(fmt.Sprintf(\"map_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\tfor range it.UniqKeys(m) { //nolint:revive\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItValues(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tm := genMapStringInt(n)\n\t\tb.Run(fmt.Sprintf(\"map_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\tfor range it.Values(m) { //nolint:revive\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItUniqValues(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tm := genMapStringInt(n)\n\t\tb.Run(fmt.Sprintf(\"map_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\tfor range it.UniqValues(m) { //nolint:revive\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItEntries(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tm := genMapStringInt(n)\n\t\tb.Run(fmt.Sprintf(\"map_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\tfor range it.Entries(m) { //nolint:revive\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItFromEntries(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tm := genMapStringInt(n)\n\t\tentries := it.Entries(m)\n\t\tb.Run(fmt.Sprintf(\"map_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\t_ = it.FromEntries(entries)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItInvert(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tm := genMapStringInt(n)\n\t\tentries := it.Entries(m)\n\t\tb.Run(fmt.Sprintf(\"map_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\tfor range it.Invert(entries) { //nolint:revive\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItAssign(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tseq := genMapSeq(n)\n\t\tb.Run(fmt.Sprintf(\"maps_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\t_ = it.Assign(seq)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItFilterKeys(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tm := genMapStringInt(n)\n\t\tb.Run(fmt.Sprintf(\"map_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\tfor range it.FilterKeys(m, func(_ string, v int) bool { return v%2 == 0 }) { //nolint:revive\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItFilterValues(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tm := genMapStringInt(n)\n\t\tb.Run(fmt.Sprintf(\"map_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\tfor range it.FilterValues(m, func(_ string, v int) bool { return v%2 == 0 }) { //nolint:revive\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItChunkString(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tvar sb strings.Builder\n\t\tfor range n {\n\t\t\tsb.WriteString(\"a\")\n\t\t}\n\t\ts := sb.String()\n\t\tb.Run(fmt.Sprintf(\"len_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\tfor range it.ChunkString(s, 5) { //nolint:revive\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "benchmark/it_math_bench_test.go",
    "content": "//go:build go1.23\n\npackage benchmark\n\nimport (\n\t\"fmt\"\n\t\"testing\"\n\n\t\"github.com/samber/lo/it\"\n)\n\nfunc BenchmarkItSum(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tints := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\t_ = it.Sum(ints)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItSumBy(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tints := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\t_ = it.SumBy(ints, func(x int) int { return x })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItProduct(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tints := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\t_ = it.Product(ints)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItMean(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tints := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\t_ = it.Mean(ints)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItMode(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tints := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\t_ = it.Mode(ints)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItRange(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\tfor range it.Range(n) { //nolint:revive\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItLength(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tints := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\t_ = it.Length(ints)\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "benchmark/it_slice_bench_test.go",
    "content": "//go:build go1.23\n\npackage benchmark\n\nimport (\n\t\"fmt\"\n\t\"iter\"\n\t\"testing\"\n\n\t\"github.com/samber/lo/it\"\n)\n\nfunc BenchmarkItChunk(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tstrs := genStrings(n)\n\t\tb.Run(fmt.Sprintf(\"strings_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\tfor range it.Chunk(strs, 5) { //nolint:revive\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n\n\tfor _, n := range itLengths {\n\t\tints := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\tfor range it.Chunk(ints, 5) { //nolint:revive\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItFlatten(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tints := make([]iter.Seq[int], 0, n)\n\t\tfor range n {\n\t\t\tints = append(ints, genInts(n))\n\t\t}\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\tfor range it.Flatten(ints) { //nolint:revive\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n\n\tfor _, n := range itLengths {\n\t\tstrs := make([]iter.Seq[string], 0, n)\n\t\tfor range n {\n\t\t\tstrs = append(strs, genStrings(n))\n\t\t}\n\t\tb.Run(fmt.Sprintf(\"strings_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\tfor range it.Flatten(strs) { //nolint:revive\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItDrop(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tstrs := genStrings(n)\n\t\tb.Run(fmt.Sprintf(\"strings_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\tfor range it.Drop(strs, n/4) { //nolint:revive\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n\n\tfor _, n := range itLengths {\n\t\tints := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\tfor range it.Drop(ints, n/4) { //nolint:revive\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItDropWhile(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tstrs := genStrings(n)\n\t\tb.Run(fmt.Sprintf(\"strings_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\tfor range it.DropWhile(strs, func(v string) bool { return len(v) < 4 }) { //nolint:revive\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n\n\tfor _, n := range itLengths {\n\t\tints := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints%d\", n), func(b *testing.B) {\n\t\t\tfor i := range b.N {\n\t\t\t\tfor range it.DropWhile(ints, func(v int) bool { return i < 10_000 }) { //nolint:revive\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItDropLastWhile(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tstrs := genStrings(n)\n\t\tb.Run(fmt.Sprintf(\"strings_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\tfor range it.DropLastWhile(strs, func(v string) bool { return len(v) < 4 }) { //nolint:revive\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n\n\tfor _, n := range itLengths {\n\t\tints := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\tfor range it.DropLastWhile(ints, func(v int) bool { return v < 10_000 }) { //nolint:revive\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItDropByIndex(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tstrs := genStrings(n)\n\t\tb.Run(fmt.Sprintf(\"strings_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\tfor range it.DropByIndex(strs, n/4) { //nolint:revive\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n\n\tfor _, n := range itLengths {\n\t\tints := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\tfor range it.DropByIndex(ints, n/4) { //nolint:revive\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItReplace(b *testing.B) {\n\tlengths := []int{1_000, 10_000, 100_000}\n\n\tfor _, n := range lengths {\n\t\tstrs := genStrings(n)\n\t\tb.Run(fmt.Sprintf(\"strings_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\tfor range it.Replace(strs, \"321321\", \"123123\", 10) { //nolint:revive\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n\n\tfor _, n := range lengths {\n\t\tints := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\tfor range it.Replace(ints, 321321, 123123, 10) { //nolint:revive\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItTrim(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tstrs := genStrings(n)\n\t\tb.Run(fmt.Sprintf(\"strings_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\tfor range it.Trim(strs, \"123\", \"456\") { //nolint:revive\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n\n\tfor _, n := range itLengths {\n\t\tints := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\tfor range it.Trim(ints, 123, 456) { //nolint:revive\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItTrimSuffix(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tstrs := genStrings(n)\n\t\tb.Run(fmt.Sprintf(\"strings_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\tfor range it.TrimSuffix(strs, []string{\"\"}) { //nolint:revive\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n\n\tfor _, n := range itLengths {\n\t\tints := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\tfor range it.TrimSuffix(ints, []int{0}) { //nolint:revive\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItFilter(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tints := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\tfor range it.Filter(ints, func(x int) bool { return x%2 == 0 }) { //nolint:revive\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItMap(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tints := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\tfor range it.Map(ints, func(x int) int { return x * 2 }) { //nolint:revive\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItUniqMap(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tints := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\tfor range it.UniqMap(ints, func(x int) int { return x % 50 }) { //nolint:revive\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItFilterMap(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tints := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\tfor range it.FilterMap(ints, func(x int) (int, bool) { return x * 2, x%2 == 0 }) { //nolint:revive\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItFlatMap(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tints := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\tfor range it.FlatMap(ints, func(x int) iter.Seq[int] { //nolint:revive\n\t\t\t\t\treturn func(yield func(int) bool) {\n\t\t\t\t\t\tyield(x)\n\t\t\t\t\t}\n\t\t\t\t}) {\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItReduce(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tints := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\t_ = it.Reduce(ints, func(agg, item int) int { return agg + item }, 0)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItForEach(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tints := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\tit.ForEach(ints, func(_ int) {})\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItForEachWhile(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tints := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\tit.ForEachWhile(ints, func(_ int) bool { return true })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItTimes(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\tfor range it.Times(n, func(i int) int { return i * 2 }) { //nolint:revive\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItUniq(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tints := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\tfor range it.Uniq(ints) { //nolint:revive\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItUniqBy(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tints := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\tfor range it.UniqBy(ints, func(x int) int { return x % 50 }) { //nolint:revive\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItGroupBy(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tints := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\t_ = it.GroupBy(ints, func(x int) int { return x % 10 })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItPartitionBy(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tints := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\t_ = it.PartitionBy(ints, func(x int) int { return x % 10 })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItConcat(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\ta := genInts(n)\n\t\tc := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\tfor range it.Concat(a, c) { //nolint:revive\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItInterleave(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\ta := genInts(n)\n\t\tc := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\tfor range it.Interleave(a, c) { //nolint:revive\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItShuffle(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tints := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\tfor range it.Shuffle(ints) { //nolint:revive\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItReverse(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tints := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\tfor range it.Reverse(ints) { //nolint:revive\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItRepeatBy(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\tfor range it.RepeatBy(n, func(i int) int { return i * 2 }) { //nolint:revive\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItKeyBy(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tints := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\t_ = it.KeyBy(ints, func(x int) int { return x })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItAssociate(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tints := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\t_ = it.Associate(ints, func(x int) (int, int) { return x, x * 2 })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItTake(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tints := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\tfor range it.Take(ints, n/2) { //nolint:revive\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItTakeWhile(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tints := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\tfor range it.TakeWhile(ints, func(x int) bool { return x < 90_000 }) { //nolint:revive\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItTakeFilter(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tints := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\tfor range it.TakeFilter(ints, 5, func(x int) bool { return x%2 == 0 }) { //nolint:revive\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItReject(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tints := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\tfor range it.Reject(ints, func(x int) bool { return x%2 == 0 }) { //nolint:revive\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItRejectMap(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tints := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\tfor range it.RejectMap(ints, func(x int) (int, bool) { return x * 2, x%2 == 0 }) { //nolint:revive\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItCount(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tints := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\t_ = it.Count(ints, 42)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItCountBy(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tints := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\t_ = it.CountBy(ints, func(x int) bool { return x%2 == 0 })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItCountValues(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tints := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\t_ = it.CountValues(ints)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItCountValuesBy(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tints := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\t_ = it.CountValuesBy(ints, func(x int) int { return x % 10 })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItSubset(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tints := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\tfor range it.Subset(ints, n/4, n/2) { //nolint:revive\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItSlice(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tints := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\tfor range it.Slice(ints, n/4, n*3/4) { //nolint:revive\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItReplaceAll(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tints := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\tfor range it.ReplaceAll(ints, 42, 99) { //nolint:revive\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItCompact(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tints := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\tfor range it.Compact(ints) { //nolint:revive\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItIsSorted(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tints := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\t_ = it.IsSorted(ints)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItSplice(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tints := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\tfor range it.Splice(ints, n/2, 1, 2, 3) { //nolint:revive\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItCutPrefix(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tints := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\tafter, _ := it.CutPrefix(ints, []int{-1, -2})\n\t\t\t\tfor range after { //nolint:revive\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItBuffer(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tints := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\tfor range it.Buffer(ints, 5) { //nolint:revive\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "benchmark/it_type_manipulation_bench_test.go",
    "content": "//go:build go1.23\n\npackage benchmark\n\nimport (\n\t\"fmt\"\n\t\"testing\"\n\n\t\"github.com/samber/lo/it\"\n)\n\nfunc BenchmarkItToSeqPtr(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tints := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\tfor range it.ToSeqPtr(ints) { //nolint:revive\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItFromSeqPtr(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tptrs := genIntPtrSeq(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\tfor range it.FromSeqPtr(ptrs) { //nolint:revive\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkItToAnySeq(b *testing.B) {\n\tfor _, n := range itLengths {\n\t\tints := genInts(n)\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor range b.N {\n\t\t\t\tfor range it.ToAnySeq(ints) { //nolint:revive\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "benchmark/mutable_slice_bench_test.go",
    "content": "package benchmark\n\nimport (\n\t\"fmt\"\n\t\"testing\"\n\n\t\"github.com/samber/lo/mutable\"\n)\n\nfunc BenchmarkMutableFilter(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tsrc := genSliceInt(n)\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\tcp := make([]int, len(src))\n\t\t\t\tcopy(cp, src)\n\t\t\t\t_ = mutable.Filter(cp, func(x int) bool { return x%2 == 0 })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkMutableFilterI(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tsrc := genSliceInt(n)\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\tcp := make([]int, len(src))\n\t\t\t\tcopy(cp, src)\n\t\t\t\t_ = mutable.FilterI(cp, func(x, _ int) bool { return x%2 == 0 })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkMutableMap(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tsrc := genSliceInt(n)\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\tcp := make([]int, len(src))\n\t\t\t\tcopy(cp, src)\n\t\t\t\tmutable.Map(cp, func(x int) int { return x * 2 })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkMutableMapI(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tsrc := genSliceInt(n)\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\tcp := make([]int, len(src))\n\t\t\t\tcopy(cp, src)\n\t\t\t\tmutable.MapI(cp, func(x, i int) int { return x * i })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkMutableShuffle(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tsrc := genSliceInt(n)\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\tcp := make([]int, len(src))\n\t\t\t\tcopy(cp, src)\n\t\t\t\tmutable.Shuffle(cp)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkMutableReverse(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tsrc := genSliceInt(n)\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\tcp := make([]int, len(src))\n\t\t\t\tcopy(cp, src)\n\t\t\t\tmutable.Reverse(cp)\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "benchmark/parallel_slice_bench_test.go",
    "content": "package benchmark\n\nimport (\n\t\"fmt\"\n\t\"testing\"\n\n\tlop \"github.com/samber/lo/parallel\"\n)\n\nfunc BenchmarkParallelMap(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tsrc := genSliceInt(n)\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lop.Map(src, func(x, _ int) int { return x * 2 })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkParallelForEach(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tsrc := genSliceInt(n)\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\tlop.ForEach(src, func(_, _ int) {})\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkParallelTimes(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lop.Times(n, func(i int) int { return i * 2 })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkParallelGroupBy(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tsrc := genSliceInt(n)\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lop.GroupBy(src, func(x int) int { return x % 10 })\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkParallelPartitionBy(b *testing.B) {\n\tfor _, n := range lengths {\n\t\tb.Run(fmt.Sprintf(\"ints_%d\", n), func(b *testing.B) {\n\t\t\tsrc := genSliceInt(n)\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = lop.PartitionBy(src, func(x int) int { return x % 10 })\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "channel.go",
    "content": "package lo\n\nimport (\n\t\"context\"\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com/samber/lo/internal/xrand\"\n)\n\n// DispatchingStrategy is a function that distributes messages to channels.\ntype DispatchingStrategy[T any] func(msg T, index uint64, channels []<-chan T) int\n\n// ChannelDispatcher distributes messages from input channels into N child channels.\n// Close events are propagated to children.\n// Underlying channels can have a fixed buffer capacity or be unbuffered when cap is 0.\n// Play: https://go.dev/play/p/UZGu2wVg3J2\nfunc ChannelDispatcher[T any](stream <-chan T, count, channelBufferCap int, strategy DispatchingStrategy[T]) []<-chan T {\n\tchildren := createChannels[T](count, channelBufferCap)\n\n\troChildren := channelsToReadOnly(children)\n\n\tgo func() {\n\t\t// propagate channel closing to children\n\t\tdefer closeChannels(children)\n\n\t\tvar i uint64\n\n\t\tfor msg := range stream {\n\t\t\tdestination := strategy(msg, i, roChildren) % count\n\t\t\tchildren[destination] <- msg\n\n\t\t\ti++\n\t\t}\n\t}()\n\n\treturn roChildren\n}\n\nfunc createChannels[T any](count, channelBufferCap int) []chan T {\n\tchildren := make([]chan T, 0, count)\n\n\tfor i := 0; i < count; i++ {\n\t\tchildren = append(children, make(chan T, channelBufferCap))\n\t}\n\n\treturn children\n}\n\nfunc channelsToReadOnly[T any](children []chan T) []<-chan T {\n\troChildren := make([]<-chan T, 0, len(children))\n\n\tfor i := range children {\n\t\troChildren = append(roChildren, children[i])\n\t}\n\n\treturn roChildren\n}\n\nfunc closeChannels[T any](children []chan T) {\n\tfor i := 0; i < len(children); i++ {\n\t\tclose(children[i])\n\t}\n}\n\nfunc channelIsNotFull[T any](ch <-chan T) bool {\n\treturn cap(ch) == 0 || len(ch) < cap(ch)\n}\n\n// DispatchingStrategyRoundRobin distributes messages in a rotating sequential manner.\n// If the channel capacity is exceeded, the next channel will be selected and so on.\n// Play: https://go.dev/play/p/UZGu2wVg3J2\nfunc DispatchingStrategyRoundRobin[T any](msg T, index uint64, channels []<-chan T) int {\n\tfor {\n\t\ti := int(index % uint64(len(channels)))\n\t\tif channelIsNotFull(channels[i]) {\n\t\t\treturn i\n\t\t}\n\n\t\tindex++\n\t\ttime.Sleep(10 * time.Microsecond) // prevent CPU from burning 🔥\n\t}\n}\n\n// DispatchingStrategyRandom distributes messages in a random manner.\n// If the channel capacity is exceeded, another random channel will be selected and so on.\n// Play: https://go.dev/play/p/GEyGn3TdGk4\nfunc DispatchingStrategyRandom[T any](msg T, index uint64, channels []<-chan T) int {\n\tfor {\n\t\ti := xrand.IntN(len(channels))\n\t\tif channelIsNotFull(channels[i]) {\n\t\t\treturn i\n\t\t}\n\n\t\ttime.Sleep(10 * time.Microsecond) // prevent CPU from burning 🔥\n\t}\n}\n\n// DispatchingStrategyWeightedRandom distributes messages in a weighted manner.\n// If the channel capacity is exceeded, another random channel will be selected and so on.\n// Play: https://go.dev/play/p/v0eMh8NZG2L\nfunc DispatchingStrategyWeightedRandom[T any](weights []int) DispatchingStrategy[T] {\n\tseq := []int{}\n\n\tfor i, weight := range weights {\n\t\tfor j := 0; j < weight; j++ {\n\t\t\tseq = append(seq, i)\n\t\t}\n\t}\n\n\treturn func(msg T, index uint64, channels []<-chan T) int {\n\t\tfor {\n\t\t\ti := seq[xrand.IntN(len(seq))]\n\t\t\tif channelIsNotFull(channels[i]) {\n\t\t\t\treturn i\n\t\t\t}\n\n\t\t\ttime.Sleep(10 * time.Microsecond) // prevent CPU from burning 🔥\n\t\t}\n\t}\n}\n\n// DispatchingStrategyFirst distributes messages in the first non-full channel.\n// If the capacity of the first channel is exceeded, the second channel will be selected and so on.\n// Play: https://go.dev/play/p/OrJCvOmk42f\nfunc DispatchingStrategyFirst[T any](msg T, index uint64, channels []<-chan T) int {\n\tfor {\n\t\tfor i := range channels {\n\t\t\tif channelIsNotFull(channels[i]) {\n\t\t\t\treturn i\n\t\t\t}\n\t\t}\n\n\t\ttime.Sleep(10 * time.Microsecond) // prevent CPU from burning 🔥\n\t}\n}\n\n// DispatchingStrategyLeast distributes messages in the emptiest channel.\n// Play: https://go.dev/play/p/ypy0jrRcEe7\nfunc DispatchingStrategyLeast[T any](msg T, index uint64, channels []<-chan T) int {\n\t_, i := MinIndexBy(channels, func(a, b <-chan T) bool {\n\t\treturn len(a) < len(b)\n\t})\n\n\treturn i\n}\n\n// DispatchingStrategyMost distributes messages in the fullest channel.\n// If the channel capacity is exceeded, the next channel will be selected and so on.\n// Play: https://go.dev/play/p/erHHone7rF9\nfunc DispatchingStrategyMost[T any](msg T, index uint64, channels []<-chan T) int {\n\t_, i := MaxIndexBy(channels, func(a, b <-chan T) bool {\n\t\treturn len(a) > len(b) && channelIsNotFull(a)\n\t})\n\n\treturn i\n}\n\n// SliceToChannel returns a read-only channel of collection elements.\n// Play: https://go.dev/play/p/lIbSY3QmiEg\nfunc SliceToChannel[T any](bufferSize int, collection []T) <-chan T {\n\tch := make(chan T, bufferSize)\n\n\tgo func() {\n\t\tfor i := range collection {\n\t\t\tch <- collection[i]\n\t\t}\n\n\t\tclose(ch)\n\t}()\n\n\treturn ch\n}\n\n// ChannelToSlice returns a slice built from channel items. Blocks until channel closes.\n// Play: https://go.dev/play/p/lIbSY3QmiEg\nfunc ChannelToSlice[T any](ch <-chan T) []T {\n\tcollection := []T{}\n\n\tfor item := range ch {\n\t\tcollection = append(collection, item)\n\t}\n\n\treturn collection\n}\n\n// Generator implements the generator design pattern.\n// Play: https://go.dev/play/p/lIbSY3QmiEg\n//\n// Deprecated: use \"iter\" package instead (Go >= 1.23).\nfunc Generator[T any](bufferSize int, generator func(yield func(T))) <-chan T {\n\tch := make(chan T, bufferSize)\n\n\tgo func() {\n\t\t// WARNING: infinite loop\n\t\tgenerator(func(t T) {\n\t\t\tch <- t\n\t\t})\n\n\t\tclose(ch)\n\t}()\n\n\treturn ch\n}\n\n// Buffer creates a slice of n elements from a channel. Returns the slice and the slice length.\n// @TODO: we should probably provide a helper that reuses the same buffer.\n// Play: https://go.dev/play/p/gPQ-6xmcKQI\nfunc Buffer[T any](ch <-chan T, size int) (collection []T, length int, readTime time.Duration, ok bool) {\n\tbuffer := make([]T, 0, size)\n\tnow := time.Now()\n\n\tfor index := 0; index < size; index++ {\n\t\titem, ok := <-ch\n\t\tif !ok {\n\t\t\treturn buffer, index, time.Since(now), false\n\t\t}\n\n\t\tbuffer = append(buffer, item)\n\t}\n\n\treturn buffer, size, time.Since(now), true\n}\n\n// BufferWithContext creates a slice of n elements from a channel, with context. Returns the slice and the slice length.\n// @TODO: we should probably provide a helper that reuses the same buffer.\n// Play: https://go.dev/play/p/oRfOyJWK9YF\nfunc BufferWithContext[T any](ctx context.Context, ch <-chan T, size int) (collection []T, length int, readTime time.Duration, ok bool) {\n\tbuffer := make([]T, 0, size)\n\tnow := time.Now()\n\n\tfor index := 0; index < size; index++ {\n\t\tselect {\n\t\tcase item, ok := <-ch:\n\t\t\tif !ok {\n\t\t\t\treturn buffer, index, time.Since(now), false\n\t\t\t}\n\n\t\t\tbuffer = append(buffer, item)\n\n\t\tcase <-ctx.Done():\n\t\t\treturn buffer, index, time.Since(now), true\n\t\t}\n\t}\n\n\treturn buffer, size, time.Since(now), true\n}\n\n// BufferWithTimeout creates a slice of n elements from a channel, with timeout. Returns the slice and the slice length.\n// Play: https://go.dev/play/p/sxyEM3koo4n\nfunc BufferWithTimeout[T any](ch <-chan T, size int, timeout time.Duration) (collection []T, length int, readTime time.Duration, ok bool) {\n\tctx, cancel := context.WithTimeout(context.Background(), timeout)\n\tdefer cancel()\n\treturn BufferWithContext(ctx, ch, size)\n}\n\n// FanIn collects messages from multiple input channels into a single buffered channel.\n// Output messages have no priority. When all upstream channels reach EOF, downstream channel closes.\n// Play: https://go.dev/play/p/FH8Wq-T04Jb\nfunc FanIn[T any](channelBufferCap int, upstreams ...<-chan T) <-chan T {\n\tout := make(chan T, channelBufferCap)\n\tvar wg sync.WaitGroup\n\n\t// Start an output goroutine for each input channel in upstreams.\n\twg.Add(len(upstreams))\n\tfor i := range upstreams {\n\t\tgo func(index int) {\n\t\t\tfor n := range upstreams[index] {\n\t\t\t\tout <- n\n\t\t\t}\n\t\t\twg.Done()\n\t\t}(i)\n\t}\n\n\t// Start a goroutine to close out once all the output goroutines are done.\n\tgo func() {\n\t\twg.Wait()\n\t\tclose(out)\n\t}()\n\treturn out\n}\n\n// FanOut broadcasts all the upstream messages to multiple downstream channels.\n// When upstream channel reaches EOF, downstream channels close. If any downstream\n// channels is full, broadcasting is paused.\n// Play: https://go.dev/play/p/2LHxcjKX23L\nfunc FanOut[T any](count, channelsBufferCap int, upstream <-chan T) []<-chan T {\n\tdownstreams := createChannels[T](count, channelsBufferCap)\n\n\tgo func() {\n\t\tfor msg := range upstream {\n\t\t\tfor i := range downstreams {\n\t\t\t\tdownstreams[i] <- msg\n\t\t\t}\n\t\t}\n\n\t\t// Close out once all the output goroutines are done.\n\t\tfor i := range downstreams {\n\t\t\tclose(downstreams[i])\n\t\t}\n\t}()\n\n\treturn channelsToReadOnly(downstreams)\n}\n"
  },
  {
    "path": "channel_test.go",
    "content": "package lo\n\nimport (\n\t\"context\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestChannelDispatcher(t *testing.T) {\n\tt.Parallel()\n\ttestWithTimeout(t, 100*time.Millisecond)\n\tis := assert.New(t)\n\n\tch := make(chan int, 10)\n\n\tch <- 0\n\tch <- 1\n\tch <- 2\n\tch <- 3\n\n\tis.Len(ch, 4)\n\n\tchildren := ChannelDispatcher(ch, 5, 10, DispatchingStrategyRoundRobin[int])\n\ttime.Sleep(10 * time.Millisecond)\n\n\t// check channels allocation\n\tis.Len(children, 5)\n\n\tis.Equal(10, cap(children[0]))\n\tis.Equal(10, cap(children[1]))\n\tis.Equal(10, cap(children[2]))\n\tis.Equal(10, cap(children[3]))\n\tis.Equal(10, cap(children[4]))\n\n\tis.Len(children[0], 1)\n\tis.Len(children[1], 1)\n\tis.Len(children[2], 1)\n\tis.Len(children[3], 1)\n\tis.Empty(children[4])\n\n\t// check channels content\n\tis.Empty(ch)\n\n\tmsg0, ok0 := <-children[0]\n\tis.True(ok0)\n\tis.Zero(msg0)\n\n\tmsg1, ok1 := <-children[1]\n\tis.True(ok1)\n\tis.Equal(1, msg1)\n\n\tmsg2, ok2 := <-children[2]\n\tis.True(ok2)\n\tis.Equal(2, msg2)\n\n\tmsg3, ok3 := <-children[3]\n\tis.True(ok3)\n\tis.Equal(3, msg3)\n\n\t// msg4, ok4 := <-children[4]\n\t// is.False(ok4)\n\t// is.Zero(msg4)\n\t// is.Nil(children[4])\n\n\t// check it is closed\n\tclose(ch)\n\ttime.Sleep(10 * time.Millisecond)\n\tis.Panics(func() {\n\t\tch <- 42\n\t})\n\n\tmsg0, ok0 = <-children[0]\n\tis.False(ok0)\n\tis.Zero(msg0)\n\n\tmsg1, ok1 = <-children[1]\n\tis.False(ok1)\n\tis.Zero(msg1)\n\n\tmsg2, ok2 = <-children[2]\n\tis.False(ok2)\n\tis.Zero(msg2)\n\n\tmsg3, ok3 = <-children[3]\n\tis.False(ok3)\n\tis.Zero(msg3)\n\n\tmsg4, ok4 := <-children[4]\n\tis.False(ok4)\n\tis.Zero(msg4)\n\n\t// unbuffered channels\n\tchildren = ChannelDispatcher(ch, 5, 0, DispatchingStrategyRoundRobin[int])\n\tis.Zero(cap(children[0]))\n}\n\nfunc TestDispatchingStrategyRoundRobin(t *testing.T) {\n\tt.Parallel()\n\ttestWithTimeout(t, 100*time.Millisecond)\n\tis := assert.New(t)\n\n\tchildren := createChannels[int](3, 2)\n\trochildren := channelsToReadOnly(children)\n\tdefer closeChannels(children)\n\n\tis.Zero(DispatchingStrategyRoundRobin(42, 0, rochildren))\n\tis.Equal(1, DispatchingStrategyRoundRobin(42, 1, rochildren))\n\tis.Equal(2, DispatchingStrategyRoundRobin(42, 2, rochildren))\n\tis.Zero(DispatchingStrategyRoundRobin(42, 3, rochildren))\n}\n\nfunc TestDispatchingStrategyRandom(t *testing.T) {\n\tt.Parallel()\n\ttestWithTimeout(t, 100*time.Millisecond)\n\tis := assert.New(t)\n\n\tchildren := createChannels[int](2, 2)\n\trochildren := channelsToReadOnly(children)\n\tdefer closeChannels(children)\n\n\tfor i := 0; i < 2; i++ {\n\t\tchildren[1] <- i\n\t}\n\n\tis.Zero(DispatchingStrategyRandom(42, 0, rochildren))\n}\n\nfunc TestDispatchingStrategyWeightedRandom(t *testing.T) {\n\tt.Parallel()\n\ttestWithTimeout(t, 100*time.Millisecond)\n\tis := assert.New(t)\n\n\tchildren := createChannels[int](2, 2)\n\trochildren := channelsToReadOnly(children)\n\tdefer closeChannels(children)\n\n\tdispatcher := DispatchingStrategyWeightedRandom[int]([]int{0, 42})\n\n\tis.Equal(1, dispatcher(42, 0, rochildren))\n\tchildren[0] <- 0\n\tis.Equal(1, dispatcher(42, 0, rochildren))\n\tchildren[1] <- 1\n\tis.Equal(1, dispatcher(42, 0, rochildren))\n}\n\nfunc TestDispatchingStrategyFirst(t *testing.T) {\n\tt.Parallel()\n\ttestWithTimeout(t, 100*time.Millisecond)\n\tis := assert.New(t)\n\n\tchildren := createChannels[int](2, 2)\n\trochildren := channelsToReadOnly(children)\n\tdefer closeChannels(children)\n\n\tis.Zero(DispatchingStrategyFirst(42, 0, rochildren))\n\tchildren[0] <- 0\n\tis.Zero(DispatchingStrategyFirst(42, 0, rochildren))\n\tchildren[0] <- 1\n\tis.Equal(1, DispatchingStrategyFirst(42, 0, rochildren))\n}\n\nfunc TestDispatchingStrategyLeast(t *testing.T) {\n\tt.Parallel()\n\ttestWithTimeout(t, 100*time.Millisecond)\n\tis := assert.New(t)\n\n\tchildren := createChannels[int](2, 2)\n\trochildren := channelsToReadOnly(children)\n\tdefer closeChannels(children)\n\n\tis.Zero(DispatchingStrategyLeast(42, 0, rochildren))\n\tchildren[0] <- 0\n\tis.Equal(1, DispatchingStrategyLeast(42, 0, rochildren))\n\tchildren[1] <- 0\n\tis.Zero(DispatchingStrategyLeast(42, 0, rochildren))\n\tchildren[0] <- 1\n\tis.Equal(1, DispatchingStrategyLeast(42, 0, rochildren))\n\tchildren[1] <- 1\n\tis.Zero(DispatchingStrategyLeast(42, 0, rochildren))\n}\n\nfunc TestDispatchingStrategyMost(t *testing.T) {\n\tt.Parallel()\n\ttestWithTimeout(t, 100*time.Millisecond)\n\tis := assert.New(t)\n\n\tchildren := createChannels[int](2, 2)\n\trochildren := channelsToReadOnly(children)\n\tdefer closeChannels(children)\n\n\tis.Zero(DispatchingStrategyMost(42, 0, rochildren))\n\tchildren[0] <- 0\n\tis.Zero(DispatchingStrategyMost(42, 0, rochildren))\n\tchildren[1] <- 0\n\tis.Zero(DispatchingStrategyMost(42, 0, rochildren))\n\tchildren[0] <- 1\n\tis.Zero(DispatchingStrategyMost(42, 0, rochildren))\n\tchildren[1] <- 1\n\tis.Zero(DispatchingStrategyMost(42, 0, rochildren))\n}\n\nfunc TestSliceToChannel(t *testing.T) {\n\tt.Parallel()\n\ttestWithTimeout(t, 100*time.Millisecond)\n\tis := assert.New(t)\n\n\tch := SliceToChannel(2, []int{1, 2, 3})\n\n\tr1, ok1 := <-ch\n\tr2, ok2 := <-ch\n\tr3, ok3 := <-ch\n\tis.True(ok1)\n\tis.Equal(1, r1)\n\tis.True(ok2)\n\tis.Equal(2, r2)\n\tis.True(ok3)\n\tis.Equal(3, r3)\n\n\t_, ok4 := <-ch\n\tis.False(ok4)\n}\n\nfunc TestChannelToSlice(t *testing.T) {\n\tt.Parallel()\n\ttestWithTimeout(t, 100*time.Millisecond)\n\tis := assert.New(t)\n\n\tch := SliceToChannel(2, []int{1, 2, 3})\n\titems := ChannelToSlice(ch)\n\n\tis.Equal([]int{1, 2, 3}, items)\n}\n\nfunc TestGenerate(t *testing.T) {\n\tt.Parallel()\n\ttestWithTimeout(t, 100*time.Millisecond)\n\tis := assert.New(t)\n\n\tgenerator := func(yield func(int)) {\n\t\tyield(0)\n\t\tyield(1)\n\t\tyield(2)\n\t\tyield(3)\n\t}\n\n\ti := 0\n\n\tfor v := range Generator(2, generator) {\n\t\tis.Equal(i, v)\n\t\ti++\n\t}\n\n\tis.Equal(4, i)\n}\n\nfunc TestBuffer(t *testing.T) {\n\tt.Parallel()\n\ttestWithTimeout(t, 100*time.Millisecond)\n\tis := assert.New(t)\n\n\tch := SliceToChannel(2, []int{1, 2, 3})\n\n\titems1, length1, _, ok1 := Buffer(ch, 2)\n\titems2, length2, _, ok2 := Buffer(ch, 2)\n\titems3, length3, _, ok3 := Buffer(ch, 2)\n\n\tis.Equal([]int{1, 2}, items1)\n\tis.Equal(2, length1)\n\tis.True(ok1)\n\tis.Equal([]int{3}, items2)\n\tis.Equal(1, length2)\n\tis.False(ok2)\n\tis.Empty(items3)\n\tis.Zero(length3)\n\tis.False(ok3)\n}\n\nfunc TestBufferWithContext(t *testing.T) { //nolint:paralleltest\n\t// t.Parallel()\n\ttestWithTimeout(t, 200*time.Millisecond)\n\tis := assert.New(t)\n\n\tch1 := make(chan int, 10)\n\tctx, cancel := context.WithCancel(context.Background())\n\tgo func() {\n\t\tch1 <- 0\n\t\tch1 <- 1\n\t\tch1 <- 2\n\t\ttime.Sleep(5 * time.Millisecond)\n\t\tcancel()\n\t\tch1 <- 3\n\t\tch1 <- 4\n\t\tch1 <- 5\n\t\tclose(ch1)\n\t}()\n\titems1, length1, _, ok1 := BufferWithContext(ctx, ch1, 20)\n\tis.Equal([]int{0, 1, 2}, items1)\n\tis.Equal(3, length1)\n\tis.True(ok1)\n\n\tch2 := make(chan int, 10)\n\tctx, cancel = context.WithCancel(context.Background())\n\tdefer cancel()\n\tdefer close(ch2)\n\tfor i := 0; i < 10; i++ {\n\t\tch2 <- i\n\t}\n\titems2, length2, _, ok2 := BufferWithContext(ctx, ch2, 5)\n\tis.Equal([]int{0, 1, 2, 3, 4}, items2)\n\tis.Equal(5, length2)\n\tis.True(ok2)\n}\n\nfunc TestBufferWithTimeout(t *testing.T) { //nolint:paralleltest\n\t// t.Parallel()\n\ttestWithTimeout(t, 2000*time.Millisecond)\n\tis := assert.New(t)\n\n\tgenerator := func(n ...int) func(yield func(int)) {\n\t\treturn func(yield func(int)) {\n\t\t\tfor i := 0; i < len(n); i++ {\n\t\t\t\tyield(n[i])\n\t\t\t\ttime.Sleep(100 * time.Millisecond)\n\t\t\t}\n\t\t}\n\t}\n\n\tch := Generator(0, generator(0, 1, 2, 3, 4))\n\titems1, length1, duration1, ok1 := BufferWithTimeout(ch, 20, 150*time.Millisecond)\n\tis.Equal([]int{0, 1}, items1)\n\tis.Equal(2, length1)\n\tis.InDelta(150*time.Millisecond, duration1, float64(20*time.Millisecond))\n\tis.True(ok1)\n\n\titems2, length2, duration2, ok2 := BufferWithTimeout(ch, 20, 10*time.Millisecond)\n\tis.Empty(items2)\n\tis.Zero(length2)\n\tis.InDelta(10*time.Millisecond, duration2, float64(10*time.Millisecond))\n\tis.True(ok2)\n\n\titems3, length3, duration3, ok3 := BufferWithTimeout(ch, 1, 300*time.Millisecond)\n\tis.Equal([]int{2}, items3)\n\tis.Equal(1, length3)\n\tis.InDelta(50*time.Millisecond, duration3, float64(20*time.Millisecond))\n\tis.True(ok3)\n\n\titems4, length4, duration4, ok4 := BufferWithTimeout(ch, 2, 250*time.Millisecond)\n\tis.Equal([]int{3, 4}, items4)\n\tis.Equal(2, length4)\n\tis.InDelta(200*time.Millisecond, duration4, float64(50*time.Millisecond))\n\tis.True(ok4)\n\n\titems5, length5, duration5, ok5 := BufferWithTimeout(ch, 3, 250*time.Millisecond)\n\tis.Empty(items5)\n\tis.Zero(length5)\n\tis.InDelta(100*time.Millisecond, duration5, float64(50*time.Millisecond))\n\tis.False(ok5)\n\n\titems6, length6, duration6, ok6 := BufferWithTimeout(ch, 3, 250*time.Millisecond)\n\tis.Empty(items6)\n\tis.Zero(length6)\n\tis.InDelta(1*time.Millisecond, duration6, float64(10*time.Millisecond))\n\tis.False(ok6)\n}\n\nfunc TestFanIn(t *testing.T) { //nolint:paralleltest\n\t// t.Parallel()\n\ttestWithTimeout(t, 100*time.Millisecond)\n\tis := assert.New(t)\n\n\tupstreams := createChannels[int](3, 10)\n\troupstreams := channelsToReadOnly(upstreams)\n\tfor i := range roupstreams {\n\t\tgo func(i int) {\n\t\t\tupstreams[i] <- 1\n\t\t\tupstreams[i] <- 1\n\t\t\tclose(upstreams[i])\n\t\t}(i)\n\t}\n\tout := FanIn(10, roupstreams...)\n\ttime.Sleep(10 * time.Millisecond)\n\n\t// check input channels\n\tis.Empty(roupstreams[0])\n\tis.Empty(roupstreams[1])\n\tis.Empty(roupstreams[2])\n\n\t// check channels allocation\n\tis.Len(out, 6)\n\tis.Equal(10, cap(out))\n\n\t// check channels content\n\tfor i := 0; i < 6; i++ {\n\t\tmsg0, ok0 := <-out\n\t\tis.True(ok0)\n\t\tis.Equal(1, msg0)\n\t}\n\n\t// check it is closed\n\ttime.Sleep(10 * time.Millisecond)\n\tmsg0, ok0 := <-out\n\tis.False(ok0)\n\tis.Zero(msg0)\n}\n\nfunc TestFanOut(t *testing.T) { //nolint:paralleltest\n\t// t.Parallel()\n\ttestWithTimeout(t, 100*time.Millisecond)\n\tis := assert.New(t)\n\n\tupstream := SliceToChannel(10, []int{0, 1, 2, 3, 4, 5})\n\trodownstreams := FanOut(3, 10, upstream)\n\n\ttime.Sleep(10 * time.Millisecond)\n\n\t// check output channels\n\tis.Len(rodownstreams, 3)\n\n\t// check channels allocation\n\tfor i := range rodownstreams {\n\t\tis.Len(rodownstreams[i], 6)\n\t\tis.Equal(10, cap(rodownstreams[i]))\n\t\tis.Equal([]int{0, 1, 2, 3, 4, 5}, ChannelToSlice(rodownstreams[i]))\n\t}\n\n\t// check it is closed\n\ttime.Sleep(10 * time.Millisecond)\n\n\t// check channels allocation\n\tfor i := range rodownstreams {\n\t\tmsg, ok := <-rodownstreams[i]\n\t\tis.False(ok)\n\t\tis.Zero(msg)\n\t}\n}\n"
  },
  {
    "path": "concurrency.go",
    "content": "package lo\n\nimport (\n\t\"context\"\n\t\"sync\"\n\t\"time\"\n)\n\ntype synchronize struct {\n\tlocker sync.Locker\n}\n\nfunc (s *synchronize) Do(callback func()) {\n\ts.locker.Lock()\n\tTry0(callback)\n\ts.locker.Unlock()\n}\n\n// Synchronize wraps the underlying callback in a mutex. It receives an optional mutex.\n// Play: https://go.dev/play/p/X3cqROSpQmu\nfunc Synchronize(opt ...sync.Locker) *synchronize { //nolint:revive\n\tif len(opt) > 1 {\n\t\tpanic(\"lo.Synchronize: unexpected arguments\")\n\t} else if len(opt) == 0 {\n\t\topt = append(opt, &sync.Mutex{})\n\t}\n\n\treturn &synchronize{\n\t\tlocker: opt[0],\n\t}\n}\n\n// Async executes a function in a goroutine and returns the result in a channel.\n// Play: https://go.dev/play/p/uo35gosuTLw\nfunc Async[A any](f func() A) <-chan A {\n\tch := make(chan A, 1)\n\tgo func() {\n\t\tch <- f()\n\t}()\n\treturn ch\n}\n\n// Async0 executes a function in a goroutine and returns a channel set once the function finishes.\n// Play: https://go.dev/play/p/tNqf1cClG_o\nfunc Async0(f func()) <-chan struct{} {\n\tch := make(chan struct{}, 1)\n\tgo func() {\n\t\tf()\n\t\tch <- struct{}{}\n\t}()\n\treturn ch\n}\n\n// Async1 is an alias to Async.\n// Play: https://go.dev/play/p/RBQWtIn4PsF\nfunc Async1[A any](f func() A) <-chan A {\n\treturn Async(f)\n}\n\n// Async2 has the same behavior as Async, but returns the 2 results as a tuple inside the channel.\n// Play: https://go.dev/play/p/5SzzDjssXOH\nfunc Async2[A, B any](f func() (A, B)) <-chan Tuple2[A, B] {\n\tch := make(chan Tuple2[A, B], 1)\n\tgo func() {\n\t\tch <- T2(f())\n\t}()\n\treturn ch\n}\n\n// Async3 has the same behavior as Async, but returns the 3 results as a tuple inside the channel.\n// Play: https://go.dev/play/p/cZpZsDXNmlx\nfunc Async3[A, B, C any](f func() (A, B, C)) <-chan Tuple3[A, B, C] {\n\tch := make(chan Tuple3[A, B, C], 1)\n\tgo func() {\n\t\tch <- T3(f())\n\t}()\n\treturn ch\n}\n\n// Async4 has the same behavior as Async, but returns the 4 results as a tuple inside the channel.\n// Play: https://go.dev/play/p/9X5O2VrLzkR\nfunc Async4[A, B, C, D any](f func() (A, B, C, D)) <-chan Tuple4[A, B, C, D] {\n\tch := make(chan Tuple4[A, B, C, D], 1)\n\tgo func() {\n\t\tch <- T4(f())\n\t}()\n\treturn ch\n}\n\n// Async5 has the same behavior as Async, but returns the 5 results as a tuple inside the channel.\n// Play: https://go.dev/play/p/MqnUJpkmopA\nfunc Async5[A, B, C, D, E any](f func() (A, B, C, D, E)) <-chan Tuple5[A, B, C, D, E] {\n\tch := make(chan Tuple5[A, B, C, D, E], 1)\n\tgo func() {\n\t\tch <- T5(f())\n\t}()\n\treturn ch\n}\n\n// Async6 has the same behavior as Async, but returns the 6 results as a tuple inside the channel.\n// Play: https://go.dev/play/p/kM1X67JPdSP\nfunc Async6[A, B, C, D, E, F any](f func() (A, B, C, D, E, F)) <-chan Tuple6[A, B, C, D, E, F] {\n\tch := make(chan Tuple6[A, B, C, D, E, F], 1)\n\tgo func() {\n\t\tch <- T6(f())\n\t}()\n\treturn ch\n}\n\n// WaitFor runs periodically until a condition is validated.\n// Play: https://go.dev/play/p/t_wTDmubbK3\nfunc WaitFor(condition func(i int) bool, timeout, heartbeatDelay time.Duration) (totalIterations int, elapsed time.Duration, conditionFound bool) {\n\tconditionWithContext := func(_ context.Context, currentIteration int) bool {\n\t\treturn condition(currentIteration)\n\t}\n\treturn WaitForWithContext(context.Background(), conditionWithContext, timeout, heartbeatDelay)\n}\n\n// WaitForWithContext runs periodically until a condition is validated or context is canceled.\n// Play: https://go.dev/play/p/t_wTDmubbK3\nfunc WaitForWithContext(ctx context.Context, condition func(ctx context.Context, currentIteration int) bool, timeout, heartbeatDelay time.Duration) (totalIterations int, elapsed time.Duration, conditionFound bool) {\n\tstart := time.Now()\n\n\tif ctx.Err() != nil {\n\t\treturn totalIterations, time.Since(start), false\n\t}\n\n\tctx, cleanCtx := context.WithTimeout(ctx, timeout)\n\tticker := time.NewTicker(heartbeatDelay)\n\n\tdefer func() {\n\t\tcleanCtx()\n\t\tticker.Stop()\n\t}()\n\n\tfor {\n\t\tselect {\n\t\tcase <-ctx.Done():\n\t\t\treturn totalIterations, time.Since(start), false\n\t\tcase <-ticker.C:\n\t\t\ttotalIterations++\n\t\t\tif condition(ctx, totalIterations-1) {\n\t\t\t\treturn totalIterations, time.Since(start), true\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "concurrency_test.go",
    "content": "package lo\n\nimport (\n\t\"context\"\n\t\"sync\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestSynchronize(t *testing.T) { //nolint:paralleltest\n\t// t.Parallel()\n\ttestWithTimeout(t, 1000*time.Millisecond)\n\tis := assert.New(t)\n\n\t// check that callbacks are not executed concurrently\n\t{\n\t\tstart := time.Now()\n\n\t\twg := sync.WaitGroup{}\n\t\twg.Add(10)\n\n\t\ts := Synchronize()\n\n\t\tfor i := 0; i < 10; i++ {\n\t\t\tgo s.Do(func() {\n\t\t\t\ttime.Sleep(50 * time.Millisecond)\n\t\t\t\twg.Done()\n\t\t\t})\n\t\t}\n\n\t\twg.Wait()\n\n\t\tduration := time.Since(start)\n\t\tis.InDelta(500*time.Millisecond, duration, float64(40*time.Millisecond))\n\t}\n\n\t// check locker is locked\n\t{\n\t\tmu := &sync.Mutex{}\n\t\ts := Synchronize(mu)\n\n\t\ts.Do(func() {\n\t\t\tis.False(mu.TryLock())\n\t\t})\n\t\tis.True(mu.TryLock())\n\n\t\tTry0(func() {\n\t\t\tmu.Unlock()\n\t\t})\n\t}\n\n\t// check we don't accept multiple arguments\n\t{\n\t\tis.PanicsWithValue(\"lo.Synchronize: unexpected arguments\", func() {\n\t\t\tmu := &sync.Mutex{}\n\t\t\tSynchronize(mu, mu, mu)\n\t\t})\n\t}\n}\n\nfunc TestAsync(t *testing.T) { //nolint:paralleltest\n\t// t.Parallel()\n\ttestWithTimeout(t, 100*time.Millisecond)\n\tis := assert.New(t)\n\n\tsync := make(chan struct{})\n\n\tch := Async(func() int {\n\t\t<-sync\n\t\treturn 10\n\t})\n\n\tsync <- struct{}{}\n\n\tselect {\n\tcase result := <-ch:\n\t\tis.Equal(10, result)\n\tcase <-time.After(time.Millisecond):\n\t\tis.Fail(\"Async should not block\")\n\t}\n}\n\nfunc TestAsyncX(t *testing.T) { //nolint:paralleltest\n\t// t.Parallel()\n\ttestWithTimeout(t, 100*time.Millisecond)\n\tis := assert.New(t)\n\n\t{\n\t\tsync := make(chan struct{})\n\n\t\tch := Async0(func() {\n\t\t\t<-sync\n\t\t})\n\n\t\tsync <- struct{}{}\n\n\t\tselect {\n\t\tcase <-ch:\n\t\tcase <-time.After(time.Millisecond):\n\t\t\tis.Fail(\"Async0 should not block\")\n\t\t}\n\t}\n\n\t{\n\t\tsync := make(chan struct{})\n\n\t\tch := Async1(func() int {\n\t\t\t<-sync\n\t\t\treturn 10\n\t\t})\n\n\t\tsync <- struct{}{}\n\n\t\tselect {\n\t\tcase result := <-ch:\n\t\t\tis.Equal(10, result)\n\t\tcase <-time.After(time.Millisecond):\n\t\t\tis.Fail(\"Async1 should not block\")\n\t\t}\n\t}\n\n\t{\n\t\tsync := make(chan struct{})\n\n\t\tch := Async2(func() (int, string) {\n\t\t\t<-sync\n\t\t\treturn 10, \"Hello\"\n\t\t})\n\n\t\tsync <- struct{}{}\n\n\t\tselect {\n\t\tcase result := <-ch:\n\t\t\tis.Equal(Tuple2[int, string]{10, \"Hello\"}, result)\n\t\tcase <-time.After(time.Millisecond):\n\t\t\tis.Fail(\"Async2 should not block\")\n\t\t}\n\t}\n\n\t{\n\t\tsync := make(chan struct{})\n\n\t\tch := Async3(func() (int, string, bool) {\n\t\t\t<-sync\n\t\t\treturn 10, \"Hello\", true\n\t\t})\n\n\t\tsync <- struct{}{}\n\n\t\tselect {\n\t\tcase result := <-ch:\n\t\t\tis.Equal(Tuple3[int, string, bool]{10, \"Hello\", true}, result)\n\t\tcase <-time.After(time.Millisecond):\n\t\t\tis.Fail(\"Async3 should not block\")\n\t\t}\n\t}\n\n\t{\n\t\tsync := make(chan struct{})\n\n\t\tch := Async4(func() (int, string, bool, float64) {\n\t\t\t<-sync\n\t\t\treturn 10, \"Hello\", true, 3.14\n\t\t})\n\n\t\tsync <- struct{}{}\n\n\t\tselect {\n\t\tcase result := <-ch:\n\t\t\tis.Equal(Tuple4[int, string, bool, float64]{10, \"Hello\", true, 3.14}, result)\n\t\tcase <-time.After(time.Millisecond):\n\t\t\tis.Fail(\"Async4 should not block\")\n\t\t}\n\t}\n\n\t{\n\t\tsync := make(chan struct{})\n\n\t\tch := Async5(func() (int, string, bool, float64, string) {\n\t\t\t<-sync\n\t\t\treturn 10, \"Hello\", true, 3.14, \"World\"\n\t\t})\n\n\t\tsync <- struct{}{}\n\n\t\tselect {\n\t\tcase result := <-ch:\n\t\t\tis.Equal(Tuple5[int, string, bool, float64, string]{10, \"Hello\", true, 3.14, \"World\"}, result)\n\t\tcase <-time.After(time.Millisecond):\n\t\t\tis.Fail(\"Async5 should not block\")\n\t\t}\n\t}\n\n\t{\n\t\tsync := make(chan struct{})\n\n\t\tch := Async6(func() (int, string, bool, float64, string, int) {\n\t\t\t<-sync\n\t\t\treturn 10, \"Hello\", true, 3.14, \"World\", 100\n\t\t})\n\n\t\tsync <- struct{}{}\n\n\t\tselect {\n\t\tcase result := <-ch:\n\t\t\tis.Equal(Tuple6[int, string, bool, float64, string, int]{10, \"Hello\", true, 3.14, \"World\", 100}, result)\n\t\tcase <-time.After(time.Millisecond):\n\t\t\tis.Fail(\"Async6 should not block\")\n\t\t}\n\t}\n}\n\nfunc TestWaitFor(t *testing.T) { //nolint:paralleltest\n\t// t.Parallel()\n\n\tt.Run(\"exist condition works\", func(t *testing.T) { //nolint:paralleltest\n\t\t// t.Parallel()\n\n\t\ttestWithTimeout(t, 300*time.Millisecond)\n\t\tis := assert.New(t)\n\n\t\tlaterTrue := func(i int) bool {\n\t\t\treturn i >= 5\n\t\t}\n\n\t\titer, duration, ok := WaitFor(laterTrue, 200*time.Millisecond, 10*time.Millisecond)\n\t\tis.Equal(6, iter, \"unexpected iteration count\")\n\t\tis.InDelta(60*time.Millisecond, duration, float64(5*time.Millisecond))\n\t\tis.True(ok)\n\t})\n\n\tt.Run(\"counter is incremented\", func(t *testing.T) { //nolint:paralleltest\n\t\t// t.Parallel()\n\n\t\ttestWithTimeout(t, 100*time.Millisecond)\n\t\tis := assert.New(t)\n\n\t\tcounter := 0\n\t\talwaysFalse := func(i int) bool {\n\t\t\tis.Equal(counter, i)\n\t\t\tcounter++\n\t\t\treturn false\n\t\t}\n\n\t\titer, duration, ok := WaitFor(alwaysFalse, 40*time.Millisecond, 10*time.Millisecond)\n\t\tis.Equal(counter, iter, \"unexpected iteration count\")\n\t\tis.InDelta(40*time.Millisecond, duration, float64(5*time.Millisecond))\n\t\tis.False(ok)\n\t})\n\n\talwaysTrue := func(_ int) bool { return true }\n\talwaysFalse := func(_ int) bool { return false }\n\n\tt.Run(\"timeout works\", func(t *testing.T) { //nolint:paralleltest\n\t\t// t.Parallel()\n\n\t\ttestWithTimeout(t, 200*time.Millisecond)\n\t\tis := assert.New(t)\n\n\t\titer, duration, ok := WaitFor(alwaysFalse, 50*time.Millisecond, 100*time.Millisecond)\n\t\tis.Zero(iter, \"unexpected iteration count\")\n\t\tis.InDelta(50*time.Millisecond, duration, float64(10*time.Millisecond))\n\t\tis.False(ok)\n\t})\n\n\tt.Run(\"exist on first condition\", func(t *testing.T) { //nolint:paralleltest\n\t\t// t.Parallel()\n\n\t\ttestWithTimeout(t, 200*time.Millisecond)\n\t\tis := assert.New(t)\n\n\t\titer, duration, ok := WaitFor(alwaysTrue, 100*time.Millisecond, 30*time.Millisecond)\n\t\tis.Equal(1, iter, \"unexpected iteration count\")\n\t\tis.InDelta(30*time.Millisecond, duration, float64(10*time.Millisecond))\n\t\tis.True(ok)\n\t})\n}\n\nfunc TestWaitForWithContext(t *testing.T) { //nolint:paralleltest\n\t// t.Parallel()\n\n\tt.Run(\"exist condition works\", func(t *testing.T) { //nolint:paralleltest\n\t\t// t.Parallel()\n\n\t\ttestWithTimeout(t, 200*time.Millisecond)\n\t\tis := assert.New(t)\n\n\t\tlaterTrue := func(_ context.Context, i int) bool {\n\t\t\treturn i >= 5\n\t\t}\n\n\t\titer, duration, ok := WaitForWithContext(context.Background(), laterTrue, 200*time.Millisecond, 10*time.Millisecond)\n\t\tis.Equal(6, iter, \"unexpected iteration count\")\n\t\tis.InDelta(60*time.Millisecond, duration, float64(5*time.Millisecond))\n\t\tis.True(ok)\n\t})\n\n\tt.Run(\"counter is incremented\", func(t *testing.T) { //nolint:paralleltest\n\t\t// t.Parallel()\n\n\t\ttestWithTimeout(t, 150*time.Millisecond)\n\t\tis := assert.New(t)\n\n\t\tcounter := 0\n\t\talwaysFalse := func(_ context.Context, i int) bool {\n\t\t\tis.Equal(counter, i)\n\t\t\tcounter++\n\t\t\treturn false\n\t\t}\n\n\t\titer, duration, ok := WaitForWithContext(context.Background(), alwaysFalse, 80*time.Millisecond, 20*time.Millisecond)\n\t\tis.Equal(counter, iter, \"unexpected iteration count\")\n\t\tis.InDelta(80*time.Millisecond, duration, float64(10*time.Millisecond))\n\t\tis.False(ok)\n\t})\n\n\talwaysTrue := func(_ context.Context, _ int) bool { return true }\n\talwaysFalse := func(_ context.Context, _ int) bool { return false }\n\n\tt.Run(\"timeout works\", func(t *testing.T) { //nolint:paralleltest\n\t\t// t.Parallel()\n\n\t\ttestWithTimeout(t, 200*time.Millisecond)\n\t\tis := assert.New(t)\n\n\t\titer, duration, ok := WaitForWithContext(context.Background(), alwaysFalse, 50*time.Millisecond, 100*time.Millisecond)\n\t\tis.Zero(iter, \"unexpected iteration count\")\n\t\tis.InDelta(50*time.Millisecond, duration, float64(10*time.Millisecond))\n\t\tis.False(ok)\n\t})\n\n\tt.Run(\"exist on first condition\", func(t *testing.T) { //nolint:paralleltest\n\t\t// t.Parallel()\n\n\t\ttestWithTimeout(t, 200*time.Millisecond)\n\t\tis := assert.New(t)\n\n\t\titer, duration, ok := WaitForWithContext(context.Background(), alwaysTrue, 100*time.Millisecond, 10*time.Millisecond)\n\t\tis.Equal(1, iter, \"unexpected iteration count\")\n\t\tis.InDelta(10*time.Millisecond, duration, float64(5*time.Millisecond))\n\t\tis.True(ok)\n\t})\n\n\tt.Run(\"context cancellation stops everything\", func(t *testing.T) { //nolint:paralleltest\n\t\t// t.Parallel()\n\n\t\ttestWithTimeout(t, 100*time.Millisecond)\n\t\tis := assert.New(t)\n\n\t\texpiringCtx, clean := context.WithTimeout(context.Background(), 45*time.Millisecond)\n\t\tt.Cleanup(func() {\n\t\t\tclean()\n\t\t})\n\n\t\titer, duration, ok := WaitForWithContext(expiringCtx, alwaysFalse, 100*time.Millisecond, 30*time.Millisecond)\n\t\tis.Equal(1, iter, \"unexpected iteration count\")\n\t\tis.InDelta(45*time.Millisecond, duration, float64(10*time.Millisecond))\n\t\tis.False(ok)\n\t})\n\n\tt.Run(\"canceled context stops everything\", func(t *testing.T) { //nolint:paralleltest\n\t\t// t.Parallel()\n\n\t\ttestWithTimeout(t, 200*time.Millisecond)\n\t\tis := assert.New(t)\n\n\t\tcanceledCtx, cancel := context.WithCancel(context.Background())\n\t\tcancel()\n\n\t\titer, duration, ok := WaitForWithContext(canceledCtx, alwaysFalse, 100*time.Millisecond, 30*time.Millisecond)\n\t\tis.Zero(iter, \"unexpected iteration count\")\n\t\tis.InDelta(1*time.Millisecond, duration, float64(1*time.Millisecond))\n\t\tis.False(ok)\n\t})\n}\n"
  },
  {
    "path": "condition.go",
    "content": "package lo\n\n// Ternary is a single line if/else statement.\n// Take care to avoid dereferencing potentially nil pointers in your A/B expressions, because they are both evaluated. See TernaryF to avoid this problem.\n// Play: https://go.dev/play/p/t-D7WBL44h2\nfunc Ternary[T any](condition bool, ifOutput, elseOutput T) T {\n\tif condition {\n\t\treturn ifOutput\n\t}\n\n\treturn elseOutput\n}\n\n// TernaryF is a single line if/else statement whose options are functions.\n// Play: https://go.dev/play/p/AO4VW20JoqM\nfunc TernaryF[T any](condition bool, ifFunc, elseFunc func() T) T {\n\tif condition {\n\t\treturn ifFunc()\n\t}\n\n\treturn elseFunc()\n}\n\n// Perf: value receivers (not pointer) allow the compiler to fully inline the entire\n// If().ElseIf().Else() chain, eliminating all function call overhead.\ntype ifElse[T any] struct {\n\tresult T\n\tdone   bool\n}\n\n// If is a single line if/else statement.\n// Play: https://go.dev/play/p/WSw3ApMxhyW\nfunc If[T any](condition bool, result T) ifElse[T] { //nolint:revive\n\tif condition {\n\t\treturn ifElse[T]{result, true}\n\t}\n\n\tvar t T\n\treturn ifElse[T]{t, false}\n}\n\n// IfF is a single line if/else statement whose options are functions.\n// Play: https://go.dev/play/p/WSw3ApMxhyW\nfunc IfF[T any](condition bool, resultF func() T) ifElse[T] { //nolint:revive\n\tif condition {\n\t\treturn ifElse[T]{resultF(), true}\n\t}\n\n\tvar t T\n\treturn ifElse[T]{t, false}\n}\n\n// ElseIf.\n// Play: https://go.dev/play/p/WSw3ApMxhyW\nfunc (i ifElse[T]) ElseIf(condition bool, result T) ifElse[T] {\n\tif !i.done && condition {\n\t\ti.result = result\n\t\ti.done = true\n\t}\n\n\treturn i\n}\n\n// ElseIfF.\n// Play: https://go.dev/play/p/WSw3ApMxhyW\nfunc (i ifElse[T]) ElseIfF(condition bool, resultF func() T) ifElse[T] {\n\tif !i.done && condition {\n\t\ti.result = resultF()\n\t\ti.done = true\n\t}\n\n\treturn i\n}\n\n// Else.\n// Play: https://go.dev/play/p/WSw3ApMxhyW\nfunc (i ifElse[T]) Else(result T) T {\n\tif i.done {\n\t\treturn i.result\n\t}\n\n\treturn result\n}\n\n// ElseF.\n// Play: https://go.dev/play/p/WSw3ApMxhyW\nfunc (i ifElse[T]) ElseF(resultF func() T) T {\n\tif i.done {\n\t\treturn i.result\n\t}\n\n\treturn resultF()\n}\n\n// Perf: value receivers (not pointer) allow the compiler to fully inline the entire\n// Switch().Case().Default() chain, eliminating all function call overhead.\ntype switchCase[T comparable, R any] struct {\n\tpredicate T\n\tresult    R\n\tdone      bool\n}\n\n// Switch is a pure functional switch/case/default statement.\n// Play: https://go.dev/play/p/TGbKUMAeRUd\nfunc Switch[T comparable, R any](predicate T) switchCase[T, R] { //nolint:revive\n\tvar result R\n\n\treturn switchCase[T, R]{\n\t\tpredicate,\n\t\tresult,\n\t\tfalse,\n\t}\n}\n\n// Case.\n// Play: https://go.dev/play/p/TGbKUMAeRUd\nfunc (s switchCase[T, R]) Case(val T, result R) switchCase[T, R] {\n\tif !s.done && s.predicate == val {\n\t\ts.result = result\n\t\ts.done = true\n\t}\n\n\treturn s\n}\n\n// CaseF.\n// Play: https://go.dev/play/p/TGbKUMAeRUd\nfunc (s switchCase[T, R]) CaseF(val T, callback func() R) switchCase[T, R] {\n\tif !s.done && s.predicate == val {\n\t\ts.result = callback()\n\t\ts.done = true\n\t}\n\n\treturn s\n}\n\n// Default.\n// Play: https://go.dev/play/p/TGbKUMAeRUd\nfunc (s switchCase[T, R]) Default(result R) R {\n\tif !s.done {\n\t\ts.result = result\n\t}\n\n\treturn s.result\n}\n\n// DefaultF.\n// Play: https://go.dev/play/p/TGbKUMAeRUd\nfunc (s switchCase[T, R]) DefaultF(callback func() R) R {\n\tif !s.done {\n\t\ts.result = callback()\n\t}\n\n\treturn s.result\n}\n"
  },
  {
    "path": "condition_test.go",
    "content": "package lo\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestTernary(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := Ternary(true, \"a\", \"b\")\n\tresult2 := Ternary(false, \"a\", \"b\")\n\n\tis.Equal(\"a\", result1)\n\tis.Equal(\"b\", result2)\n}\n\nfunc TestTernaryF(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := TernaryF(true, func() string { return \"a\" }, func() string { return \"b\" })\n\tresult2 := TernaryF(false, func() string { return \"a\" }, func() string { return \"b\" })\n\n\tis.Equal(\"a\", result1)\n\tis.Equal(\"b\", result2)\n}\n\nfunc TestIfElse(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := If(true, 1).ElseIf(false, 2).Else(3)\n\tresult2 := If(true, 1).ElseIf(true, 2).Else(3)\n\tresult3 := If(false, 1).ElseIf(true, 2).Else(3)\n\tresult4 := If(false, 1).ElseIf(false, 2).Else(3)\n\n\tis.Equal(1, result1)\n\tis.Equal(1, result2)\n\tis.Equal(2, result3)\n\tis.Equal(3, result4)\n}\n\nfunc TestIfFElseF(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := IfF(true, func() int { return 1 }).ElseIfF(false, func() int { return 2 }).ElseF(func() int { return 3 })\n\tresult2 := IfF(true, func() int { return 1 }).ElseIfF(true, func() int { return 2 }).ElseF(func() int { return 3 })\n\tresult3 := IfF(false, func() int { return 1 }).ElseIfF(true, func() int { return 2 }).ElseF(func() int { return 3 })\n\tresult4 := IfF(false, func() int { return 1 }).ElseIfF(false, func() int { return 2 }).ElseF(func() int { return 3 })\n\n\tis.Equal(1, result1)\n\tis.Equal(1, result2)\n\tis.Equal(2, result3)\n\tis.Equal(3, result4)\n}\n\nfunc TestSwitchCase(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := Switch[int, int](42).Case(42, 1).Case(1, 2).Default(3)\n\tresult2 := Switch[int, int](42).Case(42, 1).Case(42, 2).Default(3)\n\tresult3 := Switch[int, int](42).Case(1, 1).Case(42, 2).Default(3)\n\tresult4 := Switch[int, int](42).Case(1, 1).Case(1, 2).Default(3)\n\n\tis.Equal(1, result1)\n\tis.Equal(1, result2)\n\tis.Equal(2, result3)\n\tis.Equal(3, result4)\n}\n\nfunc TestSwitchCaseF(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := Switch[int, int](42).CaseF(42, func() int { return 1 }).CaseF(1, func() int { return 2 }).DefaultF(func() int { return 3 })\n\tresult2 := Switch[int, int](42).CaseF(42, func() int { return 1 }).CaseF(42, func() int { return 2 }).DefaultF(func() int { return 3 })\n\tresult3 := Switch[int, int](42).CaseF(1, func() int { return 1 }).CaseF(42, func() int { return 2 }).DefaultF(func() int { return 3 })\n\tresult4 := Switch[int, int](42).CaseF(1, func() int { return 1 }).CaseF(1, func() int { return 2 }).DefaultF(func() int { return 3 })\n\n\tis.Equal(1, result1)\n\tis.Equal(1, result2)\n\tis.Equal(2, result3)\n\tis.Equal(3, result4)\n}\n"
  },
  {
    "path": "constraints.go",
    "content": "package lo\n\n// Clonable defines a constraint of types having Clone() T method.\ntype Clonable[T any] interface {\n\tClone() T\n}\n"
  },
  {
    "path": "docs/.gitignore",
    "content": "# Dependencies\n/node_modules\n\n# Production\n/build\n\n# Generated files\n.docusaurus\n.cache-loader\n\n# Misc\n.DS_Store\n.env.local\n.env.development.local\n.env.test.local\n.env.production.local\n\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n"
  },
  {
    "path": "docs/CLAUDE.md",
    "content": "# Adding New Helper Documentation\n\nWhen adding a new helper to the `lo` library, follow these guidelines to create or update documentation files in the `docs/data/` directory.\n\n## File Structure\n\nDocumentation files follow the naming pattern `core-{helper-name}.md` for core helpers.\n\n### Frontmatter Format\n\nEach documentation file must start with a frontmatter section:\n\n```yaml\n---\nname: HelperName\nslug: helpername\nsourceRef: file.go#L123\ncategory: core\nsubCategory: slice\nsignatures:\n  - \"func HelperName(params) returnType\"\n  - \"func (receiver *Type) MethodName(params) returnType\"\n  - \"func HelperNameI(params) returnType\"\n  - \"func HelperNameWithContext(params) returnType\"\nplayUrl: https://go.dev/play/p/EXAMPLE\nvariantHelpers:\n  - core#slice#helpername\n  - core#slice#helpername2\n  - core#slice#helpername3\n  - core#slice#helpername4\n  - core#slice#helpername5\n  - core#slice#helpernamei\n  - core#slice#helpernamewithcontext\nsimilarHelpers:\n  - mutable#slice#helpername\n  - core#slice#filterhelpername\n  - core#slice#zipx\nposition: 0\n---\n```\n\n### Frontmatter Fields\n\n- **name**: The display name of the helper (PascalCase)\n- **slug**: URL-friendly name (kebab-case, matches filename without `core-` prefix)\n- **sourceRef**: Source file reference with line number (format: `file.go#L123`)\n- **category**: `core`, `mutable`, `parallel`, `it`... The category must match the file name.\n- **subCategory**: The functional category (e.g., `condition`, `map`, `find`, `slice`...)\n- **signatures**: Array of function signatures as strings. Do not list signatures from other sub-packages/category.\n- **playUrl**: Go Playground URL with working example\n- **variantHelpers**: Array of variant helper names. Must contain at least the default helper named above. This field is for:\n  - Variations of the same helper with different signatures (e.g., `Map`, `MapI`, `MapWithContext`, `MapIWithContext`)\n  - Helper variants that add functionality like indexes, context, or different parameter types\n  - All variants must be in the same category and subcategory as the main helper\n  - Examples: `core#slice#map`, `core#slice#mapi`, `core#slice#mapwithcontext`\n- **similarHelpers**: Array of related helper names (leave empty if none). This field is for:\n  - Equivalent helpers in other packages/categories (e.g., `parallel#slice#Map`, `mutable#slice#Filter`)\n  - Helper compositions or related functionality (e.g., `FilterMap` is similar to both `Map` and `Filter`)\n  - Helpers with different names but similar purposes (e.g., `FindBy` variants vs base `Find`)\n  - Cross-references to helpers that users might want to consider as alternatives\n- **position**: Position in the list (0, 10, 20, 30...). Order must follow the order in source code. Helpers are grouped by category+sub-category and displayed on a page. Position number is reset for each page.\n\n## Content Structure\n\nAfter the frontmatter, include:\n\n1. **Brief description**: One sentence explaining what the helper does\n2. **Code example**: Working Go code demonstrating usage\n3. **Expected output**: Comment showing the result\n\n```markdown\nBrief description of what this helper does. Be concise and not too long.\n\n```go\nresult := lo.HelperName(example)\n// expected result\n```\n```\n\nMultiple examples can be used for demonstration the helper, such as edge cases. If multiple signatures are grouped under this documentation, it could be useful to describe some (all?) of them.\n\n## Understanding variantHelpers vs similarHelpers\n\n### variantHelpers\nUse `variantHelpers` for different versions of the **same helper function**:\n\n**Example**: Map helper variants (all in `core#slice#map`):\n```yaml\nvariantHelpers:\n  - core#slice#map        # func Map[T, R]([]T, func(T, int) R) []R\n  - core#slice#maperr     # func MapErr[T, R]([]T, func(T, int) (R, error)) ([]R, error)\n  - core#slice#mapi       # func MapI[T, R]([]T, func(T, int) R) []R (with index)\n  - core#slice#mapwithcontext  # func MapWithContext[T, R]([]T, func(T, int, context.Context) R, context.Context) []R\n```\n\n### similarHelpers\nUse `similarHelpers` for **related but different helpers**:\n\n**Example**: FilterMap combines Map and Filter functionality:\n```yaml\nsimilarHelpers:\n  - core#slice#map        # Related transformation helper\n  - core#slice#filter     # Related filtering helper\n```\n\n**Example**: Cross-package equivalents:\n```yaml\nsimilarHelpers:\n  - parallel#slice#map    # Parallel version in different package\n  - mutable#slice#map     # Mutable version in different package\n  - mutable#slice#zipx     # Mutable version in different package\n```\n\n**Example**: Related helpers with similar functionality:\n```yaml\nsimilarHelpers:\n  - core#slice#find       # Single result search\n  - core#slice#filter     # Multiple result filtering\n  - core#slice#findby     # Key-based search\n  - core#slice#findorelse # Search with default value\n```\n\n**Example**: Helper families with similar patterns:\n```yaml\nsimilarHelpers:\n  - core#slice#min        # Find minimum value\n  - core#slice#max        # Find maximum value\n  - core#slice#minby      # Find minimum by key function\n  - core#slice#maxby      # Find maximum by key function\n  - core#slice#minindex   # Find minimum value index\n  - core#slice#maxindex   # Find maximum value index\n```\n\n**Example**: Composition helpers that combine multiple operations:\n```yaml\nsimilarHelpers:\n  - core#slice#filtermap  # Filter + Map combination\n  - core#slice#mapkeys    # Map to extract keys\n  - core#slice#mapvalues # Map to extract values\n```\n\nWhen you add similarHelpers to a new helper, please update the linked similar helpers documentation, and add the one you're adding.\n\nDon't link helpers having numeric declensions (eg: use core#slice#zipx instead of core#slice#zip2).\n\n### Key Differences\n- **variantHelpers**: Same helper, different signatures/parameters (same package)\n- **similarHelpers**: Different helpers, related functionality (can be cross-package)\n\n## Grouping Related Helpers\n\nWhen multiple helpers operate on the same struct or serve similar purposes, consolidate them into a single file:\n\n**Example**: Map helpers:\n- `Map()` base helper\n- `MapI()` add index to predicate callback\n- `MapWithContext()` add context to predicate callback\n- `MapIWithContext()` add index and context to predicate callback\n\n**Example**: Switch helpers all operate on `switchCase[T, R]`:\n- `Switch()` - constructor\n- `Case()` - method for adding cases\n- `CaseF()` - method for adding cases with functions\n- `Default()` - method for default values\n- `DefaultF()` - method for default values with functions\n\nIn such cases:\n1. Use the primary helper name in the filename (e.g., `core-switch.md`)\n2. Include all related signatures in the `signatures` array\n3. List all related helpers in `variantHelpers` array\n4. Document each helper in its own section with `### HelperName` headers\n\n## Naming Conventions\n\n### Categories\nUse these established subCategories:\n- `condition` - conditional logic (if/else, switch)\n- `map` - transformation functions\n- `find` - search and lookup functions\n- `slice` - array manipulation\n- `math` - mathematical operations\n- `string` - string operations\n- `type` - type utilities\n- `error-handling` - error management\n- `retry` - retry mechanisms\n- `time` - time operations\n- `function` - function utilities\n- `channel` - channel operations\n- `tuple` - tuple operations\n- `intersect` - set intersections\n\n### Helper Names\n- Follow Go naming conventions (PascalCase for exported)\n- Use descriptive names that clearly indicate purpose\n- For function variants, use consistent suffixes:\n  - `F` suffix for function-based versions (lazy evaluation)\n  - `I` suffix for variants having `index int` argument in predicate callback\n  - `Err` suffix for variants returning an error in predicate callback\n  - `WithContext` suffix when context.Context is provided\n  - `X` suffix for helpers with varying arguments (eg: MustX: Must2, Must3, Must4...)\n\n## Go Playground Examples\n\nEvery helper must have a working Go Playground example linked in two places:\n\n1. **Source code**: `// Play: <url>` comment on the last line of the doc block, right before the `func` keyword\n2. **Doc file**: `playUrl: <url>` field in the YAML frontmatter of `docs/data/<category>-<slug>.md`\n\n### Creating a New Playground Example\n\n#### Step 1: Write the Example Code\n\nWrite a minimal, self-contained `main.go` that demonstrates the helper. Guidelines:\n\n- Use realistic but simple data\n- Print the result with `fmt.Println` so the output is visible\n- Include edge cases when useful (e.g., empty input, error case)\n- For `Err` variants, show both a success and an error case\n- For time-based helpers, use `time.Date()` for deterministic output\n- For random helpers (`SampleBy`, `SamplesBy`), use `rand.New(rand.NewSource(42))` for reproducible output\n\n#### Step 2: Import Conventions\n\nUse the correct import path depending on the package:\n\n```go\n// Core helpers\nimport \"github.com/samber/lo\"\n// Usage: lo.Map(...)\n\n// Iterator helpers (it/ package, requires Go 1.23+)\nimport (\n    \"slices\"\n    \"github.com/samber/lo/it\"\n)\n// Usage: slices.Collect(it.Map(...))\n// Convert slices to iterators: slices.Values([]int{1, 2, 3})\n\n// Parallel helpers\nimport lop \"github.com/samber/lo/parallel\"\n// Usage: lop.Map(...)\n```\n\n#### Step 3: Run and Share via Go Playground\n\nUse the `go-playground` MCP tool to execute the example and get a shareable URL:\n\n```\nmcp__go-playground__run_and_share_go_code(code: \"<your code>\")\n```\n\nThis compiles the code on go.dev/play, runs it, and returns:\n- The program output (to verify correctness)\n- A shareable URL like `https://go.dev/play/p/XXXXXXX`\n\nIf the output doesn't match expectations, fix the code and re-run until it produces the correct result.\n\n#### Step 4: Add the URL to Source Code\n\nAdd a `// Play:` comment as the **last line** of the function's doc comment block:\n\n```go\n// Map manipulates a slice and transforms it to a slice of another type.\n// Play: https://go.dev/play/p/refNB9ZTIGo\nfunc Map[T any, R any](collection []T, iteratee func(item T, index int) R) []R {\n```\n\n#### Step 5: Add the URL to Documentation\n\nSet the `playUrl` field in the corresponding `docs/data/*.md` file:\n\n```yaml\n---\nname: Map\nslug: map\nplayUrl: https://go.dev/play/p/refNB9ZTIGo\n...\n---\n```\n\n### Troubleshooting\n\n**First-run timeouts**: The Go Playground may timeout on the first execution if `github.com/samber/lo` hasn't been cached yet. Simply retry — subsequent runs succeed because the module is cached.\n\n**New helpers not yet released**: If documentation is created at the same time as the helper source code, the Go Playground cannot compile it because the module version hasn't been published yet. In that case, skip the playground example and leave `playUrl` empty. Create the example after the next release.\n\n**SIMD helpers**: Helpers in `exp/simd/` require `go1.26+goexperiment.simd+amd64` build tags, which the Go Playground does not support. These helpers cannot have playground examples.\n\n### Bulk Verification\n\nTo verify all playground URLs compile, you can use `mcp__go-playground__execute_go_playground_url` to re-run an existing URL and check the output. To read the source code of an existing playground, use `mcp__go-playground__read_go_playground_url`.\n\n## Example: Complete File\n\n```yaml\n---\nname: Map\nslug: map\nsourceRef: map.go#L123\ncategory: core\nsubCategory: map\nsignatures:\n  - \"func Map[T any, R any](collection []T, transform func(item T, index int) R) []R\"\nplayUrl: https://go.dev/play/p/EXAMPLE\nsimilarHelpers: []\nposition: 0\n---\n\nApplies a function to each element of a collection and returns a new collection with the results.\n\n```go\nresult := lo.Map([]int{1, 2, 3}, func(item int, index int) string {\n    return fmt.Sprintf(\"%d\", item)\n})\n// []string{\"1\", \"2\", \"3\"}\n```\n```\n\n## Checklist\n\nBefore submitting:\n\n- [ ] Frontmatter is complete and correctly formatted\n- [ ] Filename matches slug (with `core-` or `mutable-` or `parallel-` or `it-` prefix)\n- [ ] Source reference points to correct line number\n- [ ] Category and subCategory are appropriate\n- [ ] All signatures are included and properly formatted\n- [ ] Go Playground example works and demonstrates usage\n- [ ] Expected output is shown as a comment\n- [ ] Similar helpers are listed if applicable\n- [ ] Related helpers are consolidated into single file when appropriate\n- [ ] All validation scripts pass without errors\n- [ ] Helper is added to llms.txt\n"
  },
  {
    "path": "docs/README.md",
    "content": "# Website\n\nThis website is built using [Docusaurus](https://docusaurus.io/), a modern static website generator.\n\n## Installation\n\n```bash\nyarn\n```\n\n## Local Development\n\n```bash\nyarn start\n```\n\nThis command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server.\n\n## Build\n\n```bash\nyarn build\n```\n\nThis command generates static content into the `build` directory and can be served using any static contents hosting service.\n\n## Deployment\n\nUsing SSH:\n\n```bash\nUSE_SSH=true yarn deploy\n```\n\nNot using SSH:\n\n```bash\nGIT_USER=<Your GitHub username> yarn deploy\n```\n\nIf you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch.\n"
  },
  {
    "path": "docs/data/core-assert.md",
    "content": "---\nname: Assert\nslug: assert\nsourceRef: errors.go#L359\ncategory: core\nsubCategory: error-handling\nplayUrl: https://go.dev/play/p/Xv8LLKBMNwI\nvariantHelpers:\n  - core#error-handling#assert\n  - core#error-handling#assertf\nsimilarHelpers:\n  - core#error-handling#validate\n  - core#error-handling#mustx\n  - core#error-handling#tryx\n  - core#error-handling#tryorx\n  - core#error-handling#trycatch\n  - core#error-handling#trywitherrorvalue\n  - core#error-handling#errorsas\nposition: 80\nsignatures:\n  - \"func Assert(condition bool, message ...string)\"\n  - \"func Assertf(condition bool, format string, args ...any)\"\n---\n\nDoes nothing when condition is true; otherwise panics.\n```go\n// Base variant with optional message\nage := 12\nlo.Assert(age >= 15, \"user age must be >= 15\")\n// panics: \"user age must be >= 15\"\n\n// Without message - panics with default message\nx := -1\nlo.Assert(x > 0)\n// panics: \"assertion failed: condition is not true\"\n\n// Formatted variant with custom message\nage = 12\nlo.Assertf(age >= 15, \"user age must be >= 15, got %d\", age)\n// panics: \"user age must be >= 15, got 12\"\n\n// When condition is true - no panic\nage = 20\nlo.Assert(age >= 15, \"user age must be >= 15\")\n// continues normally\n```\n\n## Custom handler\n\nReplace `lo.Assert` and `lo.Assertf` with your own statement:\n\n```go\nlo.Assertf = func(condition bool, format string, args ...any) {\n\t\tif !condition {\n\t\t\t  panic(fmt.Errorf(\"%s: %s\", \"customErr\", fmt.Sprintf(format, args...)))\n\t\t}\n}\n```\n"
  },
  {
    "path": "docs/data/core-assign.md",
    "content": "---\nname: Assign\nslug: assign\nsourceRef: map.go#L234\ncategory: core\nsubCategory: map\nplayUrl: https://go.dev/play/p/VhwfJOyxf5o\nvariantHelpers:\n  - core#map#assign\nsimilarHelpers:\n  - core#map#entries\n  - core#map#keys\n  - core#map#values\nposition: 160\nsignatures:\n  - \"func Assign[K comparable, V any, Map ~map[K]V](maps ...Map) Map\"\n---\n\nMerges multiple maps from left to right. Later maps overwrite earlier keys.\n\n```go\nmerged := lo.Assign(\n    map[string]int{\"a\": 1, \"b\": 2},\n    map[string]int{\"b\": 3, \"c\": 4},\n)\n// map[string]int{\"a\": 1, \"b\": 3, \"c\": 4}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-associate.md",
    "content": "---\nname: Associate\nslug: associate\nsourceRef: slice.go#L389\ncategory: core\nsubCategory: slice\nplayUrl: https://go.dev/play/p/WHa2CfMO3Lr\nvariantHelpers:\n  - core#slice#associate\n  - core#slice#associatei\n  - core#slice#slicetomap\nsimilarHelpers:\n  - core#slice#keyby\n  - core#slice#groupby\n  - core#slice#filterslicetomap\n  - core#slice#slicetomap\nposition: 240\nsignatures:\n  - \"func Associate[T any, K comparable, V any](collection []T, transform func(item T) (K, V)) map[K]V\"\n  - \"func AssociateI[T any, K comparable, V any](collection []T, transform func(item T, index int) (K, V)) map[K]V\"\n  - \"func SliceToMap[T any, K comparable, V any](collection []T, transform func(item T) (K, V)) map[K]V\"\n---\n\nBuilds a map from a slice using a transform function that yields key/value pairs for each item. Perfect for converting collections to lookup maps.\n\n### Associate\n\nTransforms each element into a key-value pair. Later items with the same key will overwrite earlier ones.\n\n```go\ntype foo struct {\n    baz string\n    bar int\n}\n\nin := []*foo{{baz: \"apple\", bar: 1}, {baz: \"banana\", bar: 2}}\n\nm := lo.Associate(in, func(f *foo) (string, int) {\n    return f.baz, f.bar\n})\n// m: map[string]int{\"apple\": 1, \"banana\": 2}\n```\n\n### AssociateI\n\nVariant that includes the element index in the transform function, useful when you need the position in the original slice.\n\n```go\ntype User struct {\n    Name string\n    Age  int\n}\n\nusers := []User{\n    {Name: \"Alice\", Age: 25},\n    {Name: \"Bob\", Age: 30},\n}\n\nresult := lo.AssociateI(users, func(user User, index int) (string, int) {\n    return fmt.Sprintf(\"%s-%d\", user.Name, index), user.Age\n})\n// result: map[string]int{\"Alice-0\": 25, \"Bob-1\": 30}\n```\n\n### SliceToMap\n\nAlias for Associate - provides the same functionality with a more explicit name.\n\n```go\nproducts := []string{\"apple\", \"banana\", \"cherry\"}\n\nresult := lo.SliceToMap(products, func(product string) (string, int) {\n    return product, len(product)\n})\n// result: map[string]int{\"apple\": 5, \"banana\": 6, \"cherry\": 6}\n```\n"
  },
  {
    "path": "docs/data/core-asyncx.md",
    "content": "---\nname: AsyncX\nslug: asyncx\nsourceRef: concurrency.go#L35\ncategory: core\nsubCategory: concurrency\nsignatures:\n  - \"func Async[A any](f func() A) <-chan A\"\n  - \"func Async0(f func()) <-chan struct{}\"\n  - \"func Async1[A any](f func() A) <-chan A\"\n  - \"func Async2[A, B any](f func() (A, B)) <-chan Tuple2[A, B]\"\n  - \"func Async3[A, B, C any](f func() (A, B, C)) <-chan Tuple3[A, B, C]\"\n  - \"func Async4[A, B, C, D any](f func() (A, B, C, D)) <-chan Tuple4[A, B, C, D]\"\n  - \"func Async5[A, B, C, D, E any](f func() (A, B, C, D, E)) <-chan Tuple5[A, B, C, D, E]\"\n  - \"func Async6[A, B, C, D, E, F any](f func() (A, B, C, D, E, F)) <-chan Tuple6[A, B, C, D, E, F]\"\nplayUrl: https://go.dev/play/p/uo35gosuTLw\nvariantHelpers:\n  - core#concurrency#async\n  - core#concurrency#asyncx\nsimilarHelpers:\n  - core#concurrency#synchronize\n  - core#concurrency#waitfor\n  - core#retry#newtransaction\n  - core#channel#channelseq\nposition: 10\n---\n\nRuns a function asynchronously and returns results via channels. Variants support 0 to 6 return values, using tuple types for multi-value results.\n\nVariants: `Async`, `Async0..Async6`\n\n```go\nch := lo.Async(func() int {\n    time.Sleep(10 * time.Millisecond)\n    return 42\n})\nv := <-ch\n\ndone := lo.Async0(func() {\n    time.Sleep(5 * time.Millisecond)\n})\n<-done\n```\n\n\n"
  },
  {
    "path": "docs/data/core-attempt.md",
    "content": "---\nname: Attempt\nslug: attempt\nsourceRef: retry.go#L153\ncategory: core\nsubCategory: retry\nplayUrl: https://go.dev/play/p/3ggJZ2ZKcMj\nvariantHelpers:\n  - core#retry#attempt\nsimilarHelpers:\n  - core#retry#attemptwithdelay\n  - core#retry#attemptwhile\n  - core#retry#attemptwhilewithdelay\nposition: 0\nsignatures:\n  - \"func Attempt(maxIteration int, f func(index int) error) (int, error)\"\n---\n\nInvokes a function up to N times until it returns nil. Returns the number of iterations attempted (1-based) and the last error. Useful for retrying operations that might fail temporarily.\n\n```go\n// Success after 3 attempts\niter, err := lo.Attempt(5, func(i int) error {\n    if i == 2 {\n        return nil // succeeds on 3rd attempt (index 2)\n    }\n    return errors.New(\"failed\")\n})\n// iter: 3, err: nil\n```\n\n```go\n// All attempts fail - returns last error\niter, err = lo.Attempt(3, func(i int) error {\n    return fmt.Errorf(\"attempt %d failed\", i)\n})\n// iter: 3, err: \"attempt 2 failed\" (last error from index 2)\n```\n\n```go\n// Immediate success on first attempt\niter, err = lo.Attempt(5, func(i int) error {\n    return nil // succeeds immediately\n})\n// iter: 1, err: nil\n```\n\n```go\n// Zero attempts - returns error without calling function\niter, err = lo.Attempt(0, func(i int) error {\n    return errors.New(\"should not be called\")\n})\n// iter: 0, err: \"maxIteration must be greater than 0\"\n```\n\n\n"
  },
  {
    "path": "docs/data/core-attemptwhile.md",
    "content": "---\nname: AttemptWhile\nslug: attemptwhile\nsourceRef: retry.go#L198\ncategory: core\nsubCategory: retry\nplayUrl: https://go.dev/play/p/1VS7HxlYMOG\nvariantHelpers:\n  - core#retry#attemptwhile\nsimilarHelpers:\n  - core#retry#attempt\n  - core#retry#attemptwithdelay\n  - core#retry#attemptwhilewithdelay\nposition: 20\nsignatures:\n  - \"func AttemptWhile(maxIteration int, f func(int) (error, bool)) (int, error)\"\n---\n\nInvokes a function up to N times until it returns nil. The second return value controls whether to continue attempting.\n\n```go\ncount, err := lo.AttemptWhile(5, func(i int) (error, bool) {\n    if i == 2 {\n        return nil, false\n    }\n    return errors.New(\"fail\"), true\n})\n// count == 3, err == nil\n```\n\n\n"
  },
  {
    "path": "docs/data/core-attemptwhilewithdelay.md",
    "content": "---\nname: AttemptWhileWithDelay\nslug: attemptwhilewithdelay\nsourceRef: retry.go#L223\ncategory: core\nsubCategory: retry\nplayUrl: https://go.dev/play/p/mhufUjJfLEF\nvariantHelpers:\n  - core#retry#attemptwhilewithdelay\nsimilarHelpers:\n  - core#retry#attempt\n  - core#retry#attemptwithdelay\n  - core#retry#attemptwhile\nposition: 30\nsignatures:\n  - \"func AttemptWhileWithDelay(maxIteration int, delay time.Duration, f func(int, time.Duration) (error, bool)) (int, time.Duration, error)\"\n---\n\nLike AttemptWhile, but pauses between attempts and returns elapsed time.\n\n```go\ncount, dur, err := lo.AttemptWhileWithDelay(\n    5,\n    time.Millisecond,\n    func(i int, d time.Duration) (error, bool) {\n        return errors.New(\"x\"), i < 1\n    },\n)\n```\n\n\n"
  },
  {
    "path": "docs/data/core-attemptwithdelay.md",
    "content": "---\nname: AttemptWithDelay\nslug: attemptwithdelay\nsourceRef: retry.go#L172\ncategory: core\nsubCategory: retry\nplayUrl: https://go.dev/play/p/tVs6CygC7m1\nvariantHelpers:\n  - core#retry#attemptwithdelay\nsimilarHelpers:\n  - core#retry#attempt\n  - core#retry#attemptwhile\n  - core#retry#attemptwhilewithdelay\nposition: 10\nsignatures:\n  - \"func AttemptWithDelay(maxIteration int, delay time.Duration, f func(index int, duration time.Duration) error) (int, time.Duration, error)\"\n---\n\nInvokes a function up to N times with a pause between calls until it returns nil. Returns iterations, elapsed, and error.\n\n```go\niter, dur, err := lo.AttemptWithDelay(\n    3,\n    100*time.Millisecond,\n    func(i int, d time.Duration) error {\n        if i == 1 {\n            return nil\n        }\n        return errors.New(\"x\")\n    },\n)\n```\n\n\n"
  },
  {
    "path": "docs/data/core-buffer.md",
    "content": "---\nname: Buffer\nslug: buffer\nsourceRef: channel.go#L214\ncategory: core\nsubCategory: channel\nsignatures:\n  - \"func Buffer[T any](ch <-chan T, size int) (collection []T, length int, readTime time.Duration, ok bool)\"\n  - \"func BufferWithContext[T any](ctx context.Context, ch <-chan T, size int) (collection []T, length int, readTime time.Duration, ok bool)\"\nvariantHelpers:\n  - core#channel#buffer\n  - core#channel#bufferwithcontext\nsimilarHelpers:\n  - core#channel#slicetochannel\n  - core#channel#channeltoslice\nposition: 260\n---\n\nBuffer reads up to size items from a channel and returns them as a slice.\n\n```go\nch := make(chan int, 10)\nfor i := 1; i <= 5; i++ {\n    ch <- i\n}\nclose(ch)\n\nitems, length, readTime, ok := lo.Buffer(ch, 3)\n// items: []int{1, 2, 3}\n// length: 3\n// readTime: ~0s (immediate read from buffered channel)\n// ok: true (channel was closed)\n```\n\n### BufferWithContext\n\nBufferWithContext reads up to size items from a channel with context cancellation.\n\n```go\nctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond)\ndefer cancel()\n\nch := make(chan int)\ngo func() {\n    time.Sleep(50 * time.Millisecond)\n    ch <- 1\n    time.Sleep(100 * time.Millisecond)\n    ch <- 2\n}()\n\nitems, length, readTime, ok := lo.BufferWithContext(ctx, ch, 5)\n// items: []int{1} (only first item received before timeout)\n// length: 1\n// readTime: ~100ms (context timeout)\n// ok: false (context cancelled)\n```"
  },
  {
    "path": "docs/data/core-bufferwithtimeout.md",
    "content": "---\nname: BufferWithTimeout\nslug: bufferwithtimeout\nsourceRef: channel.go#L214\ncategory: core\nsubCategory: channel\nsignatures:\n  - \"func BufferWithTimeout[T any](ch <-chan T, size int, timeout time.Duration) (collection []T, length int, readTime time.Duration, ok bool)\"\nvariantHelpers:\n  - core#channel#bufferwithtimeout\nsimilarHelpers:\n  - core#channel#buffer\n  - core#channel#bufferwithcontext\n  - core#channel#slicetochannel\n  - core#channel#channeltoslice\nposition: 263\n---\n\nBufferWithTimeout reads up to size items from a channel with timeout.\n\n```go\nch := make(chan int)\ngo func() {\n    time.Sleep(200 * time.Millisecond)\n    ch <- 1\n}()\n\nitems, length, readTime, ok := lo.BufferWithTimeout(ch, 5, 100*time.Millisecond)\n// Returns empty slice due to timeout\n```\n"
  },
  {
    "path": "docs/data/core-camelcase.md",
    "content": "---\nname: CamelCase\nslug: camelcase\nsourceRef: string.go#L176\ncategory: core\nsubCategory: string\nplayUrl: https://go.dev/play/p/4JNDzaMwXkm\nvariantHelpers:\n  - core#string#camelcase\nsimilarHelpers:\n  - core#string#pascalcase\n  - core#string#snakecase\n  - core#string#kebabcase\n  - core#string#capitalize\n  - core#string#words\nposition: 50\nsignatures:\n  - \"func CamelCase(str string) string\"\n---\n\nConverts a string to camelCase.\n\n```go\nlo.CamelCase(\"hello_world\")\n// \"helloWorld\"\n```\n\n\n"
  },
  {
    "path": "docs/data/core-capitalize.md",
    "content": "---\nname: Capitalize\nslug: capitalize\nsourceRef: string.go#L227\ncategory: core\nsubCategory: string\nplayUrl: https://go.dev/play/p/uLTZZQXqnsa\nvariantHelpers:\n  - core#string#capitalize\nsimilarHelpers:\n  - core#string#pascalcase\n  - core#string#camelcase\n  - core#string#snakecase\n  - core#string#kebabcase\n  - core#string#words\n  - core#string#runelength\nposition: 90\nsignatures:\n  - \"func Capitalize(str string) string\"\n---\n\nConverts the first character to uppercase and the remaining to lowercase.\n\n```go\nlo.Capitalize(\"heLLO\")\n// \"Hello\"\n```\n\n\n"
  },
  {
    "path": "docs/data/core-channeldispatcher.md",
    "content": "---\nname: ChannelDispatcher\nslug: channeldispatcher\nsourceRef: channel.go#L18\ncategory: core\nsubCategory: channel\nsignatures:\n  - \"func ChannelDispatcher[T any](stream <-chan T, count, channelBufferCap int, strategy DispatchingStrategy[T]) []<-chan T\"\nsimilarHelpers:\n  - core#channel#fanin\n  - core#channel#fanout\n  - it#channel#seqtochannel\n  - it#channel#channeltoseq\nposition: 250\n---\n\nChannelDispatcher distributes messages from a stream to multiple channels based on a strategy.\n\n```go\nstream := make(chan int, 100)\nfor i := 0; i < 100; i++ {\n    stream <- i\n}\nclose(stream)\n\nchannels := lo.ChannelDispatcher(stream, 3, 10, lo.DispatchingStrategyRoundRobin[int])\n// Returns 3 channels with round-robin distribution\n```"
  },
  {
    "path": "docs/data/core-channeltoslice.md",
    "content": "---\nname: ChannelToSlice\nslug: channeltoslice\nsourceRef: channel.go#L18\ncategory: core\nsubCategory: channel\nsignatures:\n  - \"func ChannelToSlice[T any](ch <-chan T) []T\"\nsimilarHelpers:\n  - core#channel#slicetochannel\n  - core#channel#buffer\n  - it#channel#seqtochannel\n  - it#channel#channeltoseq\nposition: 252\n---\n\nChannelToSlice converts a channel to a slice.\n\n```go\nch := make(chan int, 3)\nch <- 1\nch <- 2\nch <- 3\nclose(ch)\n\nslice := lo.ChannelToSlice(ch)\n// slice contains [1, 2, 3]\n```"
  },
  {
    "path": "docs/data/core-chunk.md",
    "content": "---\nname: Chunk\nslug: chunk\nsourceRef: slice.go#L209\ncategory: core\nsubCategory: slice\nplayUrl: https://go.dev/play/p/kEMkFbdu85g\nvariantHelpers:\n  - core#slice#chunk\nsimilarHelpers:\n  - core#slice#slice\n  - core#slice#partitionby\n  - core#slice#drop\n  - core#slice#flatten\n  - core#slice#window\n  - core#slice#sliding\n  - core#map#chunkentries\nposition: 140\nsignatures:\n  - \"func Chunk[T any, Slice ~[]T](collection Slice, size int) []Slice\"\n---\n\nSplits a slice into chunks of the given size. The final chunk may be smaller.\n\n```go\nlo.Chunk([]int{0, 1, 2, 3, 4, 5}, 2)\n// [][]int{{0, 1}, {2, 3}, {4, 5}}\n\nlo.Chunk([]int{0, 1, 2, 3, 4, 5, 6}, 2)\n// [][]int{{0, 1}, {2, 3}, {4, 5}, {6}}\n```\n\n## Note\n\n`lo.ChunkString` and `lo.Chunk` functions behave inconsistently for empty input: `lo.ChunkString(\"\", n)` returns `[\"\"]` instead of `[]`.\n\nSee https://github.com/samber/lo/issues/788\n"
  },
  {
    "path": "docs/data/core-chunkentries.md",
    "content": "---\nname: ChunkEntries\nslug: chunkentries\nsourceRef: map.go#L253\ncategory: core\nsubCategory: map\nplayUrl: https://go.dev/play/p/X_YQL6mmoD-\nvariantHelpers:\n  - core#map#chunkentries\nsimilarHelpers:\n  - core#slice#chunk\n  - core#map#mapentries\n  - core#map#keyby\n  - core#map#groupby\n  - core#map#values\nposition: 170\nsignatures:\n  - \"func ChunkEntries[K comparable, V any](m map[K]V, size int) []map[K]V\"\n---\n\nSplits a map into maps of at most the given size. The last chunk may be smaller.\n\n```go\nchunks := lo.ChunkEntries(map[string]int{\"a\":1, \"b\":2, \"c\":3, \"d\":4, \"e\":5}, 3)\n// []map[string]int{ {\"a\":1, \"b\":2, \"c\":3}, {\"d\":4, \"e\":5} }\n```\n\n\n"
  },
  {
    "path": "docs/data/core-chunkstring.md",
    "content": "---\nname: ChunkString\nslug: chunkstring\nsourceRef: string.go#L130\ncategory: core\nsubCategory: string\nplayUrl: https://go.dev/play/p/__FLTuJVz54\nvariantHelpers:\n  - core#string#chunkstring\nsimilarHelpers:\n  - core#slice#chunk\n  - core#string#substring\n  - core#string#words\n  - core#string#runelength\n  - core#string#split\nposition: 20\nsignatures:\n  - \"func ChunkString[T ~string](str T, size int) []T\"\n---\n\nSplits a string into chunks of the given size. The last chunk may be shorter. Returns [\"\"] for empty input.\n\n```go\nlo.ChunkString(\"1234567\", 2)\n// []string{\"12\", \"34\", \"56\", \"7\"}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-clamp.md",
    "content": "---\nname: Clamp\nslug: clamp\nsourceRef: math.go#L59\ncategory: core\nsubCategory: math\nplayUrl: https://go.dev/play/p/RU4lJNC2hlI\nvariantHelpers:\n  - core#math#clamp\nsimilarHelpers:\n  - core#find#min\n  - core#find#max\n  - core#find#minby\n  - core#find#maxby\n  - core#math#mean\n  - core#math#sum\n  - core#math#product\nposition: 30\nsignatures:\n  - \"func Clamp[T constraints.Ordered](value T, mIn T, mAx T) T\"\n---\n\nClamps a number within inclusive lower and upper bounds.\n\n```go\nlo.Clamp(42, -10, 10)\n// 10\n```\n\n\n"
  },
  {
    "path": "docs/data/core-clone.md",
    "content": "---\nname: Clone\nslug: clone\nsourceRef: slice.go#L741\ncategory: core\nsubCategory: slice\nplayUrl: https://go.dev/play/p/66LJ2wAF0rN\nvariantHelpers:\n  - core#slice#clone\nsimilarHelpers:\n  - core#slice#repeat\n  - core#slice#fill\nposition: 160\nsignatures:\n  - \"func Clone[T any, Slice ~[]T](collection Slice) Slice\"\n---\n\nReturns a shallow copy of the collection.\n\n```go\nin := []int{1, 2, 3, 4, 5}\ncloned := lo.Clone(in)\n// Verify it's a different slice by checking that modifying one doesn't affect the other\nin[0] = 99\n// cloned is []int{1, 2, 3, 4, 5}\n```\n"
  },
  {
    "path": "docs/data/core-coalesce.md",
    "content": "---\nname: Coalesce\nslug: coalesce\nsourceRef: type_manipulation.go#L153\ncategory: core\nsubCategory: type\nsignatures:\n  - \"func Coalesce[T comparable](values ...T) (T, bool)\"\nplayUrl: https://go.dev/play/p/Gyo9otyvFHH\nvariantHelpers:\n  - core#type#coalesce\nsimilarHelpers:\n  - core#type#coalesceorempty\n  - core#type#coalesceslice\n  - core#type#coalescesliceorempty\n  - core#type#coalescemap\n  - core#type#coalescemaporempty\n  - core#type#valueor\n  - core#type#empty\n  - core#type#fromptror\nposition: 130\n---\n\nReturns the first non-zero value from the provided comparable arguments, with a boolean indicating if a non-zero value was found.\n\n```go\n// With strings - returns first non-empty string\nresult, ok := lo.Coalesce(\"\", \"foo\", \"bar\")\n// result: \"foo\", ok: true\n\n// All zero values - returns zero value with false\nresult, ok = lo.Coalesce(\"\", \"\")\n// result: \"\", ok: false\n\n// With integers - zero is considered zero value\nresult, ok = lo.Coalesce(0, 42, 100)\n// result: 42, ok: true\n\n// With floats - zero is considered zero value\nresult, ok = lo.Coalesce(0.0, 3.14, 2.71)\n// result: 3.14, ok: true\n\n// With pointers - nil is zero value for pointer types\nvar s *string\nstr := \"hello\"\nresult, ok = lo.Coalesce(nil, &str)\n// result: &str, ok: true\n\n// All nil pointers\nresult, ok = lo.Coalesce[*string](nil, nil, nil)\n// result: nil, ok: false\n```"
  },
  {
    "path": "docs/data/core-coalescemap.md",
    "content": "---\nname: CoalesceMap\nslug: coalescemap\nsourceRef: type_manipulation.go#L196\ncategory: core\nsubCategory: type\nsignatures:\n  - \"func CoalesceMap[K comparable, V any](v ...map[K]V) (map[K]V, bool)\"\nplayUrl: https://go.dev/play/p/Gyo9otyvFHH\nvariantHelpers:\n  - core#type#coalescemap\nsimilarHelpers:\n  - core#type#coalesce\n  - core#type#coalesceorempty\n  - core#type#coalesceslice\n  - core#type#coalescesliceorempty\n  - core#type#coalescemaporempty\n  - core#type#empty\nposition: 150\n---\n\nReturns the first non-empty map from the provided arguments, with a boolean indicating if a non-empty map was found.\n\n```go\nresult, ok := lo.CoalesceMap(map[string]int{}, map[string]int{\"a\": 1}, map[string]int{\"b\": 2})\n// map[string]int{\"a\": 1}, true\n\nresult, ok = lo.CoalesceMap(map[string]int{}, map[string]int{})\n// map[string]int{}, false\n\nresult, ok = lo.CoalesceMap(map[int]string{}, map[int]string{1: \"one\"}, map[int]string{2: \"two\"})\n// map[int]string{1: \"one\"}, true\n```"
  },
  {
    "path": "docs/data/core-coalescemaporempty.md",
    "content": "---\nname: CoalesceMapOrEmpty\nslug: coalescemaporempty\nsourceRef: type_manipulation.go#L207\ncategory: core\nsubCategory: type\nsignatures:\n  - \"func CoalesceMapOrEmpty[K comparable, V any](v ...map[K]V) map[K]V\"\nplayUrl: https://go.dev/play/p/Gyo9otyvFHH\nvariantHelpers:\n  - core#type#coalescemaporempty\nsimilarHelpers:\n  - core#type#coalesce\n  - core#type#coalesceorempty\n  - core#type#coalesceslice\n  - core#type#coalescesliceorempty\n  - core#type#coalescemap\n  - core#type#empty\nposition: 155\n---\n\nReturns the first non-empty map from the provided arguments, or an empty map if all arguments are empty.\n\n```go\nresult := lo.CoalesceMapOrEmpty(map[string]int{}, map[string]int{\"a\": 1}, map[string]int{\"b\": 2})\n// map[string]int{\"a\": 1}\n\nresult = lo.CoalesceMapOrEmpty(map[string]int{}, map[string]int{})\n// map[string]int{}\n\nresult = lo.CoalesceMapOrEmpty(map[int]string{}, map[int]string{1: \"one\"}, map[int]string{2: \"two\"})\n// map[int]string{1: \"one\"}\n```"
  },
  {
    "path": "docs/data/core-coalesceorempty.md",
    "content": "---\nname: CoalesceOrEmpty\nslug: coalesceorempty\nsourceRef: type_manipulation.go#L167\ncategory: core\nsubCategory: type\nsignatures:\n  - \"func CoalesceOrEmpty[T comparable](v ...T) T\"\nplayUrl: https://go.dev/play/p/Gyo9otyvFHH\nvariantHelpers:\n  - core#type#coalesceorempty\nsimilarHelpers:\n  - core#type#coalesce\n  - core#type#coalesceslice\n  - core#type#coalescesliceorempty\n  - core#type#coalescemap\n  - core#type#coalescemaporempty\n  - core#type#valueor\n  - core#type#empty\nposition: 135\n---\n\nReturns the first non-zero value from the provided comparable arguments, or the zero value if all arguments are zero.\n\n```go\nresult := lo.CoalesceOrEmpty(\"\", \"foo\", \"bar\")\n// \"foo\"\n\nresult = lo.CoalesceOrEmpty(\"\", \"\")\n// \"\"\n\nresult = lo.CoalesceOrEmpty(0, 42, 100)\n// 42\n\nresult = lo.CoalesceOrEmpty(0.0, 0.0, 0.0)\n// 0.0\n```"
  },
  {
    "path": "docs/data/core-coalesceslice.md",
    "content": "---\nname: CoalesceSlice\nslug: coalesceslice\nsourceRef: type_manipulation.go#L174\ncategory: core\nsubCategory: type\nsignatures:\n  - \"func CoalesceSlice[T any](v ...[]T) ([]T, bool)\"\nplayUrl: https://go.dev/play/p/Gyo9otyvFHH\nvariantHelpers:\n  - core#type#coalesceslice\nsimilarHelpers:\n  - core#type#coalesce\n  - core#type#coalesceorempty\n  - core#type#coalescesliceorempty\n  - core#type#coalescemap\n  - core#type#coalescemaporempty\n  - core#type#empty\nposition: 140\n---\n\nReturns the first non-empty slice from the provided arguments, with a boolean indicating if a non-empty slice was found.\n\n```go\nresult, ok := lo.CoalesceSlice([]int{}, []int{1, 2, 3}, []int{4, 5})\n// []int{1, 2, 3}, true\n\nresult, ok = lo.CoalesceSlice([]int{}, []int{})\n// []int{}, false\n\nresult, ok = lo.CoalesceSlice([]string{}, []string{\"a\", \"b\"}, []string{\"c\"})\n// []string{\"a\", \"b\"}, true\n```"
  },
  {
    "path": "docs/data/core-coalescesliceorempty.md",
    "content": "---\nname: CoalesceSliceOrEmpty\nslug: coalescesliceorempty\nsourceRef: type_manipulation.go#L185\ncategory: core\nsubCategory: type\nsignatures:\n  - \"func CoalesceSliceOrEmpty[T any](v ...[]T) []T\"\nplayUrl: https://go.dev/play/p/Gyo9otyvFHH\nvariantHelpers:\n  - core#type#coalescesliceorempty\nsimilarHelpers:\n  - core#type#coalesce\n  - core#type#coalesceorempty\n  - core#type#coalesceslice\n  - core#type#coalescemap\n  - core#type#coalescemaporempty\n  - core#type#empty\nposition: 145\n---\n\nReturns the first non-empty slice from the provided arguments, or an empty slice if all arguments are empty.\n\n```go\nresult := lo.CoalesceSliceOrEmpty([]int{}, []int{1, 2, 3}, []int{4, 5})\n// []int{1, 2, 3}\n\nresult = lo.CoalesceSliceOrEmpty([]int{}, []int{})\n// []int{}\n\nresult = lo.CoalesceSliceOrEmpty([]string{}, []string{\"a\", \"b\"}, []string{\"c\"})\n// []string{\"a\", \"b\"}\n```"
  },
  {
    "path": "docs/data/core-compact.md",
    "content": "---\nname: Compact\nslug: compact\nsourceRef: slice.go#L706\ncategory: core\nsubCategory: slice\nplayUrl: https://go.dev/play/p/tXiy-iK6PAc\nvariantHelpers:\n  - core#slice#compact\nsimilarHelpers:\n  - core#slice#filter\n  - core#slice#reject\n  - core#slice#without\n  - core#slice#withoutempty\nposition: 270\nsignatures:\n  - \"func Compact[T comparable, Slice ~[]T](collection Slice) Slice\"\n---\n\nReturns a slice of all non-zero elements.\n\n```go\nlo.Compact([]string{\"\", \"foo\", \"\", \"bar\", \"\"})\n// []string{\"foo\", \"bar\"}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-concat.md",
    "content": "---\nname: Concat\nslug: concat\nsourceRef: slice.go#L282\ncategory: core\nsubCategory: slice\nplayUrl: https://go.dev/play/p/Ux2UuR2xpRK\nvariantHelpers:\n  - core#slice#concat\nsimilarHelpers:\n  - it#sequence#concat\n  - core#slice#flatten\n  - core#intersection#union\nposition: 160\nsignatures:\n  - \"func Concat[T any, Slice ~[]T](collections ...Slice) Slice\"\n---\n\nReturns a new slice containing all the elements in collections. Concat conserves the order of the elements.\n\n```go\nlist1 := []int{0, 1}\nlist2 := []int{2, 3, 4, 5}\nflat := lo.Flatten(list1, list2)\n// []int{0, 1, 2, 3, 4, 5}\n```\n"
  },
  {
    "path": "docs/data/core-contains.md",
    "content": "---\nname: Contains\nslug: contains\nsourceRef: intersect.go#L5\ncategory: core\nsubCategory: intersect\nplayUrl: https://go.dev/play/p/W1EvyqY6t9j\nvariantHelpers:\n  - core#intersect#contains\nsimilarHelpers:\n  - core#intersect#containsby\n  - core#intersect#every\n  - core#intersect#some\n  - core#intersect#none\n  - core#slice#find\nposition: 0\nsignatures:\n  - \"func Contains[T comparable](collection []T, element T) bool\"\n---\n\nReturns true if an element is present in a collection.\n\n```go\npresent := lo.Contains([]int{0, 1, 2, 3, 4, 5}, 5)\n// true\n```\n\n\n"
  },
  {
    "path": "docs/data/core-containsby.md",
    "content": "---\nname: ContainsBy\nslug: containsby\nsourceRef: intersect.go#L17\ncategory: core\nsubCategory: intersect\nplayUrl: https://go.dev/play/p/W1EvyqY6t9j\nvariantHelpers:\n  - core#intersect#containsby\nsimilarHelpers:\n  - core#intersect#contains\n  - core#intersect#some\n  - core#intersect#every\n  - core#intersect#none\n  - core#slice#some\n  - core#slice#every\n  - core#slice#findby\n  - core#slice#filter\nposition: 10\nsignatures:\n  - \"func ContainsBy[T any](collection []T, predicate func(item T) bool) bool\"\n---\n\nReturns true if the predicate returns true for any element in the collection.\n\n```go\nexists := lo.ContainsBy(\n    []int{0, 1, 2, 3},\n    func(x int) bool {\n        return x == 3\n    },\n)\n// true\n```\n\n\n"
  },
  {
    "path": "docs/data/core-count.md",
    "content": "---\nname: Count\nslug: count\nsourceRef: slice.go#L582\ncategory: core\nsubCategory: slice\nplayUrl: https://go.dev/play/p/Y3FlK54yveC\nvariantHelpers:\n  - core#slice#count\nsimilarHelpers:\n  - core#slice#countby\n  - core#slice#countvalues\n  - core#slice#every\n  - core#slice#some\nposition: 0\nsignatures:\n  - \"func Count[T comparable](collection []T, value T) int\"\n---\n\nCounts the number of elements in the collection that equal a given value.\n\n```go\nlo.Count([]int{1, 5, 1}, 1)\n// 2\n```\n\n\n"
  },
  {
    "path": "docs/data/core-countby.md",
    "content": "---\nname: CountBy\nslug: countby\nsourceRef: slice.go#L849\ncategory: core\nsubCategory: slice\nplayUrl: https://go.dev/play/p/5GMQP5vNT4q\nvariantHelpers:\n  - core#slice#countby\nsimilarHelpers:\n  - core#slice#count\n  - core#slice#every\n  - core#slice#some\n  - core#slice#filter\n  - core#slice#find\n  - core#slice#countbyerr\nposition: 0\nsignatures:\n  - \"func CountBy[T any](collection []T, predicate func(item T) bool) int\"\n---\n\nCounts the number of elements for which the predicate is true.\n\n```go\nlo.CountBy([]int{1, 5, 1}, func(i int) bool {\n    return i < 4\n})\n// 2\n```\n\n\n"
  },
  {
    "path": "docs/data/core-countbyerr.md",
    "content": "---\nname: CountByErr\nslug: countbyerr\nsourceRef: slice.go#L863\ncategory: core\nsubCategory: slice\nsignatures:\n  - \"func CountByErr[T any](collection []T, predicate func(item T) (bool, error)) (int, error)\"\nvariantHelpers:\n  - core#slice#countbyerr\nplayUrl: https://go.dev/play/p/7BnyPhpG6lW\nsimilarHelpers:\n  - core#slice#countby\n  - core#slice#count\n  - core#slice#everybyerr\n  - core#slice#somebyerr\nposition: 5\n---\n\nCounts the number of elements for which the predicate is true. Returns an error if the predicate function fails, stopping iteration immediately.\n\n```go\ncount, err := lo.CountByErr([]int{1, 5, 1}, func(i int) (bool, error) {\n    if i == 5 {\n        return false, fmt.Errorf(\"5 not allowed\")\n    }\n    return i < 4, nil\n})\n// 0, error(\"5 not allowed\")\n```\n\n```go\ncount, err := lo.CountByErr([]int{1, 5, 1}, func(i int) (bool, error) {\n    return i < 4, nil\n})\n// 2, nil\n```\n"
  },
  {
    "path": "docs/data/core-countvalues.md",
    "content": "---\nname: CountValues\nslug: countvalues\nsourceRef: slice.go#L610\ncategory: core\nsubCategory: slice\nplayUrl: https://go.dev/play/p/-p-PyLT4dfy\nvariantHelpers:\n  - core#slice#countvalues\nsimilarHelpers:\n  - core#slice#count\n  - core#slice#countby\n  - core#slice#countvaluesby\n  - core#slice#groupby\n  - core#slice#uniq\nposition: 0\nsignatures:\n  - \"func CountValues[T comparable](collection []T) map[T]int\"\n---\n\nCounts the number of occurrences of each element in the collection.\n\n```go\nlo.CountValues([]int{1, 2, 2})\n// map[int]int{1: 1, 2: 2}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-countvaluesby.md",
    "content": "---\nname: CountValuesBy\nslug: countvaluesby\nsourceRef: slice.go#L623\ncategory: core\nsubCategory: slice\nplayUrl: https://go.dev/play/p/2U0dG1SnOmS\nvariantHelpers:\n  - core#slice#countvaluesby\nsimilarHelpers:\n  - core#slice#countvalues\n  - core#slice#groupby\n  - core#slice#map\n  - core#slice#mapvalues\nposition: 0\nsignatures:\n  - \"func CountValuesBy[T any, U comparable](collection []T, transform func(item T) U) map[U]int\"\n---\n\nCounts the number of each transformed value (equivalent to Map followed by CountValues).\n\n```go\nisEven := func(v int) bool {\n    return v%2 == 0\n}\nlo.CountValuesBy([]int{1, 2, 2}, isEven)\n// map[bool]int{false: 1, true: 2}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-crossjoinbyerrx.md",
    "content": "---\nname: CrossJoinByErrX\nslug: crossjoinbyerrx\nsourceRef: tuples.go#L1320\ncategory: core\nsubCategory: tuple\nsignatures:\n  - \"func CrossJoinByErr2[A any, B any, Out any](listA []A, listB []B, transform func(a A, b B) (Out, error)) ([]Out, error)\"\n  - \"func CrossJoinByErr3[A any, B any, C any, Out any](listA []A, listB []B, listC []C, transform func(a A, b B, c C) (Out, error)) ([]Out, error)\"\n  - \"func CrossJoinByErr4[A any, B any, C any, D any, Out any](listA []A, listB []B, listC []C, listD []D, transform func(a A, b B, c C, d D) (Out, error)) ([]Out, error)\"\n  - \"func CrossJoinByErr5[A any, B any, C any, D any, E any, Out any](listA []A, listB []B, listC []C, listD []D, listE []E, transform func(a A, b B, c C, d D, e E) (Out, error)) ([]Out, error)\"\n  - \"func CrossJoinByErr6[A any, B any, C any, D any, E any, F any, Out any](listA []A, listB []B, listC []C, listD []D, listE []E, listF []F, transform func(a A, b B, c C, d D, e E, f F) (Out, error)) ([]Out, error)\"\n  - \"func CrossJoinByErr7[A any, B any, C any, D any, E any, F any, G any, Out any](listA []A, listB []B, listC []C, listD []D, listE []E, listF []F, listG []G, transform func(a A, b B, c C, d D, e E, f F, g G) (Out, error)) ([]Out, error)\"\n  - \"func CrossJoinByErr8[A any, B any, C any, D any, E any, F any, G any, H any, Out any](listA []A, listB []B, listC []C, listD []D, listE []E, listF []F, listG []G, listH []H, transform func(a A, b B, c C, d D, e E, f F, g G, h H) (Out, error)) ([]Out, error)\"\n  - \"func CrossJoinByErr9[A any, B any, C any, D any, E any, F any, G any, H any, I any, Out any](listA []A, listB []B, listC []C, listD []D, listE []E, listF []F, listG []G, listH []H, listI []I, transform func(a A, b B, c C, d D, e E, f F, g G, h H, i I) (Out, error)) ([]Out, error)\"\nvariantHelpers:\n  - core#tuple#crossjoinbyerrx\nsimilarHelpers:\n  - core#tuple#crossjoinbyx\nposition: 61\n---\n\nComputes a cartesian product and projects each combination through a function that can return an error. Stops iteration immediately when an error is encountered and returns the zero value (nil for slices).\n\nVariants: `CrossJoinByErr2..CrossJoinByErr9`\n\n```go\nresult, err := lo.CrossJoinByErr2([]string{\"a\", \"b\"}, []int{1, 2}, func(a string, b int) (string, error) {\n    if a == \"b\" {\n        return \"\", fmt.Errorf(\"b not allowed\")\n    }\n    return fmt.Sprintf(\"%s-%d\", a, b), nil\n})\n// []string(nil), error(\"b not allowed\")\n```\n\n```go\nresult, err := lo.CrossJoinByErr2([]string{\"a\", \"b\"}, []int{1, 2}, func(a string, b int) (string, error) {\n    return fmt.Sprintf(\"%s-%d\", a, b), nil\n})\n// []string{\"a-1\", \"a-2\", \"b-1\", \"b-2\"}, nil\n```\n\nReturns an empty list if any input list is empty.\n"
  },
  {
    "path": "docs/data/core-crossjoinbyx.md",
    "content": "---\nname: CrossJoinByX\nslug: crossjoinbyx\nsourceRef: tuples.go#L956\ncategory: core\nsubCategory: tuple\nsignatures:\n  - \"func CrossJoinBy2[A, B, Out any](listA []A, listB []B, transform func(a A, b B) Out) []Out\"\n  - \"func CrossJoinBy3[A, B, C, Out any](listA []A, listB []B, listC []C, transform func(a A, b B, c C) Out) []Out\"\n  - \"func CrossJoinBy4[A, B, C, D, Out any](listA []A, listB []B, listC []C, listD []D, transform func(a A, b B, c C, d D) Out) []Out\"\n  - \"func CrossJoinBy5[A, B, C, D, E, Out any](listA []A, listB []B, listC []C, listD []D, listE []E, transform func(a A, b B, c C, d D, e E) Out) []Out\"\n  - \"func CrossJoinBy6[A, B, C, D, E, F, Out any](listA []A, listB []B, listC []C, listD []D, listE []E, listF []F, transform func(a A, b B, c C, d D, e E, f F) Out) []Out\"\n  - \"func CrossJoinBy7[A, B, C, D, E, F, G, Out any](listA []A, listB []B, listC []C, listD []D, listE []E, listF []F, listG []G, transform func(a A, b B, c C, d D, e E, f F, g G) Out) []Out\"\n  - \"func CrossJoinBy8[A, B, C, D, E, F, G, H, Out any](listA []A, listB []B, listC []C, listD []D, listE []E, listF []F, listG []G, listH []H, transform func(a A, b B, c C, d D, e E, f F, g G, h H) Out) []Out\"\n  - \"func CrossJoinBy9[A, B, C, D, E, F, G, H, I, Out any](listA []A, listB []B, listC []C, listD []D, listE []E, listF []F, listG []G, listH []H, listI []I, transform func(a A, b B, c C, d D, e E, f F, g G, h H, i I) Out) []Out\"\nplayUrl: https://go.dev/play/p/8Y7btpvuA-C\nvariantHelpers:\n  - core#tuple#crossjoinbyx\n  - core#tuple#crossjoinbyerrx\nsimilarHelpers:\n  - core#tuple#zipx\n  - core#tuple#unzipx\n  - core#tuple#zipbyx\n  - core#tuple#unzipbyx\n  - core#slice#product\n  - core#slice#productby\nposition: 62\n---\n\nComputes a cartesian product and projects each combination through a function. Variants support 2 up to 9 input slices.\n\nVariants: `CrossJoinBy2..CrossJoinBy9`\n\n```go\na := []int{1,2}\nb := []string{\"x\",\"y\"}\nout := lo.CrossJoinBy2(a, b, func(x int, y string) string {\n    return fmt.Sprintf(\"%d-%s\", x, y)\n})\n```\n\n\n"
  },
  {
    "path": "docs/data/core-crossjoinx.md",
    "content": "---\nname: CrossJoinX\nslug: crossjoinx\nsourceRef: tuples.go#L891\ncategory: core\nsubCategory: tuple\nsignatures:\n  - \"func CrossJoin2[A, B any](listA []A, listB []B) []Tuple2[A, B]\"\n  - \"func CrossJoin3[A, B, C any](listA []A, listB []B, listC []C) []Tuple3[A, B, C]\"\n  - \"func CrossJoin4[A, B, C, D any](listA []A, listB []B, listC []C, listD []D) []Tuple4[A, B, C, D]\"\n  - \"func CrossJoin5[A, B, C, D, E any](listA []A, listB []B, listC []C, listD []D, listE []E) []Tuple5[A, B, C, D, E]\"\n  - \"func CrossJoin6[A, B, C, D, E, F any](listA []A, listB []B, listC []C, listD []D, listE []E, listF []F) []Tuple6[A, B, C, D, E, F]\"\n  - \"func CrossJoin7[A, B, C, D, E, F, G any](listA []A, listB []B, listC []C, listD []D, listE []E, listF []F, listG []G) []Tuple7[A, B, C, D, E, F, G]\"\n  - \"func CrossJoin8[A, B, C, D, E, F, G, H any](listA []A, listB []B, listC []C, listD []D, listE []E, listF []F, listG []G, listH []H) []Tuple8[A, B, C, D, E, F, G, H]\"\n  - \"func CrossJoin9[A, B, C, D, E, F, G, H, I any](listA []A, listB []B, listC []C, listD []D, listE []E, listF []F, listG []G, listH []H, listI []I) []Tuple9[A, B, C, D, E, F, G, H, I]\"\nplayUrl: https://go.dev/play/p/3VFppyL9FDU\nvariantHelpers:\n  - core#tuple#crossjoinx\nsimilarHelpers:\n  - core#tuple#tuplex\n  - core#intersect#product\n  - core#intersect#productby\n  - core#map#entries\nposition: 50\n---\n\nComputes the cartesian product of input slices, returning tuples of all combinations. Variants support 2 up to 9 input slices.\n\nVariants: `CrossJoin2..CrossJoin9`\n\n```go\na := []int{1,2}\nb := []string{\"x\",\"y\"}\npairs := lo.CrossJoin2(a, b)\n```\n\n\n"
  },
  {
    "path": "docs/data/core-cut.md",
    "content": "---\nname: Cut\nslug: cut\nsourceRef: slice.go#L774\ncategory: core\nsubCategory: slice\nplayUrl: https://go.dev/play/p/GiL3qhpIP3f\nvariantHelpers:\n  - core#slice#cut\nsimilarHelpers:\n  - core#slice#cutprefix\n  - core#slice#cutsuffix\n  - core#slice#slice\n  - core#slice#trim\n  - core#slice#trimprefix\n  - core#slice#trimsuffix\n  - core#slice#partitionby\nposition: 0\nsignatures:\n  - \"func Cut[T comparable, Slice ~[]T](collection Slice, separator Slice) (before Slice, after Slice, found bool)\"\n---\n\nSlices the collection around the first instance of the separator, returning before, after, and whether it was found.\n\n```go\nleft, right, found := lo.Cut([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, []string{\"b\", \"c\", \"d\"})\n// left: []string{\"a\"}\n// right: []string{\"e\", \"f\", \"g\"}\n// found: true\n\nleft, right, found = lo.Cut([]string{\"a\", \"b\", \"c\"}, []string{\"z\"})\n// left: []string{\"a\", \"b\", \"c\"}\n// right: []string{}\n// found: false\n```\n\n\n"
  },
  {
    "path": "docs/data/core-cutprefix.md",
    "content": "---\nname: CutPrefix\nslug: cutprefix\nsourceRef: slice.go#L800\ncategory: core\nsubCategory: slice\nplayUrl: https://go.dev/play/p/P1scQj53aFa\nvariantHelpers:\n  - core#slice#cutprefix\nsimilarHelpers:\n  - core#slice#cutsuffix\n  - core#slice#cut\n  - core#slice#trimprefix\n  - core#slice#trimleft\n  - core#slice#slice\n  - core#slice#drop\n  - core#slice#hasprefix\nposition: 0\nsignatures:\n  - \"func CutPrefix[T comparable, Slice ~[]T](collection Slice, separator Slice) (after Slice, found bool)\"\n---\n\nReturns the collection without the provided leading prefix and a boolean indicating whether it was present.\n\n```go\nright, found := lo.CutPrefix([]string{\"a\", \"b\", \"c\", \"d\"}, []string{\"a\", \"b\", \"c\"})\n// right: []string{\"d\"}\n// found: true\n\nright, found = lo.CutPrefix([]string{\"a\", \"b\", \"c\"}, []string{\"b\"})\n// right: []string{\"a\", \"b\", \"c\"}\n// found: false\n```\n\n\n"
  },
  {
    "path": "docs/data/core-cutsuffix.md",
    "content": "---\nname: CutSuffix\nslug: cutsuffix\nsourceRef: slice.go#L821\ncategory: core\nsubCategory: slice\nplayUrl: https://go.dev/play/p/7FKfBFvPTaT\nvariantHelpers:\n  - core#slice#cutsuffix\nsimilarHelpers:\n  - core#slice#cutprefix\n  - core#slice#cut\n  - core#slice#trimsuffix\n  - core#slice#trimright\n  - core#slice#slice\n  - core#slice#dropright\n  - core#slice#hassuffix\nposition: 0\nsignatures:\n  - \"func CutSuffix[T comparable, Slice ~[]T](collection Slice, separator Slice) (before Slice, found bool)\"\n---\n\nReturns the collection without the provided trailing suffix and a boolean indicating whether it was present.\n\n```go\nleft, found := lo.CutSuffix([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, []string{\"f\", \"g\"})\n// left: []string{\"a\", \"b\", \"c\", \"d\", \"e\"}\n// found: true\n\nleft, found = lo.CutSuffix([]string{\"a\", \"b\", \"c\"}, []string{\"b\"})\n// left: []string{\"a\", \"b\", \"c\"}\n// found: false\n```\n\n\n"
  },
  {
    "path": "docs/data/core-difference.md",
    "content": "---\nname: Difference\nslug: difference\nsourceRef: intersect.go#L124\ncategory: core\nsubCategory: intersect\nplayUrl: https://go.dev/play/p/pKE-JgzqRpz\nvariantHelpers:\n  - core#intersect#difference\nsimilarHelpers:\n  - core#intersect#intersect\n  - core#intersect#union\n  - core#intersect#without\n  - core#intersect#withoutby\n  - core#slice#uniq\n  - core#slice#uniqby\nposition: 90\nsignatures:\n  - \"func Difference[T comparable, Slice ~[]T](list1 Slice, list2 Slice) (Slice, Slice)\"\n---\n\nReturns the difference between two collections. The first slice contains elements absent from list2; the second contains elements absent from list1.\n\n```go\nleft, right := lo.Difference([]int{0, 1, 2, 3, 4, 5}, []int{0, 2, 6})\n// []int{1, 3, 4, 5}, []int{6}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-dispatchingstrategy.md",
    "content": "---\nname: DispatchingStrategy\nslug: dispatchingstrategy\nsourceRef: channel.go#L78\ncategory: core\nsubCategory: channel\nsignatures:\n  - \"func DispatchingStrategyRoundRobin[T any](msg T, index uint64, channels []<-chan T) int\"\n  - \"func DispatchingStrategyRandom[T any](msg T, index uint64, channels []<-chan T) int\"\n  - \"func DispatchingStrategyWeightedRandom[T any](weights []int) DispatchingStrategy[T]\"\n  - \"func DispatchingStrategyFirst[T any](msg T, index uint64, channels []<-chan T) int\"\n  - \"func DispatchingStrategyLeast[T any](msg T, index uint64, channels []<-chan T) int\"\n  - \"func DispatchingStrategyMost[T any](msg T, index uint64, channels []<-chan T) int\"\nvariantHelpers:\n  - core#channel#dispatchingstrategyroundrobin\n  - core#channel#dispatchingstrategyrandom\n  - core#channel#dispatchingstrategyweightedrandom\n  - core#channel#dispatchingstrategyfirst\n  - core#channel#dispatchingstrategyleast\n  - core#channel#dispatchingstrategymost\nsimilarHelpers:\n  - core#channel#channeldispatcher\nposition: 270\n---\n\nDispatchingStrategyRoundRobin distributes messages to channels in round-robin order.\n\n```go\nstrategy := lo.DispatchingStrategyRoundRobin[int]\nindex := strategy(42, 0, []chan int{ch1, ch2, ch3})\n// Returns 0, then 1, then 2, then 0, cycling through channels\n```\n\nDispatchingStrategyRandom distributes messages to a random channel.\n\n```go\nstrategy := lo.DispatchingStrategyRandom[int]\nindex := strategy(42, 0, []chan int{ch1, ch2, ch3})\n// Returns a random channel index 0, 1, or 2\n```\n\nDispatchingStrategyWeightedRandom distributes messages to channels based on weights.\n\n```go\nweights := []int{1, 3, 6} // Channel 0: 10%, Channel 1: 30%, Channel 2: 60%\nstrategy := lo.DispatchingStrategyWeightedRandom[int](weights)\nindex := strategy(42, 0, []chan int{ch1, ch2, ch3})\n// Returns 2 most often, 1 sometimes, 0 rarely\n```\n\nDispatchingStrategyFirst distributes messages to the first non-full channel.\n\n```go\nstrategy := lo.DispatchingStrategyFirst[int]\nindex := strategy(42, 0, []chan int{ch1, ch2, ch3})\n// Always returns 0 if ch1 is not full\n```\n\nDispatchingStrategyLeast distributes messages to the channel with the fewest items.\n\n```go\nstrategy := lo.DispatchingStrategyLeast[int]\nindex := strategy(42, 0, []chan int{ch1, ch2, ch3})\n// Returns the index of the channel with the smallest buffer size\n```\n\nDispatchingStrategyMost distributes messages to the channel with the most items.\n\n```go\nstrategy := lo.DispatchingStrategyMost[int]\nindex := strategy(42, 0, []chan int{ch1, ch2, ch3})\n// Returns the index of the channel with the largest buffer size\n```"
  },
  {
    "path": "docs/data/core-drop.md",
    "content": "---\nname: Drop\nslug: drop\nsourceRef: slice.go#L441\ncategory: core\nsubCategory: slice\nplayUrl: https://go.dev/play/p/JswS7vXRJP2\nvariantHelpers:\n  - core#slice#drop\nsimilarHelpers:\n  - core#slice#dropright\n  - core#slice#dropwhile\n  - core#slice#dropbyindex\n  - core#slice#slice\n  - core#slice#droprightwhile\n  - core#slice#cutprefix\n  - core#slice#take\n  - core#slice#takewhile\nposition: 170\nsignatures:\n  - \"func Drop[T any, Slice ~[]T](collection Slice, n int) Slice\"\n---\n\nDrops n elements from the beginning of a slice.\n\n```go\nlo.Drop([]int{0, 1, 2, 3, 4, 5}, 2)\n// []int{2, 3, 4, 5}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-dropbyindex.md",
    "content": "---\nname: DropByIndex\nslug: dropbyindex\nsourceRef: slice.go#L501\ncategory: core\nsubCategory: slice\nplayUrl: https://go.dev/play/p/bPIH4npZRxS\nvariantHelpers:\n  - core#slice#dropbyindex\nsimilarHelpers:\n  - core#slice#drop\n  - core#slice#dropright\n  - core#slice#dropwhile\n  - core#slice#droprightwhile\n  - core#slice#slice\n  - core#slice#withoutnth\n  - core#slice#splice\nposition: 210\nsignatures:\n  - \"func DropByIndex[T any, Slice ~[]T](collection Slice, indexes ...int) Slice\"\n---\n\nDrops elements from a slice by index. Negative indexes count from the end.\n\n```go\nlo.DropByIndex([]int{0, 1, 2, 3, 4, 5}, 2, 4, -1)\n// []int{0, 1, 3}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-dropright.md",
    "content": "---\nname: DropRight\nslug: dropright\nsourceRef: slice.go#L457\ncategory: core\nsubCategory: slice\nplayUrl: https://go.dev/play/p/GG0nXkSJJa3\nvariantHelpers:\n  - core#slice#dropright\nsimilarHelpers:\n  - core#slice#drop\n  - core#slice#dropwhile\n  - core#slice#droprightwhile\n  - core#slice#dropbyindex\n  - core#slice#slice\n  - core#slice#cutsuffix\n  - core#slice#trimright\nposition: 180\nsignatures:\n  - \"func DropRight[T any, Slice ~[]T](collection Slice, n int) Slice\"\n---\n\nDrops n elements from the end of a slice.\n\n```go\nlo.DropRight([]int{0, 1, 2, 3, 4, 5}, 2)\n// []int{0, 1, 2, 3}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-droprightwhile.md",
    "content": "---\nname: DropRightWhile\nslug: droprightwhile\nsourceRef: slice.go#L486\ncategory: core\nsubCategory: slice\nplayUrl: https://go.dev/play/p/HBh8pHl-ZZz\nvariantHelpers:\n  - core#slice#droprightwhile\nsimilarHelpers:\n  - core#slice#dropwhile\n  - core#slice#drop\n  - core#slice#dropright\n  - core#slice#dropbyindex\n  - core#slice#filterreject\n  - core#slice#partitionby\nposition: 200\nsignatures:\n  - \"func DropRightWhile[T any, Slice ~[]T](collection Slice, predicate func(item T) bool) Slice\"\n---\n\nDrops elements from the end while the predicate returns true.\n\n```go\nlo.DropRightWhile([]string{\"a\", \"aa\", \"aaa\", \"aa\", \"aa\"}, func(val string) bool {\n    return len(val) <= 2\n})\n// []string{\"a\", \"aa\", \"aaa\"}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-dropwhile.md",
    "content": "---\nname: DropWhile\nslug: dropwhile\nsourceRef: slice.go#L472\ncategory: core\nsubCategory: slice\nplayUrl: https://go.dev/play/p/b_PYomVQLGy\nvariantHelpers:\n  - core#slice#dropwhile\nsimilarHelpers:\n  - core#slice#droprightwhile\n  - core#slice#drop\n  - core#slice#dropright\n  - core#slice#dropbyindex\n  - core#slice#filterreject\n  - core#slice#partitionby\n  - core#slice#takewhile\nposition: 190\nsignatures:\n  - \"func DropWhile[T any, Slice ~[]T](collection Slice, predicate func(item T) bool) Slice\"\n---\n\nDrops elements from the beginning while the predicate returns true.\n\n```go\nlo.DropWhile([]string{\"a\", \"aa\", \"aaa\", \"aa\", \"aa\"}, func(val string) bool {\n    return len(val) <= 2\n})\n// []string{\"aaa\", \"aa\", \"aa\"}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-durationx.md",
    "content": "---\nname: DurationX\nslug: durationx\nsourceRef: time.go#L7\ncategory: core\nsubCategory: time\nsignatures:\n  - \"func Duration(callback func()) time.Duration\"\n  - \"func Duration0(callback func()) time.Duration\"\n  - \"func Duration1[T any](callback func() T) (T, time.Duration)\"\n  - \"func Duration2[T, U any](callback func() (T, U)) (T, U, time.Duration)\"\n  - \"func Duration3[T, U, V any](callback func() (T, U, V)) (T, U, V, time.Duration)\"\n  - \"func Duration4[T, U, V, W any](callback func() (T, U, V, W)) (T, U, V, W, time.Duration)\"\n  - \"func Duration5[T, U, V, W, X any](callback func() (T, U, V, W, X)) (T, U, V, W, X, time.Duration)\"\n  - \"func Duration6[T, U, V, W, X, Y any](callback func() (T, U, V, W, X, Y)) (T, U, V, W, X, Y, time.Duration)\"\n  - \"func Duration7[T, U, V, W, X, Y, Z any](callback func() (T, U, V, W, X, Y, Z)) (T, U, V, W, X, Y, Z, time.Duration)\"\n  - \"func Duration8[T, U, V, W, X, Y, Z, A any](callback func() (T, U, V, W, X, Y, Z, A)) (T, U, V, W, X, Y, Z, A, time.Duration)\"\n  - \"func Duration9[T, U, V, W, X, Y, Z, A, B any](callback func() (T, U, V, W, X, Y, Z, A, B)) (T, U, V, W, X, Y, Z, A, B, time.Duration)\"\n  - \"func Duration10[T, U, V, W, X, Y, Z, A, B, C any](callback func() (T, U, V, W, X, Y, Z, A, B, C)) (T, U, V, W, X, Y, Z, A, B, C, time.Duration)\"\nplayUrl: https://go.dev/play/p/LFhKq2vY9Ty\nvariantHelpers:\n  - core#time#duration\n  - core#time#durationx\nsimilarHelpers:\n  - core#concurrency#waitfor\n  - core#retry#attemptwithdelay\n  - core#retry#attemptwhilewithdelay\n  - core#retry#newdebounce\n  - core#retry#newdebounceby\n  - core#retry#newthrottle\n  - core#retry#newthrottleby\n  - core#retry#newthrottlebywithcount\nposition: 0\n---\n\nMeasures execution time of a function. Variants return the elapsed duration alongside 0 to 10 returned values from the function.\n\n```go\n// Base variant (no return values): Duration\nelapsedOnly := lo.Duration(func() {\n    time.Sleep(3 * time.Millisecond)\n})\n_ = elapsedOnly\n\n// Zero-return variant: Duration0\nelapsed := lo.Duration0(func() {\n    time.Sleep(10 * time.Millisecond)\n})\n_ = elapsed\n\n// One-return variant: Duration1\nv, dur := lo.Duration1(func() int {\n    time.Sleep(5 * time.Millisecond)\n    return 123\n})\n_ = v\n_ = dur\n\n// Two-return variant: Duration2\na, b, elapsed2 := lo.Duration2(func() (int, string) {\n    time.Sleep(2 * time.Millisecond)\n    return 7, \"x\"\n})\n_ = a\n_ = b\n_ = elapsed2\n```\n\n\n"
  },
  {
    "path": "docs/data/core-earliest.md",
    "content": "---\nname: Earliest\nslug: earliest\nsourceRef: find.go#L363\ncategory: core\nsubCategory: find\nplayUrl: https://go.dev/play/p/pRyy0c6hsBs\nvariantHelpers:\n  - core#find#earliest\nsimilarHelpers:\n  - core#find#latest\n  - core#find#earliestby\n  - core#find#latestby\n  - core#find#min\n  - core#find#max\n  - core#find#minby\n  - core#find#maxby\n  - core#find#minindex\n  - core#find#maxindex\n  - core#find#minindexby\n  - core#find#maxindexby\nposition: 180\nsignatures:\n  - \"func Earliest(times ...time.Time) time.Time\"\n---\n\nSearches the minimum time.Time in the provided arguments. Returns zero value when the input is empty.\n\n```go\nt1 := time.Date(2023, 1, 1, 0, 0, 0, 0, time.UTC)\nt2 := time.Date(2024, 1, 1, 0, 0, 0, 0, time.UTC)\nmin := lo.Earliest(t2, t1)\n// 2023-01-01 00:00:00 +0000 UTC\n```\n\n\n"
  },
  {
    "path": "docs/data/core-earliestby.md",
    "content": "---\nname: EarliestBy\nslug: earliestby\nsourceRef: find.go#L462\ncategory: core\nsubCategory: find\nplayUrl: https://go.dev/play/p/0XvCF6vuLXC\nvariantHelpers:\n  - core#find#earliestby\nsimilarHelpers:\n  - core#find#earliestbyerr\n  - core#find#latestby\n  - core#find#earliest\n  - core#find#latest\n  - core#find#minby\n  - core#find#maxby\n  - core#find#minindexby\n  - core#find#maxindexby\n  - core#find#findby\n  - core#find#findkeyby\n  - core#find#findduplicatesby\n  - core#find#finduniquesby\nposition: 190\nsignatures:\n  - \"func EarliestBy[T any](collection []T, iteratee func(item T) time.Time) T\"\n---\n\nSearches a collection for the element with the minimum time extracted by the predicate. Returns zero value when the collection is empty.\n\n```go\ntype Event struct{ At time.Time }\nevents := []Event{{At: time.Now().Add(2 * time.Hour)}, {At: time.Now()}}\nfirst := lo.EarliestBy(events, func(e Event) time.Time {\n    return e.At\n})\n```\n\n\n"
  },
  {
    "path": "docs/data/core-earliestbyerr.md",
    "content": "---\nname: EarliestByErr\nslug: earliestbyerr\nsourceRef: find.go#L484\ncategory: core\nsubCategory: find\nplayUrl: https://go.dev/play/p/zJUBUj7ANvq\nvariantHelpers:\n  - core#find#earliestbyerr\nsimilarHelpers:\n  - core#find#earliestby\n  - core#find#latestby\n  - core#find#earliest\n  - core#find#latest\n  - core#find#minby\n  - core#find#maxby\nposition: 191\nsignatures:\n  - \"func EarliestByErr[T any](collection []T, iteratee func(item T) (time.Time, error)) (T, error)\"\n---\n\nSearches a collection for the element with the minimum time extracted by the predicate. Returns zero value and nil error when the collection is empty.\n\nIf the iteratee returns an error, iteration stops and the error is returned.\n\n```go\ntype Event struct{ At time.Time }\nevents := []Event{{At: time.Now().Add(2 * time.Hour)}, {At: time.Now()}}\nfirst, err := lo.EarliestByErr(events, func(e Event) (time.Time, error) {\n    return e.At, nil\n})\n// Event, <nil>\n```\n\nExample with error:\n\n```go\ntype Event struct{ At time.Time }\nevents := []Event{{At: time.Now()}, {At: time.Now().Add(time.Hour)}}\nfirst, err := lo.EarliestByErr(events, func(e Event) (time.Time, error) {\n    if e.At.After(time.Now().Add(30 * time.Minute)) {\n        return time.Time{}, fmt.Errorf(\"event too far in the future\")\n    }\n    return e.At, nil\n})\n// Event, error(\"event too far in the future\")\n```\n"
  },
  {
    "path": "docs/data/core-elementsmatch.md",
    "content": "---\nname: ElementsMatch\nslug: elementsmatch\nsourceRef: intersect.go#L247\ncategory: core\nsubCategory: intersect\nplayUrl: https://go.dev/play/p/XWSEM4Ic_t0\nvariantHelpers:\n  - core#intersect#elementsmatch\nsimilarHelpers:\n  - core#intersect#elementsmatchby\n  - core#intersect#contains\n  - core#intersect#containsby\n  - core#intersect#intersect\n  - core#intersect#difference\n  - core#intersect#union\n  - core#intersect#every\n  - core#intersect#everyby\n  - core#intersect#some\n  - core#intersect#someby\n  - core#intersect#none\n  - core#intersect#noneby\nposition: 150\nsignatures:\n  - \"func ElementsMatch[T comparable, Slice ~[]T](list1 Slice, list2 Slice) bool\"\n---\n\nReturns true if lists contain the same set of elements (including empty set). If there are duplicate elements, occurrences must match. Order is not checked.\n\n```go\nlo.ElementsMatch([]int{1, 1, 2}, []int{2, 1, 1})\n// true\n```\n\n\n"
  },
  {
    "path": "docs/data/core-elementsmatchby.md",
    "content": "---\nname: ElementsMatchBy\nslug: elementsmatchby\nsourceRef: intersect.go#L255\ncategory: core\nsubCategory: intersect\nplayUrl: https://go.dev/play/p/XWSEM4Ic_t0\nvariantHelpers:\n  - core#intersect#elementsmatchby\nsimilarHelpers:\n  - core#intersect#elementsmatch\n  - core#intersect#containsby\n  - core#intersect#contains\n  - core#intersect#intersect\n  - core#intersect#difference\n  - core#intersect#union\n  - core#intersect#everyby\n  - core#intersect#every\n  - core#intersect#someby\n  - core#intersect#some\n  - core#intersect#noneby\n  - core#intersect#none\nposition: 160\nsignatures:\n  - \"func ElementsMatchBy[T any, K comparable](list1 []T, list2 []T, iteratee func(item T) K) bool\"\n---\n\nReturns true if lists contain the same set of keys computed by the predicate, with matching multiplicities. Order is not checked.\n\n```go\ntype Item struct{\n    ID string\n}\n\nlo.ElementsMatchBy(\n    []Item{{\"a\"}, {\"b\"}},\n    []Item{{\"b\"}, {\"a\"}},\n    func(i Item) string {\n        return i.ID\n    },\n)\n// true\n```\n\n\n"
  },
  {
    "path": "docs/data/core-ellipsis.md",
    "content": "---\nname: Ellipsis\nslug: ellipsis\nsourceRef: string.go#L235\ncategory: core\nsubCategory: string\nplayUrl: https://go.dev/play/p/qE93rgqe1TW\nvariantHelpers:\n  - core#string#ellipsis\nsimilarHelpers:\n  - core#string#substring\n  - core#string#runelength\n  - core#string#trim\n  - core#string#capitalize\nposition: 100\nsignatures:\n  - \"func Ellipsis(str string, length int) string\"\n---\n\nTrims and truncates a string to the specified length in runes (Unicode code points) and appends an ellipsis if truncated. Multi-byte characters such as emoji or CJK ideographs are never split in the middle.\n\n```go\nlo.Ellipsis(\"  Lorem Ipsum  \", 5)\n// \"Lo...\"\n\nstr = lo.Ellipsis(\"Lorem Ipsum\", 100)\n// \"Lorem Ipsum\"\n\nstr = lo.Ellipsis(\"Lorem Ipsum\", 3)\n// \"...\"\n\nstr = lo.Ellipsis(\"hello 世界! 你好\", 8)\n// \"hello...\"\n\nstr = lo.Ellipsis(\"🏠🐶🐱🌟\", 4)\n// \"🏠🐶🐱🌟\"\n```\n\n\n"
  },
  {
    "path": "docs/data/core-empty.md",
    "content": "---\nname: Empty\nslug: empty\nsourceRef: type_manipulation.go#L132\ncategory: core\nsubCategory: type\nsignatures:\n  - \"func Empty[T any]() T\"\nvariantHelpers:\n  - core#type#empty\nsimilarHelpers:\n  - core#type#isempty\n  - core#type#isnotempty\n  - core#type#coalesceorempty\n  - core#type#coalescesliceorempty\n  - core#type#coalescemaporempty\nposition: 120\n---\n\nReturns the zero value for the specified type. This is useful when you need an empty value of a specific type.\n\n```go\nresult := lo.Empty[string]()\n// \"\" (zero value for string)\n\nresult = lo.Empty[int]()\n// 0 (zero value for int)\n\nresult = lo.Empty[[]int]()\n// []int{} (zero value for slice)\n\nresult = lo.Empty[map[string]int]()\n// map[string]int{} (zero value for map)\n\nresult = lo.Empty[*int]()\n// nil (zero value for pointer)\n```"
  },
  {
    "path": "docs/data/core-emptyabletoptr.md",
    "content": "---\nname: EmptyableToPtr\nslug: emptyabletoptr\nsourceRef: type_manipulation.go#L41\ncategory: core\nsubCategory: type\nsignatures:\n  - \"func EmptyableToPtr[T any](x T) *T\"\nvariantHelpers:\n  - core#type#emptyabletoptr\nsimilarHelpers:\n  - core#type#toptr\n  - core#type#fromptr\n  - core#type#fromptror\n  - core#type#tosliceptr\n  - core#type#fromsliceptr\nposition: 105\n---\n\nReturns a pointer to the provided value, or nil if the value is empty (zero value). This is useful for avoiding pointers to empty values.\n\n```go\nptr := lo.EmptyableToPtr(\"\")\n// nil (because empty string is zero value)\n\nptr = lo.EmptyableToPtr(\"hello\")\n// *string pointing to \"hello\"\n\nptr = lo.EmptyableToPtr(0)\n// nil (because 0 is zero value for int)\n\nptr = lo.EmptyableToPtr(42)\n// *int pointing to 42\n```"
  },
  {
    "path": "docs/data/core-entries.md",
    "content": "---\nname: Entries\nslug: entries\nsourceRef: map.go#L179\ncategory: core\nsubCategory: map\nplayUrl: https://go.dev/play/p/_t4Xe34-Nl5\nvariantHelpers:\n  - core#map#entries\nsimilarHelpers:\n  - core#map#fromentries\n  - core#map#keys\n  - core#map#values\n  - core#map#toentries\nposition: 120\nsignatures:\n  - \"func Entries[K comparable, V any](in map[K]V) []Entry[K, V]\"\n---\n\nTransforms a map into a slice of key/value pairs.\n\n```go\nentries := lo.Entries(map[string]int{\"foo\": 1, \"bar\": 2})\n// []lo.Entry[string, int]{ {Key: \"foo\", Value: 1}, {Key: \"bar\", Value: 2} }\n```\n\n\n"
  },
  {
    "path": "docs/data/core-errorsas.md",
    "content": "---\nname: ErrorsAs\nslug: errorsas\nsourceRef: errors.go#L351\ncategory: core\nsubCategory: error-handling\nplayUrl: https://go.dev/play/p/8wk5rH8UfrE\nvariantHelpers:\n  - core#error-handling#erroras\nsimilarHelpers:\n  - core#error-handling#validate\n  - core#error-handling#mustx\n  - core#error-handling#tryx\n  - core#error-handling#tryorx\n  - core#error-handling#trycatch\n  - core#error-handling#trywitherrorvalue\n  - core#error-handling#trycatchwitherrorvalue\n  - core#error-handling#assert\nposition: 70\nsignatures:\n  - \"func ErrorsAs[T error](err error) (T, bool)\"\n---\n\nA generic wrapper around `errors.As` that returns the typed error and a boolean indicating success.\n\n```go\nif rateLimitErr, ok := lo.ErrorsAs[*RateLimitError](err); ok {\n    // handle\n}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-every.md",
    "content": "---\nname: Every\nslug: every\nsourceRef: intersect.go#L29\ncategory: core\nsubCategory: intersect\nplayUrl: https://go.dev/play/p/W1EvyqY6t9j\nvariantHelpers:\n  - core#intersect#every\nsimilarHelpers:\n  - core#intersect#everyby\n  - core#intersect#some\n  - core#intersect#someby\n  - core#intersect#none\n  - core#intersect#noneby\n  - core#intersect#contains\n  - core#intersect#containsby\n  - core#intersect#elementsmatch\n  - core#intersect#elementsmatchby\nposition: 20\nsignatures:\n  - \"func Every[T comparable](collection []T, subset []T) bool\"\n---\n\nReturns true if all elements of a subset are contained in a collection, or if the subset is empty.\n\n```go\nok := lo.Every([]int{0, 1, 2, 3, 4, 5}, []int{0, 2})\n// true\n```\n\n\n"
  },
  {
    "path": "docs/data/core-everyby.md",
    "content": "---\nname: EveryBy\nslug: everyby\nsourceRef: intersect.go#L41\ncategory: core\nsubCategory: intersect\nplayUrl: https://go.dev/play/p/dn1-vhHsq9x\nvariantHelpers:\n  - core#intersect#everyby\nsimilarHelpers:\n  - core#intersect#every\n  - core#intersect#someby\n  - core#intersect#some\n  - core#intersect#noneby\n  - core#intersect#none\n  - core#intersect#containsby\n  - core#intersect#contains\n  - core#intersect#elementsmatchby\n  - core#intersect#elementsmatch\nposition: 30\nsignatures:\n  - \"func EveryBy[T any](collection []T, predicate func(item T) bool) bool\"\n---\n\nReturns true if the predicate returns true for all elements in the collection, or if the collection is empty.\n\n```go\nok := lo.EveryBy(\n    []int{1, 2, 3, 4},\n    func(x int) bool {\n        return x < 5\n    },\n)\n// true\n```\n\n\n"
  },
  {
    "path": "docs/data/core-fanin.md",
    "content": "---\nname: FanIn\nslug: fanin\nsourceRef: channel.go#L18\ncategory: core\nsubCategory: channel\nsignatures:\n  - \"func FanIn[T any](channelBufferCap int, upstreams ...<-chan T) <-chan T\"\nsimilarHelpers:\n  - core#channel#fanout\n  - core#channel#channeldispatcher\nposition: 254\n---\n\nFanIn merges multiple upstream channels into a single downstream channel, reading from all input channels and forwarding their values to one output channel. The channelBufferCap parameter sets the buffer size of the output channel.\n\n```go\nch1 := make(chan int, 2)\nch2 := make(chan int, 2)\nch1 <- 1\nch1 <- 2\nch2 <- 3\nch2 <- 4\nclose(ch1)\nclose(ch2)\n\nmerged := lo.FanIn(10, ch1, ch2)\nvar result []int\nfor item := range merged {\n    result = append(result, item)\n}\n// result: []int{1, 2, 3, 4} (order may vary as goroutine scheduling differs)\n```"
  },
  {
    "path": "docs/data/core-fanout.md",
    "content": "---\nname: FanOut\nslug: fanout\nsourceRef: channel.go#L18\ncategory: core\nsubCategory: channel\nsignatures:\n  - \"func FanOut[T any](count, channelsBufferCap int, upstream <-chan T) []<-chan T\"\nsimilarHelpers:\n  - core#channel#fanin\n  - core#channel#channeldispatcher\n  - it#channel#channelseq\nposition: 256\n---\n\nFanOut splits a single channel into multiple channels.\n\n```go\nupstream := make(chan int, 6)\nfor i := 0; i < 6; i++ {\n    upstream <- i\n}\nclose(upstream)\n\ndownstreams := lo.FanOut(3, 10, upstream)\n// Returns 3 channels, each receiving 2 items\n```"
  },
  {
    "path": "docs/data/core-fill.md",
    "content": "---\nname: Fill\nslug: fill\nsourceRef: slice.go#L338\ncategory: core\nsubCategory: slice\nplayUrl: https://go.dev/play/p/VwR34GzqEub\nvariantHelpers:\n  - core#slice#fill\nsimilarHelpers:\n  - core#slice#repeat\n  - core#slice#slice\n  - core#slice#flatten\n  - core#slice#chunk\n  - core#slice#chunkentries\n  - core#slice#interleave\n  - core#slice#reverse\n  - core#slice#shuffle\n  - core#slice#sample\n  - core#slice#drop\n  - core#slice#dropwhile\n  - core#slice#dropright\n  - core#slice#droprightwhile\nposition: 200\nsignatures:\n  - \"func Fill[T Clonable[T], Slice ~[]T](collection Slice, initial T) Slice\"\n---\n\nFills a slice with clones of the provided initial value.\n\n```go\ntype foo struct{ bar string }\nfunc (f foo) Clone() foo {\n    return foo{f.bar}\n}\n\nlo.Fill([]foo{{\"a\"}, {\"a\"}}, foo{\"b\"})\n// []foo{{\"b\"}, {\"b\"}}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-filter.md",
    "content": "---\nname: Filter\nslug: filter\nsourceRef: slice.go#L12\ncategory: core\nsubCategory: slice\nplayUrl: https://go.dev/play/p/Apjg3WeSi7K\nsimilarHelpers:\n  - core#slice#reject\n  - core#slice#filtererr\n  - core#slice#filtermap\n  - core#slice#filterreject\n  - core#slice#rejectmap\n  - core#slice#takefilter\n  - parallel#slice#filter\n  - mutable#slice#filter\nvariantHelpers:\n  - core#slice#filter\nposition: 0\nsignatures:\n  - \"func Filter[T any, Slice ~[]T](collection Slice, predicate func(item T, index int) bool) Slice\"\n---\n\nIterates over a collection and returns a slice of all the elements the predicate function returns `true` for.\n\n```go\neven := lo.Filter([]int{1, 2, 3, 4}, func(x int, index int) bool {\n    return x%2 == 0\n})\n// []int{2, 4}\n```\n"
  },
  {
    "path": "docs/data/core-filtererr.md",
    "content": "---\nname: FilterErr\nslug: filtererr\nsourceRef: slice.go#L27\ncategory: core\nsubCategory: slice\nsignatures:\n  - \"func FilterErr[T any, Slice ~[]T](collection Slice, predicate func(item T, index int) (bool, error)) (Slice, error)\"\nplayUrl: https://go.dev/play/p/Apjg3WeSi7K\nvariantHelpers:\n  - core#slice#filtererr\nsimilarHelpers:\n  - core#slice#filter\n  - core#slice#reject\n  - core#slice#filtermap\n  - core#slice#filterreject\nposition: 5\n---\n\nIterates over a collection and returns a slice of all the elements the predicate function returns `true` for. If the predicate returns an error, iteration stops immediately and returns the error.\n\n```go\neven, err := lo.FilterErr([]int{1, 2, 3, 4}, func(x int, index int) (bool, error) {\n    if x == 3 {\n        return false, errors.New(\"number 3 is not allowed\")\n    }\n    return x%2 == 0, nil\n})\n// []int(nil), error(\"number 3 is not allowed\")\n```\n\n```go\neven, err := lo.FilterErr([]int{1, 2, 3, 4}, func(x int, index int) (bool, error) {\n    return x%2 == 0, nil\n})\n// []int{2, 4}, nil\n```\n"
  },
  {
    "path": "docs/data/core-filterkeys.md",
    "content": "---\nname: FilterKeys\nslug: filterkeys\nsourceRef: map.go#L350\ncategory: core\nsubCategory: map\nplayUrl: https://go.dev/play/p/OFlKXlPrBAe\nvariantHelpers:\n  - core#map#filterkeys\nsimilarHelpers:\n  - core#map#filtervalues\n  - core#map#filterkeyserr\n  - core#map#pickbykeys\n  - core#map#omitbykeys\n  - core#map#pickbyvalues\n  - core#map#omitbyvalues\nposition: 230\nsignatures:\n  - \"func FilterKeys[K comparable, V any](in map[K]V, predicate func(key K, value V) bool) []K\"\n---\n\nReturns a slice of keys for which the predicate is true.\n\n```go\nkv := map[int]string{1:\"foo\", 2:\"bar\", 3:\"baz\"}\nresult := lo.FilterKeys(kv, func(k int, v string) bool {\n    return v == \"foo\"\n})\n// []int{1}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-filterkeyserr.md",
    "content": "---\nname: FilterKeysErr\nslug: filterkeyserr\nsourceRef: map.go#L498\ncategory: core\nsubCategory: map\nsignatures:\n  - \"func FilterKeysErr[K comparable, V any](in map[K]V, predicate func(key K, value V) (bool, error)) ([]K, error)\"\nplayUrl: https://go.dev/play/p/j2gUQzCTu4t\nvariantHelpers:\n  - core#map#filterkeyserr\nsimilarHelpers:\n  - core#map#filterkeys\n  - core#map#filtervalueserr\n  - core#slice#filter\nposition: 235\n---\n\nTransforms a map into a slice of keys based on a predicate that can return an error. It is a mix of Filter() and Keys() with error handling. If the predicate returns true, the key is included. If the predicate returns an error, iteration stops immediately and returns the error.\n\n```go\nkv := map[int]string{1:\"foo\", 2:\"bar\", 3:\"baz\"}\nresult, err := lo.FilterKeysErr(kv, func(k int, v string) (bool, error) {\n    if k == 3 {\n        return false, errors.New(\"key 3 not allowed\")\n    }\n    return v == \"foo\", nil\n})\n// []int(nil), error(\"key 3 not allowed\")\n```\n\n```go\nkv := map[int]string{1:\"foo\", 2:\"bar\", 3:\"baz\"}\nresult, err := lo.FilterKeysErr(kv, func(k int, v string) (bool, error) {\n    return v == \"bar\", nil\n})\n// []int{2}, nil\n```\n"
  },
  {
    "path": "docs/data/core-filtermap.md",
    "content": "---\nname: FilterMap\nslug: filtermap\nsourceRef: slice.go#L58\ncategory: core\nsubCategory: slice\nplayUrl: https://go.dev/play/p/CgHYNUpOd1I\nvariantHelpers:\n  - core#slice#filtermap\nsimilarHelpers:\n  - core#slice#map\n  - core#slice#filter\n  - core#slice#uniqmap\n  - core#slice#rejectmap\n  - core#slice#filtermaptoslice\n  - core#slice#takefilter\n  - parallel#slice#filtermap\nposition: 30\nsignatures:\n  - \"func FilterMap[T any, R any](collection []T, callback func(item T, index int) (R, bool)) []R\"\n---\n\nReturns a slice obtained after both filtering and mapping using the given callback function.\n\nThe callback function should return two values: the result of the mapping operation and whether the result element should be included or not.\n\n```go\nmatching := lo.FilterMap([]string{\"cpu\", \"gpu\", \"mouse\", \"keyboard\"}, func(x string, _ int) (string, bool) {\n    if strings.HasSuffix(x, \"pu\") {\n        return \"xpu\", true\n    }\n    return \"\", false\n})\n// []string{\"xpu\", \"xpu\"}\n```\n"
  },
  {
    "path": "docs/data/core-filtermaptoslice.md",
    "content": "---\nname: FilterMapToSlice\nslug: filtermaptoslice\nsourceRef: map.go#L430\ncategory: core\nsubCategory: map\nplayUrl: https://go.dev/play/p/jgsD_Kil9pV\nvariantHelpers:\n  - core#map#filtermaptoslice\nsimilarHelpers:\n  - core#map#maptoslice\n  - core#slice#filtermap\n  - core#slice#filterreject\n  - core#map#filterkeys\n  - core#map#filtervalues\n  - core#map#filtermaptosliceerr\nposition: 220\nsignatures:\n  - \"func FilterMapToSlice[K comparable, V any, R any](in map[K]V, iteratee func(key K, value V) (R, bool)) []R\"\n---\n\nTransforms a map into a slice using an predicate that returns a value and a boolean to include it.\n\n```go\nkv := map[int]int64{1:1, 2:2, 3:3, 4:4}\nresult := lo.FilterMapToSlice(kv, func(k int, v int64) (string, bool) {\n    return fmt.Sprintf(\"%d_%d\", k, v), k%2 == 0\n})\n// []string{\"2_2\", \"4_4\"}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-filtermaptosliceerr.md",
    "content": "---\nname: FilterMapToSliceErr\nslug: filtermaptosliceerr\nsourceRef: map.go#L443\ncategory: core\nsubCategory: map\nsignatures:\n  - \"func FilterMapToSliceErr[K comparable, V any, R any](in map[K]V, iteratee func(key K, value V) (R, bool, error)) ([]R, error)\"\nplayUrl: https://go.dev/play/p/YjFEORLBWvk\nvariantHelpers:\n  - core#map#filtermaptosliceerr\nsimilarHelpers:\n  - core#map#filtermaptoslice\n  - core#map#maptosliceerr\n  - core#slice#filtermap\n  - core#slice#filtermaperr\nposition: 225\n---\n\nTransforms a map into a slice using a predicate that returns a value, a boolean to include it, and an error. Stops iteration immediately on error.\n\n```go\nkv := map[int]int64{1:1, 2:2, 3:3, 4:4}\nresult, err := lo.FilterMapToSliceErr(kv, func(k int, v int64) (string, bool, error) {\n    if k == 3 {\n        return \"\", false, fmt.Errorf(\"key 3 not allowed\")\n    }\n    return fmt.Sprintf(\"%d_%d\", k, v), k%2 == 0, nil\n})\n// []string(nil), error(\"key 3 not allowed\")\n```\n\n```go\nkv := map[int]int64{1:1, 2:2, 3:3, 4:4}\nresult, err := lo.FilterMapToSliceErr(kv, func(k int, v int64) (string, bool, error) {\n    return fmt.Sprintf(\"%d_%d\", k, v), k%2 == 0, nil\n})\n// []string{\"2_2\", \"4_4\"}, nil\n```\n"
  },
  {
    "path": "docs/data/core-filterreject.md",
    "content": "---\nname: FilterReject\nslug: filterreject\nsourceRef: slice.go#L565\ncategory: core\nsubCategory: slice\nplayUrl: https://go.dev/play/p/lHSEGSznJjB\nvariantHelpers:\n  - core#slice#filterreject\nsimilarHelpers:\n  - core#slice#filter\n  - core#slice#reject\n  - core#slice#partitionby\n  - mutable#slice#filterreject\nposition: 280\nsignatures:\n  - \"func FilterReject[T any, Slice ~[]T](collection Slice, predicate func(T, int) bool) (kept Slice, rejected Slice)\"\n---\n\nReturns two slices: elements kept (predicate true) and elements rejected (predicate false).\n\n```go\nkept, rejected := lo.FilterReject(\n    []int{1, 2, 3, 4},\n    func(x int, _ int) bool {\n        return x%2 == 0\n    },\n)\n// kept: []int{2, 4}\n// rejected: []int{1, 3}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-filterslicetomap.md",
    "content": "---\nname: FilterSliceToMap\nslug: filterslicetomap\nsourceRef: slice.go#L414\ncategory: core\nsubCategory: slice\nplayUrl: https://go.dev/play/p/eurMiQEqey2\nvariantHelpers:\n  - core#slice#filterslicetomap\nsimilarHelpers:\n  - core#slice#filter\n  - core#slice#map\n  - core#slice#groupby\n  - core#slice#keyby\nposition: 260\nsignatures:\n  - \"func FilterSliceToMap[T any, K comparable, V any](collection []T, transform func(item T) (K, V, bool)) map[K]V\"\n---\n\nTransforms elements to key/value pairs and includes them in the result only when the transform's boolean is true.\n\n```go\nlist := []string{\"a\", \"aa\", \"aaa\"}\n\nm := lo.FilterSliceToMap(list, func(str string) (string, int, bool) {\n    return str, len(str), len(str) > 1\n})\n// map[string]int{\"aa\": 2, \"aaa\": 3}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-filtervalues.md",
    "content": "---\nname: FilterValues\nslug: filtervalues\nsourceRef: map.go#L365\ncategory: core\nsubCategory: map\nplayUrl: https://go.dev/play/p/YVD5r_h-LX-\nvariantHelpers:\n  - core#map#filtervalues\nsimilarHelpers:\n  - core#map#filterkeys\n  - core#map#filtervalueserr\n  - core#map#pickbyvalues\n  - core#map#omitbyvalues\n  - core#map#pickbykeys\n  - core#map#omitbykeys\nposition: 240\nsignatures:\n  - \"func FilterValues[K comparable, V any](in map[K]V, predicate func(key K, value V) bool) []V\"\n---\n\nReturns a slice of values for which the predicate is true.\n\n```go\nkv := map[int]string{1:\"foo\", 2:\"bar\", 3:\"baz\"}\nresult := lo.FilterValues(kv, func(k int, v string) bool {\n    return v == \"foo\"\n})\n// []string{\"foo\"}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-filtervalueserr.md",
    "content": "---\nname: FilterValuesErr\nslug: filtervalueserr\nsourceRef: map.go#L519\ncategory: core\nsubCategory: map\nsignatures:\n  - \"func FilterValuesErr[K comparable, V any](in map[K]V, predicate func(key K, value V) (bool, error)) ([]V, error)\"\nplayUrl: https://go.dev/play/p/hKvHlqLzbdE\nvariantHelpers:\n  - core#map#filtervalueserr\nsimilarHelpers:\n  - core#map#filtervalues\n  - core#map#filterkeyserr\n  - core#slice#filter\nposition: 245\n---\n\nTransforms a map into a slice of values based on a predicate that can return an error. It is a mix of Filter() and Values() with error handling. If the predicate returns true, the value is included. If the predicate returns an error, iteration stops immediately and returns the error.\n\n```go\nkv := map[int]string{1:\"foo\", 2:\"bar\", 3:\"baz\"}\nresult, err := lo.FilterValuesErr(kv, func(k int, v string) (bool, error) {\n    if k == 3 {\n        return false, errors.New(\"key 3 not allowed\")\n    }\n    return v == \"foo\", nil\n})\n// []string(nil), error(\"key 3 not allowed\")\n```\n\n```go\nkv := map[int]string{1:\"foo\", 2:\"bar\", 3:\"baz\"}\nresult, err := lo.FilterValuesErr(kv, func(k int, v string) (bool, error) {\n    return v == \"bar\", nil\n})\n// []string{\"bar\"}, nil\n```\n"
  },
  {
    "path": "docs/data/core-find.md",
    "content": "---\nname: Find\nslug: find\nsourceRef: find.go#L72\ncategory: core\nsubCategory: find\nplayUrl: https://go.dev/play/p/Eo7W0lvKTky\nvariantHelpers:\n  - core#find#find\nsimilarHelpers:\n  - core#find#findorelse\n  - core#find#findkey\n  - core#find#findindexof\n  - core#find#finderr\n  - core#slice#filter\n  - core#slice#first\n  - core#slice#last\nposition: 40\nsignatures:\n  - \"func Find[T any](collection []T, predicate func(item T) bool) (T, bool)\"\n---\n\nSearches for an element in a slice based on a predicate and returns the element with a boolean indicating success.\n\n```go\nvalue, ok := lo.Find([]string{\"a\", \"b\", \"c\", \"d\"}, func(i string) bool {\n    return i == \"b\"\n})\n// \"b\", true\n\nvalue, ok = lo.Find([]string{\"foobar\"}, func(i string) bool {\n    return i == \"b\"\n})\n// \"\", false\n```\n\n\n"
  },
  {
    "path": "docs/data/core-findduplicates.md",
    "content": "---\nname: FindDuplicates\nslug: findduplicates\nsourceRef: find.go#L207\ncategory: core\nsubCategory: find\nplayUrl: https://go.dev/play/p/muFgL_XBwoP\nvariantHelpers:\n  - core#find#findduplicates\nsimilarHelpers:\n  - core#find#findduplicatesby\n  - core#slice#uniq\n  - core#slice#finduniques\nposition: 120\nsignatures:\n  - \"func FindDuplicates[T comparable, Slice ~[]T](collection Slice) Slice\"\n---\n\nReturns a slice with the first occurrence of each duplicated element in the collection, preserving order.\n\n```go\nlo.FindDuplicates([]int{1, 2, 2, 1, 2, 3})\n// []int{1, 2}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-findduplicatesby.md",
    "content": "---\nname: FindDuplicatesBy\nslug: findduplicatesby\nsourceRef: find.go#L234\ncategory: core\nsubCategory: find\nplayUrl: https://go.dev/play/p/LKdYdNHuGJG\nvariantHelpers:\n  - core#find#findduplicatesby\n  - core#find#findduplicatesbyerr\nsimilarHelpers:\n  - core#find#findduplicates\n  - core#find#finduniques\n  - core#find#finduniquesby\nposition: 130\nsignatures:\n  - \"func FindDuplicatesBy[T any, U comparable, Slice ~[]T](collection Slice, iteratee func(item T) U) Slice\"\n---\n\nReturns a slice with the first occurrence of each duplicated element by key, preserving order.\n\n```go\nlo.FindDuplicatesBy([]int{3, 4, 5, 6, 7}, func(i int) int {\n    return i % 3\n})\n// []int{3, 4}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-findduplicatesbyerr.md",
    "content": "---\nname: FindDuplicatesByErr\nslug: findduplicatesbyerr\nsourceRef: find.go#L296\ncategory: core\nsubCategory: find\nplayUrl: https://go.dev/play/p/HiVILQqdFP0\nsignatures:\n  - \"func FindDuplicatesByErr[T any, U comparable, Slice ~[]T](collection Slice, iteratee func(item T) (U, error)) (Slice, error)\"\nvariantHelpers:\n  - core#find#findduplicatesbyerr\nsimilarHelpers:\n  - core#find#findduplicatesby\n  - core#find#findduplicates\n  - core#find#finduniques\n  - core#find#finduniquesby\nposition: 135\n---\n\nReturns a slice with the first occurrence of each duplicated element by key, preserving order. The iteratee can return an error to stop iteration immediately.\n\n```go\nresult, err := lo.FindDuplicatesByErr([]int{3, 4, 5, 6, 7}, func(i int) (int, error) {\n    return i % 3, nil\n})\n// []int{3, 4}, <nil>\n```\n\nExample with error:\n\n```go\nresult, err := lo.FindDuplicatesByErr([]int{3, 4, 5, 6, 7}, func(i int) (int, error) {\n    if i == 5 {\n        return 0, fmt.Errorf(\"number 5 is not allowed\")\n    }\n    return i % 3, nil\n})\n// []int(nil), error(\"number 5 is not allowed\")\n```\n"
  },
  {
    "path": "docs/data/core-finderr.md",
    "content": "---\nname: FindErr\nslug: finderr\nsourceRef: find.go#L83\ncategory: core\nsubCategory: find\nsignatures:\n  - \"func FindErr[T any](collection []T, predicate func(item T) (bool, error)) (T, error)\"\nplayUrl: https://go.dev/play/p/XK-qtpQWXJ9\nvariantHelpers: []\nsimilarHelpers:\n  - core#find#find\n  - core#find#findorelse\n  - core#find#findkey\n  - core#find#findindexof\n  - core#slice#filter\nposition: 41\n---\n\nSearches for an element in a slice based on a predicate that can return an error. Returns the element and nil error if found. Returns zero value and nil error if not found. If the predicate returns an error, iteration stops immediately and returns zero value and the error.\n\n```go\nresult, err := lo.FindErr([]string{\"a\", \"b\", \"c\", \"d\"}, func(i string) (bool, error) {\n    return i == \"b\", nil\n})\n// \"b\", nil\n\nresult, err = lo.FindErr([]string{\"foobar\"}, func(i string) (bool, error) {\n    return i == \"b\", nil\n})\n// \"\", nil\n\nresult, err = lo.FindErr([]string{\"a\", \"b\", \"c\"}, func(i string) (bool, error) {\n    if i == \"b\" {\n        return false, fmt.Errorf(\"b is not allowed\")\n    }\n    return i == \"b\", nil\n})\n// \"\", error(\"b is not allowed\")\n```\n"
  },
  {
    "path": "docs/data/core-findindexof.md",
    "content": "---\nname: FindIndexOf\nslug: findindexof\nsourceRef: find.go#L87\ncategory: core\nsubCategory: find\nplayUrl: https://go.dev/play/p/XWSEM4Ic_t0\nvariantHelpers:\n  - core#find#findindexof\nsimilarHelpers:\n  - core#find#find\n  - core#slice#indexof\n  - core#find#findlastindexof\nposition: 50\nsignatures:\n  - \"func FindIndexOf[T any](collection []T, predicate func(item T) bool) (T, int, bool)\"\n---\n\nSearches for an element based on a predicate and returns the element, its index, and a boolean indicating success.\n\n```go\nval, idx, ok := lo.FindIndexOf([]string{\"a\", \"b\", \"a\", \"b\"}, func(i string) bool {\n    return i == \"b\"\n})\n// \"b\", 1, true\n```\n\n\n"
  },
  {
    "path": "docs/data/core-findkey.md",
    "content": "---\nname: FindKey\nslug: findkey\nsourceRef: find.go#L128\ncategory: core\nsubCategory: find\nplayUrl: https://go.dev/play/p/Bg0w1VDPYXx\nvariantHelpers:\n  - core#find#findkey\nsimilarHelpers:\n  - core#find#findkeyby\n  - core#find#find\n  - core#find#findby\nposition: 80\nsignatures:\n  - \"func FindKey[K comparable, V comparable](object map[K]V, value V) (K, bool)\"\n---\n\nReturns the first key whose value equals the provided value.\n\n```go\nk, ok := lo.FindKey(map[string]int{\"foo\":1, \"bar\":2, \"baz\":3}, 2)\n// \"bar\", true\n```\n\n\n"
  },
  {
    "path": "docs/data/core-findkeyby.md",
    "content": "---\nname: FindKeyBy\nslug: findkeyby\nsourceRef: find.go#L140\ncategory: core\nsubCategory: find\nplayUrl: https://go.dev/play/p/9IbiPElcyo8\nvariantHelpers:\n  - core#find#findkeyby\nsimilarHelpers:\n  - core#find#findkey\n  - core#find#findby\n  - core#find#findorelse\nposition: 90\nsignatures:\n  - \"func FindKeyBy[K comparable, V any](object map[K]V, predicate func(key K, value V) bool) (K, bool)\"\n---\n\nReturns the first key in the map for which the predicate returns true.\n\n```go\nk, ok := lo.FindKeyBy(map[string]int{\"foo\":1, \"bar\":2, \"baz\":3}, func(k string, v int) bool {\n    return k == \"foo\"\n})\n// \"foo\", true\n```\n\n\n"
  },
  {
    "path": "docs/data/core-findlastindexof.md",
    "content": "---\nname: FindLastIndexOf\nslug: findlastindexof\nsourceRef: find.go#L101\ncategory: core\nsubCategory: find\nplayUrl: https://go.dev/play/p/2VhPMiQvX-D\nvariantHelpers:\n  - core#find#findlastindexof\nsimilarHelpers:\n  - core#find#findindexof\n  - core#find#find\n  - core#find#lastindexof\n  - core#find#findby\nposition: 60\nsignatures:\n  - \"func FindLastIndexOf[T any](collection []T, predicate func(item T) bool) (T, int, bool)\"\n---\n\nSearches for the last element matching the predicate and returns the element, its index, and a boolean indicating success.\n\n```go\nval, idx, ok := lo.FindLastIndexOf([]string{\"a\", \"b\", \"a\", \"b\"}, func(i string) bool {\n    return i == \"b\"\n})\n// \"b\", 3, true\n```\n\n\n"
  },
  {
    "path": "docs/data/core-findorelse.md",
    "content": "---\nname: FindOrElse\nslug: findorelse\nsourceRef: find.go#L116\ncategory: core\nsubCategory: find\nplayUrl: https://go.dev/play/p/Eo7W0lvKTky\nvariantHelpers:\n  - core#find#findorelse\nsimilarHelpers:\n  - core#find#find\n  - core#slice#firstor\n  - core#slice#lastor\n  - core#slice#nthor\nposition: 70\nsignatures:\n  - \"func FindOrElse[T any](collection []T, fallback T, predicate func(item T) bool) T\"\n---\n\nSearches for an element based on a predicate and returns it if found, otherwise returns the fallback.\n\n```go\nvalue := lo.FindOrElse([]string{\"a\", \"b\", \"c\", \"d\"}, \"x\", func(i string) bool {\n    return i == \"b\"\n})\n// \"b\"\n\nvalue = lo.FindOrElse([]string{\"foobar\"}, \"x\", func(i string) bool {\n    return i == \"b\"\n})\n// \"x\"\n```\n\n\n"
  },
  {
    "path": "docs/data/core-finduniques.md",
    "content": "---\nname: FindUniques\nslug: finduniques\nsourceRef: find.go#L152\ncategory: core\nsubCategory: find\nplayUrl: https://go.dev/play/p/NV5vMK_2Z_n\nvariantHelpers:\n  - core#find#finduniques\nsimilarHelpers:\n  - core#find#finduniquesby\n  - core#find#findduplicates\n  - core#find#findduplicatesby\nposition: 100\nsignatures:\n  - \"func FindUniques[T comparable, Slice ~[]T](collection Slice) Slice\"\n---\n\nReturns a slice with elements that appear only once in the collection, preserving original order.\n\n```go\nlo.FindUniques([]int{1, 2, 2, 1, 2, 3})\n// []int{3}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-finduniquesby.md",
    "content": "---\nname: FindUniquesBy\nslug: finduniquesby\nsourceRef: find.go#L178\ncategory: core\nsubCategory: find\nplayUrl: https://go.dev/play/p/2vmxCs4kW_m\nvariantHelpers:\n  - core#find#finduniquesby\nsimilarHelpers:\n  - core#find#finduniques\n  - core#find#findduplicatesby\n  - core#find#uniq\n  - core#find#uniqby\nposition: 110\nsignatures:\n  - \"func FindUniquesBy[T any, U comparable, Slice ~[]T](collection Slice, iteratee func(item T) U) Slice\"\n---\n\nReturns a slice of elements that are unique by a computed key, preserving original order.\n\n```go\nlo.FindUniquesBy([]int{3, 4, 5, 6, 7}, func(i int) int {\n    return i % 3\n})\n// []int{5}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-first.md",
    "content": "---\nname: First\nslug: first\nsourceRef: find.go#L554\ncategory: core\nsubCategory: find\nplayUrl: https://go.dev/play/p/94lu5X6_cbf\nvariantHelpers:\n  - core#find#first\nsimilarHelpers:\n  - core#slice#take\n  - core#slice#takewhile\n  - core#find#firstor\n  - core#find#firstorempty\n  - core#find#last\n  - core#find#lastor\n  - core#find#lastorempty\n  - core#find#nth\nposition: 260\nsignatures:\n  - \"func First[T any](collection []T) (T, bool)\"\n---\n\nReturns the first element of a collection and whether it exists.\n\n```go\nv, ok := lo.First([]int{1, 2, 3})\n// v == 1, ok == true\n```\n\n\n"
  },
  {
    "path": "docs/data/core-firstor.md",
    "content": "---\nname: FirstOr\nslug: firstor\nsourceRef: find.go#L574\ncategory: core\nsubCategory: find\nplayUrl: https://go.dev/play/p/x9CxQyRFXeZ\nvariantHelpers:\n  - core#find#firstor\nsimilarHelpers:\n  - core#find#first\n  - core#find#firstorempty\n  - core#find#lastor\n  - core#find#nthor\nposition: 280\nsignatures:\n  - \"func FirstOr[T any](collection []T, fallback T) T\"\n---\n\nReturns the first element of a collection or the fallback value if empty.\n\n```go\nv := lo.FirstOr([]int{}, -1)\n// v == -1\n```\n\n\n"
  },
  {
    "path": "docs/data/core-firstorempty.md",
    "content": "---\nname: FirstOrEmpty\nslug: firstorempty\nsourceRef: find.go#L567\ncategory: core\nsubCategory: find\nplayUrl: https://go.dev/play/p/i200n9wgrDA\nvariantHelpers:\n  - core#find#firstorempty\nsimilarHelpers:\n  - core#find#first\n  - core#find#firstor\n  - core#find#lastorempty\n  - core#find#nthorempty\nposition: 270\nsignatures:\n  - \"func FirstOrEmpty[T any](collection []T) T\"\n---\n\nReturns the first element of a collection or the zero value if empty.\n\n```go\nv := lo.FirstOrEmpty([]int{})\n// v == 0\n```\n\n\n"
  },
  {
    "path": "docs/data/core-flatmap.md",
    "content": "---\nname: FlatMap\nslug: flatmap\nsourceRef: slice.go#L74\ncategory: core\nsubCategory: slice\nplayUrl: https://go.dev/play/p/pFCF5WVB225\nvariantHelpers:\n  - core#slice#flatmap\nsimilarHelpers:\n  - core#slice#flatmaperr\n  - core#slice#map\n  - core#slice#maperr\n  - parallel#slice#map\n  - mutable#slice#map\n  - core#slice#filtermap\nposition: 40\nsignatures:\n  - \"func FlatMap[T any, R any](collection []T, transform func(item T, index int) []R) []R\"\n---\n\nManipulates a slice and transforms and flattens it to a slice of another type. The transform function can either return a slice or a `nil`, and in the `nil` case no value is added to the final slice.\n\n```go\nout := lo.FlatMap([]int64{0, 1, 2}, func(x int64, _ int) []string {\n    return []string{strconv.FormatInt(x, 10), strconv.FormatInt(x, 10)}\n})\n// []string{\"0\", \"0\", \"1\", \"1\", \"2\", \"2\"}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-flatmaperr.md",
    "content": "---\nname: FlatMapErr\nslug: flatmaperr\nsourceRef: slice.go#L99\ncategory: core\nsubCategory: slice\nsignatures:\n  - \"func FlatMapErr[T any, R any](collection []T, transform func(item T, index int) ([]R, error)) ([]R, error)\"\nvariantHelpers:\n  - core#slice#flatmaperr\nsimilarHelpers:\n  - core#slice#flatmap\n  - core#slice#maperr\n  - core#slice#map\n  - core#slice#filtermap\nposition: 41\n---\n\nManipulates a slice and transforms and flattens it to a slice of another type using a function that can return an error. Stops iteration immediately when an error is encountered.\n\n```go\n// Error case - stops on first error\nresult, err := lo.FlatMapErr([]int64{0, 1, 2, 3}, func(x int64, _ int) ([]string, error) {\n    if x == 2 {\n        return nil, fmt.Errorf(\"number 2 is not allowed\")\n    }\n    return []string{strconv.FormatInt(x, 10), strconv.FormatInt(x, 10)}, nil\n})\n// []string(nil), error(\"number 2 is not allowed\")\n```\n\n```go\n// Success case\nresult, err := lo.FlatMapErr([]int64{0, 1, 2}, func(x int64, _ int) ([]string, error) {\n    return []string{strconv.FormatInt(x, 10), strconv.FormatInt(x, 10)}, nil\n})\n// []string{\"0\", \"0\", \"1\", \"1\", \"2\", \"2\"}, nil\n```\n"
  },
  {
    "path": "docs/data/core-flatten.md",
    "content": "---\nname: Flatten\nslug: flatten\nsourceRef: slice.go#L266\ncategory: core\nsubCategory: slice\nplayUrl: https://go.dev/play/p/rbp9ORaMpjw\nvariantHelpers:\n  - core#slice#flatten\nsimilarHelpers:\n  - core#slice#chunk\n  - core#slice#interleave\n  - core#slice#slice\nposition: 160\nsignatures:\n  - \"func Flatten[T any, Slice ~[]T](collection []Slice) Slice\"\n---\n\nFlattens a slice of slices by one level.\n\n```go\nflat := lo.Flatten([][]int{{0, 1}, {2, 3, 4, 5}})\n// []int{0, 1, 2, 3, 4, 5}\n```\n"
  },
  {
    "path": "docs/data/core-foreach.md",
    "content": "---\nname: ForEach\nslug: foreach\nsourceRef: slice.go#L107\ncategory: core\nsubCategory: slice\nplayUrl: https://go.dev/play/p/oofyiUPRf8t\nvariantHelpers:\n  - core#slice#foreach\nsimilarHelpers:\n  - core#slice#times\n  - core#slice#map\n  - core#slice#foreachwhile\n  - parallel#slice#foreach\nposition: 70\nsignatures:\n  - \"func ForEach[T any](collection []T, callback func(item T, index int))\"\n---\n\nIterates over elements of a collection and invokes the callback for each element.\n\n```go\nlo.ForEach([]string{\"hello\", \"world\"}, func(x string, _ int) {\n    println(x)\n})\n// prints \"hello\\nworld\\n\"\n```\n\n\n"
  },
  {
    "path": "docs/data/core-foreachwhile.md",
    "content": "---\nname: ForEachWhile\nslug: foreachwhile\nsourceRef: slice.go#L116\ncategory: core\nsubCategory: slice\nsignatures:\n  - \"func ForEachWhile[T any](collection []T, predicate func(item T, index int) bool)\"\nplayUrl: https://go.dev/play/p/dG7h9H4nJQf\nvariantHelpers:\n  - core#slice#foreachwhile\nsimilarHelpers:\n  - core#slice#foreach\n  - core#slice#filter\n  - core#slice#some\n  - core#slice#every\n  - core#slice#droprightwhile\n  - core#slice#dropwhile\n  - parallel#slice#foreach\nposition: 80\n---\n\nIterates over elements of a collection and invokes the predicate for each element until false is returned.\n\n```go\nnumbers := []int64{1, 2, -9223372036854775808, 4}\nlo.ForEachWhile(numbers, func(x int64, _ int) bool {\n    if x < 0 {\n        return false\n    }\n    fmt.Println(x)\n    return true\n})\n// Output:\n// 1\n// 2\n```"
  },
  {
    "path": "docs/data/core-fromanyslice.md",
    "content": "---\nname: FromAnySlice\nslug: fromanyslice\nsourceRef: type_manipulation.go#L118\ncategory: core\nsubCategory: type\nsignatures:\n  - \"func FromAnySlice[T any](in []any) ([]T, bool)\"\nvariantHelpers:\n  - core#type#fromanyslice\nsimilarHelpers:\n  - core#type#toanyslice\n  - core#type#tosliceptr\n  - core#type#fromsliceptr\nposition: 128\n---\n\nConverts a slice of empty interface values back to a typed slice. Returns the converted slice and a boolean indicating success. All elements must be of the target type.\n\n```go\ndata := []any{1, 2, 3}\nresult, ok := lo.FromAnySlice[int](data)\n// []int{1, 2, 3}, true\n\ndata = []any{\"a\", \"b\", \"c\"}\nresult, ok = lo.FromAnySlice[string](data)\n// []string{\"a\", \"b\", \"c\"}, true\n\ndata = []any{1, \"b\", 3} // mixed types\nresult, ok = lo.FromAnySlice[int](data)\n// []int{}, false (conversion failed due to string element)\n\ndata = []any{} // empty slice\nresult, ok = lo.FromAnySlice[int](data)\n// []int{}, true (empty slice always succeeds)\n```"
  },
  {
    "path": "docs/data/core-fromentries.md",
    "content": "---\nname: FromEntries\nslug: fromentries\nsourceRef: map.go#L201\ncategory: core\nsubCategory: map\nplayUrl: https://go.dev/play/p/oIr5KHFGCEN\nvariantHelpers:\n  - core#map#fromentries\nsimilarHelpers:\n  - core#map#frompairs\n  - core#map#entries\n  - core#map#topairs\n  - core#map#keys\n  - core#map#values\nposition: 130\nsignatures:\n  - \"func FromEntries[K comparable, V any](entries []Entry[K, V]) map[K]V\"\n---\n\nTransforms a slice of key/value pairs into a map.\n\n```go\nm := lo.FromEntries([]lo.Entry[string, int]{\n    {Key: \"foo\", Value: 1},\n    {Key: \"bar\", Value: 2},\n})\n// map[string]int{\"foo\": 1, \"bar\": 2}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-frompairs.md",
    "content": "---\nname: FromPairs\nslug: frompairs\nsourceRef: map.go#L214\ncategory: core\nsubCategory: map\nplayUrl: https://go.dev/play/p/oIr5KHFGCEN\nvariantHelpers:\n  - core#map#frompairs\nsimilarHelpers:\n  - core#map#fromentries\n  - core#map#entries\n  - core#map#topairs\n  - core#map#keys\n  - core#map#values\nposition: 140\nsignatures:\n  - \"func FromPairs[K comparable, V any](entries []Entry[K, V]) map[K]V\"\n---\n\nTransforms a slice of key/value pairs into a map. Alias of `FromEntries`.\n\n```go\nm := lo.FromPairs([]lo.Entry[string, int]{{Key: \"foo\", Value: 1}})\n// map[string]int{\"foo\": 1}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-fromptr.md",
    "content": "---\nname: FromPtr\nslug: fromptr\nsourceRef: type_manipulation.go#L53\ncategory: core\nsubCategory: type\nsignatures:\n  - \"func FromPtr[T any](x *T) T\"\nvariantHelpers:\n  - core#type#fromptr\nsimilarHelpers:\n  - core#type#toptr\n  - core#type#fromptror\n  - core#type#emptyabletoptr\n  - core#type#tosliceptr\n  - core#type#fromsliceptr\nposition: 95\n---\n\nDereferences a pointer and returns the underlying value. If the pointer is nil, returns the zero value for the type. This is a safe way to extract values from optional pointers without risking panics.\n\n```go\nptr := lo.ToPtr(42)\nvalue := lo.FromPtr(ptr)\n// value: 42\n\nvalue = lo.FromPtr[string](nil)\n// value: \"\" (zero value for string)\n\nvalue = lo.FromPtr[int](nil)\n// value: 0 (zero value for int)\n\n// Working with structs\ntype Person struct {\n    Name string\n    Age  int\n}\nvar personPtr *Person\nperson := lo.FromPtr(personPtr)\n// person: Person{Name: \"\", Age: 0} (zero value for Person)\n```"
  },
  {
    "path": "docs/data/core-fromptror.md",
    "content": "---\nname: FromPtrOr\nslug: fromptror\nsourceRef: type_manipulation.go#L63\ncategory: core\nsubCategory: type\nsignatures:\n  - \"func FromPtrOr[T any](x *T, fallback T) T\"\nvariantHelpers:\n  - core#type#fromptror\nsimilarHelpers:\n  - core#type#toptr\n  - core#type#fromptr\n  - core#type#emptyabletoptr\n  - core#type#tosliceptr\n  - core#type#fromsliceptr\n  - core#type#valueor\nposition: 100\n---\n\nReturns the value pointed to by the pointer, or the fallback value if the pointer is nil.\n\n```go\nptr := lo.ToPtr(42)\nvalue := lo.FromPtrOr(ptr, 0)\n// 42\n\nvalue = lo.FromPtrOr[string](nil, \"default\")\n// \"default\"\n\nvalue = lo.FromPtrOr[int](nil, -1)\n// -1\n\nptr = nil\nvalue = lo.FromPtrOr(ptr, 999)\n// 999\n```"
  },
  {
    "path": "docs/data/core-fromsliceptr.md",
    "content": "---\nname: FromSlicePtr\nslug: fromsliceptr\nsourceRef: type_manipulation.go#L85\ncategory: core\nsubCategory: type\nsignatures:\n  - \"func FromSlicePtr[T any](collection []*T) []T\"\nvariantHelpers:\n  - core#type#fromsliceptr\nsimilarHelpers:\n  - core#type#toptr\n  - core#type#fromptr\n  - core#type#fromptror\n  - core#type#emptyabletoptr\n  - core#type#tosliceptr\nposition: 115\n---\n\nConverts a slice of pointers to a slice of values. Nil pointers are converted to zero values.\n\n```go\na, b, c := 1, 2, 3\nptrs := []*int{&a, &b, &c}\nslice := lo.FromSlicePtr(ptrs)\n// []int{1, 2, 3}\n\na, b = \"hello\", \"world\"\nptrs = []*string{&a, nil, &b}\nslice = lo.FromSlicePtr(ptrs)\n// []string{\"hello\", \"\", \"world\"} (nil pointer becomes zero value)\n\nptrs = []*int{}\nslice = lo.FromSlicePtr(ptrs)\n// []int{}\n```"
  },
  {
    "path": "docs/data/core-generator.md",
    "content": "---\nname: Generator\nslug: generator\nsourceRef: channel.go#L18\ncategory: core\nsubCategory: channel\nsignatures:\n  - \"func Generator[T any](bufferSize int, generator func(yield func(T))) <-chan T\"\nsimilarHelpers:\n  - core#channel#slicetochannel\n  - core#channel#fanin\n  - it#channel#seqtochannel\nposition: 253\n---\n\nGenerator creates a channel from a generator function.\n\n```go\ngen := lo.Generator(10, func(yield func(int)) {\n    for i := 0; i < 10; i++ {\n        yield(i * 2)\n    }\n})\n\nfor item := range gen {\n    fmt.Println(item)\n}\n// Prints even numbers 0, 2, 4, 6, 8, 10, 12, 14, 16, 18\n```"
  },
  {
    "path": "docs/data/core-groupby.md",
    "content": "---\nname: GroupBy\nslug: groupby\nsourceRef: slice.go#L180\ncategory: core\nsubCategory: slice\nplayUrl: https://go.dev/play/p/XnQBd_v6brd\nvariantHelpers:\n  - core#slice#groupby\nsimilarHelpers:\n  - core#slice#groupbyerr\n  - core#slice#groupbymap\n  - core#slice#partitionby\n  - core#slice#keyby\n  - parallel#slice#groupby\nposition: 120\nsignatures:\n  - \"func GroupBy[T any, U comparable, Slice ~[]T](collection Slice, iteratee func(item T) U) map[U]Slice\"\n---\n\nGroups elements by a key computed from each element. The result is a map keyed by the group key with slices of original elements.\n\n```go\ngroups := lo.GroupBy(\n    []int{0, 1, 2, 3, 4, 5},\n    func(i int) int {\n        return i % 3\n    },\n)\n// map[int][]int{0: {0, 3}, 1: {1, 4}, 2: {2, 5}}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-groupbyerr.md",
    "content": "---\nname: GroupByErr\nslug: groupbyerr\nsourceRef: slice.go#L279\ncategory: core\nsubCategory: slice\nplayUrl: https://go.dev/play/p/BzKPcY3AdX2\nsignatures:\n  - \"func GroupByErr[T any, U comparable, Slice ~[]T](collection Slice, iteratee func(item T) (U, error)) (map[U]Slice, error)\"\nvariantHelpers:\n  - core#slice#groupbyerr\nsimilarHelpers:\n  - core#slice#groupby\n  - core#slice#groupbymap\n  - core#slice#partitionby\n  - core#slice#keyby\n  - parallel#slice#groupby\nposition: 121\n---\n\nGroups elements by a key computed from each element using an iteratee that can return an error. Stops iteration immediately when an error is encountered. The result is a map keyed by the group key with slices of original elements.\n\n```go\n// Error case - stops on first error\nresult, err := lo.GroupByErr([]int{0, 1, 2, 3, 4, 5}, func(i int) (int, error) {\n    if i == 3 {\n        return 0, fmt.Errorf(\"number 3 is not allowed\")\n    }\n    return i % 3, nil\n})\n// map[int][]int(nil), error(\"number 3 is not allowed\")\n```\n\n```go\n// Success case\nresult, err := lo.GroupByErr([]int{0, 1, 2, 3, 4, 5}, func(i int) (int, error) {\n    return i % 3, nil\n})\n// map[int][]int{0: {0, 3}, 1: {1, 4}, 2: {2, 5}}, nil\n```\n"
  },
  {
    "path": "docs/data/core-groupbymap.md",
    "content": "---\nname: GroupByMap\nslug: groupbymap\nsourceRef: slice.go#L194\ncategory: core\nsubCategory: slice\nplayUrl: https://go.dev/play/p/iMeruQ3_W80\nvariantHelpers:\n  - core#slice#groupbymap\nsimilarHelpers:\n  - core#slice#groupbymaperr\n  - core#slice#groupby\n  - core#slice#groupbyerr\n  - core#slice#partitionby\n  - core#slice#keyby\n  - core#map#associate\n  - parallel#slice#groupby\nposition: 130\nsignatures:\n  - \"func GroupByMap[T any, K comparable, V any](collection []T, transform func(item T) (K, V)) map[K][]V\"\n---\n\nGroups items by a key computed from each element and maps each element to a value.\n\n```go\ngroups := lo.GroupByMap(\n    []int{0, 1, 2, 3, 4, 5},\n    func(i int) (int, int) {\n        return i % 3, i * 2\n    },\n)\n// map[int][]int{0:{0,6}, 1:{2,8}, 2:{4,10}}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-groupbymaperr.md",
    "content": "---\nname: GroupByMapErr\nslug: groupbymaperr\nsourceRef: slice.go#L311\ncategory: core\nsubCategory: slice\nsignatures:\n  - \"func GroupByMapErr[T any, K comparable, V any](collection []T, transform func(item T) (K, V, error)) (map[K][]V, error)\"\nvariantHelpers:\n  - core#slice#groupbymaperr\nsimilarHelpers:\n  - core#slice#groupbymap\n  - core#slice#groupby\n  - core#slice#groupbyerr\n  - core#slice#partitionby\n  - core#slice#keyby\n  - core#map#associate\n  - parallel#slice#groupby\nposition: 131\n---\n\nGroups items by a key computed from each element and maps each element to a value using a transform function that can return an error. Stops iteration immediately when an error is encountered.\n\n```go\n// Error case - stops on first error\nresult, err := lo.GroupByMapErr([]int{0, 1, 2, 3, 4, 5}, func(i int) (int, int, error) {\n    if i == 3 {\n        return 0, 0, fmt.Errorf(\"number 3 is not allowed\")\n    }\n    return i % 3, i * 2, nil\n})\n// map[int][]int(nil), error(\"number 3 is not allowed\")\n```\n\n```go\n// Success case\nresult, err := lo.GroupByMapErr([]int{0, 1, 2, 3, 4, 5}, func(i int) (int, int, error) {\n    return i % 3, i * 2, nil\n})\n// map[int][]int{0: {0, 6}, 1: {2, 8}, 2: {4, 10}}, nil\n```\n"
  },
  {
    "path": "docs/data/core-haskey.md",
    "content": "---\nname: HasKey\nslug: haskey\nsourceRef: map.go#L47\ncategory: core\nsubCategory: map\nplayUrl: https://go.dev/play/p/aVwubIvECqS\nvariantHelpers:\n  - core#map#haskey\nsimilarHelpers:\n  - core#map#valueor\n  - core#map#keys\n  - core#map#values\nposition: 20\nsignatures:\n  - \"func HasKey[K comparable, V any](in map[K]V, key K) bool\"\n---\n\nReturns whether the given key exists in the map.\n\n```go\nexists := lo.HasKey(map[string]int{\"foo\": 1, \"bar\": 2}, \"foo\")\n// true\n\nexists = lo.HasKey(map[string]int{\"foo\": 1, \"bar\": 2}, \"baz\")\n// false\n```\n\n\n"
  },
  {
    "path": "docs/data/core-hasprefix.md",
    "content": "---\nname: HasPrefix\nslug: hasprefix\nsourceRef: find.go#L41\ncategory: core\nsubCategory: find\nplayUrl: https://go.dev/play/p/SrljzVDpMQM\nvariantHelpers:\n  - core#find#hasprefix\nsimilarHelpers:\n  - core#find#hassuffix\n  - core#find#contains\n  - core#slice#trimleft\n  - core#slice#trimprefix\nposition: 20\nsignatures:\n  - \"func HasPrefix[T comparable](collection []T, prefix []T) bool\"\n---\n\nReturns true if a collection starts with the given prefix slice.\n\n```go\nlo.HasPrefix([]int{1, 2, 3, 4}, []int{1, 2})\n// true\n```\n\n\n"
  },
  {
    "path": "docs/data/core-hassuffix.md",
    "content": "---\nname: HasSuffix\nslug: hassuffix\nsourceRef: find.go#L57\ncategory: core\nsubCategory: find\nplayUrl: https://go.dev/play/p/bJeLetQNAON\nvariantHelpers:\n  - core#find#hassuffix\nsimilarHelpers:\n  - core#find#hasprefix\n  - core#find#contains\n  - core#slice#trimright\n  - core#slice#trimsuffix\nposition: 30\nsignatures:\n  - \"func HasSuffix[T comparable](collection []T, suffix []T) bool\"\n---\n\nReturns true if a collection ends with the given suffix slice.\n\n```go\nlo.HasSuffix([]int{1, 2, 3, 4}, []int{3, 4})\n// true\n```\n\n\n"
  },
  {
    "path": "docs/data/core-if.md",
    "content": "---\nname: If/Else\nslug: if-else\nsourceRef: condition.go#L31\ncategory: core\nsubCategory: condition\nplayUrl: https://go.dev/play/p/WSw3ApMxhyW\nvariantHelpers:\n  - core#condition#if\n  - core#condition#iff\nsimilarHelpers:\n  - core#condition#switch\n  - core#condition#ternary\n  - core#condition#validate\nposition: 10\nsignatures:\n  - \"func If[T any](condition bool, result T) *ifElse[T]\"\n  - \"func IfF[T any](condition bool, resultF func() T) *ifElse[T]\"\n  - \"func (i *ifElse[T]) ElseIf(condition bool, result T) *ifElse[T]\"\n  - \"func (i *ifElse[T]) ElseIfF(condition bool, resultF func() T) *ifElse[T]\"\n  - \"func (i *ifElse[T]) Else(result T) T\"\n  - \"func (i *ifElse[T]) ElseF(resultF func() T) T\"\n---\n\nA fluent conditional builder that allows chaining If/ElseIf/Else conditions.\n\n### If\n\nStarts a fluent If/ElseIf/Else chain. Returns a builder that can be completed with `ElseIf`, `Else`, etc.\n\n```go\nresult := lo.If(true, 1).Else(3)\n// 1\n```\n\n### IfF\n\nFunction form of If. Lazily computes the initial result when the condition is true.\n\n```go\nresult := lo.IfF(true, func() int {\n    return 1\n}).Else(3)\n// 1\n```\n\n### ElseIf\n\nAdds an ElseIf branch to an If/Else chain.\n\n```go\nresult := lo.If(false, 1).ElseIf(true, 2).Else(3)\n// 2\n```\n\n### ElseIfF\n\nFunction form of ElseIf. Lazily computes the branch result when the condition is true.\n\n```go\nresult := lo.If(false, 1).ElseIfF(true, func() int {\n    return 2\n}).Else(3)\n// 2\n```\n\n### Else\n\nCompletes the If/Else chain by returning the chosen result or the default provided here.\n\n```go\nresult := lo.If(false, 1).ElseIf(false, 2).Else(3)\n// 3\n```\n\n### ElseF\n\nFunction form of Else. Lazily computes the default result if no previous branch matched.\n\n```go\nresult := lo.If(false, 1).ElseIf(false, 2).ElseF(func() int {\n    return 3\n})\n// 3\n```"
  },
  {
    "path": "docs/data/core-indexof.md",
    "content": "---\nname: IndexOf\nslug: indexof\nsourceRef: find.go#L14\ncategory: core\nsubCategory: find\nplayUrl: https://go.dev/play/p/Eo7W0lvKTky\nvariantHelpers:\n  - core#find#indexof\nsimilarHelpers:\n  - core#find#findindexof\n  - core#find#findlastindexof\n  - core#find#lastindexof\n  - core#find#find\nposition: 0\nsignatures:\n  - \"func IndexOf[T comparable](collection []T, element T) int\"\n---\n\nReturns the index of the first occurrence of a value in a slice, or -1 if not found.\n\n```go\nidx := lo.IndexOf([]int{0, 1, 2, 1, 2, 3}, 2)\n// 2\n\nidx = lo.IndexOf([]int{0, 1, 2, 1, 2, 3}, 6)\n// -1\n```\n\n\n"
  },
  {
    "path": "docs/data/core-interleave.md",
    "content": "---\nname: Interleave\nslug: interleave\nsourceRef: slice.go#L282\ncategory: core\nsubCategory: slice\nplayUrl: https://go.dev/play/p/KOVtGUt-tdI\nvariantHelpers:\n  - core#slice#interleave\nsimilarHelpers:\n  - core#slice#flatten\n  - core#slice#chunk\n  - core#slice#slice\n  - core#slice#shuffle\nposition: 170\nsignatures:\n  - \"func Interleave[T any, Slice ~[]T](collections ...Slice) Slice\"\n---\n\nRound-robins input slices by index, appending values sequentially into the result.\n\n```go\nlo.Interleave([]int{1, 4, 7}, []int{2, 5, 8}, []int{3, 6, 9})\n// []int{1, 2, 3, 4, 5, 6, 7, 8, 9}\n\nlo.Interleave([]int{1}, []int{2, 5, 8}, []int{3, 6}, []int{4, 7, 9, 10})\n// []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-intersect.md",
    "content": "---\nname: Intersect\nslug: intersect\nsourceRef: intersect.go#L103\ncategory: core\nsubCategory: intersect\nplayUrl: https://go.dev/play/p/uuElL9X9e58\nvariantHelpers:\n  - core#intersect#intersect\nsimilarHelpers:\n  - core#intersect#intersectby\n  - it#intersect#intersect\n  - it#intersect#intersectby\n  - core#intersect#difference\n  - core#intersect#union\n  - core#intersect#without\n  - core#slice#uniq\nposition: 80\nsignatures:\n  - \"func Intersect[T comparable, Slice ~[]T](lists ...Slice) Slice\"\n---\n\nReturns the intersection between collections.\n\n```go\nlo.Intersect([]int{0, 3, 5, 7}, []int{3, 5}, []int{0, 1, 2, 0, 3, 0})\n// []int{3}\n```\n"
  },
  {
    "path": "docs/data/core-intersectby.md",
    "content": "---\nname: IntersectBy\nslug: intersectby\nsourceRef: intersect.go#L174\ncategory: core\nsubCategory: intersect\nplayUrl: https://go.dev/play/p/uWF8y2-zmtf\nvariantHelpers:\n  - core#intersect#intersectby\nsimilarHelpers:\n  - core#intersect#intersect\n  - it#intersect#intersect\n  - it#intersect#intersectby\n  - core#intersect#difference\n  - core#intersect#union\n  - core#intersect#without\n  - core#slice#uniq\nposition: 80\nsignatures:\n  - \"func IntersectBy[T any, K comparable, Slice ~[]T](transform func(T) K, lists ...Slice) Slice\"\n---\n\nReturns the intersection between two collections using a custom key selector function.\n\n```go\ntransform := func(v int) string {\n  return strconv.Itoa(v)\n}\n\nlo.IntersectBy(transform, []int{0, 3, 5, 7}, []int{3, 5}, []int{0, 1, 2, 0, 3, 0})\n// []int{3}\n```\n"
  },
  {
    "path": "docs/data/core-invert.md",
    "content": "---\nname: Invert\nslug: invert\nsourceRef: map.go#L222\ncategory: core\nsubCategory: map\nplayUrl: https://go.dev/play/p/rFQ4rak6iA1\nvariantHelpers:\n  - core#map#invert\nsimilarHelpers:\n  - core#map#entries\n  - core#map#topairs\n  - core#map#frompairs\nposition: 150\nsignatures:\n  - \"func Invert[K comparable, V comparable](in map[K]V) map[V]K\"\n---\n\nCreates a map with keys and values swapped. If values are duplicated, later keys overwrite earlier ones.\n\n```go\nlo.Invert(map[string]int{\"a\": 1, \"b\": 2})\n// map[int]string{1: \"a\", 2: \"b\"}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-isempty.md",
    "content": "---\nname: IsEmpty\nslug: isempty\nsourceRef: type_manipulation.go#L139\ncategory: core\nsubCategory: type\nsignatures:\n  - \"func IsEmpty[T comparable](v T) bool\"\nvariantHelpers:\n  - core#type#isempty\nsimilarHelpers:\n  - core#type#isnotempty\n  - core#type#empty\n  - core#type#isnil\n  - core#type#isnotnil\nposition: 122\n---\n\nReturns true if the value is empty (zero value) for comparable types. This works with strings, numbers, slices, maps, pointers, etc.\n\n```go\nresult := lo.IsEmpty(\"\")\n// true (empty string)\n\nresult = lo.IsEmpty(\"hello\")\n// false\n\nresult = lo.IsEmpty(0)\n// true (zero value for int)\n\nresult = lo.IsEmpty(42)\n// false\n\nresult = lo.IsEmpty([]int{})\n// true (empty slice)\n\nresult = lo.IsEmpty([]int{1, 2, 3})\n// false\n\nresult = lo.IsEmpty(map[string]int{})\n// true (empty map)\n\nvar ptr *int\nresult = lo.IsEmpty(ptr)\n// true (nil pointer)\n```"
  },
  {
    "path": "docs/data/core-isnil.md",
    "content": "---\nname: IsNil\nslug: isnil\nsourceRef: type_manipulation.go#L7\ncategory: core\nsubCategory: type\nsignatures:\n  - \"func IsNil(x any) bool\"\nvariantHelpers:\n  - core#type#isnil\nsimilarHelpers:\n  - core#type#isnotnil\n  - core#type#empty\n  - core#type#isempty\n  - core#type#isnotempty\nposition: 85\n---\n\nReturns true if the input is nil or points to a nil value. This works with pointers, interfaces, maps, slices, channels, and functions.\n\n```go\nresult := lo.IsNil(nil)\n// true\n\nvar ptr *int\nresult = lo.IsNil(ptr)\n// true\n\nresult = lo.IsNil(42)\n// false\n\nresult = lo.IsNil(\"hello\")\n// false\n\nvar iface interface{}\nresult = lo.IsNil(iface)\n// true\n\niface = 42\nresult = lo.IsNil(iface)\n// false\n```"
  },
  {
    "path": "docs/data/core-isnotempty.md",
    "content": "---\nname: IsNotEmpty\nslug: isnotempty\nsourceRef: type_manipulation.go#L146\ncategory: core\nsubCategory: type\nsignatures:\n  - \"func IsNotEmpty[T comparable](v T) bool\"\nvariantHelpers:\n  - core#type#isnotempty\nsimilarHelpers:\n  - core#type#isempty\n  - core#type#empty\n  - core#type#isnil\n  - core#type#isnotnil\nposition: 124\n---\n\nReturns true if the value is not empty (not zero value) for comparable types. This is the opposite of IsEmpty.\n\n```go\nresult := lo.IsNotEmpty(\"\")\n// false (empty string)\n\nresult = lo.IsNotEmpty(\"hello\")\n// true\n\nresult = lo.IsNotEmpty(0)\n// false (zero value for int)\n\nresult = lo.IsNotEmpty(42)\n// true\n\nresult = lo.IsNotEmpty([]int{})\n// false (empty slice)\n\nresult = lo.IsNotEmpty([]int{1, 2, 3})\n// true\n\nresult = lo.IsNotEmpty(map[string]int{})\n// false (empty map)\n\nvar ptr *int\nresult = lo.IsNotEmpty(ptr)\n// false (nil pointer)\n```"
  },
  {
    "path": "docs/data/core-isnotnil.md",
    "content": "---\nname: IsNotNil\nslug: isnil\nsourceRef: type_manipulation.go#L22\ncategory: core\nsubCategory: type\nsignatures:\n  - \"func IsNotNil(x any) bool\"\nvariantHelpers:\n  - core#type#isnotnil\nsimilarHelpers:\n  - core#type#isnil\n  - core#type#empty\n  - core#type#isempty\n  - core#type#isnotempty\nposition: 87\n---\n\nReturns true if the input is not nil and does not point to a nil value. This works with pointers, interfaces, maps, slices, channels, and functions.\n\n```go\nresult := lo.IsNotNil(nil)\n// false\n\nvar ptr *int\nresult = lo.IsNotNil(ptr)\n// false\n\nresult = lo.IsNotNil(42)\n// true\n\nresult = lo.IsNotNil(\"hello\")\n// true\n\nvar iface interface{}\nresult = lo.IsNotNil(iface)\n// false\n\niface = 42\nresult = lo.IsNotNil(iface)\n// true\n```"
  },
  {
    "path": "docs/data/core-issorted.md",
    "content": "---\nname: IsSorted\nslug: issorted\nsourceRef: slice.go#L722\ncategory: core\nsubCategory: slice\nplayUrl: https://go.dev/play/p/mc3qR-t4mcx\nvariantHelpers:\n  - core#slice#issorted\nsimilarHelpers:\n  - core#slice#issortedby\n  - core#slice#min\n  - core#slice#max\n  - core#slice#reverse\nposition: 0\nsignatures:\n  - \"func IsSorted[T constraints.Ordered](collection []T) bool\"\n---\n\nChecks if a slice is sorted in ascending order.\n\n```go\nlo.IsSorted([]int{0, 1, 2, 3, 4, 5})\n// true\n```\n\n\n"
  },
  {
    "path": "docs/data/core-issortedby.md",
    "content": "---\nname: IsSortedBy\nslug: issortedby\nsourceRef: slice.go#L733\ncategory: core\nsubCategory: slice\nplayUrl: https://go.dev/play/p/wiG6XyBBu49\nvariantHelpers:\n  - core#slice#issortedby\nsimilarHelpers:\n  - core#slice#issorted\n  - core#slice#minby\n  - core#slice#maxby\n  - core#slice#reverse\nposition: 0\nsignatures:\n  - \"func IsSortedBy[T any, K constraints.Ordered](collection []T, iteratee func(item T) K) bool\"\n---\n\nChecks if a slice is sorted based on a key computed for each element.\n\n```go\nok := lo.IsSortedBy([]string{\"a\", \"bb\", \"ccc\"}, func(s string) int {\n    return len(s)\n})\n// true\n```\n"
  },
  {
    "path": "docs/data/core-kebabcase.md",
    "content": "---\nname: KebabCase\nslug: kebabcase\nsourceRef: string.go#L190\ncategory: core\nsubCategory: string\nplayUrl: https://go.dev/play/p/ZBeMB4-pq45\nvariantHelpers:\n  - core#string#kebabcase\nsimilarHelpers:\n  - core#string#pascalcase\n  - core#string#camelcase\n  - core#string#snakecase\n  - core#string#capitalize\n  - core#string#words\nposition: 60\nsignatures:\n  - \"func KebabCase(str string) string\"\n---\n\nConverts a string to kebab-case.\n\n```go\nlo.KebabCase(\"helloWorld\")\n// \"hello-world\"\n```\n\n\n"
  },
  {
    "path": "docs/data/core-keyby.md",
    "content": "---\nname: KeyBy\nslug: keyby\nsourceRef: slice.go#L374\ncategory: core\nsubCategory: slice\nplayUrl: https://go.dev/play/p/ccUiUL_Lnel\nvariantHelpers:\n  - core#slice#keyby\nsimilarHelpers:\n  - core#slice#keybyerr\n  - core#slice#groupby\n  - core#slice#groupbyerr\n  - core#slice#partitionby\n  - core#map#associate\n  - core#slice#keyify\nposition: 230\nsignatures:\n  - \"func KeyBy[K comparable, V any](collection []V, iteratee func(item V) K) map[K]V\"\n---\n\nTransforms a slice to a map using a pivot callback to compute keys.\n\n```go\nm := lo.KeyBy(\n    []string{\"a\", \"aa\", \"aaa\"},\n    func(str string) int {\n        return len(str)\n    },\n)\n// map[int]string{1: \"a\", 2: \"aa\", 3: \"aaa\"}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-keybyerr.md",
    "content": "---\nname: KeyByErr\nslug: keybyerr\nsourceRef: slice.go#L576\ncategory: core\nsubCategory: slice\nsignatures:\n  - \"func KeyByErr[K comparable, V any](collection []V, iteratee func(item V) (K, error)) (map[K]V, error)\"\nvariantHelpers:\n  - core#slice#keybyerr\nsimilarHelpers:\n  - core#slice#keyby\n  - core#slice#groupby\n  - core#slice#groupbyerr\n  - core#slice#partitionby\n  - core#map#associate\n  - core#slice#keyify\nposition: 231\n---\n\nTransforms a slice to a map using a pivot callback to compute keys. Stops iteration immediately when an error is encountered.\n\n```go\n// Error case - stops on first error\nresult, err := lo.KeyByErr([]string{\"a\", \"aa\", \"aaa\", \"\"}, func(str string) (int, error) {\n    if str == \"\" {\n        return 0, fmt.Errorf(\"empty string not allowed\")\n    }\n    return len(str), nil\n})\n// map[int]string(nil), error(\"empty string not allowed\")\n```\n\n```go\n// Success case\nresult, err := lo.KeyByErr([]string{\"a\", \"aa\", \"aaa\"}, func(str string) (int, error) {\n    if str == \"\" {\n        return 0, fmt.Errorf(\"empty string not allowed\")\n    }\n    return len(str), nil\n})\n// map[int]string{1: \"a\", 2: \"aa\", 3: \"aaa\"}, nil\n```\n\n"
  },
  {
    "path": "docs/data/core-keyify.md",
    "content": "---\nname: Keyify\nslug: keyify\nsourceRef: slice.go#L429\ncategory: core\nsubCategory: slice\nplayUrl: https://go.dev/play/p/_d5lXdzfw32\nvariantHelpers:\n  - core#slice#keyify\nsimilarHelpers:\n  - core#slice#keyby\n  - core#slice#uniq\n  - core#slice#uniqby\n  - core#slice#groupby\nposition: 270\nsignatures:\n  - \"func Keyify[T comparable, Slice ~[]T](collection Slice) map[T]struct{}\"\n---\n\nReturns a set-like map where each unique element of the slice is a key.\n\n```go\nset := lo.Keyify([]int{1, 1, 2, 3, 4})\n// map[int]struct{}{1: {}, 2: {}, 3: {}, 4: {}}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-keys.md",
    "content": "---\nname: Keys\nslug: keys\nsourceRef: map.go#L5\ncategory: core\nsubCategory: map\nplayUrl: https://go.dev/play/p/Uu11fHASqrU\nvariantHelpers:\n  - core#map#keys\nsimilarHelpers:\n  - core#map#values\n  - core#map#uniqkeys\n  - core#map#entries\n  - core#map#topairs\n  - core#map#frompairs\n  - core#map#filterkeys\nposition: 0\nsignatures:\n  - \"func Keys[K comparable, V any](in ...map[K]V) []K\"\n---\n\nCreates a slice of the map keys.\n\nUse the UniqKeys variant to deduplicate common keys.\n\n```go\nkeys := lo.Keys(map[string]int{\"foo\": 1, \"bar\": 2})\n// []string{\"foo\", \"bar\"}\n\nkeys := lo.Keys(map[string]int{\"foo\": 1, \"bar\": 2}, map[string]int{\"baz\": 3})\n// []string{\"foo\", \"bar\", \"baz\"}\n\nkeys := lo.Keys(map[string]int{\"foo\": 1, \"bar\": 2}, map[string]int{\"bar\": 3})\n// []string{\"foo\", \"bar\", \"bar\"}\n```\n"
  },
  {
    "path": "docs/data/core-last.md",
    "content": "---\nname: Last\nslug: last\nsourceRef: find.go#L585\ncategory: core\nsubCategory: find\nplayUrl: https://go.dev/play/p/ul45Z0y2EFO\nvariantHelpers:\n  - core#find#last\nsimilarHelpers:\n  - core#find#first\n  - core#find#nth\n  - core#find#lastor\n  - core#find#lastorempty\nposition: 290\nsignatures:\n  - \"func Last[T any](collection []T) (T, bool)\"\n---\n\nReturns the last element of a collection and whether it exists.\n\n```go\nv, ok := lo.Last([]int{1, 2, 3})\n// v == 3, ok == true\n```\n\n\n"
  },
  {
    "path": "docs/data/core-lastindexof.md",
    "content": "---\nname: LastIndexOf\nslug: lastindexof\nsourceRef: find.go#L27\ncategory: core\nsubCategory: find\nplayUrl: https://go.dev/play/p/Eo7W0lvKTky\nvariantHelpers:\n  - core#find#lastindexof\nsimilarHelpers:\n  - core#find#indexof\n  - core#find#findkey\n  - core#find#findlastindexof\nposition: 10\nsignatures:\n  - \"func LastIndexOf[T comparable](collection []T, element T) int\"\n---\n\nReturns the index of the last occurrence of a value in a slice, or -1 if not found.\n\n```go\nidx := lo.LastIndexOf([]int{0, 1, 2, 1, 2, 3}, 2)\n// 4\n\nidx = lo.LastIndexOf([]int{0, 1, 2, 1, 2, 3}, 6)\n// -1\n```\n\n\n"
  },
  {
    "path": "docs/data/core-lastor.md",
    "content": "---\nname: LastOr\nslug: lastor\nsourceRef: find.go#L605\ncategory: core\nsubCategory: find\nplayUrl: https://go.dev/play/p/ul45Z0y2EFO\nvariantHelpers:\n  - core#find#lastor\nsimilarHelpers:\n  - core#find#firstor\n  - core#find#last\n  - core#find#lastorempty\n  - core#find#nthor\nposition: 310\nsignatures:\n  - \"func LastOr[T any](collection []T, fallback T) T\"\n---\n\nReturns the last element of a collection or the fallback value if empty.\n\n```go\nv := lo.LastOr([]int{}, -1)\n// v == -1\n```\n\n\n"
  },
  {
    "path": "docs/data/core-lastorempty.md",
    "content": "---\nname: LastOrEmpty\nslug: lastorempty\nsourceRef: find.go#L598\ncategory: core\nsubCategory: find\nplayUrl: https://go.dev/play/p/ul45Z0y2EFO\nvariantHelpers:\n  - core#find#lastorempty\nsimilarHelpers:\n  - core#find#firstorempty\n  - core#find#last\n  - core#find#lastor\n  - core#find#nthorempty\nposition: 300\nsignatures:\n  - \"func LastOrEmpty[T any](collection []T) T\"\n---\n\nReturns the last element of a collection or the zero value if empty.\n\n```go\nv := lo.LastOrEmpty([]int{})\n// v == 0\n```\n\n\n"
  },
  {
    "path": "docs/data/core-latest.md",
    "content": "---\nname: Latest\nslug: latest\nsourceRef: find.go#L508\ncategory: core\nsubCategory: find\nplayUrl: https://go.dev/play/p/dBfdf5s8s-Y\nvariantHelpers:\n  - core#find#latest\nsimilarHelpers:\n  - core#find#earliest\n  - core#find#latestby\n  - core#find#earliestby\n  - core#find#min\n  - core#find#max\n  - core#find#minby\n  - core#find#maxby\n  - core#find#minindex\n  - core#find#maxindex\n  - core#find#minindexby\n  - core#find#maxindexby\nposition: 240\nsignatures:\n  - \"func Latest(times ...time.Time) time.Time\"\n---\n\nSearches the maximum time.Time in the provided arguments. Returns zero value when the input is empty.\n\n```go\nt1 := time.Date(2023, 1, 1, 0, 0, 0, 0, time.UTC)\nt2 := time.Date(2024, 1, 1, 0, 0, 0, 0, time.UTC)\nmax := lo.Latest(t1, t2)\n// 2024-01-01 00:00:00 +0000 UTC\n```\n\n\n"
  },
  {
    "path": "docs/data/core-latestby.md",
    "content": "---\nname: LatestBy\nslug: latestby\nsourceRef: find.go#L530\ncategory: core\nsubCategory: find\nplayUrl: https://go.dev/play/p/p1HA8XumaMU\nvariantHelpers:\n  - core#find#latestby\nsimilarHelpers:\n  - core#find#latestbyerr\n  - core#find#latest\n  - core#find#earliestby\n  - core#find#earliestbyerr\n  - core#find#earliest\n  - core#find#maxby\n  - core#find#minby\n  - core#find#maxindexby\n  - core#find#minindexby\n  - core#find#findby\n  - core#find#findkeyby\n  - core#find#findduplicatesby\n  - core#find#finduniquesby\nposition: 250\nsignatures:\n  - \"func LatestBy[T any](collection []T, iteratee func(item T) time.Time) T\"\n---\n\nSearches a collection for the element with the maximum time extracted by the predicate. Returns zero value when the collection is empty.\n\n```go\ntype Event struct{ At time.Time }\nevents := []Event{{At: time.Now()}, {At: time.Now().Add(2 * time.Hour)}}\nlast := lo.LatestBy(events, func(e Event) time.Time {\n    return e.At\n})\n```\n\n\n"
  },
  {
    "path": "docs/data/core-latestbyerr.md",
    "content": "---\nname: LatestByErr\nslug: latestbyerr\nsourceRef: find.go#L737\ncategory: core\nsubCategory: find\nplayUrl: https://go.dev/play/p/WpBUptwnxuG\nsignatures:\n  - \"func LatestByErr[T any](collection []T, iteratee func(item T) (time.Time, error)) (T, error)\"\nvariantHelpers:\n  - core#find#latestbyerr\nsimilarHelpers:\n  - core#find#latestby\n  - core#find#latest\n  - core#find#earliestby\n  - core#find#earliestbyerr\n  - core#find#earliest\n  - core#find#maxby\n  - core#find#minby\n  - core#find#maxindexby\n  - core#find#minindexby\n  - core#find#findby\n  - core#find#findkeyby\n  - core#find#findduplicatesby\n  - core#find#finduniquesby\nposition: 251\n---\n\nSearches a collection for the element with the maximum time extracted by the predicate. Returns zero value when the collection is empty. Stops iteration immediately when an error is encountered.\n\n```go\ntype Event struct{ At time.Time }\nevents := []Event{{At: time.Now()}, {At: time.Now().Add(2 * time.Hour)}}\nlast, err := lo.LatestByErr(events, func(e Event) (time.Time, error) {\n    return e.At, nil\n})\n// Event{At: ...}, nil\n```\n\n```go\n// Error case - stops on first error\ntype Event struct{ At time.Time }\nevents := []Event{{At: time.Now()}, {At: time.Time{}}, {At: time.Now().Add(2 * time.Hour)}}\n_, err := lo.LatestByErr(events, func(e Event) (time.Time, error) {\n    if e.At.IsZero() {\n        return time.Time{}, fmt.Errorf(\"zero time not allowed\")\n    }\n    return e.At, nil\n})\n// error(\"zero time not allowed\")\n```\n\n"
  },
  {
    "path": "docs/data/core-map.md",
    "content": "---\nname: Map\nslug: map\nsourceRef: slice.go#L26\ncategory: core\nsubCategory: slice\nplayUrl: https://go.dev/play/p/OkPcYAhBo0D\nsimilarHelpers:\n  - core#slice#maperr\n  - core#slice#filtermap\n  - core#slice#flatmap\n  - core#slice#uniqmap\n  - core#slice#rejectmap\n  - core#slice#mapkeys\n  - core#slice#mapvalues\n  - core#slice#mapentries\n  - core#slice#maptoslice\n  - core#slice#filtermaptoslice\n  - parallel#slice#map\n  - mutable#slice#map\nvariantHelpers:\n  - core#slice#map\nposition: 10\nsignatures:\n  - \"func Map[T any, R any](collection []T, transform func(item T, index int) R) []R\"\n---\n\nTransforms each element in a slice to a new type using a function. Takes both the element and its index, making it useful for transformations that need positional context.\n\n```go\n// Basic type transformation\ntransformed := lo.Map([]int64{1, 2, 3, 4}, func(x int64, index int) string {\n    return strconv.FormatInt(x, 10)\n})\n// transformed: []string{\"1\", \"2\", \"3\", \"4\"}\n```\n\n```go\n// Transforming structs\ntype Person struct {\n    FirstName string\n    LastName  string\n    Age       int\n}\n\npeople := []Person{\n    {FirstName: \"John\", LastName: \"Doe\", Age: 25},\n    {FirstName: \"Jane\", LastName: \"Smith\", Age: 30},\n}\n\nfullNames := lo.Map(people, func(p Person, index int) string {\n    return fmt.Sprintf(\"%s %s\", p.FirstName, p.LastName)\n})\n// fullNames: []string{\"John Doe\", \"Jane Smith\"}\n```\n"
  },
  {
    "path": "docs/data/core-mapentries.md",
    "content": "---\nname: MapEntries\nslug: mapentries\nsourceRef: map.go#L336\ncategory: core\nsubCategory: map\nplayUrl: https://go.dev/play/p/VuvNQzxKimT\nvariantHelpers:\n  - core#map#mapentries\nsimilarHelpers:\n  - core#map#mapkeys\n  - core#map#mapvalues\n  - core#map#maptoslice\n  - core#slice#map\n  - core#map#mapentrieserr\nposition: 200\nsignatures:\n  - \"func MapEntries[K1 comparable, V1 any, K2 comparable, V2 any](in map[K1]V1, iteratee func(key K1, value V1) (K2, V2)) map[K2]V2\"\n---\n\nTransforms both keys and values using an predicate function.\n\n```go\nin := map[string]int{\"foo\":1, \"bar\":2}\nout := lo.MapEntries(in, func(k string, v int) (int, string) {\n    return v, k\n})\n// map[int]string{1:\"foo\", 2:\"bar\"}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-mapentrieserr.md",
    "content": "---\nname: MapEntriesErr\nslug: mapentrieserr\nsourceRef: map.go#L351\ncategory: core\nsubCategory: map\nsignatures:\n  - \"func MapEntriesErr[K1 comparable, V1 any, K2 comparable, V2 any](in map[K1]V1, iteratee func(key K1, value V1) (K2, V2, error)) (map[K2]V2, error)\"\nvariantHelpers:\n  - core#map#mapentrieserr\nsimilarHelpers:\n  - core#map#mapentries\n  - core#map#mapkeyserr\n  - core#map#mapvalueserr\nposition: 205\n---\n\nTransforms both keys and values using an predicate function. Returns an error if the iteratee function fails, stopping iteration immediately.\n\n```go\nin := map[string]int{\"foo\": 1, \"bar\": 2, \"baz\": 3}\nout, err := lo.MapEntriesErr(in, func(k string, v int) (int, string, error) {\n    if k == \"bar\" {\n        return 0, \"\", fmt.Errorf(\"bar not allowed\")\n    }\n    return v, k, nil\n})\n// map[int]string(nil), error(\"bar not allowed\")\n```\n\n```go\nin := map[string]int{\"foo\": 1, \"bar\": 2}\nout, err := lo.MapEntriesErr(in, func(k string, v int) (int, string, error) {\n    return v, k, nil\n})\n// map[int]string{1:\"foo\", 2:\"bar\"}, nil\n```\n"
  },
  {
    "path": "docs/data/core-maperr.md",
    "content": "---\nname: MapErr\nslug: maperr\nsourceRef: slice.go#L36\ncategory: core\nsubCategory: slice\nsignatures:\n  - \"func MapErr[T any, R any](collection []T, transform func(item T, index int) (R, error)) ([]R, error)\"\nvariantHelpers:\n  - core#slice#maperr\nsimilarHelpers:\n  - core#slice#map\n  - core#slice#filtermap\n  - core#slice#flatmap\n  - core#slice#rejectmap\n  - parallel#slice#map\nposition: 11\n---\n\nTransforms each element in a slice to a new type using a function that can return an error. Stops iteration immediately when an error is encountered.\n\n```go\n// Error case - stops on first error\nresult, err := lo.MapErr([]int{1, 2, 3, 4}, func(x int, _ int) (string, error) {\n    if x == 3 {\n        return \"\", fmt.Errorf(\"number 3 is not allowed\")\n    }\n    return strconv.Itoa(x), nil\n})\n// []string(nil), error(\"number 3 is not allowed\")\n```\n\n```go\n// Success case\nresult, err := lo.MapErr([]int{1, 2, 3, 4}, func(x int, _ int) (string, error) {\n    return strconv.Itoa(x), nil\n})\n// []string{\"1\", \"2\", \"3\", \"4\"}, nil\n```\n"
  },
  {
    "path": "docs/data/core-mapkeys.md",
    "content": "---\nname: MapKeys\nslug: mapkeys\nsourceRef: map.go#L283\ncategory: core\nsubCategory: map\nplayUrl: https://go.dev/play/p/9_4WPIqOetJ\nvariantHelpers:\n  - core#map#mapkeys\nsimilarHelpers:\n  - core#map#mapvalues\n  - core#map#mapentries\n  - core#map#keyby\n  - core#slice#map\n  - core#map#mapkeyserr\nposition: 180\nsignatures:\n  - \"func MapKeys[K comparable, V any, R comparable](in map[K]V, iteratee func(value V, key K) R) map[R]V\"\n---\n\nTransforms map keys using a predicate while keeping values.\n\n```go\nin := map[int]int{1:1, 2:2}\nout := lo.MapKeys(in, func(v int, _ int) string {\n    return strconv.Itoa(v)\n})\n// map[string]int{\"1\":1, \"2\":2}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-mapkeyserr.md",
    "content": "---\nname: MapKeysErr\nslug: mapkeyserr\nsourceRef: map.go#L293\ncategory: core\nsubCategory: map\nsignatures:\n  - \"func MapKeysErr[K comparable, V any, R comparable](in map[K]V, iteratee func(value V, key K) (R, error)) (map[R]V, error)\"\nvariantHelpers:\n  - core#map#mapkeyserr\nsimilarHelpers:\n  - core#map#mapkeys\n  - core#map#mapvalueserr\nposition: 185\n---\n\nTransforms map keys using a predicate while keeping values. Returns an error if the iteratee function fails, stopping iteration immediately.\n\n```go\nin := map[int]int{1: 1, 2: 2, 3: 3}\nout, err := lo.MapKeysErr(in, func(v int, _ int) (string, error) {\n    if v == 2 {\n        return \"\", fmt.Errorf(\"even number not allowed\")\n    }\n    return strconv.Itoa(v), nil\n})\n// map[string]int(nil), error(\"even number not allowed\")\n```\n\n```go\nin := map[int]int{1: 1, 2: 2, 3: 3}\nout, err := lo.MapKeysErr(in, func(v int, _ int) (string, error) {\n    return strconv.Itoa(v), nil\n})\n// map[string]int{\"1\":1, \"2\":2, \"3\":3}, nil\n```\n"
  },
  {
    "path": "docs/data/core-maptoslice.md",
    "content": "---\nname: MapToSlice\nslug: maptoslice\nsourceRef: map.go#L367\ncategory: core\nsubCategory: map\nplayUrl: https://go.dev/play/p/4f5hbHyMf5h\nvariantHelpers:\n  - core#map#maptoslice\nsimilarHelpers:\n  - core#map#mapentries\n  - core#map#entries\n  - core#slice#map\n  - core#slice#mapentries\n  - core#map#maptosliceerr\nposition: 210\nsignatures:\n  - \"func MapToSlice[K comparable, V any, R any](in map[K]V, iteratee func(key K, value V) R) []R\"\n---\n\nTransforms a map into a slice by applying an predicate to each key/value pair.\n\n```go\nm := map[int]int64{1:4, 2:5, 3:6}\ns := lo.MapToSlice(m, func(k int, v int64) string {\n    return fmt.Sprintf(\"%d_%d\", k, v)\n})\n// []string{\"1_4\", \"2_5\", \"3_6\"}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-maptosliceerr.md",
    "content": "---\nname: MapToSliceErr\nslug: maptosliceerr\nsourceRef: map.go#L379\ncategory: core\nsubCategory: map\nsignatures:\n  - \"func MapToSliceErr[K comparable, V any, R any](in map[K]V, iteratee func(key K, value V) (R, error)) ([]R, error)\"\nvariantHelpers:\n  - core#map#maptosliceerr\nsimilarHelpers:\n  - core#map#maptoslice\n  - core#map#mapentrieserr\n  - core#slice#maperr\nposition: 215\n---\n\nTransforms a map into a slice by applying an predicate to each key/value pair. Returns an error if the iteratee function fails, stopping iteration immediately.\n\n```go\nm := map[int]int64{1: 4, 2: 5, 3: 6}\ns, err := lo.MapToSliceErr(m, func(k int, v int64) (string, error) {\n    if k == 2 {\n        return \"\", fmt.Errorf(\"key 2 not allowed\")\n    }\n    return fmt.Sprintf(\"%d_%d\", k, v), nil\n})\n// []string(nil), error(\"key 2 not allowed\")\n```\n\n```go\nm := map[int]int64{1:4, 2:5, 3:6}\ns, err := lo.MapToSliceErr(m, func(k int, v int64) (string, error) {\n    return fmt.Sprintf(\"%d_%d\", k, v), nil\n})\n// []string{\"1_4\", \"2_5\", \"3_6\"}, nil\n```\n"
  },
  {
    "path": "docs/data/core-mapvalues.md",
    "content": "---\nname: MapValues\nslug: mapvalues\nsourceRef: map.go#L310\ncategory: core\nsubCategory: map\nplayUrl: https://go.dev/play/p/T_8xAfvcf0W\nvariantHelpers:\n  - core#map#mapvalues\nsimilarHelpers:\n  - core#map#mapkeys\n  - core#map#mapentries\n  - core#map#groupby\n  - core#slice#map\n  - core#map#mapvalueserr\nposition: 190\nsignatures:\n  - \"func MapValues[K comparable, V any, R any](in map[K]V, iteratee func(value V, key K) R) map[K]R\"\n---\n\nTransforms map values using a predicate while keeping keys.\n\n```go\nin := map[int]int64{1:1, 2:2}\nout := lo.MapValues(in, func(v int64, _ int) string {\n    return strconv.FormatInt(v, 10)\n})\n// map[int]string{1:\"1\", 2:\"2\"}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-mapvalueserr.md",
    "content": "---\nname: MapValuesErr\nslug: mapvalueserr\nsourceRef: map.go#L322\ncategory: core\nsubCategory: map\nsignatures:\n  - \"func MapValuesErr[K comparable, V any, R any](in map[K]V, iteratee func(value V, key K) (R, error)) (map[K]R, error)\"\nvariantHelpers:\n  - core#map#mapvalueserr\nsimilarHelpers:\n  - core#map#mapvalues\n  - core#map#mapkeyserr\n  - core#map#mapentrieserr\nposition: 195\n---\n\nTransforms map values using a predicate while keeping keys. Returns an error if the iteratee function fails, stopping iteration immediately.\n\n```go\nin := map[int]int64{1: 1, 2: 2, 3: 3}\nout, err := lo.MapValuesErr(in, func(v int64, _ int) (string, error) {\n    if v == 2 {\n        return \"\", fmt.Errorf(\"even number not allowed\")\n    }\n    return strconv.FormatInt(v, 10), nil\n})\n// map[int]string(nil), error(\"even number not allowed\")\n```\n\n```go\nin := map[int]int64{1: 1, 2: 2, 3: 3}\nout, err := lo.MapValuesErr(in, func(v int64, _ int) (string, error) {\n    return strconv.FormatInt(v, 10), nil\n})\n// map[int]string{1:\"1\", 2:\"2\", 3:\"3\"}, nil\n```\n"
  },
  {
    "path": "docs/data/core-max.md",
    "content": "---\nname: Max\nslug: max\nsourceRef: find.go#L410\ncategory: core\nsubCategory: find\nplayUrl: https://go.dev/play/p/wYvG8gRRFw-\nvariantHelpers:\n  - core#find#max\nsimilarHelpers:\n  - core#find#min\n  - core#find#maxby\n  - core#find#minby\n  - core#find#maxindex\n  - core#find#minindex\n  - core#find#maxindexby\n  - core#find#minindexby\n  - core#math#sum\n  - core#math#mean\n  - core#math#product\n  - core#math#mode\nposition: 200\nsignatures:\n  - \"func Max[T constraints.Ordered](collection []T) T\"\n---\n\nSearches the maximum value of a collection. Returns zero value when the collection is empty.\n\n```go\nmax := lo.Max([]int{2, 5, 3})\n// 5\n```\n\n\n"
  },
  {
    "path": "docs/data/core-maxby.md",
    "content": "---\nname: MaxBy\nslug: maxby\nsourceRef: find.go#L507\ncategory: core\nsubCategory: find\nplayUrl: https://go.dev/play/p/PJCc-ThrwX1\nvariantHelpers:\n  - core#find#maxby\nsimilarHelpers:\n  - core#find#max\n  - core#find#maxbyerr\n  - core#find#maxindex\n  - core#find#maxindexby\n  - core#find#min\n  - core#find#minby\n  - core#find#minindex\n  - core#find#minindexby\n  - core#math#sum\n  - core#math#mean\n  - core#math#product\n  - core#math#mode\nposition: 220\nsignatures:\n  - \"func MaxBy[T any](collection []T, comparison func(a T, b T) bool) T\"\n---\n\nSearches the maximum value of a collection using the given comparison function. Returns zero value when the collection is empty.\n\n```go\ntype Point struct{ X int }\nmax := lo.MaxBy([]Point{{1}, {5}, {3}}, func(a, b Point) bool {\n    return a.X > b.X\n})\n// {5}\n```\n\nNote: the comparison function is inconsistent with most languages, since we use the opposite of the usual convention.\n\nSee https://github.com/samber/lo/issues/129\n"
  },
  {
    "path": "docs/data/core-maxbyerr.md",
    "content": "---\nname: MaxByErr\nslug: maxbyerr\nsourceRef: find.go#L528\ncategory: core\nsubCategory: find\nplayUrl: https://go.dev/play/p/s-63-6_9zqM\nvariantHelpers:\n  - core#find#maxbyerr\nsimilarHelpers:\n  - core#find#maxby\n  - core#find#max\n  - core#find#maxindex\n  - core#find#maxindexby\n  - core#find#min\n  - core#find#minby\n  - core#find#minindex\n  - core#find#minindexby\nposition: 221\nsignatures:\n  - \"func MaxByErr[T any](collection []T, comparison func(a T, b T) (bool, error)) (T, error)\"\n---\n\nSearches the maximum value of a collection using the given comparison function. Returns zero value and nil error when empty.\n\nIf the comparison function returns an error, iteration stops and the error is returned.\n\n```go\ntype Point struct{ X int }\nmax, err := lo.MaxByErr([]Point{{1}, {5}, {3}}, func(a, b Point) (bool, error) {\n    return a.X > b.X, nil\n})\n// {5}, <nil>\n```\n\nExample with error:\n\n```go\ntype Point struct{ X int }\nmax, err := lo.MaxByErr([]Point{{1}, {5}, {3}}, func(a, b Point) (bool, error) {\n    if a.X == 5 {\n        return false, fmt.Errorf(\"cannot compare with 5\")\n    }\n    return a.X > b.X, nil\n})\n// {1}, error(\"cannot compare with 5\")\n```\n\nNote: the comparison function is inconsistent with most languages, since we use the opposite of the usual convention.\n\nSee https://github.com/samber/lo/issues/129\n"
  },
  {
    "path": "docs/data/core-maxindex.md",
    "content": "---\nname: MaxIndex\nslug: maxindex\nsourceRef: find.go#L432\ncategory: core\nsubCategory: find\nplayUrl: https://go.dev/play/p/RFkB4Mzb1qt\nvariantHelpers:\n  - core#find#maxindex\nsimilarHelpers:\n  - core#find#max\n  - core#find#maxby\n  - core#find#maxindexby\n  - core#find#min\n  - core#find#minby\n  - core#find#minindex\n  - core#find#minindexby\n  - core#math#sum\n  - core#math#mean\n  - core#math#product\n  - core#math#mode\nposition: 210\nsignatures:\n  - \"func MaxIndex[T constraints.Ordered](collection []T) (T, int)\"\n---\n\nReturns the maximum value and its index. Returns (zero value, -1) when the collection is empty.\n\n```go\nvalue, idx := lo.MaxIndex([]int{2, 5, 3})\n// value == 5, idx == 1\n```\n\n\n"
  },
  {
    "path": "docs/data/core-maxindexby.md",
    "content": "---\nname: MaxIndexBy\nslug: maxindexby\nsourceRef: find.go#L566\ncategory: core\nsubCategory: find\nplayUrl: https://go.dev/play/p/5yd4W7pe2QJ\nvariantHelpers:\n  - core#find#maxindexby\nsimilarHelpers:\n  - core#find#max\n  - core#find#maxby\n  - core#find#maxbyerr\n  - core#find#maxindex\n  - core#find#maxindexbyerr\n  - core#find#min\n  - core#find#minby\n  - core#find#minindex\n  - core#find#minindexby\n  - core#math#sum\n  - core#math#mean\n  - core#math#product\n  - core#math#mode\nposition: 230\nsignatures:\n  - \"func MaxIndexBy[T any](collection []T, comparison func(a T, b T) bool) (T, int)\"\n---\n\nReturns the maximum value and its index using the given comparison function. Returns (zero value, -1) when the collection is empty.\n\n```go\ntype Point struct{ X int }\nvalue, idx := lo.MaxIndexBy([]Point{{1}, {5}, {3}}, func(a, b Point) bool {\n    return a.X > b.X\n})\n// value == {5}, idx == 1\n```\n\nNote: the comparison function is inconsistent with most languages, since we use the opposite of the usual convention.\n\nSee https://github.com/samber/lo/issues/129\n"
  },
  {
    "path": "docs/data/core-maxindexbyerr.md",
    "content": "---\nname: MaxIndexByErr\nslug: maxindexbyerr\nsourceRef: find.go#L591\ncategory: core\nsubCategory: find\nvariantHelpers:\n  - core#find#maxindexbyerr\nsimilarHelpers:\n  - core#find#maxindexby\n  - core#find#max\n  - core#find#maxby\n  - core#find#maxindex\n  - core#find#min\n  - core#find#minby\n  - core#find#minindex\n  - core#find#minindexby\nposition: 231\nsignatures:\n  - \"func MaxIndexByErr[T any](collection []T, comparison func(a T, b T) (bool, error)) (T, int, error)\"\n---\n\nReturns the maximum value and its index using the given comparison function. Returns (zero value, -1, nil) when empty.\n\nIf the comparison function returns an error, iteration stops and the error is returned.\n\n```go\ntype Point struct{ X int }\nvalue, idx, err := lo.MaxIndexByErr([]Point{{1}, {5}, {3}}, func(a, b Point) (bool, error) {\n    return a.X > b.X, nil\n})\n// value == {5}, idx == 1, err == nil\n```\n\nExample with error:\n\n```go\ntype Point struct{ X int }\nvalue, idx, err := lo.MaxIndexByErr([]Point{{1}, {5}, {3}}, func(a, b Point) (bool, error) {\n    if a.X == 5 {\n        return false, fmt.Errorf(\"cannot compare with 5\")\n    }\n    return a.X > b.X, nil\n})\n// value == {1}, idx == 0, error(\"cannot compare with 5\")\n```\n\nNote: the comparison function is inconsistent with most languages, since we use the opposite of the usual convention.\n\nSee https://github.com/samber/lo/issues/129\n"
  },
  {
    "path": "docs/data/core-mean.md",
    "content": "---\nname: Mean\nslug: mean\nsourceRef: math.go#L126\ncategory: core\nsubCategory: math\nplayUrl: https://go.dev/play/p/tPURSuteUsP\nvariantHelpers:\n  - core#math#mean\nsimilarHelpers:\n  - core#math#meanby\n  - core#math#mode\n  - core#math#sum\n  - core#math#sumby\n  - core#math#product\n  - core#math#productby\n  - core#find#min\n  - core#find#max\n  - core#find#minby\n  - core#find#maxby\nposition: 80\nsignatures:\n  - \"func Mean[T constraints.Float | constraints.Integer](collection []T) T\"\n---\n\nCalculates the arithmetic mean of a collection of numbers. Returns 0 for an empty collection.\n\n```go\nlo.Mean([]int{2, 3, 4, 5})\n// 3\n```\n\n\n"
  },
  {
    "path": "docs/data/core-meanby.md",
    "content": "---\nname: MeanBy\nslug: meanby\nsourceRef: math.go#L161\ncategory: core\nsubCategory: math\nplayUrl: https://go.dev/play/p/j7TsVwBOZ7P\nvariantHelpers:\n  - core#math#meanby\nsimilarHelpers:\n  - core#math#mean\n  - core#math#meanbyerr\n  - core#math#mode\n  - core#math#sum\n  - core#math#sumby\n  - core#math#product\n  - core#math#productby\n  - core#find#min\n  - core#find#max\n  - core#find#minby\n  - core#find#maxby\nposition: 90\nsignatures:\n  - \"func MeanBy[T any, R constraints.Float | constraints.Integer](collection []T, iteratee func(item T) R) R\"\n---\n\nCalculates the mean of values computed by a predicate. Returns 0 for an empty collection.\n\n```go\nlist := []string{\"aa\", \"bbb\", \"cccc\", \"ddddd\"}\nlo.MeanBy(list, func(item string) float64 {\n    return float64(len(item))\n})\n// 3.5\n```\n\n\n"
  },
  {
    "path": "docs/data/core-meanbyerr.md",
    "content": "---\nname: MeanByErr\nslug: meanbyerr\nsourceRef: math.go#L172\ncategory: core\nsubCategory: math\nvariantHelpers:\n  - core#math#meanbyerr\nsimilarHelpers:\n  - core#math#meanby\n  - core#math#mean\n  - core#math#mode\n  - core#math#sum\n  - core#math#sumbyerr\n  - core#math#product\n  - core#math#productby\n  - core#find#min\n  - core#find#max\n  - core#find#minby\n  - core#find#maxby\nposition: 91\nsignatures:\n  - \"func MeanByErr[T any, R constraints.Float | constraints.Integer](collection []T, iteratee func(item T) (R, error)) (R, error)\"\n---\n\nCalculates the mean of values computed by a predicate. Returns 0 for an empty collection.\n\nIf the iteratee returns an error, iteration stops and the error is returned.\n\n```go\nlist := []string{\"aa\", \"bbb\", \"cccc\", \"ddddd\"}\nresult, err := lo.MeanByErr(list, func(item string) (float64, error) {\n    return float64(len(item)), nil\n})\n// 3.5, <nil>\n```\n\nExample with error:\n\n```go\nlist := []string{\"aa\", \"bbb\", \"cccc\", \"ddddd\"}\nresult, err := lo.MeanByErr(list, func(item string) (float64, error) {\n    if item == \"cccc\" {\n        return 0, fmt.Errorf(\"cccc is not allowed\")\n    }\n    return float64(len(item)), nil\n})\n// 0, error(\"cccc is not allowed\")\n```\n"
  },
  {
    "path": "docs/data/core-min.md",
    "content": "---\nname: Min\nslug: min\nsourceRef: find.go#L265\ncategory: core\nsubCategory: find\nplayUrl: https://go.dev/play/p/fJFLwpY8eMN\nvariantHelpers:\n  - core#find#min\nsimilarHelpers:\n  - core#find#minby\n  - core#find#minindex\n  - core#find#minindexby\n  - core#find#max\n  - core#find#maxby\n  - core#find#maxindex\n  - core#find#maxindexby\nposition: 140\nsignatures:\n  - \"func Min[T constraints.Ordered](collection []T) T\"\n---\n\nReturns the minimum value of a collection. Returns the zero value when the collection is empty.\n\n```go\nlo.Min([]int{1, 2, 3})\n// 1\n```\n\n\n"
  },
  {
    "path": "docs/data/core-minby.md",
    "content": "---\nname: MinBy\nslug: minby\nsourceRef: find.go#L329\ncategory: core\nsubCategory: find\nplayUrl: https://go.dev/play/p/-B1PsrHVnfx\nvariantHelpers:\n  - core#find#minby\nsimilarHelpers:\n  - core#find#min\n  - core#find#minbyerr\n  - core#find#minindex\n  - core#find#minindexby\n  - core#find#max\n  - core#find#maxby\n  - core#find#maxindex\n  - core#find#maxindexby\n  - core#math#sum\n  - core#math#mean\n  - core#math#product\n  - core#math#mode\nposition: 160\nsignatures:\n  - \"func MinBy[T any](collection []T, comparison func(a T, b T) bool) T\"\n---\n\nSearches the minimum value of a collection using the given comparison function. Returns the first minimal value; zero value when empty.\n\n```go\ntype Point struct{ X int }\nmin := lo.MinBy([]Point{{1}, {5}, {3}}, func(a, b Point) bool {\n    return a.X < b.X\n})\n// {1}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-minbyerr.md",
    "content": "---\nname: MinByErr\nslug: minbyerr\nsourceRef: find.go#L349\ncategory: core\nsubCategory: find\nplayUrl: https://go.dev/play/p/nvDYGS8q895\nvariantHelpers:\n  - core#find#minbyerr\nsimilarHelpers:\n  - core#find#minby\n  - core#find#min\n  - core#find#minindex\n  - core#find#minindexby\n  - core#find#max\n  - core#find#maxby\n  - core#find#maxindex\n  - core#find#maxindexby\nposition: 161\nsignatures:\n  - \"func MinByErr[T any](collection []T, comparison func(a T, b T) (bool, error)) (T, error)\"\n---\n\nSearches the minimum value of a collection using the given comparison function. Returns the first minimal value; zero value and nil error when empty.\n\nIf the comparison function returns an error, iteration stops and the error is returned.\n\n```go\ntype Point struct{ X int }\nmin, err := lo.MinByErr([]Point{{1}, {5}, {3}}, func(a, b Point) (bool, error) {\n    return a.X < b.X, nil\n})\n// {1}, <nil>\n```\n\nExample with error:\n\n```go\ntype Point struct{ X int }\nmin, err := lo.MinByErr([]Point{{1}, {5}, {3}}, func(a, b Point) (bool, error) {\n    if a.X == 5 {\n        return false, fmt.Errorf(\"cannot compare with 5\")\n    }\n    return a.X < b.X, nil\n})\n// {0}, error(\"cannot compare with 5\")\n```\n"
  },
  {
    "path": "docs/data/core-minindex.md",
    "content": "---\nname: MinIndex\nslug: minindex\nsourceRef: find.go#L287\ncategory: core\nsubCategory: find\nplayUrl: https://go.dev/play/p/RxAidik4p50\nvariantHelpers:\n  - core#find#minindex\nsimilarHelpers:\n  - core#find#min\n  - core#find#minby\n  - core#find#minindexby\n  - core#find#max\n  - core#find#maxby\n  - core#find#maxindex\n  - core#find#maxindexby\n  - core#math#sum\n  - core#math#mean\n  - core#math#product\n  - core#math#mode\nposition: 150\nsignatures:\n  - \"func MinIndex[T constraints.Ordered](collection []T) (T, int)\"\n---\n\nReturns the minimum value and its index. Returns (zero value, -1) when the collection is empty.\n\n```go\nvalue, idx := lo.MinIndex([]int{2, 5, 3})\n// value == 2, idx == 0\n```\n\n\n"
  },
  {
    "path": "docs/data/core-minindexby.md",
    "content": "---\nname: MinIndexBy\nslug: minindexby\nsourceRef: find.go#L337\ncategory: core\nsubCategory: find\nplayUrl: https://go.dev/play/p/zwwPRqWhnUY\nvariantHelpers:\n  - core#find#minindexby\nsimilarHelpers:\n  - core#find#minindexbyerr\n  - core#find#min\n  - core#find#minby\n  - core#find#minindex\n  - core#find#max\n  - core#find#maxby\n  - core#find#maxindex\n  - core#find#maxindexby\n  - core#math#sum\n  - core#math#mean\n  - core#math#product\n  - core#math#mode\nposition: 170\nsignatures:\n  - \"func MinIndexBy[T any](collection []T, comparison func(a T, b T) bool) (T, int)\"\n---\n\nSearches the minimum value using a comparison function and returns the value and its index. Returns (zero value, -1) when empty.\n\n```go\ntype Point struct{ X int }\nvalue, idx := lo.MinIndexBy([]Point{{1}, {5}, {3}}, func(a, b Point) bool {\n    return a.X < b.X\n})\n// value == {1}, idx == 0\n```\n\n\n"
  },
  {
    "path": "docs/data/core-minindexbyerr.md",
    "content": "---\nname: MinIndexByErr\nslug: minindexbyerr\nsourceRef: find.go#L404\ncategory: core\nsubCategory: find\nplayUrl: https://go.dev/play/p/MUqi_NvTKM1\nsignatures:\n  - \"func MinIndexByErr[T any](collection []T, comparison func(a T, b T) (bool, error)) (T, int, error)\"\nvariantHelpers:\n  - core#find#minindexbyerr\nsimilarHelpers:\n  - core#find#minindexby\n  - core#find#min\n  - core#find#minby\n  - core#find#minbyerr\n  - core#find#minindex\n  - core#find#max\n  - core#find#maxby\n  - core#find#maxbyerr\n  - core#find#maxindex\n  - core#find#maxindexby\n  - core#find#maxindexbyerr\n  - core#math#sum\n  - core#math#sumbyerr\n  - core#math#mean\n  - core#math#meanbyerr\n  - core#math#product\n  - core#math#productbyerr\n  - core#math#mode\nposition: 171\n---\n\nSearches the minimum value using a comparison function and returns the value and its index. Returns (zero value, -1, nil) when empty. Stops iteration immediately when an error is encountered.\n\n```go\ntype Point struct{ X int }\nvalue, idx, err := lo.MinIndexByErr([]Point{{1}, {5}, {3}}, func(a, b Point) (bool, error) {\n    return a.X < b.X, nil\n})\n// value == {1}, idx == 0, err == nil\n```\n\n```go\n// Error case - stops on first error\n_, _, err := lo.MinIndexByErr([]Point{{1}, {5}, {0}}, func(a, b Point) (bool, error) {\n    if a.X == 0 || b.X == 0 {\n        return false, fmt.Errorf(\"zero value not allowed\")\n    }\n    return a.X < b.X, nil\n})\n// error(\"zero value not allowed\")\n```\n\n```go\n// Error case on first comparison\n_, _, err := lo.MinIndexByErr([]Point{{1}, {5}}, func(a, b Point) (bool, error) {\n    return false, fmt.Errorf(\"comparison error\")\n})\n// error(\"comparison error\")\n```\n\n"
  },
  {
    "path": "docs/data/core-mode.md",
    "content": "---\nname: Mode\nslug: mode\nsourceRef: math.go#L149\ncategory: core\nsubCategory: math\nplayUrl: https://go.dev/play/p/PbiviqnV5zX\nvariantHelpers:\n  - core#math#mode\nsimilarHelpers:\n  - core#math#mean\n  - core#math#meanby\n  - core#math#sum\n  - core#math#sumby\n  - core#math#product\n  - core#math#productby\n  - core#find#min\n  - core#find#max\n  - core#find#minby\n  - core#find#maxby\n  - core#math#countvalues\n  - core#math#countvaluesby\nposition: 100\nsignatures:\n  - \"func Mode[T constraints.Integer | constraints.Float](collection []T) []T\"\n---\n\nReturns the mode(s), i.e., the most frequent value(s) in a collection. If multiple values share the highest frequency, returns all. Empty input yields an empty slice.\n\n```go\nlo.Mode([]int{2, 2, 3, 3})\n// []int{2, 3}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-mustx.md",
    "content": "---\nname: MustX\nslug: mustx\nsourceRef: errors.go#L65\ncategory: core\nsubCategory: error-handling\nsignatures:\n  - \"func Must[T any](val T, err any, messageArgs ...any) T\"\n  - \"func Must0(err any, messageArgs ...any)\"\n  - \"func Must1[T any](val T, err any, messageArgs ...any) T\"\n  - \"func Must2[T1, T2 any](val1 T1, val2 T2, err any, messageArgs ...any) (T1, T2)\"\n  - \"func Must3[T1, T2, T3 any](val1 T1, val2 T2, val3 T3, err any, messageArgs ...any) (T1, T2, T3)\"\n  - \"func Must4[T1, T2, T3, T4 any](val1 T1, val2 T2, val3 T3, val4 T4, err any, messageArgs ...any) (T1, T2, T3, T4)\"\n  - \"func Must5[T1, T2, T3, T4, T5 any](val1 T1, val2 T2, val3 T3, val4 T4, val5 T5, err any, messageArgs ...any) (T1, T2, T3, T4, T5)\"\n  - \"func Must6[T1, T2, T3, T4, T5, T6 any](val1 T1, val2 T2, val3 T3, val4 T4, val5 T5, val6 T6, err any, messageArgs ...any) (T1, T2, T3, T4, T5, T6)\"\nplayUrl: https://go.dev/play/p/TMoWrRp3DyC\nvariantHelpers:\n  - core#error-handling#must\n  - core#error-handling#mustx\nsimilarHelpers:\n  - core#error-handling#validate\n  - core#error-handling#tryx\n  - core#error-handling#tryorx\n  - core#error-handling#trycatch\n  - core#error-handling#trywitherrorvalue\n  - core#error-handling#errorsas\n  - core#error-handling#assert\nposition: 10\n---\n\nPanics if err is an error or false, returning successful values otherwise. Variants cover functions returning 0 to 6 values.\n\n\n```go\n// returns 10, panics if err is not nil\nv := lo.Must(strconv.Atoi(\"10\"))\n\n// panics with custom message\nlo.Must0(fmt.Errorf(\"boom\"), \"failed to parse\")\n\n// panics if myFunc returns an error\nfunc myFunc() (int, string, float64, bool, error) { ... }\na, b, c, d := lo.Must4(myFunc())\n```\n"
  },
  {
    "path": "docs/data/core-newdebounce.md",
    "content": "---\nname: NewDebounce\nslug: newdebounce\nsourceRef: retry.go#L54\ncategory: core\nsubCategory: concurrency\nplayUrl: https://go.dev/play/p/_IPY7ROzbMk\nvariantHelpers:\n  - core#concurrency#newdebounce\nsimilarHelpers:\n  - core#concurrency#newdebounceby\n  - core#concurrency#newthrottle\n  - core#concurrency#newthrottleby\n  - core#concurrency#newtransaction\n  - core#concurrency#synchronize\nposition: 0\nsignatures:\n  - \"func NewDebounce(duration time.Duration, f ...func()) (func(), func())\"\n---\n\nCreates a debounced function that delays invoking the callbacks until after the wait duration has elapsed since the last call. Returns the debounced function and a cancel function.\n\n```go\ndebounce, cancel := lo.NewDebounce(\n    100 * time.Millisecond,\n    func() {\n        println(\"Called once after debounce!\")\n    },\n)\n\nfor i := 0; i < 10; i++ {\n    debounce()\n}\n\ntime.Sleep(200 * time.Millisecond)\ncancel()\n```\n\n\n"
  },
  {
    "path": "docs/data/core-newdebounceby.md",
    "content": "---\nname: NewDebounceBy\nslug: newdebounceby\nsourceRef: retry.go#L137\ncategory: core\nsubCategory: concurrency\nplayUrl: https://go.dev/play/p/Izk7GEzZm2Q\nvariantHelpers:\n  - core#concurrency#newdebounceby\nsimilarHelpers:\n  - core#concurrency#newdebounce\n  - core#concurrency#newthrottle\n  - core#concurrency#newthrottleby\n  - core#concurrency#newdebounceby\nposition: 10\nsignatures:\n  - \"func NewDebounceBy[T comparable](duration time.Duration, f ...func(key T, count int)) (func(key T), func(key T))\"\n---\n\nCreates a debounced function per key that delays invoking callbacks until after the wait duration has elapsed for that key. Returns a per-key debounced function and a per-key cancel function.\n\n```go\ndebounce, cancel := lo.NewDebounceBy[string](\n    100*time.Millisecond,\n    func(key string, count int) {\n        println(key, count)\n    },\n)\n\nfor i := 0; i < 10; i++ {\n    debounce(\"first\")\n}\n\ntime.Sleep(200 * time.Millisecond)\ncancel(\"first\")\n```\n\n\n"
  },
  {
    "path": "docs/data/core-newthrottle.md",
    "content": "---\nname: NewThrottle\nslug: newthrottle\nsourceRef: retry.go#L349\ncategory: core\nsubCategory: concurrency\nplayUrl: https://go.dev/play/p/qQn3fm8Z7jS\nvariantHelpers:\n  - core#concurrency#newthrottle\nsimilarHelpers:\n  - core#concurrency#newthrottleby\n  - core#concurrency#newthrottlewithcount\n  - core#concurrency#newdebounce\n  - core#concurrency#newdebounceby\nposition: 70\nsignatures:\n  - \"func NewThrottle(interval time.Duration, f ...func()) (throttle func(), reset func())\"\n---\n\nCreates a throttled function that invokes callbacks at most once per interval. Returns the throttled function and a reset function.\n\n```go\nthrottle, reset := lo.NewThrottle(\n    100*time.Millisecond,\n    func() {\n        println(\"tick\")\n    },\n)\n\nfor i := 0; i < 10; i++ {\n    throttle();\n    time.Sleep(30*time.Millisecond)\n}\n\nreset()\n```\n\n\n"
  },
  {
    "path": "docs/data/core-newthrottleby.md",
    "content": "---\nname: NewThrottleBy\nslug: newthrottleby\nsourceRef: retry.go#L371\ncategory: core\nsubCategory: concurrency\nplayUrl: https://go.dev/play/p/0Wv6oX7dHdC\nvariantHelpers:\n  - core#concurrency#newthrottleby\nsimilarHelpers:\n  - core#concurrency#newthrottle\n  - core#concurrency#newthrottlebywithcount\n  - core#concurrency#newdebounce\n  - core#concurrency#newdebounceby\nposition: 90\nsignatures:\n  - \"func NewThrottleBy[T comparable](interval time.Duration, f ...func(key T)) (throttle func(key T), reset func())\"\n---\n\nCreates a throttled function per key.\n\n```go\nthrottle, reset := lo.NewThrottleBy[string](\n    100*time.Millisecond,\n    func(key string) {\n        println(key)\n    },\n)\n\nfor i := 0; i < 10; i++ {\n    throttle(\"foo\");\n    time.Sleep(30*time.Millisecond)\n}\n\nreset()\n```\n\n\n"
  },
  {
    "path": "docs/data/core-newthrottlebywithcount.md",
    "content": "---\nname: NewThrottleByWithCount\nslug: newthrottlebywithcount\nsourceRef: retry.go#L377\ncategory: core\nsubCategory: concurrency\nplayUrl: https://go.dev/play/p/vQk3ECH7_EW\nvariantHelpers:\n  - core#concurrency#newthrottlebywithcount\nsimilarHelpers:\n  - core#concurrency#newthrottle\n  - core#concurrency#newthrottleby\n  - core#concurrency#newthrottlewithcount\n  - core#concurrency#newdebounce\n  - core#concurrency#newdebounceby\nposition: 100\nsignatures:\n  - \"func NewThrottleByWithCount[T comparable](interval time.Duration, count int, f ...func(key T)) (throttle func(key T), reset func())\"\n---\n\nCreates a throttled function per key with a per-interval invocation limit.\n\n```go\nthrottle, reset := lo.NewThrottleByWithCount[string](\n    100*time.Millisecond,\n    3,\n    func(key string) {\n        println(key)\n    },\n)\n\nfor i := 0; i < 10; i++ {\n    throttle(\"foo\")\n}\n\nreset()\n```\n\n\n"
  },
  {
    "path": "docs/data/core-newthrottlewithcount.md",
    "content": "---\nname: NewThrottleWithCount\nslug: newthrottlewithcount\nsourceRef: retry.go#L355\ncategory: core\nsubCategory: concurrency\nplayUrl: https://go.dev/play/p/w5nc0MgWtjC\nvariantHelpers:\n  - core#concurrency#newthrottlewithcount\nsimilarHelpers:\n  - core#concurrency#newthrottle\n  - core#concurrency#newthrottleby\n  - core#concurrency#newthrottlebywithcount\n  - core#concurrency#newdebounce\n  - core#concurrency#newdebounceby\nposition: 80\nsignatures:\n  - \"func NewThrottleWithCount(interval time.Duration, count int, f ...func()) (throttle func(), reset func())\"\n---\n\nCreates a throttled function with a per-interval invocation limit.\n\n```go\nthrottle, reset := lo.NewThrottleWithCount(\n    100*time.Millisecond,\n    3,\n    func() {\n        println(\"tick\")\n    },\n)\n\nfor i := 0; i < 10; i++ {\n    throttle();\n    time.Sleep(30*time.Millisecond)\n}\n\nreset()\n```\n\n\n"
  },
  {
    "path": "docs/data/core-newtransaction.md",
    "content": "---\nname: NewTransaction\nslug: newtransaction\nsourceRef: retry.go#L253\ncategory: core\nsubCategory: concurrency\nplayUrl: https://go.dev/play/p/7B2o52wEQbj\nvariantHelpers:\n  - core#concurrency#newtransaction\nsimilarHelpers:\n  - core#concurrency#synchronize\n  - core#concurrency#asyncx\n  - core#concurrency#waitfor\nposition: 30\nsignatures:\n  - \"func NewTransaction[T any]() *Transaction[T]\"\n---\n\nCreates a new Saga transaction that chains steps with rollback functions.\n\nUse Then to add steps with exec and rollback functions. Call Process with an initial state to execute the pipeline; if a step returns an error, previously executed steps are rolled back in reverse order using their rollback functions.\n\n```go\ntype Acc struct{ Sum int }\n\ntx := lo.NewTransaction[Acc]().\n    Then(\n        func(a Acc) (Acc, error) {\n            a.Sum += 10\n            return a, nil\n        },\n        func(a Acc) Acc {\n            a.Sum -= 10\n            return a\n        },\n    ).\n    Then(\n        func(a Acc) (Acc, error) {\n            a.Sum *= 3\n            return a, nil\n        },\n        func(a Acc) Acc {\n            a.Sum /= 3\n            return a\n        },\n    )\n\nres, err := tx.Process(Acc{Sum: 1})\n// res.Sum == 33, err == nil\n```\n"
  },
  {
    "path": "docs/data/core-nil.md",
    "content": "---\nname: Nil\nslug: nil\nsourceRef: type_manipulation.go#L34\ncategory: core\nsubCategory: type\nplayUrl: https://go.dev/play/p/P2sD0PMXw4F\nvariantHelpers:\n  - core#type#nil\nsimilarHelpers:\n  - core#type#isnil\n  - core#type#isnotnil\n  - core#type#toptr\n  - core#type#fromptr\nposition: 1\nsignatures:\n  - \"func Nil[T any]() *T\"\n---\n\nReturns a nil pointer of type.\n\n```go\nlo.Nil[string]()\n// (*string)(nil)\n\nlo.Nil[int]()\n// (*int)(nil)\n```\n\nUseful when you need a nil pointer of a specific type without declaring a variable first."
  },
  {
    "path": "docs/data/core-none.md",
    "content": "---\nname: None\nslug: none\nsourceRef: intersect.go#L79\ncategory: core\nsubCategory: intersect\nplayUrl: https://go.dev/play/p/fye7JsmxzPV\nvariantHelpers:\n  - core#intersect#none\nsimilarHelpers:\n  - core#intersect#noneby\n  - core#intersect#contains\n  - core#intersect#every\n  - core#intersect#some\n  - core#intersect#containsby\nposition: 60\nsignatures:\n  - \"func None[T comparable](collection []T, subset []T) bool\"\n---\n\nReturns true if no element of a subset is contained in a collection, or if the subset is empty.\n\n```go\nok := lo.None([]int{0, 1, 2, 3, 4, 5}, []int{-1, 6})\n// true\n```\n\n\n"
  },
  {
    "path": "docs/data/core-noneby.md",
    "content": "---\nname: NoneBy\nslug: noneby\nsourceRef: intersect.go#L91\ncategory: core\nsubCategory: intersect\nplayUrl: https://go.dev/play/p/O64WZ32H58S\nvariantHelpers:\n  - core#intersect#noneby\nsimilarHelpers:\n  - core#intersect#none\n  - core#intersect#everyby\n  - core#intersect#every\n  - core#intersect#someby\n  - core#intersect#some\n  - core#intersect#containsby\n  - core#intersect#contains\nposition: 70\nsignatures:\n  - \"func NoneBy[T any](collection []T, predicate func(item T) bool) bool\"\n---\n\nReturns true if the predicate returns true for none of the elements in the collection, or if the collection is empty.\n\n```go\nok := lo.NoneBy(\n    []int{1, 2, 3, 4},\n    func(x int) bool {\n        return x < 0\n    },\n)\n// true\n```\n\n\n"
  },
  {
    "path": "docs/data/core-nth.md",
    "content": "---\nname: Nth\nslug: nth\nsourceRef: find.go#L617\ncategory: core\nsubCategory: find\nplayUrl: https://go.dev/play/p/mNFI9-kIZZ5\nvariantHelpers:\n  - core#find#nth\nsimilarHelpers:\n  - core#find#first\n  - core#find#last\n  - core#find#nthor\n  - core#find#nthorempty\n  - core#slice#indexof\n  - core#slice#drop\nposition: 320\nsignatures:\n  - \"func Nth[T any, N constraints.Integer](collection []T, nth N) (T, error)\"\n---\n\nReturns the element at index nth of collection. If nth is negative, returns the nth element from the end. Returns an error when nth is out of slice bounds.\n\n```go\nv, _ := lo.Nth([]int{10, 20, 30}, 1)\n// v == 20\n```\n\n\n"
  },
  {
    "path": "docs/data/core-nthor.md",
    "content": "---\nname: NthOr\nslug: nthor\nsourceRef: find.go#L635\ncategory: core\nsubCategory: find\nplayUrl: https://go.dev/play/p/njKcNhBBVsF\nvariantHelpers:\n  - core#find#nthor\nsimilarHelpers:\n  - core#find#nthorempty\n  - core#find#nth\n  - core#find#findorelse\n  - core#find#firstor\nposition: 330\nsignatures:\n  - \"func NthOr[T any, N constraints.Integer](collection []T, nth N, fallback T) T\"\n---\n\nReturns the element at index nth of collection, or the fallback if out of bounds. If nth is negative, returns the nth element from the end.\n\n```go\nv := lo.NthOr([]int{10, 20, 30}, 10, -1)\n// v == -1\n```\n\n\n"
  },
  {
    "path": "docs/data/core-nthorempty.md",
    "content": "---\nname: NthOrEmpty\nslug: nthorempty\nsourceRef: find.go#L647\ncategory: core\nsubCategory: find\nplayUrl: https://go.dev/play/p/sHoh88KWt6B\nvariantHelpers:\n  - core#find#nthorempty\nsimilarHelpers:\n  - core#find#nthor\n  - core#find#nth\n  - core#find#findorelse\n  - core#find#firstorempty\nposition: 340\nsignatures:\n  - \"func NthOrEmpty[T any, N constraints.Integer](collection []T, nth N) T\"\n---\n\nReturns the element at index nth of collection, or the zero value if out of bounds. If nth is negative, returns the nth element from the end.\n\n```go\nv := lo.NthOrEmpty([]int{10, 20, 30}, 10)\n// v == 0\n```\n\n\n"
  },
  {
    "path": "docs/data/core-omitby.md",
    "content": "---\nname: OmitBy\nslug: omitby\nsourceRef: map.go#L159\ncategory: core\nsubCategory: map\nplayUrl: https://go.dev/play/p/EtBsR43bdsd\nvariantHelpers:\n  - core#map#omitby\nsimilarHelpers:\n  - core#map#pickby\n  - core#map#omitbykeys\n  - core#map#omitbyvalues\n  - core#map#pickbykeys\n  - core#map#pickbyvalues\n  - core#map#filterkeys\n  - core#map#filtervalues\n  - core#map#omitbyerr\nposition: 90\nsignatures:\n  - \"func OmitBy[K comparable, V any, Map ~map[K]V](in Map, predicate func(key K, value V) bool) Map\"\n---\n\nReturns a map of the same type excluding entries that match the predicate.\n\n```go\nm := lo.OmitBy(\n    map[string]int{\"foo\": 1, \"bar\": 2, \"baz\": 3},\n    func(key string, value int) bool {\n        return value%2 == 1\n    },\n)\n// map[string]int{\"bar\": 2}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-omitbyerr.md",
    "content": "---\nname: OmitByErr\nslug: omitbyerr\nsourceRef: map.go#L171\ncategory: core\nsubCategory: map\nsignatures:\n  - \"func OmitByErr[K comparable, V any, Map ~map[K]V](in Map, predicate func(key K, value V) (bool, error)) (Map, error)\"\nvariantHelpers:\n  - core#map#omitbyerr\nsimilarHelpers:\n  - core#map#omitby\n  - core#map#pickbyerr\n  - core#map#pickby\nposition: 95\n---\n\nReturns a map of the same type excluding entries that match the predicate. Returns an error if the predicate function fails, stopping iteration immediately.\n\n```go\nm, err := lo.OmitByErr(\n    map[string]int{\"foo\": 1, \"bar\": 2, \"baz\": 3},\n    func(key string, value int) (bool, error) {\n        if key == \"bar\" {\n            return false, fmt.Errorf(\"bar not allowed\")\n        }\n        return value%2 == 1, nil\n    },\n)\n// map[string]int(nil), error(\"bar not allowed\")\n```\n\n```go\nm, err := lo.OmitByErr(\n    map[string]int{\"foo\": 1, \"bar\": 2, \"baz\": 3},\n    func(key string, value int) (bool, error) {\n        return value%2 == 1, nil\n    },\n)\n// map[string]int{\"bar\": 2}, nil\n```\n"
  },
  {
    "path": "docs/data/core-omitbykeys.md",
    "content": "---\nname: OmitByKeys\nslug: omitbykeys\nsourceRef: map.go#L154\ncategory: core\nsubCategory: map\nplayUrl: https://go.dev/play/p/t1QjCrs-ysk\nvariantHelpers:\n  - core#map#omitbykeys\nsimilarHelpers:\n  - core#map#omitby\n  - core#map#omitbyvalues\n  - core#map#pickby\n  - core#map#pickbykeys\n  - core#map#pickbyvalues\nposition: 100\nsignatures:\n  - \"func OmitByKeys[K comparable, V any, Map ~map[K]V](in Map, keys []K) Map\"\n---\n\nReturns a map of the same type excluding the provided keys.\n\n```go\nm := lo.OmitByKeys(map[string]int{\"foo\": 1, \"bar\": 2, \"baz\": 3}, []string{\"foo\", \"baz\"})\n// map[string]int{\"bar\": 2}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-omitbyvalues.md",
    "content": "---\nname: OmitByValues\nslug: omitbyvalues\nsourceRef: map.go#L167\ncategory: core\nsubCategory: map\nplayUrl: https://go.dev/play/p/9UYZi-hrs8j\nvariantHelpers:\n  - core#map#omitbyvalues\nsimilarHelpers:\n  - core#map#omitby\n  - core#map#omitbykeys\n  - core#map#pickby\n  - core#map#pickbykeys\n  - core#map#pickbyvalues\nposition: 110\nsignatures:\n  - \"func OmitByValues[K comparable, V comparable, Map ~map[K]V](in Map, values []V) Map\"\n---\n\nReturns a map of the same type excluding the provided values.\n\n```go\nm := lo.OmitByValues(map[string]int{\"foo\": 1, \"bar\": 2, \"baz\": 3}, []int{1, 3})\n// map[string]int{\"bar\": 2}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-partialx.md",
    "content": "---\nname: PartialX\nslug: partialx\nsourceRef: func.go#L5\ncategory: core\nsubCategory: function\nsignatures:\n  - \"func Partial[T1, T2, R any](f func(a T1, b T2) R, arg1 T1) func(T2) R\"\n  - \"func Partial1[T1, T2, R any](f func(T1, T2) R, arg1 T1) func(T2) R\"\n  - \"func Partial2[T1, T2, T3, R any](f func(T1, T2, T3) R, arg1 T1) func(T2, T3) R\"\n  - \"func Partial3[T1, T2, T3, T4, R any](f func(T1, T2, T3, T4) R, arg1 T1) func(T2, T3, T4) R\"\n  - \"func Partial4[T1, T2, T3, T4, T5, R any](f func(T1, T2, T3, T4, T5) R, arg1 T1) func(T2, T3, T4, T5) R\"\n  - \"func Partial5[T1, T2, T3, T4, T5, T6, R any](f func(T1, T2, T3, T4, T5, T6) R, arg1 T1) func(T2, T3, T4, T5, T6) R\"\nplayUrl: https://go.dev/play/p/Sy1gAQiQZ3v\nvariantHelpers:\n  - core#function#partial\n  - core#function#partialx\nsimilarHelpers:\n  - core#condition#if\n  - core#condition#ternary\n  - core#condition#switch\n  - core#retry#attempt\n  - core#retry#attemptwithdelay\nposition: 0\n---\n\nPre-binds the first argument of a function. Variants support functions taking from 2 up to 6 input parameters.\n\n```go\nadd := func(x, y int) int {\n    return x + y\n}\nadd10 := lo.Partial(add, 10)\nsum := add10(5)\n// 15\n```\n\n\n"
  },
  {
    "path": "docs/data/core-partitionby.md",
    "content": "---\nname: PartitionBy\nslug: partitionby\nsourceRef: slice.go#L240\ncategory: core\nsubCategory: slice\nplayUrl: https://go.dev/play/p/NfQ_nGjkgXW\nvariantHelpers:\n  - core#slice#partitionby\nsimilarHelpers:\n  - core#slice#partitionbyerr\n  - core#slice#groupby\n  - core#slice#groupbyerr\n  - core#slice#groupbymap\n  - core#slice#chunk\n  - core#map#keyby\nposition: 150\nsignatures:\n  - \"func PartitionBy[T any, K comparable, Slice ~[]T](collection Slice, iteratee func(item T) K) []Slice\"\n---\n\nPartitions a slice into groups determined by a key computed from each element, preserving original order.\n\n\n"
  },
  {
    "path": "docs/data/core-partitionbyerr.md",
    "content": "---\nname: PartitionByErr\nslug: partitionbyerr\nsourceRef: slice.go#L385\ncategory: core\nsubCategory: slice\nsignatures:\n  - \"func PartitionByErr[T any, K comparable, Slice ~[]T](collection Slice, iteratee func(item T) (K, error)) ([]Slice, error)\"\nvariantHelpers:\n  - core#slice#partitionbyerr\nsimilarHelpers:\n  - core#slice#partitionby\n  - core#slice#groupby\n  - core#slice#groupbyerr\n  - core#slice#groupbymap\n  - core#slice#chunk\n  - core#map#keyby\nposition: 151\n---\n\nPartitions a slice into groups determined by a key computed from each element using an iteratee that can return an error. Stops iteration immediately when an error is encountered. Preserves original order.\n\n```go\n// Error case - stops on first error\nresult, err := lo.PartitionByErr([]int{-2, -1, 0, 1, 2, 3}, func(x int) (string, error) {\n    if x == 0 {\n        return \"\", fmt.Errorf(\"zero is not allowed\")\n    }\n    if x < 0 {\n        return \"negative\", nil\n    } else if x%2 == 0 {\n        return \"even\", nil\n    }\n    return \"odd\", nil\n})\n// [][]int(nil), error(\"zero is not allowed\")\n```\n\n```go\n// Success case\nresult, err := lo.PartitionByErr([]int{-2, -1, 0, 1, 2}, func(x int) (string, error) {\n    if x < 0 {\n        return \"negative\", nil\n    } else if x%2 == 0 {\n        return \"even\", nil\n    }\n    return \"odd\", nil\n})\n// [][]int{{-2, -1}, {0, 2}, {1}}, nil\n```\n"
  },
  {
    "path": "docs/data/core-pascalcase.md",
    "content": "---\nname: PascalCase\nslug: pascalcase\nsourceRef: string.go#L166\ncategory: core\nsubCategory: string\nplayUrl: https://go.dev/play/p/uxER7XpRHLB\nvariantHelpers:\n  - core#string#pascalcase\nsimilarHelpers:\n  - core#string#camelcase\n  - core#string#snakecase\n  - core#string#kebabcase\n  - core#string#capitalize\n  - core#string#words\nposition: 40\nsignatures:\n  - \"func PascalCase(str string) string\"\n---\n\nConverts a string to PascalCase.\n\n```go\nlo.PascalCase(\"hello_world\")\n// \"HelloWorld\"\n```\n\n\n"
  },
  {
    "path": "docs/data/core-pickby.md",
    "content": "---\nname: PickBy\nslug: pickby\nsourceRef: map.go#L105\ncategory: core\nsubCategory: map\nplayUrl: https://go.dev/play/p/kdg8GR_QMmf\nvariantHelpers:\n  - core#map#pickby\nsimilarHelpers:\n  - core#map#omitby\n  - core#map#omitbykeys\n  - core#map#omitbyvalues\n  - core#map#pickbykeys\n  - core#map#pickbyvalues\n  - core#map#filterkeys\n  - core#map#filtervalues\n  - core#map#pickbyerr\nposition: 60\nsignatures:\n  - \"func PickBy[K comparable, V any, Map ~map[K]V](in Map, predicate func(key K, value V) bool) Map\"\n---\n\nReturns a map of the same type filtered by a key/value predicate.\n\n```go\nm := lo.PickBy(\n    map[string]int{\"foo\": 1, \"bar\": 2, \"baz\": 3},\n    func(key string, value int) bool {\n        return value%2 == 1\n    },\n)\n// map[string]int{\"foo\": 1, \"baz\": 3}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-pickbyerr.md",
    "content": "---\nname: PickByErr\nslug: pickbyerr\nsourceRef: map.go#L117\ncategory: core\nsubCategory: map\nsignatures:\n  - \"func PickByErr[K comparable, V any, Map ~map[K]V](in Map, predicate func(key K, value V) (bool, error)) (Map, error)\"\nvariantHelpers:\n  - core#map#pickbyerr\nsimilarHelpers:\n  - core#map#pickby\n  - core#map#omitby\n  - core#map#omitbyerr\nposition: 65\n---\n\nReturns a map of the same type filtered by a key/value predicate. Returns an error if the predicate function fails, stopping iteration immediately.\n\n```go\nm, err := lo.PickByErr(\n    map[string]int{\"foo\": 1, \"bar\": 2, \"baz\": 3},\n    func(key string, value int) (bool, error) {\n        if key == \"bar\" {\n            return false, fmt.Errorf(\"bar not allowed\")\n        }\n        return value%2 == 1, nil\n    },\n)\n// map[string]int(nil), error(\"bar not allowed\")\n```\n\n```go\nm, err := lo.PickByErr(\n    map[string]int{\"foo\": 1, \"bar\": 2, \"baz\": 3},\n    func(key string, value int) (bool, error) {\n        return value%2 == 1, nil\n    },\n)\n// map[string]int{\"foo\": 1, \"baz\": 3}, nil\n```\n"
  },
  {
    "path": "docs/data/core-pickbykeys.md",
    "content": "---\nname: PickByKeys\nslug: pickbykeys\nsourceRef: map.go#L118\ncategory: core\nsubCategory: map\nplayUrl: https://go.dev/play/p/R1imbuci9qU\nvariantHelpers:\n  - core#map#pickbykeys\nsimilarHelpers:\n  - core#map#pickby\n  - core#map#pickbyvalues\n  - core#map#omitby\n  - core#map#omitbykeys\n  - core#map#omitbyvalues\nposition: 70\nsignatures:\n  - \"func PickByKeys[K comparable, V any, Map ~map[K]V](in Map, keys []K) Map\"\n---\n\nReturns a map of the same type filtered by the provided keys.\n\n```go\nm := lo.PickByKeys(\n    map[string]int{\"foo\": 1, \"bar\": 2, \"baz\": 3},\n    []string{\"foo\", \"baz\"},\n)\n// map[string]int{\"foo\": 1, \"baz\": 3}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-pickbyvalues.md",
    "content": "---\nname: PickByValues\nslug: pickbyvalues\nsourceRef: map.go#L130\ncategory: core\nsubCategory: map\nplayUrl: https://go.dev/play/p/-_PPkSbO1Kc\nvariantHelpers:\n  - core#map#pickbyvalues\nsimilarHelpers:\n  - core#map#pickby\n  - core#map#pickbykeys\n  - core#map#omitby\n  - core#map#omitbykeys\n  - core#map#omitbyvalues\nposition: 80\nsignatures:\n  - \"func PickByValues[K comparable, V comparable, Map ~map[K]V](in Map, values []V) Map\"\n---\n\nReturns a map of the same type filtered by the provided values.\n\n```go\nm := lo.PickByValues(map[string]int{\"foo\": 1, \"bar\": 2, \"baz\": 3}, []int{1, 3})\n// map[string]int{\"foo\": 1, \"baz\": 3}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-product.md",
    "content": "---\nname: Product\nslug: product\nsourceRef: math.go#L90\ncategory: core\nsubCategory: math\nplayUrl: https://go.dev/play/p/2_kjM_smtAH\nvariantHelpers:\n  - core#math#product\nsimilarHelpers:\n  - core#math#sum\n  - core#math#mean\n  - core#math#productby\n  - core#math#sumby\n  - core#math#meanby\n  - core#find#min\n  - core#find#max\n  - core#find#minby\n  - core#find#maxby\n  - core#math#mode\nposition: 60\nsignatures:\n  - \"func Product[T constraints.Float | constraints.Integer | constraints.Complex](collection []T) T\"\n---\n\nCalculates the product of the values in a collection. Returns 1 for nil or empty collections.\n\n```go\nlo.Product([]int{1, 2, 3, 4, 5})\n// 120\n```\n\n\n"
  },
  {
    "path": "docs/data/core-productby.md",
    "content": "---\nname: ProductBy\nslug: productby\nsourceRef: math.go#L125\ncategory: core\nsubCategory: math\nplayUrl: https://go.dev/play/p/wadzrWr9Aer\nvariantHelpers:\n  - core#math#productby\nsimilarHelpers:\n  - core#math#product\n  - core#math#productbyerr\n  - core#math#sumby\n  - core#math#meanby\n  - core#find#minby\n  - core#find#maxby\n  - core#find#minindexby\n  - core#find#maxindexby\n  - core#math#sum\n  - core#math#mean\nposition: 70\nsignatures:\n  - \"func ProductBy[T any, R constraints.Float | constraints.Integer | constraints.Complex](collection []T, iteratee func(item T) R) R\"\n---\n\nCalculates the product of values computed by a predicate. Returns 1 for nil or empty collections.\n\n```go\nstrings := []string{\"foo\", \"bar\"}\nlo.ProductBy(strings, func(item string) int {\n    return len(item)\n})\n// 9\n```\n\n\n"
  },
  {
    "path": "docs/data/core-productbyerr.md",
    "content": "---\nname: ProductByErr\nslug: productbyerr\nsourceRef: math.go#L134\ncategory: core\nsubCategory: math\nvariantHelpers:\n  - core#math#productbyerr\nsimilarHelpers:\n  - core#math#productby\n  - core#math#product\n  - core#math#sumbyerr\n  - core#math#meanby\n  - core#find#minby\n  - core#find#maxby\nposition: 71\nsignatures:\n  - \"func ProductByErr[T any, R constraints.Float | constraints.Integer | constraints.Complex](collection []T, iteratee func(item T) (R, error)) (R, error)\"\n---\n\nCalculates the product of values computed by a predicate. Returns 1 for nil or empty collections.\n\nIf the iteratee returns an error, iteration stops and the error is returned.\n\n```go\nstrings := []string{\"foo\", \"bar\"}\nresult, err := lo.ProductByErr(strings, func(item string) (int, error) {\n    return len(item), nil\n})\n// 9, <nil>\n```\n\nExample with error:\n\n```go\nstrings := []string{\"foo\", \"bar\", \"baz\"}\nresult, err := lo.ProductByErr(strings, func(item string) (int, error) {\n    if item == \"bar\" {\n        return 0, fmt.Errorf(\"bar is not allowed\")\n    }\n    return len(item), nil\n})\n// 3, error(\"bar is not allowed\")\n```\n"
  },
  {
    "path": "docs/data/core-randomstring.md",
    "content": "---\nname: RandomString\nslug: randomstring\nsourceRef: string.go#L35\ncategory: core\nsubCategory: string\nplayUrl: https://go.dev/play/p/rRseOQVVum4\nvariantHelpers:\n  - core#string#randomstring\nsimilarHelpers:\n  - core#string#substring\n  - core#string#chunkstring\n  - core#string#words\n  - core#string#capitalize\n  - core#string#camelcase\n  - core#string#pascalcase\n  - core#string#kebabcase\n  - core#string#snakecase\nposition: 0\nsignatures:\n  - \"func RandomString(size int, charset []rune) string\"\n---\n\nReturns a random string of the specified length from the given charset.\n\n```go\nstr := lo.RandomString(5, lo.LettersCharset)\n// e.g., \"eIGbt\"\n```\n\n\n"
  },
  {
    "path": "docs/data/core-range.md",
    "content": "---\nname: Range\nslug: range\nsourceRef: math.go#L9\ncategory: core\nsubCategory: math\nplayUrl: https://go.dev/play/p/rho00R0WuHs\nvariantHelpers:\n  - core#math#range\nsimilarHelpers:\n  - core#math#rangefrom\n  - core#math#rangewithsteps\n  - core#math#times\n  - core#slice#repeat\n  - core#slice#repeatby\nposition: 0\nsignatures:\n  - \"func Range(elementNum int) []int\"\n---\n\nCreates a slice of integers of the given length starting at 0. Negative length produces a descending sequence.\n\n```go\nlo.Range(4)\n// []int{0, 1, 2, 3}\n\nlo.Range(-4)\n// []int{0, -1, -2, -3}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-rangefrom.md",
    "content": "---\nname: RangeFrom\nslug: rangefrom\nsourceRef: math.go#L21\ncategory: core\nsubCategory: math\nplayUrl: https://go.dev/play/p/0r6VimXAi9H\nvariantHelpers:\n  - core#math#rangefrom\nsimilarHelpers:\n  - core#math#range\n  - core#math#rangewithsteps\n  - core#math#times\n  - core#slice#repeat\n  - core#slice#repeatby\nposition: 10\nsignatures:\n  - \"func RangeFrom[T constraints.Integer | constraints.Float](start T, elementNum int) []T\"\n---\n\nCreates a slice starting at `start` with the specified length. Negative length yields a descending sequence.\n\n```go\nlo.RangeFrom(1, 5)\n// []int{1, 2, 3, 4, 5}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-rangewithsteps.md",
    "content": "---\nname: RangeWithSteps\nslug: rangewithsteps\nsourceRef: math.go#L34\ncategory: core\nsubCategory: math\nplayUrl: https://go.dev/play/p/0r6VimXAi9H\nvariantHelpers:\n  - core#math#rangewithsteps\nsimilarHelpers:\n  - core#math#range\n  - core#math#rangefrom\n  - core#math#times\n  - core#slice#repeat\n  - core#slice#repeatby\nposition: 20\nsignatures:\n  - \"func RangeWithSteps[T constraints.Integer | constraints.Float](start, end, step T) []T\"\n---\n\nCreates a slice progressing from `start` up to, but not including, `end` by `step`. Returns empty if `step` is 0 or direction mismatches.\n\n```go\nlo.RangeWithSteps(0, 20, 5)\n// []int{0, 5, 10, 15}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-reduce.md",
    "content": "---\nname: Reduce\nslug: reduce\nsourceRef: slice.go#L87\ncategory: core\nsubCategory: slice\nplayUrl: https://go.dev/play/p/CgHYNUpOd1I\nvariantHelpers:\n  - core#slice#reduce\nsimilarHelpers:\n  - core#slice#reduceerr\n  - core#slice#reduceright\n  - core#slice#sum\n  - core#slice#sumby\n  - core#slice#sumbyerr\n  - core#slice#product\n  - core#slice#productby\n  - core#slice#mean\n  - core#slice#meanby\nposition: 50\nsignatures:\n  - \"func Reduce[T any, R any](collection []T, accumulator func(agg R, item T, index int) R, initial R) R\"\n---\n\nReduces a collection to a single value by accumulating results of an accumulator function. Each call receives the previous result value.\n\n```go\nsum := lo.Reduce([]int{1, 2, 3, 4}, func(agg int, item int, _ int) int {\n    return agg + item\n}, 0)\n// 10\n```\n\n\n"
  },
  {
    "path": "docs/data/core-reduceerr.md",
    "content": "---\nname: ReduceErr\nslug: reduceerr\nsourceRef: slice.go#L128\ncategory: core\nsubCategory: slice\nsignatures:\n  - \"func ReduceErr[T any, R any](collection []T, accumulator func(agg R, item T, index int) (R, error), initial R) (R, error)\"\nvariantHelpers:\n  - core#slice#reduceerr\nsimilarHelpers:\n  - core#slice#reduce\n  - core#slice#reduceright\n  - core#slice#sum\n  - core#slice#sumby\n  - core#slice#sumbyerr\nposition: 51\n---\n\nReduces a collection to a single value by accumulating results of an accumulator function that can return an error. Stops iteration immediately when an error is encountered.\n\n```go\n// Error case - stops on first error\nresult, err := lo.ReduceErr([]int{1, 2, 3, 4}, func(agg int, item int, _ int) (int, error) {\n    if item == 3 {\n        return 0, fmt.Errorf(\"number 3 is not allowed\")\n    }\n    return agg + item, nil\n}, 0)\n// 0, error(\"number 3 is not allowed\")\n```\n\n```go\n// Success case\nresult, err := lo.ReduceErr([]int{1, 2, 3, 4}, func(agg int, item int, _ int) (int, error) {\n    return agg + item, nil\n}, 0)\n// 10, nil\n```\n"
  },
  {
    "path": "docs/data/core-reduceright.md",
    "content": "---\nname: ReduceRight\nslug: reduceright\nsourceRef: slice.go#L97\ncategory: core\nsubCategory: slice\nplayUrl: https://go.dev/play/p/Fq3W70l7wXF\nvariantHelpers:\n  - core#slice#reduceright\nsimilarHelpers:\n  - core#slice#reducerighterr\n  - core#slice#reduce\n  - core#slice#reduceerr\n  - core#slice#sum\n  - core#slice#product\n  - core#slice#mean\n  - core#slice#max\n  - core#slice#min\nposition: 60\nsignatures:\n  - \"func ReduceRight[T any, R any](collection []T, accumulator func(agg R, item T, index int) R, initial R) R\"\n---\n\nLike Reduce except it iterates from right to left and accumulates into a single value.\n\n```go\nresult := lo.ReduceRight([][]int{{0, 1}, {2, 3}, {4, 5}}, func(agg []int, item []int, _ int) []int {\n    return append(agg, item...)\n}, []int{})\n// []int{4, 5, 2, 3, 0, 1}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-reducerighterr.md",
    "content": "---\nname: ReduceRightErr\nslug: reducerighterr\nsourceRef: slice.go#L153\ncategory: core\nsubCategory: slice\nsignatures:\n  - \"func ReduceRightErr[T any, R any](collection []T, accumulator func(agg R, item T, index int) (R, error), initial R) (R, error)\"\nvariantHelpers:\n  - core#slice#reducerighterr\nsimilarHelpers:\n  - core#slice#reduceright\n  - core#slice#reduce\n  - core#slice#reduceerr\nposition: 61\n---\n\nLike Reduce but iterates from right to left and accumulates into a single value using an accumulator function that can return an error. Stops iteration immediately when an error is encountered.\n\n```go\n// Error case - stops on first error (from right to left)\nresult, err := lo.ReduceRightErr([][]int{{0, 1}, {2, 3}, {4, 5}}, func(agg []int, item []int, _ int) ([]int, error) {\n    if len(item) > 0 && item[0] == 4 {\n        return nil, fmt.Errorf(\"element starting with 4 is not allowed\")\n    }\n    return append(agg, item...), nil\n}, []int{})\n// []int(nil), error(\"element starting with 4 is not allowed\")\n```\n\n```go\n// Success case\nresult, err := lo.ReduceRightErr([]int{1, 2, 3, 4}, func(agg int, item int, _ int) (int, error) {\n    return agg + item, nil\n}, 0)\n// 10, nil\n```\n"
  },
  {
    "path": "docs/data/core-reject.md",
    "content": "---\nname: Reject\nslug: reject\nsourceRef: slice.go#L532\ncategory: core\nsubCategory: slice\nplayUrl: https://go.dev/play/p/pFCF5WVB225\nvariantHelpers:\n  - core#slice#reject\nsimilarHelpers:\n  - core#slice#filter\n  - core#slice#rejecterr\n  - core#slice#filterreject\n  - core#slice#rejectmap\n  - core#slice#filterreject\n  - mutable#slice#reject\nposition: 260\nsignatures:\n  - \"func Reject[T any, Slice ~[]T](collection Slice, predicate func(item T, index int) bool) Slice\"\n---\n\nReturns the elements for which the predicate returns false (opposite of Filter).\n\n```go\nlo.Reject(\n    []int{1, 2, 3, 4},\n    func(x int, _ int) bool {\n        return x%2 == 0\n    },\n)\n// []int{1, 3}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-rejecterr.md",
    "content": "---\nname: RejectErr\nslug: rejecterr\nsourceRef: slice.go#L897\ncategory: core\nsubCategory: slice\nsignatures:\n  - \"func RejectErr[T any, Slice ~[]T](collection Slice, predicate func(item T, index int) (bool, error)) (Slice, error)\"\nplayUrl: https://go.dev/play/p/pFCF5WVB225\nvariantHelpers:\n  - core#slice#rejecterr\nsimilarHelpers:\n  - core#slice#reject\n  - core#slice#filtererr\n  - core#slice#rejectmap\n  - core#slice#filterreject\nposition: 265\n---\n\nThe opposite of FilterErr. Returns the elements for which the predicate returns false. If the predicate returns an error, iteration stops immediately and returns the error.\n\n```go\nodd, err := lo.RejectErr([]int{1, 2, 3, 4}, func(x int, index int) (bool, error) {\n    if x == 3 {\n        return false, errors.New(\"number 3 is not allowed\")\n    }\n    return x%2 == 0, nil\n})\n// []int(nil), error(\"number 3 is not allowed\")\n```\n\n```go\nodd, err := lo.RejectErr([]int{1, 2, 3, 4}, func(x int, index int) (bool, error) {\n    return x%2 == 0, nil\n})\n// []int{1, 3}, nil\n```\n"
  },
  {
    "path": "docs/data/core-rejectmap.md",
    "content": "---\nname: RejectMap\nslug: rejectmap\nsourceRef: slice.go#L550\ncategory: core\nsubCategory: slice\nplayUrl: https://go.dev/play/p/bmXhtuM2OMq\nvariantHelpers:\n  - core#slice#rejectmap\nsimilarHelpers:\n  - core#slice#filtermap\n  - core#slice#map\n  - core#slice#filter\n  - core#slice#reject\nposition: 270\nsignatures:\n  - \"func RejectMap[T any, R any](collection []T, callback func(item T, index int) (R, bool)) []R\"\n---\n\nOpposite of FilterMap: maps each item and includes results where the predicate returned false.\n\n```go\nitems := lo.RejectMap([]int{1, 2, 3, 4}, func(x int, _ int) (int, bool) {\n    return x * 10, x%2 == 0\n})\n// []int{10, 30}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-repeat.md",
    "content": "---\nname: Repeat\nslug: repeat\nsourceRef: slice.go#L362\ncategory: core\nsubCategory: slice\nplayUrl: https://go.dev/play/p/g3uHXbmc3b6\nvariantHelpers:\n  - core#slice#repeat\nsimilarHelpers:\n  - core#slice#times\n  - core#slice#repeatby\nposition: 220\nsignatures:\n  - \"func Repeat[T any](count int, initial T) []T\"\n---\n\nBuilds a slice with N copies of initial value.\n\n```go\nlo.Repeat(5, \"42\")\n// []string{\"42\", \"42\", \"42\", \"42\", \"42\"}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-repeatby.md",
    "content": "---\nname: RepeatBy\nslug: repeatby\nsourceRef: slice.go#L362\ncategory: core\nsubCategory: slice\nplayUrl: https://go.dev/play/p/ozZLCtX_hNU\nvariantHelpers:\n  - core#slice#repeatby\n  - core#slice#repeatbyerr\nsimilarHelpers:\n  - core#slice#times\n  - core#slice#repeat\nposition: 220\nsignatures:\n  - \"func RepeatBy[T any](count int, callback func(index int) T) []T\"\n---\n\nBuilds a slice by calling the callback N times with the current index.\n\n```go\nlo.RepeatBy(5, func(i int) string {\n    return strconv.Itoa(i * i)\n})\n// []string{\"0\", \"1\", \"4\", \"9\", \"16\"}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-repeatbyerr.md",
    "content": "---\nname: RepeatByErr\nslug: repeatbyerr\nsourceRef: slice.go#L564\ncategory: core\nsubCategory: slice\nsignatures:\n  - \"func RepeatByErr[T any](count int, callback func(index int) (T, error)) ([]T, error)\"\nvariantHelpers:\n  - core#slice#repeatbyerr\nsimilarHelpers:\n  - core#slice#repeatby\n  - core#slice#times\n  - core#slice#repeat\nposition: 225\n---\n\nBuilds a slice by calling the callback N times with the current index. The callback can return an error to stop iteration immediately.\n\n```go\nresult, err := lo.RepeatByErr(5, func(i int) (int, error) {\n    return i * i, nil\n})\n// []int{0, 1, 4, 9, 16}, <nil>\n```\n\nExample with error:\n\n```go\nresult, err := lo.RepeatByErr(5, func(i int) (int, error) {\n    if i == 3 {\n        return 0, fmt.Errorf(\"number 3 is not allowed\")\n    }\n    return i * i, nil\n})\n// []int(nil), error(\"number 3 is not allowed\")\n```\n"
  },
  {
    "path": "docs/data/core-replace.md",
    "content": "---\nname: Replace\nslug: replace\nsourceRef: slice.go#L684\ncategory: core\nsubCategory: slice\nplayUrl: https://go.dev/play/p/XfPzmf9gql6\nvariantHelpers:\n  - core#slice#replace\nsimilarHelpers:\n  - core#string#replace\n  - core#string#replaceall\n  - core#slice#fill\n  - core#slice#splice\n  - core#slice#slice\nposition: 0\nsignatures:\n  - \"func Replace[T comparable, Slice ~[]T](collection Slice, old T, nEw T, n int) Slice\"\n---\n\nReturns a copy of the slice with the first n non-overlapping instances of old replaced by new.\n\n```go\nin := []int{0, 1, 0, 1, 2, 3, 0}\nlo.Replace(in, 0, 42, 2)\n// []int{42, 1, 42, 1, 2, 3, 0}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-replaceall.md",
    "content": "---\nname: ReplaceAll\nslug: replaceall\nsourceRef: slice.go#L700\ncategory: core\nsubCategory: slice\nplayUrl: https://go.dev/play/p/a9xZFUHfYcV\nvariantHelpers:\n  - core#slice#replaceall\nsimilarHelpers:\n  - core#slice#replace\n  - core#slice#map\n  - core#slice#filtermap\nposition: 0\nsignatures:\n  - \"func ReplaceAll[T comparable, Slice ~[]T](collection Slice, old T, nEw T) Slice\"\n---\n\nReturns a copy of the slice with all non-overlapping instances of old replaced by new.\n\n```go\nin := []int{0, 1, 0, 1, 2, 3, 0}\nlo.ReplaceAll(in, 0, 42)\n// []int{42, 1, 42, 1, 2, 3, 42}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-reverse.md",
    "content": "---\nname: Reverse\nslug: reverse\nsourceRef: slice.go#L331\ncategory: core\nsubCategory: slice\nplayUrl: https://go.dev/play/p/iv2e9jslfBM\nvariantHelpers:\n  - core#slice#reverse\nsimilarHelpers:\n  - mutable#slice#reverse\n  - core#slice#drop\n  - core#slice#dropright\n  - core#slice#slice\n  - core#slice#flatten\nposition: 190\nsignatures:\n  - \"func Reverse[T any, Slice ~[]T](collection Slice) Slice\"\n---\n\nReverses a slice in place. Deprecated: use `mutable.Reverse`.\n\n\n"
  },
  {
    "path": "docs/data/core-runelength.md",
    "content": "---\nname: RuneLength\nslug: runelength\nsourceRef: string.go#L160\ncategory: core\nsubCategory: string\nplayUrl: https://go.dev/play/p/BXT52mBk0zO\nvariantHelpers:\n  - core#string#runelength\nsimilarHelpers:\n  - core#string#substring\n  - core#string#chunkstring\n  - core#string#words\n  - core#string#capitalize\n  - core#string#ellipsis\nposition: 30\nsignatures:\n  - \"func RuneLength(str string) int\"\n---\n\nReturns the number of runes (Unicode code points) in a string.\n\n```go\nlo.RuneLength(\"hellô\")\n// 5\n```\n\n\n"
  },
  {
    "path": "docs/data/core-sample.md",
    "content": "---\nname: Sample\nslug: sample\nsourceRef: find.go#L662\ncategory: core\nsubCategory: find\nplayUrl: https://go.dev/play/p/vCcSJbh5s6l\nvariantHelpers:\n  - core#find#sample\nsimilarHelpers:\n  - core#find#samples\n  - core#find#samplesby\n  - core#find#shuffle\nposition: 350\nsignatures:\n  - \"func Sample[T any](collection []T) T\"\n---\n\nReturns a random item from a collection.\n\n```go\nv := lo.Sample(\n    []int{10, 20, 30},\n)\n```\n\n\n"
  },
  {
    "path": "docs/data/core-sampleby.md",
    "content": "---\nname: SampleBy\nslug: sampleby\nsourceRef: find.go#L669\ncategory: core\nsubCategory: find\nplayUrl: https://go.dev/play/p/HDmKmMgq0XN\nvariantHelpers:\n  - core#find#sampleby\nsimilarHelpers:\n  - core#find#sample\n  - core#find#samples\n  - core#find#samplesby\n  - core#find#shuffle\nposition: 360\nsignatures:\n  - \"func SampleBy[T any](collection []T, randomIntGenerator randomIntGenerator) T\"\n---\n\nReturns a random item from a collection, using the provided random index generator.\n\n```go\nv := lo.SampleBy([]int{10, 20, 30}, func(n int) int {\n    return 0\n})\n// v == 10\n```\n\n\n"
  },
  {
    "path": "docs/data/core-samples.md",
    "content": "---\nname: Samples\nslug: samples\nsourceRef: find.go#L679\ncategory: core\nsubCategory: find\nplayUrl: https://go.dev/play/p/QYRD8aufD0C\nvariantHelpers:\n  - core#find#samples\nsimilarHelpers:\n  - core#find#sample\n  - core#find#samplesby\n  - core#find#shuffle\nposition: 370\nsignatures:\n  - \"func Samples[T any, Slice ~[]T](collection Slice, count int) Slice\"\n---\n\nReturns N random unique items from a collection.\n\n```go\nv := lo.Samples(\n    []int{10, 20, 30},\n    2,\n)\n```\n\n\n"
  },
  {
    "path": "docs/data/core-samplesby.md",
    "content": "---\nname: SamplesBy\nslug: samplesby\nsourceRef: find.go#L686\ncategory: core\nsubCategory: find\nplayUrl: https://go.dev/play/p/Dy9bGDhD_Gw\nvariantHelpers:\n  - core#find#samplesby\nsimilarHelpers:\n  - core#find#sample\n  - core#find#samples\n  - core#find#shuffle\nposition: 380\nsignatures:\n  - \"func SamplesBy[T any, Slice ~[]T](collection Slice, count int, randomIntGenerator randomIntGenerator) Slice\"\n---\n\nReturns N random unique items from a collection, using the provided random index generator.\n\n```go\nv := lo.SamplesBy(\n    []int{10, 20, 30},\n    2,\n    func(n int) int {\n        return 0\n    },\n)\n```\n\n\n"
  },
  {
    "path": "docs/data/core-shuffle.md",
    "content": "---\nname: Shuffle\nslug: shuffle\nsourceRef: slice.go#L322\ncategory: core\nsubCategory: slice\nplayUrl: https://go.dev/play/p/whgrQWwOy-j\nvariantHelpers:\n  - core#slice#shuffle\nsimilarHelpers:\n  - mutable#slice#shuffle\n  - core#slice#sample\n  - core#slice#samples\n  - core#slice#sampleby\n  - core#slice#samplesby\nposition: 180\nsignatures:\n  - \"func Shuffle[T any, Slice ~[]T](collection Slice) Slice\"\n---\n\nReturns a slice of shuffled values (Fisher–Yates). Deprecated: use `mutable.Shuffle`.\n\n\n"
  },
  {
    "path": "docs/data/core-slice.md",
    "content": "---\nname: Slice\nslug: slice\nsourceRef: slice.go#L658\ncategory: core\nsubCategory: slice\nplayUrl: https://go.dev/play/p/8XWYhfMMA1h\nvariantHelpers:\n  - core#slice#slice\nsimilarHelpers:\n  - core#slice#subset\n  - core#slice#drop\n  - core#slice#dropright\n  - core#slice#splice\n  - core#slice#replace\nposition: 0\nsignatures:\n  - \"func Slice[T any, Slice ~[]T](collection Slice, start int, end int) Slice\"\n---\n\nReturns a copy of a slice from `start` up to, but not including, `end`. Like `slice[start:end]`, but does not panic on overflow.\n\n```go\nin := []int{0, 1, 2, 3, 4}\nlo.Slice(in, 2, 6)\n// []int{2, 3, 4}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-slicetochannel.md",
    "content": "---\nname: SliceToChannel\nslug: slicetochannel\nsourceRef: channel.go#L18\ncategory: core\nsubCategory: channel\nsignatures:\n  - \"func SliceToChannel[T any](bufferSize int, collection []T) <-chan T\"\nsimilarHelpers:\n  - core#channel#channeltoslice\n  - core#channel#buffer\n  - it#channel#seqtochannel\n  - it#channel#channeltoseq\nposition: 251\n---\n\nSliceToChannel converts a slice to a channel with specified buffer size.\n\n```go\nitems := []int{1, 2, 3, 4, 5}\nch := lo.SliceToChannel(10, items)\n\nfor item := range ch {\n    fmt.Println(item)\n}\n// Prints 1, 2, 3, 4, 5\n```"
  },
  {
    "path": "docs/data/core-slicetomap.md",
    "content": "---\nname: SliceToMap\nslug: slicetomap\nsourceRef: slice.go#L405\ncategory: core\nsubCategory: slice\nplayUrl: https://go.dev/play/p/WHa2CfMO3Lr\nvariantHelpers:\n  - core#slice#slicetomap\n  - core#slice#associate\n  - core#slice#associatei\nsimilarHelpers:\n  - core#slice#filterslicetomap\n  - core#slice#keyby\n  - core#slice#groupby\n  - core#slice#groupbymap\nposition: 250\nsignatures:\n  - \"func SliceToMap[T any, K comparable, V any](collection []T, transform func(item T) (K, V)) map[K]V\"\n  - \"func Associate[T any, K comparable, V any](collection []T, transform func(item T) (K, V)) map[K]V\"\n  - \"func AssociateI[T any, K comparable, V any](collection []T, transform func(item T, index int) (K, V)) map[K]V\"\n---\n\nAlias of Associate: transforms a slice into a map using a key/value transform function.\n\n```go\ntype foo struct {\n    baz string\n    bar int\n}\n\nin := []*foo{{baz: \"apple\", bar: 1}, {baz: \"banana\", bar: 2}}\n\nm := lo.SliceToMap(in, func(f *foo) (string, int) {\n    return f.baz, f.bar\n})\n// map[string]int{\"apple\": 1, \"banana\": 2}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-sliding.md",
    "content": "---\nname: Sliding\nslug: sliding\nsourceRef: slice.go#L313\ncategory: core\nsubCategory: slice\nvariantHelpers:\n  - core#slice#sliding\nplayUrl: https://go.dev/play/p/aIIU6gWxl2T\nsimilarHelpers:\n  - core#slice#window\n  - core#slice#chunk\n  - core#slice#partitionby\n  - core#slice#flatten\n  - it#sequence#sliding\nposition: 150\nsignatures:\n  - \"func Sliding[T any, Slice ~[]T](collection Slice, size, step int) []Slice\"\n---\n\nCreates a slice of sliding windows of a given size with a given step. If step is equal to size, windows don't overlap (similar to Chunk). If step is less than size, windows overlap.\n\n```go\n// Overlapping windows (step < size)\nlo.Sliding([]int{1, 2, 3, 4, 5, 6}, 3, 1)\n// [][]int{{1, 2, 3}, {2, 3, 4}, {3, 4, 5}, {4, 5, 6}}\n\n// Non-overlapping windows (step == size, like Chunk)\nlo.Sliding([]int{1, 2, 3, 4, 5, 6}, 3, 3)\n// [][]int{{1, 2, 3}, {4, 5, 6}}\n\n// Step > size (skipping elements)\nlo.Sliding([]int{1, 2, 3, 4, 5, 6, 7, 8}, 2, 3)\n// [][]int{{1, 2}, {4, 5}, {7, 8}}\n```\n\n"
  },
  {
    "path": "docs/data/core-snakecase.md",
    "content": "---\nname: SnakeCase\nslug: snakecase\nsourceRef: string.go#L200\ncategory: core\nsubCategory: string\nplayUrl: https://go.dev/play/p/ziB0V89IeVH\nvariantHelpers:\n  - core#string#snakecase\nsimilarHelpers:\n  - core#string#pascalcase\n  - core#string#camelcase\n  - core#string#kebabcase\n  - core#string#capitalize\n  - core#string#words\nposition: 70\nsignatures:\n  - \"func SnakeCase(str string) string\"\n---\n\nConverts a string to snake_case.\n\n```go\nlo.SnakeCase(\"HelloWorld\")\n// \"hello_world\"\n```\n\n\n"
  },
  {
    "path": "docs/data/core-some.md",
    "content": "---\nname: Some\nslug: some\nsourceRef: intersect.go#L54\ncategory: core\nsubCategory: intersect\nplayUrl: https://go.dev/play/p/Lj4ceFkeT9V\nvariantHelpers:\n  - core#intersect#some\nsimilarHelpers:\n  - core#intersect#someby\n  - core#intersect#every\n  - core#intersect#everyby\n  - core#intersect#none\n  - core#intersect#noneby\n  - core#intersect#contains\n  - core#intersect#containsby\nposition: 40\nsignatures:\n  - \"func Some[T comparable](collection []T, subset []T) bool\"\n---\n\nReturns true if at least one element of a subset is contained in a collection. Returns false for an empty subset.\n\n```go\nok := lo.Some([]int{0, 1, 2, 3, 4, 5}, []int{0, 6})\n// true\n```\n\n\n"
  },
  {
    "path": "docs/data/core-someby.md",
    "content": "---\nname: SomeBy\nslug: someby\nsourceRef: intersect.go#L67\ncategory: core\nsubCategory: intersect\nplayUrl: https://go.dev/play/p/DXF-TORBudx\nvariantHelpers:\n  - core#intersect#someby\nsimilarHelpers:\n  - core#intersect#some\n  - core#intersect#everyby\n  - core#intersect#every\n  - core#intersect#noneby\n  - core#intersect#none\n  - core#intersect#containsby\n  - core#intersect#contains\nposition: 50\nsignatures:\n  - \"func SomeBy[T any](collection []T, predicate func(item T) bool) bool\"\n---\n\nReturns true if the predicate returns true for any element in the collection. Returns false for an empty collection.\n\n```go\nok := lo.SomeBy(\n    []int{1, 2, 3, 4},\n    func(x int) bool {\n        return x < 3\n    },\n)\n// true\n```\n\n\n"
  },
  {
    "path": "docs/data/core-splice.md",
    "content": "---\nname: Splice\nslug: splice\nsourceRef: slice.go#L748\ncategory: core\nsubCategory: slice\nplayUrl: https://go.dev/play/p/G5_GhkeSUBA\nvariantHelpers:\n  - core#slice#splice\nsimilarHelpers:\n  - core#slice#slice\n  - core#slice#drop\n  - core#slice#dropright\n  - core#slice#insert\nposition: 0\nsignatures:\n  - \"func Splice[T any, Slice ~[]T](collection Slice, i int, elements ...T) Slice\"\n---\n\nInserts multiple elements at the specified index, with support for negative indices and automatic bounds handling. Negative indices count from the end (-1 means before last element), and indices beyond the slice length append to the end.\n\n```go\n// Basic insertion at position 1\nresult := lo.Splice([]string{\"a\", \"b\"}, 1, \"1\", \"2\")\n// result: []string{\"a\", \"1\", \"2\", \"b\"}\n\n// Negative index: -1 means before the last element\nresult = lo.Splice([]string{\"a\", \"b\"}, -1, \"1\", \"2\")\n// result: []string{\"a\", \"1\", \"2\", \"b\"}\n\n// Index overflow: when index > len(slice), elements are appended\nresult = lo.Splice([]string{\"a\", \"b\"}, 42, \"1\", \"2\")\n// result: []string{\"a\", \"b\", \"1\", \"2\"}\n\n// Insert at beginning (index 0)\nresult = lo.Splice([]int{3, 4, 5}, 0, 1, 2)\n// result: []int{1, 2, 3, 4, 5}\n\n// Insert before last element with negative index\nresult = lo.Splice([]int{1, 2, 3}, -2, 99)\n// result: []int{1, 99, 2, 3}\n\n// No elements to insert returns original slice\nresult = lo.Splice([]string{\"a\", \"b\"}, 1)\n// result: []string{\"a\", \"b\"}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-subset.md",
    "content": "---\nname: Subset\nslug: subset\nsourceRef: slice.go#L635\ncategory: core\nsubCategory: slice\nplayUrl: https://go.dev/play/p/tOQu1GhFcog\nvariantHelpers:\n  - core#slice#subset\nsimilarHelpers:\n  - core#slice#slice\n  - core#slice#chunk\n  - core#slice#drop\n  - core#slice#dropright\nposition: 0\nsignatures:\n  - \"func Subset[T any, Slice ~[]T](collection Slice, offset int, length uint) Slice\"\n---\n\nReturns a copy of a slice from `offset` up to `length` elements. Like `slice[start:start+length]`, but does not panic on overflow.\n\n```go\nin := []int{0, 1, 2, 3, 4}\nlo.Subset(in, 2, 3)\n// []int{2, 3, 4}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-substring.md",
    "content": "---\nname: Substring\nslug: substring\nsourceRef: string.go#L105\ncategory: core\nsubCategory: string\nplayUrl: https://go.dev/play/p/emzCC9zBjHu\nvariantHelpers:\n  - core#string#substring\nsimilarHelpers:\n  - core#string#chunkstring\n  - core#string#runelength\n  - core#string#ellipsis\n  - core#string#words\n  - core#slice#replace\n  - core#slice#replaceall\nposition: 10\nsignatures:\n  - \"func Substring[T ~string](str T, offset int, length uint) T\"\n---\n\nReturns a substring starting at the given offset with the specified length. Supports negative offsets; out-of-bounds are clamped. Operates on Unicode runes (characters) and is optimized for zero allocations.\n\n```go\n// Basic usage\nresult := lo.Substring(\"hello\", 2, 3)\n// result: \"llo\"\n\n// Negative offset - counts from end\nresult = lo.Substring(\"hello\", -4, 3)\n// result: \"ell\"\n\n// Length longer than string - clamped to available characters\nresult = lo.Substring(\"hello\", 1, 10)\n// result: \"ello\" (only 4 characters available from position 1)\n\n// Zero length - returns empty string\nresult = lo.Substring(\"hello\", 1, 0)\n// result: \"\"\n\n// Offset beyond string length - returns empty string\nresult = lo.Substring(\"hello\", 10, 3)\n// result: \"\"\n\n// With Unicode strings (rune-aware)\nresult = lo.Substring(\"héllo\", 1, 3)\n// result: \"él\"\n\n// Negative offset with negative values clamped\nresult = lo.Substring(\"hello\", -10, 3)\n// result: \"hel\" (offset clamped to 0)\n```\n\n\n"
  },
  {
    "path": "docs/data/core-sum.md",
    "content": "---\nname: Sum\nslug: sum\nsourceRef: math.go#L70\ncategory: core\nsubCategory: math\nplayUrl: https://go.dev/play/p/upfeJVqs4Bt\nvariantHelpers:\n  - core#math#sum\nsimilarHelpers:\n  - core#math#product\n  - core#math#mean\n  - core#math#sumby\n  - core#math#productby\n  - core#math#meanby\n  - core#find#min\n  - core#find#max\n  - core#find#minby\n  - core#find#maxby\n  - core#math#mode\nposition: 40\nsignatures:\n  - \"func Sum[T constraints.Float | constraints.Integer | constraints.Complex](collection []T) T\"\n---\n\nSums the values in a collection. Returns 0 for an empty collection.\n\n```go\nlo.Sum([]int{1, 2, 3, 4, 5})\n// 15\n```\n\n\n"
  },
  {
    "path": "docs/data/core-sumby.md",
    "content": "---\nname: SumBy\nslug: sumby\nsourceRef: math.go#L80\ncategory: core\nsubCategory: math\nplayUrl: https://go.dev/play/p/Dz_a_7jN_ca\nvariantHelpers:\n  - core#math#sumby\nsimilarHelpers:\n  - core#math#sum\n  - core#math#sumbyerr\n  - core#math#productby\n  - core#math#meanby\n  - core#math#product\n  - core#math#mean\nposition: 50\nsignatures:\n  - \"func SumBy[T any, R constraints.Float | constraints.Integer | constraints.Complex](collection []T, iteratee func(item T) R) R\"\n---\n\nSums the values computed by a predicate across a collection. Returns 0 for an empty collection.\n\n```go\nstrings := []string{\"foo\", \"bar\"}\nlo.SumBy(strings, func(item string) int {\n    return len(item)\n})\n// 6\n```\n\n```go\n// See also: SumByErr for error handling\nstrings := []string{\"foo\", \"bar\", \"baz\"}\nsum, err := lo.SumByErr(strings, func(item string) (int, error) {\n    if item == \"bar\" {\n        return 0, fmt.Errorf(\"invalid item: %s\", item)\n    }\n    return len(item), nil\n})\n// sum: 3, err: invalid item: bar\n```\n"
  },
  {
    "path": "docs/data/core-sumbyerr.md",
    "content": "---\nname: SumByErr\nslug: sumbyerr\nsourceRef: math.go#L102\ncategory: core\nsubCategory: math\nvariantHelpers:\n  - core#math#sumbyerr\nsimilarHelpers:\n  - core#math#sumby\n  - core#math#sum\n  - core#math#productby\n  - core#math#meanby\nposition: 50\nsignatures:\n  - \"func SumByErr[T any, R constraints.Float | constraints.Integer | constraints.Complex](collection []T, iteratee func(item T) (R, error)) (R, error)\"\n---\n\nSums the values computed by a predicate across a collection, stopping early and returning an error if the predicate returns one. Returns 0 for an empty collection.\n\n```go\nstrings := []string{\"foo\", \"bar\", \"baz\"}\nsum, err := lo.SumByErr(strings, func(item string) (int, error) {\n    if item == \"bar\" {\n        return 0, fmt.Errorf(\"invalid item: %s\", item)\n    }\n    return len(item), nil\n})\n// sum: 3, err: invalid item: bar\n```\n\n```go\nstrings := []string{\"foo\", \"bar\"}\nsum, err := lo.SumByErr(strings, func(item string) (int, error) {\n    return len(item), nil\n})\n// sum: 6, err: nil\n```\n\n```go\nstrings := []string{}\nsum, err := lo.SumByErr(strings, func(item string) (int, error) {\n    return len(item), nil\n})\n// sum: 0, err: nil\n```\n"
  },
  {
    "path": "docs/data/core-switch.md",
    "content": "---\nname: Switch\nslug: switch\nsourceRef: condition.go#L101\ncategory: core\nsubCategory: condition\nplayUrl: https://go.dev/play/p/TGbKUMAeRUd\nvariantHelpers:\n  - core#condition#switch\n  - core#condition#case\n  - core#condition#casef\n  - core#condition#default\n  - core#condition#defaultf\nsimilarHelpers:\n  - core#condition#if\n  - core#condition#ternary\n  - core#condition#validate\nposition: 20\nsignatures:\n  - \"func Switch[T comparable, R any](predicate T) *switchCase[T, R]\"\n  - \"func (s *switchCase[T, R]) Case(val T, result R) *switchCase[T, R]\"\n  - \"func (s *switchCase[T, R]) CaseF(val T, callback func() R) *switchCase[T, R]\"\n  - \"func (s *switchCase[T, R]) Default(result R) R\"\n  - \"func (s *switchCase[T, R]) DefaultF(callback func() R) R\"\n---\n\nStarts a functional switch/case/default chain using a predicate value.\n\n```go\nresult := lo.Switch(2).Case(1, \"1\").Case(2, \"2\").Default(\"3\")\n// \"2\"\n```\n\n### Case\n\nAdds a Case branch to a Switch chain returning a constant result.\n\n```go\nresult := lo.Switch(1).Case(1, \"1\").Default(\"?\")\n// \"1\"\n```\n\n### CaseF\n\nAdds a Case branch that lazily computes its result.\n\n```go\nresult := lo.Switch(2).CaseF(2, func() string {\n    return \"2\"\n}).Default(\"?\")\n// \"2\"\n```\n\n### Default\n\nCompletes the Switch chain by providing a default result when no Case matched.\n\n```go\nresult := lo.Switch(42).Default(\"none\")\n// \"none\"\n```\n\n### DefaultF\n\nFunction form of Default. Lazily computes the default result when no Case matched.\n\n```go\nresult := lo.Switch(0).Case(1, \"1\").DefaultF(func() string {\n    return \"3\"\n})\n// \"3\"\n```\n\n\n"
  },
  {
    "path": "docs/data/core-synchronize.md",
    "content": "---\nname: Synchronize\nslug: synchronize\nsourceRef: concurrency.go#L21\ncategory: core\nsubCategory: concurrency\nplayUrl: https://go.dev/play/p/X3cqROSpQmu\nvariantHelpers:\n  - core#concurrency#synchronize\nsimilarHelpers:\n  - core#retry#newtransaction\n  - core#concurrency#asyncx\n  - core#concurrency#waitfor\nposition: 0\nsignatures:\n  - \"func Synchronize(opt ...sync.Locker) *synchronize\"\n---\n\nWraps a callback in a mutex to ensure sequential execution. Optionally accepts a custom locker.\n\n```go\ns := lo.Synchronize()\nfor i := 0; i < 10; i++ {\n    go s.Do(func() { println(\"sequential\") })\n}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-take.md",
    "content": "---\nname: Take\nslug: take\nsourceRef: slice.go#L587\ncategory: core\nsubCategory: slice\nvariantHelpers:\n  - core#slice#take\nsimilarHelpers:\n  - core#slice#takewhile\n  - core#slice#drop\n  - core#slice#dropright\n  - core#slice#dropwhile\n  - core#slice#first\n  - core#slice#filtermap\n  - core#slice#takefilter\n  - it#sequence#take\nposition: 175\nsignatures:\n  - \"func Take[T any, Slice ~[]T](collection Slice, n int) Slice\"\n---\n\nTakes the first n elements from a slice.\n\n```go\nlo.Take([]int{0, 1, 2, 3, 4, 5}, 3)\n// []int{0, 1, 2}\n\nlo.Take([]int{0, 1, 2}, 5)\n// []int{0, 1, 2}\n```\n\n"
  },
  {
    "path": "docs/data/core-takefilter.md",
    "content": "---\nname: TakeFilter\nslug: takefilter\nsourceRef: slice.go#L643\ncategory: core\nsubCategory: slice\nvariantHelpers:\n  - core#slice#takefilter\nplayUrl: https://go.dev/play/p/l99lvN4gReF\nsimilarHelpers:\n  - core#slice#filter\n  - core#slice#take\n  - core#slice#takewhile\n  - core#slice#filtermap\n  - core#slice#filterreject\n  - it#sequence#takefilter\nposition: 125\nsignatures:\n  - \"func TakeFilter[T any, Slice ~[]T](collection Slice, n int, predicate func(item T, index int) bool) Slice\"\n---\n\nFilters elements and takes the first n elements that match the predicate. Equivalent to calling Take(Filter(...)), but more efficient as it stops after finding n matches.\n\n```go\nlo.TakeFilter([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 3, func(val int, index int) bool {\n    return val%2 == 0\n})\n// []int{2, 4, 6}\n\nlo.TakeFilter([]string{\"a\", \"aa\", \"aaa\", \"aaaa\"}, 2, func(val string, index int) bool {\n    return len(val) > 1\n})\n// []string{\"aa\", \"aaa\"}\n```\n"
  },
  {
    "path": "docs/data/core-takewhile.md",
    "content": "---\nname: TakeWhile\nslug: takewhile\nsourceRef: slice.go#L605\ncategory: core\nsubCategory: slice\nvariantHelpers:\n  - core#slice#takewhile\nplayUrl: https://go.dev/play/p/NJkLGvyRWm4\nsimilarHelpers:\n  - core#slice#take\n  - core#slice#dropwhile\n  - core#slice#droprightwhile\n  - core#slice#filter\n  - core#slice#takefilter\n  - core#slice#first\n  - it#sequence#takewhile\nposition: 195\nsignatures:\n  - \"func TakeWhile[T any, Slice ~[]T](collection Slice, predicate func(item T) bool) Slice\"\n---\n\nTakes elements from the beginning while the predicate returns true.\n\n```go\nlo.TakeWhile([]int{0, 1, 2, 3, 4, 5}, func(val int) bool {\n    return val < 3\n})\n// []int{0, 1, 2}\n\nlo.TakeWhile([]string{\"a\", \"aa\", \"aaa\", \"aa\"}, func(val string) bool {\n    return len(val) <= 2\n})\n// []string{\"a\", \"aa\"}\n```\n\n"
  },
  {
    "path": "docs/data/core-ternary.md",
    "content": "---\nname: Ternary\nslug: ternary\nsourceRef: condition.go#L6\ncategory: core\nsubCategory: condition\nplayUrl: https://go.dev/play/p/t-D7WBL44h2\nvariantHelpers:\n  - core#condition#ternary\n  - core#condition#ternaryf\nsimilarHelpers:\n  - core#condition#if\n  - core#condition#switch\n  - core#condition#validate\n  - core#function#partialx\nposition: 0\nsignatures:\n  - \"func Ternary[T any](condition bool, ifOutput T, elseOutput T) T\"\n  - \"func TernaryF[T any](condition bool, ifFunc func() T, elseFunc func() T) T\"\n---\n\nA single-line if/else that returns `ifOutput` when condition is true, otherwise `elseOutput`.\n\n```go\nresult := lo.Ternary(true, \"a\", \"b\")\n// result: \"a\"\n\nresult = lo.Ternary(false, \"a\", \"b\")\n// result: \"b\"\n\n// With numbers\nage := 25\nstatus := lo.Ternary(age >= 18, \"adult\", \"minor\")\n// status: \"adult\"\n\n// With complex expressions\nx, y := 10, 20\nmax := lo.Ternary(x > y, x, y)\n// max: 20\n```\n\n### TernaryF - Function Form\n\nFunction form of Ternary. Lazily evaluates the selected branch to avoid unnecessary work or nil dereferences.\n\n```go\nvar s *string\nstr := lo.TernaryF(s == nil, func() string {\n    return uuid.New().String()\n}, func() string {\n    return *s\n})\n// str: newly generated UUID (since s is nil)\n\n// Example with expensive operations\nstr = \"hello\"\nresult := lo.TernaryF(s != nil, func() string {\n    return *s // safe dereference only when s is not nil\n}, func() string {\n    return \"default value\"\n})\n// result: \"hello\"\n\n// Performance benefit - only executes needed branch\nresult = lo.TernaryF(false, func() string {\n    time.Sleep(1 * time.Second) // this won't execute\n    return \"slow operation\"\n}, func() string {\n    return \"fast operation\" // only this executes\n})\n// result: \"fast operation\" (returns immediately)\n```\n\n\n"
  },
  {
    "path": "docs/data/core-times.md",
    "content": "---\nname: Times\nslug: times\nsourceRef: slice.go#L127\ncategory: core\nsubCategory: slice\nplayUrl: https://go.dev/play/p/vgQj3Glr6lT\nvariantHelpers:\n  - core#slice#times\nsimilarHelpers:\n  - core#slice#foreach\n  - core#slice#repeat\n  - core#slice#repeatby\n  - parallel#slice#times\nposition: 90\nsignatures:\n  - \"func Times[T any](count int, iteratee func(index int) T) []T\"\n---\n\nInvokes the predicate n times, returning a slice of results. The predicate receives the index on each call.\n\n```go\nlo.Times(3, func(i int) string {\n    return strconv.Itoa(i)\n})\n// []string{\"0\", \"1\", \"2\"}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-toanyslice.md",
    "content": "---\nname: ToAnySlice\nslug: toanyslice\nsourceRef: type_manipulation.go#L107\ncategory: core\nsubCategory: type\nsignatures:\n  - \"func ToAnySlice[T any](collection []T) []any\"\nvariantHelpers:\n  - core#type#toanyslice\nsimilarHelpers:\n  - core#type#fromanyslice\n  - core#type#tosliceptr\n  - core#type#fromsliceptr\nposition: 126\n---\n\nConverts a typed slice to a slice of empty interface values (any). This is useful when working with heterogeneous data.\n\n```go\nints := []int{1, 2, 3}\nresult := lo.ToAnySlice(ints)\n// []any{1, 2, 3}\n\nstrings := []string{\"a\", \"b\", \"c\"}\nresult = lo.ToAnySlice(strings)\n// []any{\"a\", \"b\", \"c\"}\n\ncustom := []struct{ Name string }{{Name: \"Alice\"}, {Name: \"Bob\"}}\nresult = lo.ToAnySlice(custom)\n// []any{struct{ Name string }{Name: \"Alice\"}, struct{ Name string }{Name: \"Bob\"}}\n```"
  },
  {
    "path": "docs/data/core-topairs.md",
    "content": "---\nname: ToPairs\nslug: topairs\nsourceRef: map.go#L195\ncategory: core\nsubCategory: map\nplayUrl: https://go.dev/play/p/3Dhgx46gawJ\nvariantHelpers:\n  - core#map#topairs\nsimilarHelpers:\n  - core#map#entries\n  - core#map#fromentries\n  - core#map#frompairs\nposition: 130\nsignatures:\n  - \"func ToPairs[K comparable, V any](in map[K]V) []Entry[K, V]\"\n---\n\nTransforms a map into a slice of key/value pairs. Alias of `Entries`.\n\n```go\npairs := lo.ToPairs(map[string]int{\"foo\": 1, \"bar\": 2})\n// []lo.Entry[string, int]{...}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-toptr.md",
    "content": "---\nname: ToPtr\nslug: toptr\nsourceRef: type_manipulation.go#L28\ncategory: core\nsubCategory: type\nsignatures:\n  - \"func ToPtr[T any](x T) *T\"\nvariantHelpers:\n  - core#type#toptr\nsimilarHelpers:\n  - core#type#fromptr\n  - core#type#fromptror\n  - core#type#emptyabletoptr\n  - core#type#tosliceptr\n  - core#type#fromsliceptr\nposition: 90\n---\n\nReturns a pointer to the provided value.\n\n```go\nptr := lo.ToPtr(42)\n// *int pointing to 42\n\nptr = lo.ToPtr(\"hello\")\n// *string pointing to \"hello\"\n\nptr = lo.ToPtr([]int{1, 2, 3})\n// *[]int pointing to []int{1, 2, 3}\n```"
  },
  {
    "path": "docs/data/core-tosliceptr.md",
    "content": "---\nname: ToSlicePtr\nslug: tosliceptr\nsourceRef: type_manipulation.go#L73\ncategory: core\nsubCategory: type\nsignatures:\n  - \"func ToSlicePtr[T any](collection []T) []*T\"\nvariantHelpers:\n  - core#type#tosliceptr\nsimilarHelpers:\n  - core#type#toptr\n  - core#type#fromptr\n  - core#type#fromptror\n  - core#type#emptyabletoptr\n  - core#type#fromsliceptr\nposition: 110\n---\n\nConverts a slice of values to a slice of pointers to those values.\n\n```go\nslice := []int{1, 2, 3}\nptrs := lo.ToSlicePtr(slice)\n// []*int{&1, &2, &3}\n\nslice = []string{\"a\", \"b\", \"c\"}\nptrs = lo.ToSlicePtr(slice)\n// []*string{&\"a\", &\"b\", &\"c\"}\n\nslice = []int{}\nptrs = lo.ToSlicePtr(slice)\n// []*int{}\n```"
  },
  {
    "path": "docs/data/core-trim.md",
    "content": "---\nname: Trim\nslug: trim\nsourceRef: slice.go#L842\ncategory: core\nsubCategory: slice\nplayUrl: https://go.dev/play/p/LZLfLj5C8Lg\nvariantHelpers:\n  - core#slice#trim\nsimilarHelpers:\n  - core#slice#trimleft\n  - core#slice#trimright\n  - core#slice#trimprefix\n  - core#slice#trimsuffix\nposition: 0\nsignatures:\n  - \"func Trim[T comparable, Slice ~[]T](collection Slice, cutset Slice) Slice\"\n---\n\nRemoves all leading and trailing elements in the cutset from the collection.\n\n```go\nresult := lo.Trim([]int{0, 1, 2, 0, 3, 0}, []int{1, 0})\n// []int{2, 0, 3}\n\nresult = lo.Trim([]string{\"hello\", \"world\", \" \"}, []string{\" \", \"\"})\n// []string{\"hello\", \"world\"}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-trimleft.md",
    "content": "---\nname: TrimLeft\nslug: trimleft\nsourceRef: slice.go#L847\ncategory: core\nsubCategory: slice\nplayUrl: https://go.dev/play/p/fJK-AhROy9w\nvariantHelpers:\n  - core#slice#trimleft\nsimilarHelpers:\n  - core#slice#trim\n  - core#slice#trimright\n  - core#slice#trimprefix\n  - core#slice#trimsuffix\nposition: 0\nsignatures:\n  - \"func TrimLeft[T comparable, Slice ~[]T](collection Slice, cutset Slice) Slice\"\n---\n\nRemoves all leading elements found in the cutset from the collection.\n\n```go\nresult := lo.TrimLeft([]int{0, 1, 2, 0, 3, 0}, []int{1, 0})\n// []int{2, 0, 3, 0}\n\nresult = lo.TrimLeft([]string{\"hello\", \"world\", \" \"}, []string{\" \", \"\"})\n// []string{\"hello\", \"world\", \" \"}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-trimprefix.md",
    "content": "---\nname: TrimPrefix\nslug: trimprefix\nsourceRef: slice.go#L858\ncategory: core\nsubCategory: slice\nplayUrl: https://go.dev/play/p/8O2RoWYzi8J\nvariantHelpers:\n  - core#slice#trimprefix\nsimilarHelpers:\n  - core#slice#trim\n  - core#slice#trimleft\n  - core#slice#trimright\n  - core#slice#trimsuffix\nposition: 0\nsignatures:\n  - \"func TrimPrefix[T comparable, Slice ~[]T](collection Slice, prefix Slice) Slice\"\n---\n\nRemoves all leading occurrences of the given prefix from the collection.\n\n```go\nresult := lo.TrimPrefix([]int{1, 2, 1, 2, 3, 1, 2, 4}, []int{1, 2})\n// []int{3, 1, 2, 4}\n\nresult = lo.TrimPrefix([]string{\"hello\", \"world\", \"hello\", \"test\"}, []string{\"hello\"})\n// []string{\"world\", \"hello\", \"test\"}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-trimright.md",
    "content": "---\nname: TrimRight\nslug: trimright\nsourceRef: slice.go#L873\ncategory: core\nsubCategory: slice\nplayUrl: https://go.dev/play/p/9V_N8sRyyiZ\nvariantHelpers:\n  - core#slice#trimright\nsimilarHelpers:\n  - core#slice#trim\n  - core#slice#trimleft\n  - core#slice#trimprefix\n  - core#slice#trimsuffix\nposition: 0\nsignatures:\n  - \"func TrimRight[T comparable, Slice ~[]T](collection Slice, cutset Slice) Slice\"\n---\n\nRemoves all trailing elements found in the cutset from the collection.\n\n```go\nresult := lo.TrimRight([]int{0, 1, 2, 0, 3, 0}, []int{0, 3})\n// []int{0, 1, 2}\n\nresult = lo.TrimRight([]string{\"hello\", \"world\", \"  \"}, []string{\" \", \"\"})\n// []string{\"hello\", \"world\", \"\"}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-trimsuffix.md",
    "content": "---\nname: TrimSuffix\nslug: trimsuffix\nsourceRef: slice.go#L884\ncategory: core\nsubCategory: slice\nplayUrl: https://go.dev/play/p/IjEUrV0iofq\nvariantHelpers:\n  - core#slice#trimsuffix\nsimilarHelpers:\n  - core#slice#trim\n  - core#slice#trimleft\n  - core#slice#trimright\n  - core#slice#trimprefix\nposition: 0\nsignatures:\n  - \"func TrimSuffix[T comparable, Slice ~[]T](collection Slice, suffix Slice) Slice\"\n---\n\nRemoves all trailing occurrences of the given suffix from the collection.\n\n```go\nresult := lo.TrimSuffix([]int{1, 2, 3, 1, 2, 4, 2, 4, 2, 4}, []int{2, 4})\n// []int{1, 2, 3, 1}\n\nresult = lo.TrimSuffix([]string{\"hello\", \"world\", \"hello\", \"test\"}, []string{\"test\"})\n// []string{\"hello\", \"world\", \"hello\"}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-trycatch.md",
    "content": "---\nname: TryCatch\nslug: trycatch\nsourceRef: errors.go#L335\ncategory: core\nsubCategory: error-handling\nplayUrl: https://go.dev/play/p/PnOON-EqBiU\nvariantHelpers:\n  - core#error-handling#trycatch\nsimilarHelpers:\n  - core#error-handling#validate\n  - core#error-handling#mustx\n  - core#error-handling#tryx\n  - core#error-handling#tryorx\n  - core#error-handling#trywitherrorvalue\n  - core#error-handling#trycatchwitherrorvalue\n  - core#error-handling#errorsas\n  - core#error-handling#assert\nposition: 50\nsignatures:\n  - \"func TryCatch(callback func() error, catch func())\"\n---\n\nCalls the catch function when the callback errors or panics.\n\n```go\ncaught := false\nlo.TryCatch(func() error { panic(\"error\") }, func() { caught = true })\n// caught == true\n```\n\n\n"
  },
  {
    "path": "docs/data/core-trycatchwitherrorvalue.md",
    "content": "---\nname: TryCatchWithErrorValue\nslug: trycatchwitherrorvalue\nsourceRef: errors.go#L343\ncategory: core\nsubCategory: error-handling\nplayUrl: https://go.dev/play/p/8Pc9gwX_GZO\nvariantHelpers:\n  - core#error-handling#trycatchwitherrorvalue\nsimilarHelpers:\n  - core#error-handling#validate\n  - core#error-handling#mustx\n  - core#error-handling#tryx\n  - core#error-handling#tryorx\n  - core#error-handling#trywitherrorvalue\n  - core#error-handling#trycatch\n  - core#error-handling#errorsas\n  - core#error-handling#assert\nposition: 60\nsignatures:\n  - \"func TryCatchWithErrorValue(callback func() error, catch func(any))\"\n---\n\nCalls the catch function with the error value when the callback errors or panics.\n\n```go\nlo.TryCatchWithErrorValue(\n    func() error {\n        panic(\"error\")\n    },\n    func(val any) {\n        fmt.Println(val)\n    },\n)\n```\n\n"
  },
  {
    "path": "docs/data/core-tryorx.md",
    "content": "---\nname: TryOrX\nslug: tryorx\nsourceRef: errors.go#L197\ncategory: core\nsubCategory: error-handling\nsignatures:\n  - \"func TryOr[A any](callback func() (A, error), fallbackA A) (A, bool)\"\n  - \"func TryOr1[A any](callback func() (A, error), fallbackA A) (A, bool)\"\n  - \"func TryOr2[A, B any](callback func() (A, B, error), fallbackA A, fallbackB B) (A, B, bool)\"\n  - \"func TryOr3[A, B, C any](callback func() (A, B, C, error), fallbackA A, fallbackB B, fallbackC C) (A, B, C, bool)\"\n  - \"func TryOr4[A, B, C, D any](callback func() (A, B, C, D, error), fallbackA A, fallbackB B, fallbackC C, fallbackD D) (A, B, C, D, bool)\"\n  - \"func TryOr5[A, B, C, D, E any](callback func() (A, B, C, D, E, error), fallbackA A, fallbackB B, fallbackC C, fallbackD D, fallbackE E) (A, B, C, D, E, bool)\"\n  - \"func TryOr6[A, B, C, D, E, F any](callback func() (A, B, C, D, E, F, error), fallbackA A, fallbackB B, fallbackC C, fallbackD D, fallbackE E, fallbackF F) (A, B, C, D, E, F, bool)\"\nplayUrl: https://go.dev/play/p/B4F7Wg2Zh9X\nvariantHelpers:\n  - core#error-handling#tryor\n  - core#error-handling#tryorx\nsimilarHelpers:\n  - core#error-handling#validate\n  - core#error-handling#mustx\n  - core#error-handling#tryx\n  - core#error-handling#trycatch\n  - core#error-handling#trywitherrorvalue\n  - core#error-handling#errorsas\n  - core#error-handling#assert\nposition: 30\n---\n\nLike Try, but returns provided fallback values in case of error; also returns a success flag. Variants cover callbacks returning 1 to 6 values.\n\n```go\nvalue, ok := lo.TryOr(func() (int, error) {\n    return 0, fmt.Errorf(\"boom\")\n}, 123)\n// value == 123, ok == false\n\nvalue, ok = lo.TryOr(func() (int, error) {\n    return 42, nil\n}, 0)\n// value == 42, ok == true\n```\n"
  },
  {
    "path": "docs/data/core-trywitherrorvalue.md",
    "content": "---\nname: TryWithErrorValue\nslug: trywitherrorvalue\nsourceRef: errors.go#L314\ncategory: core\nsubCategory: error-handling\nplayUrl: https://go.dev/play/p/Kc7afQIT2Fs\nvariantHelpers:\n  - core#error-handling#trywitherrorvalue\nsimilarHelpers:\n  - core#error-handling#validate\n  - core#error-handling#mustx\n  - core#error-handling#tryx\n  - core#error-handling#tryorx\n  - core#error-handling#trycatch\n  - core#error-handling#trycatchwitherrorvalue\n  - core#error-handling#errorsas\n  - core#error-handling#assert\nposition: 40\nsignatures:\n  - \"func TryWithErrorValue(callback func() error) (errorValue any, ok bool)\"\n---\n\nRuns a function and returns the error value (panic or error) along with a boolean indicating success.\n\n```go\nerr, ok := lo.TryWithErrorValue(func() error { panic(\"error\") })\n// err == \"error\", ok == false\n```\n\n\n"
  },
  {
    "path": "docs/data/core-tryx.md",
    "content": "---\nname: TryX\nslug: tryx\nsourceRef: errors.go#L118\ncategory: core\nsubCategory: error-handling\nsignatures:\n  - \"func Try(callback func() error) bool\"\n  - \"func Try0(callback func()) bool\"\n  - \"func Try1(callback func() error) bool\"\n  - \"func Try2[T any](callback func() (T, error)) bool\"\n  - \"func Try3[T, R any](callback func() (T, R, error)) bool\"\n  - \"func Try4[T, R, S any](callback func() (T, R, S, error)) bool\"\n  - \"func Try5[T, R, S, Q any](callback func() (T, R, S, Q, error)) bool\"\n  - \"func Try6[T, R, S, Q, U any](callback func() (T, R, S, Q, U, error)) bool\"\nplayUrl: https://go.dev/play/p/mTyyWUvn9u4\nvariantHelpers:\n  - core#error-handling#try\n  - core#error-handling#tryx\nsimilarHelpers:\n  - core#error-handling#validate\n  - core#error-handling#mustx\n  - core#error-handling#tryorx\n  - core#error-handling#trycatch\n  - core#error-handling#trywitherrorvalue\n  - core#error-handling#errorsas\n  - core#error-handling#assert\nposition: 20\n---\n\nCalls a function and returns false in case of error or panic. Variants cover callbacks returning 0 to 6 values.\n\n```go\nok := lo.Try(func() error {\n    // return an error to mark failure\n    return fmt.Errorf(\"boom\")\n})\n// ok == false\n\nok = lo.Try0(func() {\n    // panics are caught and return false\n    panic(\"boom\")\n})\n// ok == false\n\nok = lo.Try2(func() (int, error) {\n    return 42, nil\n})\n// ok == true\n```\n\n\n"
  },
  {
    "path": "docs/data/core-tuplex.md",
    "content": "---\nname: TupleX\nslug: tuplex\nsourceRef: tuples.go#L5\ncategory: core\nsubCategory: tuple\nsignatures:\n  - \"func T2[A, B any](a A, b B) lo.Tuple2[A, B]\"\n  - \"func T3[A, B, C any](a A, b B, c C) lo.Tuple3[A, B, C]\"\n  - \"func T4[A, B, C, D any](a A, b B, c C, d D) lo.Tuple4[A, B, C, D]\"\n  - \"func T5[A, B, C, D, E any](a A, b B, c C, d D, e E) lo.Tuple5[A, B, C, D, E]\"\n  - \"func T6[A, B, C, D, E, F any](a A, b B, c C, d D, e E, f F) lo.Tuple6[A, B, C, D, E, F]\"\n  - \"func T7[A, B, C, D, E, F, G any](a A, b B, c C, d D, e E, f F, g G) lo.Tuple7[A, B, C, D, E, F, G]\"\n  - \"func T8[A, B, C, D, E, F, G, H any](a A, b B, c C, d D, e E, f F, g G, h H) lo.Tuple8[A, B, C, D, E, F, G, H]\"\n  - \"func T9[A, B, C, D, E, F, G, H, I any](a A, b B, c C, d D, e E, f F, g G, h H, i I) lo.Tuple9[A, B, C, D, E, F, G, H, I]\"\nplayUrl: https://go.dev/play/p/IllL3ZO4BQm\nvariantHelpers:\n  - core#tuple#tx\n  - core#tuple#tuplex\nsimilarHelpers:\n  - core#tuple#unpackx\n  - core#tuple#zipx\n  - core#tuple#zipbyx\n  - core#tuple#unzipx\n  - core#tuple#unzipbyx\nposition: 0\n---\n\nConstructors for tuple values from 2 up to 9 elements.\n\nVariants: `T2..T9`\n\n```go\nt := lo.T3(1, \"a\", true)\n// lo.Tuple3[int, string, bool]{A:1, B:\"a\", C:true}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-union.md",
    "content": "---\nname: Union\nslug: union\nsourceRef: intersect.go#L157\ncategory: core\nsubCategory: intersect\nplayUrl: https://go.dev/play/p/-hsqZNTH0ej\nvariantHelpers:\n  - core#intersect#union\nsimilarHelpers:\n  - core#intersect#intersect\n  - core#intersect#difference\n  - core#intersect#without\n  - core#slice#uniq\n  - core#slice#uniqby\nposition: 100\nsignatures:\n  - \"func Union[T comparable, Slice ~[]T](lists ...Slice) Slice\"\n---\n\nReturns all distinct elements from given collections while preserving relative order.\n\n```go\nlo.Union([]int{0, 1, 2, 3, 4, 5}, []int{0, 2}, []int{0, 10})\n// []int{0, 1, 2, 3, 4, 5, 10}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-uniq.md",
    "content": "---\nname: Uniq\nslug: uniq\nsourceRef: slice.go#L140\ncategory: core\nsubCategory: slice\nplayUrl: https://go.dev/play/p/DTzbeXZ6iEN\nvariantHelpers:\n  - core#slice#uniq\nsimilarHelpers:\n  - core#slice#uniqby\n  - core#slice#uniqmap\n  - core#slice#uniqkeys\n  - core#slice#uniqvalues\nposition: 100\nsignatures:\n  - \"func Uniq[T comparable, Slice ~[]T](collection Slice) Slice\"\n---\n\nReturns a duplicate-free version of a slice, keeping only the first occurrence of each value. Order is preserved.\n\n```go\nlo.Uniq([]int{1, 2, 2, 1})\n// []int{1, 2}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-uniqby.md",
    "content": "---\nname: UniqBy\nslug: uniqby\nsourceRef: slice.go#L160\ncategory: core\nsubCategory: slice\nplayUrl: https://go.dev/play/p/g42Z3QSb53u\nvariantHelpers:\n  - core#slice#uniqby\nsimilarHelpers:\n  - core#slice#uniqbyerr\n  - core#slice#uniq\n  - core#slice#uniqmap\n  - core#slice#partitionby\nposition: 110\nsignatures:\n  - \"func UniqBy[T any, U comparable, Slice ~[]T](collection Slice, iteratee func(item T) U) Slice\"\n---\n\nReturns a duplicate-free version of a slice based on a computed key. Keeps only the first element for each unique key.\n\n```go\nlo.UniqBy(\n    []int{0, 1, 2, 3, 4, 5},\n    func(i int) int {\n        return i % 3\n    },\n)\n// []int{0, 1, 2}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-uniqbyerr.md",
    "content": "---\nname: UniqByErr\nslug: uniqbyerr\nsourceRef: slice.go#L240\ncategory: core\nsubCategory: slice\nsignatures:\n  - \"func UniqByErr[T any, U comparable, Slice ~[]T](collection Slice, iteratee func(item T) (U, error)) (Slice, error)\"\nvariantHelpers:\n  - core#slice#uniqbyerr\nsimilarHelpers:\n  - core#slice#uniqby\n  - core#slice#uniq\n  - core#slice#uniqmap\n  - core#slice#partitionby\nposition: 111\n---\n\nReturns a duplicate-free version of a slice based on a computed key using an iteratee that can return an error. Stops iteration immediately when an error is encountered. Keeps only the first element for each unique key.\n\n```go\n// Error case - stops on first error\nresult, err := lo.UniqByErr([]int{0, 1, 2, 3, 4, 5}, func(i int) (int, error) {\n    if i == 3 {\n        return 0, fmt.Errorf(\"number 3 is not allowed\")\n    }\n    return i % 3, nil\n})\n// []int(nil), error(\"number 3 is not allowed\")\n```\n\n```go\n// Success case\nresult, err := lo.UniqByErr([]int{0, 1, 2, 3, 4, 5}, func(i int) (int, error) {\n    return i % 3, nil\n})\n// []int{0, 1, 2}, nil\n```\n"
  },
  {
    "path": "docs/data/core-uniqkeys.md",
    "content": "---\nname: UniqKeys\nslug: uniqkeys\nsourceRef: map.go#L23\ncategory: core\nsubCategory: map\nplayUrl: https://go.dev/play/p/TPKAb6ILdHk\nvariantHelpers:\n  - core#map#uniqkeys\nsimilarHelpers:\n  - core#map#keys\n  - core#map#values\n  - core#map#uniqvalues\nposition: 10\nsignatures:\n  - \"func UniqKeys[K comparable, V any](in ...map[K]V) []K\"\n---\n\nCreates a slice of unique map keys across one or more maps.\n\n```go\nkeys := lo.UniqKeys(map[string]int{\"foo\": 1, \"bar\": 2}, map[string]int{\"bar\": 3})\n// []string{\"foo\", \"bar\"}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-uniqmap.md",
    "content": "---\nname: UniqMap\nslug: uniqmap\nsourceRef: slice.go#L38\ncategory: core\nsubCategory: slice\nplayUrl: https://go.dev/play/p/fygzLBhvUdB\nvariantHelpers:\n  - core#slice#uniqmap\nsimilarHelpers:\n  - core#slice#uniq\n  - core#slice#uniqby\n  - core#slice#map\n  - core#slice#filtermap\nposition: 20\nsignatures:\n  - \"func UniqMap[T any, R comparable](collection []T, transform func(item T, index int) R) []R\"\n---\n\nManipulates a slice and transforms it to a slice of another type with unique values.\n\n```go\ntype User struct {\n    Name string\n    Age  int\n}\n\nusers := []User{{Name: \"Alex\", Age: 10}, {Name: \"Alex\", Age: 12}, {Name: \"Bob\", Age: 11}, {Name: \"Alice\", Age: 20}}\n\nnames := lo.UniqMap(users, func(u User, index int) string {\n    return u.Name\n})\n// []string{\"Alex\", \"Bob\", \"Alice\"}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-uniqvalues.md",
    "content": "---\nname: UniqValues\nslug: uniqvalues\nsourceRef: map.go#L72\ncategory: core\nsubCategory: map\nplayUrl: https://go.dev/play/p/nf6bXMh7rM3\nvariantHelpers:\n  - core#map#uniqvalues\nsimilarHelpers:\n  - core#map#values\n  - core#map#uniqkeys\n  - core#slice#uniq\nposition: 40\nsignatures:\n  - \"func UniqValues[K comparable, V comparable](in ...map[K]V) []V\"\n---\n\nCreates a slice of unique map values across one or more maps.\n\n```go\nvalues := lo.UniqValues(map[string]int{\"foo\": 1, \"bar\": 2}, map[string]int{\"bar\": 2})\n// []int{1, 2}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-unpackx.md",
    "content": "---\nname: UnpackX\nslug: unpackx\nsourceRef: tuples.go#L53\ncategory: core\nsubCategory: tuple\nsignatures:\n  - \"func Unpack2[A, B any](tuple Tuple2[A, B]) (A, B)\"\nplayUrl: https://go.dev/play/p/xVP_k0kJ96W\nvariantHelpers:\n  - core#tuple#unpackx\nsimilarHelpers:\n  - core#tuple#tuplex\n  - core#tuple#zipx\n  - core#tuple#zipbyx\n  - core#tuple#unzipx\n  - core#tuple#unzipbyx\nposition: 10\n---\n\nExtracts values from tuples. Variants support tuple sizes from 2 to 9.\n\nVariants: `Unpack2..Unpack9`\n\n```go\na, b, c := lo.Unpack3(lo.T3(1, \"a\", true))\n```\n\n\n"
  },
  {
    "path": "docs/data/core-unzipbyerrx.md",
    "content": "---\nname: UnzipByErrX\nslug: unzipbyerrx\nsourceRef: tuples.go#L1024\ncategory: core\nsubCategory: tuple\nsignatures:\n  - \"func UnzipByErr2[In any, A any, B any](items []In, predicate func(In) (a A, b B, err error)) ([]A, []B, error)\"\n  - \"func UnzipByErr3[In any, A any, B any, C any](items []In, predicate func(In) (a A, b B, c C, err error)) ([]A, []B, []C, error)\"\n  - \"func UnzipByErr4[In any, A any, B any, C any, D any](items []In, predicate func(In) (a A, b B, c C, d D, err error)) ([]A, []B, []C, []D, error)\"\n  - \"func UnzipByErr5[In any, A any, B any, C any, D any, E any](items []In, predicate func(In) (a A, b B, c C, d D, e E, err error)) ([]A, []B, []C, []D, []E, error)\"\n  - \"func UnzipByErr6[In any, A any, B any, C any, D any, E any, F any](items []In, predicate func(In) (a A, b B, c C, d D, e E, f F, err error)) ([]A, []B, []C, []D, []E, []F, error)\"\n  - \"func UnzipByErr7[In any, A any, B any, C any, D any, E any, F any, G any](items []In, predicate func(In) (a A, b B, c C, d D, e E, f F, g G, err error)) ([]A, []B, []C, []D, []E, []F, []G, error)\"\n  - \"func UnzipByErr8[In any, A any, B any, C any, D any, E any, F any, G any, H any](items []In, predicate func(In) (a A, b B, c C, d D, e E, f F, g G, h H, err error)) ([]A, []B, []C, []D, []E, []F, []G, []H, error)\"\n  - \"func UnzipByErr9[In any, A any, B any, C any, D any, E any, F any, G any, H any, I any](items []In, predicate func(In) (a A, b B, c C, d D, e E, f F, g G, h H, i I, err error)) ([]A, []B, []C, []D, []E, []F, []G, []H, []I, error)\"\nplayUrl: https://go.dev/play/p/G2pyXQa1SUD\nvariantHelpers:\n  - core#tuple#unzipbyerrx\nsimilarHelpers:\n  - core#tuple#unzipbyx\n  - core#tuple#tuplex\n  - core#slice#map\nposition: 41\n---\n\nTransforms each input element into a tuple and splits results into parallel slices. The iteratee can return an error to stop iteration immediately. Variants support arities from 2 to 9.\n\nVariants: `UnzipByErr2..UnzipByErr9`\n\n```go\na, b, err := lo.UnzipByErr2([]string{\"hello\", \"error\", \"world\"}, func(str string) (string, int, error) {\n    if str == \"error\" {\n        return \"\", 0, fmt.Errorf(\"error string not allowed\")\n    }\n    return str, len(str), nil\n})\n// []string{}\n// []int{}\n// error string not allowed\n```\n\nOn error, all result slices are `nil` and iteration stops immediately.\n"
  },
  {
    "path": "docs/data/core-unzipbyx.md",
    "content": "---\nname: UnzipByX\nslug: unzipbyx\nsourceRef: tuples.go#L698\ncategory: core\nsubCategory: tuple\nsignatures:\n  - \"func UnzipBy2[In any, A any, B any](items []In, predicate func(In) (a A, b B)) ([]A, []B)\"\n  - \"func UnzipBy3[In any, A any, B any, C any](items []In, predicate func(In) (a A, b B, c C)) ([]A, []B, []C)\"\n  - \"func UnzipBy4[In any, A any, B any, C any, D any](items []In, predicate func(In) (a A, b B, c C, d D)) ([]A, []B, []C, []D)\"\n  - \"func UnzipBy5[In any, A any, B any, C any, D any, E any](items []In, predicate func(In) (a A, b B, c C, d D, e E)) ([]A, []B, []C, []D, []E)\"\n  - \"func UnzipBy6[In any, A any, B any, C any, D any, E any, F any](items []In, predicate func(In) (a A, b B, c C, d D, e E, f F)) ([]A, []B, []C, []D, []E, []F)\"\n  - \"func UnzipBy7[In any, A any, B any, C any, D any, E any, F any, G any](items []In, predicate func(In) (a A, b B, c C, d D, e E, f F, g G)) ([]A, []B, []C, []D, []E, []F, []G)\"\n  - \"func UnzipBy8[In any, A any, B any, C any, D any, E any, F any, G any, H any](items []In, predicate func(In) (a A, b B, c C, d D, e E, f F, g G, h H)) ([]A, []B, []C, []D, []E, []F, []G, []H)\"\n  - \"func UnzipBy9[In any, A any, B any, C any, D any, E any, F any, G any, H any, I any](items []In, predicate func(In) (a A, b B, c C, d D, e E, f F, g G, h H, i I)) ([]A, []B, []C, []D, []E, []F, []G, []H, []I)\"\nplayUrl: https://go.dev/play/p/tN8yqaRZz0r\nvariantHelpers:\n  - core#tuple#unzipbyx\nsimilarHelpers:\n  - core#tuple#tuplex\n  - core#tuple#unpackx\n  - core#tuple#zipx\n  - core#tuple#zipbyx\n  - core#tuple#unzipx\n  - core#tuple#unzipbyerrx\n  - core#slice#map\n  - core#slice#filtermap\nposition: 40\n---\n\nTransforms each input element into a tuple and splits results into parallel slices. Variants support arities from 2 to 9.\n\nVariants: `UnzipBy2..UnzipBy9`\n\n```go\ntype User struct{ ID int; Name string }\nids, names := lo.UnzipBy2([]User{{1,\"a\"},{2,\"b\"}}, func(u User) (int, string) {\n    return u.ID, u.Name\n})\n```\n\n\n"
  },
  {
    "path": "docs/data/core-unzipx.md",
    "content": "---\nname: UnzipX\nslug: unzipx\nsourceRef: tuples.go#L514\ncategory: core\nsubCategory: tuple\nsignatures:\n  - \"func Unzip2[A, B any](tuples []Tuple2[A, B]) ([]A, []B)\"\n  - \"func Unzip3[A, B, C any](tuples []Tuple3[A, B, C]) ([]A, []B, []C)\"\n  - \"func Unzip4[A, B, C, D any](tuples []Tuple4[A, B, C, D]) ([]A, []B, []C, []D)\"\n  - \"func Unzip5[A, B, C, D, E any](tuples []Tuple5[A, B, C, D, E]) ([]A, []B, []C, []D, []E)\"\n  - \"func Unzip6[A, B, C, D, E, F any](tuples []Tuple6[A, B, C, D, E, F]) ([]A, []B, []C, []D, []E, []F)\"\n  - \"func Unzip7[A, B, C, D, E, F, G any](tuples []Tuple7[A, B, C, D, E, F, G]) ([]A, []B, []C, []D, []E, []F, []G)\"\n  - \"func Unzip8[A, B, C, D, E, F, G, H any](tuples []Tuple8[A, B, C, D, E, F, G, H]) ([]A, []B, []C, []D, []E, []F, []G, []H)\"\n  - \"func Unzip9[A, B, C, D, E, F, G, H, I any](tuples []Tuple9[A, B, C, D, E, F, G, H, I]) ([]A, []B, []C, []D, []E, []F, []G, []H, []I)\"\nplayUrl: https://go.dev/play/p/K-vG9tyD3Kf\nvariantHelpers:\n  - core#tuple#unzipx\nsimilarHelpers:\n  - core#tuple#tuplex\n  - core#tuple#unpackx\n  - core#tuple#zipx\n  - core#tuple#zipbyx\n  - core#tuple#unzipbyx\n  - core#slice#mapkeys\n  - core#slice#mapvalues\nposition: 30\n---\n\nSplits a slice of tuples back into multiple parallel slices. Variants support tuple sizes from 2 to 9.\n\nVariants: `Unzip2..Unzip9`\n\n```go\npairs := []lo.Tuple2[int, string]{\n  lo.T2(1, \"a\"),\n  lo.T2(2, \"b\"),\n}\nxs, ys := lo.Unzip2(pairs)\n```\n\n\n"
  },
  {
    "path": "docs/data/core-validate.md",
    "content": "---\nname: Validate\nslug: validate\nsourceRef: errors.go#L13\ncategory: core\nsubCategory: error-handling\nplayUrl: https://go.dev/play/p/vPyh51XpCBt\nvariantHelpers:\n  - core#error-handling#validate\nsimilarHelpers:\n  - core#error-handling#mustx\n  - core#error-handling#tryx\n  - core#error-handling#tryorx\n  - core#error-handling#assert\nposition: 0\nsignatures:\n  - \"func Validate(ok bool, format string, args ...any) error\"\n---\n\nCreates an error when a condition is not met; returns nil when it is.\n\n```go\nslice := []string{\"a\"}\n\nerr := lo.Validate(len(slice) == 0, \"Slice should be empty\")\n// error(\"Slice should be empty\")\n\nerr := lo.Validate(len(slice) == 0, \"Slice should be empty but contains %v\", slice)\n// error(\"Slice should be empty but contains [a]\")\n```\n\n\n"
  },
  {
    "path": "docs/data/core-valueor.md",
    "content": "---\nname: ValueOr\nslug: valueor\nsourceRef: map.go#L97\ncategory: core\nsubCategory: map\nplayUrl: https://go.dev/play/p/bAq9mHErB4V\nvariantHelpers:\n  - core#map#valueor\nsimilarHelpers:\n  - core#map#haskey\n  - core#map#keys\n  - core#map#values\nposition: 50\nsignatures:\n  - \"func ValueOr[K comparable, V any](in map[K]V, key K, fallback V) V\"\n---\n\nReturns the value for a key or a fallback if the key is not present.\n\n```go\nvalue := lo.ValueOr(map[string]int{\"foo\": 1, \"bar\": 2}, \"foo\", 42)\n// 1\n\nvalue = lo.ValueOr(map[string]int{\"foo\": 1, \"bar\": 2}, \"baz\", 42)\n// 42\n```\n\n\n"
  },
  {
    "path": "docs/data/core-values.md",
    "content": "---\nname: Values\nslug: values\nsourceRef: map.go#L54\ncategory: core\nsubCategory: map\nplayUrl: https://go.dev/play/p/nnRTQkzQfF6\nvariantHelpers:\n  - core#map#values\nsimilarHelpers:\n  - core#map#keys\n  - core#map#entries\n  - core#map#topairs\n  - core#map#frompairs\n  - core#map#uniqvalues\nposition: 30\nsignatures:\n  - \"func Values[K comparable, V any](in ...map[K]V) []V\"\n---\n\nCreates a slice of the map values across one or more maps.\n\n```go\nvalues := lo.Values(map[string]int{\"foo\": 1, \"bar\": 2})\n// []int{1, 2}\n\nvalues = lo.Values(map[string]int{\"foo\": 1}, map[string]int{\"bar\": 2})\n// []int{1, 2}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-waitfor.md",
    "content": "---\nname: WaitFor\nslug: waitfor\nsourceRef: concurrency.go#L112\ncategory: core\nsubCategory: concurrency\nplayUrl: https://go.dev/play/p/t_wTDmubbK3\nvariantHelpers:\n  - core#concurrency#waitfor\n  - core#concurrency#waitforwithcontext\nsimilarHelpers:\n  - core#retry#attemptwithdelay\n  - core#retry#attemptwhilewithdelay\n  - core#time#durationx\nposition: 20\nsignatures:\n  - \"func WaitFor(condition func(i int) bool, timeout time.Duration, heartbeatDelay time.Duration) (totalIterations int, elapsed time.Duration, conditionFound bool)\"\n  - \"func WaitForWithContext(ctx context.Context, condition func(ctx context.Context, i int) bool, timeout time.Duration, heartbeatDelay time.Duration) (totalIterations int, elapsed time.Duration, conditionFound bool)\"\n---\n\nRuns periodically until a condition is validated. Use WaitFor for simple predicates, or WaitForWithContext when you need context cancellation/timeout inside the predicate. Both return total iterations, elapsed time, and whether the condition became true.\n\n```go\niterations, elapsed, ok := lo.WaitFor(\n    func(i int) bool {\n        return i > 5\n    },\n    10*time.Millisecond,\n    time.Millisecond,\n)\n```\n\nWith context:\n\n```go\niterations, elapsed, ok := lo.WaitForWithContext(\n    context.Background(),\n    func(_ context.Context, i int) bool {\n        return i >= 5\n    },\n    10*time.Millisecond,\n    time.Millisecond,\n)\n```\n\n\n"
  },
  {
    "path": "docs/data/core-window.md",
    "content": "---\nname: Window\nslug: window\nsourceRef: slice.go#L289\ncategory: core\nsubCategory: slice\nvariantHelpers:\n  - core#slice#window\nsimilarHelpers:\n  - core#slice#sliding\n  - core#slice#chunk\n  - core#slice#partitionby\n  - core#slice#flatten\n  - it#sequence#window\nposition: 145\nsignatures:\n  - \"func Window[T any, Slice ~[]T](collection Slice, size int) []Slice\"\n---\n\nCreates a slice of sliding windows of a given size. Each window overlaps with the previous one by size-1 elements. This is equivalent to `Sliding(collection, size, 1)`.\n\n```go\nlo.Window([]int{1, 2, 3, 4, 5}, 3)\n// [][]int{{1, 2, 3}, {2, 3, 4}, {3, 4, 5}}\n\nlo.Window([]float64{20, 22, 21, 23, 24}, 3)\n// [][]float64{{20, 22, 21}, {22, 21, 23}, {21, 23, 24}}\n```\n\n"
  },
  {
    "path": "docs/data/core-without.md",
    "content": "---\nname: Without\nslug: without\nsourceRef: intersect.go#L181\ncategory: core\nsubCategory: intersect\nplayUrl: https://go.dev/play/p/PcAVtYJsEsS\nvariantHelpers:\n  - core#intersect#without\nsimilarHelpers:\n  - core#intersect#withoutby\n  - core#intersect#intersect\n  - core#intersect#difference\n  - core#intersect#union\n  - core#slice#reject\nposition: 110\nsignatures:\n  - \"func Without[T comparable, Slice ~[]T](collection Slice, exclude ...T) Slice\"\n---\n\nReturns a slice excluding all given values.\n\n```go\nlo.Without([]int{0, 2, 10}, 2)\n// []int{0, 10}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-withoutby.md",
    "content": "---\nname: WithoutBy\nslug: withoutby\nsourceRef: intersect.go#L273\ncategory: core\nsubCategory: intersect\nplayUrl: https://go.dev/play/p/VgWJOF01NbJ\nvariantHelpers:\n  - core#intersect#withoutby\nsimilarHelpers:\n  - core#intersect#without\n  - core#intersect#difference\n  - core#slice#rejectby\n  - core#intersect#withoutbyerr\nposition: 120\nsignatures:\n  - \"func WithoutBy[T any, K comparable, Slice ~[]T](collection Slice, iteratee func(item T) K, exclude ...K) Slice\"\n---\n\nFilters a slice by excluding elements whose extracted keys match any in the exclude list.\n\n```go\ntype User struct {\n  ID int\n  Name string\n}\n\nusers := []User{\n  {1, \"Alice\"},\n  {2, \"Bob\"},\n  {3, \"Charlie\"},\n}\n\nfiltered := lo.WithoutBy(users, func(u User) int {\n    return u.ID\n}, 2, 3)\n// []User{{1, \"Alice\"}}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-withoutbyerr.md",
    "content": "---\nname: WithoutByErr\nslug: withoutbyerr\nsourceRef: intersect.go#L287\ncategory: core\nsubCategory: intersect\nsignatures:\n  - \"func WithoutByErr[T any, K comparable, Slice ~[]T](collection Slice, iteratee func(item T) (K, error), exclude ...K) (Slice, error)\"\nvariantHelpers:\n  - core#intersect#withoutbyerr\nsimilarHelpers:\n  - core#intersect#withoutby\n  - core#intersect#without\n  - core#slice#rejectbyerr\nposition: 125\n---\n\nFilters a slice by excluding elements whose extracted keys match any in the exclude list. Returns an error if the iteratee function fails, stopping iteration immediately.\n\n```go\ntype User struct {\n  ID int\n  Name string\n}\n\nusers := []User{\n  {1, \"Alice\"},\n  {2, \"Bob\"},\n  {3, \"Charlie\"},\n}\n\nfiltered, err := lo.WithoutByErr(users, func(u User) (int, error) {\n  if u.ID == 2 {\n    return 0, fmt.Errorf(\"Bob not allowed\")\n  }\n  return u.ID, nil\n}, 2, 3)\n// []User(nil), error(\"Bob not allowed\")\n```\n\n```go\ntype User struct {\n  ID int\n  Name string\n}\n\nusers := []User{\n  {1, \"Alice\"},\n  {2, \"Bob\"},\n  {3, \"Charlie\"},\n}\n\nfiltered, err := lo.WithoutByErr(users, func(u User) (int, error) {\n  return u.ID, nil\n}, 2, 3)\n// []User{{1, \"Alice\"}}, nil\n```\n"
  },
  {
    "path": "docs/data/core-withoutempty.md",
    "content": "---\nname: WithoutEmpty\nslug: withoutempty\nsourceRef: intersect.go#L218\ncategory: core\nsubCategory: intersect\nplayUrl: https://go.dev/play/p/iZvYJWuniJm\nvariantHelpers:\n  - core#intersect#withoutempty\nsimilarHelpers:\n  - core#slice#compact\n  - core#intersect#without\n  - core#intersect#withoutby\nposition: 130\nsignatures:\n  - \"func WithoutEmpty[T comparable, Slice ~[]T](collection Slice) Slice\"\n---\n\nReturns a slice excluding zero values. Deprecated: use `Compact` instead.\n\n```go\nlo.WithoutEmpty([]int{0, 2, 10})\n// []int{2, 10}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-withoutnth.md",
    "content": "---\nname: WithoutNth\nslug: withoutnth\nsourceRef: intersect.go#L223\ncategory: core\nsubCategory: intersect\nplayUrl: https://go.dev/play/p/AIro-_UtL9c\nvariantHelpers:\n  - core#intersect#withoutnth\nsimilarHelpers:\n  - core#intersect#without\n  - core#intersect#withoutby\n  - core#slice#dropbyindex\nposition: 140\nsignatures:\n  - \"func WithoutNth[T comparable, Slice ~[]T](collection Slice, nths ...int) Slice\"\n---\n\nReturns a slice excluding the elements at the given indexes.\n\n```go\nlo.WithoutNth([]int{-2, -1, 0, 1, 2}, 3)\n// []int{-2, -1, 0, 2}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-words.md",
    "content": "---\nname: Words\nslug: words\nsourceRef: string.go#L210\ncategory: core\nsubCategory: string\nplayUrl: https://go.dev/play/p/-f3VIQqiaVw\nvariantHelpers:\n  - core#string#words\nsimilarHelpers:\n  - core#string#pascalcase\n  - core#string#camelcase\n  - core#string#kebabcase\n  - core#string#snakecase\n  - core#string#capitalize\n  - core#string#chunkstring\n  - core#string#substring\nposition: 80\nsignatures:\n  - \"func Words(str string) []string\"\n---\n\nSplits a string into a slice of its words, separating letters and digits and removing non-alphanumeric separators.\n\n```go\nlo.Words(\"helloWorld\")\n// []string{\"hello\", \"world\"}\n```\n\n\n"
  },
  {
    "path": "docs/data/core-zipbyerrx.md",
    "content": "---\nname: ZipByErrX\nslug: zipbyerrx\nsourceRef: tuples.go#L444\ncategory: core\nsubCategory: tuple\nsignatures:\n  - \"func ZipByErr2[A any, B any, Out any](a []A, b []B, iteratee func(a A, b B) (Out, error)) ([]Out, error)\"\n  - \"func ZipByErr3[A any, B any, C any, Out any](a []A, b []B, c []C, iteratee func(a A, b B, c C) (Out, error)) ([]Out, error)\"\n  - \"func ZipByErr4[A any, B any, C any, D any, Out any](a []A, b []B, c []C, d []D, iteratee func(a A, b B, c C, d D) (Out, error)) ([]Out, error)\"\n  - \"func ZipByErr5[A any, B any, C any, D any, E any, Out any](a []A, b []B, c []C, d []D, e []E, iteratee func(a A, b B, c C, d D, e E) (Out, error)) ([]Out, error)\"\n  - \"func ZipByErr6[A any, B any, C any, D any, E any, F any, Out any](a []A, b []B, c []C, d []D, e []E, f []F, iteratee func(a A, b B, c C, d D, e E, f F) (Out, error)) ([]Out, error)\"\n  - \"func ZipByErr7[A any, B any, C any, D any, E any, F any, G any, Out any](a []A, b []B, c []C, d []D, e []E, f []F, g []G, iteratee func(a A, b B, c C, d D, e E, f F, g G) (Out, error)) ([]Out, error)\"\n  - \"func ZipByErr8[A any, B any, C any, D any, E any, F any, G any, H any, Out any](a []A, b []B, c []C, d []D, e []E, f []F, g []G, h []H, iteratee func(a A, b B, c C, d D, e E, f F, g G, h H) (Out, error)) ([]Out, error)\"\n  - \"func ZipByErr9[A any, B any, C any, D any, E any, F any, G any, H any, I any, Out any](a []A, b []B, c []C, d []D, e []E, f []F, g []G, h []H, i []I, iteratee func(a A, b B, c C, d D, e E, f F, g G, h H, i I) (Out, error)) ([]Out, error)\"\nvariantHelpers:\n  - core#tuple#zipbyerrx\nsimilarHelpers:\n  - core#tuple#zipbyx\nposition: 30\n---\n\nZips multiple slices and projects each grouped set through a function that can return an error. Stops iteration immediately when an error is encountered and returns the zero value (nil for slices).\n\nVariants: `ZipByErr2..ZipByErr9`\n\n```go\nresult, err := lo.ZipByErr2([]string{\"a\", \"b\"}, []int{1, 2}, func(a string, b int) (string, error) {\n    if b == 2 {\n        return \"\", fmt.Errorf(\"number 2 is not allowed\")\n    }\n    return fmt.Sprintf(\"%s-%d\", a, b), nil\n})\n// []string(nil), error(\"number 2 is not allowed\")\n```\n\n```go\nresult, err := lo.ZipByErr2([]string{\"a\", \"b\"}, []int{1, 2}, func(a string, b int) (string, error) {\n    return fmt.Sprintf(\"%s-%d\", a, b), nil\n})\n// []string{\"a-1\", \"b-2\"}, nil\n```\n\nWhen collections are different sizes, the missing attributes are filled with zero value before calling the iteratee.\n"
  },
  {
    "path": "docs/data/core-zipbyx.md",
    "content": "---\nname: ZipByX\nslug: zipbyx\nsourceRef: tuples.go#L335\ncategory: core\nsubCategory: tuple\nsignatures:\n  - \"func ZipBy2[A any, B any, Out any](a []A, b []B, predicate func(a A, b B) Out) []Out\"\n  - \"func ZipBy3[A any, B any, C any, Out any](a []A, b []B, c []C, predicate func(a A, b B, c C) Out) []Out\"\n  - \"func ZipBy4[A any, B any, C any, D any, Out any](a []A, b []B, c []C, d []D, predicate func(a A, b B, c C, d D) Out) []Out\"\n  - \"func ZipBy5[A any, B any, C any, D any, E any, Out any](a []A, b []B, c []C, d []D, e []E, predicate func(a A, b B, c C, d D, e E) Out) []Out\"\n  - \"func ZipBy6[A any, B any, C any, D any, E any, F any, Out any](a []A, b []B, c []C, d []D, e []E, f []F, predicate func(a A, b B, c C, d D, e E, f F) Out) []Out\"\n  - \"func ZipBy7[A any, B any, C any, D any, E any, F any, G any, Out any](a []A, b []B, c []C, d []D, e []E, f []F, g []G, predicate func(a A, b B, c C, d D, e E, f F, g G) Out) []Out\"\n  - \"func ZipBy8[A any, B any, C any, D any, E any, F any, G any, H any, Out any](a []A, b []B, c []C, d []D, e []E, f []F, g []G, h []H, predicate func(a A, b B, c C, d D, e E, f F, g G, h H) Out) []Out\"\n  - \"func ZipBy9[A any, B any, C any, D any, E any, F any, G any, H any, I any, Out any](a []A, b []B, c []C, d []D, e []E, f []F, g []G, h []H, i []I, predicate func(a A, b B, c C, d D, e E, f F, g G, h H, i I) Out) []Out\"\nplayUrl: https://go.dev/play/p/wlHur6yO8rR\nvariantHelpers:\n  - core#tuple#zipbyx\n  - core#tuple#zipbyerrx\nsimilarHelpers:\n  - core#tuple#tuplex\n  - core#tuple#unpackx\n  - core#tuple#zipx\n  - core#tuple#unzipx\n  - core#tuple#unzipbyx\n  - core#slice#map\n  - core#slice#filtermap\nposition: 31\n---\n\nZips multiple slices and projects each grouped set through a function. Variants support 2 up to 9 input slices.\n\nVariants: `ZipBy2..ZipBy9`\n\n```go\nxs := []int{1,2}\nys := []string{\"a\",\"b\"}\npairs := lo.ZipBy2(xs, ys, func(x int, y string) string {\n    return fmt.Sprintf(\"%d-%s\", x, y)\n})\n```\n\n\n"
  },
  {
    "path": "docs/data/core-zipx.md",
    "content": "---\nname: ZipX\nslug: zipx\nsourceRef: tuples.go#L103\ncategory: core\nsubCategory: tuple\nsignatures:\n  - \"func Zip2[A, B any](a []A, b []B) []Tuple2[A, B]\"\nplayUrl: https://go.dev/play/p/jujaA6GaJTp\nvariantHelpers:\n  - core#tuple#zipx\nsimilarHelpers:\n  - core#tuple#tuplex\n  - core#tuple#unpackx\n  - core#tuple#zipbyx\n  - core#tuple#unzipx\n  - core#tuple#unzipbyx\n  - core#slice#interleave\nposition: 20\n---\n\nZips multiple slices into a slice of tuples. Variants support 2 up to 9 input slices.\n\nVariants: `Zip2..Zip9`\n\n```go\nxs := []int{1,2}\nys := []string{\"a\",\"b\"}\npairs := lo.Zip2(xs, ys)\n```\n\n\n"
  },
  {
    "path": "docs/data/it-assign.md",
    "content": "---\nname: Assign\nslug: assign\nsourceRef: it/map.go#L122\ncategory: it\nsubCategory: map\nsignatures:\n  - \"func Assign[K comparable, V any, Map ~map[K]V](maps ...iter.Seq[Map]) Map\"\nvariantHelpers:\n  - it#map#assign\nsimilarHelpers:\n  - core#map#assign\n  - it#map#fromentries\n  - it#map#invert\nposition: 50\n---\n\nMerges multiple map sequences into a single map. Later maps overwrite values from earlier maps when keys conflict.\n\n```go\nmap1 := func(yield func(map[string]int) bool) {\n    yield(map[string]int{\"a\": 1, \"b\": 2})\n}\nmap2 := func(yield func(map[string]int) bool) {\n    yield(map[string]int{\"b\": 3, \"c\": 4})\n}\nmap3 := func(yield func(map[string]int) bool) {\n    yield(map[string]int{\"d\": 5, \"e\": 6})\n}\nresult := it.Assign(map1, map2, map3)\n// map[string]int{\"a\": 1, \"b\": 3, \"c\": 4, \"d\": 5, \"e\": 6}\n// Note: \"b\" is 3 (overwritten from map2)\n\nsingleMap := func(yield func(map[int]string) bool) {\n    yield(map[int]string{1: \"one\", 2: \"two\"})\n}\nresult = it.Assign(singleMap)\n// map[int]string{1: \"one\", 2: \"two\"}\n\nemptyMap1 := func(yield func(map[string]bool) bool) {\n    yield(map[string]bool{})\n}\nemptyMap2 := func(yield func(map[string]bool) bool) {\n    yield(map[string]bool{\"active\": true})\n}\nresult = it.Assign(emptyMap1, emptyMap2)\n// map[string]bool{\"active\": true}\n```"
  },
  {
    "path": "docs/data/it-associate.md",
    "content": "---\nname: Associate\nslug: associate\nsourceRef: it/seq.go#L412\ncategory: it\nsubCategory: map\nsignatures:\n  - \"func Associate[T any, K comparable, V any](collection iter.Seq[T], transform func(item T) (K, V)) map[K]V\"\n  - \"func AssociateI[T any, K comparable, V any](collection iter.Seq[T], transform func(item T, index int) (K, V)) map[K]V\"\n  - \"func SeqToMap[T any, K comparable, V any](collection iter.Seq[T], transform func(item T) (K, V)) map[K]V\"\n  - \"func SeqToMapI[T any, K comparable, V any](collection iter.Seq[T], transform func(item T, index int) (K, V)) map[K]V\"\n  - \"func FilterSeqToMap[T any, K comparable, V any](collection iter.Seq[T], transform func(item T) (K, V, bool)) map[K]V\"\n  - \"func FilterSeqToMapI[T any, K comparable, V any](collection iter.Seq[T], transform func(item T, index int) (K, V, bool)) map[K]V\"\nvariantHelpers:\n  - it#sequence#associate\n  - it#sequence#associatei\n  - it#sequence#seqtomap\n  - it#sequence#seqtomapi\n  - it#sequence#filterseqtomap\n  - it#sequence#filterseqtomapi\nsimilarHelpers:\n  - core#slice#associate\n  - core#map#keyby\n  - it#map#keyby\nposition: 140\n---\n\nAssociate returns a map containing key-value pairs provided by transform function applied to elements of the given sequence.\nIf any of two pairs have the same key the last one gets added to the map.\n\n```go\ncollection := func(yield func(string) bool) {\n    yield(\"apple\")\n    yield(\"banana\")\n    yield(\"cherry\")\n}\n\nresult := it.Associate(collection, func(s string) (string, int) {\n    return s, len(s)\n})\n// result contains {\"apple\": 5, \"banana\": 6, \"cherry\": 6}\n```\n\nAssociateI returns a map containing key-value pairs provided by transform function applied to elements of the given sequence, with index.\n\n```go\ncollection := func(yield func(string) bool) {\n    yield(\"a\")\n    yield(\"b\")\n    yield(\"c\")\n}\n\nresult := it.AssociateI(collection, func(item string, index int) (int, string) {\n    return index, item\n})\n// result contains {0: \"a\", 1: \"b\", 2: \"c\"}\n```\n\nSeqToMap returns a map containing key-value pairs provided by transform function applied to elements of the given sequence.\nAlias of Associate().\n\n```go\ncollection := func(yield func(int) bool) {\n    yield(1)\n    yield(2)\n    yield(3)\n}\n\nresult := it.SeqToMap(collection, func(i int) (int, string) {\n    return i, fmt.Sprintf(\"item-%d\", i)\n})\n// result contains {1: \"item-1\", 2: \"item-2\", 3: \"item-3\"}\n```\n\nFilterSeqToMap returns a map containing key-value pairs provided by transform function applied to elements of the given sequence.\nThe third return value of the transform function is a boolean that indicates whether the key-value pair should be included in the map.\n\n```go\ncollection := func(yield func(int) bool) {\n    yield(1)\n    yield(2)\n    yield(3)\n    yield(4)\n}\n\nresult := it.FilterSeqToMap(collection, func(i int) (int, string, bool) {\n    return i, fmt.Sprintf(\"item-%d\", i), i%2 == 0\n})\n// result contains {2: \"item-2\", 4: \"item-4\"}\n```"
  },
  {
    "path": "docs/data/it-buffer.md",
    "content": "---\nname: Buffer\nslug: buffer\nsourceRef: it/seq.go#L1162\ncategory: it\nsubCategory: sequence\nsignatures:\n  - \"func Buffer[T any](seq iter.Seq[T], size int) iter.Seq[[]T]\"\nplayUrl: https://go.dev/play/p/zDZdcCA20ut\nvariantHelpers:\n  - it#sequence#buffer\nsimilarHelpers:\n  - it#sequence#chunk\n  - it#sequence#sliding\n  - it#sequence#window\nposition: 65\n---\n\nReturns a sequence of slices, each containing up to size items read from the sequence.\nThe last slice may be smaller if the sequence closes before filling the buffer.\n\nExamples:\n\n```go\nseq := func(yield func(int) bool) {\n    _ = yield(1)\n    _ = yield(2)\n    _ = yield(3)\n    _ = yield(4)\n    _ = yield(5)\n    _ = yield(6)\n    _ = yield(7)\n}\nbuffers := it.Buffer(seq, 3)\nvar result [][]int\nfor buffer := range buffers {\n    result = append(result, buffer)\n}\n// result contains [[1 2 3] [4 5 6] [7]]\n```\n"
  },
  {
    "path": "docs/data/it-channelseq.md",
    "content": "---\nname: ChannelToSeq\nslug: channeltoseq\nsourceRef: it/channel.go#L39\ncategory: it\nsubCategory: channel\nsignatures:\n  - \"func ChannelToSeq[T any](ch <-chan T) iter.Seq[T]\"\nplayUrl: \"https://go.dev/play/p/IXqSs2Ooqpm\"\nvariantHelpers:\n  - it#channel#channeltoseq\nsimilarHelpers:\n  - it#channel#seqtochannel\nposition: 10\n---\n\nBuilds an `iter.Seq` from a channel. The returned sequence yields each value received from the channel in order. Iteration blocks until the channel is closed.\n\nExamples:\n\n```go\nch := make(chan int, 3)\nch <- 1; ch <- 2; ch <- 3\nclose(ch)\n\nseq := it.ChannelToSeq(ch)\nvar got []int\nfor v := range seq {\n    got = append(got, v)\n}\n// got == []int{1, 2, 3}\n```\n\n\n"
  },
  {
    "path": "docs/data/it-channeltoseq.md",
    "content": "---\nname: SeqToChannel2\nslug: channeltoseq\nsourceRef: it/channel.go#L26\ncategory: it\nsubCategory: channel\nsignatures:\n  - \"func SeqToChannel2[K, V any](bufferSize int, collection iter.Seq2[K, V]) <-chan lo.Tuple2[K, V]\"\n  - \"func ChannelToSeq[T any](ch <-chan T) iter.Seq[T]\"\nplayUrl: \"https://go.dev/play/p/IXqSs2Ooqpm\"\nvariantHelpers:\n  - it#channel#seqtochannel\n  - it#channel#seqtochannel2\n  - it#channel#channeltoseq\nsimilarHelpers:\n  - core#channel#channelseq\nposition: 10\n---\n\nSeqToChannel2 returns a read-only channel of key-value tuple elements from a sequence.\n\n```go\ncollection := func(yield func(int, string) bool) {\n    yield(1, \"a\")\n    yield(2, \"b\")\n}\n\nch := it.SeqToChannel2(10, collection)\nfor tuple := range ch {\n    fmt.Printf(\"%d: %s\\n\", tuple.A, tuple.B)\n}\n// 1: a\n// 2: b\n```\n\nChannelToSeq returns a sequence built from channel items. Blocks until channel closes.\n\n```go\nch := make(chan int, 3)\nch <- 1\nch <- 2\nch <- 3\nclose(ch)\n\nseq := it.ChannelToSeq(ch)\nfor item := range seq {\n    fmt.Println(item)\n}\n// 1\n// 2\n// 3\n```"
  },
  {
    "path": "docs/data/it-chunk.md",
    "content": "---\nname: Chunk\nslug: chunk\nsourceRef: it/seq.go#L264\ncategory: it\nsubCategory: sequence\nsignatures:\n  - \"func Chunk[T any](collection iter.Seq[T], size int) iter.Seq[[]T]\"\nplayUrl: https://go.dev/play/p/qo8esZ_L60Q\nvariantHelpers:\n  - it#sequence#chunk\nsimilarHelpers:\n  - core#slice#chunk\n  - it#sequence#partitionby\nposition: 60\n---\n\nReturns a sequence of elements split into groups of length size. The last chunk may be smaller than size.\n\nExamples:\n\n```go\nseq := func(yield func(int) bool) {\n    _ = yield(1)\n    _ = yield(2)\n    _ = yield(3)\n    _ = yield(4)\n    _ = yield(5)\n}\nchunks := it.Chunk(seq, 2)\nvar result [][]int\nfor chunk := range chunks {\n    result = append(result, chunk)\n}\n// result contains [1, 2], [3, 4], [5]\n```\n\n## Note\n\n`it.ChunkString` and `it.Chunk` functions behave inconsistently for empty input: `it.ChunkString(\"\", n)` returns `[\"\"]` instead of `[]`.\n\nSee https://github.com/samber/lo/issues/788\n"
  },
  {
    "path": "docs/data/it-chunkentries.md",
    "content": "---\nname: ChunkEntries\nslug: chunkentries\nsourceRef: it/map.go#L138\ncategory: it\nsubCategory: map\nsignatures:\n  - \"func ChunkEntries[K comparable, V any](m map[K]V, size int) iter.Seq[map[K]V]\"\nvariantHelpers:\n  - it#map#chunkentries\nsimilarHelpers:\n  - core#map#chunkentries\n  - it#sequence#chunk\n  - it#map#keys\n  - it#map#values\nposition: 60\n---\n\nChunks a map into smaller maps of the specified size. Returns a sequence of maps, each containing up to the specified number of entries.\n\n```go\noriginalMap := map[string]int{\n    \"a\": 1, \"b\": 2, \"c\": 3, \"d\": 4, \"e\": 5,\n}\nresult := it.ChunkEntries(originalMap, 2)\n// iter.Seq[map[string]int] yielding:\n// map[string]int{\"a\": 1, \"b\": 2}\n// map[string]int{\"c\": 3, \"d\": 4}\n// map[string]int{\"e\": 5}\n\nsmallMap := map[int]string{1: \"one\", 2: \"two\"}\nresult = it.ChunkEntries(smallMap, 5)\n// iter.Seq[map[int]string] yielding:\n// map[int]string{1: \"one\", 2: \"two\"}\n\nlargeMap := make(map[int]bool)\nfor i := 0; i < 10; i++ {\n    largeMap[i] = true\n}\nresult = it.ChunkEntries(largeMap, 3)\n// iter.Seq[map[int]bool] yielding 4 maps with 3, 3, 3, and 1 entries respectively\n```"
  },
  {
    "path": "docs/data/it-chunkstring.md",
    "content": "---\nname: ChunkString\nslug: chunkstring\nsourceRef: it/string.go#L130\ncategory: it\nsubCategory: string\nplayUrl: \"https://go.dev/play/p/Bcc5ixTQQoQ\"\nvariantHelpers:\n  - it#string#chunkstring\nsimilarHelpers:\n  - core#string#chunkstring\nposition: 0\nsignatures:\n  - \"func ChunkString[T ~string](str T, size int) iter.Seq[T]\"\n---\n\nReturns a sequence of chunks of length `size` from the input string. If the string length is not a multiple of `size`, the final chunk contains the remaining characters. Panics if `size <= 0`.\n\nExamples:\n\n```go\n// Even split\nseq := it.ChunkString(\"123456\", 2)\nvar out []string\nfor s := range seq { out = append(out, s) }\n// out == []string{\"12\", \"34\", \"56\"}\n```\n\n```go\n// Remainder chunk\nseq := it.ChunkString(\"1234567\", 2)\nvar out []string\nfor s := range seq { out = append(out, s) }\n// out == []string{\"12\", \"34\", \"56\", \"7\"}\n```\n\n```go\n// Empty and small inputs\nseq1 := it.ChunkString(\"\", 2)\nseq2 := it.ChunkString(\"1\", 2)\n// seq1 yields \"\"\n// seq2 yields \"1\"\n```"
  },
  {
    "path": "docs/data/it-coalesceseq.md",
    "content": "---\nname: CoalesceSeq\nslug: coalesceseq\nsourceRef: it/type_manipulation.go#L65\ncategory: it\nsubCategory: type\nsignatures:\n  - \"func CoalesceSeq[T any](v ...iter.Seq[T]) (iter.Seq[T], bool)\"\nvariantHelpers:\n  - it#type#coalesceseq\nsimilarHelpers:\n  - it#type#coalesceseqorempty\n  - core#type#coalesce\n  - core#type#coalesceslice\nposition: 100\n---\n\nReturns the first non-empty sequence from the provided arguments, with a boolean indicating if a non-empty sequence was found.\n\n```go\nemptySeq := func(yield func(int) bool) bool {\n    return false // empty sequence\n}\nnonEmptySeq := it.Range(3)\nresult, ok := it.CoalesceSeq(emptySeq, nonEmptySeq, emptySeq)\n// iter.Seq[int] yielding 0, 1, 2, true\n\nemptyStrSeq := func(yield func(string) bool) bool {\n    return false // empty sequence\n}\nstrSeq := func(yield func(string) bool) bool {\n    yield(\"a\")\n    yield(\"b\")\n    return true\n}\nresult, ok = it.CoalesceSeq(emptyStrSeq, strSeq)\n// iter.Seq[string] yielding \"a\", \"b\", true\n\nresult, ok = it.CoalesceSeq(emptySeq, emptyStrSeq)\n// nil sequence, false\n```"
  },
  {
    "path": "docs/data/it-coalesceseqorempty.md",
    "content": "---\nname: CoalesceSeqOrEmpty\nslug: coalesceseqorempty\nsourceRef: it/type_manipulation.go#L76\ncategory: it\nsubCategory: type\nsignatures:\n  - \"func CoalesceSeqOrEmpty[T any](v ...iter.Seq[T]) iter.Seq[T]\"\nvariantHelpers:\n  - it#type#coalesceseqorempty\nsimilarHelpers:\n  - it#type#coalesceseq\n  - core#type#coalesceorempty\n  - core#type#coalescesliceorempty\nposition: 102\n---\n\nReturns the first non-empty sequence from the provided arguments, or an empty sequence if all arguments are empty.\n\n```go\nemptySeq := func(yield func(int) bool) bool {\n    return false // empty sequence\n}\nnonEmptySeq := it.Range(3)\nresult := it.CoalesceSeqOrEmpty(emptySeq, nonEmptySeq, emptySeq)\n// iter.Seq[int] yielding 0, 1, 2\n\nemptyStrSeq := func(yield func(string) bool) bool {\n    return false // empty sequence\n}\nstrSeq := func(yield func(string) bool) bool {\n    yield(\"a\")\n    yield(\"b\")\n    return true\n}\nresult = it.CoalesceSeqOrEmpty(emptyStrSeq, strSeq)\n// iter.Seq[string] yielding \"a\", \"b\"\n\nresult = it.CoalesceSeqOrEmpty(emptySeq, emptyStrSeq)\n// empty sequence (yields nothing)\n```"
  },
  {
    "path": "docs/data/it-compact.md",
    "content": "---\nname: Compact\nslug: compact\nsourceRef: it/seq.go#L699\ncategory: it\nsubCategory: slice\nsignatures:\n  - \"func Compact[T comparable, I ~func(func(T) bool)](collection I) I\"\nvariantHelpers:\n  - it#slice#compact\nsimilarHelpers:\n  - core#slice#compact\nposition: 192\n---\n\nCompact returns a sequence of all non-zero elements.\n\n```go\ncollection := func(yield func(int) bool) {\n    yield(0)\n    yield(1)\n    yield(0)\n    yield(2)\n    yield(3)\n    yield(0)\n}\n\ncompacted := it.Compact(collection)\nvar result []int\nfor item := range compacted {\n    result = append(result, item)\n}\n// result contains [1, 2, 3]\n```"
  },
  {
    "path": "docs/data/it-concat.md",
    "content": "---\nname: Concat\nslug: concat\nsourceRef: it/seq.go#L358\ncategory: it\nsubCategory: sequence\nplayUrl: https://go.dev/play/p/Fa0u7xT2JOR\nvariantHelpers:\n  - it#sequence#concat\nsimilarHelpers:\n  - it#sequence#flatten\n  - core#slice#concat\nposition: 160\nsignatures:\n  - \"func Concat[T any, I ~func(func(T) bool)](collection ...I) I\"\n---\n\nReturns a sequence of all the elements in iterators. Concat conserves the order of the elements.\n\n```go\nlist1 := slices.Values([]int{0, 1, 2})\nlist2 := slices.Values([]int{3, 4, 5})\nlist3 := slices.Values([]int{6, 7, 8})\n\nresult := it.Concat(list1, list2, list3)\n\n// result: []int{0, 1, 2, 3, 4, 5, 6, 7, 8}\n```\n"
  },
  {
    "path": "docs/data/it-contains.md",
    "content": "---\nname: Contains\nslug: contains\nsourceRef: it/intersect.go#L13\ncategory: it\nsubCategory: intersect\nsignatures:\n  - \"func Contains[T comparable](collection iter.Seq[T], element T) bool\"\nplayUrl: \"https://go.dev/play/p/1edj7hH3TS2\"\nvariantHelpers:\n  - it#intersect#contains\nsimilarHelpers:\n  - core#slice#contains\n  - it#intersect#containsby\n  - it#intersect#some\nposition: 0\n---\n\nReturns true if an element is present in a collection.\n\nExamples:\n\n```go\nseq := func(yield func(int) bool) {\n    _ = yield(10)\n    _ = yield(20)\n    _ = yield(30)\n}\nhas := it.Contains(seq, 20)\n// has == true\n```\n\n```go\nseq := func(yield func(string) bool) {\n    _ = yield(\"apple\")\n    _ = yield(\"banana\")\n    _ = yield(\"cherry\")\n}\nhas := it.Contains(seq, \"orange\")\n// has == false\n```"
  },
  {
    "path": "docs/data/it-containsby.md",
    "content": "---\nname: ContainsBy\nslug: containsby\nsourceRef: it/intersect.go#L17\ncategory: it\nsubCategory: intersect\nsignatures:\n  - \"func ContainsBy[T any](collection iter.Seq[T], predicate func(item T) bool) bool\"\nplayUrl: https://go.dev/play/p/m86Cpsoyv8k\nvariantHelpers:\n  - it#intersect#containsby\nsimilarHelpers:\n  - core#slice#containsby\nposition: 650\n---\n\nReturns true if predicate function returns true for any element in the collection.\n\nWill iterate through the entire sequence if predicate never returns true.\n\nExamples:\n\n```go\n// Check if collection contains an even number\nnumbers := it.Slice([]int{1, 3, 5, 7, 9})\nhasEven := it.ContainsBy(numbers, func(n int) bool { return n%2 == 0 })\n// hasEven: false\n\nnumbers = it.Slice([]int{1, 3, 5, 8, 9})\nhasEven = it.ContainsBy(numbers, func(n int) bool { return n%2 == 0 })\n// hasEven: true\n\n// Check if collection contains a string with specific prefix\nwords := it.Slice([]string{\"hello\", \"world\", \"go\", \"lang\"})\nhasPrefix := it.ContainsBy(words, func(s string) bool { return strings.HasPrefix(s, \"go\") })\n// hasPrefix: true\n\n// Check if collection contains a person with specific age\ntype Person struct {\n    Name string\n    Age  int\n}\npeople := it.Slice([]Person{\n    {Name: \"Alice\", Age: 30},\n    {Name: \"Bob\", Age: 25},\n    {Name: \"Charlie\", Age: 35},\n})\nhasAge30 := it.ContainsBy(people, func(p Person) bool { return p.Age == 30 })\n// hasAge30: true\n\nhasAge40 := it.ContainsBy(people, func(p Person) bool { return p.Age == 40 })\n// hasAge40: false\n\n// Check if collection contains an element with specific property\nstrings := it.Slice([]string{\"apple\", \"banana\", \"cherry\"})\nhasLongString := it.ContainsBy(strings, func(s string) bool { return len(s) > 5 })\n// hasLongString: true\n\n// Check if collection contains negative numbers\nnumbers = it.Slice([]int{1, -2, 3, 4, -5})\nhasNegative := it.ContainsBy(numbers, func(n int) bool { return n < 0 })\n// hasNegative: true\n\n// Check if collection contains valid email\nemails := it.Slice([]string{\"user@example.com\", \"invalid-email\", \"test@domain.org\"})\nhasValidEmail := it.ContainsBy(emails, func(email string) bool {\n    return strings.Contains(email, \"@\") && strings.Contains(email, \".\")\n})\n// hasValidEmail: true\n\n// Check empty collection\nempty := it.Slice([]int{})\nhasAny := it.ContainsBy(empty, func(n int) bool { return n > 0 })\n// hasAny: false\n\n// Check for nil pointers (with pointer slice)\nptrs := it.Slice([]*int{ptr(5), nil, ptr(10)})\nhasNil := it.ContainsBy(ptrs, func(p *int) bool { return p == nil })\n// hasNil: true\n```"
  },
  {
    "path": "docs/data/it-count.md",
    "content": "---\nname: Count / CountBy\nslug: count\nsourceRef: it/seq.go#L630\ncategory: it\nsubCategory: sequence\nsignatures:\n  - \"func Count[T comparable](collection iter.Seq[T], value T) int\"\n  - \"func CountBy[T any](collection iter.Seq[T], predicate func(item T) bool) int\"\nplayUrl: https://go.dev/play/p/UcJ-6cANwfY\nvariantHelpers:\n  - it#sequence#count\n  - it#sequence#countby\nsimilarHelpers:\n  - core#slice#count\n  - it#sequence#countvalues\nposition: 110\n---\n\nCounts elements in a collection. Count counts elements equal to a value, CountBy counts elements matching a predicate.\n\nExamples:\n\n```go\nseq := func(yield func(int) bool) {\n    _ = yield(1)\n    _ = yield(2)\n    _ = yield(2)\n    _ = yield(3)\n    _ = yield(2)\n}\ncnt := it.Count(seq, 2)\n// cnt == 3\n```\n\n```go\nseq := func(yield func(string) bool) {\n    _ = yield(\"apple\")\n    _ = yield(\"banana\")\n    _ = yield(\"apricot\")\n}\ncnt := it.CountBy(seq, func(s string) bool {\n    return len(s) > 5\n})\n// cnt == 2 (banana, apricot)\n```"
  },
  {
    "path": "docs/data/it-countby.md",
    "content": "---\nname: CountBy\nslug: countby\nsourceRef: it/seq.go#L325\ncategory: it\nsubCategory: find\nsignatures:\n  - \"func CountBy[T any](collection iter.Seq[T], predicate func(item T) bool) int\"\nplayUrl: https://go.dev/play/p/m6G0o3huCOG\nvariantHelpers:\n  - it#find#count\nsimilarHelpers:\n  - core#slice#countby\n  - core#slice#count\nposition: 35\n---\n\nCounts the number of elements in the collection that satisfy the predicate.\n\n```go\nresult := it.CountBy(it.Range(1, 11), func(item int) bool {\n    return item%2 == 0\n})\n// 5\n```"
  },
  {
    "path": "docs/data/it-countvalues.md",
    "content": "---\nname: CountValues\nslug: countvalues\nsourceRef: it/seq.go#L720\ncategory: it\nsubCategory: slice\nsignatures:\n  - \"func CountValues[T comparable](collection iter.Seq[T]) map[T]int\"\nplayUrl: https://go.dev/play/p/PPBT4Fp-V3B\nvariantHelpers: []\nsimilarHelpers:\n  - core#slice#countvalues\nposition: 203\n---\n\nCountValues counts the number of each element in the collection.\n\n```go\ncollection := func(yield func(string) bool) {\n    yield(\"apple\")\n    yield(\"banana\")\n    yield(\"apple\")\n    yield(\"cherry\")\n    yield(\"banana\")\n    yield(\"apple\")\n}\n\ncounts := it.CountValues(collection)\n// counts contains {\"apple\": 3, \"banana\": 2, \"cherry\": 1}\n```"
  },
  {
    "path": "docs/data/it-countvaluesby.md",
    "content": "---\nname: CountValuesBy\nslug: countvaluesby\nsourceRef: it/seq.go#L720\ncategory: it\nsubCategory: slice\nsignatures:\n  - \"func CountValuesBy[T any, U comparable](collection iter.Seq[T], transform func(item T) U) map[U]int\"\nplayUrl: https://go.dev/play/p/gnr_MPhYCHX\nvariantHelpers: []\nsimilarHelpers:\n  - core#slice#countvaluesby\nposition: 204\n---\n\nCountValuesBy counts the number of each element returned from transform function.\nIs equivalent to chaining Map and CountValues.\n\n```go\ntype Person struct {\n    Name string\n    Age  int\n}\n\ncollection := func(yield func(Person) bool) {\n    yield(Person{\"Alice\", 25})\n    yield(Person{\"Bob\", 30})\n    yield(Person{\"Charlie\", 25})\n    yield(Person{\"Diana\", 30})\n}\n\ncountsByAge := it.CountValuesBy(collection, func(p Person) int {\n    return p.Age\n})\n// countsByAge contains {25: 2, 30: 2}\n```"
  },
  {
    "path": "docs/data/it-crossjoinbyx.md",
    "content": "---\nname: CrossJoinByX\nslug: crossjoinbyx\nsourceRef: it/tuples.go#L439\ncategory: it\nsubCategory: tuple\nsignatures:\n  - \"func CrossJoinBy2[T1, T2, R any](seq1 iter.Seq[T1], seq2 iter.Seq[T2], transform func(T1, T2) R) iter.Seq[R]\"\n  - \"func CrossJoinBy3[T1, T2, T3, R any](seq1 iter.Seq[T1], seq2 iter.Seq[T2], seq3 iter.Seq[T3], transform func(T1, T2, T3) R) iter.Seq[R]\"\n  - \"func CrossJoinBy4[T1, T2, T3, T4, R any](seq1 iter.Seq[T1], seq2 iter.Seq[T2], seq3 iter.Seq[T3], seq4 iter.Seq[T4], transform func(T1, T2, T3, T4) R) iter.Seq[R]\"\n  - \"func CrossJoinBy5[T1, T2, T3, T4, T5, R any](seq1 iter.Seq[T1], seq2 iter.Seq[T2], seq3 iter.Seq[T3], seq4 iter.Seq[T4], seq5 iter.Seq[T5], transform func(T1, T2, T3, T4, T5) R) iter.Seq[R]\"\n  - \"func CrossJoinBy6[T1, T2, T3, T4, T5, T6, R any](seq1 iter.Seq[T1], seq2 iter.Seq[T2], seq3 iter.Seq[T3], seq4 iter.Seq[T4], seq5 iter.Seq[T5], seq6 iter.Seq[T6], transform func(T1, T2, T3, T4, T5, T6) R) iter.Seq[R]\"\n  - \"func CrossJoinBy7[T1, T2, T3, T4, T5, T6, T7, R any](seq1 iter.Seq[T1], seq2 iter.Seq[T2], seq3 iter.Seq[T3], seq4 iter.Seq[T4], seq5 iter.Seq[T5], seq6 iter.Seq[T6], seq7 iter.Seq[T7], transform func(T1, T2, T3, T4, T5, T6, T7) R) iter.Seq[R]\"\n  - \"func CrossJoinBy8[T1, T2, T3, T4, T5, T6, T7, T8, R any](seq1 iter.Seq[T1], seq2 iter.Seq[T2], seq3 iter.Seq[T3], seq4 iter.Seq[T4], seq5 iter.Seq[T5], seq6 iter.Seq[T6], seq7 iter.Seq[T7], seq8 iter.Seq[T8], transform func(T1, T2, T3, T4, T5, T6, T7, T8) R) iter.Seq[R]\"\n  - \"func CrossJoinBy9[T1, T2, T3, T4, T5, T6, T7, T8, T9, R any](seq1 iter.Seq[T1], seq2 iter.Seq[T2], seq3 iter.Seq[T3], seq4 iter.Seq[T4], seq5 iter.Seq[T5], seq6 iter.Seq[T6], seq7 iter.Seq[T7], seq8 iter.Seq[T8], seq9 iter.Seq[T9], transform func(T1, T2, T3, T4, T5, T6, T7, T8, T9) R) iter.Seq[R]\"\nplayUrl: https://go.dev/play/p/6QGp3W-bQU1\nvariantHelpers:\n  - it#tuple#crossjoinbyx\nsimilarHelpers:\n  - core#tuple#crossjoinbyx\n  - it#tuple#crossjoinx\n  - core#slice#map\nposition: 20\n---\n\nCombines every item from multiple lists (cartesian product) using a callback function to transform the results. Returns an empty sequence if any input sequence is empty.\n\nVariants: `CrossJoinBy2..CrossJoinBy9`\n\n```go\nseq1 := func(yield func(int) bool) {\n    _ = yield(1)\n    _ = yield(2)\n}\nseq2 := func(yield func(string) bool) {\n    _ = yield(\"a\")\n    _ = yield(\"b\")\n}\nresult := it.CrossJoinBy2(seq1, seq2, func(i int, s string) string {\n    return fmt.Sprintf(\"%d-%s\", i, s)\n})\nvar output []string\nfor item := range result {\n    output = append(output, item)\n}\n// output contains [\"1-a\", \"1-b\", \"2-a\", \"2-b\"]\n```"
  },
  {
    "path": "docs/data/it-crossjoinx.md",
    "content": "---\nname: CrossJoinX\nslug: crossjoinx\nsourceRef: it/tuples.go#L370\ncategory: it\nsubCategory: tuple\nsignatures:\n  - \"func CrossJoin2[T1, T2 any](list1 iter.Seq[T1], list2 iter.Seq[T2]) iter.Seq[lo.Tuple2[T1, T2]]\"\n  - \"func CrossJoin3[T1, T2, T3 any](list1 iter.Seq[T1], list2 iter.Seq[T2], list3 iter.Seq[T3]) iter.Seq[lo.Tuple3[T1, T2, T3]]\"\n  - \"func CrossJoin4[T1, T2, T3, T4 any](list1 iter.Seq[T1], list2 iter.Seq[T2], list3 iter.Seq[T3], list4 iter.Seq[T4]) iter.Seq[lo.Tuple4[T1, T2, T3, T4]]\"\n  - \"func CrossJoin5[T1, T2, T3, T4, T5 any](list1 iter.Seq[T1], list2 iter.Seq[T2], list3 iter.Seq[T3], list4 iter.Seq[T4], list5 iter.Seq[T5]) iter.Seq[lo.Tuple5[T1, T2, T3, T4, T5]]\"\n  - \"func CrossJoin6[T1, T2, T3, T4, T5, T6 any](list1 iter.Seq[T1], list2 iter.Seq[T2], list3 iter.Seq[T3], list4 iter.Seq[T4], list5 iter.Seq[T5], list6 iter.Seq[T6]) iter.Seq[lo.Tuple6[T1, T2, T3, T4, T5, T6]]\"\n  - \"func CrossJoin7[T1, T2, T3, T4, T5, T6, T7 any](list1 iter.Seq[T1], list2 iter.Seq[T2], list3 iter.Seq[T3], list4 iter.Seq[T4], list5 iter.Seq[T5], list6 iter.Seq[T6], list7 iter.Seq[T7]) iter.Seq[lo.Tuple7[T1, T2, T3, T4, T5, T6, T7]]\"\n  - \"func CrossJoin8[T1, T2, T3, T4, T5, T6, T7, T8 any](list1 iter.Seq[T1], list2 iter.Seq[T2], list3 iter.Seq[T3], list4 iter.Seq[T4], list5 iter.Seq[T5], list6 iter.Seq[T6], list7 iter.Seq[T7], list8 iter.Seq[T8]) iter.Seq[lo.Tuple8[T1, T2, T3, T4, T5, T6, T7, T8]]\"\n  - \"func CrossJoin9[T1, T2, T3, T4, T5, T6, T7, T8, T9 any](list1 iter.Seq[T1], list2 iter.Seq[T2], list3 iter.Seq[T3], list4 iter.Seq[T4], list5 iter.Seq[T5], list6 iter.Seq[T6], list7 iter.Seq[T7], list8 iter.Seq[T8], list9 iter.Seq[T9]) iter.Seq[lo.Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9]]\"\nplayUrl: https://go.dev/play/p/OFe8xjZFjWU\nvariantHelpers:\n  - it#tuple#crossjoinx\nsimilarHelpers:\n  - core#tuple#crossjoinx\n  - it#tuple#zipx\n  - it#tuple#crossjoinbyx\nposition: 10\n---\n\nCombines every item from multiple lists (cartesian product). The resulting sequence contains all possible combinations of elements from each input sequence.\n\nThe cartesian product means every element from the first sequence is paired with every element from the second sequence, then those pairs are combined with every element from the third sequence, and so on.\n\n```go\nseq1 := func(yield func(int) bool) {\n    _ = yield(1)\n    _ = yield(2)\n}\nseq2 := func(yield func(string) bool) {\n    _ = yield(\"a\")\n    _ = yield(\"b\")\n}\ncross := it.CrossJoin2(seq1, seq2)\nvar result []string\nfor tuple := range cross {\n    result = append(result, fmt.Sprintf(\"%d%s\", tuple.A, tuple.B))\n}\n// result contains [\"1a\", \"1b\", \"2a\", \"2b\"] (all 4 combinations in lexical order)\n```\n\nExample with 3 sequences:\n```go\nnumbers := func(yield func(int) bool) {\n    _ = yield(1)\n    _ = yield(2)\n}\nletters := func(yield func(string) bool) {\n    _ = yield(\"a\")\n    _ = yield(\"b\")\n}\ncolors := func(yield func(string) bool) {\n    _ = yield(\"red\")\n    _ = yield(\"blue\")\n}\ncross := it.CrossJoin3(numbers, letters, colors)\nvar result []string\nfor tuple := range cross {\n    result = append(result, fmt.Sprintf(\"%d%s%s\", tuple.A, tuple.B, tuple.C))\n}\n// result contains 8 combinations: [\"1ared\", \"1ablue\", \"1bred\", \"1bblue\", \"2ared\", \"2ablue\", \"2bred\", \"2bblue\"]\n```"
  },
  {
    "path": "docs/data/it-cutprefix.md",
    "content": "---\nname: CutPrefix\nslug: cutprefix\nsourceRef: it/seq.go#L778\ncategory: it\nsubCategory: string\nsignatures:\n  - \"func CutPrefix[T comparable, I ~func(func(T) bool)](collection I, separator []T) (after I, found bool)\"\nplayUrl: https://go.dev/play/p/bPnV39zVnAV\nvariantHelpers: []\nsimilarHelpers:\n  - core#string#cutprefix\nposition: 260\n---\n\nCutPrefix returns collection without the provided leading prefix and reports whether it found the prefix.\nIf collection doesn't start with prefix, CutPrefix returns collection, false.\nIf prefix is empty, CutPrefix returns collection, true.\n\n```go\ncollection := func(yield func(int) bool) {\n    yield(1)\n    yield(2)\n    yield(3)\n    yield(4)\n}\n\nafter, found := it.CutPrefix(collection, []int{1, 2})\nvar result []int\nfor item := range after {\n    result = append(result, item)\n}\n// result contains [3, 4], found is true\n\nafter2, found2 := it.CutPrefix(collection, []int{9, 10})\nvar result2 []int\nfor item := range after2 {\n    result2 = append(result2, item)\n}\n// result2 contains [1, 2, 3, 4], found2 is false\n```"
  },
  {
    "path": "docs/data/it-cutsuffix.md",
    "content": "---\nname: CutSuffix\nslug: cutsuffix\nsourceRef: it/seq.go#L778\ncategory: it\nsubCategory: string\nsignatures:\n  - \"func CutSuffix[T comparable, I ~func(func(T) bool)](collection I, separator []T) (before I, found bool)\"\nplayUrl: https://go.dev/play/p/CTRh9m1UHrZ\nvariantHelpers: []\nsimilarHelpers:\n  - core#string#cutsuffix\nposition: 261\n---\n\nCutSuffix returns collection without the provided ending suffix and reports whether it found the suffix.\nIf collection doesn't end with suffix, CutSuffix returns collection, false.\nIf suffix is empty, CutSuffix returns collection, true.\n\n```go\ncollection := func(yield func(int) bool) {\n    yield(1)\n    yield(2)\n    yield(3)\n    yield(4)\n}\n\nbefore, found := it.CutSuffix(collection, []int{3, 4})\nvar result []int\nfor item := range before {\n    result = append(result, item)\n}\n// result contains [1, 2], found is true\n```"
  },
  {
    "path": "docs/data/it-drain.md",
    "content": "---\nname: Drain\nslug: drain\nsourceRef: it/seq.go#L26\ncategory: it\nsubCategory: sequence\nsignatures:\n  - \"func Drain[T any](collection iter.Seq[T])\"\nplayUrl: https://go.dev/play/p/xU_GCG861r1\nvariantHelpers: []\nsimilarHelpers: []\nposition: 170\n---\n\nDrain consumes an entire sequence.\n\n```go\ncollection := func(yield func(int) bool) {\n    yield(1)\n    yield(2)\n    yield(3)\n    fmt.Println(\"yielding\")\n}\n\nit.Drain(collection)\n// prints \"yielding\" three times, sequence is consumed\n```"
  },
  {
    "path": "docs/data/it-drop.md",
    "content": "---\nname: Drop\nslug: drop\nsourceRef: it/seq.go#L498\ncategory: it\nsubCategory: sequence\nsignatures:\n  - \"func Drop[T any, I ~func(func(T) bool)](collection I, n int) I\"\nplayUrl: https://go.dev/play/p/O1J1-uWc3z9\nvariantHelpers:\n  - it#sequence#drop\nsimilarHelpers:\n  - core#slice#drop\n  - it#sequence#droplast\nposition: 100\n---\n\nDrops n elements from the beginning of a sequence.\n\nExamples:\n\n```go\nseq := func(yield func(int) bool) {\n    _ = yield(1)\n    _ = yield(2)\n    _ = yield(3)\n    _ = yield(4)\n    _ = yield(5)\n}\ndropped := it.Drop(seq, 2)\nvar result []int\nfor v := range dropped {\n    result = append(result, v)\n}\n// result contains 3, 4, 5\n```"
  },
  {
    "path": "docs/data/it-dropbyindex.md",
    "content": "---\nname: DropByIndex\nslug: dropbyindex\nsourceRef: it/seq.go#L581\ncategory: it\nsubCategory: sequence\nsignatures:\n  - \"func DropByIndex[T any, I ~func(func(T) bool)](collection I, indexes ...int) I\"\nplayUrl: https://go.dev/play/p/vPbrZYgiU4q\nvariantHelpers:\n  - it#slice#drop\nsimilarHelpers:\n  - core#slice#dropbyindex\n  - core#slice#withoutnth\nposition: 55\n---\n\nRemoves elements from a collection at the specified indexes.\n\n```go\nresult := it.DropByIndex(it.Range(1, 6), 1, 3)\n// [1, 3, 5]\n```"
  },
  {
    "path": "docs/data/it-droplast.md",
    "content": "---\nname: DropLast\nslug: droplast\nsourceRef: it/seq.go#L512\ncategory: it\nsubCategory: sequence\nsignatures:\n  - \"func DropLast[T any, I ~func(func(T) bool)](collection I, n int) I\"\nvariantHelpers:\n  - it#sequence#droplast\nsimilarHelpers:\n  - it#sequence#drop\n  - it#sequence#dropwhile\n  - it#sequence#droplastwhile\n  - it#sequence#trim\n  - it#sequence#trimsuffix\nposition: 78\n---\n\nDrops the last n elements from a sequence. Returns a new sequence without the specified number of trailing elements.\n\n```go\nseq := func(yield func(int) bool) {\n    yield(1)\n    yield(2)\n    yield(3)\n    yield(4)\n    yield(5)\n}\nresult := it.DropLast(seq, 2)\n// iter.Seq[int] yielding 1, 2, 3\n\nresult = it.DropLast(seq, 0)\n// iter.Seq[int] yielding 1, 2, 3, 4, 5 (unchanged)\n\nresult = it.DropLast(seq, 10)\n// iter.Seq[int] yielding nothing (all elements dropped)\n\nseq = func(yield func(string) bool) {\n    yield(\"a\")\n    yield(\"b\")\n    yield(\"c\")\n}\nresult = it.DropLast(seq, 1)\n// iter.Seq[string] yielding \"a\", \"b\"\n```"
  },
  {
    "path": "docs/data/it-droplastwhile.md",
    "content": "---\nname: DropLastWhile\nslug: droplastwhile\nsourceRef: it/seq.go#L180\ncategory: it\nsubCategory: sequence\nsignatures:\n  - \"func DropLastWhile[T any, I ~func(func(T) bool)](collection I, predicate func(item T) bool) I\"\nvariantHelpers: []\nsimilarHelpers:\n  - core#slice#droplastwhile\nposition: 163\n---\n\nDropLastWhile drops elements from the end of a sequence while the predicate returns true.\n\n```go\ncollection := func(yield func(int) bool) {\n    yield(1)\n    yield(2)\n    yield(3)\n    yield(4)\n    yield(5)\n}\n\nfiltered := it.DropLastWhile(collection, func(x int) bool {\n    return x > 3\n})\nvar result []int\nfor item := range filtered {\n    result = append(result, item)\n}\n// result contains [1, 2, 3]\n```"
  },
  {
    "path": "docs/data/it-dropslice.md",
    "content": "---\nname: DropLast\nslug: dropslice\nsourceRef: it/seq.go#L510\ncategory: it\nsubCategory: slice\nsignatures:\n  - \"func DropLast[T any, I ~func(func(T) bool)](collection I, n int) I\"\n  - \"func DropByIndex[T any, I ~func(func(T) bool)](collection I, indexes ...int) I\"\n  - \"func Subset[T any, I ~func(func(T) bool)](collection I, offset, length int) I\"\n  - \"func Slice[T any, I ~func(func(T) bool)](collection I, start, end int) I\"\nvariantHelpers:\n  - it#slice#droplast\n  - it#slice#dropbyindex\n  - it#slice#subset\n  - it#slice#slice\nsimilarHelpers:\n  - core#slice#drop\n  - core#slice#droplast\n  - core#slice#dropbyindex\n  - core#slice#subset\n  - core#slice#slice\nposition: 150\n---\n\nDropLast drops n elements from the end of a sequence.\n\n```go\ncollection := func(yield func(int) bool) {\n    yield(1)\n    yield(2)\n    yield(3)\n    yield(4)\n    yield(5)\n}\n\nfiltered := it.DropLast(collection, 2)\nvar result []int\nfor item := range filtered {\n    result = append(result, item)\n}\n// result contains [1, 2, 3]\n```\n\nDropByIndex drops elements from a sequence by the index.\n\n```go\ncollection := func(yield func(int) bool) {\n    yield(1)\n    yield(2)\n    yield(3)\n    yield(4)\n    yield(5)\n}\n\nfiltered := it.DropByIndex(collection, 1, 3)\nvar result []int\nfor item := range filtered {\n    result = append(result, item)\n}\n// result contains [1, 3, 5]\n```\n\nSubset returns a subset of a sequence from `offset` up to `length` elements.\n\n```go\ncollection := func(yield func(int) bool) {\n    yield(1)\n    yield(2)\n    yield(3)\n    yield(4)\n    yield(5)\n    yield(6)\n}\n\nsubset := it.Subset(collection, 2, 3)\nvar result []int\nfor item := range subset {\n    result = append(result, item)\n}\n// result contains [3, 4, 5]\n```\n\nSlice returns a subset of a sequence from `start` up to, but not including `end`.\n\n```go\ncollection := func(yield func(int) bool) {\n    yield(1)\n    yield(2)\n    yield(3)\n    yield(4)\n    yield(5)\n}\n\nsliced := it.Slice(collection, 1, 4)\nvar result []int\nfor item := range sliced {\n    result = append(result, item)\n}\n// result contains [2, 3, 4]\n```"
  },
  {
    "path": "docs/data/it-dropwhile.md",
    "content": "---\nname: DropWhile\nslug: dropwhile\nsourceRef: it/seq.go#L180\ncategory: it\nsubCategory: sequence\nsignatures:\n  - \"func DropWhile[T any, I ~func(func(T) bool)](collection I, predicate func(item T) bool) I\"\nvariantHelpers: []\nsimilarHelpers:\n  - core#slice#dropwhile\n  - it#sequence#drop\nposition: 162\n---\n\nDropWhile drops elements from the beginning of a sequence while the predicate returns true.\n\n```go\ncollection := func(yield func(int) bool) {\n    yield(1)\n    yield(2)\n    yield(3)\n    yield(4)\n    yield(5)\n}\n\nfiltered := it.DropWhile(collection, func(x int) bool {\n    return x < 3\n})\nvar result []int\nfor item := range filtered {\n    result = append(result, item)\n}\n// result contains [3, 4, 5]\n```"
  },
  {
    "path": "docs/data/it-earliest.md",
    "content": "---\nname: Earliest\nslug: earliest\nsourceRef: it/find.go#L278\ncategory: it\nsubCategory: find\nsignatures:\n  - \"func Earliest(times iter.Seq[time.Time]) time.Time\"\nplayUrl: https://go.dev/play/p/fI6_S10H7Py\nvariantHelpers:\n  - it#find#earliest\nsimilarHelpers:\n  - core#slice#earliest\nposition: 500\n---\n\nSearches for the earliest (minimum) time.Time in a collection.\n\nReturns zero value when the collection is empty.\nWill iterate through the entire sequence.\n\nExamples:\n\n```go\nimport \"time\"\n\n// Find the earliest time from a collection\ntimes := it.Slice([]time.Time{\n    time.Date(2023, 5, 15, 10, 0, 0, 0, time.UTC),\n    time.Date(2023, 3, 20, 14, 30, 0, 0, time.UTC),\n    time.Date(2023, 8, 1, 9, 15, 0, 0, time.UTC),\n})\nearliest := it.Earliest(times)\n// earliest: 2023-03-20 14:30:00 +0000 UTC\n\n// With empty collection\nempty := it.Slice([]time.Time{})\nearliest := it.Earliest(empty)\n// earliest: 0001-01-01 00:00:00 +0000 UTC (zero value)\n\n// Find earliest from parsed times\ntimes := it.Slice([]time.Time{\n    time.Parse(time.RFC3339, \"2023-01-01T12:00:00Z\"),\n    time.Parse(time.RFC3339, \"2023-01-01T10:00:00Z\"),\n    time.Parse(time.RFC3339, \"2023-01-01T14:00:00Z\"),\n})\nearliest := it.Earliest(times)\n// earliest: 2023-01-01 10:00:00 +0000 UTC\n```"
  },
  {
    "path": "docs/data/it-earliestby.md",
    "content": "---\nname: EarliestBy\nslug: earliestby\nsourceRef: it/find.go#L285\ncategory: it\nsubCategory: find\nsignatures:\n  - \"func EarliestBy[T any](collection iter.Seq[T], transform func(item T) time.Time) T\"\nplayUrl: https://go.dev/play/p/y_Pf3Jmw-B4\nvariantHelpers:\n  - it#find#earliestby\nsimilarHelpers:\n  - core#slice#earliestby\nposition: 510\n---\n\nSearches for the element with the earliest time using a transform function.\n\nReturns zero value when the collection is empty.\nWill iterate through the entire sequence.\n\nExamples:\n\n```go\nimport \"time\"\n\ntype Event struct {\n    Name string\n    Time time.Time\n}\n\n// Find the earliest event by time\nevents := it.Slice([]Event{\n    {\"Meeting\", time.Date(2023, 5, 15, 10, 0, 0, 0, time.UTC)},\n    {\"Lunch\", time.Date(2023, 5, 15, 12, 0, 0, 0, time.UTC)},\n    {\"Breakfast\", time.Date(2023, 5, 15, 8, 0, 0, 0, time.UTC)},\n})\nearliest := it.EarliestBy(events, func(e Event) time.Time {\n    return e.Time\n})\n// earliest: {Name: \"Breakfast\", Time: 2023-05-15 08:00:00 +0000 UTC}\n\n// Find the earliest task by deadline\ntype Task struct {\n    ID       int\n    Deadline time.Time\n}\ntasks := it.Slice([]Task{\n    {1, time.Date(2023, 6, 1, 0, 0, 0, 0, time.UTC)},\n    {2, time.Date(2023, 5, 15, 0, 0, 0, 0, time.UTC)},\n    {3, time.Date(2023, 7, 1, 0, 0, 0, 0, time.UTC)},\n})\nearliest := it.EarliestBy(tasks, func(t Task) time.Time {\n    return t.Deadline\n})\n// earliest: {ID: 2, Deadline: 2023-05-15 00:00:00 +0000 UTC}\n```"
  },
  {
    "path": "docs/data/it-elementsmatch.md",
    "content": "---\nname: ElementsMatch\nslug: elementsmatch\nsourceRef: it/intersect.go#L174\ncategory: it\nsubCategory: intersect\nsignatures:\n  - \"func ElementsMatch[T comparable](list1, list2 iter.Seq[T]) bool\"\nplayUrl: \"https://go.dev/play/p/24SGQm1yMRe\"\nvariantHelpers:\n  - it#intersect#elementsmatch\nsimilarHelpers:\n  - core#slice#elementsmatch\nposition: 720\n---\n\nReturns true if lists contain the same set of elements (including empty set).\n\nIf there are duplicate elements, the number of occurrences in each list should match.\nThe order of elements is not checked.\nWill iterate through each sequence before returning and allocate a map large enough to hold all distinct elements.\nLong heterogeneous input sequences can cause excessive memory usage.\n\nExamples:\n\n```go\n// Lists with same elements in different order\nlist1 := it.Slice([]int{1, 2, 3, 4, 5})\nlist2 := it.Slice([]int{5, 4, 3, 2, 1})\nmatch := it.ElementsMatch(list1, list2)\n// match: true\n\n// Lists with different elements\nlist1 = it.Slice([]int{1, 2, 3, 4, 5})\nlist2 = it.Slice([]int{1, 2, 3, 4, 6})\nmatch = it.ElementsMatch(list1, list2)\n// match: false (5 vs 6)\n\n// Lists with duplicates\nlist1 = it.Slice([]int{1, 2, 2, 3, 4})\nlist2 = it.Slice([]int{4, 3, 2, 1, 2})\nmatch = it.ElementsMatch(list1, list2)\n// match: true (both have two 2's)\n\n// Lists with different number of duplicates\nlist1 = it.Slice([]int{1, 2, 2, 3, 4})\nlist2 = it.Slice([]int{4, 3, 2, 1, 1})\nmatch = it.ElementsMatch(list1, list2)\n// match: false (list1 has two 2's, list2 has two 1's)\n\n// Empty lists\nempty1 := it.Slice([]int{})\nempty2 := it.Slice([]int{})\nmatch = it.ElementsMatch(empty1, empty2)\n// match: true\n\n// One empty, one not empty\nempty := it.Slice([]int{})\nnonEmpty := it.Slice([]int{1, 2, 3})\nmatch = it.ElementsMatch(empty, nonEmpty)\n// match: false\n\n// String lists\nwords1 := it.Slice([]string{\"hello\", \"world\", \"go\"})\nwords2 := it.Slice([]string{\"go\", \"hello\", \"world\"})\nmatch := it.ElementsMatch(words1, words2)\n// match: true\n\nwords1 = it.Slice([]string{\"hello\", \"world\", \"go\"})\nwords2 = it.Slice([]string{\"go\", \"hello\", \"golang\"})\nmatch = it.ElementsMatch(words1, words2)\n// match: false\n\n// Struct lists\ntype Person struct {\n    Name string\n    Age  int\n}\npeople1 := it.Slice([]Person{\n    {Name: \"Alice\", Age: 30},\n    {Name: \"Bob\", Age: 25},\n    {Name: \"Charlie\", Age: 35},\n})\npeople2 := it.Slice([]Person{\n    {Name: \"Charlie\", Age: 35},\n    {Name: \"Alice\", Age: 30},\n    {Name: \"Bob\", Age: 25},\n})\nmatch := it.ElementsMatch(people1, people2)\n// match: true\n\n// Different lengths\nlist1 = it.Slice([]int{1, 2, 3})\nlist2 = it.Slice([]int{1, 2, 3, 4})\nmatch = it.ElementsMatch(list1, list2)\n// match: false\n\n// Same elements but different counts\nlist1 = it.Slice([]int{1, 1, 2, 3})\nlist2 = it.Slice([]int{1, 2, 2, 3})\nmatch = it.ElementsMatch(list1, list2)\n// match: false (list1 has two 1's, list2 has two 2's)\n\n// Boolean values\nbools1 := it.Slice([]bool{true, false, true})\nbools2 := it.Slice([]bool{true, true, false})\nmatch := it.ElementsMatch(bools1, bools2)\n// match: true\n\n// Different boolean counts\nbools1 = it.Slice([]bool{true, false, true})\nbools2 = it.Slice([]bool{true, false, false})\nmatch = it.ElementsMatch(bools1, bools2)\n// match: false\n\n// Lists with same single element\nlist1 = it.Slice([]int{42})\nlist2 = it.Slice([]int{42})\nmatch = it.ElementsMatch(list1, list2)\n// match: true\n\n// Lists with different single elements\nlist1 = it.Slice([]int{42})\nlist2 = it.Slice([]int{43})\nmatch = it.ElementsMatch(list1, list2)\n// match: false\n```"
  },
  {
    "path": "docs/data/it-elementsmatchby.md",
    "content": "---\nname: ElementsMatchBy\nslug: elementsmatchby\nsourceRef: it/intersect.go#L183\ncategory: it\nsubCategory: intersect\nsignatures:\n  - \"func ElementsMatchBy[T any, K comparable](list1, list2 iter.Seq[T], transform func(item T) K) bool\"\nplayUrl: \"https://go.dev/play/p/I3vFrmQo43E\"\nvariantHelpers:\n  - it#intersect#elementsmatchby\nsimilarHelpers:\n  - core#slice#elementsmatchby\nposition: 730\n---\n\nReturns true if lists contain the same set of elements' keys (including empty set).\n\nIf there are duplicate keys, the number of occurrences in each list should match.\nThe order of elements is not checked.\nWill iterate through each sequence before returning and allocate a map large enough to hold all distinct transformed elements.\nLong heterogeneous input sequences can cause excessive memory usage.\n\nExamples:\n\n```go\n// Match people by age (ignoring names)\ntype Person struct {\n    Name string\n    Age  int\n}\npeople1 := it.Slice([]Person{\n    {Name: \"Alice\", Age: 30},\n    {Name: \"Bob\", Age: 25},\n    {Name: \"Charlie\", Age: 35},\n})\npeople2 := it.Slice([]Person{\n    {Name: \"David\", Age: 35},\n    {Name: \"Eve\", Age: 25},\n    {Name: \"Frank\", Age: 30},\n})\nmatch := it.ElementsMatchBy(people1, people2, func(p Person) int { return p.Age })\n// match: true (both have ages 25, 30, 35)\n\n// Match by string length\nwords1 := it.Slice([]string{\"hello\", \"world\", \"go\", \"lang\"})\nwords2 := it.Slice([]string{\"short\", \"longer\", \"golang\", \"python\"})\nmatch = it.ElementsMatchBy(words1, words2, func(s string) int { return len(s) })\n// match: false (lengths: 5,5,2,4 vs 6,6,6,6)\n\n// Match by first character\nitems1 := it.Slice([]string{\"apple\", \"apricot\", \"banana\", \"blueberry\"})\nitems2 := it.Slice([]string{\"ant\", \"anchor\", \"boat\", \"berry\"})\nmatch = it.ElementsMatchBy(items1, items2, func(s string) byte { return s[0] })\n// match: true (both start with a, a, b, b)\n\n// Match emails by domain\ntype Email struct {\n    Address string\n}\nemails1 := it.Slice([]Email{\n    {Address: \"user1@example.com\"},\n    {Address: \"user2@gmail.com\"},\n    {Address: \"user3@example.com\"},\n})\nemails2 := it.Slice([]Email{\n    {Address: \"different@gmail.com\"},\n    {Address: \"another@example.com\"},\n    {Address: \"third@example.com\"},\n})\nmatch = it.ElementsMatchBy(emails1, emails2, func(e Email) string {\n    parts := strings.Split(e.Address, \"@\")\n    if len(parts) > 1 {\n        return parts[1]\n    }\n    return \"\"\n})\n// match: true (both have domains: example.com, gmail.com, example.com)\n\n// Match by modulo operation\nnumbers1 := it.Slice([]int{1, 2, 3, 4, 5, 6})\nnumbers2 := it.Slice([]int{7, 8, 9, 10, 11, 12})\nmatch = it.ElementsMatchBy(numbers1, numbers2, func(n int) int { return n % 3 })\n// match: true (remainders: 1,2,0,1,2,0 vs 1,2,0,1,2,0)\n\n// Match by case-insensitive strings\nstrings1 := it.Slice([]string{\"Hello\", \"World\", \"GO\"})\nstrings2 := it.Slice([]string{\"hello\", \"world\", \"go\"})\nmatch = it.ElementsMatchBy(strings1, strings2, func(s string) string { return strings.ToLower(s) })\n// match: true\n\n// Match orders by customer ID (ignoring order details)\ntype Order struct {\n    ID         string\n    CustomerID string\n    ProductID  string\n}\norders1 := it.Slice([]Order{\n    {ID: \"1\", CustomerID: \"A\", ProductID: \"X\"},\n    {ID: \"2\", CustomerID: \"B\", ProductID: \"Y\"},\n    {ID: \"3\", CustomerID: \"A\", ProductID: \"Z\"},\n})\norders2 := it.Slice([]Order{\n    {ID: \"4\", CustomerID: \"B\", ProductID: \"W\"},\n    {ID: \"5\", CustomerID: \"A\", ProductID: \"V\"},\n    {ID: \"6\", CustomerID: \"A\", ProductID: \"U\"},\n})\nmatch = it.ElementsMatchBy(orders1, orders2, func(o Order) string { return o.CustomerID })\n// match: true (both have customer IDs: A, B, A)\n\n// Match dates by year-month (ignoring day)\nimport \"time\"\ndates1 := it.Slice([]time.Time{\n    time.Date(2023, 1, 15, 0, 0, 0, 0, time.UTC),\n    time.Date(2023, 2, 20, 0, 0, 0, 0, time.UTC),\n    time.Date(2023, 1, 25, 0, 0, 0, 0, time.UTC),\n})\ndates2 := it.Slice([]time.Time{\n    time.Date(2023, 1, 5, 0, 0, 0, 0, time.UTC),\n    time.Date(2023, 2, 10, 0, 0, 0, 0, time.UTC),\n    time.Date(2023, 1, 30, 0, 0, 0, 0, time.UTC),\n})\nmatch = it.ElementsMatchBy(dates1, dates2, func(t time.Time) string {\n    return fmt.Sprintf(\"%d-%02d\", t.Year(), t.Month())\n})\n// match: true (both have: 2023-01, 2023-02, 2023-01)\n\n// Match by category function\ntype Product struct {\n    Name  string\n    Price float64\n}\nproducts1 := it.Slice([]Product{\n    {Name: \"Book\", Price: 19.99},\n    {Name: \"Pen\", Price: 1.99},\n    {Name: \"Laptop\", Price: 999.99},\n})\nproducts2 := it.Slice([]Product{\n    {Name: \"Pencil\", Price: 0.99},\n    {Name: \"Phone\", Price: 699.99},\n    {Name: \"Desk\", Price: 199.99},\n})\nmatch = it.ElementsMatchBy(products1, products2, func(p Product) string {\n    if p.Price < 10 {\n        return \"cheap\"\n    } else if p.Price < 100 {\n        return \"medium\"\n    }\n    return \"expensive\"\n})\n// match: true (both have: medium, cheap, expensive)\n\n// Match by custom classification\ntype Student struct {\n    Name string\n    Age  int\n}\nstudents1 := it.Slice([]Student{\n    {Name: \"Alice\", Age: 8},\n    {Name: \"Bob\", Age: 15},\n    {Name: \"Charlie\", Age: 20},\n})\nstudents2 := it.Slice([]Student{\n    {Name: \"Diana\", Age: 25},\n    {Name: \"Eve\", Age: 10},\n    {Name: \"Frank\", Age: 12},\n})\nmatch = it.ElementsMatchBy(students1, students2, func(s Student) string {\n    if s.Age < 12 {\n        return \"child\"\n    } else if s.Age < 18 {\n        return \"teen\"\n    }\n    return \"adult\"\n})\n// match: false (students1: child, teen, adult vs students2: adult, child, child)\n```"
  },
  {
    "path": "docs/data/it-empty.md",
    "content": "---\nname: Empty\nslug: empty\nsourceRef: it/type_manipulation.go#L44\ncategory: it\nsubCategory: type\nsignatures:\n  - \"func Empty[T any]() iter.Seq[T]\"\nplayUrl: \"https://go.dev/play/p/E5fF1hH8Bc3\"\nvariantHelpers:\n  - it#type#empty\nsimilarHelpers:\n  - it#type#isempty\n  - it#type#isnotempty\nposition: 0\n---\n\nReturns an empty sequence of the specified type.\n\nExamples:\n\n```go\nemptySeq := it.Empty[int]()\ncount := 0\nfor range emptySeq {\n    count++\n}\n// count == 0\n```\n\n```go\nemptySeq := it.Empty[string]()\nvar result []string\nfor v := range emptySeq {\n    result = append(result, v)\n}\n// result is empty slice\n```"
  },
  {
    "path": "docs/data/it-entries.md",
    "content": "---\nname: Entries\nslug: entries\nsourceRef: it/map.go#L77\ncategory: it\nsubCategory: map\nsignatures:\n  - \"func Entries[K comparable, V any](in ...map[K]V) iter.Seq2[K, V]\"\nplayUrl: https://go.dev/play/p/ckLxqTE9KCz\nvariantHelpers:\n  - it#map#entries\nsimilarHelpers:\n  - core#slice#entries\n  - it#map#fromentries\n  - it#map#topairs\nposition: 20\n---\n\nTransforms a map into a sequence of key/value pairs. Accepts multiple maps and concatenates their entries.\n\nExamples:\n\n```go\nm := map[string]int{\n    \"apple\":  1,\n    \"banana\": 2,\n    \"cherry\": 3,\n}\nentriesSeq := it.Entries(m)\nvar keys []string\nvar values []int\nfor k, v := range entriesSeq {\n    keys = append(keys, k)\n    values = append(values, v)\n}\n// keys contains map keys, values contains corresponding values\n```"
  },
  {
    "path": "docs/data/it-every.md",
    "content": "---\nname: Every\nslug: every\nsourceRef: it/intersect.go#L25\ncategory: it\nsubCategory: intersect\nsignatures:\n  - \"func Every[T comparable](collection iter.Seq[T], subset ...T) bool\"\nplayUrl: \"https://go.dev/play/p/rwM9Y353aIC\"\nvariantHelpers:\n  - it#intersect#every\nsimilarHelpers:\n  - core#slice#every\n  - it#intersect#some\n  - it#intersect#none\nposition: 30\n---\n\nReturns true if all elements of a subset are contained in a collection.\n\nExamples:\n\n```go\nseq := func(yield func(int) bool) {\n    _ = yield(1)\n    _ = yield(2)\n    _ = yield(3)\n    _ = yield(4)\n    _ = yield(5)\n}\nhasAll := it.Every(seq, 2, 4)\n// hasAll == true\n```\n\n```go\nseq := func(yield func(string) bool) {\n    _ = yield(\"apple\")\n    _ = yield(\"banana\")\n    _ = yield(\"cherry\")\n}\nhasAll := it.Every(seq, \"apple\", \"orange\")\n// hasAll == false (orange is not in collection)\n```"
  },
  {
    "path": "docs/data/it-everyby.md",
    "content": "---\nname: EveryBy\nslug: everyby\nsourceRef: it/intersect.go#L43\ncategory: it\nsubCategory: intersect\nsignatures:\n  - \"func EveryBy[T any](collection iter.Seq[T], predicate func(item T) bool) bool\"\nplayUrl: https://go.dev/play/p/7OvV1BRWsER\nvariantHelpers:\n  - it#intersect#everyby\nsimilarHelpers:\n  - core#slice#everyby\nposition: 660\n---\n\nReturns true if the predicate returns true for all elements in the collection or if the collection is empty.\n\nWill iterate through the entire sequence if predicate never returns false.\n\nExamples:\n\n```go\n// Check if all numbers are positive\nnumbers := it.Slice([]int{1, 3, 5, 7, 9})\nallPositive := it.EveryBy(numbers, func(n int) bool { return n > 0 })\n// allPositive: true\n\nnumbers = it.Slice([]int{1, -3, 5, 7, 9})\nallPositive = it.EveryBy(numbers, func(n int) bool { return n > 0 })\n// allPositive: false\n\n// Check if all strings have minimum length\nwords := it.Slice([]string{\"hello\", \"world\", \"go\", \"lang\"})\nallLongEnough := it.EveryBy(words, func(s string) bool { return len(s) >= 2 })\n// allLongEnough: true\n\nallVeryLong := it.EveryBy(words, func(s string) bool { return len(s) >= 5 })\n// allVeryLong: false\n\n// Check if all people are adults\ntype Person struct {\n    Name string\n    Age  int\n}\npeople := it.Slice([]Person{\n    {Name: \"Alice\", Age: 30},\n    {Name: \"Bob\", Age: 25},\n    {Name: \"Charlie\", Age: 35},\n})\nallAdults := it.EveryBy(people, func(p Person) bool { return p.Age >= 18 })\n// allAdults: true\n\nminors := it.Slice([]Person{\n    {Name: \"Alice\", Age: 30},\n    {Name: \"Bob\", Age: 15},  // Not adult\n    {Name: \"Charlie\", Age: 35},\n})\nallAdults = it.EveryBy(minors, func(p Person) bool { return p.Age >= 18 })\n// allAdults: false\n\n// Check if all numbers are even\nnumbers = it.Slice([]int{2, 4, 6, 8, 10})\nallEven := it.EveryBy(numbers, func(n int) bool { return n%2 == 0 })\n// allEven: true\n\nnumbers = it.Slice([]int{2, 4, 6, 7, 10})  // 7 is odd\nallEven = it.EveryBy(numbers, func(n int) bool { return n%2 == 0 })\n// allEven: false\n\n// Check if all strings are lowercase\nstrings := it.Slice([]string{\"hello\", \"world\", \"go\", \"lang\"})\nallLowercase := it.EveryBy(strings, func(s string) bool { return s == strings.ToLower(s) })\n// allLowercase: true\n\nstrings = it.Slice([]string{\"hello\", \"World\", \"go\", \"lang\"})  // \"World\" has uppercase\nallLowercase = it.EveryBy(strings, func(s string) bool { return s == strings.ToLower(s) })\n// allLowercase: false\n\n// Empty collection returns true\nempty := it.Slice([]int{})\nallPositive := it.EveryBy(empty, func(n int) bool { return n > 0 })\n// allPositive: true\n\n// Check if all emails are valid\nemails := it.Slice([]string{\"user@example.com\", \"test@domain.org\", \"admin@site.net\"})\nallValid := it.EveryBy(emails, func(email string) bool {\n    return strings.Contains(email, \"@\") && strings.Contains(email, \".\")\n})\n// allValid: true\n\nemails = it.Slice([]string{\"user@example.com\", \"invalid-email\", \"test@domain.org\"})\nallValid = it.EveryBy(emails, func(email string) bool {\n    return strings.Contains(email, \"@\") && strings.Contains(email, \".\")\n})\n// allValid: false\n```"
  },
  {
    "path": "docs/data/it-fill.md",
    "content": "---\nname: Fill\nslug: fill\nsourceRef: it/seq.go#L26\ncategory: it\nsubCategory: sequence\nsignatures:\n  - \"func Fill[T lo.Clonable[T], I ~func(func(T) bool)](collection I, initial T) I\"\nvariantHelpers: []\nplayUrl: https://go.dev/play/p/mHShWq5ezMc\nsimilarHelpers:\n  - core#slice#fill\nposition: 174\n---\n\nFill replaces elements of a sequence with `initial` value.\n\n```go\ncollection := func(yield func(int) bool) {\n    yield(1)\n    yield(2)\n    yield(3)\n}\n\nfilled := it.Fill(collection, 99)\nvar result []int\nfor item := range filled {\n    result = append(result, item)\n}\n// result contains [99, 99, 99]\n```"
  },
  {
    "path": "docs/data/it-filter.md",
    "content": "---\nname: Filter\nslug: filter\nsourceRef: it/seq.go#L33\ncategory: it\nsubCategory: sequence\nsignatures:\n  - \"func Filter[T any, I ~func(func(T) bool)](collection I, predicate func(item T) bool) I\"\n  - \"func FilterI[T any, I ~func(func(T) bool)](collection I, predicate func(item T, index int) bool) I\"\nplayUrl: \"https://go.dev/play/p/psenko2KKsX\"\nvariantHelpers:\n  - it#sequence#filter\n  - it#sequence#filteri\nsimilarHelpers:\n  - core#slice#filter\n  - core#slice#filteri\n  - it#sequence#reject\nposition: 10\n---\n\nReturns a sequence of all elements for which the predicate function returns true.\n\n### Filter\n\n```go\nseq := func(yield func(int) bool) {\n    _ = yield(1)\n    _ = yield(2)\n    _ = yield(3)\n    _ = yield(4)\n    _ = yield(5)\n}\nfiltered := it.Filter(seq, func(x int) bool {\n    return x%2 == 0\n})\nvar result []int\nfor v := range filtered {\n    result = append(result, v)\n}\n// result contains 2, 4 (even numbers)\n```\n\n### FilterI\n\nFilterI iterates over elements of collection, returning a sequence of all elements predicate returns true for. The predicate function includes the index.\n\n```go\nresult := it.FilterI(it.Range(1, 6), func(item int, index int) bool {\n    return item%2 == 0 && index > 1\n})\nvar filtered []int\nfor v := range result {\n    filtered = append(filtered, v)\n}\n// filtered contains [4, 6]\n```"
  },
  {
    "path": "docs/data/it-filterkeys.md",
    "content": "---\nname: FilterKeys\nslug: filterkeys\nsourceRef: it/map.go#L238\ncategory: it\nsubCategory: map\nsignatures:\n  - \"func FilterKeys[K comparable, V any](in map[K]V, predicate func(key K, value V) bool) []K\"\nvariantHelpers:\n  - it#map#filterkeys\nsimilarHelpers:\n  - core#map#filterkeys\n  - it#map#filtervalues\n  - it#map#keys\n  - it#map#values\nposition: 56\n---\n\nFilters map keys based on a predicate function that takes both key and value. Returns a slice of keys that satisfy the predicate.\n\n```go\nm := map[string]int{\n    \"apple\":  3,\n    \"banana\": 5,\n    \"cherry\": 2,\n    \"date\":   0,\n}\nresult := it.FilterKeys(m, func(key string, value int) bool {\n    return value > 2\n})\n// []string{\"apple\", \"banana\"} (keys with values > 2)\n\nnumberMap := map[int]string{1: \"one\", 2: \"two\", 3: \"three\", 4: \"four\"}\nresult = it.FilterKeys(numberMap, func(key int, value string) bool {\n    return len(value) == 3\n})\n// []int{1, 2, 3} (keys where value length is 3)\n\npersonMap := map[string]int{\"alice\": 25, \"bob\": 30, \"charlie\": 17}\nresult = it.FilterKeys(personMap, func(key string, age int) bool {\n    return strings.HasPrefix(key, \"a\") && age >= 20\n})\n// []string{\"alice\"} (keys starting with \"a\" and age >= 20)\n\nemptyMap := map[string]int{}\nresult = it.FilterKeys(emptyMap, func(key string, value int) bool {\n    return true\n})\n// []string{} (empty map)\n```"
  },
  {
    "path": "docs/data/it-filtermap.md",
    "content": "---\nname: FilterMap\nslug: filtermap\nsourceRef: it/seq.go#L86\ncategory: it\nsubCategory: sequence\nsignatures:\n  - \"func FilterMap[T, R any](collection iter.Seq[T], callback func(item T) (R, bool)) iter.Seq[R]\"\n  - \"func FilterMapI[T, R any](collection iter.Seq[T], callback func(item T, index int) (R, bool)) iter.Seq[R]\"\nvariantHelpers:\n  - it#sequence#filtermap\n  - it#sequence#filtermapi\nsimilarHelpers:\n  - it#sequence#map\n  - it#sequence#filter\n  - it#sequence#filtermaptoslice\n  - it#sequence#rejectmap\nposition: 40\n---\n\nMaps elements of a sequence to new values and filters out elements where the callback returns false. Only elements where the second return value is true are included in the result.\n\n```go\nseq := func(yield func(int) bool) {\n    yield(1)\n    yield(2)\n    yield(3)\n    yield(4)\n}\nresult := it.FilterMap(seq, func(x int) (string, bool) {\n    if x%2 == 0 {\n        return fmt.Sprintf(\"even-%d\", x), true\n    }\n    return \"\", false\n})\n// iter.Seq[string] yielding \"even-2\", \"even-4\"\n\nseq = func(yield func(string) bool) {\n    yield(\"a\")\n    yield(\"\")\n    yield(\"c\")\n    yield(\"d\")\n}\nresult = it.FilterMap(seq, func(s string) (int, bool) {\n    if s != \"\" {\n        return len(s), true\n    }\n    return 0, false\n})\n// iter.Seq[int] yielding 1, 1, 1 (length of \"a\", \"c\", \"d\")\n```\n\n### FilterMapI\n\nMaps elements of a sequence to new values and filters out elements where the callback returns false. The callback receives both the item and its index.\n\n```go\nseq := func(yield func(string) bool) {\n    yield(\"apple\")\n    yield(\"banana\")\n    yield(\"cherry\")\n}\nresult := it.FilterMapI(seq, func(s string, index int) (string, bool) {\n    if index%2 == 0 {\n        return fmt.Sprintf(\"%s-%d\", s, index), true\n    }\n    return \"\", false\n})\n// iter.Seq[string] yielding \"apple-0\", \"cherry-2\"\n```"
  },
  {
    "path": "docs/data/it-filtermaptoseq.md",
    "content": "---\nname: FilterMapToSeq\nslug: filtermaptoseq\nsourceRef: it/map.go#L178\ncategory: it\nsubCategory: map\nsignatures:\n  - \"func FilterMapToSeq[K comparable, V, R any](in map[K]V, transform func(key K, value V) (R, bool)) iter.Seq[R]\"\nvariantHelpers:\n  - it#map#filtermaptoseq\nsimilarHelpers:\n  - it#map#maptoseq\n  - core#map#filtermaptoslice\n  - it#map#filterkeys\n  - it#map#filtervalues\nposition: 54\n---\n\nTransforms a map into a sequence by applying a transform function to each key-value pair, but only includes values where the transform function returns true as the second value.\n\n```go\nm := map[string]int{\n    \"apple\":  3,\n    \"banana\": 0,\n    \"cherry\": 2,\n    \"date\":   0,\n}\nresult := it.FilterMapToSeq(m, func(key string, value int) (string, bool) {\n    if value > 0 {\n        return fmt.Sprintf(\"%s:%d\", key, value), true\n    }\n    return \"\", false\n})\n// iter.Seq[string] yielding \"apple:3\", \"cherry:2\" (only entries with value > 0)\n\npersonMap := map[string]int{\"alice\": 25, \"bob\": 30, \"charlie\": 15}\ntype Person struct {\n    Name string\n    Age  int\n}\nresult = it.FilterMapToSeq(personMap, func(name string, age int) (Person, bool) {\n    person := Person{Name: name, Age: age}\n    return person, age >= 18\n})\n// iter.Seq[Person] yielding {Name: \"alice\", Age: 25}, {Name: \"bob\", Age: 30} (only adults)\n\ndataMap := map[string]float64{\"a\": 1.5, \"b\": -2.0, \"c\": 3.14}\nresult = it.FilterMapToSeq(dataMap, func(key string, value float64) (int, bool) {\n    if value > 0 {\n        return int(value * 100), true\n    }\n    return 0, false\n})\n// iter.Seq[int] yielding 150, 314 (1.5*100, 3.14*100 rounded)\n```"
  },
  {
    "path": "docs/data/it-filtervalues.md",
    "content": "---\nname: FilterValues\nslug: filtervalues\nsourceRef: it/map.go#L253\ncategory: it\nsubCategory: map\nsignatures:\n  - \"func FilterValues[K comparable, V any](in map[K]V, predicate func(key K, value V) bool) []V\"\nvariantHelpers:\n  - it#map#filtervalues\nsimilarHelpers:\n  - core#map#filtervalues\n  - it#map#filterkeys\n  - it#map#keys\n  - it#map#values\nposition: 58\n---\n\nFilters map values based on a predicate function that takes both key and value. Returns a slice of values that satisfy the predicate.\n\n```go\nm := map[string]int{\n    \"apple\":  3,\n    \"banana\": 5,\n    \"cherry\": 2,\n    \"date\":   0,\n}\nresult := it.FilterValues(m, func(key string, value int) bool {\n    return value > 2\n})\n// []int{3, 5} (values > 2, corresponds to \"apple\" and \"banana\")\n\nnumberMap := map[int]string{1: \"one\", 2: \"two\", 3: \"three\", 4: \"four\"}\nresult = it.FilterValues(numberMap, func(key int, value string) bool {\n    return len(value) == 3\n})\n// []string{\"one\", \"two\", \"three\"} (values with length 3)\n\npersonMap := map[string]int{\"alice\": 25, \"bob\": 30, \"charlie\": 17}\nresult = it.FilterValues(personMap, func(key string, age int) bool {\n    return strings.HasPrefix(key, \"a\") && age >= 20\n})\n// []int{25} (value for \"alice\" only)\n\nemptyMap := map[string]int{}\nresult = it.FilterValues(emptyMap, func(key string, value int) bool {\n    return true\n})\n// []int{} (empty map)\n\ndataMap := map[string]float64{\"a\": 1.5, \"b\": -2.0, \"c\": 0.0, \"d\": 3.14}\nresult = it.FilterValues(dataMap, func(key string, value float64) bool {\n    return value > 0\n})\n// []float64{1.5, 3.14} (positive values only)\n```"
  },
  {
    "path": "docs/data/it-find.md",
    "content": "---\nname: Find\nslug: find\nsourceRef: it/find.go#L105\ncategory: it\nsubCategory: find\nsignatures:\n  - \"func Find[T any](collection iter.Seq[T], predicate func(item T) bool) (T, bool)\"\nplayUrl: https://go.dev/play/p/4w28pF_l58a\nvariantHelpers:\n  - it#find#find\nsimilarHelpers:\n  - core#slice#find\n  - it#find#findindexof\n  - it#find#findorelse\nposition: 40\n---\n\nSearches for an element in a sequence based on a predicate function. Returns the element and true if found, zero value and false if not found.\n\nExamples:\n\n```go\nseq := func(yield func(int) bool) {\n    _ = yield(10)\n    _ = yield(20)\n    _ = yield(30)\n    _ = yield(40)\n}\nfound, ok := it.Find(seq, func(x int) bool {\n    return x > 25\n})\n// found == 30, ok == true\n```\n\n```go\nseq := func(yield func(string) bool) {\n    _ = yield(\"apple\")\n    _ = yield(\"banana\")\n    _ = yield(\"cherry\")\n}\nfound, ok := it.Find(seq, func(s string) bool {\n    return len(s) > 10\n})\n// found == \"\", ok == false (no element longer than 10 chars)\n```"
  },
  {
    "path": "docs/data/it-findduplicates.md",
    "content": "---\nname: FindDuplicates\nslug: findduplicates\nsourceRef: it/find.go#L196\ncategory: it\nsubCategory: find\nsignatures:\n  - \"func FindDuplicates[T comparable, I ~func(func(T) bool)](collection I) I\"\nplayUrl: https://go.dev/play/p/dw-VLQXKijT\nvariantHelpers:\n  - it#find#findduplicates\nsimilarHelpers:\n  - core#slice#findduplicates\n  - it#find#finduniques\n  - it#find#findduplicatesby\nposition: 90\n---\n\nReturns the first occurrence of each duplicated element in the collection (elements that appear more than once).\n\nExamples:\n\n```go\nseq := func(yield func(int) bool) {\n    _ = yield(1)\n    _ = yield(2)\n    _ = yield(2)\n    _ = yield(3)\n    _ = yield(4)\n    _ = yield(4)\n    _ = yield(4)\n}\ndupSeq := it.FindDuplicates(seq)\nvar result []int\nfor v := range dupSeq {\n    result = append(result, v)\n}\n// result contains 2, 4 (first occurrence of each duplicated element)\n```\n\n```go\nseq := func(yield func(string) bool) {\n    _ = yield(\"apple\")\n    _ = yield(\"banana\")\n    _ = yield(\"apple\")\n    _ = yield(\"cherry\")\n    _ = yield(\"banana\")\n}\ndupSeq := it.FindDuplicates(seq)\nvar result []string\nfor v := range dupSeq {\n    result = append(result, v)\n}\n// result contains \"apple\", \"banana\" (duplicated elements)\n```"
  },
  {
    "path": "docs/data/it-findduplicatesby.md",
    "content": "---\nname: FindDuplicatesBy\nslug: findduplicatesby\nsourceRef: it/find.go#L200\ncategory: it\nsubCategory: find\nsignatures:\n  - \"func FindDuplicatesBy[T any, U comparable, I ~func(func(T) bool)](collection I, transform func(item T) U) I\"\nplayUrl: https://go.dev/play/p/tm1tZdC93OH\nvariantHelpers:\n  - it#find#findduplicatesby\nsimilarHelpers:\n  - core#slice#findduplicatesby\nposition: 640\n---\n\nReturns a sequence with the first occurrence of each duplicated element in the collection, based on a transform function.\n\nThe order of result values is determined by the order duplicates occur in the sequence. A transform function is\ninvoked for each element in the sequence to generate the criterion by which uniqueness is computed.\nWill allocate a map large enough to hold all distinct transformed elements.\nLong heterogeneous input sequences can cause excessive memory usage.\n\nExamples:\n\n```go\n// Find duplicate people by age\ntype Person struct {\n    Name string\n    Age  int\n}\npeople := it.Slice([]Person{\n    {Name: \"Alice\", Age: 30},\n    {Name: \"Bob\", Age: 25},\n    {Name: \"Charlie\", Age: 30},  // Same age as Alice - Alice is returned\n    {Name: \"Diana\", Age: 30},   // Same age as Alice - already marked as duplicate\n    {Name: \"Eve\", Age: 25},     // Same age as Bob - Bob is returned\n})\nduplicates := it.FindDuplicatesBy(people, func(p Person) int { return p.Age })\n// duplicates: sequence with Alice (age 30) and Bob (age 25)\n\n// Find duplicate strings by length\nwords := it.Slice([]string{\"hello\", \"world\", \"hi\", \"go\", \"bye\", \"yes\"})\nduplicates := it.FindDuplicatesBy(words, func(s string) int { return len(s) })\n// duplicates: sequence with \"hello\" (length 5, also \"world\" has length 5)\n// and \"hi\" (length 2, also \"go\", \"yes\" have length 2)\n\n// Find duplicate items by first letter\nitems := it.Slice([]string{\"apple\", \"apricot\", \"banana\", \"blueberry\", \"cherry\", \"cranberry\"})\nduplicates := it.FindDuplicatesBy(items, func(s string) byte { return s[0] })\n// duplicates: sequence with \"apple\" (starts with 'a', also \"apricot\"),\n// \"banana\" (starts with 'b', also \"blueberry\"),\n// \"cherry\" (starts with 'c', also \"cranberry\")\n\n// Find duplicate numbers by modulo\nnumbers := it.Slice([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12})\nduplicates := it.FindDuplicatesBy(numbers, func(n int) int { return n % 3 })\n// duplicates: sequence with 1, 2, 3 (remainders 1, 2, 0 appear multiple times)\n\n// Find duplicate structs by composite key\ntype Order struct {\n    CustomerID string\n    ProductID  string\n}\norders := it.Slice([]Order{\n    {CustomerID: \"A\", ProductID: \"1\"},\n    {CustomerID: \"A\", ProductID: \"2\"},\n    {CustomerID: \"B\", ProductID: \"1\"},  // Same customer as first\n    {CustomerID: \"C\", ProductID: \"3\"},\n    {CustomerID: \"A\", ProductID: \"3\"},  // Same customer as first two\n})\nduplicates := it.FindDuplicatesBy(orders, func(o Order) string { return o.CustomerID })\n// duplicates: sequence with first order {CustomerID: \"A\", ProductID: \"1\"}\n\n// Find duplicate items by case-insensitive comparison\nwords := it.Slice([]string{\"Hello\", \"hello\", \"WORLD\", \"world\", \"Go\", \"GO\", \"go\"})\nduplicates := it.FindDuplicatesBy(words, func(s string) string { return strings.ToLower(s) })\n// duplicates: sequence with \"Hello\", \"WORLD\", \"Go\" (first occurrences of each case-insensitive duplicate)\n\n// Find duplicate dates by year-month\nimport \"time\"\ndates := it.Slice([]time.Time{\n    time.Date(2023, 1, 15, 0, 0, 0, 0, time.UTC),\n    time.Date(2023, 1, 20, 0, 0, 0, 0, time.UTC),  // Same month as first\n    time.Date(2023, 2, 10, 0, 0, 0, 0, time.UTC),\n    time.Date(2022, 1, 5, 0, 0, 0, 0, time.UTC),   // Different year\n    time.Date(2023, 2, 25, 0, 0, 0, 0, time.UTC),  // Same month as third\n})\nduplicates := it.FindDuplicatesBy(dates, func(t time.Time) string {\n    return fmt.Sprintf(\"%d-%02d\", t.Year(), t.Month())\n})\n// duplicates: sequence with first January date and first February date\n\n// Find duplicate emails by domain\ntype Email struct {\n    Address string\n}\nemails := it.Slice([]Email{\n    {Address: \"user1@example.com\"},\n    {Address: \"user2@example.com\"},  // Same domain as first\n    {Address: \"user3@gmail.com\"},\n    {Address: \"user4@example.com\"},  // Same domain as first two\n    {Address: \"user5@yahoo.com\"},\n})\nduplicates := it.FindDuplicatesBy(emails, func(e Email) string {\n    parts := strings.Split(e.Address, \"@\")\n    if len(parts) > 1 {\n        return parts[1]\n    }\n    return \"\"\n})\n// duplicates: sequence with first email {Address: \"user1@example.com\"}\n```"
  },
  {
    "path": "docs/data/it-findindexof.md",
    "content": "---\nname: FindIndexOf\nslug: findindexof\nsourceRef: it/find.go#L112\ncategory: it\nsubCategory: find\nsignatures:\n  - \"func FindIndexOf[T any](collection iter.Seq[T], predicate func(item T) bool) (T, int, bool)\"\nplayUrl: https://go.dev/play/p/ihchBAEkhXO\nvariantHelpers:\n  - it#find#findindexof\nsimilarHelpers:\n  - core#slice#findindexof\n  - it#find#find\n  - it#find#findlastindexof\nposition: 50\n---\n\nSearches for an element based on a predicate and returns the element, its index, and true if found. Returns zero value, -1, and false if not found.\n\nExamples:\n\n```go\nseq := func(yield func(int) bool) {\n    _ = yield(10)\n    _ = yield(20)\n    _ = yield(30)\n    _ = yield(40)\n}\nfound, index, ok := it.FindIndexOf(seq, func(x int) bool {\n    return x > 25\n})\n// found == 30, index == 2, ok == true\n```\n\n```go\nseq := func(yield func(string) bool) {\n    _ = yield(\"apple\")\n    _ = yield(\"banana\")\n    _ = yield(\"cherry\")\n}\nfound, index, ok := it.FindIndexOf(seq, func(s string) bool {\n    return s == \"orange\"\n})\n// found == \"\", index == -1, ok == false\n```"
  },
  {
    "path": "docs/data/it-findlastindexof.md",
    "content": "---\nname: FindLastIndexOf\nslug: findlastindexof\nsourceRef: it/find.go#L127\ncategory: it\nsubCategory: find\nsignatures:\n  - \"func FindLastIndexOf[T any](collection iter.Seq[T], predicate func(item T) bool) (T, int, bool)\"\nplayUrl: https://go.dev/play/p/ezz6hXaC4Md\nvariantHelpers:\n  - it#find#findlastindexof\nsimilarHelpers:\n  - core#slice#findlastindexof\n  - it#find#findindexof\n  - it#find#find\nposition: 60\n---\n\nSearches for the last element matching a predicate and returns the element, its index, and true if found. Returns zero value, -1, and false if not found.\n\nExamples:\n\n```go\nseq := func(yield func(int) bool) {\n    _ = yield(10)\n    _ = yield(20)\n    _ = yield(30)\n    _ = yield(20)\n    _ = yield(40)\n}\nfound, index, ok := it.FindLastIndexOf(seq, func(x int) bool {\n    return x == 20\n})\n// found == 20, index == 3, ok == true\n```\n\n```go\nseq := func(yield func(string) bool) {\n    _ = yield(\"apple\")\n    _ = yield(\"banana\")\n    _ = yield(\"cherry\")\n}\nfound, index, ok := it.FindLastIndexOf(seq, func(s string) bool {\n    return len(s) > 10\n})\n// found == \"\", index == -1, ok == false\n```"
  },
  {
    "path": "docs/data/it-findorelse.md",
    "content": "---\nname: FindOrElse\nslug: findorelse\nsourceRef: it/find.go#L147\ncategory: it\nsubCategory: find\nsignatures:\n  - \"func FindOrElse[T any](collection iter.Seq[T], fallback T, predicate func(item T) bool) T\"\nplayUrl: https://go.dev/play/p/1harvaiGMfI\nvariantHelpers:\n  - it#find#findorelse\nsimilarHelpers:\n  - core#slice#findorelse\n  - it#find#find\nposition: 70\n---\n\nSearches for an element using a predicate or returns a fallback value if not found.\n\nExamples:\n\n```go\nseq := func(yield func(int) bool) {\n    _ = yield(10)\n    _ = yield(20)\n    _ = yield(30)\n    _ = yield(40)\n}\nresult := it.FindOrElse(seq, 99, func(x int) bool {\n    return x > 25\n})\n// result == 30\n```\n\n```go\nseq := func(yield func(string) bool) {\n    _ = yield(\"apple\")\n    _ = yield(\"banana\")\n    _ = yield(\"cherry\")\n}\nresult := it.FindOrElse(seq, \"unknown\", func(s string) bool {\n    return len(s) > 10\n})\n// result == \"unknown\" (fallback value)\n```"
  },
  {
    "path": "docs/data/it-finduniques.md",
    "content": "---\nname: FindUniques\nslug: finduniques\nsourceRef: it/find.go#L159\ncategory: it\nsubCategory: find\nsignatures:\n  - \"func FindUniques[T comparable, I ~func(func(T) bool)](collection I) I\"\nplayUrl: https://go.dev/play/p/O8dwXEbT56F\nvariantHelpers:\n  - it#find#finduniques\nsimilarHelpers:\n  - core#slice#finduniques\n  - it#find#findduplicates\n  - it#find#finduniquesby\nposition: 80\n---\n\nReturns a sequence with elements that appear only once in the original collection (duplicates are removed).\n\nExamples:\n\n```go\nseq := func(yield func(int) bool) {\n    _ = yield(1)\n    _ = yield(2)\n    _ = yield(2)\n    _ = yield(3)\n    _ = yield(4)\n    _ = yield(4)\n}\nuniqueSeq := it.FindUniques(seq)\nvar result []int\nfor v := range uniqueSeq {\n    result = append(result, v)\n}\n// result contains 1, 3 (elements that appear only once)\n```\n\n```go\nseq := func(yield func(string) bool) {\n    _ = yield(\"apple\")\n    _ = yield(\"banana\")\n    _ = yield(\"apple\")\n    _ = yield(\"cherry\")\n}\nuniqueSeq := it.FindUniques(seq)\nvar result []string\nfor v := range uniqueSeq {\n    result = append(result, v)\n}\n// result contains \"banana\", \"cherry\" (unique elements)\n```"
  },
  {
    "path": "docs/data/it-finduniquesby.md",
    "content": "---\nname: FindUniquesBy\nslug: finduniquesby\nsourceRef: it/find.go#L163\ncategory: it\nsubCategory: find\nsignatures:\n  - \"func FindUniquesBy[T any, U comparable, I ~func(func(T) bool)](collection I, transform func(item T) U) I\"\nplayUrl: https://go.dev/play/p/TiwGIzeDuML\nvariantHelpers:\n  - it#find#finduniquesby\nsimilarHelpers:\n  - core#slice#finduniquesby\nposition: 630\n---\n\nReturns a sequence with all the elements that appear in the collection only once, based on a transform function.\n\nThe order of result values is determined by the order they occur in the collection. A transform function is\ninvoked for each element in the sequence to generate the criterion by which uniqueness is computed.\nWill iterate through the entire sequence before yielding and allocate a map large enough to hold all distinct transformed elements.\nLong heterogeneous input sequences can cause excessive memory usage.\n\nExamples:\n\n```go\n// Find unique people by age\ntype Person struct {\n    Name string\n    Age  int\n}\npeople := it.Slice([]Person{\n    {Name: \"Alice\", Age: 30},\n    {Name: \"Bob\", Age: 25},\n    {Name: \"Charlie\", Age: 30},  // Same age as Alice, so Alice is not unique\n    {Name: \"Diana\", Age: 28},\n})\nuniques := it.FindUniquesBy(people, func(p Person) int { return p.Age })\n// uniques: sequence with Bob (age 25) and Diana (age 28)\n\n// Find unique strings by length\nwords := it.Slice([]string{\"hello\", \"world\", \"hi\", \"go\", \"bye\"})\nuniques := it.FindUniquesBy(words, func(s string) int { return len(s) })\n// uniques: sequence with words of unique lengths\n// \"hello\" (5), \"world\" (5) - not unique due to same length\n// \"hi\" (2), \"go\" (2), \"bye\" (3) - \"bye\" is unique (length 3)\n\n// Find unique items by first letter\nitems := it.Slice([]string{\"apple\", \"apricot\", \"banana\", \"blueberry\", \"cherry\"})\nuniques := it.FindUniquesBy(items, func(s string) byte { return s[0] })\n// uniques: sequence with \"cherry\" (only word starting with 'c')\n\n// Find unique numbers by modulo\nnumbers := it.Slice([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10})\nuniques := it.FindUniquesBy(numbers, func(n int) int { return n % 3 })\n// uniques: sequence with numbers that have unique remainders when divided by 3\n\n// Find unique structs by composite key\ntype Order struct {\n    CustomerID string\n    ProductID  string\n}\norders := it.Slice([]Order{\n    {CustomerID: \"A\", ProductID: \"1\"},\n    {CustomerID: \"A\", ProductID: \"2\"},\n    {CustomerID: \"B\", ProductID: \"1\"},  // Same customer as first orders\n    {CustomerID: \"C\", ProductID: \"3\"},\n})\nuniques := it.FindUniquesBy(orders, func(o Order) string { return o.CustomerID })\n// uniques: sequence with Order{CustomerID: \"C\", ProductID: \"3\"} only\n\n// Find unique items by case-insensitive comparison\nwords := it.Slice([]string{\"Hello\", \"hello\", \"WORLD\", \"world\", \"Go\"})\nuniques := it.FindUniquesBy(words, func(s string) string { return strings.ToLower(s) })\n// uniques: sequence with \"Go\" only (others have case-insensitive duplicates)\n\n// Find unique dates by year-month\nimport \"time\"\ndates := it.Slice([]time.Time{\n    time.Date(2023, 1, 15, 0, 0, 0, 0, time.UTC),\n    time.Date(2023, 1, 20, 0, 0, 0, 0, time.UTC),  // Same month as first\n    time.Date(2023, 2, 10, 0, 0, 0, 0, time.UTC),\n    time.Date(2022, 1, 5, 0, 0, 0, 0, time.UTC),   // Different year\n})\nuniques := it.FindUniquesBy(dates, func(t time.Time) string {\n    return fmt.Sprintf(\"%d-%02d\", t.Year(), t.Month())\n})\n// uniques: sequence with dates from unique year-month combinations\n```"
  },
  {
    "path": "docs/data/it-first.md",
    "content": "---\nname: First\nslug: first\nsourceRef: it/find.go#L362\ncategory: it\nsubCategory: find\nsignatures:\n  - \"func First[T any](collection iter.Seq[T]) (T, bool)\"\nplayUrl: https://go.dev/play/p/EhNyrc8jPfY\nvariantHelpers:\n  - it#find#first\nsimilarHelpers:\n  - core#slice#first\n  - it#find#last\n  - it#find#firstor\nposition: 120\n---\n\nReturns the first element of a collection and a boolean indicating availability. Returns zero value and false if the collection is empty.\n\nExamples:\n\n```go\nseq := func(yield func(int) bool) {\n    _ = yield(10)\n    _ = yield(20)\n    _ = yield(30)\n}\nfirst, ok := it.First(seq)\n// first == 10, ok == true\n```\n\n```go\nseq := func(yield func(string) bool) {\n    // empty sequence\n}\nfirst, ok := it.First(seq)\n// first == \"\", ok == false (zero value for string)\n```"
  },
  {
    "path": "docs/data/it-firstor.md",
    "content": "---\nname: FirstOr\nslug: firstor\nsourceRef: it/find.go#L377\ncategory: it\nsubCategory: find\nsignatures:\n  - \"func FirstOr[T any](collection iter.Seq[T], fallback T) T\"\nplayUrl: https://go.dev/play/p/wGFXI5NHkE2\nvariantHelpers:\n  - it#find#firstor\nsimilarHelpers:\n  - core#slice#firstor\nposition: 550\n---\n\nReturns the first element of a collection or the fallback value if empty.\n\nWill iterate at most once.\n\nExamples:\n\n```go\n// Get the first element or fallback value\nnumbers := it.Slice([]int{5, 2, 8, 1, 9})\nfirst := it.FirstOr(numbers, 42)\n// first: 5\n\n// With empty collection\nempty := it.Slice([]int{})\nfirst := it.FirstOr(empty, 42)\n// first: 42 (fallback value)\n\n// With strings\nwords := it.Slice([]string{\"hello\", \"world\", \"go\"})\nfirst := it.FirstOr(words, \"fallback\")\n// first: \"hello\"\n\nemptyWords := it.Slice([]string{})\nfirst := it.FirstOr(emptyWords, \"fallback\")\n// first: \"fallback\"\n\n// With structs\ntype Person struct {\n    Name string\n    Age  int\n}\npeople := it.Slice([]Person{\n    {Name: \"Alice\", Age: 30},\n    {Name: \"Bob\", Age: 25},\n})\nfirst := it.FirstOr(people, Person{Name: \"Default\", Age: 0})\n// first: {Name: \"Alice\", Age: 30}\n\nemptyPeople := it.Slice([]Person{})\nfirst := it.FirstOr(emptyPeople, Person{Name: \"Default\", Age: 0})\n// first: {Name: \"Default\", Age: 0} (fallback value)\n\n// Using with pointers\npointers := it.Slice([]*int{ptr(5), ptr(10), ptr(15)})\nfirst := it.FirstOr(pointers, nil)\n// first: pointer to 5\n\nemptyPointers := it.Slice([]*int{})\nfirst := it.FirstOr(emptyPointers, nil)\n// first: nil (fallback value)\n```"
  },
  {
    "path": "docs/data/it-firstorempty.md",
    "content": "---\nname: FirstOrEmpty\nslug: firstorempty\nsourceRef: it/find.go#L370\ncategory: it\nsubCategory: find\nsignatures:\n  - \"func FirstOrEmpty[T any](collection iter.Seq[T]) T\"\nplayUrl: https://go.dev/play/p/NTUTgPCfevx\nvariantHelpers:\n  - it#find#firstorempty\nsimilarHelpers:\n  - core#slice#firstorempty\nposition: 540\n---\n\nReturns the first element of a collection or zero value if empty.\n\nWill iterate at most once.\n\nExamples:\n\n```go\n// Get the first element or zero value\nnumbers := it.Slice([]int{5, 2, 8, 1, 9})\nfirst := it.FirstOrEmpty(numbers)\n// first: 5\n\n// With empty collection\nempty := it.Slice([]int{})\nfirst := it.FirstOrEmpty(empty)\n// first: 0 (zero value for int)\n\n// With strings\nwords := it.Slice([]string{\"hello\", \"world\", \"go\"})\nfirst := it.FirstOrEmpty(words)\n// first: \"hello\"\n\nemptyWords := it.Slice([]string{})\nfirst := it.FirstOrEmpty(emptyWords)\n// first: \"\" (zero value for string)\n\n// With structs\ntype Person struct {\n    Name string\n    Age  int\n}\npeople := it.Slice([]Person{\n    {Name: \"Alice\", Age: 30},\n    {Name: \"Bob\", Age: 25},\n})\nfirst := it.FirstOrEmpty(people)\n// first: {Name: \"Alice\", Age: 30}\n\nemptyPeople := it.Slice([]Person{})\nfirst := it.FirstOrEmpty(emptyPeople)\n// first: {Name: \"\", Age: 0} (zero value for Person)\n```"
  },
  {
    "path": "docs/data/it-flatmap.md",
    "content": "---\nname: FlatMap\nslug: flatmap\nsourceRef: it/seq.go#L109\ncategory: it\nsubCategory: sequence\nsignatures:\n  - \"func FlatMap[T, R any](collection iter.Seq[T], transform func(item T) iter.Seq[R]) iter.Seq[R]\"\n  - \"func FlatMapI[T, R any](collection iter.Seq[T], transform func(item T, index int) iter.Seq[R]) iter.Seq[R]\"\nplayUrl: https://go.dev/play/p/6toB9w2gpSy\nvariantHelpers:\n  - it#sequence#flatmap\n  - it#sequence#flatmapi\nsimilarHelpers:\n  - core#slice#flatmap\n  - it#sequence#map\nposition: 120\n---\n\nTransforms and flattens a sequence to another type. Each element is transformed into a sequence, then all sequences are concatenated.\n\nExamples:\n\n```go\nseq := func(yield func([]int) bool) {\n    _ = yield([]int{1, 2})\n    _ = yield([]int{3, 4})\n    _ = yield([]int{5})\n}\nflattened := it.FlatMap(seq, func(arr []int) iter.Seq[int] {\n    return func(yield func(int) bool) {\n        for _, v := range arr {\n            if !yield(v * 2) {\n                return\n            }\n        }\n    }\n})\nvar result []int\nfor v := range flattened {\n    result = append(result, v)\n}\n// result contains 2, 4, 6, 8, 10\n```\n\n### FlatMapI\n\nTransforms and flattens a sequence to another type. Each element is transformed into a sequence with access to the element's index, then all sequences are concatenated.\n\n```go\nseq := func(yield func(string) bool) {\n    _ = yield(\"a\")\n    _ = yield(\"b\")\n    _ = yield(\"c\")\n}\nflattened := it.FlatMapI(seq, func(s string, index int) iter.Seq[string] {\n    return func(yield func(string) bool) {\n        for i := 0; i <= index; i++ {\n            if !yield(fmt.Sprintf(\"%s-%d\", s, i)) {\n                return\n            }\n        }\n    }\n})\nvar result []string\nfor v := range flattened {\n    result = append(result, v)\n}\n// result contains \"a-0\", \"b-0\", \"b-1\", \"c-0\", \"c-1\", \"c-2\"\n```"
  },
  {
    "path": "docs/data/it-flatten.md",
    "content": "---\nname: Flatten\nslug: flatten\nsourceRef: it/seq.go#L26\ncategory: it\nsubCategory: sequence\nsignatures:\n  - \"func Flatten[T any, I ~func(func(T) bool)](collection []I) I\"\nvariantHelpers: []\nplayUrl: https://go.dev/play/p/CCklxuNk7Lm\nsimilarHelpers:\n  - core#slice#flatten\nposition: 172\n---\n\nFlatten returns a sequence a single level deep.\n\n```go\nseq1 := func(yield func(int) bool) {\n    yield(1)\n    yield(2)\n}\nseq2 := func(yield func(int) bool) {\n    yield(3)\n    yield(4)\n}\n\nflattened := it.Flatten([]iter.Seq[int]{seq1, seq2})\nvar result []int\nfor item := range flattened {\n    result = append(result, item)\n}\n// result contains [1, 2, 3, 4]\n```"
  },
  {
    "path": "docs/data/it-foreach.md",
    "content": "---\nname: ForEach\nslug: foreach\nsourceRef: it/seq.go#L166\ncategory: it\nsubCategory: sequence\nsignatures:\n  - \"func ForEach[T any](collection iter.Seq[T], callback func(item T))\"\nplayUrl: \"https://go.dev/play/p/agIsKpG-S-P\"\nvariantHelpers:\n  - it#sequence#foreach\n  - it#sequence#foreachi\nsimilarHelpers:\n  - core#slice#foreach\n  - it#sequence#map\nposition: 40\n---\n\nIterates over elements and invokes a callback function for each element.\n\nExamples:\n\n```go\nseq := func(yield func(int) bool) {\n    _ = yield(1)\n    _ = yield(2)\n    _ = yield(3)\n}\nvar result []int\nit.ForEach(seq, func(item int) {\n    result = append(result, item*2)\n})\n// result contains 2, 4, 6\n```\n\n```go\nseq := func(yield func(string) bool) {\n    _ = yield(\"hello\")\n    _ = yield(\"world\")\n}\nit.ForEach(seq, func(item string) {\n    fmt.Println(\"Item:\", item)\n})\n// Prints: Item: hello\n//        Item: world\n```"
  },
  {
    "path": "docs/data/it-foreachwhile.md",
    "content": "---\nname: ForEachWhile\nslug: foreachwhile\nsourceRef: it/seq.go#L180\ncategory: it\nsubCategory: sequence\nsignatures:\n  - \"func ForEachWhile[T any](collection iter.Seq[T], predicate func(item T) bool)\"\n  - \"func ForEachWhileI[T any](collection iter.Seq[T], predicate func(item T, index int) bool)\"\nvariantHelpers:\n  - it#sequence#foreachwhile\n  - it#sequence#foreachwhilei\nsimilarHelpers:\n  - it#sequence#foreach\nposition: 160\n---\n\nForEachWhile iterates over elements of collection and invokes predicate for each element.\nThe predicate return value decides to continue or break, like do while().\n\n```go\ncollection := func(yield func(int) bool) {\n    yield(1)\n    yield(2)\n    yield(3)\n    yield(4)\n    yield(5)\n}\n\ncalled := 0\nit.ForEachWhile(collection, func(item int) bool {\n    called++\n    return item < 3\n})\n// called is 3 (elements 1, 2, 3 were processed)\n```\n\nForEachWhileI iterates over elements of collection and invokes predicate for each element with index.\nThe predicate return value decides to continue or break, like do while().\n\n```go\ncollection := func(yield func(string) bool) {\n    yield(\"a\")\n    yield(\"b\")\n    yield(\"c\")\n    yield(\"d\")\n}\n\ncalled := 0\nit.ForEachWhileI(collection, func(item string, index int) bool {\n    called++\n    return index < 2\n})\n// called is 3 (elements at indices 0, 1, 2 were processed)\n```"
  },
  {
    "path": "docs/data/it-fromanyseq.md",
    "content": "---\nname: FromAnySeq\nslug: fromanyseq\nsourceRef: it/type_manipulation.go#L11\ncategory: it\nsubCategory: type\nsignatures:\n  - \"func FromAnySeq[T any](collection iter.Seq[any]) iter.Seq[T]\"\nvariantHelpers:\n  - it#type#toanyseq\nplayUrl: \"https://go.dev/play/p/wnOma1j5Uzu\"\nsimilarHelpers:\n  - core#type#fromany\nposition: 244\n---\n\nFromAnySeq returns a sequence with all elements mapped to a type.\nPanics on type conversion failure.\n\n```go\ncollection := func(yield func(any) bool) {\n    yield(1)\n    yield(2)\n    yield(\"three\") // This will cause panic\n}\n\nintSeq := it.FromAnySeq[int](collection)\n// This will panic when trying to convert \"three\" to int\n```"
  },
  {
    "path": "docs/data/it-fromentries.md",
    "content": "---\nname: FromEntries\nslug: fromentries\nsourceRef: it/map.go#L96\ncategory: it\nsubCategory: map\nsignatures:\n  - \"func FromEntries[K comparable, V any](entries ...iter.Seq2[K, V]) map[K]V\"\nplayUrl: https://go.dev/play/p/MgEF1J5-tuK\nvariantHelpers:\n  - it#map#fromentries\n  - it#map#frompairs\nsimilarHelpers:\n  - core#slice#fromentries\n  - it#map#entries\nposition: 30\n---\n\nTransforms a sequence of key/value pairs into a map. Accepts multiple sequences and merges them.\n\nExamples:\n\n```go\nentries := func(yield func(string, int) bool) {\n    _ = yield(\"apple\", 1)\n    _ = yield(\"banana\", 2)\n    _ = yield(\"cherry\", 3)\n}\nm := it.FromEntries(entries)\n// m == map[string]int{\"apple\": 1, \"banana\": 2, \"cherry\": 3}\n```\n\n```go\nentries1 := func(yield func(string, int) bool) {\n    _ = yield(\"a\", 1)\n    _ = yield(\"b\", 2)\n}\nentries2 := func(yield func(string, int) bool) {\n    _ = yield(\"c\", 3)\n    _ = yield(\"d\", 4)\n}\nm := it.FromEntries(entries1, entries2)\n// m contains all entries from both sequences\n```"
  },
  {
    "path": "docs/data/it-frompairs.md",
    "content": "---\nname: FromPairs\nslug: frompairs\nsourceRef: it/map.go#L104\ncategory: it\nsubCategory: map\nsignatures:\n  - \"func FromPairs[K comparable, V any](entries ...iter.Seq2[K, V]) map[K]V\"\nplayUrl: \"https://go.dev/play/p/K3wL9j7TmXs\" \nvariantHelpers:\n  - it#map#fromentries\nsimilarHelpers:\n  - core#slice#frompairs\n  - core#slice#fromentries\nposition: 20\n---\n\nTransforms a sequence of key/value pairs into a map. Alias of FromEntries().\n\n```go\npairs := it.Seq2(func(yield func(string, int) bool) {\n    yield(\"a\", 1)\n    yield(\"b\", 2)\n    yield(\"c\", 3)\n})\n\nresult := it.FromPairs(pairs)\n// map[string]int{\"a\": 1, \"b\": 2, \"c\": 3}\n```\n"
  },
  {
    "path": "docs/data/it-fromseqptr.md",
    "content": "---\nname: FromSeqPtr\nslug: fromseqptr\nsourceRef: it/type_manipulation.go#L11\ncategory: it\nsubCategory: type\nsignatures:\n  - \"func FromSeqPtr[T any](collection iter.Seq[*T]) iter.Seq[T]\"\nvariantHelpers:\n  - it#type#fromseqptror\nplayUrl: \"https://go.dev/play/p/_eO6scpLcBF\"\nsimilarHelpers:\n  - core#type#fromptr\nposition: 241\n---\n\nFromSeqPtr returns a sequence with the pointer values.\nReturns a zero value in case of a nil pointer element.\n\n```go\none := 1\ntwo := 2\nvar three *int = nil\n\ncollection := func(yield func(*int) bool) {\n    yield(&one)\n    yield(&two)\n    yield(three)\n}\n\nvalues := it.FromSeqPtr(collection)\nvar result []int\nfor val := range values {\n    result = append(result, val)\n}\n// result contains [1, 2, 0]\n```"
  },
  {
    "path": "docs/data/it-fromseqptror.md",
    "content": "---\nname: FromSeqPtrOr\nslug: fromseqptror\nsourceRef: it/type_manipulation.go#L11\ncategory: it\nsubCategory: type\nsignatures:\n  - \"func FromSeqPtrOr[T any](collection iter.Seq[*T], fallback T) iter.Seq[T]\"\nvariantHelpers:\n  - it#type#fromseqptr\nplayUrl: \"https://go.dev/play/p/LJ17S4pvOjo\"\nsimilarHelpers: []\nposition: 242\n---\n\nFromSeqPtrOr returns a sequence with the pointer values or the fallback value.\n\n```go\none := 1\nvar two *int = nil\n\ncollection := func(yield func(*int) bool) {\n    yield(&one)\n    yield(two)\n}\n\nvalues := it.FromSeqPtrOr(collection, 99)\nvar result []int\nfor val := range values {\n    result = append(result, val)\n}\n// result contains [1, 99]\n```"
  },
  {
    "path": "docs/data/it-groupby.md",
    "content": "---\nname: GroupBy\nslug: groupby\nsourceRef: it/seq.go#L244\ncategory: it\nsubCategory: sequence\nsignatures:\n  - \"func GroupBy[T any, U comparable](collection iter.Seq[T], transform func(item T) U) map[U][]T\"\nplayUrl: https://go.dev/play/p/oRIakS89OYy\nvariantHelpers:\n  - it#sequence#groupby\nsimilarHelpers:\n  - core#slice#groupby\n  - it#sequence#partitionby\n  - it#sequence#groupbymap\nposition: 80\n---\n\nReturns an object composed of keys generated from running each element of collection through a transform function. The value of each key is an array of elements responsible for generating the key.\n\nExamples:\n\n```go\nseq := func(yield func(string) bool) {\n    _ = yield(\"apple\")\n    _ = yield(\"banana\")\n    _ = yield(\"apricot\")\n    _ = yield(\"blueberry\")\n}\ngrouped := it.GroupBy(seq, func(s string) string {\n    return string(s[0]) // group by first letter\n})\n// grouped contains map with keys: \"a\": [\"apple\", \"apricot\"], \"b\": [\"banana\", \"blueberry\"]\n```"
  },
  {
    "path": "docs/data/it-hasprefix.md",
    "content": "---\nname: HasPrefix\nslug: hasprefix\nsourceRef: it/find.go#L49\ncategory: it\nsubCategory: find\nsignatures:\n  - \"func HasPrefix[T comparable](collection iter.Seq[T], prefix ...T) bool\"\nplayUrl: https://go.dev/play/p/Fyj6uq-G5IH\nvariantHelpers:\n  - it#find#hasprefix\nsimilarHelpers:\n  - core#slice#hasprefix\n  - it#find#hassuffix\nposition: 20\n---\n\nReturns true if the collection has the specified prefix. The prefix can be specified as multiple arguments.\n\nExamples:\n\n```go\nseq := func(yield func(int) bool) {\n    _ = yield(1)\n    _ = yield(2)\n    _ = yield(3)\n    _ = yield(4)\n}\nhasPrefix := it.HasPrefix(seq, 1, 2)\n// hasPrefix == true\n```\n\n```go\nseq := func(yield func(string) bool) {\n    _ = yield(\"hello\")\n    _ = yield(\"world\")\n}\nhasPrefix := it.HasPrefix(seq, \"hello\")\n// hasPrefix == true\n```\n\n```go\nseq := func(yield func(int) bool) {\n    _ = yield(1)\n    _ = yield(2)\n    _ = yield(3)\n}\nhasPrefix := it.HasPrefix(seq, 2, 3)\n// hasPrefix == false\n```"
  },
  {
    "path": "docs/data/it-hassuffix.md",
    "content": "---\nname: HasSuffix\nslug: hassuffix\nsourceRef: it/find.go#L71\ncategory: it\nsubCategory: find\nsignatures:\n  - \"func HasSuffix[T comparable](collection iter.Seq[T], suffix ...T) bool\"\nplayUrl: https://go.dev/play/p/r6bF9Rmq5S0\nvariantHelpers:\n  - it#find#hassuffix\nsimilarHelpers:\n  - core#slice#hassuffix\n  - it#find#hasprefix\nposition: 30\n---\n\nReturns true if the collection has the specified suffix. The suffix can be specified as multiple arguments.\n\nExamples:\n\n```go\nseq := func(yield func(int) bool) {\n    _ = yield(1)\n    _ = yield(2)\n    _ = yield(3)\n    _ = yield(4)\n}\nhasSuffix := it.HasSuffix(seq, 3, 4)\n// hasSuffix == true\n```\n\n```go\nseq := func(yield func(string) bool) {\n    _ = yield(\"hello\")\n    _ = yield(\"world\")\n}\nhasSuffix := it.HasSuffix(seq, \"world\")\n// hasSuffix == true\n```\n\n```go\nseq := func(yield func(int) bool) {\n    _ = yield(1)\n    _ = yield(2)\n    _ = yield(3)\n}\nhasSuffix := it.HasSuffix(seq, 1, 2)\n// hasSuffix == false\n```"
  },
  {
    "path": "docs/data/it-indexof.md",
    "content": "---\nname: IndexOf\nslug: indexof\nsourceRef: it/find.go#L19\ncategory: it\nsubCategory: find\nsignatures:\n  - \"func IndexOf[T comparable](collection iter.Seq[T], element T) int\"\nplayUrl: \"https://go.dev/play/p/1OZHU2yfb-m\"\nvariantHelpers:\n  - it#find#indexof\nsimilarHelpers:\n  - core#slice#indexof\n  - it#find#lastindexof\nposition: 0\n---\n\nReturns the index at which the first occurrence of a value is found in the sequence, or -1 if the value is not found. Scans the sequence from the beginning and returns the position of the first matching element.\n\n```go\n// Find existing element - returns first occurrence\nseq := func(yield func(int) bool) {\n    _ = yield(10)\n    _ = yield(20)\n    _ = yield(30)\n    _ = yield(20)\n}\nidx := it.IndexOf(seq, 20)\n// idx: 1 (first occurrence of 20)\n```\n\n```go\n// Element not found - returns -1\nseq := func(yield func(string) bool) {\n    _ = yield(\"apple\")\n    _ = yield(\"banana\")\n    _ = yield(\"cherry\")\n}\nidx := it.IndexOf(seq, \"orange\")\n// idx: -1 (orange not found in sequence)\n```\n\n```go\n// Empty sequence - returns -1\nemptySeq := func(yield func(string) bool) {\n    // no elements yielded\n}\nidx := it.IndexOf(emptySeq, \"anything\")\n// idx: -1 (sequence is empty)\n```"
  },
  {
    "path": "docs/data/it-interleave.md",
    "content": "---\nname: Interleave\nslug: interleave\nsourceRef: it/seq.go#L26\ncategory: it\nsubCategory: sequence\nsignatures:\n  - \"func Interleave[T any](collections ...iter.Seq[T]) iter.Seq[T]\"\nvariantHelpers: []\nplayUrl: https://go.dev/play/p/kNvnz4ClLgH\nsimilarHelpers:\n  - core#slice#interleave\nposition: 173\n---\n\nInterleave round-robin alternating input sequences and sequentially appending value at index into result.\n\n```go\nseq1 := func(yield func(int) bool) {\n    yield(1)\n    yield(3)\n}\nseq2 := func(yield func(int) bool) {\n    yield(2)\n    yield(4)\n}\nseq3 := func(yield func(int) bool) {\n    yield(5)\n    yield(6)\n}\n\ninterleaved := it.Interleave(seq1, seq2, seq3)\nvar result []int\nfor item := range interleaved {\n    result = append(result, item)\n}\n// result contains [1, 2, 5, 3, 4, 6]\n```"
  },
  {
    "path": "docs/data/it-intersect.md",
    "content": "---\nname: Intersect\nslug: intersect\nsourceRef: it/intersect.go#L78\ncategory: it\nsubCategory: intersect\nsignatures:\n  - \"func Intersect[T comparable, I ~func(func(T) bool)](lists ...I) I\"\nplayUrl: \"https://go.dev/play/p/kz3cGhGZZWF\"\nvariantHelpers:\n  - it#intersect#intersect\nsimilarHelpers:\n  - it#intersect#intersectby\n  - core#slice#intersect\n  - core#slice#intersectby\n  - it#intersect#union\nposition: 10\n---\n\nReturns the intersection between given collections (elements present in all collections).\n\nExamples:\n\n```go\nseq1 := func(yield func(int) bool) {\n    _ = yield(1)\n    _ = yield(2)\n    _ = yield(3)\n    _ = yield(4)\n}\nseq2 := func(yield func(int) bool) {\n    _ = yield(2)\n    _ = yield(3)\n    _ = yield(5)\n}\nseq3 := func(yield func(int) bool) {\n    _ = yield(3)\n    _ = yield(2)\n    _ = yield(6)\n}\nintersection := it.Intersect(seq1, seq2, seq3)\nvar result []int\nfor v := range intersection {\n    result = append(result, v)\n}\n// result contains 2, 3 (elements present in all sequences)\n```"
  },
  {
    "path": "docs/data/it-intersectby.md",
    "content": "---\nname: IntersectBy\nslug: intersectby\nsourceRef: it/intersect.go#L78\ncategory: it\nsubCategory: intersect\nsignatures:\n  - \"func IntersectBy[T any, K comparable, I ~func(func(T) bool)](func(T) K, lists ...I) I\"\nplayUrl: https://go.dev/play/p/X2nEvHC-lE2\nvariantHelpers:\n  - it#intersect#intersectby\nsimilarHelpers:\n  - it#intersect#intersect\n  - core#slice#intersect\n  - core#slice#intersectby\n  - it#intersect#union\nposition: 10\n---\n\nReturns the intersection between given collections using a custom key selector function.\n\nExamples:\n\n```go\nseq1 := func(yield func(int) bool) {\n    _ = yield(1)\n    _ = yield(2)\n    _ = yield(3)\n    _ = yield(4)\n}\nseq2 := func(yield func(int) bool) {\n    _ = yield(2)\n    _ = yield(3)\n    _ = yield(5)\n}\nseq3 := func(yield func(int) bool) {\n    _ = yield(3)\n    _ = yield(2)\n    _ = yield(6)\n}\n\ntransform := func(v int) string {\n  return strconv.Itoa(v)\n}\n\nintersection := it.IntersectBy(transform, seq1, seq2, seq3)\n\nvar result []int\nfor v := range intersection {\n    result = append(result, v)\n}\n// result contains 2, 3 (elements present in all sequences)\n```"
  },
  {
    "path": "docs/data/it-invert.md",
    "content": "---\nname: Invert\nslug: invert\nsourceRef: it/map.go#L111\ncategory: it\nsubCategory: map\nsignatures:\n  - \"func Invert[K, V comparable](in iter.Seq2[K, V]) iter.Seq2[V, K]\"\nplayUrl: https://go.dev/play/p/Iph19Lgcsx-\nvariantHelpers:\n  - it#map#invert\nsimilarHelpers:\n  - core#slice#invert\n  - it#map#entries\nposition: 40\n---\n\nCreates a sequence composed of inverted keys and values from a sequence of key/value pairs.\n\nExamples:\n\n```go\nentries := func(yield func(string, int) bool) {\n    _ = yield(\"apple\", 1)\n    _ = yield(\"banana\", 2)\n    _ = yield(\"cherry\", 3)\n}\ninverted := it.Invert(entries)\nvar keys []int\nvar values []string\nfor k, v := range inverted {\n    keys = append(keys, k)\n    values = append(values, v)\n}\n// keys contains 1, 2, 3 and values contains \"apple\", \"banana\", \"cherry\"\n```"
  },
  {
    "path": "docs/data/it-isempty.md",
    "content": "---\nname: IsEmpty\nslug: isempty\nsourceRef: it/type_manipulation.go#L50\ncategory: it\nsubCategory: type\nsignatures:\n  - \"func IsEmpty[T any](collection iter.Seq[T]) bool\"\nplayUrl: https://go.dev/play/p/krZ-laaVi2C\nvariantHelpers:\n  - it#type#isempty\nsimilarHelpers:\n  - it#type#isnotempty\n  - it#type#empty\n  - it#sequence#length\nposition: 10\n---\n\nReturns true if the sequence is empty. Will consume the entire sequence to check.\n\nExamples:\n\n```go\nseq := func(yield func(int) bool) {\n    // empty sequence\n}\nempty := it.IsEmpty(seq)\n// empty == true\n```\n\n```go\nseq := func(yield func(int) bool) {\n    _ = yield(1)\n    _ = yield(2)\n}\nempty := it.IsEmpty(seq)\n// empty == false\n```"
  },
  {
    "path": "docs/data/it-isnotempty.md",
    "content": "---\nname: IsNotEmpty\nslug: isnotempty\nsourceRef: it/type_manipulation.go#L59\ncategory: it\nsubCategory: condition\nsignatures:\n  - \"func IsNotEmpty[T any](collection iter.Seq[T]) bool\"\nplayUrl: \"https://go.dev/play/p/G7hH3jJ0De5\" \nvariantHelpers:\n  - it#condition#isempty\nsimilarHelpers:\n  - core#slice#isnotempty\n  - core#slice#isempty\nposition: 10\n---\n\nReturns true if the collection is not empty, false otherwise.\n\n```go\nresult1 := it.IsNotEmpty(it.Range(1, 5))\n// true\n\nresult2 := it.IsNotEmpty(it.Empty[int]())\n// false\n```"
  },
  {
    "path": "docs/data/it-issorted.md",
    "content": "---\nname: IsSorted\nslug: issorted\nsourceRef: it/seq.go#L720\ncategory: it\nsubCategory: slice\nsignatures:\n  - \"func IsSorted[T constraints.Ordered](collection iter.Seq[T]) bool\"\nplayUrl: https://go.dev/play/p/o-BD4UOn-0U\nvariantHelpers: []\nsimilarHelpers:\n  - core#slice#issorted\nposition: 200\n---\n\nIsSorted checks if a sequence is sorted.\n\n```go\nsorted := func(yield func(int) bool) {\n    yield(1)\n    yield(2)\n    yield(3)\n    yield(4)\n}\nunsorted := func(yield func(int) bool) {\n    yield(1)\n    yield(3)\n    yield(2)\n    yield(4)\n}\n\nfmt.Println(it.IsSorted(sorted))    // true\nfmt.Println(it.IsSorted(unsorted))  // false\n```"
  },
  {
    "path": "docs/data/it-issortedby.md",
    "content": "---\nname: IsSortedBy\nslug: issortedby\nsourceRef: it/seq.go#L720\ncategory: it\nsubCategory: slice\nsignatures:\n  - \"func IsSortedBy[T any, K constraints.Ordered](collection iter.Seq[T], transform func(item T) K) bool\"\nplayUrl: https://go.dev/play/p/AfYOiGWa78T\nvariantHelpers: []\nsimilarHelpers:\n  - core#slice#issortedby\nposition: 201\n---\n\nIsSortedBy checks if a sequence is sorted by transform.\n\n```go\ncollection := func(yield func(string) bool) {\n    yield(\"apple\")\n    yield(\"banana\")\n    yield(\"cherry\")\n}\n\nsortedByLength := it.IsSortedBy(collection, func(s string) int {\n    return len(s)\n})\n// true (5, 6, 6 is sorted)\n```"
  },
  {
    "path": "docs/data/it-keyby.md",
    "content": "---\nname: KeyBy\nslug: keyby\nsourceRef: it/seq.go#L398\ncategory: it\nsubCategory: sequence\nsignatures:\n  - \"func KeyBy[K comparable, V any](collection iter.Seq[V], transform func(item V) K) map[K]V\"\nplayUrl: https://go.dev/play/p/MMaHpzTqY0a\nvariantHelpers:\n  - it#map#associate\nsimilarHelpers:\n  - core#slice#keyby\n  - core#slice#associate\nposition: 15\n---\n\nTransforms a sequence into a map using a transform function to generate keys.\n\n```go\nresult := it.KeyBy(it.Range(1, 5), func(item int) string {\n    return fmt.Sprintf(\"key-%d\", item)\n})\n// map[string]int{\"key-1\": 1, \"key-2\": 2, \"key-3\": 3, \"key-4\": 4}\n```"
  },
  {
    "path": "docs/data/it-keyify.md",
    "content": "---\nname: Keyify\nslug: keyify\nsourceRef: it/seq.go#L720\ncategory: it\nsubCategory: slice\nsignatures:\n  - \"func Keyify[T comparable](collection iter.Seq[T]) map[T]struct{}\"\nplayUrl: https://go.dev/play/p/aHOD29_l-rF\nvariantHelpers: []\nsimilarHelpers:\n  - core#slice#keyby\nposition: 202\n---\n\nKeyify returns a map with each unique element of the sequence as a key.\n\n```go\ncollection := func(yield func(int) bool) {\n    yield(1)\n    yield(2)\n    yield(1)\n    yield(3)\n    yield(2)\n}\n\nkeyMap := it.Keyify(collection)\n// keyMap contains {1: {}, 2: {}, 3: {}}\n```"
  },
  {
    "path": "docs/data/it-keys.md",
    "content": "---\nname: Keys\nslug: keys\nsourceRef: it/map.go#L11\ncategory: it\nsubCategory: map\nsignatures:\n  - \"func Keys[K comparable, V any](in ...map[K]V) iter.Seq[K]\"\nplayUrl: \"https://go.dev/play/p/Fu7h-eW18QM\"\nvariantHelpers:\n  - it#map#keys\nsimilarHelpers:\n  - core#slice#keys\n  - it#map#values\n  - it#map#uniqkeys\nposition: 0\n---\n\nCreates a sequence of the map keys. Accepts multiple maps and concatenates their keys.\n\nExamples:\n\n```go\nm1 := map[string]int{\n    \"apple\":  1,\n    \"banana\": 2,\n}\nm2 := map[string]int{\n    \"cherry\": 3,\n    \"date\":   4,\n}\nkeysSeq := it.Keys(m1, m2)\nvar result []string\nfor k := range keysSeq {\n    result = append(result, k)\n}\n// result contains keys from both maps\n```"
  },
  {
    "path": "docs/data/it-last.md",
    "content": "---\nname: Last\nslug: last\nsourceRef: it/find.go#L389\ncategory: it\nsubCategory: find\nsignatures:\n  - \"func Last[T any](collection iter.Seq[T]) (T, bool)\"\nplayUrl: https://go.dev/play/p/eGZV-sSmn_Q\nvariantHelpers:\n  - it#find#last\nsimilarHelpers:\n  - core#slice#last\n  - it#find#first\n  - it#find#lastor\nposition: 130\n---\n\nReturns the last element of a collection and a boolean indicating availability. Returns zero value and false if the collection is empty.\n\nExamples:\n\n```go\nseq := func(yield func(int) bool) {\n    _ = yield(10)\n    _ = yield(20)\n    _ = yield(30)\n}\nlast, ok := it.Last(seq)\n// last == 30, ok == true\n```\n\n```go\nseq := func(yield func(string) bool) {\n    // empty sequence\n}\nlast, ok := it.Last(seq)\n// last == \"\", ok == false (zero value for string)\n```"
  },
  {
    "path": "docs/data/it-lastindexof.md",
    "content": "---\nname: LastIndexOf\nslug: lastindexof\nsourceRef: it/find.go#L34\ncategory: it\nsubCategory: find\nsignatures:\n  - \"func LastIndexOf[T comparable](collection iter.Seq[T], element T) int\"\nplayUrl: https://go.dev/play/p/QPATR3VC5wT\nvariantHelpers:\n  - it#find#lastindexof\nsimilarHelpers:\n  - core#slice#lastindexof\n  - it#find#indexof\nposition: 10\n---\n\nReturns the index at which the last occurrence of a value is found in the sequence, or -1 if the value is not found.\n\nExamples:\n\n```go\nseq := func(yield func(int) bool) {\n    _ = yield(10)\n    _ = yield(20)\n    _ = yield(30)\n    _ = yield(20)\n}\nidx := it.LastIndexOf(seq, 20)\n// idx == 3\n```\n\n```go\nseq := func(yield func(string) bool) {\n    _ = yield(\"apple\")\n    _ = yield(\"banana\")\n    _ = yield(\"cherry\")\n}\nidx := it.LastIndexOf(seq, \"orange\")\n// idx == -1\n```"
  },
  {
    "path": "docs/data/it-lastor.md",
    "content": "---\nname: LastOr\nslug: lastor\nsourceRef: it/find.go#L407\ncategory: it\nsubCategory: find\nsignatures:\n  - \"func LastOr[T any](collection iter.Seq[T], fallback T) T\"\nplayUrl: https://go.dev/play/p/HNubjW2Mrxs\nvariantHelpers:\n  - it#find#lastor\nsimilarHelpers:\n  - core#slice#lastor\nposition: 570\n---\n\nReturns the last element of a collection or the fallback value if empty.\n\nWill iterate through the entire sequence.\n\nExamples:\n\n```go\n// Get the last element or fallback value\nnumbers := it.Slice([]int{5, 2, 8, 1, 9})\nlast := it.LastOr(numbers, 42)\n// last: 9\n\n// With empty collection\nempty := it.Slice([]int{})\nlast := it.LastOr(empty, 42)\n// last: 42 (fallback value)\n\n// With strings\nwords := it.Slice([]string{\"hello\", \"world\", \"go\"})\nlast := it.LastOr(words, \"fallback\")\n// last: \"go\"\n\nemptyWords := it.Slice([]string{})\nlast := it.LastOr(emptyWords, \"fallback\")\n// last: \"fallback\"\n\n// With structs\ntype Person struct {\n    Name string\n    Age  int\n}\npeople := it.Slice([]Person{\n    {Name: \"Alice\", Age: 30},\n    {Name: \"Bob\", Age: 25},\n})\nlast := it.LastOr(people, Person{Name: \"Default\", Age: 0})\n// last: {Name: \"Bob\", Age: 25}\n\nemptyPeople := it.Slice([]Person{})\nlast := it.LastOr(emptyPeople, Person{Name: \"Default\", Age: 0})\n// last: {Name: \"Default\", Age: 0} (fallback value)\n\n// With single element\nsingle := it.Slice([]int{42})\nlast := it.LastOr(single, 99)\n// last: 42\n\n// Using with nil pointer fallback\nvalues := it.Slice([]*string{ptr(\"hello\"), ptr(\"world\")})\nlast := it.LastOr(values, nil)\n// last: pointer to \"world\"\n\nemptyValues := it.Slice([]*string{})\nlast := it.LastOr(emptyValues, nil)\n// last: nil (fallback value)\n```"
  },
  {
    "path": "docs/data/it-lastorempty.md",
    "content": "---\nname: LastOrEmpty\nslug: lastorempty\nsourceRef: it/find.go#L400\ncategory: it\nsubCategory: find\nsignatures:\n  - \"func LastOrEmpty[T any](collection iter.Seq[T]) T\"\nplayUrl: https://go.dev/play/p/teODFK4YqM4\nvariantHelpers:\n  - it#find#lastorempty\nsimilarHelpers:\n  - core#slice#lastorempty\nposition: 560\n---\n\nReturns the last element of a collection or zero value if empty.\n\nWill iterate through the entire sequence.\n\nExamples:\n\n```go\n// Get the last element or zero value\nnumbers := it.Slice([]int{5, 2, 8, 1, 9})\nlast := it.LastOrEmpty(numbers)\n// last: 9\n\n// With empty collection\nempty := it.Slice([]int{})\nlast := it.LastOrEmpty(empty)\n// last: 0 (zero value for int)\n\n// With strings\nwords := it.Slice([]string{\"hello\", \"world\", \"go\"})\nlast := it.LastOrEmpty(words)\n// last: \"go\"\n\nemptyWords := it.Slice([]string{})\nlast := it.LastOrEmpty(emptyWords)\n// last: \"\" (zero value for string)\n\n// With structs\ntype Person struct {\n    Name string\n    Age  int\n}\npeople := it.Slice([]Person{\n    {Name: \"Alice\", Age: 30},\n    {Name: \"Bob\", Age: 25},\n})\nlast := it.LastOrEmpty(people)\n// last: {Name: \"Bob\", Age: 25}\n\nemptyPeople := it.Slice([]Person{})\nlast := it.LastOrEmpty(emptyPeople)\n// last: {Name: \"\", Age: 0} (zero value for Person)\n\n// With single element\nsingle := it.Slice([]int{42})\nlast := it.LastOrEmpty(single)\n// last: 42\n```"
  },
  {
    "path": "docs/data/it-latest.md",
    "content": "---\nname: Latest\nslug: latest\nsourceRef: it/find.go#L346\ncategory: it\nsubCategory: find\nsignatures:\n  - \"func Latest(times iter.Seq[time.Time]) time.Time\"\nplayUrl: https://go.dev/play/p/r5Yq6ATSHoH\nvariantHelpers:\n  - it#find#latest\nsimilarHelpers:\n  - core#slice#latest\nposition: 520\n---\n\nSearches for the latest (maximum) time.Time in a collection.\n\nReturns zero value when the collection is empty.\nWill iterate through the entire sequence.\n\nExamples:\n\n```go\nimport \"time\"\n\n// Find the latest time from a collection\ntimes := it.Slice([]time.Time{\n    time.Date(2023, 5, 15, 10, 0, 0, 0, time.UTC),\n    time.Date(2023, 3, 20, 14, 30, 0, 0, time.UTC),\n    time.Date(2023, 8, 1, 9, 15, 0, 0, time.UTC),\n})\nlatest := it.Latest(times)\n// latest: 2023-08-01 09:15:00 +0000 UTC\n\n// With empty collection\nempty := it.Slice([]time.Time{})\nlatest := it.Latest(empty)\n// latest: 0001-01-01 00:00:00 +0000 UTC (zero value)\n\n// Find latest from parsed times\ntimes := it.Slice([]time.Time{\n    time.Parse(time.RFC3339, \"2023-01-01T12:00:00Z\"),\n    time.Parse(time.RFC3339, \"2023-01-01T10:00:00Z\"),\n    time.Parse(time.RFC3339, \"2023-01-01T14:00:00Z\"),\n})\nlatest := it.Latest(times)\n// latest: 2023-01-01 14:00:00 +0000 UTC\n\n// Find latest log entry timestamp\nlogs := it.Slice([]time.Time{\n    time.Now().Add(-2 * time.Hour),\n    time.Now().Add(-1 * time.Hour),\n    time.Now(),\n})\nlatest := it.Latest(logs)\n// latest: current time\n```"
  },
  {
    "path": "docs/data/it-latestby.md",
    "content": "---\nname: LatestBy\nslug: latestby\nsourceRef: it/find.go#L353\ncategory: it\nsubCategory: find\nsignatures:\n  - \"func LatestBy[T any](collection iter.Seq[T], transform func(item T) time.Time) T\"\nplayUrl: https://go.dev/play/p/o_daRzHrDUU\nvariantHelpers:\n  - it#find#latestby\nsimilarHelpers:\n  - core#slice#latestby\nposition: 530\n---\n\nSearches for the element with the latest time using a transform function.\n\nReturns zero value when the collection is empty.\nWill iterate through the entire sequence.\n\nExamples:\n\n```go\nimport \"time\"\n\ntype Event struct {\n    Name string\n    Time time.Time\n}\n\n// Find the latest event by time\nevents := it.Slice([]Event{\n    {\"Meeting\", time.Date(2023, 5, 15, 10, 0, 0, 0, time.UTC)},\n    {\"Lunch\", time.Date(2023, 5, 15, 12, 0, 0, 0, time.UTC)},\n    {\"Breakfast\", time.Date(2023, 5, 15, 8, 0, 0, 0, time.UTC)},\n})\nlatest := it.LatestBy(events, func(e Event) time.Time {\n    return e.Time\n})\n// latest: {Name: \"Lunch\", Time: 2023-05-15 12:00:00 +0000 UTC}\n\n// Find the latest task by deadline\ntype Task struct {\n    ID       int\n    Deadline time.Time\n}\ntasks := it.Slice([]Task{\n    {1, time.Date(2023, 6, 1, 0, 0, 0, 0, time.UTC)},\n    {2, time.Date(2023, 5, 15, 0, 0, 0, 0, time.UTC)},\n    {3, time.Date(2023, 7, 1, 0, 0, 0, 0, time.UTC)},\n})\nlatest := it.LatestBy(tasks, func(t Task) time.Time {\n    return t.Deadline\n})\n// latest: {ID: 3, Deadline: 2023-07-01 00:00:00 +0000 UTC}\n\n// Find the most recent activity\ntype Activity struct {\n    User    string\n    Action  string\n    Time    time.Time\n}\nactivities := it.Slice([]Activity{\n    {\"alice\", \"login\", time.Now().Add(-24 * time.Hour)},\n    {\"bob\", \"logout\", time.Now().Add(-12 * time.Hour)},\n    {\"alice\", \"post\", time.Now().Add(-1 * time.Hour)},\n})\nlatest := it.LatestBy(activities, func(a Activity) time.Time {\n    return a.Time\n})\n// latest: {User: \"alice\", Action: \"post\", Time: 1 hour ago}\n```"
  },
  {
    "path": "docs/data/it-length.md",
    "content": "---\nname: Length\nslug: length\nsourceRef: it/seq.go#L16\ncategory: it\nsubCategory: sequence\nsignatures:\n  - \"func Length[T any](collection iter.Seq[T]) int\"\nplayUrl: \"https://go.dev/play/p/3dnbOjTbL-o\"\nvariantHelpers:\n  - it#sequence#length\nsimilarHelpers:\n  - core#slice#length\n  - it#sequence#isempty\n  - it#sequence#isnotempty\nposition: 0\n---\n\nReturns the length of a collection by iterating through the entire sequence.\n\nExamples:\n\n```go\nseq := func(yield func(int) bool) {\n    _ = yield(1)\n    _ = yield(2)\n    _ = yield(3)\n}\nlength := it.Length(seq)\n// length == 3\n```\n\n```go\nseq := func(yield func(string) bool) {\n    // empty sequence\n}\nlength := it.Length(seq)\n// length == 0\n```"
  },
  {
    "path": "docs/data/it-map.md",
    "content": "---\nname: Map\nslug: map\nsourceRef: it/seq.go#L51\ncategory: it\nsubCategory: sequence\nsignatures:\n  - \"func Map[T, R any](collection iter.Seq[T], transform func(item T) R) iter.Seq[R]\"\n  - \"func MapI[T, R any](collection iter.Seq[T], transform func(item T, index int) R) iter.Seq[R]\"\nplayUrl: \"https://go.dev/play/p/rWZiPB-RZOo\"\nvariantHelpers:\n  - it#sequence#map\n  - it#sequence#mapi\nsimilarHelpers:\n  - core#slice#map\n  - it#sequence#filtermap\n  - it#sequence#flatmap\nposition: 20\n---\n\nTransforms a sequence to another type by applying a transform function to each element.\n\nExamples:\n\n```go\nseq := func(yield func(int) bool) {\n    _ = yield(1)\n    _ = yield(2)\n    _ = yield(3)\n}\nmapped := it.Map(seq, func(x int) string {\n    return fmt.Sprintf(\"item-%d\", x)\n})\nvar result []string\nfor v := range mapped {\n    result = append(result, v)\n}\n// result contains \"item-1\", \"item-2\", \"item-3\"\n```\n\n### MapI\n\nTransforms a sequence to another type by applying a transform function to each element and its index.\n\n```go\nseq := func(yield func(int) bool) {\n    _ = yield(10)\n    _ = yield(20)\n    _ = yield(30)\n}\nmapped := it.MapI(seq, func(x int, index int) string {\n    return fmt.Sprintf(\"item-%d-%d\", x, index)\n})\nvar result []string\nfor v := range mapped {\n    result = append(result, v)\n}\n// result contains \"item-10-0\", \"item-20-1\", \"item-30-2\"\n```\n"
  },
  {
    "path": "docs/data/it-maptoseq.md",
    "content": "---\nname: MapToSeq\nslug: maptoseq\nsourceRef: it/map.go#L164\ncategory: it\nsubCategory: map\nsignatures:\n  - \"func MapToSeq[K comparable, V, R any](in map[K]V, transform func(key K, value V) R) iter.Seq[R]\"\nvariantHelpers:\n  - it#map#maptoseq\nsimilarHelpers:\n  - core#map#maptoslice\n  - it#map#values\n  - it#map#keys\n  - it#map#entries\n  - it#map#filtermaptoseq\nposition: 52\n---\n\nTransforms a map into a sequence by applying a transform function to each key-value pair. The transform function determines what values are yielded in the output sequence.\n\n```go\nm := map[string]int{\n    \"apple\":  3,\n    \"banana\": 5,\n    \"cherry\": 2,\n}\nresult := it.MapToSeq(m, func(key string, value int) string {\n    return fmt.Sprintf(\"%s:%d\", key, value)\n})\n// iter.Seq[string] yielding \"apple:3\", \"banana:5\", \"cherry:2\"\n\nnumberMap := map[int]string{1: \"one\", 2: \"two\", 3: \"three\"}\nresult = it.MapToSeq(numberMap, func(key int, value string) int {\n    return key * len(value)\n})\n// iter.Seq[int] yielding 3, 6, 15 (1*3, 2*3, 3*5)\n\npersonMap := map[string]int{\"alice\": 25, \"bob\": 30}\ntype Person struct {\n    Name string\n    Age  int\n}\nresult = it.MapToSeq(personMap, func(name string, age int) Person {\n    return Person{Name: name, Age: age}\n})\n// iter.Seq[Person] yielding {Name: \"alice\", Age: 25}, {Name: \"bob\", Age: 30}\n```"
  },
  {
    "path": "docs/data/it-max.md",
    "content": "---\nname: Max\nslug: max\nsourceRef: it/find.go#L295\ncategory: it\nsubCategory: find\nsignatures:\n  - \"func Max[T constraints.Ordered](collection iter.Seq[T]) T\"\nplayUrl: https://go.dev/play/p/C2ZtW2bsBZ6\nvariantHelpers:\n  - it#find#max\nsimilarHelpers:\n  - core#slice#max\n  - it#find#min\n  - it#find#maxby\nposition: 110\n---\n\nSearches the maximum value of a collection. Returns the largest element found.\n\nExamples:\n\n```go\nseq := func(yield func(int) bool) {\n    _ = yield(5)\n    _ = yield(2)\n    _ = yield(8)\n    _ = yield(1)\n    _ = yield(9)\n}\nmax := it.Max(seq)\n// max == 9\n```\n\n```go\nseq := func(yield func(string) bool) {\n    _ = yield(\"zebra\")\n    _ = yield(\"apple\")\n    _ = yield(\"banana\")\n}\nmax := it.Max(seq)\n// max == \"zebra\" (lexicographically largest)\n```"
  },
  {
    "path": "docs/data/it-maxby.md",
    "content": "---\nname: MaxBy\nslug: maxby\nsourceRef: it/find.go#L310\ncategory: it\nsubCategory: find\nsignatures:\n  - \"func MaxBy[T any](collection iter.Seq[T], comparison func(a, b T) bool) T\"\nplayUrl: https://go.dev/play/p/yBhXFJb5oxC\nvariantHelpers:\n  - it#find#maxby\nsimilarHelpers:\n  - core#slice#maxby\n  - it#find#minby\n  - it#find#max\nposition: 150\n---\n\nSearches maximum value using a custom comparison function. The comparison function should return true if the first argument is \"greater than\" the second.\n\nExamples:\n\n```go\ntype Person struct {\n    Name string\n    Age  int\n}\nseq := func(yield func(Person) bool) {\n    _ = yield(Person{\"Alice\", 30})\n    _ = yield(Person{\"Bob\", 25})\n    _ = yield(Person{\"Charlie\", 35})\n}\noldest := it.MaxBy(seq, func(a, b Person) bool {\n    return a.Age > b.Age\n})\n// oldest == Person{\"Charlie\", 35}\n```"
  },
  {
    "path": "docs/data/it-maxindex.md",
    "content": "---\nname: MaxIndex\nslug: maxindex\nsourceRef: it/find.go#L299\ncategory: it\nsubCategory: find\nsignatures:\n  - \"func MaxIndex[T constraints.Ordered](collection iter.Seq[T]) (T, int)\"\nplayUrl: https://go.dev/play/p/zeu2wUvhl5e\nvariantHelpers:\n  - it#find#maxindex\nsimilarHelpers:\n  - core#slice#maxindex\nposition: 480\n---\n\nSearches the maximum value of a collection and returns both the value and its index.\n\nReturns (zero value, -1) when the collection is empty.\nWill iterate through the entire sequence.\n\nExamples:\n\n```go\n// Find the maximum value and its index\nnumbers := it.Slice([]int{5, 2, 8, 1, 9})\nvalue, index := it.MaxIndex(numbers)\n// value: 9, index: 4\n\n// With empty collection\nempty := it.Slice([]int{})\nvalue, index := it.MaxIndex(empty)\n// value: 0, index: -1\n\n// Find the maximum string alphabetically and its index\nwords := it.Slice([]string{\"apple\", \"zebra\", \"banana\", \"xylophone\"})\nvalue, index := it.MaxIndex(words)\n// value: \"zebra\", index: 1\n```"
  },
  {
    "path": "docs/data/it-maxindexby.md",
    "content": "---\nname: MaxIndexBy\nslug: maxindexby\nsourceRef: it/find.go#L326\ncategory: it\nsubCategory: find\nsignatures:\n  - \"func MaxIndexBy[T any](collection iter.Seq[T], comparison func(a, b T) bool) (T, int)\"\nplayUrl: https://go.dev/play/p/MXyE6BTILjx\nvariantHelpers:\n  - it#find#maxindexby\nsimilarHelpers:\n  - core#slice#maxindexby\nposition: 490\n---\n\nSearches the maximum value of a collection using a comparison function and returns both the value and its index.\n\nIf several values are equal to the greatest value, returns the first such value.\nReturns (zero value, -1) when the collection is empty.\nWill iterate through the entire sequence.\n\nExamples:\n\n```go\n// Find the maximum string by length and its index\nwords := it.Slice([]string{\"apple\", \"hi\", \"banana\", \"xylophone\"})\nvalue, index := it.MaxIndexBy(words, func(a, b string) bool {\n    return len(a) > len(b)\n})\n// value: \"xylophone\", index: 3\n\n// Find the maximum person by age and its index\npeople := it.Slice([]Person{\n    {Name: \"Alice\", Age: 30},\n    {Name: \"Bob\", Age: 25},\n    {Name: \"Charlie\", Age: 35},\n})\nvalue, index := it.MaxIndexBy(people, func(a, b Person) bool {\n    return a.Age > b.Age\n})\n// value: {Name: \"Charlie\", Age: 35}, index: 2\n\n// Find the maximum number by absolute value and its index\nnumbers := it.Slice([]int{-5, 2, -8, 1})\nvalue, index := it.MaxIndexBy(numbers, func(a, b int) bool {\n    return abs(a) > abs(b)\n})\n// value: -8, index: 2\n```"
  },
  {
    "path": "docs/data/it-mean.md",
    "content": "---\nname: Mean / MeanBy\nslug: mean\nsourceRef: it/math.go#L80\ncategory: it\nsubCategory: math\nsignatures:\n  - \"func Mean[T constraints.Float | constraints.Integer](collection iter.Seq[T]) T\"\n  - \"func MeanBy[T any, R constraints.Float | constraints.Integer](collection iter.Seq[T], iteratee func(item T) R) R\"\nplayUrl: \"https://go.dev/play/p/Lez0CsvVRl_l\"\nvariantHelpers:\n  - it#math#mean\n  - it#math#meanby\nsimilarHelpers:\n  - core#slice#mean\n  - core#slice#meanby\nposition: 30\n---\n\nComputes the arithmetic mean. `MeanBy` applies a transform before averaging. Returns 0 for empty sequences.\n\nExamples:\n\n```go\navg := it.Mean(iter.Seq[int](func(y func(int) bool){ _ = y(2); _ = y(3); _ = y(5) }))\n// avg == 10/3 == 3 (int division)\n```\n\n```go\navg := it.MeanBy(iter.Seq[string](func(y func(string) bool){ _ = y(\"aa\"); _ = y(\"bbb\") }), func(s string) int { return len(s) })\n// (2+3)/2 == 2\n```\n\n\n"
  },
  {
    "path": "docs/data/it-meanby.md",
    "content": "---\nname: MeanBy\nslug: meanby\nsourceRef: it/math.go#L106\ncategory: it\nsubCategory: math\nsignatures:\n  - \"func MeanBy[T any, R constraints.Float | constraints.Integer](collection iter.Seq[T], transform func(item T) R) R\"\nplayUrl: https://go.dev/play/p/Ked4rpztH5Y\nvariantHelpers:\n  - it#math#mean\nsimilarHelpers:\n  - core#slice#meanby\n  - core#slice#mean\nposition: 70\n---\n\nReturns the mean value of the collection using the given transform function.\n\n```go\ntype Person struct {\n    Name string\n    Age  int\n}\n\npeople := it.Slice([]Person{\n    {\"Alice\", 25},\n    {\"Bob\", 30},\n    {\"Charlie\", 35},\n})\n\nresult := it.MeanBy(people, func(p Person) int {\n    return p.Age\n})\n// 30.0\n```"
  },
  {
    "path": "docs/data/it-min.md",
    "content": "---\nname: Min\nslug: min\nsourceRef: it/find.go#L227\ncategory: it\nsubCategory: find\nsignatures:\n  - \"func Min[T constraints.Ordered](collection iter.Seq[T]) T\"\nplayUrl: https://go.dev/play/p/0VihyYEaM-M\nvariantHelpers:\n  - it#find#min\nsimilarHelpers:\n  - core#slice#min\n  - it#find#max\n  - it#find#minby\nposition: 100\n---\n\nSearches the minimum value of a collection. Returns the smallest element found.\n\nExamples:\n\n```go\nseq := func(yield func(int) bool) {\n    _ = yield(5)\n    _ = yield(2)\n    _ = yield(8)\n    _ = yield(1)\n    _ = yield(9)\n}\nmin := it.Min(seq)\n// min == 1\n```\n\n```go\nseq := func(yield func(string) bool) {\n    _ = yield(\"zebra\")\n    _ = yield(\"apple\")\n    _ = yield(\"banana\")\n}\nmin := it.Min(seq)\n// min == \"apple\" (lexicographically smallest)\n```"
  },
  {
    "path": "docs/data/it-minby.md",
    "content": "---\nname: MinBy\nslug: minby\nsourceRef: it/find.go#L242\ncategory: it\nsubCategory: find\nsignatures:\n  - \"func MinBy[T any](collection iter.Seq[T], comparison func(a, b T) bool) T\"\nplayUrl: https://go.dev/play/p/J5koo8khN-g\nvariantHelpers:\n  - it#find#minby\nsimilarHelpers:\n  - core#slice#minby\n  - it#find#maxby\n  - it#find#min\nposition: 140\n---\n\nSearches minimum value using a custom comparison function. The comparison function should return true if the first argument is \"less than\" the second.\n\nExamples:\n\n```go\ntype Person struct {\n    Name string\n    Age  int\n}\nseq := func(yield func(Person) bool) {\n    _ = yield(Person{\"Alice\", 30})\n    _ = yield(Person{\"Bob\", 25})\n    _ = yield(Person{\"Charlie\", 35})\n}\nyoungest := it.MinBy(seq, func(a, b Person) bool {\n    return a.Age < b.Age\n})\n// youngest == Person{\"Bob\", 25}\n```"
  },
  {
    "path": "docs/data/it-minindex.md",
    "content": "---\nname: MinIndex\nslug: minindex\nsourceRef: it/find.go#L231\ncategory: it\nsubCategory: find\nsignatures:\n  - \"func MinIndex[T constraints.Ordered](collection iter.Seq[T]) (T, int)\"\nplayUrl: https://go.dev/play/p/70ncPxECj6l\nvariantHelpers:\n  - it#find#minindex\nsimilarHelpers:\n  - core#slice#minindex\nposition: 460\n---\n\nSearches the minimum value of a collection and returns both the value and its index.\n\nReturns (zero value, -1) when the collection is empty.\nWill iterate through the entire sequence.\n\nExamples:\n\n```go\n// Find the minimum value and its index\nnumbers := it.Slice([]int{5, 2, 8, 1, 9})\nvalue, index := it.MinIndex(numbers)\n// value: 1, index: 3\n\n// With empty collection\nempty := it.Slice([]int{})\nvalue, index := it.MinIndex(empty)\n// value: 0, index: -1\n```"
  },
  {
    "path": "docs/data/it-minindexby.md",
    "content": "---\nname: MinIndexBy\nslug: minindexby\nsourceRef: it/find.go#L258\ncategory: it\nsubCategory: find\nsignatures:\n  - \"func MinIndexBy[T any](collection iter.Seq[T], comparison func(a, b T) bool) (T, int)\"\nplayUrl: https://go.dev/play/p/blldzWJpqVa\nvariantHelpers:\n  - it#find#minindexby\nsimilarHelpers:\n  - core#slice#minindexby\nposition: 470\n---\n\nSearches the minimum value of a collection using a comparison function and returns both the value and its index.\n\nIf several values are equal to the smallest value, returns the first such value.\nReturns (zero value, -1) when the collection is empty.\nWill iterate through the entire sequence.\n\nExamples:\n\n```go\n// Find the minimum string by length and its index\nwords := it.Slice([]string{\"apple\", \"hi\", \"banana\", \"ok\"})\nvalue, index := it.MinIndexBy(words, func(a, b string) bool {\n    return len(a) < len(b)\n})\n// value: \"hi\", index: 1\n\n// Find the minimum person by age and its index\npeople := it.Slice([]Person{\n    {Name: \"Alice\", Age: 30},\n    {Name: \"Bob\", Age: 25},\n    {Name: \"Charlie\", Age: 35},\n})\nvalue, index := it.MinIndexBy(people, func(a, b Person) bool {\n    return a.Age < b.Age\n})\n// value: {Name: \"Bob\", Age: 25}, index: 1\n```"
  },
  {
    "path": "docs/data/it-mode.md",
    "content": "---\nname: Mode\nslug: mode\nsourceRef: it/math.go#L124\ncategory: it\nsubCategory: math\nsignatures:\n  - \"func Mode[T constraints.Integer | constraints.Float](collection iter.Seq[T]) []T\"\nplayUrl: \"https://go.dev/play/p/c_cmMMA5EhH\"\nvariantHelpers:\n  - it#math#mode\nsimilarHelpers:\n  - core#slice#mode\nposition: 40\n---\n\nReturns the mode (most frequent value) of a collection. If multiple values have the same highest frequency, then multiple values are returned. If the collection is empty, then the zero value of T is returned.\n\nWill iterate through the entire sequence and allocate a map large enough to hold all distinct elements. Long heterogeneous input sequences can cause excessive memory usage.\n\nExamples:\n\n```go\nseq := func(yield func(int) bool) {\n    _ = yield(1)\n    _ = yield(2)\n    _ = yield(2)\n    _ = yield(3)\n    _ = yield(3)\n    _ = yield(3)\n}\nmode := it.Mode(seq)\n// mode == []int{3}\n```\n\n```go\n// Multiple modes\nseq := func(yield func(string) bool) {\n    _ = yield(\"a\")\n    _ = yield(\"b\")\n    _ = yield(\"a\")\n    _ = yield(\"b\")\n}\nmode := it.Mode(seq)\n// mode contains both \"a\" and \"b\" (order may vary)\n```"
  },
  {
    "path": "docs/data/it-none.md",
    "content": "---\nname: None\nslug: none\nsourceRef: it/intersect.go#L63\ncategory: it\nsubCategory: intersect\nsignatures:\n  - \"func None[T comparable](collection iter.Seq[T], subset ...T) bool\"\nplayUrl: \"https://go.dev/play/p/L7mm5S4a8Yo\"\nvariantHelpers:\n  - it#intersect#none\nsimilarHelpers:\n  - core#slice#none\nposition: 680\n---\n\nReturns true if no element of a subset is contained in a collection or if the subset is empty.\n\nWill iterate through the entire sequence if subset elements never match.\n\nExamples:\n\n```go\n// Check if collection contains none of the forbidden values\nnumbers := it.Slice([]int{1, 3, 5, 7, 9})\nforbidden := []int{2, 4, 6, 8}\nhasNone := it.None(numbers, forbidden...)\n// hasNone: true\n\nnumbers = it.Slice([]int{1, 3, 5, 8, 9})\nhasNone = it.None(numbers, forbidden...)\n// hasNone: false (8 is in both collection and forbidden)\n\n// Check if collection contains none of unwanted words\nwords := it.Slice([]string{\"hello\", \"world\", \"go\", \"lang\"})\nunwanted := []string{\"bad\", \"evil\", \"wrong\"}\nhasNone := it.None(words, unwanted...)\n// hasNone: true\n\nwords = it.Slice([]string{\"hello\", \"bad\", \"go\", \"lang\"})\nhasNone = it.None(words, unwanted...)\n// hasNone: false (\"bad\" is in both)\n\n// Check if collection contains none of specific IDs\nids := it.Slice([]int{101, 102, 103, 104})\nrestrictedIds := []int{201, 202, 203}\nhasNone := it.None(ids, restrictedIds...)\n// hasNone: true\n\nids = it.Slice([]int{101, 102, 203, 104})\nhasNone = it.None(ids, restrictedIds...)\n// hasNone: false (203 is restricted)\n\n// Check with empty subset (always returns true)\nnumbers = it.Slice([]int{1, 3, 5, 7, 9})\nhasNone = it.None(numbers)\n// hasNone: true\n\n// Check with strings containing specific characters\nwords := it.Slice([]string{\"hello\", \"world\", \"go\", \"lang\"})\nforbiddenChars := []string{\"@\", \"#\", \"$\"}\nhasNone := it.None(words, forbiddenChars...)\n// hasNone: true\n\nwords = it.Slice([]string{\"hello\", \"world\", \"go@\"})\nhasNone = it.None(words, forbiddenChars...)\n// hasNone: false (contains \"@\")\n\n// Check if collection has none of problematic status codes\nstatusCodes := it.Slice([]int{200, 201, 204})\nerrorCodes := []int{400, 401, 403, 404, 500}\nhasNone := it.None(statusCodes, errorCodes...)\n// hasNone: true\n\nstatusCodes = it.Slice([]int{200, 404, 204})\nhasNone = it.None(statusCodes, errorCodes...)\n// hasNone: false (contains 404)\n\n// Check with empty collection (always returns true)\nempty := it.Slice([]int{})\nhasNone = it.None(empty, 1, 2, 3)\n// hasNone: true\n\n// Check for none of forbidden usernames\nusernames := it.Slice([]string{\"alice\", \"bob\", \"charlie\"})\nforbiddenUsers := []string{\"admin\", \"root\", \"system\"}\nhasNone := it.None(usernames, forbiddenUsers...)\n// hasNone: true\n\nusernames = it.Slice([]string{\"alice\", \"admin\", \"charlie\"})\nhasNone = it.None(usernames, forbiddenUsers...)\n// hasNone: false (\"admin\" is forbidden)\n```"
  },
  {
    "path": "docs/data/it-noneby.md",
    "content": "---\nname: NoneBy\nslug: noneby\nsourceRef: it/intersect.go#L69\ncategory: it\nsubCategory: intersect\nsignatures:\n  - \"func NoneBy[T any](collection iter.Seq[T], predicate func(item T) bool) bool\"\nplayUrl: https://go.dev/play/p/PR7ddQ7Ckz5\nvariantHelpers:\n  - it#intersect#noneby\nsimilarHelpers:\n  - core#slice#noneby\nposition: 690\n---\n\nReturns true if the predicate returns true for none of the elements in the collection or if the collection is empty.\n\nWill iterate through the entire sequence if predicate never returns true.\n\nExamples:\n\n```go\n// Check if collection has no even numbers\nnumbers := it.Slice([]int{1, 3, 5, 7, 9})\nhasNoEvens := it.NoneBy(numbers, func(n int) bool { return n%2 == 0 })\n// hasNoEvens: true\n\nnumbers = it.Slice([]int{1, 3, 5, 8, 9})\nhasNoEvens = it.NoneBy(numbers, func(n int) bool { return n%2 == 0 })\n// hasNoEvens: false (8 is even)\n\n// Check if collection has no strings with specific prefix\nwords := it.Slice([]string{\"hello\", \"world\", \"go\", \"lang\"})\nhasNoGoPrefix := it.NoneBy(words, func(s string) bool { return strings.HasPrefix(s, \"go\") })\n// hasNoGoPrefix: false (\"go\" has go prefix)\n\nhasNoPythonPrefix := it.NoneBy(words, func(s string) bool { return strings.HasPrefix(s, \"python\") })\n// hasNoPythonPrefix: true\n\n// Check if collection has no minors\ntype Person struct {\n    Name string\n    Age  int\n}\npeople := it.Slice([]Person{\n    {Name: \"Alice\", Age: 30},\n    {Name: \"Bob\", Age: 25},\n    {Name: \"Charlie\", Age: 35},\n})\nhasNoMinors := it.NoneBy(people, func(p Person) bool { return p.Age < 18 })\n// hasNoMinors: true\n\nwithMinor := it.Slice([]Person{\n    {Name: \"Alice\", Age: 30},\n    {Name: \"Bob\", Age: 16},  // Minor\n    {Name: \"Charlie\", Age: 35},\n})\nhasNoMinors = it.NoneBy(withMinor, func(p Person) bool { return p.Age < 18 })\n// hasNoMinors: false\n\n// Check if collection has no negative numbers\nnumbers = it.Slice([]int{1, 3, 5, 7, 9})\nhasNoNegatives := it.NoneBy(numbers, func(n int) bool { return n < 0 })\n// hasNoNegatives: true\n\nnumbers = it.Slice([]int{1, -3, 5, 7, 9})\nhasNoNegatives = it.NoneBy(numbers, func(n int) bool { return n < 0 })\n// hasNoNegatives: false (-3 is negative)\n\n// Check if collection has no uppercase strings\nstrings := it.Slice([]string{\"hello\", \"world\", \"go\", \"lang\"})\nhasNoUppercase := it.NoneBy(strings, func(s string) bool { return s != strings.ToLower(s) })\n// hasNoUppercase: true\n\nstrings = it.Slice([]string{\"hello\", \"World\", \"go\", \"lang\"})  // \"World\" has uppercase\nhasNoUppercase = it.NoneBy(strings, func(s string) bool { return s != strings.ToLower(s) })\n// hasNoUppercase: false\n\n// Empty collection returns true\nempty := it.Slice([]int{})\nhasNoEvens := it.NoneBy(empty, func(n int) bool { return n%2 == 0 })\n// hasNoEvens: true\n\n// Check if collection has no invalid emails\nemails := it.Slice([]string{\"user@example.com\", \"test@domain.org\", \"admin@site.net\"})\nhasNoInvalid := it.NoneBy(emails, func(email string) bool {\n    return !strings.Contains(email, \"@\") || !strings.Contains(email, \".\")\n})\n// hasNoInvalid: true\n\nemails = it.Slice([]string{\"user@example.com\", \"invalid-email\", \"test@domain.org\"})\nhasNoInvalid = it.NoneBy(emails, func(email string) bool {\n    return !strings.Contains(email, \"@\") || !strings.Contains(email, \".\")\n})\n// hasNoInvalid: false\n\n// Check if collection has no numbers greater than 100\nnumbers = it.Slice([]int{1, 3, 5, 7, 9})\nhasNoLargeNumbers := it.NoneBy(numbers, func(n int) bool { return n > 100 })\n// hasNoLargeNumbers: true\n\nnumbers = it.Slice([]int{1, 3, 5, 150, 9})\nhasNoLargeNumbers = it.NoneBy(numbers, func(n int) bool { return n > 100 })\n// hasNoLargeNumbers: false (150 > 100)\n\n// Check if collection has no strings shorter than 3 characters\nwords := it.Slice([]string{\"hello\", \"world\", \"go\", \"lang\"})\nhasNoShortWords := it.NoneBy(words, func(s string) bool { return len(s) < 3 })\n// hasNoShortWords: false (\"go\" has length 2)\n```"
  },
  {
    "path": "docs/data/it-nth.md",
    "content": "---\nname: Nth\nslug: nth\nsourceRef: it/find.go#L417\ncategory: it\nsubCategory: find\nsignatures:\n  - \"func Nth[T any, N constraints.Integer](collection iter.Seq[T], nth N) (T, error)\"\nplayUrl: https://go.dev/play/p/FqgCobsKqva\nvariantHelpers:\n  - it#find#nth\nsimilarHelpers:\n  - core#slice#nth\nposition: 580\n---\n\nReturns the element at index `nth` of collection. Returns an error when nth is out of bounds.\n\nWill iterate n times through the sequence.\n\nExamples:\n\n```go\n// Get element at specific index\nnumbers := it.Slice([]int{5, 2, 8, 1, 9})\nelement, err := it.Nth(numbers, 2)\n// element: 8, err: nil\n\n// Get first element (index 0)\nfirst, err := it.Nth(numbers, 0)\n// first: 5, err: nil\n\n// Get last element\nlast, err := it.Nth(numbers, 4)\n// last: 9, err: nil\n\n// Out of bounds - negative\n_, err := it.Nth(numbers, -1)\n// err: nth: -1 out of bounds\n\n// Out of bounds - too large\n_, err := it.Nth(numbers, 10)\n// err: nth: 10 out of bounds\n\n// With strings\nwords := it.Slice([]string{\"hello\", \"world\", \"go\", \"lang\"})\nelement, err := it.Nth(words, 1)\n// element: \"world\", err: nil\n\n// With different integer types\nnumbers := it.Slice([]int{1, 2, 3, 4, 5})\nelement, err := it.Nth(numbers, int8(3))\n// element: 4, err: nil\n\n// With structs\ntype Person struct {\n    Name string\n    Age  int\n}\npeople := it.Slice([]Person{\n    {Name: \"Alice\", Age: 30},\n    {Name: \"Bob\", Age: 25},\n    {Name: \"Charlie\", Age: 35},\n})\nelement, err := it.Nth(people, 1)\n// element: {Name: \"Bob\", Age: 25}, err: nil\n```"
  },
  {
    "path": "docs/data/it-nthor.md",
    "content": "---\nname: NthOr\nslug: nthor\nsourceRef: it/find.go#L433\ncategory: it\nsubCategory: find\nsignatures:\n  - \"func NthOr[T any, N constraints.Integer](collection iter.Seq[T], nth N, fallback T) T\"\nplayUrl: https://go.dev/play/p/MNweuhpy4Ym\nvariantHelpers:\n  - it#find#nthor\nsimilarHelpers:\n  - core#slice#nthor\nposition: 590\n---\n\nReturns the element at index `nth` of collection. If `nth` is out of bounds, returns the fallback value instead of an error.\n\nWill iterate n times through the sequence.\n\nExamples:\n\n```go\n// Get element at specific index\nnumbers := it.Slice([]int{5, 2, 8, 1, 9})\nelement := it.NthOr(numbers, 2, 42)\n// element: 8\n\n// Get first element (index 0)\nfirst := it.NthOr(numbers, 0, 42)\n// first: 5\n\n// Get last element\nlast := it.NthOr(numbers, 4, 42)\n// last: 9\n\n// Out of bounds - negative, returns fallback\nelement := it.NthOr(numbers, -1, 42)\n// element: 42 (fallback)\n\n// Out of bounds - too large, returns fallback\nelement := it.NthOr(numbers, 10, 42)\n// element: 42 (fallback)\n\n// With strings\nwords := it.Slice([]string{\"hello\", \"world\", \"go\", \"lang\"})\nelement := it.NthOr(words, 1, \"fallback\")\n// element: \"world\"\n\n// Out of bounds with string fallback\nelement := it.NthOr(words, 10, \"fallback\")\n// element: \"fallback\"\n\n// With structs\ntype Person struct {\n    Name string\n    Age  int\n}\npeople := it.Slice([]Person{\n    {Name: \"Alice\", Age: 30},\n    {Name: \"Bob\", Age: 25},\n})\nfallback := Person{Name: \"Default\", Age: 0}\nelement := it.NthOr(people, 1, fallback)\n// element: {Name: \"Bob\", Age: 25}\n\n// Out of bounds with struct fallback\nelement := it.NthOr(people, 5, fallback)\n// element: {Name: \"Default\", Age: 0}\n\n// With different integer types\nnumbers := it.Slice([]int{1, 2, 3, 4, 5})\nelement := it.NthOr(numbers, int8(3), 99)\n// element: 4\n```"
  },
  {
    "path": "docs/data/it-nthorempty.md",
    "content": "---\nname: NthOrEmpty\nslug: nthorempty\nsourceRef: it/find.go#L444\ncategory: it\nsubCategory: find\nsignatures:\n  - \"func NthOrEmpty[T any, N constraints.Integer](collection iter.Seq[T], nth N) T\"\nplayUrl: https://go.dev/play/p/pC0Zhu3EUhe\nvariantHelpers:\n  - it#find#nthorempty\nsimilarHelpers:\n  - core#slice#nthorempty\nposition: 600\n---\n\nReturns the element at index `nth` of collection. If `nth` is out of bounds, returns the zero value (empty value) for that type.\n\nWill iterate n times through the sequence.\n\nExamples:\n\n```go\n// Get element at specific index\nnumbers := it.Slice([]int{5, 2, 8, 1, 9})\nelement := it.NthOrEmpty(numbers, 2)\n// element: 8\n\n// Get first element (index 0)\nfirst := it.NthOrEmpty(numbers, 0)\n// first: 5\n\n// Get last element\nlast := it.NthOrEmpty(numbers, 4)\n// last: 9\n\n// Out of bounds - negative, returns zero value\nelement := it.NthOrEmpty(numbers, -1)\n// element: 0 (zero value for int)\n\n// Out of bounds - too large, returns zero value\nelement := it.NthOrEmpty(numbers, 10)\n// element: 0 (zero value for int)\n\n// With strings\nwords := it.Slice([]string{\"hello\", \"world\", \"go\", \"lang\"})\nelement := it.NthOrEmpty(words, 1)\n// element: \"world\"\n\n// Out of bounds with string - returns empty string\nelement := it.NthOrEmpty(words, 10)\n// element: \"\" (zero value for string)\n\n// With structs\ntype Person struct {\n    Name string\n    Age  int\n}\npeople := it.Slice([]Person{\n    {Name: \"Alice\", Age: 30},\n    {Name: \"Bob\", Age: 25},\n})\nelement := it.NthOrEmpty(people, 1)\n// element: {Name: \"Bob\", Age: 25}\n\n// Out of bounds with struct - returns zero value\nelement := it.NthOrEmpty(people, 5)\n// element: {Name: \"\", Age: 0} (zero value for Person)\n\n// With pointers - returns nil when out of bounds\nvalues := it.Slice([]*string{ptr(\"hello\"), ptr(\"world\")})\nelement := it.NthOrEmpty(values, 1)\n// element: pointer to \"world\"\n\n// Out of bounds with pointer - returns nil\nelement := it.NthOrEmpty(values, 5)\n// element: nil (zero value for *string)\n\n// With different integer types\nnumbers := it.Slice([]int{1, 2, 3, 4, 5})\nelement := it.NthOrEmpty(numbers, int8(3))\n// element: 4\n```"
  },
  {
    "path": "docs/data/it-partitionby.md",
    "content": "---\nname: PartitionBy\nslug: partitionby\nsourceRef: it/seq.go#L26\ncategory: it\nsubCategory: sequence\nsignatures:\n  - \"func PartitionBy[T any, K comparable](collection iter.Seq[T], transform func(item T) K) [][]T\"\nvariantHelpers: []\nplayUrl: https://go.dev/play/p/VxTx8mva28z\nsimilarHelpers:\n  - core#slice#partitionby\nposition: 171\n---\n\nPartitionBy returns a sequence of elements split into groups. The order of grouped values is\ndetermined by the order they occur in collection. The grouping is generated from the results\nof running each element of collection through transform.\n\n```go\ncollection := func(yield func(int) bool) {\n    yield(1)\n    yield(2)\n    yield(3)\n    yield(4)\n    yield(5)\n    yield(6)\n}\n\nresult := it.PartitionBy(collection, func(x int) int {\n    return x % 3\n})\n// result contains [[1, 4], [2, 5], [3, 6]]\n```"
  },
  {
    "path": "docs/data/it-product.md",
    "content": "---\nname: Product / ProductBy\nslug: product\nsourceRef: it/math.go#L70\ncategory: it\nsubCategory: math\nsignatures:\n  - \"func Product[T constraints.Float | constraints.Integer | constraints.Complex](collection iter.Seq[T]) T\"\n  - \"func ProductBy[T any, R constraints.Float | constraints.Integer | constraints.Complex](collection iter.Seq[T], iteratee func(item T) R) R\"\nplayUrl: \"https://go.dev/play/p/AOMCD1Yl5Bc\"\nvariantHelpers:\n  - it#math#product\n  - it#math#productby\nsimilarHelpers:\n  - core#slice#product\n  - core#slice#productby\nposition: 20\n---\n\nMultiplies values from a sequence. `ProductBy` applies a transform then multiplies. Returns 1 for empty sequences.\n\nExamples:\n\n```go\nseq := it.RangeFrom(1, 4) // 1,2,3,4\np := it.Product(seq)\n// p == 24\n```\n\n```go\nnums := it.RangeFrom(2, 3) // 2,3,4\np := it.ProductBy(nums, func(n int) int { return n - 1 })\n// (1*2*3) == 6\n```\n\n\n"
  },
  {
    "path": "docs/data/it-productby.md",
    "content": "---\nname: ProductBy\nslug: productby\nsourceRef: it/math.go#L90\ncategory: it\nsubCategory: math\nsignatures:\n  - \"func ProductBy[T any, R constraints.Float | constraints.Integer | constraints.Complex](collection iter.Seq[T], transform func(item T) R) R\"\nplayUrl: \"https://go.dev/play/p/dgFCRJrlPHY\"\nvariantHelpers:\n  - it#math#product\nsimilarHelpers:\n  - core#slice#productby\n  - core#slice#product\nposition: 67\n---\n\nReturns the product of values in the collection using the given transform function.\n\n```go\nresult := it.ProductBy(it.Range(1, 5), func(item int) int {\n    return item * 2\n})\n// 384 (2 * 4 * 6 * 8)\n```"
  },
  {
    "path": "docs/data/it-range.md",
    "content": "---\nname: Range\nslug: range\nsourceRef: it/math.go#L12\ncategory: it\nsubCategory: math\nsignatures:\n  - \"func Range(elementNum int) iter.Seq[int]\"\nplayUrl: \"https://go.dev/play/p/79QUZBa8Ukn\"\nvariantHelpers:\n  - it#math#range\nsimilarHelpers:\n  - core#slice#range\n  - it#math#rangefrom\n  - it#math#rangewithsteps\nposition: 0\n---\n\nCreates a sequence of integers starting from 0. Yields `elementNum` integers, stepping by ±1 depending on sign.\n\n```go\nseq := it.Range(4)\nvar out []int\nfor v := range seq { out = append(out, v) }\n// out == []int{0, 1, 2, 3}\n```"
  },
  {
    "path": "docs/data/it-rangefrom.md",
    "content": "---\nname: RangeFrom\nslug: rangefrom\nsourceRef: it/math.go#L25\ncategory: it\nsubCategory: math\nsignatures:\n  - \"func RangeFrom[T constraints.Integer | constraints.Float](start T, elementNum int) iter.Seq[T]\"\nplayUrl: \"https://go.dev/play/p/WHP_NI5scj9\"\nvariantHelpers:\n  - it#math#rangefrom\nsimilarHelpers:\n  - core#slice#rangefrom\n  - it#math#range\n  - it#math#rangewithsteps\nposition: 10\n---\n\nCreates a sequence of numbers from start with specified length. Yields `elementNum` values starting from `start`, stepping by ±1 depending on sign.\n\n```go\nseq := it.RangeFrom(5, 4)\nvar result []int\nfor item := range seq {\n    result = append(result, item)\n}\n// result contains [5, 6, 7, 8]\n\nseq2 := it.RangeFrom(10.5, 3)\nvar result2 []float64\nfor item := range seq2 {\n    result2 = append(result2, item)\n}\n// result2 contains [10.5, 11.5, 12.5]\n```"
  },
  {
    "path": "docs/data/it-rangewithsteps.md",
    "content": "---\nname: RangeWithSteps\nslug: rangewithsteps\nsourceRef: it/math.go#L35\ncategory: it\nsubCategory: math\nsignatures:\n  - \"func RangeWithSteps[T constraints.Integer | constraints.Float](start, end, step T) iter.Seq[T]\"\nplayUrl: \"https://go.dev/play/p/qxm2YNLG0vT\"\nvariantHelpers:\n  - it#math#rangewithsteps\nsimilarHelpers:\n  - core#slice#rangewithsteps\n  - it#math#range\n  - it#math#rangefrom\nposition: 20\n---\n\nCreates a sequence of numbers from start up to (excluding) end with a custom step. Step set to zero will return an empty sequence.\n\n```go\nseq := it.RangeWithSteps(0, 10, 3)\nvar result []int\nfor item := range seq {\n    result = append(result, item)\n}\n// result contains [0, 3, 6, 9]\n\nseq2 := it.RangeWithSteps(10, 1, -3)\nvar result2 []int\nfor item := range seq2 {\n    result2 = append(result2, item)\n}\n// result2 contains [10, 7, 4, 1]\n\nseq3 := it.RangeWithSteps(0, 5, 1.5)\nvar result3 []float64\nfor item := range seq3 {\n    result3 = append(result3, item)\n}\n// result3 contains [0, 1.5, 3, 4.5]\n```"
  },
  {
    "path": "docs/data/it-reduce.md",
    "content": "---\nname: Reduce\nslug: reduce\nsourceRef: it/seq.go#L133\ncategory: it\nsubCategory: sequence\nsignatures:\n  - \"func Reduce[T, R any](collection iter.Seq[T], accumulator func(agg R, item T) R, initial R) R\"\n  - \"func ReduceI[T, R any](collection iter.Seq[T], accumulator func(agg R, item T, index int) R, initial R) R\"\nplayUrl: \"https://go.dev/play/p/FmkVUf39ZP_Y\"\nvariantHelpers:\n  - it#sequence#reduce\n  - it#sequence#reducei\nsimilarHelpers:\n  - core#slice#reduce\n  - core#slice#reducei\n  - core#slice#reduceright\nposition: 30\n---\n\nReduces a collection to a single accumulated value by applying an accumulator function to each element starting with an initial value.\n\n### Reduce\n\n```go\nseq := func(yield func(int) bool) {\n    _ = yield(1)\n    _ = yield(2)\n    _ = yield(3)\n    _ = yield(4)\n}\nsum := it.Reduce(seq, func(acc int, item int) int {\n    return acc + item\n}, 0)\n// sum == 10\n```\n\n```go\nseq := func(yield func(string) bool) {\n    _ = yield(\"hello\")\n    _ = yield(\"world\")\n}\nconcat := it.Reduce(seq, func(acc string, item string) string {\n    return acc + \" \" + item\n}, \"\")\n// concat == \" hello world\"\n```\n\n### ReduceI\n\nReduces a collection to a single value by iterating through elements and applying an accumulator function that includes the index.\n\n```go\nresult := it.ReduceI(it.Range(1, 5), func(agg int, item int, index int) int {\n    return agg + item*index\n}, 0)\n// 20 (0*0 + 1*1 + 2*2 + 3*3)\n```"
  },
  {
    "path": "docs/data/it-reducelast.md",
    "content": "---\nname: ReduceLast\nslug: reducelast\nsourceRef: it/seq.go#L153\ncategory: it\nsubCategory: sequence\nsignatures:\n  - \"func ReduceLast[T, R any](collection iter.Seq[T], accumulator func(agg R, item T) R, initial R) R\"\n  - \"func ReduceLastI[T, R any](collection iter.Seq[T], accumulator func(agg R, item T, index int) R, initial R) R\"\nplayUrl: https://go.dev/play/p/D2ZGZ2pN270\nvariantHelpers:\n  - it#sequence#reduce\n  - it#sequence#reducei\n  - it#sequence#reducelast\n  - it#sequence#reducelasti\nsimilarHelpers:\n  - core#slice#reducelast\n  - core#slice#reducelasti\n  - core#slice#reduce\nposition: 54\n---\n\nReduces a collection from right to left, returning a single value.\n\n### ReduceLast\n\n```go\nresult := it.ReduceLast(it.Range(1, 5), func(agg int, item int) int {\n    return agg - item\n}, 0)\n// -10 (0 - 4 - 3 - 2 - 1)\n```\n\n### ReduceLastI\n\nReduces a collection from right to left, returning a single value. The accumulator function includes the index.\n\n```go\nresult := it.ReduceLastI(it.Range(1, 5), func(agg int, item int, index int) int {\n    return agg - item*index\n}, 0)\n// -20 (0 - 4*3 - 3*2 - 2*1 - 1*0)\n```"
  },
  {
    "path": "docs/data/it-reject.md",
    "content": "---\nname: Reject\nslug: reject\nsourceRef: it/seq.go#L586\ncategory: it\nsubCategory: sequence\nsignatures:\n  - \"func Reject[T any, I ~func(func(T) bool)](collection I, predicate func(item T) bool) I\"\n  - \"func RejectI[T any, I ~func(func(T) bool)](collection I, predicate func(item T, index int) bool) I\"\n  - \"func RejectMap[T, R any](collection iter.Seq[T], callback func(item T) (R, bool)) iter.Seq[R]\"\n  - \"func RejectMapI[T, R any](collection iter.Seq[T], callback func(item T, index int) (R, bool)) iter.Seq[R]\"\nvariantHelpers:\n  - it#sequence#reject\n  - it#sequence#rejecti\n  - it#sequence#rejectmap\n  - it#sequence#rejectmapi\nsimilarHelpers:\n  - core#slice#reject\n  - core#slice#filter\n  - it#sequence#filter\n  - it#sequence#filtermap\nposition: 180\n---\n\nReject is the opposite of Filter, this method returns the elements of collection that predicate does not return true for.\n\n```go\ncollection := func(yield func(int) bool) {\n    yield(1)\n    yield(2)\n    yield(3)\n    yield(4)\n}\n\nfiltered := it.Reject(collection, func(x int) bool {\n    return x%2 == 0\n})\nvar result []int\nfor item := range filtered {\n    result = append(result, item)\n}\n// result contains [1, 3]\n```\n\nRejectI is the opposite of Filter, this method returns the elements of collection that predicate does not return true for, with index.\n\n```go\ncollection := func(yield func(string) bool) {\n    yield(\"a\")\n    yield(\"b\")\n    yield(\"c\")\n}\n\nfiltered := it.RejectI(collection, func(item string, index int) bool {\n    return index == 1\n})\nvar result []string\nfor item := range filtered {\n    result = append(result, item)\n}\n// result contains [\"a\", \"c\"]\n```\n\nRejectMap returns a sequence obtained after both filtering and mapping using the given callback function.\nThe callback function should return two values: the result of the mapping operation and whether the result element should be included or not.\n\n```go\ncollection := func(yield func(int) bool) {\n    yield(1)\n    yield(2)\n    yield(3)\n    yield(4)\n}\n\nfiltered := it.RejectMap(collection, func(x int) (string, bool) {\n    return fmt.Sprintf(\"item-%d\", x), x%2 == 0\n})\nvar result []string\nfor item := range filtered {\n    result = append(result, item)\n}\n// result contains [\"item-1\", \"item-3\"]\n```"
  },
  {
    "path": "docs/data/it-rejectmap.md",
    "content": "---\nname: RejectMap\nslug: rejectmap\nsourceRef: it/seq.go#L608\ncategory: it\nsubCategory: sequence\nsignatures:\n  - \"func RejectMap[T, R any](collection iter.Seq[T], callback func(item T) (R, bool)) iter.Seq[R]\"\nvariantHelpers:\n  - it#sequence#rejectmap\nsimilarHelpers:\n  - it#sequence#filtermap\n  - it#sequence#map\n  - it#sequence#filter\n  - it#sequence#reject\nposition: 42\n---\n\nMaps elements of a sequence to new values and rejects elements where the callback returns true. Only elements where the second return value is false are included in the result.\n\n```go\nseq := func(yield func(int) bool) {\n    yield(1)\n    yield(2)\n    yield(3)\n    yield(4)\n}\nresult := it.RejectMap(seq, func(x int) (string, bool) {\n    if x%2 == 0 {\n        return fmt.Sprintf(\"even-%d\", x), true // reject even numbers\n    }\n    return fmt.Sprintf(\"odd-%d\", x), false\n})\n// iter.Seq[string] yielding \"odd-1\", \"odd-3\"\n\nseq = func(yield func(string) bool) {\n    yield(\"a\")\n    yield(\"\")\n    yield(\"c\")\n    yield(\"d\")\n}\nresult = it.RejectMap(seq, func(s string) (int, bool) {\n    if s == \"\" {\n        return 0, true // reject empty strings\n    }\n    return len(s), false\n})\n// iter.Seq[int] yielding 1, 1, 1 (length of \"a\", \"c\", \"d\")\n```"
  },
  {
    "path": "docs/data/it-repeat.md",
    "content": "---\nname: Repeat\nslug: repeat\nsourceRef: it/seq.go#L384\ncategory: it\nsubCategory: sequence\nsignatures:\n  - \"func Repeat[T lo.Clonable[T]](count int, initial T) iter.Seq[T]\"\nplayUrl: https://go.dev/play/p/xs-aq0p_uDP\nvariantHelpers:\n  - it#slice#repeatby\nsimilarHelpers:\n  - core#slice#repeat\n  - core#slice#repeatby\nposition: 75\n---\n\nCreates a sequence that repeats the initial value count times.\n\n```go\nresult := it.Repeat(3, \"hello\")\n// [\"hello\", \"hello\", \"hello\"]\n```"
  },
  {
    "path": "docs/data/it-repeatby.md",
    "content": "---\nname: RepeatBy\nslug: repeatby\nsourceRef: it/seq.go#L388\ncategory: it\nsubCategory: sequence\nsignatures:\n  - \"func RepeatBy[T any](count int, callback func(index int) T) iter.Seq[T]\"\nplayUrl: https://go.dev/play/p/i7BuZQBcUzZ\nvariantHelpers:\n  - it#sequence#repeatby\nsimilarHelpers:\n  - core#slice#repeat\n  - core#slice#times\n  - it#sequence#times\nposition: 130\n---\n\nBuilds a sequence with values returned by N calls of callback.\n\n```go\nresult := it.RepeatBy(3, func(index int) string {\n    return fmt.Sprintf(\"item-%d\", index+1)\n})\nvar output []string\nfor item := range result {\n    output = append(output, item)\n}\n// output contains [\"item-1\", \"item-2\", \"item-3\"]\n\nresult2 := it.RepeatBy(5, func(index int) int {\n    return index * 2\n})\nvar output2 []int\nfor item := range result2 {\n    output2 = append(output2, item)\n}\n// output2 contains [0, 2, 4, 6, 8]\n```"
  },
  {
    "path": "docs/data/it-replace.md",
    "content": "---\nname: Replace\nslug: replace\nsourceRef: it/seq.go#L699\ncategory: it\nsubCategory: slice\nsignatures:\n  - \"func Replace[T comparable, I ~func(func(T) bool)](collection I, old, nEw T, n int) I\"\nvariantHelpers:\n  - it#slice#replace\nsimilarHelpers:\n  - core#slice#replace\nposition: 190\n---\n\nReplace returns a sequence with the first n non-overlapping instances of old replaced by new.\n\n```go\ncollection := func(yield func(int) bool) {\n    yield(1)\n    yield(2)\n    yield(2)\n    yield(3)\n    yield(2)\n    yield(4)\n}\n\nreplaced := it.Replace(collection, 2, 99, 2)\nvar result []int\nfor item := range replaced {\n    result = append(result, item)\n}\n// result contains [1, 99, 99, 3, 2, 4]\n```"
  },
  {
    "path": "docs/data/it-replaceall.md",
    "content": "---\nname: ReplaceAll\nslug: replaceall\nsourceRef: it/seq.go#L699\ncategory: it\nsubCategory: slice\nsignatures:\n  - \"func ReplaceAll[T comparable, I ~func(func(T) bool)](collection I, old, nEw T) I\"\nvariantHelpers:\n  - it#slice#replaceall\nsimilarHelpers:\n  - core#slice#replaceall\nposition: 191\n---\n\nReturns a sequence with all non-overlapping instances of old replaced by new.\n\n```go\n// Basic replacement\ncollection := func(yield func(int) bool) {\n    yield(1)\n    yield(2)\n    yield(2)\n    yield(3)\n}\n\nreplaced := it.ReplaceAll(collection, 2, 99)\nvar result []int\nfor item := range replaced {\n    result = append(result, item)\n}\n// result: [1, 99, 99, 3]\n\n// With strings - replacing multiple occurrences\nstrings := func(yield func(string) bool) {\n    yield(\"apple\")\n    yield(\"banana\")\n    yield(\"apple\")\n    yield(\"cherry\")\n    yield(\"apple\")\n}\n\nreplacedStrings := it.ReplaceAll(strings, \"apple\", \"orange\")\nvar fruitResult []string\nfor item := range replacedStrings {\n    fruitResult = append(fruitResult, item)\n}\n// fruitResult: [\"orange\", \"banana\", \"orange\", \"cherry\", \"orange\"]\n\n// No matches found\nnoMatch := it.ReplaceAll(strings, \"grape\", \"kiwi\")\nvar noMatchResult []string\nfor item := range noMatch {\n    noMatchResult = append(noMatchResult, item)\n}\n// noMatchResult: [\"apple\", \"banana\", \"apple\", \"cherry\", \"apple\"] (unchanged)\n\n// Empty collection\nempty := func(yield func(int) bool) {\n    // no yields\n}\nemptyReplaced := it.ReplaceAll(empty, 1, 99)\nvar emptyResult []int\nfor item := range emptyReplaced {\n    emptyResult = append(emptyResult, item)\n}\n// emptyResult: [] (empty sequence)\n```"
  },
  {
    "path": "docs/data/it-reverse.md",
    "content": "---\nname: Reverse\nslug: reverse\nsourceRef: it/seq.go#L366\ncategory: it\nsubCategory: sequence\nsignatures:\n  - \"func Reverse[T any, I ~func(func(T) bool)](collection I) I\"\nplayUrl: https://go.dev/play/p/R6-lR8yiNwa\nvariantHelpers:\n  - it#sequence#reverse\nsimilarHelpers:\n  - core#slice#reverse\n  - it#sequence#shuffle\nposition: 90\n---\n\nReverses a sequence so the first element becomes the last and the last element becomes the first.\n\nExamples:\n\n```go\nseq := func(yield func(int) bool) {\n    _ = yield(1)\n    _ = yield(2)\n    _ = yield(3)\n    _ = yield(4)\n}\nreversed := it.Reverse(seq)\nvar result []int\nfor v := range reversed {\n    result = append(result, v)\n}\n// result contains 4, 3, 2, 1\n```"
  },
  {
    "path": "docs/data/it-sample.md",
    "content": "---\nname: Sample\nslug: sample\nsourceRef: it/find.go#L455\ncategory: it\nsubCategory: find\nsignatures:\n  - \"func Sample[T any](collection iter.Seq[T]) T\"\nplayUrl: https://go.dev/play/p/YDJVX0UXYDi\nvariantHelpers:\n  - it#find#sample\nsimilarHelpers:\n  - core#slice#sample\n  - it#find#samples\n  - it#find#sampleBy\n  - it#find#samplesBy\nposition: 160\n---\n\nReturns a random item from collection.\n\nExample:\n\n```go\nseq := func(yield func(string) bool) {\n    _ = yield(\"apple\")\n    _ = yield(\"banana\")\n    _ = yield(\"cherry\")\n}\nitem := it.Sample(seq)\n// item is randomly one of: \"apple\", \"banana\", \"cherry\"\n\n// Example with integers\nnumbers := func(yield func(int) bool) {\n    _ = yield(10)\n    _ = yield(20)\n    _ = yield(30)\n    _ = yield(40)\n}\nrandomNum := it.Sample(numbers)\n// randomNum is randomly one of: 10, 20, 30, 40\n\n// Example with empty sequence - returns zero value\nempty := func(yield func(string) bool) {\n    // no yields\n}\nemptyResult := it.Sample(empty)\n// emptyResult: \"\" (zero value for string)\n\n// Example with single item\nsingle := func(yield func(int) bool) {\n    _ = yield(42)\n}\nsingleResult := it.Sample(single)\n// singleResult: 42 (always returns 42 since it's the only option)\n```\n"
  },
  {
    "path": "docs/data/it-sampleby.md",
    "content": "---\nname: SampleBy\nslug: sampleby\nsourceRef: it/find.go#L455\ncategory: it\nsubCategory: find\nsignatures:\n  - \"func SampleBy[T any](collection iter.Seq[T], randomIntGenerator func(int) int) T\"\nplayUrl: https://go.dev/play/p/QQooySxORib\nvariantHelpers:\n  - it#find#sampleby\nsimilarHelpers:\n  - core#slice#sample\n  - it#find#sample\n  - it#find#samples\n  - it#find#samplesby\nposition: 160\n---\n\nReturns a random item from collection, using a custom random index generator.\n\nExample:\n\n```go\nseq := func(yield func(int) bool) {\n    _ = yield(1)\n    _ = yield(2)\n    _ = yield(3)\n}\n// Use custom RNG for predictable results (returns first element)\nitem := it.SampleBy(seq, func(max int) int { return 0 })\n// item == 1\n```"
  },
  {
    "path": "docs/data/it-samples.md",
    "content": "---\nname: Samples\nslug: samples\nsourceRef: it/find.go#L467\ncategory: it\nsubCategory: find\nsignatures:\n  - \"func Samples[T any, I ~func(func(T) bool)](collection I, count int) I\"\nplayUrl: https://go.dev/play/p/GUTFx9LQ8pP\nvariantHelpers:\n  - it#find#samples\nsimilarHelpers:\n  - core#slice#samples\n  - it#find#sample\n  - it#find#sampleby\n  - it#find#samplesby\nposition: 610\n---\n\nReturns N random unique items from collection.\n\nWill iterate through the entire sequence and allocate a slice large enough to hold all elements.\nLong input sequences can cause excessive memory usage.\n\nExamples:\n\n```go\n// Get 3 random unique items from collection\nnumbers := it.Slice([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10})\nsamples := it.Samples(numbers, 3)\n// samples: sequence of 3 random unique numbers from 1-10\n\n// Get all items if count equals collection size\nnumbers := it.Slice([]int{1, 2, 3, 4, 5})\nsamples := it.Samples(numbers, 5)\n// samples: sequence containing all 5 numbers in random order\n\n// Get fewer items than collection size\nnumbers := it.Slice([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10})\nsamples := it.Samples(numbers, 3)\n// samples: sequence of 3 random unique numbers\n\n// With strings\nwords := it.Slice([]string{\"apple\", \"banana\", \"cherry\", \"date\", \"elderberry\"})\nsamples := it.Samples(words, 2)\n// samples: sequence of 2 random unique words\n\n// With structs\ntype Person struct {\n    Name string\n    Age  int\n}\npeople := it.Slice([]Person{\n    {Name: \"Alice\", Age: 30},\n    {Name: \"Bob\", Age: 25},\n    {Name: \"Charlie\", Age: 35},\n    {Name: \"Diana\", Age: 28},\n    {Name: \"Eve\", Age: 32},\n})\nsamples := it.Samples(people, 3)\n// samples: sequence of 3 random unique people\n\n// Count larger than collection size - returns all items in random order\nnumbers := it.Slice([]int{1, 2, 3})\nsamples := it.Samples(numbers, 10)\n// samples: sequence of all 3 numbers in random order\n\n// Zero count - returns empty sequence\nnumbers := it.Slice([]int{1, 2, 3, 4, 5})\nsamples := it.Samples(numbers, 0)\n// samples: empty sequence\n\n// Negative count - returns empty sequence\nnumbers := it.Slice([]int{1, 2, 3, 4, 5})\nsamples := it.Samples(numbers, -1)\n// samples: empty sequence\n```"
  },
  {
    "path": "docs/data/it-samplesby.md",
    "content": "---\nname: SamplesBy\nslug: samplesby\nsourceRef: it/find.go#L474\ncategory: it\nsubCategory: find\nsignatures:\n  - \"func SamplesBy[T any, I ~func(func(T) bool)](collection I, count int, randomIntGenerator func(int) int) I\"\nplayUrl: https://go.dev/play/p/fX2FEtixrVG\nvariantHelpers:\n  - it#find#samplesby\nsimilarHelpers:\n  - core#slice#samplesby\n  - it#find#sample\n  - it#find#samples\n  - it#find#sampleby\nposition: 620\n---\n\nReturns N random unique items from collection, using randomIntGenerator as the random index generator.\n\nWill iterate through the entire sequence and allocate a slice large enough to hold all elements.\nLong input sequences can cause excessive memory usage.\n\nExamples:\n\n```go\nimport (\n    \"math/rand\"\n    \"time\"\n)\n\n// Use default random generator with seed\nrng := rand.New(rand.NewSource(time.Now().UnixNano()))\n\n// Get 3 random unique items with custom random generator\nnumbers := it.Slice([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10})\nsamples := it.SamplesBy(numbers, 3, rng.Intn)\n// samples: sequence of 3 random unique numbers\n\n// Use deterministic random generator for testing\ndeterministicRng := rand.New(rand.NewSource(42))\nsamples := it.SamplesBy(numbers, 3, deterministicRng.Intn)\n// samples: predictable sequence of 3 unique numbers\n\n// With strings\nwords := it.Slice([]string{\"apple\", \"banana\", \"cherry\", \"date\", \"elderberry\"})\nsamples := it.SamplesBy(words, 2, rng.Intn)\n// samples: sequence of 2 random unique words\n\n// With structs\ntype Person struct {\n    Name string\n    Age  int\n}\npeople := it.Slice([]Person{\n    {Name: \"Alice\", Age: 30},\n    {Name: \"Bob\", Age: 25},\n    {Name: \"Charlie\", Age: 35},\n    {Name: \"Diana\", Age: 28},\n    {Name: \"Eve\", Age: 32},\n})\nsamples := it.SamplesBy(people, 3, rng.Intn)\n// samples: sequence of 3 random unique people\n\n// Custom random function that biases towards certain items\nbiasedRandom := func(max int) int {\n    // Bias towards first half of collection\n    return rng.Intn(max/2 + 1)\n}\nsamples := it.SamplesBy(numbers, 3, biasedRandom)\n// samples: sequence of 3 random unique numbers, biased towards lower indices\n\n// With zero-based modulo function (wraps around)\nmoduloRandom := func(max int) int {\n    return rng.Intn(max*3) % max\n}\nsamples := it.SamplesBy(numbers, 3, moduloRandom)\n// samples: sequence of 3 random unique numbers\n\n// Test with deterministic function\ndeterministicFunc := func(max int) int {\n    return (max - 1) / 2 // Always return middle index\n}\nsamples := it.SamplesBy(numbers, 1, deterministicFunc)\n// samples: sequence with single element from middle\n```"
  },
  {
    "path": "docs/data/it-seqtochannel.md",
    "content": "---\nname: SeqToChannel\nslug: seqtochannel\nsourceRef: it/channel.go#L12\ncategory: it\nsubCategory: channel\nsignatures:\n  - \"func SeqToChannel[T any](bufferSize int, collection iter.Seq[T]) <-chan T\"\n  - \"func SeqToChannel2[K, V any](bufferSize int, collection iter.Seq2[K, V]) <-chan Tuple2[K, V]\"\nplayUrl: \"https://go.dev/play/p/id3jqJPffT6\"\nvariantHelpers:\n  - it#channel#seqtochannel\n  - it#channel#seqtochannel2\nsimilarHelpers:\n  - it#channel#channeltoseq\nposition: 0\n---\n\nConverts an `iter.Seq` (or `iter.Seq2`) into a read-only channel. Items are sent on a buffered channel and the channel is closed when the sequence ends.\n\nExamples:\n\n```go\n// SeqToChannel: stream ints from a sequence\nseq := it.Range(5) // 0..4\nch := it.SeqToChannel(2, seq)\nvar got []int\nfor v := range ch {\n    got = append(got, v)\n}\n// got == []int{0, 1, 2, 3, 4}\n```\n\n```go\n// SeqToChannel2: stream key/value pairs as Tuple2\nm := map[string]int{\"a\": 1, \"b\": 2}\nkv := it.Entries(m)\nch := it.SeqToChannel2(1, kv)\nfor pair := range ch {\n    // pair.A is key, pair.B is value\n}\n```\n\n\n"
  },
  {
    "path": "docs/data/it-sequencestate.md",
    "content": "---\nname: Empty\nslug: sequencestate\nsourceRef: it/type_manipulation.go#L43\ncategory: it\nsubCategory: type\nsignatures:\n  - \"func Empty[T any]() iter.Seq[T]\"\n  - \"func IsEmpty[T any](collection iter.Seq[T]) bool\"\n  - \"func IsNotEmpty[T any](collection iter.Seq[T]) bool\"\n  - \"func CoalesceSeq[T any](v ...iter.Seq[T]) (iter.Seq[T], bool)\"\n  - \"func CoalesceSeqOrEmpty[T any](v ...iter.Seq[T]) iter.Seq[T]\"\nvariantHelpers:\n  - it#type#empty\n  - it#type#isempty\n  - it#type#isnotempty\n  - it#type#coalesceseq\n  - it#type#coalesceseqorempty\nsimilarHelpers:\n  - core#type#isempty\n  - core#type#isnotempty\n  - core#condition#coalesce\nposition: 250\n---\n\nEmpty returns an empty sequence.\n\n```go\nempty := it.Empty[int]()\nvar result []int\nfor item := range empty {\n    result = append(result, item)\n}\n// result is empty []\n```\n\nIsEmpty returns true if the sequence is empty.\n\n```go\nemptySeq := it.Empty[int]()\nnotEmptySeq := func(yield func(int) bool) {\n    yield(1)\n}\n\nfmt.Println(it.IsEmpty(emptySeq))    // true\nfmt.Println(it.IsEmpty(notEmptySeq)) // false\n```\n\nIsNotEmpty returns true if the sequence is not empty.\n\n```go\nemptySeq := it.Empty[int]()\nnotEmptySeq := func(yield func(int) bool) {\n    yield(1)\n}\n\nfmt.Println(it.IsNotEmpty(emptySeq))    // false\nfmt.Println(it.IsNotEmpty(notEmptySeq)) // true\n```\n\nCoalesceSeq returns the first non-empty sequence.\n\n```go\nempty1 := it.Empty[int]()\nempty2 := it.Empty[int]()\nnotEmpty := func(yield func(int) bool) {\n    yield(1)\n    yield(2)\n}\n\nresult, found := it.CoalesceSeq(empty1, empty2, notEmpty)\n// found is true, result is the notEmpty sequence\n\nresult2, found2 := it.CoalesceSeq(empty1, empty2)\n// found2 is false, result2 is an empty sequence\n```\n\nCoalesceSeqOrEmpty returns the first non-empty sequence.\n\n```go\nempty1 := it.Empty[int]()\nempty2 := it.Empty[int]()\nnotEmpty := func(yield func(int) bool) {\n    yield(1)\n    yield(2)\n}\n\nresult := it.CoalesceSeqOrEmpty(empty1, empty2, notEmpty)\n// result is the notEmpty sequence\n\nresult2 := it.CoalesceSeqOrEmpty(empty1, empty2)\n// result2 is an empty sequence\n```"
  },
  {
    "path": "docs/data/it-shuffle.md",
    "content": "---\nname: Shuffle\nslug: shuffle\nsourceRef: it/seq.go#L357\ncategory: it\nsubCategory: sequence\nsignatures:\n  - \"func Shuffle[T any, I ~func(func(T) bool)](collection I) I\"\nplayUrl: https://go.dev/play/p/3WOx-ukGvKK\nvariantHelpers:\n  - it#sequence#shuffle\nsimilarHelpers:\n  - core#slice#shuffle\n  - it#sequence#reverse\nposition: 130\n---\n\nReturns a sequence of shuffled values using Fisher-Yates algorithm. Note: this requires collecting all elements in memory.\n\nExamples:\n\n```go\nseq := func(yield func(int) bool) {\n    _ = yield(1)\n    _ = yield(2)\n    _ = yield(3)\n    _ = yield(4)\n    _ = yield(5)\n}\nshuffled := it.Shuffle(seq)\nvar result []int\nfor v := range shuffled {\n    result = append(result, v)\n}\n// result contains the same elements in random order\n```"
  },
  {
    "path": "docs/data/it-slice.md",
    "content": "---\nname: Slice\nslug: slice\nsourceRef: it/seq.go#L680\ncategory: it\nsubCategory: sequence\nsignatures:\n  - \"func Slice[T any, I ~func(func(T) bool)](collection I, start, end int) I\"\nplayUrl: \"https://go.dev/play/p/5WqJN9-zv\" \nvariantHelpers:\n  - it#slice#drop\nsimilarHelpers:\n  - core#slice#slice\n  - core#slice#chunk\nposition: 80\n---\n\nReturns a sub-sequence from start index to end index (exclusive).\n\n```go\nresult := it.Slice(it.Range(1, 10), 2, 5)\n// [3, 4, 5]\n```"
  },
  {
    "path": "docs/data/it-sliding.md",
    "content": "---\nname: Sliding\nslug: sliding\nsourceRef: it/seq.go#L329\ncategory: it\nsubCategory: sequence\nsignatures:\n  - \"func Sliding[T any](collection iter.Seq[T], size, step int) iter.Seq[[]T]\"\nplayUrl: https://go.dev/play/p/mzhO4CZeiik\nvariantHelpers:\n  - it#sequence#sliding\nsimilarHelpers:\n  - core#slice#sliding\nposition: 80\n---\n\nCreates a sequence of sliding windows of a given size with a given step. If step equals size, windows don't overlap.\n\n```go\nseq := func(yield func(int) bool) {\n    yield(1)\n    yield(2)\n    yield(3)\n    yield(4)\n    yield(5)\n    yield(6)\n    yield(7)\n    yield(8)\n}\nwindows := it.Sliding(seq, 2, 3)\nvar result [][]int\nfor w := range windows {\n    result = append(result, w)\n}\n// result contains [1 2], [4 5], [7 8]\n```\n"
  },
  {
    "path": "docs/data/it-some.md",
    "content": "---\nname: Some\nslug: some\nsourceRef: it/intersect.go#L52\ncategory: it\nsubCategory: intersect\nsignatures:\n  - \"func Some[T comparable](collection iter.Seq[T], subset ...T) bool\"\nplayUrl: \"https://go.dev/play/p/KmX-fXictQl\"\nvariantHelpers:\n  - it#intersect#some\nsimilarHelpers:\n  - core#slice#some\n  - it#intersect#every\n  - it#intersect#none\nposition: 40\n---\n\nReturns true if at least one element of a subset is contained in a collection.\n\nExamples:\n\n```go\nseq := func(yield func(int) bool) {\n    _ = yield(1)\n    _ = yield(2)\n    _ = yield(3)\n    _ = yield(4)\n    _ = yield(5)\n}\nhasAny := it.Some(seq, 2, 6)\n// hasAny == true (2 is in collection)\n```\n\n```go\nseq := func(yield func(string) bool) {\n    _ = yield(\"apple\")\n    _ = yield(\"banana\")\n    _ = yield(\"cherry\")\n}\nhasAny := it.Some(seq, \"orange\", \"grape\")\n// hasAny == false (neither is in collection)\n```"
  },
  {
    "path": "docs/data/it-someby.md",
    "content": "---\nname: SomeBy\nslug: someby\nsourceRef: it/intersect.go#L56\ncategory: it\nsubCategory: intersect\nsignatures:\n  - \"func SomeBy[T any](collection iter.Seq[T], predicate func(item T) bool) bool\"\nplayUrl: https://go.dev/play/p/PDT6dWCl7Md\nvariantHelpers:\n  - it#intersect#someby\nsimilarHelpers:\n  - core#slice#someby\nposition: 670\n---\n\nReturns true if the predicate returns true for any of the elements in the collection.\n\nIf the collection is empty SomeBy returns false.\nWill iterate through the entire sequence if predicate never returns true.\n\nExamples:\n\n```go\n// Check if any number is even\nnumbers := it.Slice([]int{1, 3, 5, 7, 9})\nhasEven := it.SomeBy(numbers, func(n int) bool { return n%2 == 0 })\n// hasEven: false\n\nnumbers = it.Slice([]int{1, 3, 5, 8, 9})\nhasEven = it.SomeBy(numbers, func(n int) bool { return n%2 == 0 })\n// hasEven: true\n\n// Check if any string starts with specific prefix\nwords := it.Slice([]string{\"hello\", \"world\", \"go\", \"lang\"})\nhasGoPrefix := it.SomeBy(words, func(s string) bool { return strings.HasPrefix(s, \"go\") })\n// hasGoPrefix: true\n\nhasPythonPrefix := it.SomeBy(words, func(s string) bool { return strings.HasPrefix(s, \"python\") })\n// hasPythonPrefix: false\n\n// Check if any person is a teenager\ntype Person struct {\n    Name string\n    Age  int\n}\npeople := it.Slice([]Person{\n    {Name: \"Alice\", Age: 30},\n    {Name: \"Bob\", Age: 25},\n    {Name: \"Charlie\", Age: 35},\n})\nhasTeenager := it.SomeBy(people, func(p Person) bool { return p.Age >= 13 && p.Age <= 19 })\n// hasTeenager: false\n\nteenagers := it.Slice([]Person{\n    {Name: \"Alice\", Age: 30},\n    {Name: \"Bob\", Age: 16},  // Teenager\n    {Name: \"Charlie\", Age: 35},\n})\nhasTeenager = it.SomeBy(teenagers, func(p Person) bool { return p.Age >= 13 && p.Age <= 19 })\n// hasTeenager: true\n\n// Check if any number is greater than 100\nnumbers = it.Slice([]int{1, 3, 5, 7, 9})\nhasLargeNumber := it.SomeBy(numbers, func(n int) bool { return n > 100 })\n// hasLargeNumber: false\n\nnumbers = it.Slice([]int{1, 3, 5, 150, 9})\nhasLargeNumber = it.SomeBy(numbers, func(n int) bool { return n > 100 })\n// hasLargeNumber: true\n\n// Check if any string contains a substring\nstrings := it.Slice([]string{\"hello\", \"world\", \"go\", \"lang\"})\nhasWorld := it.SomeBy(strings, func(s string) bool { return strings.Contains(s, \"world\") })\n// hasWorld: true\n\nhasPython := it.SomeBy(strings, func(s string) bool { return strings.Contains(s, \"python\") })\n// hasPython: false\n\n// Empty collection returns false\nempty := it.Slice([]int{})\nhasAny := it.SomeBy(empty, func(n int) bool { return n > 0 })\n// hasAny: false\n\n// Check if any email is from specific domain\nemails := it.Slice([]string{\"user@example.com\", \"test@gmail.com\", \"admin@site.net\"})\nhasGmail := it.SomeBy(emails, func(email string) bool { return strings.HasSuffix(email, \"@gmail.com\") })\n// hasGmail: true\n\nhasYahoo := it.SomeBy(emails, func(email string) bool { return strings.HasSuffix(email, \"@yahoo.com\") })\n// hasYahoo: false\n\n// Check if any string is palindrome\nwords := it.Slice([]string{\"level\", \"hello\", \"world\", \"radar\"})\nhasPalindrome := it.SomeBy(words, func(s string) bool {\n    return s == reverseString(s)\n})\n// hasPalindrome: true (\"level\" and \"radar\" are palindromes)\n```"
  },
  {
    "path": "docs/data/it-splice.md",
    "content": "---\nname: Splice\nslug: splice\nsourceRef: it/seq.go#L744\ncategory: it\nsubCategory: sequence\nsignatures:\n  - \"func Splice[T any, I ~func(func(T) bool)](collection I, index int, elements ...T) I\"\nvariantHelpers:\n  - it#sequence#splice\nsimilarHelpers:\n  - it#sequence#slice\n  - it#sequence#replace\n  - it#sequence#replaceall\n  - core#slice#splice\nposition: 122\n---\n\nInserts elements into a sequence at the specified index. Returns a new sequence with the elements inserted.\n\n```go\nseq := func(yield func(int) bool) {\n    yield(1)\n    yield(2)\n    yield(5)\n}\nresult := it.Splice(seq, 2, 3, 4)\n// iter.Seq[int] yielding 1, 2, 3, 4, 5\n\nresult = it.Splice(seq, 0, 0)\n// iter.Seq[int] yielding 0, 1, 2, 5 (insert at beginning)\n\nresult = it.Splice(seq, 3, 6, 7)\n// iter.Seq[int] yielding 1, 2, 5, 6, 7 (insert at end)\n\nseq = func(yield func(string) bool) {\n    yield(\"a\")\n    yield(\"c\")\n}\nresult = it.Splice(seq, 1, \"b\")\n// iter.Seq[string] yielding \"a\", \"b\", \"c\"\n\nresult = it.Splice(seq, 1, \"x\", \"y\")\n// iter.Seq[string] yielding \"a\", \"x\", \"y\", \"c\"\n```\n"
  },
  {
    "path": "docs/data/it-subset.md",
    "content": "---\nname: Subset\nslug: subset\nsourceRef: it/seq.go#L667\ncategory: it\nsubCategory: sequence\nsignatures:\n  - \"func Subset[T any, I ~func(func(T) bool)](collection I, offset, length int) I\"\nvariantHelpers:\n  - it#sequence#subset\nsimilarHelpers:\n  - it#sequence#slice\n  - it#sequence#drop\n  - it#sequence#dropright\n  - core#slice#slice\nposition: 120\n---\n\nReturns a subset of a sequence starting from the specified offset with the given length.\n\n```go\nseq := func(yield func(int) bool) {\n    yield(1)\n    yield(2)\n    yield(3)\n    yield(4)\n    yield(5)\n}\nresult := it.Subset(seq, 1, 3)\n// iter.Seq[int] yielding 2, 3, 4\n\nresult = it.Subset(seq, 0, 2)\n// iter.Seq[int] yielding 1, 2\n\nresult = it.Subset(seq, 3, 10)\n// iter.Seq[int] yielding 4, 5 (returns available elements)\n\nresult = it.Subset(seq, 10, 5)\n// iter.Seq[int] yielding nothing (offset beyond sequence)\n\nseq = func(yield func(string) bool) {\n    yield(\"a\")\n    yield(\"b\")\n    yield(\"c\")\n    yield(\"d\")\n}\nresult = it.Subset(seq, 1, 2)\n// iter.Seq[string] yielding \"b\", \"c\"\n```"
  },
  {
    "path": "docs/data/it-sum.md",
    "content": "---\nname: Sum / SumBy\nslug: sum\nsourceRef: it/math.go#L59\ncategory: it\nsubCategory: math\nsignatures:\n  - \"func Sum[T constraints.Float | constraints.Integer | constraints.Complex](collection iter.Seq[T]) T\"\n  - \"func SumBy[T any, R constraints.Float | constraints.Integer | constraints.Complex](collection iter.Seq[T], iteratee func(item T) R) R\"\nplayUrl: \"https://go.dev/play/p/nHbGFOEIeTa\"\nvariantHelpers:\n  - it#math#sum\n  - it#math#sumby\nsimilarHelpers:\n  - core#slice#sum\n  - core#slice#sumby\n  - core#slice#product\n  - core#slice#productby\nposition: 10\n---\n\nSums values from a sequence. `SumBy` applies a transform and sums the results. Returns 0 for empty sequences.\n\nExamples:\n\n```go\nsum := it.Sum(it.RangeFrom(1, 5))\n// 1 + 2 + 3 + 4 + 5 == 15\n```\n\n```go\ntype User struct { Name string; Score int }\nusers := func(yield func(User) bool) {\n    _ = yield(User{\"a\", 3})\n    _ = yield(User{\"b\", 7})\n}\ntotal := it.SumBy(iter.Seq[User](users), func(u User) int { return u.Score })\n// total == 10\n```\n\n\n"
  },
  {
    "path": "docs/data/it-sumby.md",
    "content": "---\nname: SumBy\nslug: sumby\nsourceRef: it/math.go#L74\ncategory: it\nsubCategory: math\nsignatures:\n  - \"func SumBy[T any, R constraints.Float | constraints.Integer | constraints.Complex](collection iter.Seq[T], transform func(item T) R) R\"\nplayUrl: https://go.dev/play/p/ZNiqXNMu5QP\nvariantHelpers:\n  - it#math#sumby\nsimilarHelpers:\n  - core#slice#sumby\n  - core#slice#sum\nposition: 65\n---\n\nReturns the sum of values in the collection using the given transform function.\n\n```go\ntype Person struct {\n    Name string\n    Age  int\n}\n\npeople := it.Slice([]Person{\n    {\"Alice\", 25},\n    {\"Bob\", 30},\n    {\"Charlie\", 35},\n})\n\nresult := it.SumBy(people, func(p Person) int {\n    return p.Age\n})\n// 90\n```"
  },
  {
    "path": "docs/data/it-take.md",
    "content": "---\nname: Take\nslug: take\nsourceRef: it/seq.go#L682\ncategory: it\nsubCategory: sequence\nsignatures:\n  - \"func Take[T any, I ~func(func(T) bool)](collection I, n int) I\"\nvariantHelpers:\n  - it#sequence#take\nsimilarHelpers:\n  - core#slice#take\nposition: 110\n---\n\nTakes the first n elements from a sequence.\n\n```go\nseq := func(yield func(int) bool) {\n    yield(1)\n    yield(2)\n    yield(3)\n    yield(4)\n}\nresult := it.Take(seq, 2)\nvar out []int\nfor v := range result {\n    out = append(out, v)\n}\n// out contains [1, 2]\n```\n"
  },
  {
    "path": "docs/data/it-takefilter.md",
    "content": "---\nname: TakeFilter\nslug: takefilter\nsourceRef: it/seq.go#L725\ncategory: it\nsubCategory: sequence\nsignatures:\n  - \"func TakeFilter[T any, I ~func(func(T) bool)](collection I, n int, predicate func(item T) bool) I\"\n  - \"func TakeFilterI[T any, I ~func(func(T) bool)](collection I, n int, predicate func(item T, index int) bool) I\"\nplayUrl: https://go.dev/play/p/Db68Bhu4MCA\nvariantHelpers:\n  - it#sequence#takefilter\n  - it#sequence#takefilteri\nsimilarHelpers:\n  - core#slice#takefilter\nposition: 130\n---\n\nFilters elements and takes the first n matches. Stops once n matches are found.\n\n### TakeFilter\n\n```go\nseq := func(yield func(int) bool) {\n    yield(1)\n    yield(2)\n    yield(3)\n    yield(4)\n    yield(5)\n    yield(6)\n}\nresult := it.TakeFilter(seq, 2, func(x int) bool {\n    return x%2 == 0\n})\nvar out []int\nfor v := range result {\n    out = append(out, v)\n}\n// out contains [2, 4]\n```\n\n### TakeFilterI\n\n```go\nresult := it.TakeFilterI(seq, 2, func(x, index int) bool {\n    return x%2 == 0 && index < 4\n})\n// out contains [2, 4]\n```\n"
  },
  {
    "path": "docs/data/it-takewhile.md",
    "content": "---\nname: TakeWhile\nslug: takewhile\nsourceRef: it/seq.go#L706\ncategory: it\nsubCategory: sequence\nsignatures:\n  - \"func TakeWhile[T any, I ~func(func(T) bool)](collection I, predicate func(item T) bool) I\"\nvariantHelpers:\n  - it#sequence#takewhile\nsimilarHelpers:\n  - core#slice#takewhile\nposition: 120\n---\n\nTakes elements from the beginning of a sequence while the predicate returns true.\n\n```go\nseq := func(yield func(int) bool) {\n    yield(1)\n    yield(2)\n    yield(3)\n    yield(4)\n}\nresult := it.TakeWhile(seq, func(x int) bool {\n    return x < 3\n})\nvar out []int\nfor v := range result {\n    out = append(out, v)\n}\n// out contains [1, 2]\n```\n"
  },
  {
    "path": "docs/data/it-times.md",
    "content": "---\nname: Times\nslug: times\nsourceRef: it/seq.go#L202\ncategory: it\nsubCategory: sequence\nsignatures:\n  - \"func Times[T any](count int, callback func(index int) T) iter.Seq[T]\"\nplayUrl: https://go.dev/play/p/0W4IRzQuCEc\nvariantHelpers:\n  - it#sequence#times\nsimilarHelpers:\n  - core#slice#times\n  - it#math#range\nposition: 70\n---\n\nInvokes a callback function n times and returns a sequence of the results.\n\nExamples:\n\n```go\nseq := it.Times(5, func(index int) int {\n    return index * 2\n})\nvar result []int\nfor v := range seq {\n    result = append(result, v)\n}\n// result contains 0, 2, 4, 6, 8\n```\n\n```go\nseq := it.Times(3, func(index int) string {\n    return fmt.Sprintf(\"item-%d\", index+1)\n})\nvar result []string\nfor v := range seq {\n    result = append(result, v)\n}\n// result contains \"item-1\", \"item-2\", \"item-3\"\n```"
  },
  {
    "path": "docs/data/it-toanyseq.md",
    "content": "---\nname: ToAnySeq\nslug: toanyseq\nsourceRef: it/type_manipulation.go#L11\ncategory: it\nsubCategory: type\nsignatures:\n  - \"func ToAnySeq[T any](collection iter.Seq[T]) iter.Seq[any]\"\nvariantHelpers:\n  - it#type#fromanyseq\nplayUrl: \"https://go.dev/play/p/ktE4IMXDMxv\"\nsimilarHelpers:\n  - core#type#toany\nposition: 243\n---\n\nToAnySeq returns a sequence with all elements mapped to `any` type.\n\n```go\ncollection := func(yield func(int) bool) {\n    yield(1)\n    yield(2)\n    yield(3)\n}\n\nanySeq := it.ToAnySeq(collection)\nvar result []any\nfor item := range anySeq {\n    result = append(result, item)\n}\n// result contains [1, 2, 3] as any type\n```"
  },
  {
    "path": "docs/data/it-toseqptr.md",
    "content": "---\nname: ToSeqPtr\nslug: toseqptr\nsourceRef: it/type_manipulation.go#L11\ncategory: it\nsubCategory: type\nsignatures:\n  - \"func ToSeqPtr[T any](collection iter.Seq[T]) iter.Seq[*T]\"\nplayUrl: \"https://go.dev/play/p/70BcKpDcOKm\"\nvariantHelpers: []\nsimilarHelpers:\n  - core#type#toptr\nposition: 240\n---\n\nToSeqPtr returns a sequence of pointers to each value.\n\n```go\ncollection := func(yield func(int) bool) {\n    yield(1)\n    yield(2)\n    yield(3)\n}\n\nptrs := it.ToSeqPtr(collection)\nvar result []*int\nfor ptr := range ptrs {\n    result = append(result, ptr)\n}\n// result contains pointers to 1, 2, 3\n```"
  },
  {
    "path": "docs/data/it-trim.md",
    "content": "---\nname: Trim\nslug: trim\nsourceRef: it/seq.go#L778\ncategory: it\nsubCategory: string\nsignatures:\n  - \"func Trim[T comparable, I ~func(func(T) bool)](collection I, cutset ...T) I\"\nplayUrl: https://go.dev/play/p/k0VCcilk4V1\nvariantHelpers:\n  - it#string#trimfirst\n  - it#string#trimlast\nsimilarHelpers:\n  - core#string#trim\nposition: 262\n---\n\nTrim removes all the leading and trailing cutset from the collection.\n\n```go\ncollection := func(yield func(int) bool) {\n    yield(0)\n    yield(0)\n    yield(1)\n    yield(2)\n    yield(3)\n    yield(0)\n    yield(0)\n}\n\ntrimmed := it.Trim(collection, 0)\nvar result []int\nfor item := range trimmed {\n    result = append(result, item)\n}\n// result contains [1, 2, 3]\n```"
  },
  {
    "path": "docs/data/it-trimfirst.md",
    "content": "---\nname: TrimFirst\nslug: trimfirst\nsourceRef: it/seq.go#L778\ncategory: it\nsubCategory: string\nsignatures:\n  - \"func TrimFirst[T comparable, I ~func(func(T) bool)](collection I, cutset ...T) I\"\nplayUrl: https://go.dev/play/p/4D4Ke5C5MwH\nvariantHelpers:\n  - it#string#trim\n  - it#string#trimlast\nsimilarHelpers: []\nposition: 263\n---\n\nTrimFirst removes all the leading cutset from the collection.\n\n```go\ncollection := func(yield func(int) bool) {\n    yield(0)\n    yield(0)\n    yield(1)\n    yield(2)\n    yield(3)\n}\n\ntrimmed := it.TrimFirst(collection, 0)\nvar result []int\nfor item := range trimmed {\n    result = append(result, item)\n}\n// result contains [1, 2, 3]\n```"
  },
  {
    "path": "docs/data/it-trimlast.md",
    "content": "---\nname: TrimLast\nslug: trimlast\nsourceRef: it/seq.go#L778\ncategory: it\nsubCategory: string\nsignatures:\n  - \"func TrimLast[T comparable, I ~func(func(T) bool)](collection I, cutset ...T) I\"\nplayUrl: https://go.dev/play/p/GQLhnaeW0gd\nvariantHelpers:\n  - it#string#trim\n  - it#string#trimfirst\nsimilarHelpers: []\nposition: 264\n---\n\nTrimLast removes all the trailing cutset from the collection.\n\n```go\ncollection := func(yield func(int) bool) {\n    yield(1)\n    yield(2)\n    yield(3)\n    yield(0)\n    yield(0)\n}\n\ntrimmed := it.TrimLast(collection, 0)\nvar result []int\nfor item := range trimmed {\n    result = append(result, item)\n}\n// result contains [1, 2, 3]\n```"
  },
  {
    "path": "docs/data/it-trimprefix.md",
    "content": "---\nname: TrimPrefix\nslug: trimprefix\nsourceRef: it/seq.go#L778\ncategory: it\nsubCategory: string\nsignatures:\n  - \"func TrimPrefix[T comparable, I ~func(func(T) bool)](collection I, prefix []T) I\"\nplayUrl: https://go.dev/play/p/Pce4zSPnThY\nvariantHelpers: []\nsimilarHelpers:\n  - core#string#trimprefix\nposition: 265\n---\n\nTrimPrefix removes all the leading prefix from the collection.\n\n```go\ncollection := func(yield func(int) bool) {\n    yield(1)\n    yield(2)\n    yield(1)\n    yield(2)\n    yield(3)\n}\n\ntrimmed := it.TrimPrefix(collection, []int{1, 2})\nvar result []int\nfor item := range trimmed {\n    result = append(result, item)\n}\n// result contains [1, 2, 3]\n```"
  },
  {
    "path": "docs/data/it-trimsuffix.md",
    "content": "---\nname: TrimSuffix\nslug: trimsuffix\nsourceRef: it/seq.go#L778\ncategory: it\nsubCategory: string\nsignatures:\n  - \"func TrimSuffix[T comparable, I ~func(func(T) bool)](collection I, suffix []T) I\"\nplayUrl: https://go.dev/play/p/s9nwy9helEi\nvariantHelpers: []\nsimilarHelpers:\n  - core#string#trimsuffix\nposition: 266\n---\n\nTrimSuffix removes all the trailing suffix from the collection.\n\n```go\ncollection := func(yield func(int) bool) {\n    yield(1)\n    yield(2)\n    yield(3)\n    yield(4)\n    yield(3)\n    yield(4)\n}\n\ntrimmed := it.TrimSuffix(collection, []int{3, 4})\nvar result []int\nfor item := range trimmed {\n    result = append(result, item)\n}\n// result contains [1, 2]\n```"
  },
  {
    "path": "docs/data/it-union.md",
    "content": "---\nname: Union\nslug: union\nsourceRef: it/intersect.go#L136\ncategory: it\nsubCategory: intersect\nsignatures:\n  - \"func Union[T comparable, I ~func(func(T) bool)](lists ...I) I\"\nplayUrl: \"https://go.dev/play/p/ImIoFNpSUUB\"\nvariantHelpers:\n  - it#intersect#union\nsimilarHelpers:\n  - core#slice#union\n  - it#intersect#intersect\nposition: 20\n---\n\nReturns all distinct elements from given collections (union of all collections).\n\nExamples:\n\n```go\nseq1 := func(yield func(int) bool) {\n    _ = yield(1)\n    _ = yield(2)\n    _ = yield(3)\n}\nseq2 := func(yield func(int) bool) {\n    _ = yield(2)\n    _ = yield(3)\n    _ = yield(4)\n}\nseq3 := func(yield func(int) bool) {\n    _ = yield(3)\n    _ = yield(5)\n}\nunion := it.Union(seq1, seq2, seq3)\nvar result []int\nfor v := range union {\n    result = append(result, v)\n}\n// result contains 1, 2, 3, 4, 5 (all distinct elements)\n```"
  },
  {
    "path": "docs/data/it-uniq.md",
    "content": "---\nname: Uniq\nslug: uniq\nsourceRef: it/seq.go#L216\ncategory: it\nsubCategory: sequence\nsignatures:\n  - \"func Uniq[T comparable, I ~func(func(T) bool)](collection I) I\"\nplayUrl: https://go.dev/play/p/D-SenTW-ipj\nvariantHelpers:\n  - it#sequence#uniq\nsimilarHelpers:\n  - core#slice#uniq\n  - it#sequence#uniqby\nposition: 50\n---\n\nReturns a duplicate-free version of a sequence, removing consecutive duplicates.\n\nExamples:\n\n```go\nseq := func(yield func(int) bool) {\n    _ = yield(1)\n    _ = yield(2)\n    _ = yield(2)\n    _ = yield(3)\n    _ = yield(2)\n    _ = yield(2)\n}\nuniqueSeq := it.Uniq(seq)\nvar result []int\nfor v := range uniqueSeq {\n    result = append(result, v)\n}\n// result contains 1, 2, 3, 2 (consecutive duplicates removed)\n```"
  },
  {
    "path": "docs/data/it-uniqby.md",
    "content": "---\nname: UniqBy\nslug: uniqby\nsourceRef: it/seq.go#L225\ncategory: it\nsubCategory: sequence\nsignatures:\n  - \"func UniqBy[T any, U comparable, I ~func(func(T) bool)](collection I, transform func(item T) U) I\"\nplayUrl: https://go.dev/play/p/HKrt3AvwMTR\nvariantHelpers:\n  - it#slice#uniq\nsimilarHelpers:\n  - core#slice#uniqby\n  - core#slice#uniq\nposition: 45\n---\n\nReturns a sequence with duplicate elements removed based on a transform function.\n\n```go\nresult := it.UniqBy(it.Range(1, 7), func(item int) int {\n    return item % 3\n})\n// [1, 2, 3]\n```"
  },
  {
    "path": "docs/data/it-uniqkeys.md",
    "content": "---\nname: UniqKeys\nslug: uniqkeys\nsourceRef: it/map.go#L26\ncategory: it\nsubCategory: map\nsignatures:\n  - \"func UniqKeys[K comparable, V any](in ...map[K]V) iter.Seq[K]\"\nplayUrl: \"https://go.dev/play/p/_NicwfgAHbO\"\nvariantHelpers:\n  - it#map#uniqkeys\nsimilarHelpers:\n  - core#slice#uniqkeys\nposition: 800\n---\n\nCreates a sequence of unique keys from multiple maps.\n\nWill allocate a map large enough to hold all distinct input keys.\nLong input sequences with heterogeneous keys can cause excessive memory usage.\n\nExamples:\n\n```go\n// Single map\nm1 := map[string]int{\n    \"apple\":  1,\n    \"banana\": 2,\n    \"cherry\": 3,\n}\nuniqueKeys := it.UniqKeys(m1)\n// uniqueKeys: sequence with \"apple\", \"banana\", \"cherry\"\n\n// Multiple maps with duplicate keys\nm1 := map[string]int{\n    \"apple\":  1,\n    \"banana\": 2,\n}\nm2 := map[string]int{\n    \"banana\": 3,\n    \"cherry\": 4,\n    \"apple\":  5,\n}\nuniqueKeys = it.UniqKeys(m1, m2)\n// uniqueKeys: sequence with \"apple\", \"banana\", \"cherry\" (no duplicates)\n\n// Maps with integer keys\nscores1 := map[int]string{\n    1: \"Alice\",\n    2: \"Bob\",\n    3: \"Charlie\",\n}\nscores2 := map[int]string{\n    3: \"David\",\n    4: \"Eve\",\n    1: \"Frank\",\n}\nuniqueKeys = it.UniqKeys(scores1, scores2)\n// uniqueKeys: sequence with 1, 2, 3, 4\n\n// Maps with struct keys\ntype Person struct {\n    Name string\n    Age  int\n}\npeople1 := map[Person]bool{\n    {Name: \"Alice\", Age: 30}: true,\n    {Name: \"Bob\", Age: 25}:   true,\n}\npeople2 := map[Person]bool{\n    {Name: \"Bob\", Age: 25}:     false,  // Same struct\n    {Name: \"Charlie\", Age: 35}: true,\n}\nuniqueKeys = it.UniqKeys(people1, people2)\n// uniqueKeys: sequence with {Alice 30}, {Bob 25}, {Charlie 35}\n\n// Empty maps\nempty1 := map[string]int{}\nempty2 := map[string]int{}\nuniqueKeys = it.UniqKeys(empty1, empty2)\n// uniqueKeys: empty sequence\n\n// Mix of empty and non-empty maps\nm1 := map[string]int{\"a\": 1}\nempty := map[string]int{}\nm2 := map[string]int{\"b\": 2}\nuniqueKeys = it.UniqKeys(m1, empty, m2)\n// uniqueKeys: sequence with \"a\", \"b\"\n\n// Maps with same keys but different values\nm1 := map[string]int{\n    \"key1\": 10,\n    \"key2\": 20,\n}\nm2 := map[string]int{\n    \"key1\": 100,  // Same key, different value\n    \"key3\": 30,\n}\nuniqueKeys = it.UniqKeys(m1, m2)\n// uniqueKeys: sequence with \"key1\", \"key2\", \"key3\" (key1 appears once)\n\n// Large number of maps\nmaps := make([]map[int]string, 100)\nfor i := range maps {\n    maps[i] = map[int]string{i: fmt.Sprintf(\"value%d\", i)}\n}\nuniqueKeys = it.UniqKeys(maps...)\n// uniqueKeys: sequence with keys 0, 1, 2, ..., 99\n```"
  },
  {
    "path": "docs/data/it-uniqvalues.md",
    "content": "---\nname: UniqValues\nslug: uniqvalues\nsourceRef: it/map.go#L59\ncategory: it\nsubCategory: map\nsignatures:\n  - \"func UniqValues[K, V comparable](in ...map[K]V) iter.Seq[V]\"\nplayUrl: https://go.dev/play/p/QQv4zGrk-fF\nvariantHelpers:\n  - it#map#uniqvalues\nsimilarHelpers:\n  - core#slice#uniqvalues\nposition: 810\n---\n\nCreates a sequence of unique values from multiple maps.\n\nWill allocate a map large enough to hold all distinct input values.\nLong input sequences with heterogeneous values can cause excessive memory usage.\n\nExamples:\n\n```go\n// Single map\nm1 := map[string]int{\n    \"apple\":  1,\n    \"banana\": 2,\n    \"cherry\": 3,\n}\nuniqueValues := it.UniqValues(m1)\n// uniqueValues: sequence with 1, 2, 3\n\n// Multiple maps with duplicate values\nm1 := map[string]int{\n    \"apple\":  1,\n    \"banana\": 2,\n}\nm2 := map[string]int{\n    \"orange\": 1,  // Same value as \"apple\"\n    \"grape\":  3,\n}\nuniqueValues = it.UniqValues(m1, m2)\n// uniqueValues: sequence with 1, 2, 3 (no duplicates)\n\n// Maps with string values\nscores1 := map[int]string{\n    1: \"Alice\",\n    2: \"Bob\",\n    3: \"Charlie\",\n}\nscores2 := map[int]string{\n    4: \"Alice\",   // Same value\n    5: \"David\",\n    6: \"Bob\",     // Same value\n}\nuniqueValues = it.UniqValues(scores1, scores2)\n// uniqueValues: sequence with \"Alice\", \"Bob\", \"Charlie\", \"David\"\n\n// Maps with boolean values\nboolMaps := []map[string]bool{\n    {\"enabled\": true, \"debug\": false},\n    {\"test\": true, \"prod\": false},  // Same values\n    {\"dev\": true, \"staging\": false}, // Same values\n}\nuniqueValues = it.UniqValues(boolMaps...)\n// uniqueValues: sequence with true, false\n\n// Maps with float values\nprices1 := map[string]float64{\n    \"apple\":  1.99,\n    \"banana\": 2.99,\n}\nprices2 := map[string]float64{\n    \"orange\": 1.99,  // Same price as apple\n    \"grape\":  3.99,\n}\nuniqueValues = it.UniqValues(prices1, prices2)\n// uniqueValues: sequence with 1.99, 2.99, 3.99\n\n// Maps with struct values\ntype Product struct {\n    Name  string\n    Price float64\n}\nproducts1 := map[int]Product{\n    1: {Name: \"Book\", Price: 19.99},\n    2: {Name: \"Pen\", Price: 1.99},\n}\nproducts2 := map[int]Product{\n    3: {Name: \"Notebook\", Price: 19.99},  // Same price as book\n    4: {Name: \"Book\", Price: 19.99},      // Same struct as products1[1]\n}\nuniqueValues = it.UniqValues(products1, products2)\n// uniqueValues: sequence with {Book 19.99}, {Pen 1.99}, {Notebook 19.99}\n\n// Maps with pointer values\ntype Person struct {\n    Name string\n}\nalice := &Person{Name: \"Alice\"}\nbob := &Person{Name: \"Bob\"}\npeople1 := map[string]*Person{\n    \"user1\": alice,\n    \"user2\": bob,\n}\npeople2 := map[string]*Person{\n    \"user3\": alice,  // Same pointer\n    \"user4\": &Person{Name: \"Charlie\"},\n}\nuniqueValues = it.UniqValues(people1, people2)\n// uniqueValues: sequence with pointers to Alice, Bob, Charlie\n\n// Empty maps\nempty1 := map[string]int{}\nempty2 := map[string]int{}\nuniqueValues = it.UniqValues(empty1, empty2)\n// uniqueValues: empty sequence\n\n// Mix of empty and non-empty maps\nm1 := map[string]int{\"a\": 10}\nempty := map[string]int{}\nm2 := map[string]int{\"b\": 20, \"c\": 10}  // 10 is duplicate\nuniqueValues = it.UniqValues(m1, empty, m2)\n// uniqueValues: sequence with 10, 20\n\n// Maps with same values from different keys\nm1 := map[string]int{\n    \"key1\": 100,\n    \"key2\": 200,\n}\nm2 := map[string]int{\n    \"key3\": 100,  // Same value as key1\n    \"key4\": 200,  // Same value as key2\n    \"key5\": 300,\n}\nuniqueValues = it.UniqValues(m1, m2)\n// uniqueValues: sequence with 100, 200, 300\n\n// Large number of duplicate values\nmaps := make([]map[int]string, 10)\nfor i := range maps {\n    maps[i] = map[int]string{\n        i: \"common\",  // All maps have the same value\n        i + 100: fmt.Sprintf(\"unique_%d\", i),\n    }\n}\nuniqueValues = it.UniqValues(maps...)\n// uniqueValues: sequence with \"common\" and 10 unique values\n```"
  },
  {
    "path": "docs/data/it-values.md",
    "content": "---\nname: Values\nslug: values\nsourceRef: it/map.go#L44\ncategory: it\nsubCategory: map\nsignatures:\n  - \"func Values[K comparable, V any](in ...map[K]V) iter.Seq[V]\"\nplayUrl: https://go.dev/play/p/-WehUfGtC6C\nvariantHelpers:\n  - it#map#values\nsimilarHelpers:\n  - core#slice#values\n  - it#map#keys\n  - it#map#uniqvalues\nposition: 10\n---\n\nCreates a sequence of the map values. Accepts multiple maps and concatenates their values.\n\nExamples:\n\n```go\nm1 := map[string]int{\n    \"apple\":  1,\n    \"banana\": 2,\n}\nm2 := map[string]int{\n    \"cherry\": 3,\n    \"date\":   4,\n}\nvaluesSeq := it.Values(m1, m2)\nvar result []int\nfor v := range valuesSeq {\n    result = append(result, v)\n}\n// result contains values from both maps\n```"
  },
  {
    "path": "docs/data/it-window.md",
    "content": "---\nname: Window\nslug: window\nsourceRef: it/seq.go#L318\ncategory: it\nsubCategory: sequence\nsignatures:\n  - \"func Window[T any](collection iter.Seq[T], size int) iter.Seq[[]T]\"\nplayUrl: https://go.dev/play/p/_1BzQYtKBhi\nvariantHelpers:\n  - it#sequence#window\nsimilarHelpers:\n  - core#slice#window\nposition: 70\n---\n\nCreates a sequence of sliding windows of a given size. Each window overlaps with the previous one by size-1 elements.\n\n```go\nseq := func(yield func(int) bool) {\n    yield(1)\n    yield(2)\n    yield(3)\n    yield(4)\n    yield(5)\n}\nwindows := it.Window(seq, 3)\nvar result [][]int\nfor w := range windows {\n    result = append(result, w)\n}\n// result contains [1 2 3], [2 3 4], [3 4 5]\n```\n"
  },
  {
    "path": "docs/data/it-without.md",
    "content": "---\nname: Without\nslug: without\nsourceRef: it/intersect.go#L155\ncategory: it\nsubCategory: intersect\nsignatures:\n  - \"func Without[T comparable, I ~func(func(T) bool)](collection I, exclude ...T) I\"\nplayUrl: \"https://go.dev/play/p/LbN55AVBZ7h\"\nvariantHelpers:\n  - it#intersect#without\nsimilarHelpers:\n  - core#slice#without\n  - it#intersect#intersect\nposition: 50\n---\n\nReturns a sequence excluding all given values.\n\nExamples:\n\n```go\nseq := func(yield func(int) bool) {\n    _ = yield(1)\n    _ = yield(2)\n    _ = yield(3)\n    _ = yield(4)\n    _ = yield(5)\n}\nfiltered := it.Without(seq, 2, 4)\nvar result []int\nfor v := range filtered {\n    result = append(result, v)\n}\n// result contains 1, 3, 5\n```"
  },
  {
    "path": "docs/data/it-withoutby.md",
    "content": "---\nname: WithoutBy\nslug: withoutby\nsourceRef: it/intersect.go#L159\ncategory: it\nsubCategory: intersect\nsignatures:\n  - \"func WithoutBy[T any, K comparable, I ~func(func(T) bool)](collection I, transform func(item T) K, exclude ...K) I\"\nplayUrl: \"https://go.dev/play/p/Hm734hnLnLI\"\nvariantHelpers:\n  - it#intersect#withoutby\nsimilarHelpers:\n  - core#slice#withoutby\nposition: 700\n---\n\nFilters a sequence by excluding elements whose extracted keys match any in the exclude list.\n\nReturns a sequence containing only the elements whose keys are not in the exclude list.\nWill allocate a map large enough to hold all distinct excludes.\n\nExamples:\n\n```go\n// Exclude people by specific ages\ntype Person struct {\n    Name string\n    Age  int\n}\npeople := it.Slice([]Person{\n    {Name: \"Alice\", Age: 30},\n    {Name: \"Bob\", Age: 25},\n    {Name: \"Charlie\", Age: 35},\n    {Name: \"Diana\", Age: 30},  // Same age as Alice\n})\n\nfiltered := it.WithoutBy(people, func(p Person) int { return p.Age }, 30)\n// filtered: sequence with Bob (age 25) and Charlie (age 35)\n\n// Exclude strings by their length\nwords := it.Slice([]string{\"hello\", \"world\", \"hi\", \"go\", \"bye\"})\nfiltered := it.WithoutBy(words, func(s string) int { return len(s) }, 2)\n// filtered: sequence with \"hello\" (5), \"world\" (5), \"bye\" (3)\n// excludes \"hi\" and \"go\" (both length 2)\n\n// Exclude items by first letter\nitems := it.Slice([]string{\"apple\", \"apricot\", \"banana\", \"blueberry\", \"cherry\"})\nfiltered := it.WithoutBy(items, func(s string) byte { return s[0] }, 'b')\n// filtered: sequence with \"apple\", \"apricot\", \"cherry\"\n// excludes \"banana\" and \"blueberry\" (both start with 'b')\n\n// Exclude numbers by modulo\nnumbers := it.Slice([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10})\nfiltered := it.WithoutBy(numbers, func(n int) int { return n % 3 }, 1)\n// filtered: sequence with numbers where n % 3 != 1\n// excludes 1, 4, 7, 10 (all have remainder 1)\n\n// Exclude emails by domain\ntype Email struct {\n    Address string\n}\nemails := it.Slice([]Email{\n    {Address: \"user1@example.com\"},\n    {Address: \"user2@gmail.com\"},\n    {Address: \"user3@example.com\"},\n    {Address: \"user4@yahoo.com\"},\n})\nfiltered := it.WithoutBy(emails, func(e Email) string {\n    parts := strings.Split(e.Address, \"@\")\n    if len(parts) > 1 {\n        return parts[1]\n    }\n    return \"\"\n}, \"example.com\")\n// filtered: sequence with gmail.com and yahoo.com emails\n\n// Exclude orders by customer ID\ntype Order struct {\n    ID         string\n    CustomerID string\n    ProductID  string\n}\norders := it.Slice([]Order{\n    {ID: \"1\", CustomerID: \"A\", ProductID: \"X\"},\n    {ID: \"2\", CustomerID: \"B\", ProductID: \"Y\"},\n    {ID: \"3\", CustomerID: \"A\", ProductID: \"Z\"},\n    {ID: \"4\", CustomerID: \"C\", ProductID: \"W\"},\n})\nfiltered := it.WithoutBy(orders, func(o Order) string { return o.CustomerID }, \"A\")\n// filtered: sequence with orders from customers B and C\n\n// Exclude strings by case-insensitive value\nwords := it.Slice([]string{\"Hello\", \"hello\", \"WORLD\", \"world\", \"Go\"})\nfiltered := it.WithoutBy(words, func(s string) string { return strings.ToLower(s) }, \"hello\")\n// filtered: sequence with \"WORLD\", \"world\", \"Go\"\n// excludes both \"Hello\" and \"hello\" (both become \"hello\" when lowercased)\n\n// Exclude dates by month\nimport \"time\"\ndates := it.Slice([]time.Time{\n    time.Date(2023, 1, 15, 0, 0, 0, 0, time.UTC),\n    time.Date(2023, 2, 20, 0, 0, 0, 0, time.UTC),\n    time.Date(2023, 1, 25, 0, 0, 0, 0, time.UTC),\n    time.Date(2023, 3, 10, 0, 0, 0, 0, time.UTC),\n})\nfiltered := it.WithoutBy(dates, func(t time.Time) time.Month { return t.Month() }, time.January)\n// filtered: sequence with February and March dates\n\n// Exclude multiple values\nnumbers := it.Slice([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10})\nfiltered := it.WithoutBy(numbers, func(n int) int { return n % 2 }, 0, 1)\n// filtered: empty sequence (all numbers are either even (0) or odd (1))\n\n// Exclude by custom function result\ntype Product struct {\n    Name  string\n    Price float64\n}\nproducts := it.Slice([]Product{\n    {Name: \"Book\", Price: 19.99},\n    {Name: \"Pen\", Price: 1.99},\n    {Name: \"Laptop\", Price: 999.99},\n    {Name: \"Pencil\", Price: 0.99},\n})\n// Exclude products with price < $10\nfiltered := it.WithoutBy(products, func(p Product) string {\n    if p.Price < 10 {\n        return \"cheap\"\n    }\n    return \"expensive\"\n}, \"cheap\")\n// filtered: sequence with \"Book\" and \"Laptop\"\n```"
  },
  {
    "path": "docs/data/it-withoutnth.md",
    "content": "---\nname: WithoutNth\nslug: withoutnth\nsourceRef: it/intersect.go#L167\ncategory: it\nsubCategory: intersect\nsignatures:\n  - \"func WithoutNth[T comparable, I ~func(func(T) bool)](collection I, nths ...int) I\"\nplayUrl: \"https://go.dev/play/p/KGE7Lpsk18P\"\nvariantHelpers:\n  - it#intersect#withoutnth\nsimilarHelpers:\n  - core#slice#withoutnth\nposition: 710\n---\n\nReturns a sequence excluding the elements at the specified indices.\n\nWill allocate a map large enough to hold all distinct indices.\n\nExamples:\n\n```go\n// Exclude elements at specific indices\nnumbers := it.Slice([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10})\nfiltered := it.WithoutNth(numbers, 2, 5, 8)\n// filtered: sequence with 1, 2, 4, 5, 7, 8, 10\n// excludes elements at indices 2 (3), 5 (6), and 8 (9)\n\n// Exclude single element\nwords := it.Slice([]string{\"hello\", \"world\", \"go\", \"lang\", \"awesome\"})\nfiltered := it.WithoutNth(words, 1)\n// filtered: sequence with \"hello\", \"go\", \"lang\", \"awesome\"\n// excludes \"world\" at index 1\n\n// Exclude first element\nnumbers = it.Slice([]int{10, 20, 30, 40, 50})\nfiltered = it.WithoutNth(numbers, 0)\n// filtered: sequence with 20, 30, 40, 50\n// excludes 10 at index 0\n\n// Exclude last element\nnumbers = it.Slice([]int{10, 20, 30, 40, 50})\nfiltered = it.WithoutNth(numbers, 4)\n// filtered: sequence with 10, 20, 30, 40\n// excludes 50 at index 4\n\n// Exclude multiple elements including duplicates\nwords = it.Slice([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"})\nfiltered = it.WithoutNth(words, 1, 3, 1, 5)\n// filtered: sequence with \"a\", \"c\", \"e\", \"g\"\n// excludes elements at indices 1 (b), 3 (d), and 5 (f)\n// index 1 appears twice but element at index 1 is only excluded once\n\n// Exclude with negative indices (out of bounds, no effect)\nnumbers = it.Slice([]int{1, 2, 3, 4, 5})\nfiltered = it.WithoutNth(numbers, -1, 2)\n// filtered: sequence with 1, 2, 4, 5\n// excludes element at index 2 (3), ignores -1\n\n// Exclude with indices larger than collection (out of bounds, no effect)\nnumbers = it.Slice([]int{1, 2, 3, 4, 5})\nfiltered = it.WithoutNth(numbers, 10, 2)\n// filtered: sequence with 1, 2, 4, 5\n// excludes element at index 2 (3), ignores 10\n\n// Exclude all elements\nnumbers = it.Slice([]int{1, 2, 3, 4, 5})\nfiltered = it.WithoutNth(numbers, 0, 1, 2, 3, 4)\n// filtered: empty sequence\n\n// Exclude no indices (returns original)\nnumbers = it.Slice([]int{1, 2, 3, 4, 5})\nfiltered = it.WithoutNth(numbers)\n// filtered: sequence with 1, 2, 3, 4, 5 (unchanged)\n\n// With structs\ntype Person struct {\n    Name string\n    Age  int\n}\npeople := it.Slice([]Person{\n    {Name: \"Alice\", Age: 30},\n    {Name: \"Bob\", Age: 25},\n    {Name: \"Charlie\", Age: 35},\n    {Name: \"Diana\", Age: 28},\n    {Name: \"Eve\", Age: 32},\n})\nfiltered := it.WithoutNth(people, 1, 3)\n// filtered: sequence with Alice, Charlie, Eve\n// excludes Bob at index 1 and Diana at index 3\n\n// With mixed valid and invalid indices\nwords = it.Slice([]string{\"first\", \"second\", \"third\", \"fourth\"})\nfiltered = it.WithoutNth(words, -1, 1, 10, 2)\n// filtered: sequence with \"first\", \"fourth\"\n// excludes \"second\" at index 1 and \"third\" at index 2\n// ignores -1 and 10 as they are out of bounds\n\n// Exclude from empty collection\nempty := it.Slice([]int{})\nfiltered := it.WithoutNth(empty, 0, 1, 2)\n// filtered: empty sequence\n```"
  },
  {
    "path": "docs/data/it-zipbyx.md",
    "content": "---\nname: ZipByX\nslug: zipbyx\nsourceRef: it/tuples.go#L295\ncategory: it\nsubCategory: tuple\nsignatures:\n  - \"func ZipBy2[T1, T2, R any](seq1 iter.Seq[T1], seq2 iter.Seq[T2], transform func(T1, T2) R) iter.Seq[R]\"\n  - \"func ZipBy3[T1, T2, T3, R any](seq1 iter.Seq[T1], seq2 iter.Seq[T2], seq3 iter.Seq[T3], transform func(T1, T2, T3) R) iter.Seq[R]\"\n  - \"func ZipBy4[T1, T2, T3, T4, R any](seq1 iter.Seq[T1], seq2 iter.Seq[T2], seq3 iter.Seq[T3], seq4 iter.Seq[T4], transform func(T1, T2, T3, T4) R) iter.Seq[R]\"\n  - \"func ZipBy5[T1, T2, T3, T4, T5, R any](seq1 iter.Seq[T1], seq2 iter.Seq[T2], seq3 iter.Seq[T3], seq4 iter.Seq[T4], seq5 iter.Seq[T5], transform func(T1, T2, T3, T4, T5) R) iter.Seq[R]\"\n  - \"func ZipBy6[T1, T2, T3, T4, T5, T6, R any](seq1 iter.Seq[T1], seq2 iter.Seq[T2], seq3 iter.Seq[T3], seq4 iter.Seq[T4], seq5 iter.Seq[T5], seq6 iter.Seq[T6], transform func(T1, T2, T3, T4, T5, T6) R) iter.Seq[R]\"\n  - \"func ZipBy7[T1, T2, T3, T4, T5, T6, T7, R any](seq1 iter.Seq[T1], seq2 iter.Seq[T2], seq3 iter.Seq[T3], seq4 iter.Seq[T4], seq5 iter.Seq[T5], seq6 iter.Seq[T6], seq7 iter.Seq[T7], transform func(T1, T2, T3, T4, T5, T6, T7) R) iter.Seq[R]\"\n  - \"func ZipBy8[T1, T2, T3, T4, T5, T6, T7, T8, R any](seq1 iter.Seq[T1], seq2 iter.Seq[T2], seq3 iter.Seq[T3], seq4 iter.Seq[T4], seq5 iter.Seq[T5], seq6 iter.Seq[T6], seq7 iter.Seq[T7], seq8 iter.Seq[T8], transform func(T1, T2, T3, T4, T5, T6, T7, T8) R) iter.Seq[R]\"\n  - \"func ZipBy9[T1, T2, T3, T4, T5, T6, T7, T8, T9, R any](seq1 iter.Seq[T1], seq2 iter.Seq[T2], seq3 iter.Seq[T3], seq4 iter.Seq[T4], seq5 iter.Seq[T5], seq6 iter.Seq[T6], seq7 iter.Seq[T7], seq8 iter.Seq[T8], seq9 iter.Seq[T9], transform func(T1, T2, T3, T4, T5, T6, T7, T8, T9) R) iter.Seq[R]\"\nplayUrl: https://go.dev/play/p/y03uqMEAi1E\nvariantHelpers:\n  - it#tuple#zipbyx\nsimilarHelpers:\n  - core#tuple#zipbyx\n  - it#tuple#zipx\n  - core#slice#map\nposition: 10\n---\n\nCreates a sequence of transformed elements from multiple sequences using a transform function. When sequences are different lengths, shorter sequences are padded with zero values before transformation.\n\nVariants: `ZipBy2..ZipBy9`\n\n```go\nseq1 := func(yield func(int) bool) {\n    _ = yield(1)\n    _ = yield(2)\n    _ = yield(3)\n}\nseq2 := func(yield func(string) bool) {\n    _ = yield(\"a\")\n    _ = yield(\"b\")\n}\nzipped := it.ZipBy2(seq1, seq2, func(i int, s string) string {\n    return fmt.Sprintf(\"%d-%s\", i, s)\n})\nvar result []string\nfor item := range zipped {\n    result = append(result, item)\n}\n// result contains [\"1-a\", \"2-b\", \"3-\"]\n```"
  },
  {
    "path": "docs/data/it-zipx.md",
    "content": "---\nname: ZipX\nslug: zipx\nsourceRef: it/tuples.go#L14\ncategory: it\nsubCategory: tuple\nsignatures:\n  - \"func Zip2[T1, T2 any](list1 iter.Seq[T1], list2 iter.Seq[T2]) iter.Seq[lo.Tuple2[T1, T2]]\"\n  - \"func Zip3[T1, T2, T3 any](list1 iter.Seq[T1], list2 iter.Seq[T2], list3 iter.Seq[T3]) iter.Seq[lo.Tuple3[T1, T2, T3]]\"\n  - \"func Zip4[T1, T2, T3, T4 any](list1 iter.Seq[T1], list2 iter.Seq[T2], list3 iter.Seq[T3], list4 iter.Seq[T4]) iter.Seq[lo.Tuple4[T1, T2, T3, T4]]\"\n  - \"func Zip5[T1, T2, T3, T4, T5 any](list1 iter.Seq[T1], list2 iter.Seq[T2], list3 iter.Seq[T3], list4 iter.Seq[T4], list5 iter.Seq[T5]) iter.Seq[lo.Tuple5[T1, T2, T3, T4, T5]]\"\n  - \"func Zip6[T1, T2, T3, T4, T5, T6 any](list1 iter.Seq[T1], list2 iter.Seq[T2], list3 iter.Seq[T3], list4 iter.Seq[T4], list5 iter.Seq[T5], list6 iter.Seq[T6]) iter.Seq[lo.Tuple6[T1, T2, T3, T4, T5, T6]]\"\n  - \"func Zip7[T1, T2, T3, T4, T5, T6, T7 any](list1 iter.Seq[T1], list2 iter.Seq[T2], list3 iter.Seq[T3], list4 iter.Seq[T4], list5 iter.Seq[T5], list6 iter.Seq[T6], list7 iter.Seq[T7]) iter.Seq[lo.Tuple7[T1, T2, T3, T4, T5, T6, T7]]\"\n  - \"func Zip8[T1, T2, T3, T4, T5, T6, T7, T8 any](list1 iter.Seq[T1], list2 iter.Seq[T2], list3 iter.Seq[T3], list4 iter.Seq[T4], list5 iter.Seq[T5], list6 iter.Seq[T6], list7 iter.Seq[T7], list8 iter.Seq[T8]) iter.Seq[lo.Tuple8[T1, T2, T3, T4, T5, T6, T7, T8]]\"\n  - \"func Zip9[T1, T2, T3, T4, T5, T6, T7, T8, T9 any](list1 iter.Seq[T1], list2 iter.Seq[T2], list3 iter.Seq[T3], list4 iter.Seq[T4], list5 iter.Seq[T5], list6 iter.Seq[T6], list7 iter.Seq[T7], list8 iter.Seq[T8], list9 iter.Seq[T9]) iter.Seq[lo.Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9]]\"\nplayUrl: \"https://go.dev/play/p/U5nBWvR8eUZ\"\nvariantHelpers:\n  - it#tuple#zipx\nsimilarHelpers:\n  - core#tuple#zipx\n  - it#tuple#crossjoinx\n  - it#tuple#zipbyx\nposition: 0\n---\n\nCreates a sequence of grouped elements from multiple sequences. The resulting sequence has length equal to the shortest input sequence.\n\nVariants: `Zip2..Zip9`\n\n```go\nseq1 := func(yield func(int) bool) {\n    _ = yield(1)\n    _ = yield(2)\n    _ = yield(3)\n}\nseq2 := func(yield func(string) bool) {\n    _ = yield(\"a\")\n    _ = yield(\"b\")\n    _ = yield(\"c\")\n}\nzipped := it.Zip2(seq1, seq2)\nvar result []string\nfor tuple := range zipped {\n    result = append(result, fmt.Sprintf(\"%d%s\", tuple.A, tuple.B))\n}\n// result contains \"1a\", \"2b\", \"3c\"\n```"
  },
  {
    "path": "docs/data/mutable-fill.md",
    "content": "---\nname: Fill\nslug: fill\nsourceRef: mutable/slice_example_test.go#L72\ncategory: mutable\nsubCategory: slice\nsignatures:\n  - \"func Fill[T any, Slice ~[]T](collection Slice, initial T)\"\nplayUrl: https://go.dev/play/p/VwR34GzqEub\nvariantHelpers:\n  - mutable#slice#fill\nsimilarHelpers:\n  - core#slice#fill\n  - core#slice#repeat\n  - core#slice#times\nposition: 60\n---\n\nFills all elements of a slice with the specified initial value. The operation modifies the slice in place.\n\n```go\nslice := make([]int, 5)\nlo.Fill(slice, 42)\n// []int{42, 42, 42, 42, 42}\n\nslice = make([]string, 3)\nlo.Fill(slice, \"default\")\n// []string{\"default\", \"default\", \"default\"}\n\nslice = make([]bool, 4)\nlo.Fill(slice, true)\n// []bool{true, true, true, true}\n\nslice = []int{1, 2, 3, 4, 5}\nlo.Fill(slice, 0)\n// []int{0, 0, 0, 0, 0}\n```"
  },
  {
    "path": "docs/data/mutable-filter.md",
    "content": "---\nname: Filter\nslug: filter\nsourceRef: mutable/slice.go#L11\ncategory: mutable\nsubCategory: slice\nplayUrl: https://go.dev/play/p/0jY3Z0B7O_5\nsimilarHelpers:\n  - core#slice#filter\n  - core#slice#filterreject\n  - core#slice#filtermap\n  - parallel#slice#filter\n  - it#chunkstring\nvariantHelpers:\n  - \"mutable#slice#filter\"\n  - \"mutable#slice#filteri\"\nposition: 0\nsignatures:\n  - \"func Filter[T any, Slice ~[]T](collection Slice, predicate func(item T) bool) Slice\"\n  - \"func FilterI[T any, Slice ~[]T](collection Slice, predicate func(item T, index int) bool) Slice\"\n---\n\nModifies the input slice in place, keeping only the elements for which the predicate returns true. Order is preserved. Returns the shortened slice view backed by the original array.\n\nVariants: `FilterI` accepts an index-aware predicate `(item T, index int) bool`.\n\n```go\nimport lom \"github.com/samber/lo/mutable\"\n\nlist := []int{1, 2, 3, 4}\nkept := lom.Filter(list, func(x int) bool {\n    return x%2 == 0\n})\n\n// kept -> []int{2, 4}\n// list is modified in place (backed by same array)\n```\n\nAnother example with a struct type:\n\n```go\ntype User struct { Name string; Active bool }\n\nusers := []User{{\"Alex\", true}, {\"Bob\", false}, {\"Carol\", true}}\nactive := lom.Filter(users, func(u User) bool {\n    return u.Active\n})\n\n// active -> []User{{\"Alex\", true}, {\"Carol\", true}}\n// users underlying storage is reused\n```\n\nIndex-aware variant (FilterI):\n\n```go\n// keep even-indexed items whose length >= 2\nlist2 := []string{\"a\", \"bb\", \"ccc\", \"dddd\"}\nkept2 := lom.FilterI(list2, func(s string, i int) bool {\n    return i%2 == 0 && len(s) >= 2\n})\n// kept2 -> []string{\"ccc\"}\n\nnums := []int{10, 11, 12, 13, 14}\nevenPos := lom.FilterI(nums, func(_ int, i int) bool {\n    return i%2 == 0\n})\n// evenPos -> []int{10, 12, 14}\n```\n\n"
  },
  {
    "path": "docs/data/mutable-map.md",
    "content": "---\nname: Map\nslug: map\nsourceRef: mutable/slice.go#L41\ncategory: mutable\nsubCategory: slice\nplayUrl: https://go.dev/play/p/0jY3Z0B7O_5\nvariantHelpers:\n  - \"mutable#slice#map\"\n  - \"mutable#slice#mapi\"\nsimilarHelpers:\n  - core#slice#map\n  - core#slice#mapkeys\n  - core#slice#mapvalues\n  - parallel#slice#map\nposition: 10\nsignatures:\n  - \"func Map[T any, Slice ~[]T](collection Slice, transform func(item T) T)\"\n  - \"func MapI[T any, Slice ~[]T](collection Slice, transform func(item T, index int) T)\"\n---\n\nTransforms each element in the slice by applying the transform function in place. The length remains unchanged; values are overwritten in the same backing array.\n\nVariants: `MapI` accepts an index-aware mapper `(item T, index int) T`.\n\n```go\nimport lom \"github.com/samber/lo/mutable\"\n\nlist := []int{1, 2, 3, 4}\nlom.Map(list, func(x int) int {\n    return x * 2\n})\n// list -> []int{2, 4, 6, 8}\n```\n\nMapping strings:\n\n```go\nwords := []string{\"go\", \"LoDash\", \"lo\"}\nlom.Map(words, func(s string) string {\n    return strings.ToUpper(s)\n})\n// words -> []string{\"GO\", \"LODASH\", \"LO\"}\n```\n\nIndex-aware variant (MapI):\n\n```go\nnums := []int{10, 11, 12}\n// add index to each number\nlom.MapI(nums, func(x int, i int) int {\n    return x + i\n})\n// nums -> []int{10, 12, 14}\n\nvals := []string{\"a\", \"b\", \"c\", \"d\"}\nlom.MapI(vals, func(s string, i int) string {\n    if i%2 == 0 { return s + \"!\" }\n    return s\n})\n// vals -> []string{\"a!\", \"b\", \"c!\", \"d\"}\n```\n"
  },
  {
    "path": "docs/data/mutable-reverse.md",
    "content": "---\nname: Reverse\nslug: reverse\nsourceRef: mutable/slice.go#L65\ncategory: mutable\nsubCategory: slice\nplayUrl: https://go.dev/play/p/O-M5pmCRgzV\nvariantHelpers:\n  - mutable#slice#reverse\nsimilarHelpers:\n  - core#slice#reverse\nposition: 30\nsignatures:\n  - \"func Reverse[T any, Slice ~[]T](collection Slice)\"\n---\n\nReverses the slice in place so the first element becomes the last, the second becomes the second-to-last, and so on.\n\n```go\nimport lom \"github.com/samber/lo/mutable\"\n\nlist := []int{0, 1, 2, 3, 4, 5}\nlom.Reverse(list)\n// list -> []int{5, 4, 3, 2, 1, 0}\n```\n\nWith custom types:\n\n```go\ntype Point struct{ X, Y int }\npts := []Point{{0,0}, {1,1}, {2,2}}\nlom.Reverse(pts)\n// pts -> []Point{{2,2}, {1,1}, {0,0}}\n```\n\n"
  },
  {
    "path": "docs/data/mutable-shuffle.md",
    "content": "---\nname: Shuffle\nslug: shuffle\nsourceRef: mutable/slice.go#L57\ncategory: mutable\nsubCategory: slice\nplayUrl: https://go.dev/play/p/2xb3WdLjeSJ\nvariantHelpers:\n  - \"mutable#slice#shuffle\"\nsimilarHelpers:\n  - core#slice#shuffle\n  - core#slice#sample\n  - core#slice#samples\nposition: 20\nsignatures:\n  - \"func Shuffle[T any, Slice ~[]T](collection Slice)\"\n---\n\nShuffles the slice in place using the Fisher–Yates algorithm. The operation mutates the original slice order.\n\n```go\nimport lom \"github.com/samber/lo/mutable\"\n\nlist := []int{0, 1, 2, 3, 4, 5}\nlom.Shuffle(list)\n// list order is randomized, e.g., []int{1, 4, 0, 3, 5, 2}\n```\n\nWith strings:\n\n```go\nnames := []string{\"alice\", \"bob\", \"carol\"}\nlom.Shuffle(names)\n// names order is randomized\n```\n\n"
  },
  {
    "path": "docs/data/parallel-foreach.md",
    "content": "---\nname: ForEach\nslug: foreach\nsourceRef: parallel/slice.go#L32\ncategory: parallel\nsubCategory: slice\nplayUrl: https://go.dev/play/p/sCJaB3quRMC\nsimilarHelpers:\n  - core#slice#foreach\n  - parallel#slice#map\nposition: 10\nsignatures:\n  - \"func ForEach[T any](collection []T, callback func(item T, index int))\"\nvariantHelpers:\n  - parallel#slice#foreach\n---\n\nIterates over elements of a collection and invokes the callback for each element in parallel.\n\n```go\nimport (\n    \"fmt\"\n    lop \"github.com/samber/lo/parallel\"\n)\n\nlop.ForEach([]string{\"hello\", \"world\"}, func(x string, _ int) {\n    fmt.Println(x)\n})\n// prints lines in any order depending on scheduling\n```\n\nUseful for fire-and-forget work like publishing events or independent side effects:\n\n```go\ntype Job struct{ ID int }\n\njobs := []Job{{1}, {2}, {3}}\nlop.ForEach(jobs, func(j Job, _ int) {\n    // process each job concurrently\n    // send(j)\n})\n```\n\n\n"
  },
  {
    "path": "docs/data/parallel-groupby.md",
    "content": "---\nname: GroupBy\nslug: groupby\nsourceRef: parallel/slice.go#L73\ncategory: parallel\nsubCategory: slice\nplayUrl: \"https://go.dev/play/p/EkyvA0gw4dj\"\nsimilarHelpers:\n  - core#slice#groupby\n  - core#slice#groupbymap\n  - parallel#slice#partitionby\nposition: 30\nsignatures:\n  - \"func GroupBy[T any, U comparable, Slice ~[]T](collection Slice, iteratee func(item T) U) map[U]Slice\"\nvariantHelpers:\n  - parallel#slice#groupby\n---\n\nReturns a map composed of keys generated from the results of running each element of the collection through the predicate. The predicate is called in parallel. Values keep the input order within each group.\n\n```go\nimport (\n    lop \"github.com/samber/lo/parallel\"\n)\n\ngroups := lop.GroupBy([]int{0, 1, 2, 3, 4, 5}, func(i int) int {\n    return i % 3\n})\n// map[int][]int{0: {0, 3}, 1: {1, 4}, 2: {2, 5}}\n```\n\nCustom key types work as long as they are comparable:\n\n```go\ntype Kind string\ngroups2 := lop.GroupBy([]string{\"go\", \"rust\", \"java\"}, func(s string) Kind {\n    if len(s) <= 2 { return \"short\" }\n    return \"long\"\n})\n// map[Kind][]string{\"short\": {\"go\"}, \"long\": {\"rust\", \"java\"}}\n```\n\n\n"
  },
  {
    "path": "docs/data/parallel-map.md",
    "content": "---\nname: Map\nslug: map\nsourceRef: parallel/slice.go#L8\ncategory: parallel\nsubCategory: slice\nplayUrl: https://go.dev/play/p/sCJaB3quRMC\nsimilarHelpers:\n  - core#slice#map\n  - mutable#slice#map\n  - parallel#slice#foreach\nposition: 0\nsignatures:\n  - \"func Map[T any, R any](collection []T, transform func(item T, index int) R) []R\"\nvariantHelpers:\n  - parallel#slice#map\n---\n\nManipulates a slice and transforms it into a slice of another type. The transform is called in parallel and results are written back in the original order.\n\n```go\nimport (\n    \"strconv\"\n    lop \"github.com/samber/lo/parallel\"\n)\n\nout := lop.Map([]int64{1, 2, 3, 4}, func(x int64, i int) string {\n    return strconv.FormatInt(x, 10)\n})\n// []string{\"1\", \"2\", \"3\", \"4\"}\n```\n\nParallel execution is useful when the predicate is slow or I/O-bound:\n\n```go\nimport (\n    \"net/http\"\n    \"io\"\n    lop \"github.com/samber/lo/parallel\"\n)\n\nurls := []string{\"https://example.com/a\", \"https://example.com/b\"}\npages := lop.Map(urls, func(u string, _ int) string {\n    resp, _ := http.Get(u)\n    defer resp.Body.Close()\n    b, _ := io.ReadAll(resp.Body)\n    return string(b)\n})\n// pages keeps the same order as urls\n```\n\n\n"
  },
  {
    "path": "docs/data/parallel-partitionby.md",
    "content": "---\nname: PartitionBy\nslug: partitionby\nsourceRef: parallel/slice.go#L92\ncategory: parallel\nsubCategory: slice\nplayUrl: \"https://go.dev/play/p/GwBQdMgx2nC\"\nsimilarHelpers:\n  - core#slice#partitionby\n  - parallel#slice#groupby\nposition: 40\nsignatures:\n  - \"func PartitionBy[T any, K comparable, Slice ~[]T](collection Slice, iteratee func(item T) K) []Slice\"\nvariantHelpers:\n  - parallel#slice#partitionby\n---\n\nReturns a slice of groups where contiguous elements sharing the same key are batched together. Groups are created from the results of running each element of the collection through the predicate. The predicate is called in parallel and the order of groups follows their first appearance in the collection.\n\n```go\nimport (\n    lop \"github.com/samber/lo/parallel\"\n)\n\ngroups := lop.PartitionBy([]int{-2, -1, 0, 1, 2, 3, 4, 5}, func(x int) string {\n    if x < 0 { return \"negative\" }\n    if x%2 == 0 { return \"even\" }\n    return \"odd\"\n})\n// [][]int{{-2, -1}, {0, 2, 4}, {1, 3, 5}}\n```\n\nWorks with any comparable key type:\n\n```go\ntype Bucket int\nparts := lop.PartitionBy([]int{1,2,2,3,3,3}, func(x int) Bucket {\n    return Bucket(x)\n})\n// [][]int{{1}, {2,2}, {3,3,3}}\n```\n\n\n"
  },
  {
    "path": "docs/data/parallel-times.md",
    "content": "---\nname: Times\nslug: times\nsourceRef: parallel/slice.go#L49\ncategory: parallel\nsubCategory: slice\nplayUrl: https://go.dev/play/p/ZNnWNcJ4Au-\nsimilarHelpers:\n  - core#slice#times\nposition: 20\nsignatures:\n  - \"func Times[T any](count int, iteratee func(index int) T) []T\"\nvariantHelpers:\n  - parallel#slice#times\n---\n\nInvokes the predicate count times, returning a slice of the results of each invocation. The predicate is called in parallel with the index as argument.\n\n```go\nimport (\n    \"strconv\"\n    lop \"github.com/samber/lo/parallel\"\n)\n\nnums := lop.Times(5, func(i int) string {\n    return strconv.Itoa(i)\n})\n// []string{\"0\", \"1\", \"2\", \"3\", \"4\"}\n```\n\nGreat for generating data concurrently:\n\n```go\nids := lop.Times(10, func(i int) string {\n    return fmt.Sprintf(\"item-%d\", i)\n})\n```\n\n\n"
  },
  {
    "path": "docs/data/simd-clamp.md",
    "content": "---\nname: Clamp\nslug: clamp\nsourceRef: exp/simd/math_avx.go#L453\ncategory: exp\nsubCategory: simd\nsimilarHelpers:\n  - exp#simd#clamp\nposition: 40\nsignatures:\n  - \"func ClampInt8x16[T ~int8, Slice ~[]T](collection Slice, min, max T) Slice\"\n  - \"func ClampInt8x32[T ~int8, Slice ~[]T](collection Slice, min, max T) Slice\"\n  - \"func ClampInt8x64[T ~int8, Slice ~[]T](collection Slice, min, max T) Slice\"\n  - \"func ClampInt16x8[T ~int16, Slice ~[]T](collection Slice, min, max T) Slice\"\n  - \"func ClampInt16x16[T ~int16, Slice ~[]T](collection Slice, min, max T) Slice\"\n  - \"func ClampInt16x32[T ~int16, Slice ~[]T](collection Slice, min, max T) Slice\"\n  - \"func ClampInt32x4[T ~int32, Slice ~[]T](collection Slice, min, max T) Slice\"\n  - \"func ClampInt32x8[T ~int32, Slice ~[]T](collection Slice, min, max T) Slice\"\n  - \"func ClampInt32x16[T ~int32, Slice ~[]T](collection Slice, min, max T) Slice\"\n  - \"func ClampInt64x2[T ~int64, Slice ~[]T](collection Slice, min, max T) Slice\"\n  - \"func ClampInt64x4[T ~int64, Slice ~[]T](collection Slice, min, max T) Slice\"\n  - \"func ClampInt64x8[T ~int64, Slice ~[]T](collection Slice, min, max T) Slice\"\n  - \"func ClampUint8x16[T ~uint8, Slice ~[]T](collection Slice, min, max T) Slice\"\n  - \"func ClampUint8x32[T ~uint8, Slice ~[]T](collection Slice, min, max T) Slice\"\n  - \"func ClampUint8x64[T ~uint8, Slice ~[]T](collection Slice, min, max T) Slice\"\n  - \"func ClampUint16x8[T ~uint16, Slice ~[]T](collection Slice, min, max T) Slice\"\n  - \"func ClampUint16x16[T ~uint16, Slice ~[]T](collection Slice, min, max T) Slice\"\n  - \"func ClampUint16x32[T ~uint16, Slice ~[]T](collection Slice, min, max T) Slice\"\n  - \"func ClampUint32x4[T ~uint32, Slice ~[]T](collection Slice, min, max T) Slice\"\n  - \"func ClampUint32x8[T ~uint32, Slice ~[]T](collection Slice, min, max T) Slice\"\n  - \"func ClampUint32x16[T ~uint32, Slice ~[]T](collection Slice, min, max T) Slice\"\n  - \"func ClampUint64x2[T ~uint64, Slice ~[]T](collection Slice, min, max T) Slice\"\n  - \"func ClampUint64x4[T ~uint64, Slice ~[]T](collection Slice, min, max T) Slice\"\n  - \"func ClampUint64x8[T ~uint64, Slice ~[]T](collection Slice, min, max T) Slice\"\n  - \"func ClampFloat32x4[T ~float32, Slice ~[]T](collection Slice, min, max T) Slice\"\n  - \"func ClampFloat32x8[T ~float32, Slice ~[]T](collection Slice, min, max T) Slice\"\n  - \"func ClampFloat32x16[T ~float32, Slice ~[]T](collection Slice, min, max T) Slice\"\n  - \"func ClampFloat64x2[T ~float64, Slice ~[]T](collection Slice, min, max T) Slice\"\n  - \"func ClampFloat64x4[T ~float64, Slice ~[]T](collection Slice, min, max T) Slice\"\n  - \"func ClampFloat64x8[T ~float64, Slice ~[]T](collection Slice, min, max T) Slice\"\n---\n\nClamps each element in a collection between min and max values using SIMD instructions. The suffix (x2, x4, x8, x16, x32, x64) indicates the number of lanes processed simultaneously.\n\n> **Note**: Choose the variant matching your CPU's capabilities. Higher lane counts provide better performance but require newer CPU support.\n\n```go\n// Using AVX2 variant (32 lanes at once) - Intel Haswell+ / AMD Excavator+\nresult := simd.ClampInt8x32([]int8{1, 5, 10, 15, 20}, 5, 15)\n// []int8{5, 5, 10, 15, 15}\n```\n\n```go\n// Using AVX-512 variant (16 lanes at once) - Intel Skylake-X+\nresult := simd.ClampFloat32x16([]float32{0.5, 1.5, 2.5, 3.5}, 1.0, 3.0)\n// []float32{1.0, 1.5, 2.5, 3.0}\n```\n\n```go\n// Using AVX variant (8 lanes at once) - works on all amd64\nresult := simd.ClampInt16x8([]int16{100, 150, 200, 250}, 120, 220)\n// []int16{120, 150, 200, 220}\n```\n\n```go\n// Empty collection returns empty collection\nresult := simd.ClampUint32x4([]uint32{}, 10, 100)\n// []uint32{}\n```\n"
  },
  {
    "path": "docs/data/simd-contains.md",
    "content": "---\nname: Contains\nslug: contains\nsourceRef: exp/simd/intersect_avx512.go#L9\ncategory: exp\nsubCategory: simd\nsimilarHelpers:\n  - exp#simd#contains\nposition: 0\nsignatures:\n  - \"func ContainsInt8x16[T ~int8](collection []T, target T) bool\"\n  - \"func ContainsInt8x32[T ~int8](collection []T, target T) bool\"\n  - \"func ContainsInt8x64[T ~int8](collection []T, target T) bool\"\n  - \"func ContainsInt16x8[T ~int16](collection []T, target T) bool\"\n  - \"func ContainsInt16x16[T ~int16](collection []T, target T) bool\"\n  - \"func ContainsInt16x32[T ~int16](collection []T, target T) bool\"\n  - \"func ContainsInt32x4[T ~int32](collection []T, target T) bool\"\n  - \"func ContainsInt32x8[T ~int32](collection []T, target T) bool\"\n  - \"func ContainsInt32x16[T ~int32](collection []T, target T) bool\"\n  - \"func ContainsInt64x2[T ~int64](collection []T, target T) bool\"\n  - \"func ContainsInt64x4[T ~int64](collection []T, target T) bool\"\n  - \"func ContainsInt64x8[T ~int64](collection []T, target T) bool\"\n  - \"func ContainsUint8x16[T ~uint8](collection []T, target T) bool\"\n  - \"func ContainsUint8x32[T ~uint8](collection []T, target T) bool\"\n  - \"func ContainsUint8x64[T ~uint8](collection []T, target T) bool\"\n  - \"func ContainsUint16x8[T ~uint16](collection []T, target T) bool\"\n  - \"func ContainsUint16x16[T ~uint16](collection []T, target T) bool\"\n  - \"func ContainsUint16x32[T ~uint16](collection []T, target T) bool\"\n  - \"func ContainsUint32x4[T ~uint32](collection []T, target T) bool\"\n  - \"func ContainsUint32x8[T ~uint32](collection []T, target T) bool\"\n  - \"func ContainsUint32x16[T ~uint32](collection []T, target T) bool\"\n  - \"func ContainsUint64x2[T ~uint64](collection []T, target T) bool\"\n  - \"func ContainsUint64x4[T ~uint64](collection []T, target T) bool\"\n  - \"func ContainsUint64x8[T ~uint64](collection []T, target T) bool\"\n  - \"func ContainsFloat32x4[T ~float32](collection []T, target T) bool\"\n  - \"func ContainsFloat32x8[T ~float32](collection []T, target T) bool\"\n  - \"func ContainsFloat32x16[T ~float32](collection []T, target T) bool\"\n  - \"func ContainsFloat64x2[T ~float64](collection []T, target T) bool\"\n  - \"func ContainsFloat64x4[T ~float64](collection []T, target T) bool\"\n  - \"func ContainsFloat64x8[T ~float64](collection []T, target T) bool\"\n---\n\nChecks if a target value is present in a collection using SIMD instructions. The suffix (x4, x8, x16, x32, x64) indicates the number of lanes processed simultaneously.\n\n> **Note**: Choose the variant matching your CPU's capabilities. Higher lane counts provide better performance but require newer CPU support.\n\n```go\n// Using AVX2 variant (32 lanes at once) - Intel Haswell+ / AMD Excavator+\nfound := simd.ContainsInt8x32([]int8{1, 2, 3, 4, 5}, 3)\n// true\n```\n\n```go\n// Using AVX variant (16 lanes at once) - works on all amd64\nfound := simd.ContainsInt64x2([]int64{1000000, 2000000, 3000000}, 2000000)\n// true\n```\n\n```go\n// Using AVX-512 variant (64 lanes at once) - Intel Skylake-X+\nfound := simd.ContainsUint8x64([]uint8{10, 20, 30, 40, 50}, 30)\n// true\n```\n\n```go\n// Float32 with AVX2 (8 lanes at once)\nfound := simd.ContainsFloat32x8([]float32{1.1, 2.2, 3.3, 4.4}, 3.3)\n// true\n```\n\n```go\n// Empty collection returns false\nfound := simd.ContainsInt16x16([]int16{}, 5)\n// false\n```\n"
  },
  {
    "path": "docs/data/simd-max.md",
    "content": "---\nname: Max\nslug: max\nsourceRef: exp/simd/math_avx.go#L1279\ncategory: exp\nsubCategory: simd\nsimilarHelpers:\n  - exp#simd#max\nposition: 30\nsignatures:\n  - \"func MaxInt8x16[T ~int8](collection []T) T\"\n  - \"func MaxInt8x32[T ~int8](collection []T) T\"\n  - \"func MaxInt8x64[T ~int8](collection []T) T\"\n  - \"func MaxInt16x8[T ~int16](collection []T) T\"\n  - \"func MaxInt16x16[T ~int16](collection []T) T\"\n  - \"func MaxInt16x32[T ~int16](collection []T) T\"\n  - \"func MaxInt32x4[T ~int32](collection []T) T\"\n  - \"func MaxInt32x8[T ~int32](collection []T) T\"\n  - \"func MaxInt32x16[T ~int32](collection []T) T\"\n  - \"func MaxInt64x2[T ~int64](collection []T) T\"\n  - \"func MaxInt64x4[T ~int64](collection []T) T\"\n  - \"func MaxInt64x8[T ~int64](collection []T) T\"\n  - \"func MaxUint8x16[T ~uint8](collection []T) T\"\n  - \"func MaxUint8x32[T ~uint8](collection []T) T\"\n  - \"func MaxUint8x64[T ~uint8](collection []T) T\"\n  - \"func MaxUint16x8[T ~uint16](collection []T) T\"\n  - \"func MaxUint16x16[T ~uint16](collection []T) T\"\n  - \"func MaxUint16x32[T ~uint16](collection []T) T\"\n  - \"func MaxUint32x4[T ~uint32](collection []T) T\"\n  - \"func MaxUint32x8[T ~uint32](collection []T) T\"\n  - \"func MaxUint32x16[T ~uint32](collection []T) T\"\n  - \"func MaxUint64x2[T ~uint64](collection []T) T\"\n  - \"func MaxUint64x4[T ~uint64](collection []T) T\"\n  - \"func MaxUint64x8[T ~uint64](collection []T) T\"\n  - \"func MaxFloat32x4[T ~float32](collection []T) T\"\n  - \"func MaxFloat32x8[T ~float32](collection []T) T\"\n  - \"func MaxFloat32x16[T ~float32](collection []T) T\"\n  - \"func MaxFloat64x2[T ~float64](collection []T) T\"\n  - \"func MaxFloat64x4[T ~float64](collection []T) T\"\n  - \"func MaxFloat64x8[T ~float64](collection []T) T\"\n---\n\nFinds the maximum value in a collection using SIMD instructions. The suffix (x2, x4, x8, x16, x32, x64) indicates the number of lanes processed simultaneously.\n\n> **Note**: Choose the variant matching your CPU's capabilities. Higher lane counts provide better performance but require newer CPU support.\n\n```go\n// Using AVX2 variant (32 lanes at once) - Intel Haswell+ / AMD Excavator+\nmax := simd.MaxInt8x32([]int8{5, 2, 8, 1, 9})\n// 9\n```\n\n```go\n// Using AVX-512 variant (16 lanes at once) - Intel Skylake-X+\nmax := simd.MaxFloat32x16([]float32{3.5, 1.2, 4.8, 2.1})\n// 4.8\n```\n\n```go\n// Using AVX variant (4 lanes at once) - works on all amd64\nmax := simd.MaxInt32x4([]int32{100, 50, 200, 75})\n// 200\n```\n\n```go\n// Empty collection returns 0\nmax := simd.MaxUint16x8([]uint16{})\n// 0\n```\n"
  },
  {
    "path": "docs/data/simd-mean.md",
    "content": "---\nname: Mean\nslug: mean\nsourceRef: exp/simd/math_avx.go#L352\ncategory: exp\nsubCategory: simd\nsimilarHelpers:\n  - exp#simd#mean\n  - exp#simd#meanby\nposition: 10\nsignatures:\n  - \"func MeanInt8x16[T ~int8](collection []T) T\"\n  - \"func MeanInt8x32[T ~int8](collection []T) T\"\n  - \"func MeanInt8x64[T ~int8](collection []T) T\"\n  - \"func MeanInt16x8[T ~int16](collection []T) T\"\n  - \"func MeanInt16x16[T ~int16](collection []T) T\"\n  - \"func MeanInt16x32[T ~int16](collection []T) T\"\n  - \"func MeanInt32x4[T ~int32](collection []T) T\"\n  - \"func MeanInt32x8[T ~int32](collection []T) T\"\n  - \"func MeanInt32x16[T ~int32](collection []T) T\"\n  - \"func MeanInt64x2[T ~int64](collection []T) T\"\n  - \"func MeanInt64x4[T ~int64](collection []T) T\"\n  - \"func MeanInt64x8[T ~int64](collection []T) T\"\n  - \"func MeanUint8x16[T ~uint8](collection []T) T\"\n  - \"func MeanUint8x32[T ~uint8](collection []T) T\"\n  - \"func MeanUint8x64[T ~uint8](collection []T) T\"\n  - \"func MeanUint16x8[T ~uint16](collection []T) T\"\n  - \"func MeanUint16x16[T ~uint16](collection []T) T\"\n  - \"func MeanUint16x32[T ~uint16](collection []T) T\"\n  - \"func MeanUint32x4[T ~uint32](collection []T) T\"\n  - \"func MeanUint32x8[T ~uint32](collection []T) T\"\n  - \"func MeanUint32x16[T ~uint32](collection []T) T\"\n  - \"func MeanUint64x2[T ~uint64](collection []T) T\"\n  - \"func MeanUint64x4[T ~uint64](collection []T) T\"\n  - \"func MeanUint64x8[T ~uint64](collection []T) T\"\n  - \"func MeanFloat32x4[T ~float32](collection []T) T\"\n  - \"func MeanFloat32x8[T ~float32](collection []T) T\"\n  - \"func MeanFloat32x16[T ~float32](collection []T) T\"\n  - \"func MeanFloat64x2[T ~float64](collection []T) T\"\n  - \"func MeanFloat64x4[T ~float64](collection []T) T\"\n  - \"func MeanFloat64x8[T ~float64](collection []T) T\"\n---\n\nCalculates the arithmetic mean of a collection using SIMD instructions. The suffix (x2, x4, x8, x16, x32, x64) indicates the number of lanes processed simultaneously.\n\n> **Note**: Choose the variant matching your CPU's capabilities. Higher lane counts provide better performance but require newer CPU support.\n\n```go\n// Using AVX2 variant (32 lanes at once) - Intel Haswell+ / AMD Excavator+\nmean := simd.MeanInt8x32([]int8{1, 2, 3, 4, 5})\n// 3\n```\n\n```go\n// Using AVX-512 variant (16 lanes at once) - Intel Skylake-X+\nmean := simd.MeanFloat32x16([]float32{1.0, 2.0, 3.0, 4.0})\n// 2.5\n```\n\n```go\n// Using AVX variant (8 lanes at once) - works on all amd64\nmean := simd.MeanInt16x8([]int16{10, 20, 30, 40})\n// 25\n```\n\n```go\n// Empty collection returns 0\nmean := simd.MeanUint32x4([]uint32{})\n// 0\n```\n"
  },
  {
    "path": "docs/data/simd-meanby.md",
    "content": "---\nname: MeanBy\nslug: meanby\nsourceRef: exp/simd/math.go#L1006\ncategory: exp\nsubCategory: simd\nsimilarHelpers:\n  - exp#simd#mean\n  - exp#simd#sumby\nposition: 30\nsignatures:\n  - \"func MeanByInt8[T any, R ~int8](collection []T, iteratee func(item T) R) R\"\n  - \"func MeanByInt16[T any, R ~int16](collection []T, iteratee func(item T) R) R\"\n  - \"func MeanByInt32[T any, R ~int32](collection []T, iteratee func(item T) R) R\"\n  - \"func MeanByInt64[T any, R ~int64](collection []T, iteratee func(item T) R) R\"\n  - \"func MeanByUint8[T any, R ~uint8](collection []T, iteratee func(item T) R) R\"\n  - \"func MeanByUint16[T any, R ~uint16](collection []T, iteratee func(item T) R) R\"\n  - \"func MeanByUint32[T any, R ~uint32](collection []T, iteratee func(item T) R) R\"\n  - \"func MeanByUint64[T any, R ~uint64](collection []T, iteratee func(item T) R) R\"\n  - \"func MeanByFloat32[T any, R ~float32](collection []T, iteratee func(item T) R) R\"\n  - \"func MeanByFloat64[T any, R ~float64](collection []T, iteratee func(item T) R) R\"\n  - \"func MeanByInt8x16[T any, R ~int8](collection []T, iteratee func(item T) R) R\"\n  - \"func MeanByInt8x32[T any, R ~int8](collection []T, iteratee func(item T) R) R\"\n  - \"func MeanByInt8x64[T any, R ~int8](collection []T, iteratee func(item T) R) R\"\n  - \"func MeanByInt16x8[T any, R ~int16](collection []T, iteratee func(item T) R) R\"\n  - \"func MeanByInt16x16[T any, R ~int16](collection []T, iteratee func(item T) R) R\"\n  - \"func MeanByInt16x32[T any, R ~int16](collection []T, iteratee func(item T) R) R\"\n  - \"func MeanByInt32x4[T any, R ~int32](collection []T, iteratee func(item T) R) R\"\n  - \"func MeanByInt32x8[T any, R ~int32](collection []T, iteratee func(item T) R) R\"\n  - \"func MeanByInt32x16[T any, R ~int32](collection []T, iteratee func(item T) R) R\"\n  - \"func MeanByInt64x2[T any, R ~int64](collection []T, iteratee func(item T) R) R\"\n  - \"func MeanByInt64x4[T any, R ~int64](collection []T, iteratee func(item T) R) R\"\n  - \"func MeanByInt64x8[T any, R ~int64](collection []T, iteratee func(item T) R) R\"\n  - \"func MeanByUint8x16[T any, R ~uint8](collection []T, iteratee func(item T) R) R\"\n  - \"func MeanByUint8x32[T any, R ~uint8](collection []T, iteratee func(item T) R) R\"\n  - \"func MeanByUint8x64[T any, R ~uint8](collection []T, iteratee func(item T) R) R\"\n  - \"func MeanByUint16x8[T any, R ~uint16](collection []T, iteratee func(item T) R) R\"\n  - \"func MeanByUint16x16[T any, R ~uint16](collection []T, iteratee func(item T) R) R\"\n  - \"func MeanByUint16x32[T any, R ~uint16](collection []T, iteratee func(item T) R) R\"\n  - \"func MeanByUint32x4[T any, R ~uint32](collection []T, iteratee func(item T) R) R\"\n  - \"func MeanByUint32x8[T any, R ~uint32](collection []T, iteratee func(item T) R) R\"\n  - \"func MeanByUint32x16[T any, R ~uint32](collection []T, iteratee func(item T) R) R\"\n  - \"func MeanByUint64x2[T any, R ~uint64](collection []T, iteratee func(item T) R) R\"\n  - \"func MeanByUint64x4[T any, R ~uint64](collection []T, iteratee func(item T) R) R\"\n  - \"func MeanByUint64x8[T any, R ~uint64](collection []T, iteratee func(item T) R) R\"\n  - \"func MeanByFloat32x4[T any, R ~float32](collection []T, iteratee func(item T) R) R\"\n  - \"func MeanByFloat32x8[T any, R ~float32](collection []T, iteratee func(item T) R) R\"\n  - \"func MeanByFloat32x16[T any, R ~float32](collection []T, iteratee func(item T) R) R\"\n  - \"func MeanByFloat64x2[T any, R ~float64](collection []T, iteratee func(item T) R) R\"\n  - \"func MeanByFloat64x4[T any, R ~float64](collection []T, iteratee func(item T) R) R\"\n  - \"func MeanByFloat64x8[T any, R ~float64](collection []T, iteratee func(item T) R) R\"\n---\n\nMeanBy transforms a collection using an iteratee function and calculates the arithmetic mean of the result using SIMD instructions. The automatic dispatch functions (e.g., `MeanByInt8`) will select the best SIMD variant based on CPU capabilities. The specific variants (e.g., `MeanByInt8x32`) use a fixed SIMD instruction set regardless of CPU capabilities.\n\n> **Note**: The automatic dispatch functions (e.g., `MeanByInt8`) will use the best available SIMD variant for the current CPU. Use specific variants (e.g., `MeanByInt8x32`) only if you know your target CPU supports that instruction set.\n\n```go\ntype Person struct {\n    Name string\n    Age  int8\n}\n\npeople := []Person{\n    {Name: \"Alice\", Age: 20},\n    {Name: \"Bob\", Age: 30},\n    {Name: \"Charlie\", Age: 40},\n}\n\n// Automatic dispatch - uses best available SIMD\nmean := simd.MeanByInt8(people, func(p Person) int8 {\n    return p.Age\n})\n// 30\n```\n\n```go\ntype Product struct {\n    Name  string\n    Price float32\n}\n\nproducts := []Product{\n    {Name: \"Widget\", Price: 10.50},\n    {Name: \"Gadget\", Price: 20.00},\n    {Name: \"Tool\", Price: 15.75},\n}\n\n// Mean price using specific AVX2 variant\nmean := simd.MeanByFloat32x8(products, func(p Product) float32 {\n    return p.Price\n})\n// 15.4167\n```\n\n```go\ntype Metric struct {\n    Value uint16\n}\n\nmetrics := []Metric{\n    {Value: 100},\n    {Value: 200},\n    {Value: 300},\n    {Value: 400},\n}\n\n// Using AVX variant - works on all amd64\nmean := simd.MeanByUint16x8(metrics, func(m Metric) uint16 {\n    return m.Value\n})\n// 250\n```\n\n```go\n// Empty collection returns 0\ntype Item struct {\n    Count int64\n}\n\nmean := simd.MeanByInt64([]Item{}, func(i Item) int64 {\n    return i.Count\n})\n// 0\n```\n"
  },
  {
    "path": "docs/data/simd-min.md",
    "content": "---\nname: Min\nslug: min\nsourceRef: exp/simd/math_avx.go#L833\ncategory: exp\nsubCategory: simd\nsimilarHelpers:\n  - exp#simd#min\nposition: 20\nsignatures:\n  - \"func MinInt8x16[T ~int8](collection []T) T\"\n  - \"func MinInt8x32[T ~int8](collection []T) T\"\n  - \"func MinInt8x64[T ~int8](collection []T) T\"\n  - \"func MinInt16x8[T ~int16](collection []T) T\"\n  - \"func MinInt16x16[T ~int16](collection []T) T\"\n  - \"func MinInt16x32[T ~int16](collection []T) T\"\n  - \"func MinInt32x4[T ~int32](collection []T) T\"\n  - \"func MinInt32x8[T ~int32](collection []T) T\"\n  - \"func MinInt32x16[T ~int32](collection []T) T\"\n  - \"func MinInt64x2[T ~int64](collection []T) T\"\n  - \"func MinInt64x4[T ~int64](collection []T) T\"\n  - \"func MinInt64x8[T ~int64](collection []T) T\"\n  - \"func MinUint8x16[T ~uint8](collection []T) T\"\n  - \"func MinUint8x32[T ~uint8](collection []T) T\"\n  - \"func MinUint8x64[T ~uint8](collection []T) T\"\n  - \"func MinUint16x8[T ~uint16](collection []T) T\"\n  - \"func MinUint16x16[T ~uint16](collection []T) T\"\n  - \"func MinUint16x32[T ~uint16](collection []T) T\"\n  - \"func MinUint32x4[T ~uint32](collection []T) T\"\n  - \"func MinUint32x8[T ~uint32](collection []T) T\"\n  - \"func MinUint32x16[T ~uint32](collection []T) T\"\n  - \"func MinUint64x2[T ~uint64](collection []T) T\"\n  - \"func MinUint64x4[T ~uint64](collection []T) T\"\n  - \"func MinUint64x8[T ~uint64](collection []T) T\"\n  - \"func MinFloat32x4[T ~float32](collection []T) T\"\n  - \"func MinFloat32x8[T ~float32](collection []T) T\"\n  - \"func MinFloat32x16[T ~float32](collection []T) T\"\n  - \"func MinFloat64x2[T ~float64](collection []T) T\"\n  - \"func MinFloat64x4[T ~float64](collection []T) T\"\n  - \"func MinFloat64x8[T ~float64](collection []T) T\"\n---\n\nFinds the minimum value in a collection using SIMD instructions. The suffix (x2, x4, x8, x16, x32, x64) indicates the number of lanes processed simultaneously.\n\n> **Note**: Choose the variant matching your CPU's capabilities. Higher lane counts provide better performance but require newer CPU support.\n\n```go\n// Using AVX2 variant (32 lanes at once) - Intel Haswell+ / AMD Excavator+\nmin := simd.MinInt8x32([]int8{5, 2, 8, 1, 9})\n// 1\n```\n\n```go\n// Using AVX-512 variant (16 lanes at once) - Intel Skylake-X+\nmin := simd.MinFloat32x16([]float32{3.5, 1.2, 4.8, 2.1})\n// 1.2\n```\n\n```go\n// Using AVX variant (4 lanes at once) - works on all amd64\nmin := simd.MinInt32x4([]int32{100, 50, 200, 75})\n// 50\n```\n\n```go\n// Empty collection returns 0\nmin := simd.MinUint16x8([]uint16{})\n// 0\n```\n"
  },
  {
    "path": "docs/data/simd-sum.md",
    "content": "---\nname: Sum\nslug: sum\nsourceRef: exp/simd/math_avx.go#L14\ncategory: exp\nsubCategory: simd\nsimilarHelpers:\n  - exp#simd#sum\n  - exp#simd#sumby\nposition: 0\nsignatures:\n  - \"func SumInt8x16[T ~int8](collection []T) T\"\n  - \"func SumInt8x32[T ~int8](collection []T) T\"\n  - \"func SumInt8x64[T ~int8](collection []T) T\"\n  - \"func SumInt16x8[T ~int16](collection []T) T\"\n  - \"func SumInt16x16[T ~int16](collection []T) T\"\n  - \"func SumInt16x32[T ~int16](collection []T) T\"\n  - \"func SumInt32x4[T ~int32](collection []T) T\"\n  - \"func SumInt32x8[T ~int32](collection []T) T\"\n  - \"func SumInt32x16[T ~int32](collection []T) T\"\n  - \"func SumInt64x2[T ~int64](collection []T) T\"\n  - \"func SumInt64x4[T ~int64](collection []T) T\"\n  - \"func SumInt64x8[T ~int64](collection []T) T\"\n  - \"func SumUint8x16[T ~uint8](collection []T) T\"\n  - \"func SumUint8x32[T ~uint8](collection []T) T\"\n  - \"func SumUint8x64[T ~uint8](collection []T) T\"\n  - \"func SumUint16x8[T ~uint16](collection []T) T\"\n  - \"func SumUint16x16[T ~uint16](collection []T) T\"\n  - \"func SumUint16x32[T ~uint16](collection []T) T\"\n  - \"func SumUint32x4[T ~uint32](collection []T) T\"\n  - \"func SumUint32x8[T ~uint32](collection []T) T\"\n  - \"func SumUint32x16[T ~uint32](collection []T) T\"\n  - \"func SumUint64x2[T ~uint64](collection []T) T\"\n  - \"func SumUint64x4[T ~uint64](collection []T) T\"\n  - \"func SumUint64x8[T ~uint64](collection []T) T\"\n  - \"func SumFloat32x4[T ~float32](collection []T) T\"\n  - \"func SumFloat32x8[T ~float32](collection []T) T\"\n  - \"func SumFloat32x16[T ~float32](collection []T) T\"\n  - \"func SumFloat64x2[T ~float64](collection []T) T\"\n  - \"func SumFloat64x4[T ~float64](collection []T) T\"\n  - \"func SumFloat64x8[T ~float64](collection []T) T\"\n---\n\nSums the values in a collection using SIMD instructions. The suffix (x2, x4, x8, x16, x32, x64) indicates the number of lanes processed simultaneously.\n\n> **Note**: Choose the variant matching your CPU's capabilities. Higher lane counts provide better performance but require newer CPU support.\n\n```go\n// Using AVX2 variant (32 lanes at once) - Intel Haswell+ / AMD Excavator+\nsum := simd.SumInt8x32([]int8{1, 2, 3, 4, 5})\n// 15\n```\n\n```go\n// Using AVX-512 variant (16 lanes at once) - Intel Skylake-X+\nsum := simd.SumFloat32x16([]float32{1.1, 2.2, 3.3, 4.4})\n// 11\n```\n\n```go\n// Using AVX variant (4 lanes at once) - works on all amd64\nsum := simd.SumInt32x4([]int32{1000000, 2000000, 3000000})\n// 6000000\n```\n\n```go\n// Empty collection returns 0\nsum := simd.SumUint16x16([]uint16{})\n// 0\n```\n"
  },
  {
    "path": "docs/data/simd-sumby.md",
    "content": "---\nname: SumBy\nslug: sumby\nsourceRef: exp/simd/math.go#L841\ncategory: exp\nsubCategory: simd\nsimilarHelpers:\n  - exp#simd#sum\n  - exp#simd#meanby\nposition: 20\nsignatures:\n  - \"func SumByInt8[T any, R ~int8](collection []T, iteratee func(item T) R) R\"\n  - \"func SumByInt16[T any, R ~int16](collection []T, iteratee func(item T) R) R\"\n  - \"func SumByInt32[T any, R ~int32](collection []T, iteratee func(item T) R) R\"\n  - \"func SumByInt64[T any, R ~int64](collection []T, iteratee func(item T) R) R\"\n  - \"func SumByUint8[T any, R ~uint8](collection []T, iteratee func(item T) R) R\"\n  - \"func SumByUint16[T any, R ~uint16](collection []T, iteratee func(item T) R) R\"\n  - \"func SumByUint32[T any, R ~uint32](collection []T, iteratee func(item T) R) R\"\n  - \"func SumByUint64[T any, R ~uint64](collection []T, iteratee func(item T) R) R\"\n  - \"func SumByFloat32[T any, R ~float32](collection []T, iteratee func(item T) R) R\"\n  - \"func SumByFloat64[T any, R ~float64](collection []T, iteratee func(item T) R) R\"\n  - \"func SumByInt8x16[T any, R ~int8](collection []T, iteratee func(item T) R) R\"\n  - \"func SumByInt8x32[T any, R ~int8](collection []T, iteratee func(item T) R) R\"\n  - \"func SumByInt8x64[T any, R ~int8](collection []T, iteratee func(item T) R) R\"\n  - \"func SumByInt16x8[T any, R ~int16](collection []T, iteratee func(item T) R) R\"\n  - \"func SumByInt16x16[T any, R ~int16](collection []T, iteratee func(item T) R) R\"\n  - \"func SumByInt16x32[T any, R ~int16](collection []T, iteratee func(item T) R) R\"\n  - \"func SumByInt32x4[T any, R ~int32](collection []T, iteratee func(item T) R) R\"\n  - \"func SumByInt32x8[T any, R ~int32](collection []T, iteratee func(item T) R) R\"\n  - \"func SumByInt32x16[T any, R ~int32](collection []T, iteratee func(item T) R) R\"\n  - \"func SumByInt64x2[T any, R ~int64](collection []T, iteratee func(item T) R) R\"\n  - \"func SumByInt64x4[T any, R ~int64](collection []T, iteratee func(item T) R) R\"\n  - \"func SumByInt64x8[T any, R ~int64](collection []T, iteratee func(item T) R) R\"\n  - \"func SumByUint8x16[T any, R ~uint8](collection []T, iteratee func(item T) R) R\"\n  - \"func SumByUint8x32[T any, R ~uint8](collection []T, iteratee func(item T) R) R\"\n  - \"func SumByUint8x64[T any, R ~uint8](collection []T, iteratee func(item T) R) R\"\n  - \"func SumByUint16x8[T any, R ~uint16](collection []T, iteratee func(item T) R) R\"\n  - \"func SumByUint16x16[T any, R ~uint16](collection []T, iteratee func(item T) R) R\"\n  - \"func SumByUint16x32[T any, R ~uint16](collection []T, iteratee func(item T) R) R\"\n  - \"func SumByUint32x4[T any, R ~uint32](collection []T, iteratee func(item T) R) R\"\n  - \"func SumByUint32x8[T any, R ~uint32](collection []T, iteratee func(item T) R) R\"\n  - \"func SumByUint32x16[T any, R ~uint32](collection []T, iteratee func(item T) R) R\"\n  - \"func SumByUint64x2[T any, R ~uint64](collection []T, iteratee func(item T) R) R\"\n  - \"func SumByUint64x4[T any, R ~uint64](collection []T, iteratee func(item T) R) R\"\n  - \"func SumByUint64x8[T any, R ~uint64](collection []T, iteratee func(item T) R) R\"\n  - \"func SumByFloat32x4[T any, R ~float32](collection []T, iteratee func(item T) R) R\"\n  - \"func SumByFloat32x8[T any, R ~float32](collection []T, iteratee func(item T) R) R\"\n  - \"func SumByFloat32x16[T any, R ~float32](collection []T, iteratee func(item T) R) R\"\n  - \"func SumByFloat64x2[T any, R ~float64](collection []T, iteratee func(item T) R) R\"\n  - \"func SumByFloat64x4[T any, R ~float64](collection []T, iteratee func(item T) R) R\"\n  - \"func SumByFloat64x8[T any, R ~float64](collection []T, iteratee func(item T) R) R\"\n---\n\nSumBy transforms a collection using an iteratee function and sums the result using SIMD instructions. The automatic dispatch functions (e.g., `SumByInt8`) will select the best SIMD variant based on CPU capabilities. The specific variants (e.g., `SumByInt8x32`) use a fixed SIMD instruction set regardless of CPU capabilities.\n\n> **Note**: The automatic dispatch functions (e.g., `SumByInt8`) will use the best available SIMD variant for the current CPU. Use specific variants (e.g., `SumByInt8x32`) only if you know your target CPU supports that instruction set.\n\n```go\ntype Person struct {\n    Name string\n    Age  int8\n}\n\npeople := []Person{\n    {Name: \"Alice\", Age: 25},\n    {Name: \"Bob\", Age: 30},\n    {Name: \"Charlie\", Age: 35},\n}\n\n// Automatic dispatch - uses best available SIMD\nsum := simd.SumByInt8(people, func(p Person) int8 {\n    return p.Age\n})\n// 90\n```\n\n```go\ntype Product struct {\n    Name  string\n    Price float32\n    Stock int32\n}\n\nproducts := []Product{\n    {Name: \"Widget\", Price: 10.50, Stock: 5},\n    {Name: \"Gadget\", Price: 20.00, Stock: 3},\n    {Name: \"Tool\", Price: 15.75, Stock: 2},\n}\n\n// Sum stock value using specific AVX2 variant\nsum := simd.SumByFloat32x8(products, func(p Product) float32 {\n    return p.Price * float32(p.Stock)\n})\n// 152.5\n```\n\n```go\ntype Metric struct {\n    Value uint16\n}\n\nmetrics := []Metric{\n    {Value: 100},\n    {Value: 200},\n    {Value: 300},\n    {Value: 400},\n}\n\n// Using AVX variant - works on all amd64\nsum := simd.SumByUint16x8(metrics, func(m Metric) uint16 {\n    return m.Value\n})\n// 1000\n```\n\n```go\n// Empty collection returns 0\ntype Item struct {\n    Count int64\n}\n\nsum := simd.SumByInt64([]Item{}, func(i Item) int64 {\n    return i.Count\n})\n// 0\n```\n"
  },
  {
    "path": "docs/docs/_category_.json",
    "content": "{\n    \"label\": \"Documentation\",\n    \"position\": 1,\n    \"link\": {\n        \"type\": \"generated-index\",\n        \"description\": \"Learn how to use samber/lo - the reusable utility library for Go.\"\n    }\n}"
  },
  {
    "path": "docs/docs/about.md",
    "content": "---\ntitle: ✌️ About\ndescription: Discover \"lo\", the utility library for Go\nsidebar_position: 0\n---\n\n# ✌️ About\n\n**samber/lo** is a Lodash-style utility library for Go that brings the power and convenience of functional programming helpers to the Go ecosystem. Born from the need for more expressive and concise data manipulation, `lo` fills the gaps between Go's standard library and the complex data transformations that modern applications require.\n\n![logo](../static/img/functional-gopher.png)\n\n**Why `lo` Exists**\n\nGo's standard library is excellent for many use cases, but it lacks the higher-level abstractions that developers coming from JavaScript, Python, or other languages often miss. While Go 1.18 introduced generics, the standard library's `slices` and `maps` packages only cover about 5-10 basic helpers. `lo` provides hundreds of additional utilities that make everyday programming tasks more enjoyable and less error-prone.\n\n**The name \"lo\"**\n\nI wanted a short and memorable name, similar to \"Lodash\". It's easy to type and no existing Go package was using this name, making it unique in the ecosystem.\n\n## 🚀 Install\n\n```go\ngo get -u github.com/samber/lo@v1\n```\n\nThis library is v1 and follows SemVer strictly.\n\nNo breaking changes will be made to exported APIs before v2.0.0.\n\nThis library has no dependencies outside the Go standard library.\n\n## 💡 Usage\n\nYou can import `lo` using:\n\n```go\nimport (\n    \"github.com/samber/lo\"\n    lop \"github.com/samber/lo/parallel\"\n    lom \"github.com/samber/lo/mutable\"\n    loi \"github.com/samber/lo/it\"\n)\n```\n\nThen use one of the helpers below:\n\n```go\nnames := lo.Uniq([]string{\"Samuel\", \"John\", \"Samuel\"})\n// []string{\"Samuel\", \"John\"}\n```\n\n### Tips for lazy developers\n\nI cannot recommend it, but in case you are too lazy for repeating `lo.` everywhere, you can import the entire library into the namespace. 😅 🤮\n\n```go\nimport (\n    . \"github.com/samber/lo\"\n)\n```\n\nI take no responsibility for this junk. 😁 💩\n\n## 🙋‍♂️ Community and Evolution\n\n`lo` embraces Go's evolution:\n- **Go 1.18**: Leveraged generics for type safety\n- **Go 1.23**: Added iterator support with the `it` package\n- **Future**: Will continue to adapt to Go's language improvements\n\nThe library is actively maintained and welcomes contributions. It follows semantic versioning strictly, ensuring stability for production applications.\n\n## 📍 When to Use `lo`\n\nUse `lo` when you need to:\n- Transform complex data structures concisely\n- Reduce boilerplate code for common operations\n- Write more declarative and readable code\n- Leverage functional programming patterns in Go\n- Process data in parallel or with lazy evaluation\n\nFor simple operations, Go's standard library may suffice. But when you find yourself writing nested loops or complex data manipulation logic, `lo` provides the abstractions you need.\n\n## 🏛️ Design Philosophy\n\n### 1. **Type Safety Through Generics**\nEvery function in `lo` is built on Go 1.18+ generics, ensuring compile-time type safety without sacrificing flexibility. This eliminates runtime type assertions and reduces bugs.\n\n### 2. **Immutable by Default**\nThe main `lo` package follows functional programming principles by returning new collections rather than modifying existing ones. This predictability makes code easier to reason about and test.\n\n### 3. **Performance When Needed**\nFor performance-critical scenarios, `lo` offers specialized packages:\n- `lo/mutable`: In-place operations that modify collections directly\n- `lo/parallel`: Concurrent processing with built-in worker pools\n- `lo/it`: Lazy evaluation using Go 1.23+ iterators\n\n### 4. **Minimal Dependencies**\n`lo` has zero dependencies outside the Go standard library. This choice ensures reliability, security, and avoids dependency hell.\n"
  },
  {
    "path": "docs/docs/contributing.md",
    "content": "---\ntitle: 🤝 Contributing\ndescription: Join the community of contributors.\nsidebar_position: 110\n---\n\n# 🤝 Contributing\n\nHey! We are happy to have you as a new contributor. ✌️\n\nFor your contribution please follow some guidelines:\n\n## Function Naming\nHelpers must be self-explanatory and respect standards (other languages, libraries...). Feel free to suggest many names in your contributions or the related issue.\n\nWe hate breaking changes, so better think twice ;)\n\n## Variadic functions\nMany functions accept variadic parameters (like `lo.Keys(...map[K]V)` accepting multiple maps), providing flexibility while maintaining type safety.\n\n## Slice type Parameters\nFunctions use `~[]T` constraints to accept any slice type, including named slice types, not just `[]T`. This design choice makes the library more flexible in real-world usage.\n\n## Variants\nWhen applicable, some functions can be added to sub-package as well: `mutable`, `it` and `parallel`. Add a documentation for each helper.\n\nFor function variants, use consistent suffixes:\n- `F` suffix for function-based versions (lazy evaluation)\n- `I` suffix for variants having `index int` argument in predicate callback\n- `Err` suffix for variants returning an error in predicate callback\n- `WithContext` suffix when context.Context is provided\n- `X` suffix for helpers with varying arguments (eg: MustX: Must2, Must3, Must4...)\n\n## Testing\nWe try to maintain code coverage above 90%.\n\n## Benchmark and performance\nWrite performant helpers and limit extra memory consumption. Build an helper for general purpose and don't optimize for a particular use-case.\n\nFeel free to write benchmarks.\n\nIterators can be unbounded and run for a very long time. If you expect a big memory footprint, please warn developers in the function comment.\n\n## Documentation\nFunctions must be properly commented, with a Go Playground link. New helpers must be created with a markdown documentation in `docs/data/`. In markdown header, please link to similar helpers (and update other markdowns accordingly).\n\nAdd your helper to `docs/static/llms.txt`.\n\n## Examples\nEvery function includes a \"Play\" link to the Go Playground, allowing developers to quickly experiment and understand behavior without setting up a local environment.\n\nPlease add an example of your helper in the file named `xxxx_example_test.go`. It will be available from Godoc website: https://pkg.go.dev/github.com/samber/lo\n\n## Other conventions\n\n### Naming\n\n1- If a callback returns a single bool then it should probably be called \"predicate\".\n2- If a callback is used to change a collection element into something else then it should probably be called \"transform\".\n3- If a callback returns nothing (void) then it should probably be called \"callback\".\n\n### Types\n\n1- Generic functions must preserve the underlying type of collections so that the returned values maintain the same type as the input. See [#365](https://github.com/samber/lo/pull/365/files).\n"
  },
  {
    "path": "docs/docs/core/_category_.json",
    "content": "{\n  \"label\": \"🧢 Core\",\n  \"position\": 1,\n  \"link\": {\n    \"type\": \"generated-index\",\n    \"description\": \"Stop reinventing the wheel\"\n  }\n}"
  },
  {
    "path": "docs/docs/core/channel.md",
    "content": "---\ntitle: \"Channel\"\ndescription: Loop over channel and perform transformations\nsidebar_position: 20\nhide_table_of_contents: true\n---\n\n:::warning Help improve this documentation\nThis documentation is still new and evolving. If you spot any mistakes, unclear explanations, or missing details, please [open an issue](https://github.com/samber/lo/issues).\n\nYour feedback helps us improve!\n:::\n\n#\n## Core - Channel helpers\n\nThis page lists all operations on channels, available in the core package of lo.\n\nimport HelperList from '@site/plugins/helpers-pages/components/HelperList';\n\n<HelperList \n  category=\"core\"\n  subCategory=\"channel\"\n/>\n"
  },
  {
    "path": "docs/docs/core/concurrency.md",
    "content": "---\ntitle: \"Concurrency\"\ndescription: Operate on multiple gorountines\nsidebar_position: 80\nhide_table_of_contents: true\n---\n\n:::warning Help improve this documentation\nThis documentation is still new and evolving. If you spot any mistakes, unclear explanations, or missing details, please [open an issue](https://github.com/samber/lo/issues).\n\nYour feedback helps us improve!\n:::\n\n#\n## Core - Concurrency helpers\n\nThis page lists all concurrency operations available in the core package of lo.\n\nimport HelperList from '@site/plugins/helpers-pages/components/HelperList';\n\n<HelperList \n  category=\"core\"\n  subCategory=\"concurrency\"\n/>\n"
  },
  {
    "path": "docs/docs/core/condition.md",
    "content": "---\ntitle: \"Condition\"\ndescription: Perform transformations on types\nsidebar_position: 45\nhide_table_of_contents: true\n---\n\n:::warning Help improve this documentation\nThis documentation is still new and evolving. If you spot any mistakes, unclear explanations, or missing details, please [open an issue](https://github.com/samber/lo/issues).\n\nYour feedback helps us improve!\n:::\n\n#\n## Core - Conditional helpers\n\nThis page lists all conditional operations available in the core package of lo.\n\nimport HelperList from '@site/plugins/helpers-pages/components/HelperList';\n\n<HelperList \n  category=\"core\"\n  subCategory=\"condition\"\n/>\n"
  },
  {
    "path": "docs/docs/core/error-handling.md",
    "content": "---\ntitle: \"Error handling\"\ndescription: Error handling\nsidebar_position: 110\nhide_table_of_contents: true\n---\n\n:::warning Help improve this documentation\nThis documentation is still new and evolving. If you spot any mistakes, unclear explanations, or missing details, please [open an issue](https://github.com/samber/lo/issues).\n\nYour feedback helps us improve!\n:::\n\n#\n## Core - Error handling helpers\n\nThis page lists all error handling operations available in the core package of lo.\n\nimport HelperList from '@site/plugins/helpers-pages/components/HelperList';\n\n<HelperList \n  category=\"core\"\n  subCategory=\"error-handling\"\n/>\n"
  },
  {
    "path": "docs/docs/core/find.md",
    "content": "---\ntitle: \"Find\"\ndescription: Loop over a collection and find element(s)\nsidebar_position: 40\nhide_table_of_contents: true\n---\n\n:::warning Help improve this documentation\nThis documentation is still new and evolving. If you spot any mistakes, unclear explanations, or missing details, please [open an issue](https://github.com/samber/lo/issues).\n\nYour feedback helps us improve!\n:::\n\n#\n## Core - Find helpers\n\nThis page lists all search helpers, available in the core package of lo.\n\nimport HelperList from '@site/plugins/helpers-pages/components/HelperList';\n\n<HelperList \n  category=\"core\"\n  subCategory=\"find\"\n/>\n"
  },
  {
    "path": "docs/docs/core/function.md",
    "content": "---\ntitle: \"Function\"\ndescription: Functions helpers\nsidebar_position: 30\nhide_table_of_contents: true\n---\n\n:::warning Help improve this documentation\nThis documentation is still new and evolving. If you spot any mistakes, unclear explanations, or missing details, please [open an issue](https://github.com/samber/lo/issues).\n\nYour feedback helps us improve!\n:::\n\n#\n## Core - Function helpers\n\nThis page lists all operations on functions, available in the core package of lo.\n\nimport HelperList from '@site/plugins/helpers-pages/components/HelperList';\n\n<HelperList \n  category=\"core\"\n  subCategory=\"function\"\n/>\n"
  },
  {
    "path": "docs/docs/core/intersect.md",
    "content": "---\ntitle: \"Intersect\"\ndescription: Loop over a collection and find similar items\nsidebar_position: 50\nhide_table_of_contents: true\n---\n\n:::warning Help improve this documentation\nThis documentation is still new and evolving. If you spot any mistakes, unclear explanations, or missing details, please [open an issue](https://github.com/samber/lo/issues).\n\nYour feedback helps us improve!\n:::\n\n#\n## Core - Intersection helpers\n\nThis page lists all intersection helpers, available in the core package of lo.\n\nimport HelperList from '@site/plugins/helpers-pages/components/HelperList';\n\n<HelperList \n  category=\"core\"\n  subCategory=\"intersect\"\n/>\n"
  },
  {
    "path": "docs/docs/core/map.md",
    "content": "---\ntitle: \"Map\"\ndescription: Loop over maps and perform transformations\nsidebar_position: 10\nhide_table_of_contents: true\n---\n\n:::warning Help improve this documentation\nThis documentation is still new and evolving. If you spot any mistakes, unclear explanations, or missing details, please [open an issue](https://github.com/samber/lo/issues).\n\nYour feedback helps us improve!\n:::\n\n#\n## Core - Map helpers\n\nThis page lists all operations on maps, available in the core package of lo.\n\nimport HelperList from '@site/plugins/helpers-pages/components/HelperList';\n\n<HelperList \n  category=\"core\"\n  subCategory=\"map\"\n/>\n"
  },
  {
    "path": "docs/docs/core/math.md",
    "content": "---\ntitle: \"Math\"\ndescription: Perform math operations on collections\nsidebar_position: 60\nhide_table_of_contents: true\n---\n\n:::warning Help improve this documentation\nThis documentation is still new and evolving. If you spot any mistakes, unclear explanations, or missing details, please [open an issue](https://github.com/samber/lo/issues).\n\nYour feedback helps us improve!\n:::\n\n#\n## Core - Math helpers\n\nThis page lists all math operations available in the core package of lo.\n\nimport HelperList from '@site/plugins/helpers-pages/components/HelperList';\n\n<HelperList \n  category=\"core\"\n  subCategory=\"math\"\n/>\n"
  },
  {
    "path": "docs/docs/core/retry.md",
    "content": "---\ntitle: \"Retry\"\ndescription: Retry processing on error\nsidebar_position: 70\nhide_table_of_contents: true\n---\n\n:::warning Help improve this documentation\nThis documentation is still new and evolving. If you spot any mistakes, unclear explanations, or missing details, please [open an issue](https://github.com/samber/lo/issues).\n\nYour feedback helps us improve!\n:::\n\n#\n## Core - Retry helpers\n\nThis page lists all retry operations available in the core package of lo.\n\nimport HelperList from '@site/plugins/helpers-pages/components/HelperList';\n\n<HelperList \n  category=\"core\"\n  subCategory=\"retry\"\n/>\n"
  },
  {
    "path": "docs/docs/core/slice.md",
    "content": "---\ntitle: Slice\ndescription: Loop over slices and perform transformations\nsidebar_position: 0\nhide_table_of_contents: true\n---\n\n:::warning Help improve this documentation\nThis documentation is still new and evolving. If you spot any mistakes, unclear explanations, or missing details, please [open an issue](https://github.com/samber/lo/issues).\n\nYour feedback helps us improve!\n:::\n\n#\n## Core - Slice helpers\n\nThis page lists all operations on slices, available in the core package of lo.\n\nimport HelperList from '@site/plugins/helpers-pages/components/HelperList';\n\n<HelperList \n  category=\"core\"\n  subCategory=\"slice\"\n/>\n"
  },
  {
    "path": "docs/docs/core/string.md",
    "content": "---\ntitle: \"String\"\ndescription: Perform transformations on strings\nsidebar_position: 35\nhide_table_of_contents: true\n---\n\n:::warning Help improve this documentation\nThis documentation is still new and evolving. If you spot any mistakes, unclear explanations, or missing details, please [open an issue](https://github.com/samber/lo/issues).\n\nYour feedback helps us improve!\n:::\n\n#\n## Core - String helpers\n\nThis page lists all string operations available in the core package of lo.\n\nimport HelperList from '@site/plugins/helpers-pages/components/HelperList';\n\n<HelperList \n  category=\"core\"\n  subCategory=\"string\"\n/>\n"
  },
  {
    "path": "docs/docs/core/time.md",
    "content": "---\ntitle: \"Time\"\ndescription: Time manipulation\nsidebar_position: 100\nhide_table_of_contents: true\n---\n\n:::warning Help improve this documentation\nThis documentation is still new and evolving. If you spot any mistakes, unclear explanations, or missing details, please [open an issue](https://github.com/samber/lo/issues).\n\nYour feedback helps us improve!\n:::\n\n#\n## Core - Time helpers\n\nThis page lists all time operations available in the core package of lo.\n\nimport HelperList from '@site/plugins/helpers-pages/components/HelperList';\n\n<HelperList \n  category=\"core\"\n  subCategory=\"time\"\n/>\n"
  },
  {
    "path": "docs/docs/core/tuple.md",
    "content": "---\ntitle: \"Tuple\"\ndescription: Manipulate multiple items in a single variable\nsidebar_position: 90\nhide_table_of_contents: true\n---\n\n:::warning Help improve this documentation\nThis documentation is still new and evolving. If you spot any mistakes, unclear explanations, or missing details, please [open an issue](https://github.com/samber/lo/issues).\n\nYour feedback helps us improve!\n:::\n\n#\n## Core - Tuple helpers\n\nThis page lists all tuple operations available in the core package of lo.\n\nimport HelperList from '@site/plugins/helpers-pages/components/HelperList';\n\n<HelperList \n  category=\"core\"\n  subCategory=\"tuple\"\n/>\n"
  },
  {
    "path": "docs/docs/core/type.md",
    "content": "---\ntitle: \"Type manipulation\"\ndescription: Perform transformations on types\nsidebar_position: 120\nhide_table_of_contents: true\n---\n\n:::warning Help improve this documentation\nThis documentation is still new and evolving. If you spot any mistakes, unclear explanations, or missing details, please [open an issue](https://github.com/samber/lo/issues).\n\nYour feedback helps us improve!\n:::\n\n#\n## Core - Type manipulation helpers\n\nThis page lists all type operations available in the core package of lo.\n\nimport HelperList from '@site/plugins/helpers-pages/components/HelperList';\n\n<HelperList \n  category=\"core\"\n  subCategory=\"type\"\n/>\n"
  },
  {
    "path": "docs/docs/experimental/_category_.json",
    "content": "{\n  \"label\": \"🧪 Experimental\",\n  \"position\": 5,\n  \"link\": {\n    \"type\": \"generated-index\",\n    \"description\": \"Experimental features\"\n  }\n}"
  },
  {
    "path": "docs/docs/experimental/simd.md",
    "content": "---\ntitle: SIMD\ndescription: High-performance slice operations using AVX, AVX2 and AVX512 SIMD when built with Go 1.26+ and GOEXPERIMENT=simd on amd64.\nsidebar_position: 0\nhide_table_of_contents: true\n---\n\n:::warning Help improve this documentation\nThis documentation is still new and evolving. If you spot any mistakes, unclear explanations, or missing details, please [open an issue](https://github.com/samber/lo/issues).\n\nYour feedback helps us improve!\n:::\n\n#\n## SIMD helpers\n\nThis page lists all operations on slices, available in the `exp/simd` sub-package. These helpers use **AVX** (128-bit), **AVX2** (256-bit) or **AVX512** (512-bit) SIMD when built with Go 1.26+, the `GOEXPERIMENT=simd` flag, and on amd64.\n\n:::warning Unstable API\nSIMD helpers are experimental. The API may break in the future.\n:::\n\n## Performance\n\nBenchmarks show that running SIMD operators on small datasets is slower:\n\n```txt\nBenchmarkSumInt8/small/Fallback-lo-4             203616572        5.875 ns/op\nBenchmarkSumInt8/small/AVX-x16-4                 100000000        12.04 ns/op\nBenchmarkSumInt8/small/AVX2-x32-4                 64041816        17.93 ns/op\nBenchmarkSumInt8/small/AVX512-x64-4               26947528        44.75 ns/op\n```\n\nBut much much faster on big datasets:\n\n```txt\nBenchmarkSumInt8/xlarge/Fallback-lo-4               247677       4860 ns/op\nBenchmarkSumInt8/xlarge/AVX-x16-4                  3851040      311.4 ns/op\nBenchmarkSumInt8/xlarge/AVX2-x32-4                 7100002      169.2 ns/op\nBenchmarkSumInt8/xlarge/AVX512-x64-4              10107534      118.1 ns/op\n```\n\nimport HelperList from '@site/plugins/helpers-pages/components/HelperList';\n\n<HelperList\n  category=\"exp\"\n  subCategory=\"simd\"\n/>\n"
  },
  {
    "path": "docs/docs/getting-started.md",
    "content": "---\ntitle: 🚀 Getting started\ndescription: Let's discover samber/lo in less than 5 minutes.\nsidebar_position: 1\n---\n\n# Getting started\n\n**samber/lo** is a Lodash-style utility library for Go 1.18+ that leverages generics to provide type-safe helper functions. The library is organized into several packages, each serving different use cases.\n\n## 🚀 Install\n\n```bash\ngo get -u github.com/samber/lo@v1\n```\n\n## 🧢 Core Package (`lo`)\n\nThe main package provides immutable utility functions for slices, maps, strings, math operations, and more. It's the core of the library with over 300+ functions.\n\n```go\nimport \"github.com/samber/lo\"\n\n// Example: Map a slice of numbers to their squares\nnumbers := []int{1, 2, 3, 4, 5}\nsquared := lo.Map(numbers, func(x int, _ int) int {\n    return x * x\n})\n// Result: [1, 4, 9, 16, 25]\n```\n\n## 🔄 Iter Package (`lo/it`)\n\nThe  `it` package provides Go 1.23+ sequence helpers with lazy evaluation, offering over 100 functions for efficient iteration without buffering.\n\n```go\n// Future usage (Go 1.23+)\nimport (\n    \"iter\"\n    loi \"github.com/samber/lo/it\"\n)\n\nseqIn := iter.Range(0, 1000)\n\n// Lazy iteration without buffering\nseqOut := loi.Filter(seqIn, func(x int) bool {\n    return x%2 == 0\n})\n```\n\n## 👣 Mutable Package (`lo/mutable`)\n\nThe mutable package provides in-place operations that modify collections directly, useful for performance-critical scenarios.\n\n```go\nimport lom \"github.com/samber/lo/mutable\"\n\n// Filter in-place (modifies the original slice)\nnumbers := []int{1, 2, 3, 4, 5}\nlom.Filter(&numbers, func(x int) bool {\n    return x%2 == 0\n})\n// Result: [2, 4]\n```\n\n## 🏎️ Parallel Package (`lo/parallel`)\n\nThe parallel package enables concurrent processing of collections with built-in worker pools, perfect for CPU-intensive operations.\n\n```go\nimport lop \"github.com/samber/lo/parallel\"\n\n// Process items concurrently (4 workers by default)\nresults := lop.Map(numbers, 4, func(x int) int {\n    // Some expensive operation\n    return expensiveOperation(x)\n})\n```\n\n## ✅ Key Benefits\n\n- **Type-safe** with generics\n- **Immutable** by default (main package)\n- **Performance** optimized with parallel and mutable variants\n- **Comprehensive** with 500+ utility functions\n- **Lazy evaluation** with `iter` std package (Go >= 1.23)\n- **Minimal dependencies** zero dependencies outside the Go standard library\n\n## 👀 Next Steps\n\n- Check the [Go documentation](https://pkg.go.dev/github.com/samber/lo) for complete API reference\n- Explore examples in the repository\n- Choose the right sub-package for your use case\n"
  },
  {
    "path": "docs/docs/glossary.md",
    "content": "---\nid: glossary\ntitle: 📚 Glossary\ndescription: Comprehensive glossary of samber/lo library terms and concepts\nsidebar_position: 100\n---\n\n# Glossary\n\n## Generics\nGo 1.18+ feature that allows writing functions and types that work with any type while maintaining type safety. The `lo` library extensively uses generics to provide type-safe utility functions.\n\n## Reflection\nLanguage reflection is a programming technique where a program can examine and manipulate its own structure and behavior at runtime.\n\n## Type Safety\nThe principle of ensuring that operations are performed on the correct data types, preventing runtime errors. `lo` leverages Go's type system and generics to provide type-safe operations and type-safe APIs.\n\n## Immutability\nThe concept of data that cannot be changed after creation. Most `lo` functions follow immutable patterns, returning new collections rather than modifying existing ones.\n\n## Predicate Function\nA function that returns a boolean value, typically used for filtering or testing conditions. In `lo`, predicates are commonly used with `Filter`, `Find`, `Contains`, etc.\n\n## Transformer Function\nA function that transforms one value into another. Used with `Map`, `MapValues`, and other transformation operations.\n\n## Reducer Function\nA function that combines two values into one, used with `Reduce` and similar operations.\n\n## Comparator Function\nA function that compares two values and returns their relative order. Used with sorting operations.\n\n## Higher-Order Functions\nFunctions that take other functions as parameters or return functions as results. Most `lo` utilities are higher-order functions.\n\n## Mutable Operations\nFunctions that modify collections in-place rather than creating new ones. Mutable operations can be more memory efficient but less safe in concurrent scenarios and when data sharing is involved.\n\n## Lazy Evaluation\nSome `lo` operations implement lazy evaluation patterns for improved performance with large datasets.\n\n## Memory Efficiency\nConsiderations for memory usage when choosing between immutable and mutable operations. Mutable operations can be more memory efficient but less safe in concurrent scenarios and when data sharing is involved.\n\n## Concurrency Safety\nHow different operations behave in concurrent contexts and thread safety guarantees.\n"
  },
  {
    "path": "docs/docs/iter/_category_.json",
    "content": "{\n  \"label\": \"🔄 Iterator\",\n  \"position\": 2,\n  \"link\": {\n    \"type\": \"generated-index\",\n    \"description\": \"Manipulate iterators over slices, maps, and channels\"\n  }\n}"
  },
  {
    "path": "docs/docs/iter/channel.md",
    "content": "---\ntitle: Channel\ndescription: Iterate over channel and perform transformations\nsidebar_position: 30\nhide_table_of_contents: true\n---\n\n:::warning Help improve this documentation\nThis documentation is still new and evolving. If you spot any mistakes, unclear explanations, or missing details, please [open an issue](https://github.com/samber/lo/issues).\n\nYour feedback helps us improve!\n:::\n\n#\n## Iterator - Channel helpers\n\nThis page lists all operations on channels, available in the `it` lo sub-package.\n\nimport HelperList from '@site/plugins/helpers-pages/components/HelperList';\n\n<HelperList \n  category=\"it\"\n  subCategory=\"channel\"\n/>\n"
  },
  {
    "path": "docs/docs/iter/find.md",
    "content": "---\ntitle: Find\ndescription: Iterate over a collection and find element(s)\nsidebar_position: 50\nhide_table_of_contents: true\n---\n\n:::warning Help improve this documentation\nThis documentation is still new and evolving. If you spot any mistakes, unclear explanations, or missing details, please [open an issue](https://github.com/samber/lo/issues).\n\nYour feedback helps us improve!\n:::\n\n#\n## Iterator - Find helpers\n\nThis page lists all search helpers, available in the `it` lo sub-package.\n\nimport HelperList from '@site/plugins/helpers-pages/components/HelperList';\n\n<HelperList \n  category=\"it\"\n  subCategory=\"find\"\n/>\n"
  },
  {
    "path": "docs/docs/iter/intersect.md",
    "content": "---\ntitle: Intersect\ndescription: Iterate over a collection and find similar items\nsidebar_position: 60\nhide_table_of_contents: true\n---\n\n:::warning Help improve this documentation\nThis documentation is still new and evolving. If you spot any mistakes, unclear explanations, or missing details, please [open an issue](https://github.com/samber/lo/issues).\n\nYour feedback helps us improve!\n:::\n\n#\n## Iterator - Intersection helpers\n\nThis page lists all intersection helpers, available in the `it` lo sub-package.\n\nimport HelperList from '@site/plugins/helpers-pages/components/HelperList';\n\n<HelperList \n  category=\"it\"\n  subCategory=\"intersect\"\n/>\n"
  },
  {
    "path": "docs/docs/iter/map.md",
    "content": "---\ntitle: Map\ndescription: Iterate over maps and perform transformations\nsidebar_position: 10\nhide_table_of_contents: true\n---\n\n:::warning Help improve this documentation\nThis documentation is still new and evolving. If you spot any mistakes, unclear explanations, or missing details, please [open an issue](https://github.com/samber/lo/issues).\n\nYour feedback helps us improve!\n:::\n\n#\n## Iterator - Map helpers\n\nThis page lists all operations on maps, available in the `it` lo sub-package.\n\nimport HelperList from '@site/plugins/helpers-pages/components/HelperList';\n\n<HelperList \n  category=\"it\"\n  subCategory=\"map\"\n/>\n"
  },
  {
    "path": "docs/docs/iter/sequence.md",
    "content": "---\ntitle: Sequence\ndescription: Iterate over sequences and perform transformations\nsidebar_position: 20\nhide_table_of_contents: true\n---\n\n:::warning Help improve this documentation\nThis documentation is still new and evolving. If you spot any mistakes, unclear explanations, or missing details, please [open an issue](https://github.com/samber/lo/issues).\n\nYour feedback helps us improve!\n:::\n\n#\n## Iterator - Sequence helpers\n\nThis page lists all operations on sequences, available in the `it` lo sub-package.\n\nimport HelperList from '@site/plugins/helpers-pages/components/HelperList';\n\n<HelperList \n  category=\"it\"\n  subCategory=\"sequence\"\n/>\n"
  },
  {
    "path": "docs/docs/iter/slice.md",
    "content": "---\ntitle: Slice\ndescription: Iterate over slices and perform transformations\nsidebar_position: 0\nhide_table_of_contents: true\n---\n\n:::warning Help improve this documentation\nThis documentation is still new and evolving. If you spot any mistakes, unclear explanations, or missing details, please [open an issue](https://github.com/samber/lo/issues).\n\nYour feedback helps us improve!\n:::\n\n#\n## Iterator - Map helpers\n\nThis page lists all operations on slice, available in the `it` lo sub-package.\n\nimport HelperList from '@site/plugins/helpers-pages/components/HelperList';\n\n<HelperList \n  category=\"it\"\n  subCategory=\"slice\"\n/>\n"
  },
  {
    "path": "docs/docs/iter/string.md",
    "content": "---\ntitle: String\ndescription: Perform transformations on strings\nsidebar_position: 40\nhide_table_of_contents: true\n---\n\n:::warning Help improve this documentation\nThis documentation is still new and evolving. If you spot any mistakes, unclear explanations, or missing details, please [open an issue](https://github.com/samber/lo/issues).\n\nYour feedback helps us improve!\n:::\n\n#\n## Iterator - String helpers\n\nThis page lists all operations on strings, available in the `it` lo sub-package.\n\nimport HelperList from '@site/plugins/helpers-pages/components/HelperList';\n\n<HelperList \n  category=\"it\"\n  subCategory=\"string\"\n/>\n"
  },
  {
    "path": "docs/docs/iter/tuple.md",
    "content": "---\ntitle: Tuple\ndescription: Manipulate multiple items in a single variable\nsidebar_position: 70\nhide_table_of_contents: true\n---\n\n:::warning Help improve this documentation\nThis documentation is still new and evolving. If you spot any mistakes, unclear explanations, or missing details, please [open an issue](https://github.com/samber/lo/issues).\n\nYour feedback helps us improve!\n:::\n\n#\n## Iterator - Tuple helpers\n\nThis page lists all tuple operations, available in the `it` lo sub-package.\n\nimport HelperList from '@site/plugins/helpers-pages/components/HelperList';\n\n<HelperList \n  category=\"it\"\n  subCategory=\"tuple\"\n/>\n"
  },
  {
    "path": "docs/docs/iter/type.md",
    "content": "---\ntitle: Type manipulation\ndescription: Perform transformations on types\nsidebar_position: 80\nhide_table_of_contents: true\n---\n\n:::warning Help improve this documentation\nThis documentation is still new and evolving. If you spot any mistakes, unclear explanations, or missing details, please [open an issue](https://github.com/samber/lo/issues).\n\nYour feedback helps us improve!\n:::\n\n#\n## Iterator - Type manipulation helpers\n\nThis page lists all type operations available in the `it` lo sub-package.\n\nimport HelperList from '@site/plugins/helpers-pages/components/HelperList';\n\n<HelperList \n  category=\"it\"\n  subCategory=\"type\"\n/>\n"
  },
  {
    "path": "docs/docs/mutable/_category_.json",
    "content": "{\n  \"label\": \"👣 Mutable\",\n  \"position\": 3,\n  \"link\": {\n    \"type\": \"generated-index\",\n    \"description\": \"Mutable operations on slices, maps, and channels\"\n  }\n}"
  },
  {
    "path": "docs/docs/mutable/slice.md",
    "content": "---\ntitle: Slice\ndescription: Update slices in place\nsidebar_position: 0\n---\n\n:::warning Help improve this documentation\nThis documentation is still new and evolving. If you spot any mistakes, unclear explanations, or missing details, please [open an issue](https://github.com/samber/lo/issues).\n\nYour feedback helps us improve!\n:::\n\n#\n## Mutable - Slice helpers\n\nThis page lists all operations on slices, available in the `mutable` lo sub-package.\n\nimport HelperList from '@site/plugins/helpers-pages/components/HelperList';\n\n<HelperList \n  category=\"mutable\"\n  subCategory=\"slice\"\n/>\n"
  },
  {
    "path": "docs/docs/parallel/_category_.json",
    "content": "{\n  \"label\": \"🏎️ Parallel\",\n  \"position\": 4,\n  \"link\": {\n    \"type\": \"generated-index\",\n    \"description\": \"Parallel processing of slices, maps, and channels\"\n  }\n}"
  },
  {
    "path": "docs/docs/parallel/slice.md",
    "content": "---\ntitle: Slice\ndescription: Loop over slices and perform transformations in parallel\nsidebar_position: 0\nhide_table_of_contents: true\n---\n\n:::warning Help improve this documentation\nThis documentation is still new and evolving. If you spot any mistakes, unclear explanations, or missing details, please [open an issue](https://github.com/samber/lo/issues).\n\nYour feedback helps us improve!\n:::\n\n#\n## Parallel - Slice helpers\n\nThis page lists all operations on slices, available in the `parallel` lo sub-package.\n\nimport HelperList from '@site/plugins/helpers-pages/components/HelperList';\n\n<HelperList \n  category=\"parallel\"\n  subCategory=\"slice\"\n/>\n"
  },
  {
    "path": "docs/docusaurus.config.ts",
    "content": "import {themes as prismThemes} from 'prism-react-renderer';\nimport type {Config} from '@docusaurus/types';\nimport type * as Preset from '@docusaurus/preset-classic';\n\n// This runs in Node.js - Don't use client-side code here (browser APIs, JSX...)\n\nconst config: Config = {\n  title: 'lo',\n  tagline: 'A reusable utility library for Go: slices, maps, and more',\n  favicon: 'img/favicon.ico',\n\n  // Future flags, see https://docusaurus.io/docs/api/docusaurus-config#future\n  future: {\n    v4: {\n      removeLegacyPostBuildHeadAttribute: true,\n      useCssCascadeLayers: true,\n    },\n    experimental_faster: {\n      swcJsLoader: true,\n      swcJsMinimizer: true,\n      swcHtmlMinimizer: true,\n      lightningCssMinimizer: true,\n      rspackBundler: true,\n      rspackPersistentCache: true,\n      ssgWorkerThreads: true,\n      mdxCrossCompilerCache: true,\n    },\n    experimental_storage: {\n      type: 'localStorage',\n      namespace: true,\n    },\n  },\n\n  // Set the production url of your site here\n  url: 'https://ro.samber.dev',\n  // Set the /<baseUrl>/ pathname under which your site is served\n  // For GitHub pages deployment, it is often '/<projectName>/'\n  baseUrl: '/',\n\n  // GitHub pages deployment config.\n  // If you aren't using GitHub pages, you don't need these.\n  organizationName: 'samber', // Usually your GitHub org/user name.\n  projectName: 'lo', // Usually your repo name.\n\n  onBrokenLinks: 'throw',\n  onBrokenMarkdownLinks: 'throw',\n  onBrokenAnchors: 'throw',\n\n  markdown: {\n    anchors: {\n      maintainCase: true,\n    },\n    mermaid: true,\n  },\n\n  // Storage configuration for better performance\n  staticDirectories: ['static'],\n\n  // Optional: Enable hash router for offline support (experimental)\n  // Uncomment if you need offline browsing capability\n  // router: 'hash',\n  \n  // Future-proofing configurations\n  clientModules: [\n    require.resolve('./src/theme/prism-include-languages.js'),\n  ],\n\n  // Even if you don't use internationalization, you can use this field to set\n  // useful metadata like html lang. For example, if your site is Chinese, you\n  // may want to replace \"en\" with \"zh-Hans\".\n  i18n: {\n    defaultLocale: 'en',\n    locales: ['en'],\n  },\n\n  headTags: [\n    // DNS prefetch for better performance\n    {\n      tagName: 'link',\n      attributes: {\n        rel: 'dns-prefetch',\n        href: '//fonts.googleapis.com',\n      },\n    },\n    {\n      tagName: 'link',\n      attributes: {\n        rel: 'preconnect',\n        href: 'https://fonts.gstatic.com',\n        crossorigin: 'anonymous',\n      },\n    },\n    {\n      tagName: 'meta',\n      attributes: {\n        name: 'keywords',\n        content: 'go, golang, lo, slices, maps, strings, channels, functions, helpers, concurrency, error handling, reusable, utility, framework, library, samber',\n      },\n    },\n    {\n      tagName: 'meta',\n      attributes: {\n        property: 'og:image',\n        content: 'https://lo.samber.dev/img/cover.png',\n      },\n    },\n    {\n      tagName: 'meta',\n      attributes: {\n        name: 'twitter:card',\n        content: 'summary_large_image',\n      },\n    },\n    {\n      tagName: 'meta',\n      attributes: {\n        name: 'twitter:image',\n        content: 'https://lo.samber.dev/img/cover.png',\n      },\n    },\n    {\n      tagName: 'meta',\n      attributes: {\n        name: 'twitter:creator',\n        content: '@samuelberthe',\n      },\n    },\n    {\n      tagName: 'link',\n      attributes: {\n        rel: 'canonical',\n        href: 'https://lo.samber.dev',\n      },\n    },\n  ],\n\n  customFields: {\n    sponsors: [\n      {\n        name: 'DBOS',\n        url: 'https://www.dbos.dev/?utm_campaign=gh-smbr',\n        title: 'DBOS - Durable workflow orchestration library for Go',\n        logo_light: '/img/sponsors/dbos-black.png',\n        logo_dark: '/img/sponsors/dbos-white.png',\n      },\n    ],\n  },\n\n  presets: [\n    [\n      'classic',\n      {\n        docs: {\n          sidebarPath: './sidebars.ts',\n          // Please change this to your repo.\n          // Remove this to remove the \"edit this page\" links.\n          editUrl:\n          'https://github.com/samber/lo/tree/master/docs/',\n          showLastUpdateAuthor: true,\n          showLastUpdateTime: true,\n          // Enhanced docs features from 3.8+\n          breadcrumbs: true,\n          sidebarCollapsed: false,\n          numberPrefixParser: false,\n          // Enable admonitions\n          admonitions: {\n            keywords: ['note', 'tip', 'info', 'danger', 'warning'],\n            extendDefaults: true,\n          },\n          // Enhanced markdown features\n          remarkPlugins: [],\n          rehypePlugins: [],\n        },      \n        sitemap: {\n          lastmod: 'date',\n          changefreq: 'weekly',\n          priority: 0.7,\n          ignorePatterns: ['/tags/**'],\n          filename: 'sitemap.xml',\n          // Enhanced sitemap features from 3.8+\n          createSitemapItems: async (params) => {\n            const {defaultCreateSitemapItems, ...rest} = params ;\n            const items = await defaultCreateSitemapItems(rest);\n            // Add custom priority for specific pages\n            return items.map((item) => {\n              if (item.url.includes('/docs/getting-started')) {\n                return {...item, priority: 1.0};\n              }\n              if (item.url.includes('/docs/')) {\n                return {...item, priority: 0.8};\n              }\n              return item;\n            });\n          },\n        },\n        theme: {\n          customCss: './src/css/custom.css',\n        },\n        gtag: {\n          trackingID: 'G-VVXXV8747F',\n          anonymizeIP: false,\n        },\n      } satisfies Preset.Options,\n    ],\n  ],\n\n  themeConfig: {\n    // Replace with your project's social card\n    image: 'img/cover.png',\n    colorMode: {\n      defaultMode: 'light',\n      disableSwitch: false,\n      respectPrefersColorScheme: true,\n    },\n\n    // Mermaid configuration\n    mermaid: {\n      theme: {light: 'neutral', dark: 'dark'},\n      options: {\n        maxTextSize: 50000,\n      },\n    },\n    \n    // Enhanced metadata\n    metadata: [\n      {name: 'og:type', content: 'website'},\n    ],\n\n    navbar: {\n      title: '🏎️ samber/lo',\n      logo: {\n        alt: 'lo - Reusable utility library for Go',\n        src: 'img/icon.png',\n      },\n      items: [\n        {\n          type: 'docSidebar',\n          sidebarId: 'docSidebar',\n          position: 'left',\n          label: 'Doc',\n        }, \n        {\n          to: 'https://pkg.go.dev/github.com/samber/lo',\n          label: 'GoDoc',\n          position: 'left',\n        },\n        {\n          to: 'community',\n          label: 'Community',\n          position: 'left',\n        },\n        {\n          to: 'https://github.com/samber/lo/releases',\n          label: 'Changelog',\n          position: 'right',\n        },\n        {\n          to: 'https://github.com/sponsors/samber',\n          label: '💖 Sponsor',\n          position: 'right',\n        },\n        {\n          href: 'https://github.com/samber/lo',\n          // label: 'GitHub',\n          position: 'right',\n          className: 'header-github-link',\n          'aria-label': 'GitHub repository',\n        },\n        {\n          type: 'search',\n          position: 'right',\n        },\n      ],\n    },\n    footer: {\n      style: 'dark',\n      links: [\n        {\n          title: 'Project',\n          items: [\n            {\n              label: 'Documentation',\n              to: '/docs/getting-started',\n            },\n            {\n              label: 'Changelog',\n              to: 'https://github.com/samber/lo/releases',\n            },\n            {\n              label: 'Godoc',\n              to: 'https://pkg.go.dev/github.com/samber/lo',\n            },\n            {\n              label: 'License',\n              to: 'https://github.com/samber/lo/blob/master/LICENSE',\n            },\n            {\n              label: '💖 Sponsor',\n              to: 'https://github.com/sponsors/samber',\n            },\n          ],\n        },\n        {\n          title: 'Community',\n          items: [\n            {\n              label: 'New issue',\n              to: 'https://github.com/samber/lo/issues',\n            },\n            {\n              label: 'GitHub',\n              to: 'https://github.com/samber/lo',\n            },\n            {\n              label: 'Stack Overflow',\n              to: 'https://stackoverflow.com/search?q=samber+lo',\n            },\n            {\n              label: 'Twitter',\n              to: 'https://twitter.com/samuelberthe',\n            },\n            {\n              label: 'Substack',\n              to: 'https://samuelberthe.substack.com',\n            },\n          ],\n        },\n      ],\n      copyright: `Copyright © ${new Date().getFullYear()} lo.`,\n    },\n    prism: {\n      theme: prismThemes.github,\n      darkTheme: prismThemes.dracula,\n      defaultLanguage: 'go',\n      additionalLanguages: ['bash', 'diff', 'json', 'yaml', 'go'],\n      magicComments: [\n        {\n          className: 'theme-code-block-highlighted-line',\n          line: 'highlight-next-line',\n          block: {start: 'highlight-start', end: 'highlight-end'},\n        },\n        {\n          className: 'code-block-error-line',\n          line: 'error-next-line',\n          block: {start: 'error-start', end: 'error-end'},\n        },\n      ],\n    },\n    algolia: {\n      appId: 'XKJFLJJWS2',\n      // bearer:disable javascript_lang_hardcoded_secret\n      apiKey: 'a1c30d9a943ef77d4cd26ac3aca68be7',\n      externalUrlRegex: 'lo\\\\.samber\\\\.dev',\n      indexName: 'lo.samber.dev',\n      contextualSearch: true,\n      searchParameters: {\n        // facetFilters: ['type:lvl1'],\n      },\n      searchPagePath: 'search',\n      // Enhanced search features from 3.8+\n      insights: true,\n    },\n  } satisfies Preset.ThemeConfig,\n\n  themes: ['@docusaurus/theme-mermaid'],\n  \n  plugins: [\n    // Add ideal image plugin for better image optimization\n    [\n      '@docusaurus/plugin-ideal-image',\n      {\n        quality: 70,\n        max: 1030,\n        min: 640,\n        steps: 2,\n        disableInDev: false,\n      },\n    ],\n    [\n      'vercel-analytics',\n      {\n        debug: true,\n        mode: 'auto',\n      },\n    ],\n    // Custom plugin to generate helper category pages from data markdown\n    [\n      require.resolve('./plugins/helpers-pages'),\n      {},\n    ],\n  ],\n};\n\nexport default config;\n"
  },
  {
    "path": "docs/package.json",
    "content": "{\n  \"name\": \"lo\",\n  \"version\": \"0.0.0\",\n  \"private\": true,\n  \"scripts\": {\n    \"docusaurus\": \"docusaurus\",\n    \"start\": \"docusaurus start\",\n    \"build\": \"docusaurus build\",\n    \"swizzle\": \"docusaurus swizzle\",\n    \"deploy\": \"docusaurus deploy\",\n    \"clear\": \"docusaurus clear\",\n    \"serve\": \"docusaurus serve\",\n    \"write-translations\": \"docusaurus write-translations\",\n    \"write-heading-ids\": \"docusaurus write-heading-ids\",\n    \"typecheck\": \"tsc\",\n    \"sync-function-signatures\": \"node ./scripts/sync-function-signatures.js\",\n    \"check-function-signatures\": \"node ./scripts/sync-function-signatures.js --check\",\n    \"check-cross-references\": \"node ./scripts/check-cross-references.js\",\n    \"check-duplicates-in-category\": \"node ./scripts/check-duplicates-in-category.js\",\n    \"check-filename-matches-frontmatter\": \"node ./scripts/check-filename-matches-frontmatter.js\",\n    \"check-similar-exists\": \"node ./scripts/check-similar-exists.js\",\n    \"check-similar-keys-exist-in-directory\": \"node ./scripts/check-similar-keys-exist-in-directory.js\"\n  },\n  \"dependencies\": {\n    \"@docusaurus/core\": \"3.9.1\",\n    \"@docusaurus/faster\": \"^3.9.1\",\n    \"@docusaurus/plugin-css-cascade-layers\": \"^3.9.1\",\n    \"@docusaurus/plugin-ideal-image\": \"^3.9.1\",\n    \"@docusaurus/plugin-svgr\": \"^3.9.1\",\n    \"@docusaurus/plugin-vercel-analytics\": \"^3.9.1\",\n    \"@docusaurus/preset-classic\": \"3.9.1\",\n    \"@docusaurus/theme-mermaid\": \"^3.9.1\",\n    \"@mdx-js/react\": \"^3.0.0\",\n    \"@mermaid-js/layout-elk\": \"^0.1.9\",\n    \"classnames\": \"^2.3.2\",\n    \"clsx\": \"^2.0.0\",\n    \"marked\": \"^17.0.1\",\n    \"prism-react-renderer\": \"^2.3.0\",\n    \"prismjs\": \"^1.29.0\",\n    \"react\": \"^19.0.0\",\n    \"react-dom\": \"^19.0.0\"\n  },\n  \"devDependencies\": {\n    \"@docusaurus/module-type-aliases\": \"3.9.1\",\n    \"@docusaurus/tsconfig\": \"3.9.1\",\n    \"@docusaurus/types\": \"3.9.1\",\n    \"typescript\": \"~5.9.3\"\n  },\n  \"browserslist\": {\n    \"production\": [\n      \">0.5%\",\n      \"not dead\",\n      \"not op_mini all\"\n    ],\n    \"development\": [\n      \"last 3 chrome version\",\n      \"last 3 firefox version\",\n      \"last 5 safari version\"\n    ]\n  },\n  \"engines\": {\n    \"node\": \">=20.0\"\n  }\n}\n"
  },
  {
    "path": "docs/plugins/helpers-pages/components/HelperCard.tsx",
    "content": "import React, { useMemo, useCallback, useState, useEffect, useRef } from 'react';\nimport { ensurePrototypeGenericsHighlighted } from './highlightPrototypeGenerics';\nimport { marked } from 'marked';\nimport type { HelperDefinition } from '../index';\nimport Heading from '@theme/Heading';\nimport CodeBlock from '@theme/CodeBlock';\nimport '../../../src/prism-include-languages.js';\n\ninterface HelperCardProps {\n  helper: HelperDefinition;\n}\n\nexport default function HelperCard({ \n  helper, \n}: HelperCardProps) {\n  // Extract function name from signature for godoc link\n  const functionName = useMemo(() => {\n    if (!helper.signatures) return '';\n    // Extract function name from signature like \"func Map[T any, R any](collection []T, transform func(T, int) R) []R\"\n    const match = helper.signatures.find(signature => signature.match(/func\\s+(\\w+)/))?.match(/func\\s+(\\w+)/);\n    return match ? match[1] : '';\n  }, [helper.signatures]);\n\n  const godocUrl = useMemo(() => {\n    let baseUrl = 'https://pkg.go.dev/github.com/samber/lo';\n    switch (helper.category) {\n      case 'core':\n        baseUrl = 'https://pkg.go.dev/github.com/samber/lo';\n        break;\n      case 'mutable':\n        baseUrl = 'https://pkg.go.dev/github.com/samber/lo/mutable';\n        break;\n      case 'parallel':\n        baseUrl = 'https://pkg.go.dev/github.com/samber/lo/parallel';\n        break;\n      // case 'it':\n      //   baseUrl = 'https://pkg.go.dev/github.com/samber/lo/it';\n      //   break;\n    }\n\n    if (!functionName) return '';\n    return `${baseUrl}#${functionName}`;\n  }, [functionName]);\n\n  const sourceRef = useMemo(() => {\n    return `https://github.com/samber/lo/blob/master/${helper.sourceRef}`;\n  }, [helper.sourceRef]);\n\n  const renderedNodes = useMemo(() => {\n    marked.setOptions({\n      gfm: true,\n      breaks: true,\n    });\n    const tokens = marked.lexer(helper.content || '');\n\n    const elements: React.ReactNode[] = [];\n    let pendingTokens: any[] = [];\n\n    const flushPending = () => {\n      if (pendingTokens.length === 0) return;\n      const html = (marked as any).parser(pendingTokens);\n      elements.push(\n        React.createElement('div', {\n          className: 'helper-card__markdown-chunk',\n          dangerouslySetInnerHTML: { __html: html },\n          key: `md-${elements.length}`,\n        })\n      );\n      pendingTokens = [];\n    };\n\n    for (const token of tokens as any[]) {\n      if (token.type === 'code') {\n        flushPending();\n        const lang = (token.lang || '').trim() || undefined;\n        elements.push(\n          React.createElement(CodeBlock as any, {\n            language: lang,\n            key: `code-${elements.length}`,\n            children: token.text,\n          })\n        );\n      } else {\n        pendingTokens.push(token);\n      }\n    }\n    flushPending();\n\n    return elements;\n  }, [helper.content]);\n\n  const signatures = useMemo(() => {\n    return helper.signatures.join('\\n');\n  }, [helper.signatures]);\n\n  // Post-process prototype code to colorize generic type parameters locally\n  const prototypeRowRef = useRef<HTMLDivElement>(null);\n  useEffect(() => {\n    // // Ensure highlighting even if Prism updates asynchronously\n    // const raf = requestAnimationFrame(() => {\n    //   ensurePrototypeGenericsHighlighted(prototypeRowRef.current as unknown as HTMLElement);\n    // });\n    // return () => cancelAnimationFrame(raf);\n  }, [helper.signatures]);\n\n  return (\n    <div className=\"helper-card\">\n      <div className=\"helper-card__header\">\n        {/* Heading registered in MDX ToC */}\n        <Heading as=\"h3\" id={helper.slug} className=\"helper-card__title anchor\">\n          {helper.name}\n        </Heading>\n        {/* <h3 className=\"helper-card__title\">\n          <a href={`#${helper.slug}`}>\n            {helper.name}\n          </a>\n        </h3> */}\n        <div className=\"helper-card__actions\">\n          <div className=\"helper-card__badges\">\n            <span className=\"helper-card__badge helper-card__badge--category\">\n              {helper.subCategory}\n            </span>\n            <span className=\"helper-card__badge helper-card__badge--subcategory\">\n              {helper.category}\n            </span>\n          </div>\n          {sourceRef && (\n            <a \n              href={sourceRef}\n              target=\"_blank\"\n              rel=\"noopener noreferrer\"\n              className=\"helper-card__source\"\n            >\n              🧩 Source\n            </a>\n          )}\n          {godocUrl && (\n            <a \n              href={godocUrl}\n              target=\"_blank\"\n              rel=\"noopener noreferrer\"\n              className=\"helper-card__godoc\"\n            >\n              📚 GoDoc\n            </a>\n          )}\n          {helper.playUrl && (\n            <a \n              href={helper.playUrl}\n              target=\"_blank\"\n              rel=\"noopener noreferrer\"\n              className=\"helper-card__playground\"\n            >\n              🎮 Try on Go Playground\n            </a>\n          )}\n        </div>\n      </div>\n      \n      <div className=\"helper-card__content\">\n        <div className=\"helper-card__markdown\">\n          {renderedNodes}\n        </div>\n\n        <SimilarHelpers\n          title=\"Variant\"\n          similarHelpers={helper.variantHelpers}\n          currentType={helper.category || ''}\n          currentCategory={helper.subCategory || ''}\n          currentName={helper.name || ''}\n        />\n        <SimilarHelpers\n          title=\"Similar\"\n          similarHelpers={helper.similarHelpers}\n          currentType={helper.category || ''}\n          currentCategory={helper.subCategory || ''}\n          currentName={helper.name || ''}\n        />\n      </div>\n      \n      <div className=\"helper-card__prototype\">\n        <div className=\"helper-card__prototype-row\" ref={prototypeRowRef}>\n          <span className=\"helper-card__prototype-label\">Prototype{helper.signatures.length > 1 ? 's' : ''}:</span>\n          <CodeBlock language=\"go\" className=\"helper-card__prototype-code\" children={signatures} />\n        </div>\n      </div>\n    </div>\n  );\n}\n\ntype SimilarHelpersProps = {\n  title: string;\n  similarHelpers: string[];\n  currentType: string;\n  currentCategory: string;\n  currentName: string;\n};\n\nfunction SimilarHelpers({ \n  title, \n  similarHelpers, \n  currentType,\n  currentCategory, \n  currentName,\n}: SimilarHelpersProps) {\n  const currentHelperLower = `${currentType}#${currentCategory}#${currentName}`.toLowerCase();\n  similarHelpers = similarHelpers.filter((helper) => helper != currentHelperLower);\n\n  if (similarHelpers.length === 0) {\n    return null;\n  }\n\n  return (\n    <div className=\"helper-card__similar\">\n      <div className=\"helper-card__similar-row\">\n        <span className=\"helper-card__prototype-label\">{title}:</span>\n        <div className=\"helper-card__similar-list\">\n          {similarHelpers\n            .map((originalLabel) => {\n              const parts = String(originalLabel).split('#');\n              const typeRaw = parts[0];\n              const categoryRaw = parts[1];\n              const nameRaw = parts[2];\n              const fallbackType = currentType || '';\n              const fallbackCategory = currentCategory || '';\n              const type = (typeRaw || fallbackType).toLowerCase();\n              const category = (categoryRaw || fallbackCategory).toLowerCase();\n              // Fallback for legacy 2-part labels: type#name\n              const legacyName = parts.length === 2 ? parts[1] : undefined;\n              const name = (nameRaw || legacyName || '').toLowerCase();\n              return { originalLabel, type, category, name, nameRaw };\n            })\n            .sort((a, b) => {\n              const currentTypeLower = (currentType || '').toLowerCase();\n              const aSame = a.type === currentTypeLower ? 0 : 1;\n              const bSame = b.type === currentTypeLower ? 0 : 1;\n              if (aSame !== bSame) return aSame - bSame; // same type first\n              return a.name.localeCompare(b.name);\n            })\n            .map(({ originalLabel, type, category, name, nameRaw }, index) => {\n              const currentTypeLower = (currentType || '').toLowerCase();\n              const href = `/docs/${type}/${category}#${name}`;\n              const displayName = nameRaw || name;\n              const isSameSection = type === currentTypeLower; // compare only type for label\n              return (\n                <a \n                  key={index}\n                  href={href}\n                  className=\"helper-card__similar-link\"\n                >\n                  {isSameSection ? (\n                    displayName\n                  ) : (\n                    <>\n                      <span className=\"helper-card__similar-prefix\">{type}›</span>{' '}\n                      {displayName}\n                    </>\n                  )}\n                </a>\n              );\n            })}\n        </div>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "docs/plugins/helpers-pages/components/HelperList.tsx",
    "content": "import React from 'react';\nimport HelperCard from './HelperCard';\nimport {usePluginData} from '@docusaurus/useGlobalData';\nimport type {HelperDefinition} from '../index';\nimport HelperTOC from './HelperTOC';\nimport './helper-components.css';\n\ninterface HelperListProps {\n  category: string;\n  subCategory: string;\n}\n\nexport default function HelperList({\n  category,\n  subCategory,\n}: HelperListProps) {\n  const gridStyle = {\n    marginTop: '2rem'\n  };\n\n  const data = usePluginData('helpers-pages') as {helpers: HelperDefinition[]};\n  const helpers = (data?.helpers ?? [])\n    .filter((h) => h.category === category && h.subCategory === subCategory)\n    .slice()\n    .sort((a, b) => a.position - b.position);\n\n  return (\n    <div className=\"row\">\n      <div className=\"col col--10\">\n        <ul className=\"helper-list\" style={gridStyle}>\n          {helpers.map((helper) => (\n            <li key={helper.slug}>\n              <HelperCard\n                helper={helper}\n              />\n            </li>\n          ))}\n        </ul>\n      </div>\n      <div className=\"col col--2\">\n        <HelperTOC category={category} subCategory={subCategory} />\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "docs/plugins/helpers-pages/components/HelperTOC.tsx",
    "content": "import React from 'react';\nimport {usePluginData} from '@docusaurus/useGlobalData';\nimport type {HelperDefinition} from '../index';\nimport './helper-components.css';\n\ninterface HelperTOCProps {\n  category: string;\n  subCategory: string;\n  title?: string;\n}\n\nexport default function HelperTOC({\n  category,\n  subCategory,\n  title = 'On this page',\n}: HelperTOCProps) {\n  const data = usePluginData('helpers-pages') as {helpers: HelperDefinition[]};\n  const helpers = (data?.helpers ?? [])\n    .filter((h) => h.category === category && h.subCategory === subCategory)\n    .slice()\n    .sort((a, b) => a.position - b.position);\n\n  if (helpers.length === 0) {\n    return null;\n  }\n\n  return (\n    <nav className=\"helper-toc\" aria-label=\"Page navigation\">\n      <div className=\"helper-toc__title\">{title}</div>\n      <ul className=\"helper-toc__list\">\n        {helpers.map((h) => (\n          <li key={h.slug} className=\"helper-toc__item\">\n            <a className=\"helper-toc__link\" href={`#${h.slug}`}>{h.name}</a>\n          </li>\n        ))}\n      </ul>\n    </nav>\n  );\n}\n\n\n"
  },
  {
    "path": "docs/plugins/helpers-pages/components/helper-components.css",
    "content": "/* Helper Card Styles */\n/* Theme tokens */\n:root {\n    --helper-bg: #ffffff;\n    --helper-surface: #f6f8fa;\n    --helper-border: #e1e4e8;\n    --helper-border-strong: #c8d1dc;\n    --helper-text: #24292e;\n    --helper-text-muted: #586069;\n    --helper-primary: #0366d6;\n    --helper-primary-weak: #f1f8ff;\n    --helper-success: #28a745;\n    --helper-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n    --helper-shadow-hover: 0 8px 24px rgba(140, 149, 159, 0.2);\n\n    /* Prototype color tokens (Solarized Light, extra contrast) */\n    --proto-fn: #6f5700;\n    /* deeper yellow */\n    --proto-type: #4a51a3;\n    /* deeper violet */\n    --proto-param: #157a80;\n    /* deeper cyan */\n    --proto-key: #1b5fa5;\n    /* deeper blue */\n    --proto-op: #a11d4f;\n    /* deeper magenta */\n    --proto-str: #556b00;\n    /* deeper green */\n    --proto-num: #973e12;\n    /* deeper orange */\n    --proto-punc: #36454f;\n    /* deeper base01 */\n}\n\nhtml[data-theme='dark'] {\n    --helper-bg: #0d1117;\n    --helper-surface: #161b22;\n    --helper-border: #30363d;\n    --helper-border-strong: #3d444d;\n    --helper-text: #c9d1d9;\n    --helper-text-muted: #8b949e;\n    --helper-primary: #2f81f7;\n    --helper-primary-weak: #0b1f3a;\n    --helper-success: #2ea043;\n    --helper-shadow: 0 1px 3px rgba(1, 4, 9, 0.4);\n    --helper-shadow-hover: 0 8px 24px rgba(1, 4, 9, 0.6);\n\n    /* Prototype color tokens (Solarized Dark) */\n    --proto-fn: #b58900;\n    /* yellow */\n    --proto-type: #6c71c4;\n    /* violet */\n    --proto-param: #2aa198;\n    /* cyan */\n    --proto-key: #268bd2;\n    /* blue */\n    --proto-op: #d33682;\n    /* magenta */\n    --proto-str: #859900;\n    /* green */\n    --proto-num: #cb4b16;\n    /* orange */\n    --proto-punc: #93a1a1;\n    /* base1 */\n}\n\nul.helper-list {\n    list-style: none;\n    padding: 0;\n    margin: 0;\n}\n\nul.helper-list>li {\n    list-style: none;\n    margin: 0;\n}\n\n.helper-card {\n    background: var(--helper-bg);\n    border: 1px solid var(--helper-border);\n    border-radius: 8px;\n    padding: 1.5rem;\n    margin-bottom: 1rem;\n    transition: border-color 150ms ease, box-shadow 200ms ease, transform 200ms ease;\n    box-shadow: var(--helper-shadow);\n    position: relative;\n    overflow: hidden;\n}\n\n.helper-card:hover {\n    border-color: var(--helper-primary);\n    box-shadow: var(--helper-shadow-hover);\n    transform: translateY(-2px);\n}\n\n.helper-card::before {\n    content: \"\";\n    position: absolute;\n    inset: 0;\n    background: radial-gradient(1200px 200px at -20% -10%, rgba(3, 102, 214, 0.06), transparent 40%),\n        radial-gradient(800px 200px at 120% 110%, rgba(3, 102, 214, 0.04), transparent 40%);\n    pointer-events: none;\n}\n\n.helper-card__header {\n    display: flex;\n    justify-content: space-between;\n    align-items: flex-start;\n    margin-bottom: 1rem;\n}\n\n.helper-card__title {\n    margin: 0;\n    font-size: 1.25rem;\n    font-weight: 600;\n}\n\n.helper-card__title a {\n    color: var(--helper-text);\n    text-decoration: none;\n}\n\n.helper-card__title a:hover {\n    color: var(--helper-primary);\n}\n\n.helper-card__actions {\n    display: flex;\n    align-items: center;\n    gap: 0.75rem;\n}\n\n.helper-card__badges {\n    display: flex;\n    gap: 0.5rem;\n    flex-wrap: wrap;\n}\n\n.helper-card__badge {\n    padding: 0.35rem 0.5rem;\n    border-radius: 4px;\n    font-size: 0.75rem;\n    font-weight: 500;\n    text-transform: uppercase;\n    letter-spacing: 0.5px;\n    line-height: 1;\n}\n\n.helper-card__badge--category {\n    background: var(--helper-primary-weak);\n    color: var(--helper-primary);\n    border: 1px solid var(--helper-border-strong);\n}\n\n.helper-card__badge--subcategory {\n    background: var(--helper-surface);\n    color: var(--helper-text-muted);\n    border: 1px solid var(--helper-border);\n}\n\n.helper-card__content {\n    margin-bottom: 1rem;\n}\n\n.helper-card__markdown {\n    color: var(--helper-text);\n    line-height: 1.6;\n}\n\n.helper-card__markdown p {\n    margin: 0 0 0.75rem 0;\n}\n\n.helper-card__markdown a {\n    color: var(--helper-primary);\n    text-decoration: underline;\n}\n\n.helper-card__markdown code {\n    background: var(--helper-surface);\n    border: 1px solid var(--helper-border);\n    border-radius: 4px;\n    padding: 0.1rem 0.3rem;\n    font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;\n    font-size: 0.9em;\n}\n\n.helper-card__markdown pre {\n    background: var(--helper-surface);\n    border: 1px solid var(--helper-border);\n    border-radius: 4px;\n    padding: 0.75rem;\n    overflow-x: auto;\n}\n\n.helper-card__markdown pre code {\n    border: none;\n    background: transparent;\n    padding: 0;\n}\n\n.helper-card__description {\n    color: var(--helper-text-muted);\n    margin-bottom: 1rem;\n    line-height: 1.5;\n}\n\n.helper-card__signature {\n    margin-bottom: 1rem;\n}\n\n.helper-card__signature h4 {\n    margin: 0 0 0.5rem 0;\n    font-size: 0.875rem;\n    font-weight: 600;\n    color: #24292e;\n}\n\n.helper-card__code {\n    background: var(--helper-surface);\n    border: 1px solid var(--helper-border);\n    border-radius: 4px;\n    padding: 0.75rem;\n    margin: 0;\n    font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;\n    font-size: 0.875rem;\n    line-height: 1.4;\n    overflow-x: auto;\n}\n\n.helper-card__code::-webkit-scrollbar {\n    height: 8px;\n}\n\n.helper-card__code::-webkit-scrollbar-thumb {\n    background: var(--helper-border-strong);\n    border-radius: 4px;\n}\n\n.helper-card__examples {\n    margin-bottom: 1rem;\n}\n\n.helper-card__examples h4 {\n    margin: 0 0 0.5rem 0;\n    font-size: 0.875rem;\n    font-weight: 600;\n    color: #24292e;\n}\n\n.helper-card__example {\n    margin-bottom: 0.75rem;\n}\n\n.helper-card__example h5 {\n    margin: 0 0 0.25rem 0;\n    font-size: 0.75rem;\n    font-weight: 500;\n    color: #586069;\n}\n\n.helper-card__similar {\n    margin-bottom: 1rem;\n}\n\n.helper-card__similar-row {\n    display: flex;\n    align-items: center;\n    gap: 0.5rem;\n    margin-bottom: 0.5rem;\n}\n\n.helper-card__section-head {\n    display: flex;\n    align-items: center;\n    justify-content: flex-start;\n    gap: 1rem;\n    margin-bottom: 0.5rem;\n}\n\n.helper-card__prototype-actions {\n    display: inline-flex;\n    align-items: center;\n    gap: 0.5rem;\n}\n\n.helper-card__prototype-label {\n    font-size: 0.75rem;\n    text-transform: uppercase;\n    letter-spacing: 0.5px;\n    color: var(--helper-text-muted);\n    flex: 0 0 auto;\n    margin-top: 0;\n}\n\n.helper-card__similar-list {\n    display: flex;\n    flex-wrap: wrap;\n    gap: 0.5rem;\n}\n\n/* Right-side sticky TOC */\n.helper-toc {\n    position: sticky;\n    top: calc(var(--ifm-navbar-height) + var(--ifm-toc-padding-vertical, 1rem));\n    max-height: calc(100vh - 2rem);\n    overflow: auto;\n    padding-left: 1rem;\n    border-left: 1px solid var(--ifm-toc-border-color, var(--ifm-color-emphasis-200));\n}\n\n.helper-toc__title {\n    font-weight: 600;\n    margin-bottom: 0.5rem;\n    font-size: 0.9rem;\n    color: var(--ifm-color-emphasis-700);\n}\n\n.helper-toc__list {\n    list-style: none;\n    margin: 0;\n    padding: 0;\n}\n\n.helper-toc__item {\n    margin: 0.25rem 0;\n}\n\n.helper-toc__link {\n    font-size: 0.9rem;\n    text-decoration: none;\n}\n\n.helper-card__similar-link {\n    padding: 0.25rem 0.5rem;\n    background: var(--helper-surface);\n    border: 1px solid var(--helper-border);\n    border-radius: 4px;\n    color: var(--helper-primary);\n    text-decoration: none;\n    font-size: 0.75rem;\n    transition: all 0.2s ease;\n}\n\n.helper-card__similar-link:hover {\n    background: var(--helper-primary-weak);\n    border-color: var(--helper-primary);\n}\n\n.helper-card__similar-prefix {\n    color: var(--helper-text-muted);\n}\n\n.helper-card__footer {\n    border-top: 1px solid #e1e4e8;\n    padding-top: 1rem;\n    text-align: center;\n}\n\n/* Prototype block (compact code block placed after similar helpers) */\n.helper-card__prototype {\n    margin-top: 0.25rem;\n    border-top: 1px dashed var(--helper-border);\n    padding-top: 0.75rem;\n}\n\n.helper-card__prototype-row {\n    display: flex;\n    align-items: center;\n    gap: 0.5rem;\n}\n\n.helper-card__prototype-code {\n    font-size: 0.80rem;\n    padding: 0.15rem 0.4rem;\n    border-radius: 6px;\n    margin: 0;\n    flex: 1 1 auto;\n    width: 100%;\n}\n\n/* Token colors inside prototype code only */\n.helper-card__prototype-code .token.keyword {\n    color: var(--proto-key) !important;\n}\n\n.helper-card__prototype-code .token.function {\n    color: var(--proto-fn) !important;\n    font-weight: 600;\n}\n\n.helper-card__prototype-code .token.punctuation {\n    color: var(--proto-punc) !important;\n}\n\n.helper-card__prototype-code .token.operator {\n    color: var(--proto-op) !important;\n}\n\n.helper-card__prototype-code .token.constant,\n.helper-card__prototype-code .token.number {\n    color: var(--proto-num) !important;\n}\n\n.helper-card__prototype-code .token.parameter,\n.helper-card__prototype-code .token.variable {\n    color: var(--proto-param) !important;\n}\n\n.helper-card__prototype-code .token.class-name,\n.helper-card__prototype-code .token.builtin,\n.helper-card__prototype-code .token.type,\n.helper-card__prototype-code .token.generic,\n.helper-card__prototype-code .token.type-parameter,\n.helper-card__prototype-code .token.template,\n.helper-card__prototype-code .token.namespace {\n    color: var(--proto-type) !important;\n    font-weight: 600;\n}\n\n/* Force violet for all generic type parameters in prototype block */\n.helper-card__prototype-code .token.type-parameter {\n    color: var(--proto-type) !important;\n    font-weight: 600;\n}\n\n/* Also target any spans we create for generics */\n.helper-card__prototype-code span.token.type.type-parameter {\n    color: var(--proto-type) !important;\n    font-weight: 600;\n}\n\n/* Strings mapping */\n.helper-card__prototype-code .token.string {\n    color: var(--proto-str) !important;\n}\n\n.helper-card__prototype-code code {\n    padding: 0.4rem;\n}\n\n/* Copy button */\n.helper-card__copy {\n    padding: 0.125rem 0.4rem;\n    border-radius: 4px;\n    font-size: 0.7rem;\n    line-height: 1;\n    border: 1px solid var(--helper-border);\n    background: var(--helper-surface);\n    color: var(--helper-text);\n    cursor: pointer;\n}\n\n.helper-card__copy:hover {\n    border-color: var(--helper-primary);\n}\n\n.helper-card__copy.is-copied {\n    background: #2ea043;\n    color: #ffffff;\n    border-color: #2ea043;\n}\n\n/* Reduce Prism copy button size inside prototype code blocks */\n.helper-card__prototype-code .clean-btn,\n.helper-card__prototype-code .theme-code-block-copy-button {\n    display: none !important;\n}\n\n.helper-card__godoc {\n    display: inline-flex;\n    align-items: center;\n    gap: 0.5rem;\n    padding: 0.35rem 0.5rem;\n    background: var(--helper-primary);\n    color: #ffffff;\n    text-decoration: none;\n    border-radius: 4px;\n    font-size: 0.75rem;\n    line-height: 1;\n    font-weight: 500;\n    transition: all 0.2s ease;\n    white-space: nowrap;\n    border: 1px solid transparent;\n}\n\n.helper-card__source {\n    display: inline-flex;\n    align-items: center;\n    gap: 0.5rem;\n    padding: 0.35rem 0.5rem;\n    background: rgba(168, 85, 247, 0.12);\n    /* soft purple */\n    color: #6d28d9;\n    /* purple-700 */\n    text-decoration: none;\n    border-radius: 4px;\n    font-size: 0.75rem;\n    line-height: 1;\n    font-weight: 500;\n    transition: all 0.2s ease;\n    white-space: nowrap;\n    border: 1px solid rgba(167, 139, 250, 0.6);\n}\n\n.helper-card__source:hover {\n    background: #c084fc;\n    /* purple-400 - much lighter */\n    color: #ffffff;\n    text-decoration: none;\n}\n\nhtml[data-theme='dark'] .helper-card__source {\n    background: rgba(168, 85, 247, 0.22);\n    color: #c4b5fd;\n    /* purple-300 */\n    border-color: rgba(167, 139, 250, 0.75);\n}\n\nhtml[data-theme='dark'] .helper-card__source:hover {\n    background: #c084fc;\n    color: #ffffff;\n}\n\n.helper-card__godoc:hover {\n    background: #0256cc;\n    color: #ffffff;\n    text-decoration: none;\n}\n\n.helper-card__playground {\n    display: inline-flex;\n    align-items: center;\n    gap: 0.5rem;\n    padding: 0.35rem 0.5rem;\n    background: var(--helper-success);\n    color: #ffffff;\n    text-decoration: none;\n    border-radius: 4px;\n    font-size: 0.75rem;\n    line-height: 1;\n    font-weight: 500;\n    transition: all 0.2s ease;\n    white-space: nowrap;\n    border: 1px solid transparent;\n}\n\n.helper-card__playground:hover {\n    background: #22863a;\n    color: #ffffff;\n    text-decoration: none;\n}\n\n/* Focus visibility */\n.helper-card a:focus-visible,\n.helper-card__similar-link:focus-visible,\n.helper-card__source:focus-visible,\n.helper-card__godoc:focus-visible,\n.helper-card__playground:focus-visible {\n    outline: 2px solid var(--helper-primary);\n    outline-offset: 2px;\n    border-radius: 6px;\n}\n\n/* Motion reduction */\n@media (prefers-reduced-motion: reduce) {\n\n    .helper-card,\n    .helper-card * {\n        transition: none !important;\n    }\n}"
  },
  {
    "path": "docs/plugins/helpers-pages/components/highlightPrototypeGenerics.ts",
    "content": "function getGenericTypeNamesFromText(text: string): string[] {\n  // Extract generic type names from the declaration brackets\n  const bracketMatch = text.match(/\\[([^\\]]+)\\]/);\n  if (!bracketMatch) return [];\n  const content = bracketMatch[1];\n  \n  // Split by commas and extract type names (before constraints like \"any\", \"~[]T\", etc.)\n  const names = content\n    .split(',')\n    .map(s => s.trim())\n    .map(s => (s.match(/^([A-Z][A-Za-z0-9_]*)\\b/) || [])[1])\n    .filter(Boolean) as string[];\n\n  // Also look for any other capitalized identifiers that might be generic types\n  // This catches cases where generics are used as types throughout the signature\n  const allCapsIdentifiers = text.match(/\\b([A-Z][A-Za-z0-9_]*)\\b/g) || [];\n  const additionalNames = allCapsIdentifiers.filter(name => \n    !['func', 'any', 'bool', 'int', 'string', 'float', 'byte', 'rune'].includes(name) &&\n    !name.match(/^[A-Z][a-z]+$/) // Exclude function names\n  );\n  \n  return Array.from(new Set([...names, ...additionalNames]));\n}\n\nexport function highlightPrototypeGenerics(container: HTMLElement | null): boolean {\n  if (!container) return false;\n  const codeEl = container.querySelector('.helper-card__prototype-code code');\n  if (!codeEl) return false;\n\n  // Avoid double-processing\n  if ((codeEl as HTMLElement).dataset.__genericsEnhanced === '1') return true;\n\n  const textContent = codeEl.textContent || '';\n  const genericNames = getGenericTypeNamesFromText(textContent);\n  \n  // Built-in types to color like other types\n  const builtinTypes = [\n    'bool','string','byte','rune','error',\n    'int','int8','int16','int32','int64',\n    'uint','uint8','uint16','uint32','uint64','uintptr',\n    'float32','float64','complex64','complex128'\n  ];\n  const names = Array.from(new Set([...genericNames, ...builtinTypes]));\n  if (names.length === 0) return false;\n\n  // Simple approach: replace the entire content with highlighted version\n  let newHtml = textContent;\n  const pattern = new RegExp(`\\\\b(${names.join('|')})\\\\b`, 'g');\n  newHtml = newHtml.replace(pattern, '<span class=\"token type type-parameter\">$1</span>');\n\n  if (newHtml !== textContent) {\n    codeEl.innerHTML = newHtml;\n    (codeEl as HTMLElement).dataset.__genericsEnhanced = '1';\n    return true;\n  }\n\n  return false;\n}\n\nexport function ensurePrototypeGenericsHighlighted(container: HTMLElement | null) {\n  if (!container) return;\n\n  // Try immediately\n  if (highlightPrototypeGenerics(container)) return;\n\n  // Try on next animation frame\n  requestAnimationFrame(() => {\n    if (highlightPrototypeGenerics(container)) return;\n    \n    // Try with a small delay\n    setTimeout(() => highlightPrototypeGenerics(container), 50);\n  });\n}"
  },
  {
    "path": "docs/plugins/helpers-pages/index.ts",
    "content": "import fs from 'fs';\nimport path from 'path';\nimport matter from 'gray-matter';\nimport type {LoadContext, Plugin} from '@docusaurus/types';\n\ntype HelperFrontMatter = {\n  name: string;\n  slug: string;\n  sourceRef: string;\n  category: 'core' | 'mutable' | 'parallel';\n  subCategory: 'slice'\n    | 'map'\n    | 'channel'\n    | 'string'\n    | 'function'\n    | 'find'\n    | 'condition'\n    | 'intersect'\n    | 'type'\n    | 'tuple'\n    | 'math'\n    | 'retry'\n    | 'error-handling'\n    | 'concurrency'\n    | 'time';\n  signatures: string[];\n  playUrl?: string;\n  variantHelpers: string[];\n  similarHelpers: string[];\n  position?: number;\n};\n\nexport type HelperDefinition = HelperFrontMatter & {\n  content: string;\n  filePath: string;\n};\n\nfunction readAllHelperMarkdownFiles(dataDir: string): HelperDefinition[] {\n  if (!fs.existsSync(dataDir)) {\n    return [];\n  }\n  const entries = fs.readdirSync(dataDir, {withFileTypes: true});\n  const mdFiles = entries.filter((e) => e.isFile() && e.name.endsWith('.md')).map((e) => path.join(dataDir, e.name));\n\n  const items: HelperDefinition[] = [];\n  for (const filePath of mdFiles) {\n    const raw = fs.readFileSync(filePath, 'utf8');\n    const {data, content} = matter(raw);\n    const fm = data as Partial<HelperFrontMatter>;\n    if (!fm.name || !fm.slug || !fm.category || !fm.subCategory) {\n      continue;\n    }\n    items.push({\n      name: fm.name,\n      slug: fm.slug,\n      sourceRef: fm.sourceRef,\n      category: fm.category,\n      subCategory: fm.subCategory,\n      signatures: fm.signatures,\n      playUrl: fm.playUrl,\n      variantHelpers: Array.isArray(fm.variantHelpers) ? (fm.variantHelpers as string[]) : [],\n      similarHelpers: Array.isArray(fm.similarHelpers) ? (fm.similarHelpers as string[]) : [],\n      position: typeof fm.position === 'number' ? fm.position : 9999,\n      content,\n      filePath,\n    } as HelperDefinition);\n  }\n  // stable sort within category/subcategory\n  items.sort((a, b) => {\n    if (a.category !== b.category) return a.category.localeCompare(b.category);\n    if (a.subCategory !== b.subCategory) return a.subCategory.localeCompare(b.subCategory);\n    if ((a.position ?? 9999) !== (b.position ?? 9999)) return (a.position ?? 9999) - (b.position ?? 9999);\n    return a.name.localeCompare(b.name);\n  });\n  return items;\n}\n\nexport default function pluginHelpersPages(context: LoadContext): Plugin<void> {\n  let helpersCache: HelperDefinition[] = [];\n  return {\n    name: 'helpers-pages',\n\n    async loadContent() {\n      const dataDir = path.resolve(context.siteDir, 'data');\n      helpersCache = readAllHelperMarkdownFiles(dataDir);\n    },\n\n    async contentLoaded({content, actions}) {\n      const {setGlobalData} = actions as any;\n      setGlobalData({helpers: helpersCache});\n    },\n  };\n}\n\n  "
  },
  {
    "path": "docs/scripts/check-cross-references.js",
    "content": "#!/usr/bin/env node\nconst path = require('path');\nconst { loadHelpers } = require('./utils');\n\nconst dataDir = process.argv[2] || path.join(__dirname, '..', 'data');\nconst { helpers, byFullKey } = loadHelpers(dataDir);\n\nlet hasError = false;\n\nhelpers.forEach((h) => {\n  const thisKey = `${h.category}#${h.subCategory}#${h.name}`;\n  (h.similarHelpers || []).forEach((ref) => {\n    const other = byFullKey.get(ref);\n    if (!other) return; // Existence is checked by another script\n    const otherHasBackRef = (other.similarHelpers || []).includes(thisKey);\n    if (!otherHasBackRef) {\n      hasError = true;\n      console.error(`Cross-ref missing: ${h.fileName} -> ${ref} but not reciprocated.`);\n    }\n  });\n});\n\nif (hasError) process.exit(1);\nconsole.log('OK: all similarHelpers are reciprocal.');\n"
  },
  {
    "path": "docs/scripts/check-duplicates-in-category.js",
    "content": "#!/usr/bin/env node\nconst path = require('path');\nconst { loadHelpers } = require('./utils');\n\nconst dataDir = process.argv[2] || path.join(__dirname, '..', 'data');\nconst { byCategoryName } = loadHelpers(dataDir);\n\nlet hasError = false;\nfor (const [key, list] of byCategoryName.entries()) {\n  if (list.length > 1) {\n    hasError = true;\n    const files = list.map((h) => h.fileName).join(', ');\n    console.error(`Duplicate helper in category detected for ${key}: ${files}`);\n  }\n}\n\nif (hasError) process.exit(1);\nconsole.log('OK: no duplicate helpers within categories.');\n\n"
  },
  {
    "path": "docs/scripts/check-filename-matches-frontmatter.js",
    "content": "#!/usr/bin/env node\nconst path = require('path');\nconst { loadHelpers, expectedFileName } = require('./utils');\n\nconst dataDir = process.argv[2] || path.join(__dirname, '..', 'data');\nconst { helpers } = loadHelpers(dataDir);\n\nlet hasError = false;\nhelpers.forEach((h) => {\n  const expected = expectedFileName(h);\n  if (!expected) {\n    hasError = true;\n    console.error(`Invalid or missing frontmatter (category/slug) in ${h.fileName}`);\n    return;\n  }\n  if (h.fileName !== expected) {\n    hasError = true;\n    console.error(`Filename mismatch for ${h.fileName}, expected ${expected}`);\n  }\n});\n\nif (hasError) process.exit(1);\nconsole.log('OK: all filenames match category and slug.');\n\n"
  },
  {
    "path": "docs/scripts/check-function-signatures.js",
    "content": "#!/usr/bin/env node\n\nconst fs = require('fs');\nconst path = require('path');\nconst readline = require('readline');\nconst { listMarkdownFiles, parseFrontmatter } = require('./utils');\n\nconst repoRoot = path.resolve(__dirname, '..', '..');\nconst dataDir = path.resolve(__dirname, '..', 'data');\n\nfunction readFile(filePath) {\n  return fs.readFileSync(filePath, 'utf8');\n}\n\nfunction* walkGoFiles(dir, excludeDirs = new Set()) {\n  const entries = fs.readdirSync(dir, { withFileTypes: true });\n  for (const entry of entries) {\n    if (entry.name.startsWith('.')) continue;\n    const abs = path.join(dir, entry.name);\n    const rel = path.relative(repoRoot, abs);\n    if (entry.isDirectory()) {\n      if (excludeDirs.has(entry.name)) continue;\n      yield* walkGoFiles(abs, excludeDirs);\n    } else if (entry.isFile() && entry.name.endsWith('.go')) {\n      // skip tests\n      if (entry.name.endsWith('_test.go')) continue;\n      // skip docs/ directory\n      if (rel.split(path.sep)[0] === 'docs') continue;\n      yield abs;\n    }\n  }\n}\n\nfunction buildFunctionRegex(name) {\n  // Matches: func Name[...]( or func Name(\n  const escaped = name.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n  return new RegExp('^func\\\\s+' + escaped + '(?:\\\\(|\\\\[)', '');\n}\n\nasync function findFunctionDeclarations(name, preferredPathHint) {\n  const fnRegex = buildFunctionRegex(name);\n  const hits = [];\n\n  // Prefer hinted file if provided\n  if (preferredPathHint) {\n    const hintedAbs = path.resolve(repoRoot, preferredPathHint);\n    if (fs.existsSync(hintedAbs)) {\n      const hit = await scanFileForSignature(hintedAbs, fnRegex);\n      if (hit) hits.push(hit);\n    }\n  }\n\n  for (const abs of walkGoFiles(repoRoot)) {\n    const hit = await scanFileForSignature(abs, fnRegex);\n    if (hit) hits.push(hit);\n  }\n  return hits;\n}\n\nfunction stripBOM(s) {\n  return s.charCodeAt(0) === 0xfeff ? s.slice(1) : s;\n}\n\nasync function scanFileForSignature(absPath, fnRegex) {\n  const rl = readline.createInterface({\n    input: fs.createReadStream(absPath, { encoding: 'utf8' }),\n    crlfDelay: Infinity,\n  });\n  let lineNo = 0;\n  for await (const rawLine of rl) {\n    lineNo++;\n    const line = stripBOM(rawLine);\n    if (fnRegex.test(line)) {\n      // Normalize multiple spaces and tabs minimally: keep original line\n      let signature = line.trim();\n      // Remove end-of-line comments before processing trailing bracket\n      signature = signature\n        // remove line comments\n        .replace(/\\/\\/.*$/, '')\n        // remove trailing block comment\n        .replace(/\\/\\*.*?\\*\\/\\s*$/, '')\n        .trimEnd();\n\n      // Remove spaces before and after trailing opening brace, then drop it\n      signature = signature.replace(/\\s*\\{\\s*$/, '');\n      const rel = path.relative(repoRoot, absPath).replace(/\\\\/g, '/');\n      return { file: rel, line: lineNo, signature };\n    }\n  }\n  return null;\n}\n\nfunction parseSourceRefFile(sourceRef) {\n  if (!sourceRef) return null;\n  const idx = sourceRef.indexOf('#');\n  if (idx === -1) return sourceRef;\n  return sourceRef.slice(0, idx);\n}\n\nfunction normalizeSignature(signature) {\n  // Collapse all whitespace and remove spaces before '(' or '['\n  return signature\n    .replace(/\\s+/g, ' ')\n    .replace(/\\s+(\\(|\\[)/g, '$1')\n    .trim();\n}\n\nasync function main() {\n  const args = new Set(process.argv.slice(2));\n  const files = listMarkdownFiles(dataDir);\n  let issues = 0;\n\n  for (const absPath of files) {\n    const content = readFile(absPath);\n    const fm = parseFrontmatter(content) || {};\n    const name = fm.name;\n    if (!name) continue;\n\n    const hintFile = parseSourceRefFile(fm.sourceRef);\n    const hits = await findFunctionDeclarations(name, hintFile);\n    const relMd = path.relative(repoRoot, absPath).replace(/\\\\/g, '/');\n\n    if (!hits || hits.length === 0) {\n      // eslint-disable-next-line no-console\n      console.warn(`[missing-helper] ${relMd} -> name=\"${name}\"`);\n      issues++;\n      continue;\n    }\n\n    // Sort hits by file path to ensure consistent order\n    hits.sort((a, b) => a.file.localeCompare(b.file));\n\n    // Deduplicate signatures from hits (preserve first encountered formatting)\n    const seenFromHits = new Set();\n    const uniqueHitSignatures = [];\n    for (const hit of hits) {\n      const norm = normalizeSignature(hit.signature);\n      if (!seenFromHits.has(norm)) {\n        seenFromHits.add(norm);\n        uniqueHitSignatures.push(hit.signature);\n      }\n    }\n\n    // Existing frontmatter signatures\n    const existing = Array.isArray(fm.signatures) ? fm.signatures : [];\n    const existingNorm = existing.map(normalizeSignature);\n\n    // Report duplicate signatures within frontmatter (second and further occurrences)\n    const seenExisting = new Set();\n    for (let i = 0; i < existing.length; i++) {\n      const norm = existingNorm[i];\n      if (seenExisting.has(norm)) {\n        // eslint-disable-next-line no-console\n        console.warn(`[duplicate-signature] ${relMd} -> \"${existing[i]}\"`);\n        issues++;\n      } else {\n        seenExisting.add(norm);\n      }\n    }\n\n    // Unknown signatures (exist in frontmatter but not in code)\n    const hitsNormalized = new Set(uniqueHitSignatures.map(normalizeSignature));\n    for (const sig of existing) {\n      const norm = normalizeSignature(sig);\n      if (!hitsNormalized.has(norm)) {\n        // eslint-disable-next-line no-console\n        console.warn(`[unknown-signature] ${relMd} -> \"${sig}\"`);\n        issues++;\n      }\n    }\n\n    // Missing signatures (found in code but not listed in frontmatter)\n    const existingNormalizedSet = new Set(existingNorm);\n    for (const sig of uniqueHitSignatures) {\n      const norm = normalizeSignature(sig);\n      if (!existingNormalizedSet.has(norm)) {\n        // eslint-disable-next-line no-console\n        console.warn(`[missing-signature] ${relMd} -> \"${sig}\"`);\n        issues++;\n      }\n    }\n\n    // SourceRef verification\n    const expectedSourceRef = `${hits[0].file}#L${hits[0].line}`;\n    if (fm.sourceRef !== expectedSourceRef) {\n      // eslint-disable-next-line no-console\n      console.warn(`[sourceRef-outdated] ${relMd} -> expected=${expectedSourceRef} actual=${fm.sourceRef || '\"\"'}`);\n      issues++;\n    }\n  }\n\n  if (args.has('--check') && issues > 0) {\n    process.exitCode = 1;\n  }\n}\n\nmain().catch((err) => {\n  console.error(err);\n  process.exit(1);\n});\n\n\n"
  },
  {
    "path": "docs/scripts/check-helpers-visible-in-pages.js",
    "content": "#!/usr/bin/env node\n\nconst fs = require('fs');\nconst path = require('path');\n\n// Read all markdown files in docs/data directory\nconst dataDir = path.join(__dirname, '../data');\nconst files = fs.readdirSync(dataDir).filter(f => f.endsWith('.md'));\n\nconst combinations = new Set();\nconst coreCategories = new Set();\nconst parallelCategories = new Set();\nconst itCategories = new Set();\nconst mutableCategories = new Set();\n\n// Extract type+category combinations from each file\nfiles.forEach(file => {\n  const filePath = path.join(dataDir, file);\n  const content = fs.readFileSync(filePath, 'utf8');\n\n  const typeMatch = content.match(/^category:\\s*(.+)$/m);\n  const categoryMatch = content.match(/^subCategory:\\s*(.+)$/m);\n\n  if (typeMatch && categoryMatch) {\n    const type = typeMatch[1].trim();\n    const category = categoryMatch[1].trim();\n    const combination = `${type}|${category}`;\n\n    combinations.add(combination);\n\n    if (type === 'core') {\n      coreCategories.add(category);\n    } else if (type === 'it') {\n      itCategories.add(category);\n    } else if (type === 'mutable') {\n      mutableCategories.add(category);\n    } else if (type === 'parallel') {\n      parallelCategories.add(category);\n    } else {\n      throw new Error(`Unknown type: ${type}`);\n    }\n  }\n});\n\nconsole.log('=== TYPE+CATEGORY COMBINATIONS FOUND ===');\nArray.from(combinations).sort().forEach(comb => console.log(comb));\nconsole.log('\\n=== CORE CATEGORIES ===');\nArray.from(coreCategories).sort().forEach(cat => console.log(cat));\nconsole.log('\\n=== IT CATEGORIES ===');\nArray.from(itCategories).sort().forEach(cat => console.log(cat));\nconsole.log('\\n=== MUTABLE CATEGORIES ===');\nArray.from(mutableCategories).sort().forEach(cat => console.log(cat));\nconsole.log('\\n=== PARALLEL CATEGORIES ===');\nArray.from(parallelCategories).sort().forEach(cat => console.log(cat));\n\n// Check existing pages\nconst corePagesDir = path.join(__dirname, '../docs/core');\nconst itPagesDir = path.join(__dirname, '../docs/it');\nconst mutablePagesDir = path.join(__dirname, '../docs/mutable');\nconst parallelPagesDir = path.join(__dirname, '../docs/parallel');\n\nconst existingCorePages = new Set();\nconst existingItPages = new Set();\nconst existingMutablePages = new Set();\nconst existingParallelPages = new Set();\n\nif (fs.existsSync(corePagesDir)) {\n  fs.readdirSync(corePagesDir)\n    .filter(f => f.endsWith('.md'))\n    .forEach(f => existingCorePages.add(f.replace('.md', '')));\n}\nif (fs.existsSync(itPagesDir)) {\n  fs.readdirSync(itPagesDir)\n    .filter(f => f.endsWith('.md'))\n    .forEach(f => existingItPages.add(f.replace('.md', '')));\n}\nif (fs.existsSync(mutablePagesDir)) {\n  fs.readdirSync(mutablePagesDir)\n    .filter(f => f.endsWith('.md'))\n    .forEach(f => existingMutablePages.add(f.replace('.md', '')));\n}\nif (fs.existsSync(parallelPagesDir)) {\n  fs.readdirSync(parallelPagesDir)\n    .filter(f => f.endsWith('.md'))\n    .forEach(f => existingParallelPages.add(f.replace('.md', '')));\n}\n\nconsole.log('\\n=== EXISTING CORE PAGES ===');\nArray.from(existingCorePages).sort().forEach(page => console.log(page));\nconsole.log('\\n=== EXISTING IT PAGES ===');\nArray.from(existingItPages).sort().forEach(page => console.log(page));\nconsole.log('\\n=== EXISTING MUTABLE PAGES ===');\nArray.from(existingMutablePages).sort().forEach(page => console.log(page));\nconsole.log('\\n=== EXISTING PARALLEL PAGES ===');\nArray.from(existingParallelPages).sort().forEach(page => console.log(page));\n\n// Find missing pages\nconsole.log('\\n=== MISSING CORE PAGES ===');\nArray.from(coreCategories).sort().forEach(category => {\n  if (!existingCorePages.has(category)) {\n    console.log(`MISSING: core/${category}.md`);\n  }\n});\nconsole.log('\\n=== MISSING IT PAGES ===');\nArray.from(itCategories).sort().forEach(category => {\n  if (!existingItPages.has(category)) {\n    console.log(`MISSING: it/${category}.md`);\n  }\n});\nconsole.log('\\n=== MISSING MUTABLE PAGES ===');\nArray.from(mutableCategories).sort().forEach(category => {\n  if (!existingMutablePages.has(category)) {\n    console.log(`MISSING: mutable/${category}.md`);\n  }\n});\nconsole.log('\\n=== MISSING PARALLEL PAGES ===');\nArray.from(parallelCategories).sort().forEach(category => {\n  if (!existingParallelPages.has(category)) {\n    console.log(`MISSING: parallel/${category}.md`);\n  }\n});\n\n// Check for duplicates\nconsole.log('\\n=== VALIDATION RESULTS ===');\nlet hasErrors = false;\n\nArray.from(coreCategories).sort().forEach(category => {\n  if (!existingCorePages.has(category)) {\n    console.log(`❌ ERROR: Missing core page for category: ${category}`);\n    hasErrors = true;\n  }\n});\nArray.from(itCategories).sort().forEach(category => {\n  if (!existingItPages.has(category)) {\n    console.log(`❌ ERROR: Missing it page for category: ${category}`);\n    hasErrors = true;\n  }\n});\nArray.from(mutableCategories).sort().forEach(category => {\n  if (!existingMutablePages.has(category)) {\n    console.log(`❌ ERROR: Missing mutable page for category: ${category}`);\n    hasErrors = true;\n  }\n});\nArray.from(parallelCategories).sort().forEach(category => {\n  if (!existingParallelPages.has(category)) {\n    console.log(`❌ ERROR: Missing parallel page for category: ${category}`);\n    hasErrors = true;\n  }\n});\n\nif (!hasErrors) {\n  console.log('✅ All helper categories have corresponding pages!');\n} else {\n  console.log('\\n❌ Found missing pages. Please create them as shown above.');\n  process.exit(1);\n}"
  },
  {
    "path": "docs/scripts/check-similar-exists.js",
    "content": "#!/usr/bin/env node\nconst path = require('path');\nconst { loadHelpers, toFullKey } = require('./utils');\n\nconst dataDir = process.argv[2] || path.join(__dirname, '..', 'data');\nconst { helpers, byFullKey } = loadHelpers(dataDir);\n\nlet hasError = false;\nhelpers.forEach((h) => {\n  (h.similarHelpers || []).forEach((ref) => {\n    const key = toFullKey(ref);\n    if (!byFullKey.has(key)) {\n      hasError = true;\n      console.error(`Missing similar helper reference from ${h.fileName} -> ${key}`);\n    }\n  });\n});\n\nif (hasError) process.exit(1);\nconsole.log('OK: all similarHelpers references point to existing helpers.');\n\n"
  },
  {
    "path": "docs/scripts/check-similar-keys-exist-in-directory.js",
    "content": "#!/usr/bin/env node\nconst path = require('path');\nconst { loadHelpers, toFullKey } = require('./utils');\n\nconst dataDir = process.argv[2] || path.join(__dirname, '..', 'data');\nconst { helpers, byFullKey } = loadHelpers(dataDir);\n\nlet hasError = false;\n\nhelpers.forEach((h) => {\n  (h.similarHelpers || []).forEach((ref) => {\n    const key = toFullKey(ref);\n    if (!byFullKey.has(key)) {\n      hasError = true;\n      console.error(`Reference not found in directory for ${h.fileName} -> ${key}`);\n    }\n  });\n});\n\nif (hasError) process.exit(1);\nconsole.log('OK: every similarHelpers reference exists in the directory.');\n\n"
  },
  {
    "path": "docs/scripts/utils.js",
    "content": "const fs = require('fs');\nconst path = require('path');\n\nfunction readFile(filePath) {\n  return fs.readFileSync(filePath, 'utf8');\n}\n\nfunction listMarkdownFiles(dirPath) {\n  return fs\n    .readdirSync(dirPath)\n    .filter((f) => f.endsWith('.md'))\n    .map((f) => path.join(dirPath, f));\n}\n\nfunction parseFrontmatter(content) {\n  // Very small frontmatter parser tailored to our files\n  // Expects YAML-like block between leading --- lines\n  const fmMatch = content.match(/^---[\\r\\n]+([\\s\\S]*?)[\\r\\n]+---/);\n  if (!fmMatch) return null;\n  const fm = fmMatch[1];\n  const data = {};\n\n  // Capture simple key: value pairs and array values like: key: [a, b]\n  fm.split(/\\r?\\n/).forEach((line) => {\n    const m = line.match(/^([A-Za-z][A-Za-z0-9_-]*):\\s*(.*)$/);\n    if (!m) return;\n    const key = m[1];\n    const raw = m[2].trim();\n    if (raw.startsWith('[') && raw.endsWith(']')) {\n      const inner = raw.slice(1, -1).trim();\n      if (inner.length === 0) {\n        data[key] = [];\n      } else {\n        data[key] = inner\n          .split(',')\n          .map((s) => s.trim())\n          .map((s) => (s.startsWith('\"') && s.endsWith('\"') ? s.slice(1, -1) : s));\n      }\n    } else if (raw.startsWith('\"') && raw.endsWith('\"')) {\n      data[key] = raw.slice(1, -1);\n    } else if (raw === '[]') {\n      data[key] = [];\n    } else if (raw === 'null') {\n      data[key] = null;\n    } else {\n      data[key] = raw;\n    }\n  });\n  return data;\n}\n\nfunction loadHelpers(dataDir) {\n  const files = listMarkdownFiles(dataDir);\n  const helpers = [];\n\n  files.forEach((absPath) => {\n    const filename = path.basename(absPath);\n    const content = readFile(absPath);\n    const fm = parseFrontmatter(content) || {};\n    const helper = {\n      filePath: absPath,\n      fileName: filename,\n      name: fm.name || null,\n      slug: fm.slug || null,\n      category: fm.category || null,\n      subCategory: fm.subCategory || null,\n      similarHelpers: Array.isArray(fm.similarHelpers) ? fm.similarHelpers : [],\n    };\n    helpers.push(helper);\n  });\n\n  // Build index by keys for quick lookup\n  const byCategoryName = new Map(); // key: `${category}#${name}` -> helper\n  const byFullKey = new Map(); // key: `${category}#${subCategory}#${name}` -> helper\n  const byPath = new Map(); // key: filename -> helper\n\n  helpers.forEach((h) => {\n    if (h.category && h.name) {\n      const k = `${h.category}#${h.name}`;\n      if (!byCategoryName.has(k)) byCategoryName.set(k, []);\n      byCategoryName.get(k).push(h);\n    }\n    if (h.category && h.subCategory && h.name) {\n      const k2 = `${h.category}#${h.subCategory}#${h.name}`;\n      byFullKey.set(k2, h);\n    }\n    byPath.set(h.fileName, h);\n  });\n\n  return { helpers, byCategoryName, byFullKey, byPath };\n}\n\nfunction expectedFileName(helper) {\n  if (!helper || !helper.category || !helper.slug) return null;\n  return `${helper.category}-${helper.slug}.md`;\n}\n\nfunction toFullKey(ref) {\n  // ref format: category#subcategory#Name\n  return ref.trim();\n}\n\nmodule.exports = {\n  readFile,\n  listMarkdownFiles,\n  parseFrontmatter,\n  loadHelpers,\n  expectedFileName,\n  toFullKey,\n};\n\n\n"
  },
  {
    "path": "docs/sidebars.ts",
    "content": "import type {SidebarsConfig} from '@docusaurus/plugin-content-docs';\n\n// This runs in Node.js - Don't use client-side code here (browser APIs, JSX...)\n\n/**\n * Creating a sidebar enables you to:\n - create an ordered group of docs\n - render a sidebar for each doc of that group\n - provide next/previous navigation\n\n The sidebars can be generated from the filesystem, or explicitly defined here.\n\n Create as many sidebars as you want.\n */\nconst sidebars: SidebarsConfig = {\n  // Enhanced sidebar with better organization and features from 3.8+\n  docSidebar: [\n    'about',\n    'getting-started',\n    {\n      type: 'category',\n      label: '🧢 Core',\n      collapsible: true,\n      collapsed: true,\n      items: [\n        {type: 'autogenerated', dirName: 'core'},\n      ],\n    },\n    {\n      type: 'category',\n      label: '🔄 Iterator',\n      collapsible: true,\n      collapsed: true,\n      items: [\n        {type: 'autogenerated', dirName: 'iter'},\n      ],\n    },\n    {\n      type: 'category',\n      label: '👣 Mutable',\n      collapsible: true,\n      collapsed: true,\n      items: [\n        {type: 'autogenerated', dirName: 'mutable'},\n      ],\n    },\n    {\n      type: 'category',\n      label: '🏎️ Parallel',\n      collapsible: true,\n      collapsed: true,\n      items: [\n        {type: 'autogenerated', dirName: 'parallel'},\n      ],\n    },\n    {\n      type: 'category',\n      label: '🧪 Experimental',\n      collapsible: true,\n      collapsed: true,\n      items: [\n        {type: 'autogenerated', dirName: 'experimental'},\n      ],\n    },\n    'glossary',\n    'contributing',\n  ],\n};\n\nexport default sidebars;\n"
  },
  {
    "path": "docs/src/css/custom.css",
    "content": "/**\n * Any CSS included here will be global. The classic template\n * bundles Infima by default. Infima is a CSS framework designed to\n * work well for content-centric websites.\n */\n\n/* Modern CSS cascade layers for better style organization */\n@layer base, components, utilities;\n\n/* You can override the default Infima variables here. */\n/* https://www.colors.tools/lighten-and-darken/ */\n@layer base {\n  :root {\n    --ifm-color-primary: #007D9C;\n    --ifm-color-primary-dark: #002b36;\n    --ifm-color-primary-darker: #000;\n    --ifm-color-primary-darkest: #000;\n    --ifm-color-primary-light: #03cdff;\n    --ifm-color-primary-lighter: #69e1ff;\n    --ifm-color-primary-lightest: #cff5ff;\n    --ifm-code-font-size: 95%;\n    --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.1);\n\n    --ifm-navbar-background-color: #f9f9f9;\n    --ifm-background-surface-color: #f9f9f9;\n    --ifm-background-surface-color-secondary: #f3f3f3;\n    --ifm-background-color: #ffffff;\n\n    /* --ifm-menu-link-padding-horizontal: 1rem; */\n  }\n\n  /* For readability concerns, you should choose a lighter palette in dark mode. */\n  [data-theme='dark'] {\n    --ifm-color-primary: #007D9C;\n    --ifm-color-primary-dark: #002b36;\n    --ifm-color-primary-darker: #000;\n    --ifm-color-primary-darkest: #000;\n    --ifm-color-primary-light: #03cdff;\n    --ifm-color-primary-lighter: #69e1ff;\n    --ifm-color-primary-lightest: #cff5ff;\n    --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.3);\n\n    --ifm-background-color: #1f201c;\n    --ifm-background-surface-color: #272822;\n    --ifm-background-surface-color-secondary: #2a2b25;\n    --ifm-navbar-background-color: #272822;\n  }\n}\n\n@layer components {\n  .header-github-link:hover {\n    opacity: 0.6;\n  }\n\n  .header-github-link::before {\n    content: '';\n    width: 24px;\n    height: 24px;\n    display: flex;\n    background: url(\"data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E\") no-repeat;\n  }\n\n  [data-theme='dark'] .header-github-link::before {\n    background: url(\"data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='white' d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E\") no-repeat;\n  }\n}\n\n@layer utilities {\n  .theme-doc-sidebar-item-link-level-2 {\n    /* because emojis in the level-1 menu require to push right level-2 menu entries */\n    padding-left: 1.0rem;\n  }\n\n  .docSidebarWithSpnsors {\n    display: flex;\n    flex-direction: column;\n    height: 100%;\n  }\n\n  .sidebar-spnsors {\n    margin-top: auto;\n    padding: 0.75rem 1rem 1.25rem;\n    border-top: 1px solid var(--ifm-toc-border-color);\n    background-color: var(--ifm-background-surface-color);\n  }\n\n  .sidebar-spnsors__title {\n    font-size: 0.9rem;\n    font-weight: 600;\n    /* text-transform: uppercase; */\n    margin-bottom: 0.5rem;\n    opacity: 0.7;\n  }\n\n  .sidebar-spnsors__logos {\n    display: flex;\n    flex-direction: column;\n    gap: 0.75rem;\n  }\n\n  .sidebar-spnsors__logo {\n    max-height: 40px;\n    max-width: 160px;\n    object-fit: contain;\n  }\n\n  .sidebar-spnsors__logo-wrapper {\n    display: flex;\n    flex-direction: column;\n    align-items: flex-start;\n    gap: 0.15rem;\n  }\n\n  .sidebar-spnsors__logo-title {\n    font-size: 0.8rem;\n    line-height: 1.3;\n    font-weight: 500;\n    opacity: 0.9;\n  }\n}\n\n/* CUSTOM */\n.navbar__item .dropdown__menu {\n  min-width: 7rem;\n}\n\n.navbar__item .dropdown__menu svg {\n  display: none;\n}\n\n/* Fix anchor links being hidden behind fixed navbar */\nhtml {\n  scroll-padding-top: calc(var(--ifm-navbar-height) + 1rem) !important;\n}\n\n/* Also apply scroll-margin-top to specific elements */\nh1,\nh2,\nh3,\nh4,\nh5,\nh6,\n[id],\n.anchor {\n  scroll-margin-top: calc(var(--ifm-navbar-height) + 1rem) !important;\n}\n\n/* Target any element that could be an anchor target */\n*[id] {\n  scroll-margin-top: calc(var(--ifm-navbar-height) + 1rem) !important;\n}"
  },
  {
    "path": "docs/src/pages/community.module.css",
    "content": ".icon {\n    color: var(--ifm-navbar-link-color);\n    font-weight: var(--ifm-font-weight-semibold);\n    padding: var(--ifm-navbar-item-padding-vertical) var(--ifm-navbar-item-padding-horizontal);\n    display: inline-block;\n}\n\n.headerImg {\n    padding-top: 20px;\n    height: 180px;\n}\n\n.twitter:before {\n    content: '';\n    width: 48px;\n    height: 48px;\n    display: flex;\n    background: url(\"data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M23 3a10.9 10.9 0 0 1-3.14 1.53 4.48 4.48 0 0 0-7.86 3v1A10.66 10.66 0 0 1 3 4s-4 9 5 13a11.64 11.64 0 0 1-7 2c9 5 20 0 20-11.5a4.5 4.5 0 0 0-.08-.83A7.72 7.72 0 0 0 23 3z'/%3E%3C/svg%3E\") no-repeat;\n}\n\nhtml[data-theme='dark'] .twitter:before {\n    background: url(\"data:image/svg+xml,%3Csvg viewBox='0 0 24 24' fill='white' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M23 3a10.9 10.9 0 0 1-3.14 1.53 4.48 4.48 0 0 0-7.86 3v1A10.66 10.66 0 0 1 3 4s-4 9 5 13a11.64 11.64 0 0 1-7 2c9 5 20 0 20-11.5a4.5 4.5 0 0 0-.08-.83A7.72 7.72 0 0 0 23 3z'/%3E%3C/svg%3E\") no-repeat;\n}\n\n.chat:before {\n    content: '';\n    width: 48px;\n    height: 48px;\n    display: flex;\n    background: url(\"data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z'/%3E%3C/svg%3E\") no-repeat;\n}\n\nhtml[data-theme='dark'] .chat:before {\n    background: url(\"data:image/svg+xml,%3Csvg viewBox='0 0 24 24' fill='white' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z'/%3E%3C/svg%3E\") no-repeat;\n}\n\n.email:before {\n    content: '';\n    width: 48px;\n    height: 48px;\n    display: flex;\n    background: url(\"data:image/svg+xml,%3Csvg viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z'/%3E%3Cpolyline points='22,6 12,13 2,6'/%3E%3C/svg%3E\") no-repeat;\n}\n\nhtml[data-theme='dark'] .email:before {\n    background: url(\"data:image/svg+xml,%3Csvg viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z'/%3E%3Cpolyline points='22,6 12,13 2,6'/%3E%3C/svg%3E\") no-repeat;\n}"
  },
  {
    "path": "docs/src/pages/community.tsx",
    "content": "import React from 'react';\n\nimport styles from './community.module.css';\nimport classnames from 'classnames';\nimport Layout from '@theme/Layout';\nimport Link from '@docusaurus/Link';\n\nimport useDocusaurusContext from '@docusaurus/useDocusaurusContext';\n\nfunction Community() {\n  const context = useDocusaurusContext();\n\n  return (\n    <Layout title=\"Community\" description=\"Where to ask questions and find your soulmate\">\n      <header className=\"hero\">\n        <div className=\"container text--center\">\n          <h1>Community</h1>\n          <div className=\"hero--subtitle\">\n            These are places where you can ask questions and find your soulmate (no promises).\n            <br/>\n            \"If you want to go fast, go alone. If you want to go far, go together.\"\n          </div>\n          <img className={styles.headerImg} src=\"/img/go-community.png\" />\n        </div>\n      </header>\n      <main>\n        <div className=\"container\">\n          <div className=\"row margin-vert--lg\">\n            <div className=\"col text--center padding-vert--md\">\n              <div className=\"card\">\n                <div className=\"card__header\">\n                  <i className={classnames(styles.icon, styles.chat)}></i>\n                </div>\n                <div className=\"card__body\">\n                  <p>Report bugs or suggest improvements</p>\n                </div>\n                <div className=\"card__footer\">\n                  <Link to=\"https://github.com/samber/lo/issues\" className=\"button button--outline button--primary button--block\">Open new issue</Link>\n                </div>\n              </div>\n            </div>\n\n            <div className=\"col text--center padding-vert--md\">\n              <div className=\"card\">\n                <div className=\"card__header\">\n                  <i className={classnames(styles.icon, styles.chat)}></i>\n                </div>\n                <div className=\"card__body\">\n                  <p>You like this project?</p>\n                </div>\n                <div className=\"card__footer\">\n                  <Link to=\"https://github.com/samber/lo?tab=readme-ov-file#-contributing\" className=\"button button--outline button--primary button--block\">Start contributing!</Link>\n                </div>\n              </div>\n            </div>\n\n            <div className=\"col text--center padding-vert--md\">\n              <div className=\"card\">\n                <div className=\"card__header\">\n                  <i className={classnames(styles.icon, styles.twitter)}></i>\n                </div>\n                <div className=\"card__body\">\n                  <p>Follow &#64;samuelberthe on Twitter</p>\n                </div>\n                <div className=\"card__footer\">\n                  <Link to=\"https://twitter.com/samuelberthe\" className=\"button button--outline button--primary button--block\">Follow &#64;SamuelBerthe</Link>\n                </div>\n              </div>\n            </div>\n\n            <div className=\"col text--center padding-vert--md\">\n              <div className=\"card\">\n                <div className=\"card__header\">\n                  <i className={classnames(styles.icon, styles.email)}></i>\n                </div>\n                <div className=\"card__body\">\n                  <p>For sensitive or security-related queries, send us an email</p>\n                </div>\n                <div className=\"card__footer\">\n                  <Link to=\"mailto:contact@samuel-berthe.fr\" className=\"button button--outline button--primary button--block\">contact&#64;samuel-berthe.fr</Link>\n                </div>\n              </div>\n            </div>\n          </div>\n        </div>\n      </main>\n    </Layout>\n  );\n}\n\nexport default Community;"
  },
  {
    "path": "docs/src/pages/index.module.css",
    "content": "/**\n * CSS files with the .module.css suffix will be treated as CSS modules\n * and scoped locally.\n */\n\n.heroBanner {\n  padding: 4rem 0;\n  text-align: center;\n  position: relative;\n  overflow: hidden;\n}\n\n@media screen and (max-width: 996px) {\n  .heroBanner {\n    padding: 2rem;\n  }\n}\n\n.buttons {\n  display: flex;\n  align-items: center;\n  justify-content: center;\n}\n\n.features {\n  display: flex;\n  align-items: center;\n  padding: 2rem 0;\n  width: 100%;\n}\n\n.featureSvg {\n  height: 200px;\n  width: 200px;\n}"
  },
  {
    "path": "docs/src/pages/index.tsx",
    "content": "import type {ReactNode} from 'react';\nimport clsx from 'clsx';\nimport Link from '@docusaurus/Link';\nimport useDocusaurusContext from '@docusaurus/useDocusaurusContext';\nimport Layout from '@theme/Layout';\nimport Heading from '@theme/Heading';\nimport styles from './index.module.css';\n\ntype FeatureItem = {\n  title: string;\n  Svg: React.ComponentType<React.ComponentProps<'svg'>>;\n  description: ReactNode;\n};\n\nconst FeatureList: FeatureItem[] = [\n  {\n    title: 'Type-safe Utilities for Go',\n    Svg: require('@site/static/img/oxygen-tube.svg').default,\n    description: (\n      <>\n        Generic utilities bringing type safety and convenience to daily Go programming.\n      </>\n    ),\n  },\n  {\n    title: 'Comprehensive API Coverage',\n    Svg: require('@site/static/img/compass.svg').default,\n    description: (\n      <>\n        A rich set of helpers for slices, maps, and more, ready for any data task in Go.\n      </>\n    ),\n  },\n  {\n    title: 'Built for Productivity',\n    Svg: require('@site/static/img/backpacks.svg').default,\n    description: (\n      <>\n        Minimal dependencies and intuitive APIs for seamless adoption and fast results. No breaking changes.\n      </>\n    ),\n  },\n];\n\nfunction Feature({title, Svg, description}: FeatureItem) {\n  return (\n    <div className={clsx('col col--4')}>\n      <div className=\"text--center\">\n        <Svg className={styles.featureSvg} role=\"img\" />\n      </div>\n      <div className=\"text--center padding-horiz--md\">\n        <Heading as=\"h3\">{title}</Heading>\n        <p>{description}</p>\n      </div>\n    </div>\n  );\n}\n\nfunction HomepageFeatures(): ReactNode {\n  return (\n    <section className={styles.features}>\n      <div className=\"container\">\n        <div className=\"row\">\n          {FeatureList.map((props, idx) => (\n            <Feature key={idx} {...props} />\n          ))}\n        </div>\n      </div>\n    </section>\n  );\n}\n\nfunction HomepageHeader() {\n  const {siteConfig} = useDocusaurusContext();\n  return (\n    <header className={clsx('hero hero--primary', styles.heroBanner)}>\n      <div className=\"container\">\n        <Heading as=\"h1\" className=\"hero__title\">\n          {siteConfig.title}\n        </Heading>\n        <p className=\"hero__subtitle\">{siteConfig.tagline}</p>\n        <div className={styles.buttons} style={{marginBottom: '10px'}}>\n          <Link\n            className=\"button button--secondary button--lg\"\n            to=\"/docs/about\">\n            Intro\n          </Link>\n        </div>\n        <div className={styles.buttons}>\n          <Link\n            className=\"button button--secondary button--lg\"\n            to=\"/docs/getting-started\">\n            Getting started - 5min ⏱️\n          </Link>\n        </div>\n      </div>\n    </header>\n  );\n}\n\nexport default function Home(): JSX.Element {\n  const {siteConfig} = useDocusaurusContext();\n  return (\n    <Layout\n      title={`🏎️ ${siteConfig.title}: ${siteConfig.tagline}`}\n      description=\"Reusable utility library for Go\">\n      <HomepageHeader />\n      <main>\n        <HomepageFeatures />\n      </main>\n    </Layout>\n  );\n}\n"
  },
  {
    "path": "docs/src/prism-include-languages.js",
    "content": "import siteConfig from '@generated/docusaurus.config';\nexport default function prismIncludeLanguages(PrismObject) {\n  const {\n    themeConfig: {prism},\n  } = siteConfig;\n  const {additionalLanguages, defaultLanguage} = prism;\n  \n  // Add Go language support\n  globalThis.Prism = PrismObject;\n  \n  // eslint-disable-next-line import/no-dynamic-require, global-require\n  require(`prismjs/components/prism-${defaultLanguage}`);\n  \n  additionalLanguages.forEach((lang) => {\n    // eslint-disable-next-line import/no-dynamic-require, global-require\n    require(`prismjs/components/prism-${lang}`);\n  });\n  \n  delete globalThis.Prism;\n}\n"
  },
  {
    "path": "docs/src/theme/DocSidebar/index.tsx",
    "content": "import React from 'react';\nimport OriginalDocSidebar from '@theme-original/DocSidebar';\nimport type DocSidebarProps from '@theme/DocSidebar';\nimport useDocusaurusContext from '@docusaurus/useDocusaurusContext';\nimport {useColorMode} from '@docusaurus/theme-common';\n\ntype Sponsor = {\n  name: string;\n  url: string;\n  title: string;\n  logo_light: string;\n  logo_dark: string;\n};\n\nexport default function DocSidebarWrapper(props: DocSidebarProps) {\n  const {siteConfig} = useDocusaurusContext();\n  const sponsors = (siteConfig.customFields?.sponsors ?? []) as Sponsor[];\n  const {colorMode} = useColorMode();\n\n  return (\n    <div className=\"docSidebarWithSpnsors\">\n      <OriginalDocSidebar {...props} />\n\n      {sponsors.length > 0 && (\n        <div className=\"sidebar-spnsors\">\n          <div className=\"sidebar-spnsors__title\">💖 Sponsored by</div>\n          <div className=\"sidebar-spnsors__logos\">\n            {sponsors.map((sponsor) => (\n              <a\n                key={sponsor.name}\n                href={sponsor.url}\n                target=\"_blank\"\n                rel=\"noopener noreferrer\"\n                className=\"sidebar-spnsors__logo-link\"\n                title={sponsor.title}\n              >\n                <div className=\"sidebar-spnsors__logo-wrapper\">\n                  <img\n                    src={colorMode === 'dark' ? sponsor.logo_dark : sponsor.logo_light}\n                    alt={sponsor.name}\n                    className=\"sidebar-spnsors__logo\"\n                  />\n                  <div className=\"sidebar-spnsors__logo-title\">\n                    {sponsor.title}\n                  </div>\n                </div>\n              </a>\n            ))}\n          </div>\n        </div>\n      )}\n    </div>\n  );\n}\n\n"
  },
  {
    "path": "docs/src/theme/NotFound/index.tsx",
    "content": "import React from 'react';\nimport Layout from '@theme/Layout';\nimport Translate, {translate} from '@docusaurus/Translate';\nimport {PageMetadata} from '@docusaurus/theme-common';\n\nexport default function NotFoundPage(): JSX.Element {\n  return (\n    <>\n      <PageMetadata\n        title={translate({\n          id: 'theme.NotFound.title',\n          message: 'Page Not Found',\n        })}\n      />\n      <Layout>\n        <main className=\"container margin-vert--xl\">\n          <div className=\"row\">\n            <div className=\"col col--6 col--offset-3\">\n              <h1 className=\"hero__title\">\n                <Translate\n                  id=\"theme.NotFound.title\"\n                  description=\"The title of the 404 page\">\n                  Page Not Found\n                </Translate>\n              </h1>\n              <p>\n                <Translate\n                  id=\"theme.NotFound.p1\"\n                  description=\"The first paragraph of the 404 page\">\n                  We could not find what you were looking for.\n                </Translate>\n              </p>\n              <p>\n                <Translate\n                  id=\"theme.NotFound.p2\"\n                  description=\"The 2nd paragraph of the 404 page\">\n                  Please contact the owner of the site that linked you to the\n                  original URL and let them know their link is broken.\n                </Translate>\n              </p>\n              <div className=\"margin-top--lg\">\n                <a href=\"/\" className=\"button button--primary button--lg\">\n                  <Translate\n                    id=\"theme.NotFound.backToHome\"\n                    description=\"The label for the back to home button\">\n                    Back to Home\n                  </Translate>\n                </a>\n                <a href=\"/docs/getting-started\" className=\"button button--secondary button--lg margin-left--md\">\n                  <Translate\n                    id=\"theme.NotFound.goDocs\"\n                    description=\"The label for the go to docs button\">\n                    Browse Documentation\n                  </Translate>\n                </a>\n              </div>\n            </div>\n          </div>\n        </main>\n      </Layout>\n    </>\n  );\n}\n"
  },
  {
    "path": "docs/src/theme/prism-include-languages.js",
    "content": "import siteConfig from '@generated/docusaurus.config';\nexport default function prismIncludeLanguages(PrismObject) {\n  const {\n    themeConfig: {prism},\n  } = siteConfig;\n  const {additionalLanguages, defaultLanguage} = prism;\n  \n  // Add Go language support\n  globalThis.Prism = PrismObject;\n  \n  // eslint-disable-next-line import/no-dynamic-require, global-require\n  require(`prismjs/components/prism-${defaultLanguage}`);\n  \n  additionalLanguages.forEach((lang) => {\n    // eslint-disable-next-line import/no-dynamic-require, global-require\n    require(`prismjs/components/prism-${lang}`);\n  });\n  \n  delete globalThis.Prism;\n}\n"
  },
  {
    "path": "docs/static/.nojekyll",
    "content": ""
  },
  {
    "path": "docs/static/img/README.md",
    "content": "Credit goes to https://gopherize.me/"
  },
  {
    "path": "docs/static/llms.txt",
    "content": "# Lo - A Go library for functional programming\n\nLo is a comprehensive, production-ready Lodash-style Go library built on Go 1.18+ generics that provides hundreds of utility functions for working with slices, maps, strings, channels, functions, and more. It aims to make Go code more expressive, readable, and productive by offering a rich collection of functional programming helpers inspired by libraries like Lodash in JavaScript.\n\n## Origins and Purpose\n\nBorn from the need to fill gaps in Go's standard library after the introduction of generics in Go 1.18, Lo addresses common pain points that Go developers face daily. While Go's standard library gained some generic helpers in `slices` and `maps` packages, Lo goes far beyond with 300+ carefully crafted utilities that make functional programming patterns natural and idiomatic in Go.\n\nThe library emerged from real-world production needs and has been battle-tested in numerous high-traffic applications, microservices, and enterprise systems. It's not just a collection of utility functions, but a thoughtful toolkit that enables developers to write more declarative, maintainable, and bug-free code.\n\n## Key Features\n\n- **Generic-based**: Fully leverages Go 1.18+ generics for compile-time type safety\n- **Zero dependencies**: No external dependencies outside the Go standard library\n- **Comprehensive**: 300+ helpers covering slices, maps, strings, channels, functions, and more\n- **Functional programming**: Brings functional programming paradigms to Go naturally\n- **Production-ready**: Battle-tested in high-traffic applications worldwide\n- **Well-tested**: 95%+ test coverage with comprehensive examples\n- **SemVer compliant**: Follows strict semantic versioning (v1.x.x stable)\n- **Performance-focused**: Minimal runtime overhead with optimized implementations\n- **Memory efficient**: Many helpers avoid allocations and use zero-copy patterns\n- **Composable**: Designed to work together in method chains and complex pipelines\n\n## Sub-packages\n\nThe main package is complemented by several specialized sub-packages:\n\n- **lo**: Core package with 300+ helpers for everyday operations\n- **lo/parallel**: Parallel processing helpers for concurrent operations\n- **lo/mutable**: In-place mutation helpers for memory-efficient operations\n- **lo/it**: Iterator helpers for lazy evaluation and streaming\n\n## Design Philosophy\n\nLo is built on a foundation of pragmatic engineering principles that balance power, safety, and performance:\n\n1. **Type Safety First**: All helpers leverage Go's generics for compile-time type checking, eliminating runtime type assertions and reducing bugs\n2. **Go Idiomatic**: While inspired by functional programming, helpers feel natural in Go code and follow established conventions\n3. **Performance Conscious**: Every helper is benchmarked and optimized for minimal overhead, with many using zero-copy patterns\n4. **Explicit Clarity**: Helper names clearly communicate their purpose and behavior\n5. **Composable by Design**: Functions work together seamlessly, enabling elegant data transformation pipelines\n6. **Memory Efficient**: Careful attention to allocation patterns, with many helpers avoiding unnecessary heap allocations\n7. **Error Handling Respect**: Helpers don't hide errors; they integrate naturally with Go's error handling patterns\n8. **Practical Over Pure**: Prioritizes solving real-world problems over theoretical purity\n\n## Core Package Helpers\n\n### Condition\n- Ternary: Return value based on condition\n- TernaryF: Return value from function based on condition\n- If: Return value if condition is true\n- IfF: Return value from function if condition is true\n- ElseIf: Return value if previous condition was false and this condition is true\n- ElseIfF: Return value from function if previous condition was false and this condition is true\n- Else: Return value if all previous conditions were false\n- ElseF: Return value from function if all previous conditions were false\n- Switch: Return value based on first matching case\n- Case: Define a case for switch statement\n- CaseF: Define a case with function execution for switch statement\n- Default: Define default case for switch statement\n- DefaultF: Define default case with function execution for switch statement\n\n### Concurrency\n- Synchronize: Coordinate multiple goroutines with mutex\n- Async: Execute function in goroutine and return channel\n- Async0-Async6: Execute functions with 0-6 return values in goroutines\n- WaitFor: Block until condition becomes true\n- WaitForWithContext: Block until condition becomes true with context cancellation\n\n### Error Handling\n- Validate: Return error if condition is false\n- Must: Panic if error is not nil, otherwise return value\n- Must0-Must6: Panic if error is not nil, otherwise return 0-6 values\n- Try: Execute function and panic on error\n- Try0-Try6: Execute function with 0-6 return values and panic on error\n- TryOr: Execute function and return fallback value on error\n- TryOr1-TryOr6: Execute function with 1-6 return values and return fallback on error\n- TryWithErrorValue: Execute function and return error value on panic\n- TryCatch: Execute function with panic recovery\n- TryCatchWithErrorValue: Execute function with panic recovery and error value\n- ErrorsAs: Convert error to target type\n- Assert: Panic if condition is false\n- Assertf: Panic with formatted message if condition is false\n\n### Find\n- IndexOf: Get index of first matching element\n- LastIndexOf: Get index of last matching element\n- HasPrefix: Check if collection starts with elements\n- HasSuffix: Check if collection ends with elements\n- Find: Get first element matching predicate\n- FindIndexOf: Get first element and its index matching predicate\n- FindLastIndexOf: Get last element and its index matching predicate\n- FindOrElse: Get first element matching predicate or fallback value\n- FindKey: Get first key in map with matching value\n- FindKeyBy: Get first key in map matching predicate\n- FindUniques: Get slice of unique elements\n- FindUniquesBy: Get slice of unique elements by transform\n- FindDuplicates: Get slice of duplicate elements\n- FindDuplicatesBy: Get slice of duplicate elements by transform\n- Min: Get minimum value in collection\n- MinIndex: Get index of minimum value\n- MinBy: Get minimum value by comparison function\n- MinIndexBy: Get index of minimum value by comparison function\n- Earliest: Get earliest time value\n- EarliestBy: Get earliest value by time comparison\n- Max: Get maximum value in collection\n- MaxIndex: Get index of maximum value\n- MaxBy: Get maximum value by comparison function\n- MaxIndexBy: Get index of maximum value by comparison function\n- Latest: Get latest time value\n- LatestBy: Get latest value by time comparison\n- First: Get first element from collection\n- FirstOrEmpty: Get first element or zero value\n- FirstOr: Get first element or fallback value\n- Last: Get last element from collection\n- LastOrEmpty: Get last element or zero value\n- LastOr: Get last element or fallback value\n- Nth: Get element at index\n- NthOr: Get element at index or fallback value\n- NthOrEmpty: Get element at index or zero value\n- Sample: Get random element from collection\n- SampleBy: Get random element using custom generator\n- Samples: Get N random unique elements\n- SamplesBy: Get N random elements using custom generator\n\n### Function\n- Partial: Create function with some arguments pre-filled\n- Partial1-Partial5: Create functions with 1-5 arguments pre-filled\n\n### Intersect\n- Contains: Check if collection contains element\n- ContainsBy: Check if collection contains element matching predicate\n- Every: Check if all elements in collection match subset\n- EveryBy: Check if all elements match predicate\n- Some: Check if any elements in collection match subset\n- SomeBy: Check if any elements match predicate\n- None: Check if no elements in collection match subset\n- NoneBy: Check if no elements match predicate\n- Intersect: Get elements common to all collections\n- IntersectBy: Get elements common to all collections with key selector\n- Difference: Get elements in first collection but not in others\n- Union: Get all unique elements from collections\n- Without: Get collection with specified elements removed\n- WithoutBy: Get collection with elements removed by predicate\n- WithoutNth: Get collection with element at index removed\n- ElementsMatch: Check if collections contain same elements\n- ElementsMatchBy: Check if collections match by transform function\n\n### Map\n- Keys: Get slice of map keys\n- UniqKeys: Get slice of unique map keys\n- HasKey: Check if map contains key\n- Values: Get slice of map values\n- UniqValues: Get slice of unique map values\n- ValueOr: Get map value or fallback if key not found\n- PickBy: Create map with entries matching predicate\n- PickByKeys: Create map with specified keys\n- PickByValues: Create map with specified values\n- OmitBy: Create map without entries matching predicate\n- OmitByKeys: Create map without specified keys\n- OmitByValues: Create map without specified values\n- Entries: Get slice of key-value pairs from map\n- ToPairs: Alias for Entries\n- FromEntries: Create map from key-value pairs\n- FromPairs: Alias for FromEntries\n- Invert: Create map with keys and values swapped\n- Assign: Merge multiple maps into one\n- ChunkEntries: Split map entries into chunks of specified size\n- MapKeys: Transform map keys using function\n- MapValues: Transform map values using function\n- MapEntries: Transform map entries using function\n- MapToSlice: Convert map to slice using function\n- FilterMapToSlice: Filter and convert map to slice\n- FilterKeys: Get slice of keys matching predicate\n- FilterValues: Get slice of values matching predicate\n\n### Math\n- Range: Generate slice of numbers from 0 to n-1\n- RangeFrom: Generate slice of numbers from start to end\n- RangeWithSteps: Generate slice of numbers with custom step size\n- Clamp: Constrain value between minimum and maximum\n- Sum: Calculate sum of numbers\n- SumBy: Calculate sum by applying function to each element\n- Product: Calculate product of numbers\n- ProductBy: Calculate product by applying function to each element\n- Mean: Calculate arithmetic mean of numbers\n- MeanBy: Calculate mean by applying function to each element\n- Mode: Find most frequently occurring value\n\n### Retry\n- NewDebounce: Create function that delays execution until after calls stop\n- NewDebounceBy: Create debounced function with key-based grouping\n- Attempt: Execute function with specified number of retries\n- AttemptWithDelay: Execute function with retries and delay between attempts\n- AttemptWhile: Execute function while condition is true\n- AttemptWhileWithDelay: Execute function while condition is true with delay\n- NewTransaction: Create transaction with rollback capability\n- NewThrottle: Create function that limits execution frequency\n- NewThrottleWithCount: Create throttled function with execution count limit\n- NewThrottleBy: Create throttled function with key-based grouping\n- NewThrottleByWithCount: Create throttled function with key-based grouping and count limit\n\n### Slice\n- Filter: Get elements matching predicate\n- Map: Transform each element using function\n- UniqMap: Transform elements and remove duplicates\n- FilterMap: Filter and transform elements in one operation\n- FlatMap: Transform elements and flatten result\n- Reduce: Combine elements into single value\n- ReduceRight: Combine elements from right to left\n- ForEach: Execute function for each element\n- ForEachWhile: Execute function while predicate returns true\n- Times: Execute function n times and collect results\n- Uniq: Remove duplicate elements\n- UniqBy: Remove duplicates by key function\n- GroupBy: Group elements by key function\n- GroupByMap: Group elements by key function into map\n- Chunk: Split slice into chunks of specified size\n- Window: Create sliding windows of specified size (overlapping)\n- Sliding: Create sliding windows with specified size and step\n- PartitionBy: Split elements into two groups by predicate\n- Flatten: Flatten nested slices into single slice\n- Concat: Combine multiple slices into one\n- Interleave: Interleave elements from multiple slices\n- Fill: Fill slice with specified value\n- Repeat: Create slice with element repeated n times\n- RepeatBy: Create slice by calling function n times\n- KeyBy: Create map from slice using key function\n- Associate: Create map from slice using key-value function\n- AssociateI: Create map from slice with index-aware function\n- SliceToMap: Convert slice to map using key function\n- SliceToMapI: Convert slice to map with index-aware function\n- FilterSliceToMap: Filter and convert slice to map\n- FilterSliceToMapI: Filter and convert slice to map with index\n- Keyify: Create set from slice elements\n- Take: Get first n elements from slice\n- TakeWhile: Get elements from start while predicate is true\n- TakeFilter / TakeFilterI: Filter and take first n matching elements (efficient)\n- Drop: Remove first n elements\n- DropRight: Remove last n elements\n- DropWhile: Remove elements from start while predicate is true\n- DropRightWhile: Remove elements from end while predicate is true\n- DropByIndex: Remove elements at specified indices\n- Reject: Remove elements matching predicate\n- RejectMap: Remove and transform elements matching predicate\n- FilterReject: Split elements into matching and non-matching groups\n- Count: Count occurrences of value\n- CountBy: Count elements matching predicate\n- CountValues: Count frequency of each value\n- CountValuesBy: Count frequency by key function\n- Subset: Get slice of elements from offset with length\n- Slice: Get slice of elements from start to end\n- Replace: Replace first n occurrences of value\n- ReplaceAll: Replace all occurrences of value\n- Clone: Perform a shallow copy of the collection\n- Compact: Remove zero values from slice\n- IsSorted: Check if slice is sorted in ascending order\n- IsSortedBy: Check if slice is sorted by key function\n- Splice: Insert elements at specified index\n- Cut: Split string at first occurrence of separator\n- CutPrefix: Remove prefix from string if present\n- CutSuffix: Remove suffix from string if present\n- Trim: Remove whitespace from both ends of string\n- TrimLeft: Remove whitespace from start of string\n- TrimPrefix: Remove prefix from string if present\n- TrimRight: Remove whitespace from end of string\n- TrimSuffix: Remove suffix from string if present\n\n### String\n- RandomString: Generate random string of specified length\n- Substring: Extract substring from start to end\n- ChunkString: Split string into chunks of specified size\n- RuneLength: Get number of runes in string\n- PascalCase: Convert string to PascalCase\n- CamelCase: Convert string to camelCase\n- KebabCase: Convert string to kebab-case\n- SnakeCase: Convert string to snake_case\n- Words: Split string into slice of words\n- Capitalize: Capitalize first letter of string\n- Ellipsis: Truncate string to length with ellipsis\n\n### Time\n- Duration: Measure execution time of function\n- Duration0-Duration10: Measure execution time of function with 0-10 return values\n- EarliestBy: Find earliest time value by comparison function\n- Latest: Find latest time value\n- LatestBy: Find latest time value by comparison function\n\n### Tuple\n- T2-T9: Create tuple with 2-9 elements\n- Unpack2-Unpack9: Unpack tuple with 2-9 elements into variables\n- Zip2-Zip9: Combine 2-9 collections into tuples\n- ZipBy2-ZipBy9: Combine 2-9 collections into tuples using function\n- CrossJoin2-CrossJoin9: Create cartesian product of 2-9 collections\n- CrossJoinBy2-CrossJoinBy9: Create cartesian product of 2-9 collections using function\n\n### Type\n- IsNil: Check if value is nil\n- IsNotNil: Check if value is not nil\n- ToPtr: Convert value to pointer\n- Nil: Get nil value of type\n- EmptyableToPtr: Convert emptyable value to pointer\n- FromPtr: Get value from pointer\n- FromPtrOr: Get value from pointer or fallback if nil\n- ToSlicePtr: Convert slice to slice of pointers\n- FromSlicePtr: Convert slice of pointers to slice\n- FromSlicePtrOr: Convert slice of pointers to slice or fallback\n- ToAnySlice: Convert slice to []any\n- FromAnySlice: Convert []any to typed slice\n- Empty: Get zero value of type\n- IsEmpty: Check if value is zero/empty\n- IsNotEmpty: Check if value is not zero/empty\n- Coalesce: Return first non-zero value\n- CoalesceOrEmpty: Return first non-zero value or zero value\n- CoalesceSlice: Return first non-empty slice\n- CoalesceSliceOrEmpty: Return first non-empty slice or empty slice\n- CoalesceMap: Return first non-empty map\n- CoalesceMapOrEmpty: Return first non-empty map or empty map\n\n### Channel\n- ChannelDispatcher: Interface for dispatching values to channels\n- DispatchingStrategyRoundRobin: Distribute values evenly across channels\n- DispatchingStrategyRandom: Distribute values randomly across channels\n- DispatchingStrategyWeightedRandom: Distribute values with weighted randomness\n- DispatchingStrategyFirst: Send to first available channel\n- DispatchingStrategyLeast: Send to least busy channel\n- DispatchingStrategyMost: Send to most busy channel\n- SliceToChannel: Convert slice to buffered channel\n- ChannelToSlice: Collect all values from channel into slice\n- Buffer: Buffer channel values with specified capacity\n- BufferWithContext: Buffer channel values with context cancellation\n- BufferWithTimeout: Buffer channel values with timeout\n- FanIn: Combine multiple channels into single channel\n- FanOut: Distribute single channel to multiple channels\n\n## Mutable Package Helpers\n\nThe lo/mutable package provides in-place mutation helpers for memory-efficient operations on slices:\n\n- Filter: Remove elements that don't match predicate in-place\n- FilterI: Remove elements that don't match index predicate in-place\n- Map: Transform collection elements in-place\n- MapI: Transform collection elements with index in-place\n- Shuffle: Randomly shuffle collection in-place using Fisher-Yates algorithm\n- Reverse: Reverse order of collection elements in-place\n\n## Parallel Package Helpers\n\nThe lo/parallel package provides parallel processing helpers for concurrent operations on slices:\n\n- Map: Transform collection elements in parallel while maintaining order\n- ForEach: Execute function on each element in parallel\n- Times: Execute function n times in parallel and collect results\n- GroupBy: Group collection elements by key using parallel processing\n- PartitionBy: Split collection into two groups by predicate using parallel processing\n\n## Iterator Package Helpers\n\nThe lo/it package provides iterator helpers for lazy evaluation and streaming operations on sequences:\n\n### Channel Operations\n- SeqToChannel: Convert sequence to buffered channel\n- SeqToChannel2: Convert key-value sequence to buffered channel\n- ChannelToSeq: Convert channel to sequence\n\n### Find Operations\n- IndexOf: Get index of first matching element in sequence\n- LastIndexOf: Get index of last matching element in sequence\n- Find: Get first element matching predicate\n- FindIndexOf: Get first element and its index matching predicate\n- FindLastIndexOf: Get last element and its index matching predicate\n- FindOrElse: Get first element matching predicate or fallback value\n- FindUniques: Get slice of unique elements from sequence\n- FindUniquesBy: Get slice of unique elements by transform function\n- FindDuplicates: Get slice of duplicate elements from sequence\n- FindDuplicatesBy: Get slice of duplicate elements by transform function\n- Min: Get minimum value from sequence\n- MinBy: Get minimum value by comparison function\n- MinIndex: Get minimum value and its index\n- MinIndexBy: Get minimum value and index by comparison function\n- Max: Get maximum value from sequence\n- MaxBy: Get maximum value by comparison function\n- MaxIndex: Get maximum value and its index\n- MaxIndexBy: Get maximum value and index by comparison function\n- Earliest: Get earliest time value from sequence\n- EarliestBy: Get earliest value by time comparison function\n- Latest: Get latest time value from sequence\n- LatestBy: Get latest value by time comparison function\n- First: Get first element from sequence\n- FirstOrEmpty: Get first element or zero value\n- FirstOr: Get first element or fallback value\n- Last: Get last element from sequence\n- LastOrEmpty: Get last element or zero value\n- LastOr: Get last element or fallback value\n- Nth: Get element at index from sequence\n- NthOr: Get element at index or fallback value\n- NthOrEmpty: Get element at index or zero value\n- Sample: Get random element from sequence\n- SampleBy: Get random element using custom generator\n- Samples: Get N random unique elements from sequence\n- SamplesBy: Get N random elements using custom generator\n\n### Intersect Operations\n- Contains: Check if sequence contains element\n- ContainsBy: Check if sequence contains element matching predicate\n- Every: Check if all elements in sequence match subset\n- EveryBy: Check if all elements match predicate\n- Some: Check if any elements in sequence match subset\n- SomeBy: Check if any elements match predicate\n- None: Check if no elements in sequence match subset\n- NoneBy: Check if no elements match predicate\n- Intersect: Get elements common to all sequences\n- IntersectBy: Get elements common to all sequences with key selector\n- Union: Get all unique elements from sequences\n- Without: Get sequence with specified elements excluded\n- WithoutBy: Get sequence with elements excluded by key transform\n- WithoutNth: Get sequence with element at index excluded\n- ElementsMatch: Check if sequences contain same elements\n- ElementsMatchBy: Check if sequences match by transform function\n\n### Map Operations\n- Keys: Create sequence from map keys\n- UniqKeys: Create sequence from unique map keys\n- Values: Create sequence from map values\n- UniqValues: Create sequence from unique map values\n- Entries: Transform map to key-value sequence\n- ToPairs: Alias for Entries\n- FromEntries: Transform key-value sequence to map\n- FromPairs: Alias for FromEntries\n- Invert: Create sequence with keys and values swapped\n- Assign: Merge multiple map sequences into one\n- ChunkEntries: Split map entries into chunks of specified size\n- MapToSeq: Transform map to sequence using function\n- FilterMapToSeq: Filter and transform map to sequence\n- FilterKeys: Get sequence of keys matching predicate\n- FilterValues: Get sequence of values matching predicate\n- SeqToSeq2: Convert sequence to indexed sequence\n- Seq2KeyToSeq: Extract keys from key-value sequence\n- Seq2ValueToSeq: Extract values from key-value sequence\n\n### Math Operations\n- Range: Generate sequence of numbers from 0 to n-1\n- RangeFrom: Generate sequence of numbers from start to end\n- RangeWithSteps: Generate sequence of numbers with custom step size\n- Sum: Calculate sum of numbers in sequence\n- SumBy: Calculate sum by applying function to each element\n- Product: Calculate product of numbers in sequence\n- ProductBy: Calculate product by applying function to each element\n- Mean: Calculate arithmetic mean of numbers in sequence\n- MeanBy: Calculate mean by applying function to each element\n- Mode: Find most frequently occurring values in sequence\n\n### Sequence Operations\n- Length: Get number of elements in sequence\n- Drain: Consume entire sequence and return slice\n- Filter: Get elements matching predicate\n- FilterI: Get elements matching index predicate\n- Map: Transform each element using function\n- MapI: Transform elements with index using function\n- UniqMap: Transform elements and remove duplicates\n- UniqMapI: Transform elements with index and remove duplicates\n- FilterMap: Filter and transform elements in one operation\n- FilterMapI: Filter and transform elements with index in one operation\n- FlatMap: Transform elements and flatten result\n- FlatMapI: Transform elements with index and flatten result\n- Reduce: Combine elements into single value\n- ReduceI: Combine elements with index awareness\n- ReduceLast: Combine elements from right to left\n- ReduceLastI: Combine elements from right with index\n- ForEach: Execute function for each element\n- ForEachI: Execute function with index for each element\n- ForEachWhile: Execute function while predicate returns true\n- ForEachWhileI: Execute function with index while predicate returns true\n- Times: Execute function n times and collect results\n- Uniq: Remove duplicate elements\n- UniqBy: Remove duplicates by key function\n- GroupBy: Group elements by key function\n- GroupByMap: Group elements by key function into map\n- Chunk: Split sequence into chunks of specified size\n- Window: Create sliding windows of specified size (overlapping)\n- Sliding: Create sliding windows with specified size and step\n- PartitionBy: Split elements into two groups by predicate\n- Flatten: Flatten nested sequences into single sequence\n- Concat: Combine multiple sequences into one\n- Interleave: Interleave elements from multiple sequences\n- Shuffle: Randomly shuffle sequence elements\n- Reverse: Reverse order of sequence elements\n- Fill: Fill sequence with specified value\n- Repeat: Create sequence with value repeated n times\n- RepeatBy: Create sequence by calling function n times\n- KeyBy: Create map from sequence using key function\n- Associate: Create map from sequence using key-value function\n- AssociateI: Create map from sequence with index-aware function\n- SeqToMap: Convert sequence to map using key function\n- SeqToMapI: Convert sequence to map with index-aware function\n- FilterSeqToMap: Filter and convert sequence to map\n- FilterSeqToMapI: Filter and convert sequence to map with index\n- Keyify: Create set from sequence elements\n- Drop: Remove first n elements\n- DropLast: Remove last n elements\n- DropWhile: Remove elements from start while predicate is true\n- DropLastWhile: Remove elements from end while predicate is true\n- Take: Get first n elements from sequence\n- TakeWhile: Get elements from start while predicate is true\n- DropByIndex: Remove elements at specified indices\n- TakeFilter / TakeFilterI: Filter and take first n matching elements\n- Reject: Remove elements matching predicate\n- RejectI: Remove elements matching index predicate\n- RejectMap: Remove and transform elements matching predicate\n- RejectMapI: Remove and transform elements matching index predicate\n- Count: Count occurrences of value in sequence\n- CountBy: Count elements matching predicate\n- CountValues: Count frequency of each value in sequence\n- CountValuesBy: Count frequency by key function\n- Subset: Get slice of elements from offset with length\n- Slice: Get slice of elements from start to end\n- Replace: Replace first n occurrences of value\n- ReplaceAll: Replace all occurrences of value\n- Compact: Remove zero values from sequence\n- IsSorted: Check if sequence is sorted in ascending order\n- IsSortedBy: Check if sequence is sorted by key function\n- Splice: Insert elements at specified index\n- CutPrefix: Remove prefix from sequence if present\n- CutSuffix: Remove suffix from sequence if present\n- Trim: Remove elements from both ends of sequence\n- TrimFirst: Remove elements from start of sequence\n- TrimPrefix: Remove prefix from sequence if present\n- TrimLast: Remove elements from end of sequence\n- TrimSuffix: Remove suffix from sequence if present\n\n### String Operations\n- ChunkString: Split string into chunks of specified size\n\n### Tuple Operations\n- Zip2-Zip9: Combine 2-9 sequences into tuples\n- ZipBy2-ZipBy9: Combine 2-9 sequences into tuples using function\n- CrossJoin2-CrossJoin9: Create cartesian product of 2-9 sequences\n- CrossJoinBy2-CrossJoinBy9: Create cartesian product of 2-9 sequences using function\n\n### Type Manipulation\n- ToSeqPtr: Convert sequence to sequence of pointers\n- FromSeqPtr: Convert sequence of pointers to sequence\n- FromSeqPtrOr: Convert sequence of pointers to sequence or fallback\n- ToAnySeq: Convert sequence to []any\n- FromAnySeq: Convert []any to typed sequence\n- Empty: Create empty sequence\n- IsEmpty: Check if sequence is empty\n- IsNotEmpty: Check if sequence is not empty\n- CoalesceSeq: Return first non-empty sequence\n- CoalesceSeqOrEmpty: Return first non-empty sequence or empty sequence\n\n## Additional Resources\n\n- **Documentation**: https://lo.samber.dev\n- **GoDoc**: https://pkg.go.dev/github.com/samber/lo\n- **GitHub**: https://github.com/samber/lo\n- **Playground**: Every helper includes a Go Playground example for quick testing\n- **Community**: Active community with contributions from hundreds of developers\n\n## Usage Examples\n\n### Basic Collection Operations\n\n```go\nimport \"github.com/samber/lo\"\n\n// Remove duplicates from a slice\nnames := lo.Uniq([]string{\"Samuel\", \"John\", \"Samuel\"})\n// []string{\"Samuel\", \"John\"}\n\n// Filter and transform in one operation\nnumbers := lo.FilterMap([]int{1, 2, 3, 4, 5}, func(item int, index int) (string, bool) {\n    if item%2 == 0 {\n        return fmt.Sprintf(\"even-%d\", item), true\n    }\n    return \"\", false\n})\n// []string{\"even-2\", \"even-4\"}\n```\n\n### Advanced Data Processing\n\n```go\n// Complex data transformation pipeline\nusers := []User{{ID: 1, Name: \"Alice\", Active: true}, {ID: 2, Name: \"Bob\", Active: false}}\n\n// Group active users by name length, then extract IDs\nactiveUserIDs := lo.Pipe(\n    users,\n    lo.Filter(func(u User) bool { return u.Active }),\n    lo.GroupBy(func(u User) int { return len(u.Name) }),\n    lo.MapValues(func(users []User) []int {\n        return lo.Map(users, func(u User) int { return u.ID })\n    }),\n)\n// map[int][]int{5: []int{1}}\n\n// Safe nested data access\nconfig := map[string]any{\n    \"database\": map[string]any{\n        \"host\": \"localhost\",\n        \"port\": 5432,\n    },\n}\n\nhost := lo.ValueOr(lo.CoalesceMap(\n    lo.MapValues(config, func(v any) map[string]any {\n        if m, ok := v.(map[string]any); ok {\n            return m\n        }\n        return nil\n    }),\n), \"localhost\")\n```\n\n### Concurrency and Async Operations\n\n```go\n// Parallel processing of large datasets\nresults := lop.Map(items, func(item Item) Result {\n    return processItem(item) // Executed in parallel\n})\n\n// Debounce API calls to avoid rate limiting\ndebouncedSearch := lo.NewDebounce(300*time.Millisecond, func() {\n    results := searchAPI(query)\n    updateUI(results)\n})\n\n// Safe error handling with fallbacks\nresult, ok := lo.TryOr(func() (int, error) {\n    return dangerousOperation()\n}, 0)\n```\n\n### Functional Control Flow\n\n```go\n// Elegant conditional logic\nmessage := lo.If(user != nil, \"Welcome back!\").\n    ElseIfF(isGuest, func() string { return \"Welcome guest!\" }).\n    Else(\"Please login\")\n\n// Retry logic with exponential backoff\nresult, err := lo.AttemptWithDelay(3, time.Second, func(i int, d time.Duration) error {\n    return callExternalAPI(context.Background())\n})\n\n// Transaction management\ntx := lo.NewTransaction[Order]()\ndefer tx.Rollback()\n\norder, err := tx.Run(func() (Order, error) {\n    inventory := checkInventory(items)\n    if !inventory.Available {\n        return Order{}, errors.New(\"insufficient inventory\")\n    }\n    return createOrder(user, items)\n})\n```\n\n## Performance Considerations\n\nLo is engineered for performance-critical applications with several optimization strategies:\n\n### Memory Efficiency\n- **Zero-copy patterns**: Many helpers avoid unnecessary allocations by working with existing data\n- **Slice reuse**: Mutable variants (`lo/mutable`) enable in-place operations for memory-constrained environments\n- **Lazy evaluation**: Iterator patterns in `lo/iter` support streaming of large datasets\n- **Pre-allocation**: Collection sizes are pre-calculated when possible to minimize reallocations\n\n### Performance Characteristics\n- **Compile-time optimization**: Generic types enable compile-time specialization and optimization\n- **Minimal overhead**: Most helpers add zero or single-digit nanosecond overhead\n- **Cache-friendly**: Linear memory access patterns for better CPU cache utilization\n- **Branch prediction**: Hot paths are optimized for common case execution\n\n### Benchmarks and Optimization\nEvery helper includes comprehensive benchmarks covering:\n- Different input sizes (small, medium, large)\n- Various data types (int, string, structs)\n- Comparison with standard library alternatives\n- Memory allocation tracking\n\n```go\n// Example benchmark results for lo.Uniq vs manual implementation\nBenchmarkLoUniq-8          1000000    1200 ns/op    800 B/op   4 allocs/op\nBenchmarkManualUniq-8       5000000     240 ns/op     0 B/op   0 allocs/op  (when in-place)\n```\n\n### Production Optimization Tips\n1. **Use `lo/it`** for large datasets when memory is a concern\n2. **Leverage `lo/parallel`** for CPU-bound operations on large collections\n3. **Choose appropriate helpers** - some have specialized variants for specific use cases\n4. **Profile your code** - use Go's built-in profiling tools to identify bottlenecks\n5. **Consider streaming** - use iterators for very large datasets that don't fit in memory\n\n## Ecosystem and Community\n\n### Related Projects\nLo is part of a growing ecosystem of Go libraries that enhance developer productivity:\n\n- **[samber/ro](https://github.com/samber/ro)**: Reactive Programming library for Go\n- **[samber/do](https://github.com/samber/do)**: A dependency injection toolkit based on Go 1.18+ Generics\n- **[samber/mo](https://github.com/samber/mo)**: Monads based on Go 1.18+ Generics (Option, Result, Either...)\n\n### Community and Contributions\n- **Active development**: Regular updates and improvements from maintainers\n- **Community contributions**: Hundreds of contributors from around the world\n- **Corporate adoption**: Used by major companies including startups, fintech, and enterprise organizations\n- **Discussions**: Active GitHub discussions for feature requests and support\n\n## Migration and Adoption\n\n### From Standard Library\nMigrating from standard library `slices` and `maps` packages is straightforward:\n- Lo provides similar APIs with additional features\n- Many helpers drop-in replace standard library functions\n- Enhanced error handling and edge case coverage\n\n### From Other Libraries\nIf you're coming from other utility libraries:\n- Lo emphasizes Go idioms over direct ports from other languages\n- Type safety is prioritized over dynamic patterns\n- Performance is a key consideration in all implementations\n\n## License\n\nMIT License - see LICENSE file for details\n\n## Acknowledgments\n\nLo stands on the shoulders of giants:\n- Inspired by Lodash, Underscore.js, and functional programming concepts\n- Built upon Go's excellent generics implementation\n- Community-driven with contributions from hundreds of developers\n- Production-tested across diverse use cases and industries\n"
  },
  {
    "path": "docs/tsconfig.json",
    "content": "{\n  // This file is not used in compilation. It is here just for a nice editor experience.\n  \"extends\": \"@docusaurus/tsconfig\",\n  \"compilerOptions\": {\n    \"baseUrl\": \".\"\n  },\n  \"exclude\": [\".docusaurus\", \"build\"]\n}\n"
  },
  {
    "path": "errors.go",
    "content": "package lo\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"reflect\"\n)\n\nconst defaultAssertionFailureMessage = \"assertion failed\"\n\n// Validate is a helper that creates an error when a condition is not met.\n// Play: https://go.dev/play/p/vPyh51XpCBt\nfunc Validate(ok bool, format string, args ...any) error {\n\tif !ok {\n\t\treturn fmt.Errorf(format, args...)\n\t}\n\treturn nil\n}\n\nfunc messageFromMsgAndArgs(msgAndArgs ...any) string {\n\tif len(msgAndArgs) == 1 {\n\t\tif msgAsStr, ok := msgAndArgs[0].(string); ok {\n\t\t\treturn msgAsStr\n\t\t}\n\t\treturn fmt.Sprintf(\"%+v\", msgAndArgs[0])\n\t}\n\tif len(msgAndArgs) > 1 {\n\t\treturn fmt.Sprintf(msgAndArgs[0].(string), msgAndArgs[1:]...) //nolint:errcheck,forcetypeassert\n\t}\n\treturn \"\"\n}\n\n// MustChecker panics if err is error or false.\nvar MustChecker = func(err any, messageArgs ...any) {\n\tif err == nil {\n\t\treturn\n\t}\n\n\tswitch e := err.(type) {\n\tcase bool:\n\t\tif !e {\n\t\t\tmessage := messageFromMsgAndArgs(messageArgs...)\n\t\t\tif message == \"\" {\n\t\t\t\tmessage = \"not ok\"\n\t\t\t}\n\n\t\t\tpanic(message)\n\t\t}\n\n\tcase error:\n\t\tmessage := messageFromMsgAndArgs(messageArgs...)\n\t\tif message != \"\" {\n\t\t\tpanic(message + \": \" + e.Error())\n\t\t}\n\t\tpanic(e.Error())\n\n\tdefault:\n\t\tpanic(\"must: invalid err type '\" + reflect.TypeOf(err).Name() + \"', should either be a bool or an error\")\n\t}\n}\n\n// Must is a helper that wraps a call to a function returning a value and an error\n// and panics if err is error or false.\n// Play: https://go.dev/play/p/fOqtX5HudtN\nfunc Must[T any](val T, err any, messageArgs ...any) T {\n\tMustChecker(err, messageArgs...)\n\treturn val\n}\n\n// Must0 has the same behavior as Must, but callback returns no variable.\n// Play: https://go.dev/play/p/TMoWrRp3DyC\nfunc Must0(err any, messageArgs ...any) {\n\tMustChecker(err, messageArgs...)\n}\n\n// Must1 is an alias to Must.\n// Play: https://go.dev/play/p/TMoWrRp3DyC\nfunc Must1[T any](val T, err any, messageArgs ...any) T {\n\treturn Must(val, err, messageArgs...)\n}\n\n// Must2 has the same behavior as Must, but callback returns 2 variables.\n// Play: https://go.dev/play/p/TMoWrRp3DyC\nfunc Must2[T1, T2 any](val1 T1, val2 T2, err any, messageArgs ...any) (T1, T2) {\n\tMustChecker(err, messageArgs...)\n\treturn val1, val2\n}\n\n// Must3 has the same behavior as Must, but callback returns 3 variables.\n// Play: https://go.dev/play/p/TMoWrRp3DyC\nfunc Must3[T1, T2, T3 any](val1 T1, val2 T2, val3 T3, err any, messageArgs ...any) (T1, T2, T3) {\n\tMustChecker(err, messageArgs...)\n\treturn val1, val2, val3\n}\n\n// Must4 has the same behavior as Must, but callback returns 4 variables.\n// Play: https://go.dev/play/p/TMoWrRp3DyC\nfunc Must4[T1, T2, T3, T4 any](val1 T1, val2 T2, val3 T3, val4 T4, err any, messageArgs ...any) (T1, T2, T3, T4) {\n\tMustChecker(err, messageArgs...)\n\treturn val1, val2, val3, val4\n}\n\n// Must5 has the same behavior as Must, but callback returns 5 variables.\n// Play: https://go.dev/play/p/TMoWrRp3DyC\nfunc Must5[T1, T2, T3, T4, T5 any](val1 T1, val2 T2, val3 T3, val4 T4, val5 T5, err any, messageArgs ...any) (T1, T2, T3, T4, T5) {\n\tMustChecker(err, messageArgs...)\n\treturn val1, val2, val3, val4, val5\n}\n\n// Must6 has the same behavior as Must, but callback returns 6 variables.\n// Play: https://go.dev/play/p/TMoWrRp3DyC\nfunc Must6[T1, T2, T3, T4, T5, T6 any](val1 T1, val2 T2, val3 T3, val4 T4, val5 T5, val6 T6, err any, messageArgs ...any) (T1, T2, T3, T4, T5, T6) {\n\tMustChecker(err, messageArgs...)\n\treturn val1, val2, val3, val4, val5, val6\n}\n\n// Try calls the function and return false in case of error.\nfunc Try(callback func() error) (ok bool) {\n\tok = true\n\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tok = false\n\t\t}\n\t}()\n\n\terr := callback()\n\tif err != nil {\n\t\tok = false\n\t}\n\n\treturn ok\n}\n\n// Try0 has the same behavior as Try, but callback returns no variable.\n// Play: https://go.dev/play/p/mTyyWUvn9u4\nfunc Try0(callback func()) bool {\n\treturn Try(func() error {\n\t\tcallback()\n\t\treturn nil\n\t})\n}\n\n// Try1 is an alias to Try.\n// Play: https://go.dev/play/p/mTyyWUvn9u4\nfunc Try1(callback func() error) bool {\n\treturn Try(callback)\n}\n\n// Try2 has the same behavior as Try, but callback returns 2 variables.\n// Play: https://go.dev/play/p/mTyyWUvn9u4\nfunc Try2[T any](callback func() (T, error)) bool {\n\treturn Try(func() error {\n\t\t_, err := callback()\n\t\treturn err\n\t})\n}\n\n// Try3 has the same behavior as Try, but callback returns 3 variables.\n// Play: https://go.dev/play/p/mTyyWUvn9u4\nfunc Try3[T, R any](callback func() (T, R, error)) bool {\n\treturn Try(func() error {\n\t\t_, _, err := callback()\n\t\treturn err\n\t})\n}\n\n// Try4 has the same behavior as Try, but callback returns 4 variables.\n// Play: https://go.dev/play/p/mTyyWUvn9u4\nfunc Try4[T, R, S any](callback func() (T, R, S, error)) bool {\n\treturn Try(func() error {\n\t\t_, _, _, err := callback()\n\t\treturn err\n\t})\n}\n\n// Try5 has the same behavior as Try, but callback returns 5 variables.\n// Play: https://go.dev/play/p/mTyyWUvn9u4\nfunc Try5[T, R, S, Q any](callback func() (T, R, S, Q, error)) bool {\n\treturn Try(func() error {\n\t\t_, _, _, _, err := callback()\n\t\treturn err\n\t})\n}\n\n// Try6 has the same behavior as Try, but callback returns 6 variables.\n// Play: https://go.dev/play/p/mTyyWUvn9u4\nfunc Try6[T, R, S, Q, U any](callback func() (T, R, S, Q, U, error)) bool {\n\treturn Try(func() error {\n\t\t_, _, _, _, _, err := callback()\n\t\treturn err\n\t})\n}\n\n// TryOr has the same behavior as Must, but returns a default value in case of error.\n// Play: https://go.dev/play/p/B4F7Wg2Zh9X\nfunc TryOr[A any](callback func() (A, error), fallbackA A) (A, bool) {\n\treturn TryOr1(callback, fallbackA)\n}\n\n// TryOr1 has the same behavior as Must, but returns a default value in case of error.\n// Play: https://go.dev/play/p/B4F7Wg2Zh9X\nfunc TryOr1[A any](callback func() (A, error), fallbackA A) (A, bool) {\n\tok := false\n\n\tTry0(func() {\n\t\ta, err := callback()\n\t\tif err == nil {\n\t\t\tfallbackA = a\n\t\t\tok = true\n\t\t}\n\t})\n\n\treturn fallbackA, ok\n}\n\n// TryOr2 has the same behavior as Must, but returns a default value in case of error.\n// Play: https://go.dev/play/p/B4F7Wg2Zh9X\nfunc TryOr2[A, B any](callback func() (A, B, error), fallbackA A, fallbackB B) (A, B, bool) {\n\tok := false\n\n\tTry0(func() {\n\t\ta, b, err := callback()\n\t\tif err == nil {\n\t\t\tfallbackA = a\n\t\t\tfallbackB = b\n\t\t\tok = true\n\t\t}\n\t})\n\n\treturn fallbackA, fallbackB, ok\n}\n\n// TryOr3 has the same behavior as Must, but returns a default value in case of error.\n// Play: https://go.dev/play/p/B4F7Wg2Zh9X\nfunc TryOr3[A, B, C any](callback func() (A, B, C, error), fallbackA A, fallbackB B, fallbackC C) (A, B, C, bool) {\n\tok := false\n\n\tTry0(func() {\n\t\ta, b, c, err := callback()\n\t\tif err == nil {\n\t\t\tfallbackA = a\n\t\t\tfallbackB = b\n\t\t\tfallbackC = c\n\t\t\tok = true\n\t\t}\n\t})\n\n\treturn fallbackA, fallbackB, fallbackC, ok\n}\n\n// TryOr4 has the same behavior as Must, but returns a default value in case of error.\n// Play: https://go.dev/play/p/B4F7Wg2Zh9X\nfunc TryOr4[A, B, C, D any](callback func() (A, B, C, D, error), fallbackA A, fallbackB B, fallbackC C, fallbackD D) (A, B, C, D, bool) {\n\tok := false\n\n\tTry0(func() {\n\t\ta, b, c, d, err := callback()\n\t\tif err == nil {\n\t\t\tfallbackA = a\n\t\t\tfallbackB = b\n\t\t\tfallbackC = c\n\t\t\tfallbackD = d\n\t\t\tok = true\n\t\t}\n\t})\n\n\treturn fallbackA, fallbackB, fallbackC, fallbackD, ok\n}\n\n// TryOr5 has the same behavior as Must, but returns a default value in case of error.\n// Play: https://go.dev/play/p/B4F7Wg2Zh9X\nfunc TryOr5[A, B, C, D, E any](callback func() (A, B, C, D, E, error), fallbackA A, fallbackB B, fallbackC C, fallbackD D, fallbackE E) (A, B, C, D, E, bool) {\n\tok := false\n\n\tTry0(func() {\n\t\ta, b, c, d, e, err := callback()\n\t\tif err == nil {\n\t\t\tfallbackA = a\n\t\t\tfallbackB = b\n\t\t\tfallbackC = c\n\t\t\tfallbackD = d\n\t\t\tfallbackE = e\n\t\t\tok = true\n\t\t}\n\t})\n\n\treturn fallbackA, fallbackB, fallbackC, fallbackD, fallbackE, ok\n}\n\n// TryOr6 has the same behavior as Must, but returns a default value in case of error.\n// Play: https://go.dev/play/p/B4F7Wg2Zh9X\nfunc TryOr6[A, B, C, D, E, F any](callback func() (A, B, C, D, E, F, error), fallbackA A, fallbackB B, fallbackC C, fallbackD D, fallbackE E, fallbackF F) (A, B, C, D, E, F, bool) {\n\tok := false\n\n\tTry0(func() {\n\t\ta, b, c, d, e, f, err := callback()\n\t\tif err == nil {\n\t\t\tfallbackA = a\n\t\t\tfallbackB = b\n\t\t\tfallbackC = c\n\t\t\tfallbackD = d\n\t\t\tfallbackE = e\n\t\t\tfallbackF = f\n\t\t\tok = true\n\t\t}\n\t})\n\n\treturn fallbackA, fallbackB, fallbackC, fallbackD, fallbackE, fallbackF, ok\n}\n\n// TryWithErrorValue has the same behavior as Try, but also returns value passed to panic.\n// Play: https://go.dev/play/p/Kc7afQIT2Fs\nfunc TryWithErrorValue(callback func() error) (errorValue any, ok bool) {\n\tok = true\n\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tok = false\n\t\t\terrorValue = r\n\t\t}\n\t}()\n\n\terr := callback()\n\tif err != nil {\n\t\tok = false\n\t\terrorValue = err\n\t}\n\n\treturn errorValue, ok\n}\n\n// TryCatch has the same behavior as Try, but calls the catch function in case of error.\n// Play: https://go.dev/play/p/PnOON-EqBiU\nfunc TryCatch(callback func() error, catch func()) {\n\tif !Try(callback) {\n\t\tcatch()\n\t}\n}\n\n// TryCatchWithErrorValue has the same behavior as TryWithErrorValue, but calls the catch function in case of error.\n// Play: https://go.dev/play/p/8Pc9gwX_GZO\nfunc TryCatchWithErrorValue(callback func() error, catch func(any)) {\n\tif err, ok := TryWithErrorValue(callback); !ok {\n\t\tcatch(err)\n\t}\n}\n\n// ErrorsAs is a shortcut for errors.As(err, &&T).\n// Play: https://go.dev/play/p/8wk5rH8UfrE\nfunc ErrorsAs[T error](err error) (T, bool) {\n\tvar t T\n\tok := errors.As(err, &t)\n\treturn t, ok\n}\n\n// Assert does nothing when the condition is true, otherwise it panics with an optional message.\n// Play: https://go.dev/play/p/Xv8LLKBMNwI\nvar Assert = func(condition bool, message ...string) {\n\tif condition {\n\t\treturn\n\t}\n\n\tpanicMessage := defaultAssertionFailureMessage\n\tif len(message) > 0 {\n\t\tpanicMessage = fmt.Sprintf(\"%s: %s\", defaultAssertionFailureMessage, message[0])\n\t}\n\tpanic(panicMessage)\n}\n\n// Assertf does nothing when the condition is true, otherwise it panics with a formatted message.\n// Play: https://go.dev/play/p/TVPEmVcyrdY\nvar Assertf = func(condition bool, format string, args ...any) {\n\tif condition {\n\t\treturn\n\t}\n\n\tpanicMessage := fmt.Sprintf(\"%s: %s\", defaultAssertionFailureMessage, fmt.Sprintf(format, args...))\n\tpanic(panicMessage)\n}\n"
  },
  {
    "path": "errors_test.go",
    "content": "package lo\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/url\"\n\t\"reflect\"\n\t\"runtime/debug\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestValidate(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tslice := []string{\"a\"}\n\tresult1 := Validate(len(slice) == 0, \"Slice should be empty but contains %v\", slice)\n\n\tslice = []string{}\n\tresult2 := Validate(len(slice) == 0, \"Slice should be empty but contains %v\", slice)\n\n\tis.Error(result1)\n\tis.NoError(result2)\n}\n\nfunc TestMust(t *testing.T) { //nolint:paralleltest\n\t// t.Parallel()\n\tis := assert.New(t)\n\n\tis.Equal(\"foo\", Must(\"foo\", nil))\n\tis.PanicsWithValue(\"something went wrong\", func() {\n\t\tMust(\"\", errors.New(\"something went wrong\"))\n\t})\n\tis.PanicsWithValue(\"operation shouldn't fail: something went wrong\", func() {\n\t\tMust(\"\", errors.New(\"something went wrong\"), \"operation shouldn't fail\")\n\t})\n\tis.PanicsWithValue(\"operation shouldn't fail with foo: something went wrong\", func() {\n\t\tMust(\"\", errors.New(\"something went wrong\"), \"operation shouldn't fail with %s\", \"foo\")\n\t})\n\n\tis.Equal(1, Must(1, true))\n\tis.PanicsWithValue(\"not ok\", func() {\n\t\tMust(1, false)\n\t})\n\tis.PanicsWithValue(\"operation shouldn't fail\", func() {\n\t\tMust(1, false, \"operation shouldn't fail\")\n\t})\n\tis.PanicsWithValue(\"operation shouldn't fail with foo\", func() {\n\t\tMust(1, false, \"operation shouldn't fail with %s\", \"foo\")\n\t})\n\n\tcb := func() error {\n\t\treturn assert.AnError\n\t}\n\tis.PanicsWithValue(\"operation should fail: assert.AnError general error for testing\", func() {\n\t\tMust0(cb(), \"operation should fail\")\n\t})\n\n\tis.PanicsWithValue(\"must: invalid err type 'int', should either be a bool or an error\", func() {\n\t\tMust0(0)\n\t})\n\tis.PanicsWithValue(\"must: invalid err type 'string', should either be a bool or an error\", func() {\n\t\tMust0(\"error\")\n\t})\n}\n\nfunc TestMustX(t *testing.T) { //nolint:paralleltest\n\t// t.Parallel()\n\tis := assert.New(t)\n\n\t{\n\t\tis.PanicsWithValue(\"something went wrong\", func() {\n\t\t\tMust0(errors.New(\"something went wrong\"))\n\t\t})\n\t\tis.PanicsWithValue(\"operation shouldn't fail with foo: something went wrong\", func() {\n\t\t\tMust0(errors.New(\"something went wrong\"), \"operation shouldn't fail with %s\", \"foo\")\n\t\t})\n\t\tis.NotPanics(func() {\n\t\t\tMust0(nil)\n\t\t})\n\t}\n\n\t{\n\t\tval1 := Must1(1, nil)\n\t\tis.Equal(1, val1)\n\t\tis.PanicsWithValue(\"something went wrong\", func() {\n\t\t\tMust1(1, errors.New(\"something went wrong\"))\n\t\t})\n\t\tis.PanicsWithValue(\"operation shouldn't fail with foo: something went wrong\", func() {\n\t\t\tMust1(1, errors.New(\"something went wrong\"), \"operation shouldn't fail with %s\", \"foo\")\n\t\t})\n\t}\n\n\t{\n\t\tval1, val2 := Must2(1, 2, nil)\n\t\tis.Equal(1, val1)\n\t\tis.Equal(2, val2)\n\t\tis.PanicsWithValue(\"something went wrong\", func() {\n\t\t\tMust2(1, 2, errors.New(\"something went wrong\"))\n\t\t})\n\t\tis.PanicsWithValue(\"operation shouldn't fail with foo: something went wrong\", func() {\n\t\t\tMust2(1, 2, errors.New(\"something went wrong\"), \"operation shouldn't fail with %s\", \"foo\")\n\t\t})\n\t}\n\n\t{\n\t\tval1, val2, val3 := Must3(1, 2, 3, nil)\n\t\tis.Equal(1, val1)\n\t\tis.Equal(2, val2)\n\t\tis.Equal(3, val3)\n\t\tis.PanicsWithValue(\"something went wrong\", func() {\n\t\t\tMust3(1, 2, 3, errors.New(\"something went wrong\"))\n\t\t})\n\t\tis.PanicsWithValue(\"operation shouldn't fail with foo: something went wrong\", func() {\n\t\t\tMust3(1, 2, 3, errors.New(\"something went wrong\"), \"operation shouldn't fail with %s\", \"foo\")\n\t\t})\n\t}\n\n\t{\n\t\tval1, val2, val3, val4 := Must4(1, 2, 3, 4, nil)\n\t\tis.Equal(1, val1)\n\t\tis.Equal(2, val2)\n\t\tis.Equal(3, val3)\n\t\tis.Equal(4, val4)\n\t\tis.PanicsWithValue(\"something went wrong\", func() {\n\t\t\tMust4(1, 2, 3, 4, errors.New(\"something went wrong\"))\n\t\t})\n\t\tis.PanicsWithValue(\"operation shouldn't fail with foo: something went wrong\", func() {\n\t\t\tMust4(1, 2, 3, 4, errors.New(\"something went wrong\"), \"operation shouldn't fail with %s\", \"foo\")\n\t\t})\n\t}\n\n\t{\n\t\tval1, val2, val3, val4, val5 := Must5(1, 2, 3, 4, 5, nil)\n\t\tis.Equal(1, val1)\n\t\tis.Equal(2, val2)\n\t\tis.Equal(3, val3)\n\t\tis.Equal(4, val4)\n\t\tis.Equal(5, val5)\n\t\tis.PanicsWithValue(\"something went wrong\", func() {\n\t\t\tMust5(1, 2, 3, 4, 5, errors.New(\"something went wrong\"))\n\t\t})\n\t\tis.PanicsWithValue(\"operation shouldn't fail with foo: something went wrong\", func() {\n\t\t\tMust5(1, 2, 3, 4, 5, errors.New(\"something went wrong\"), \"operation shouldn't fail with %s\", \"foo\")\n\t\t})\n\t}\n\n\t{\n\t\tval1, val2, val3, val4, val5, val6 := Must6(1, 2, 3, 4, 5, 6, nil)\n\t\tis.Equal(1, val1)\n\t\tis.Equal(2, val2)\n\t\tis.Equal(3, val3)\n\t\tis.Equal(4, val4)\n\t\tis.Equal(5, val5)\n\t\tis.Equal(6, val6)\n\t\tis.PanicsWithValue(\"something went wrong\", func() {\n\t\t\tMust6(1, 2, 3, 4, 5, 6, errors.New(\"something went wrong\"))\n\t\t})\n\t\tis.PanicsWithValue(\"operation shouldn't fail with foo: something went wrong\", func() {\n\t\t\tMust6(1, 2, 3, 4, 5, 6, errors.New(\"something went wrong\"), \"operation shouldn't fail with %s\", \"foo\")\n\t\t})\n\t}\n\n\t{\n\t\tis.PanicsWithValue(\"not ok\", func() {\n\t\t\tMust0(false)\n\t\t})\n\t\tis.PanicsWithValue(\"operation shouldn't fail with foo\", func() {\n\t\t\tMust0(false, \"operation shouldn't fail with %s\", \"foo\")\n\t\t})\n\t\tis.NotPanics(func() {\n\t\t\tMust0(true)\n\t\t})\n\t}\n\n\t{\n\t\tval1 := Must1(1, true)\n\t\tis.Equal(1, val1)\n\t\tis.PanicsWithValue(\"not ok\", func() {\n\t\t\tMust1(1, false)\n\t\t})\n\t\tis.PanicsWithValue(\"operation shouldn't fail with foo\", func() {\n\t\t\tMust1(1, false, \"operation shouldn't fail with %s\", \"foo\")\n\t\t})\n\t}\n\n\t{\n\t\tval1, val2 := Must2(1, 2, true)\n\t\tis.Equal(1, val1)\n\t\tis.Equal(2, val2)\n\t\tis.PanicsWithValue(\"not ok\", func() {\n\t\t\tMust2(1, 2, false)\n\t\t})\n\t\tis.PanicsWithValue(\"operation shouldn't fail with foo\", func() {\n\t\t\tMust2(1, 2, false, \"operation shouldn't fail with %s\", \"foo\")\n\t\t})\n\t}\n\n\t{\n\t\tval1, val2, val3 := Must3(1, 2, 3, true)\n\t\tis.Equal(1, val1)\n\t\tis.Equal(2, val2)\n\t\tis.Equal(3, val3)\n\t\tis.PanicsWithValue(\"not ok\", func() {\n\t\t\tMust3(1, 2, 3, false)\n\t\t})\n\t\tis.PanicsWithValue(\"operation shouldn't fail with foo\", func() {\n\t\t\tMust3(1, 2, 3, false, \"operation shouldn't fail with %s\", \"foo\")\n\t\t})\n\t}\n\n\t{\n\t\tval1, val2, val3, val4 := Must4(1, 2, 3, 4, true)\n\t\tis.Equal(1, val1)\n\t\tis.Equal(2, val2)\n\t\tis.Equal(3, val3)\n\t\tis.Equal(4, val4)\n\t\tis.PanicsWithValue(\"not ok\", func() {\n\t\t\tMust4(1, 2, 3, 4, false)\n\t\t})\n\t\tis.PanicsWithValue(\"operation shouldn't fail with foo\", func() {\n\t\t\tMust4(1, 2, 3, 4, false, \"operation shouldn't fail with %s\", \"foo\")\n\t\t})\n\t}\n\n\t{\n\t\tval1, val2, val3, val4, val5 := Must5(1, 2, 3, 4, 5, true)\n\t\tis.Equal(1, val1)\n\t\tis.Equal(2, val2)\n\t\tis.Equal(3, val3)\n\t\tis.Equal(4, val4)\n\t\tis.Equal(5, val5)\n\t\tis.PanicsWithValue(\"not ok\", func() {\n\t\t\tMust5(1, 2, 3, 4, 5, false)\n\t\t})\n\t\tis.PanicsWithValue(\"operation shouldn't fail with foo\", func() {\n\t\t\tMust5(1, 2, 3, 4, 5, false, \"operation shouldn't fail with %s\", \"foo\")\n\t\t})\n\t}\n\n\t{\n\t\tval1, val2, val3, val4, val5, val6 := Must6(1, 2, 3, 4, 5, 6, true)\n\t\tis.Equal(1, val1)\n\t\tis.Equal(2, val2)\n\t\tis.Equal(3, val3)\n\t\tis.Equal(4, val4)\n\t\tis.Equal(5, val5)\n\t\tis.Equal(6, val6)\n\t\tis.PanicsWithValue(\"not ok\", func() {\n\t\t\tMust6(1, 2, 3, 4, 5, 6, false)\n\t\t})\n\t\tis.PanicsWithValue(\"operation shouldn't fail with foo\", func() {\n\t\t\tMust6(1, 2, 3, 4, 5, 6, false, \"operation shouldn't fail with %s\", \"foo\")\n\t\t})\n\t}\n}\n\nfunc mustCheckerWithStack(err any, messageArgs ...any) {\n\tif err == nil {\n\t\treturn\n\t}\n\n\tswitch e := err.(type) {\n\tcase bool:\n\t\tif !e {\n\t\t\tmessage := messageFromMsgAndArgs(messageArgs...)\n\t\t\tif message == \"\" {\n\t\t\t\tmessage = \"not ok\"\n\t\t\t}\n\n\t\t\t// panic(stackErrors.New(message))\n\t\t\tpanic(errorsJoin(errors.New(message), errors.New(string(debug.Stack()))))\n\t\t}\n\n\tcase error:\n\t\tmessage := messageFromMsgAndArgs(messageArgs...)\n\t\tif message != \"\" {\n\t\t\t// panic(stackErrors.Wrap(e, message))\n\t\t\tpanic(errorsJoin(e, errors.New(message), errors.New(string(debug.Stack()))))\n\t\t}\n\t\t// panic(stackErrors.WithStack(e))\n\t\tpanic(errorsJoin(e, errors.New(string(debug.Stack()))))\n\n\tdefault:\n\t\t// panic(stackErrors.New(\"must: invalid err type '\" + reflect.TypeOf(err).Name() + \"', should either be a bool or an error\"))\n\t\tpanic(errorsJoin(errors.New(\"must: invalid err type '\"+reflect.TypeOf(err).Name()+\"', should either be a bool or an error\"),\n\t\t\terrors.New(string(debug.Stack()))))\n\t}\n}\n\n// errorsJoin: var errorsJoin = errors.Join // only go 1.20+, not in go 1.18 .\nfunc errorsJoin(es ...error) joinErrors { return joinErrors(es) }\n\ntype joinErrors []error\n\nfunc (es joinErrors) Is(target error) bool {\n\tfor _, e := range es {\n\t\tif errors.Is(e, target) {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn error(es) == target\n}\n\nfunc (es joinErrors) Error() string {\n\tsb := strings.Builder{}\n\tfor _, e := range es {\n\t\tsb.WriteString(e.Error())\n\t\tsb.WriteRune('\\n')\n\t}\n\treturn sb.String()\n}\n\nfunc (es joinErrors) As(t any) bool {\n\tfor _, e := range es {\n\t\tif errors.As(e, t) {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\nfunc TestMustUserCustomHandler(t *testing.T) { //nolint:paralleltest\n\toldMustChecker := MustChecker\n\tMustChecker = mustCheckerWithStack\n\tdefer func() {\n\t\tMustChecker = oldMustChecker\n\t}()\n\n\tt.Run(\"wrap stack\", func(t *testing.T) { //nolint:paralleltest\n\t\terr, ok := TryWithErrorValue(func() error {\n\t\t\tMust(\"foo\", errors.New(\"wrap callstack\"))\n\t\t\treturn nil\n\t\t})\n\t\tassert.False(t, ok)\n\t\tfullErrStr := fmt.Sprintf(\"%+v\", err)\n\t\tassert.Contains(t, fullErrStr, \"/errors_test.go:\", fullErrStr)\n\t})\n\tt.Run(\"wrap as\", func(t *testing.T) { //nolint:paralleltest\n\t\te, ok := TryWithErrorValue(func() error {\n\t\t\tMust(\"foo\", errorsJoin(io.EOF, &url.Error{\n\t\t\t\tOp:  \"test op\",\n\t\t\t\tURL: \"test url\",\n\t\t\t\tErr: io.ErrUnexpectedEOF,\n\t\t\t}))\n\t\t\treturn nil\n\t\t})\n\t\tassert.False(t, ok)\n\t\terr, ok := e.(error)\n\t\tassert.True(t, ok)\n\t\terrURL, ok := ErrorsAs[*url.Error](err)\n\t\tassert.True(t, ok)\n\t\tassert.NotNil(t, errURL)\n\t\tif errURL != nil {\n\t\t\tassert.Equal(t, \"test url\", errURL.URL)\n\t\t\tassert.Equal(t, \"test op\", errURL.Op)\n\t\t\tassert.ErrorIs(t, err, io.EOF)\n\t\t\tassert.ErrorIs(t, err, io.ErrUnexpectedEOF)\n\t\t}\n\t})\n}\n\nfunc TestTry(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tis.False(Try(func() error {\n\t\tpanic(\"error\")\n\t}))\n\tis.True(Try(func() error {\n\t\treturn nil\n\t}))\n\tis.False(Try(func() error {\n\t\treturn errors.New(\"fail\")\n\t}))\n}\n\nfunc TestTryX(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tis.True(Try1(func() error {\n\t\treturn nil\n\t}))\n\n\tis.True(Try2(func() (string, error) {\n\t\treturn \"\", nil\n\t}))\n\n\tis.True(Try3(func() (string, string, error) {\n\t\treturn \"\", \"\", nil\n\t}))\n\n\tis.True(Try4(func() (string, string, string, error) {\n\t\treturn \"\", \"\", \"\", nil\n\t}))\n\n\tis.True(Try5(func() (string, string, string, string, error) {\n\t\treturn \"\", \"\", \"\", \"\", nil\n\t}))\n\n\tis.True(Try6(func() (string, string, string, string, string, error) {\n\t\treturn \"\", \"\", \"\", \"\", \"\", nil\n\t}))\n\n\tis.False(Try1(func() error {\n\t\tpanic(\"error\")\n\t}))\n\n\tis.False(Try2(func() (string, error) {\n\t\tpanic(\"error\")\n\t}))\n\n\tis.False(Try3(func() (string, string, error) {\n\t\tpanic(\"error\")\n\t}))\n\n\tis.False(Try4(func() (string, string, string, error) {\n\t\tpanic(\"error\")\n\t}))\n\n\tis.False(Try5(func() (string, string, string, string, error) {\n\t\tpanic(\"error\")\n\t}))\n\n\tis.False(Try6(func() (string, string, string, string, string, error) {\n\t\tpanic(\"error\")\n\t}))\n\n\tis.False(Try1(func() error {\n\t\treturn errors.New(\"foo\")\n\t}))\n\n\tis.False(Try2(func() (string, error) {\n\t\treturn \"\", errors.New(\"foo\")\n\t}))\n\n\tis.False(Try3(func() (string, string, error) {\n\t\treturn \"\", \"\", errors.New(\"foo\")\n\t}))\n\n\tis.False(Try4(func() (string, string, string, error) {\n\t\treturn \"\", \"\", \"\", errors.New(\"foo\")\n\t}))\n\n\tis.False(Try5(func() (string, string, string, string, error) {\n\t\treturn \"\", \"\", \"\", \"\", errors.New(\"foo\")\n\t}))\n\n\tis.False(Try6(func() (string, string, string, string, string, error) {\n\t\treturn \"\", \"\", \"\", \"\", \"\", errors.New(\"foo\")\n\t}))\n}\n\nfunc TestTryOr(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\ta1, ok1 := TryOr(func() (int, error) { panic(\"error\") }, 42)\n\ta2, ok2 := TryOr(func() (int, error) { return 21, assert.AnError }, 42)\n\ta3, ok3 := TryOr(func() (int, error) { return 21, nil }, 42)\n\n\tis.Equal(42, a1)\n\tis.False(ok1)\n\n\tis.Equal(42, a2)\n\tis.False(ok2)\n\n\tis.Equal(21, a3)\n\tis.True(ok3)\n}\n\nfunc TestTryOrX(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\t{\n\t\ta1, ok1 := TryOr1(func() (int, error) { panic(\"error\") }, 42)\n\t\ta2, ok2 := TryOr1(func() (int, error) { return 21, assert.AnError }, 42)\n\t\ta3, ok3 := TryOr1(func() (int, error) { return 21, nil }, 42)\n\n\t\tis.Equal(42, a1)\n\t\tis.False(ok1)\n\n\t\tis.Equal(42, a2)\n\t\tis.False(ok2)\n\n\t\tis.Equal(21, a3)\n\t\tis.True(ok3)\n\t}\n\n\t{\n\t\ta1, b1, ok1 := TryOr2(func() (int, string, error) { panic(\"error\") }, 42, \"hello\")\n\t\ta2, b2, ok2 := TryOr2(func() (int, string, error) { return 21, \"world\", assert.AnError }, 42, \"hello\")\n\t\ta3, b3, ok3 := TryOr2(func() (int, string, error) { return 21, \"world\", nil }, 42, \"hello\")\n\n\t\tis.Equal(42, a1)\n\t\tis.Equal(\"hello\", b1)\n\t\tis.False(ok1)\n\n\t\tis.Equal(42, a2)\n\t\tis.Equal(\"hello\", b2)\n\t\tis.False(ok2)\n\n\t\tis.Equal(21, a3)\n\t\tis.Equal(\"world\", b3)\n\t\tis.True(ok3)\n\t}\n\n\t{\n\t\ta1, b1, c1, ok1 := TryOr3(func() (int, string, bool, error) { panic(\"error\") }, 42, \"hello\", false)\n\t\ta2, b2, c2, ok2 := TryOr3(func() (int, string, bool, error) { return 21, \"world\", true, assert.AnError }, 42, \"hello\", false)\n\t\ta3, b3, c3, ok3 := TryOr3(func() (int, string, bool, error) { return 21, \"world\", true, nil }, 42, \"hello\", false)\n\n\t\tis.Equal(42, a1)\n\t\tis.Equal(\"hello\", b1)\n\t\tis.False(c1)\n\t\tis.False(ok1)\n\n\t\tis.Equal(42, a2)\n\t\tis.Equal(\"hello\", b2)\n\t\tis.False(c2)\n\t\tis.False(ok2)\n\n\t\tis.Equal(21, a3)\n\t\tis.Equal(\"world\", b3)\n\t\tis.True(c3)\n\t\tis.True(ok3)\n\t}\n\n\t{\n\t\ta1, b1, c1, d1, ok1 := TryOr4(func() (int, string, bool, int, error) { panic(\"error\") }, 42, \"hello\", false, 42)\n\t\ta2, b2, c2, d2, ok2 := TryOr4(func() (int, string, bool, int, error) { return 21, \"world\", true, 21, assert.AnError }, 42, \"hello\", false, 42)\n\t\ta3, b3, c3, d3, ok3 := TryOr4(func() (int, string, bool, int, error) { return 21, \"world\", true, 21, nil }, 42, \"hello\", false, 42)\n\n\t\tis.Equal(42, a1)\n\t\tis.Equal(\"hello\", b1)\n\t\tis.False(c1)\n\t\tis.Equal(42, d1)\n\t\tis.False(ok1)\n\n\t\tis.Equal(42, a2)\n\t\tis.Equal(\"hello\", b2)\n\t\tis.False(c2)\n\t\tis.Equal(42, d2)\n\t\tis.False(ok2)\n\n\t\tis.Equal(21, a3)\n\t\tis.Equal(\"world\", b3)\n\t\tis.True(c3)\n\t\tis.Equal(21, d3)\n\t\tis.True(ok3)\n\t}\n\n\t{\n\t\ta1, b1, c1, d1, e1, ok1 := TryOr5(func() (int, string, bool, int, int, error) { panic(\"error\") }, 42, \"hello\", false, 42, 42)\n\t\ta2, b2, c2, d2, e2, ok2 := TryOr5(func() (int, string, bool, int, int, error) { return 21, \"world\", true, 21, 21, assert.AnError }, 42, \"hello\", false, 42, 42)\n\t\ta3, b3, c3, d3, e3, ok3 := TryOr5(func() (int, string, bool, int, int, error) { return 21, \"world\", true, 21, 21, nil }, 42, \"hello\", false, 42, 42)\n\n\t\tis.Equal(42, a1)\n\t\tis.Equal(\"hello\", b1)\n\t\tis.False(c1)\n\t\tis.Equal(42, d1)\n\t\tis.Equal(42, e1)\n\t\tis.False(ok1)\n\n\t\tis.Equal(42, a2)\n\t\tis.Equal(\"hello\", b2)\n\t\tis.False(c2)\n\t\tis.Equal(42, d2)\n\t\tis.Equal(42, e2)\n\t\tis.False(ok2)\n\n\t\tis.Equal(21, a3)\n\t\tis.Equal(\"world\", b3)\n\t\tis.True(c3)\n\t\tis.Equal(21, d3)\n\t\tis.Equal(21, e3)\n\t\tis.True(ok3)\n\t}\n\n\t{\n\t\ta1, b1, c1, d1, e1, f1, ok1 := TryOr6(func() (int, string, bool, int, int, int, error) { panic(\"error\") }, 42, \"hello\", false, 42, 42, 42)\n\t\ta2, b2, c2, d2, e2, f2, ok2 := TryOr6(func() (int, string, bool, int, int, int, error) { return 21, \"world\", true, 21, 21, 21, assert.AnError }, 42, \"hello\", false, 42, 42, 42)\n\t\ta3, b3, c3, d3, e3, f3, ok3 := TryOr6(func() (int, string, bool, int, int, int, error) { return 21, \"world\", true, 21, 21, 21, nil }, 42, \"hello\", false, 42, 42, 42)\n\n\t\tis.Equal(42, a1)\n\t\tis.Equal(\"hello\", b1)\n\t\tis.False(c1)\n\t\tis.Equal(42, d1)\n\t\tis.Equal(42, e1)\n\t\tis.Equal(42, f1)\n\t\tis.False(ok1)\n\n\t\tis.Equal(42, a2)\n\t\tis.Equal(\"hello\", b2)\n\t\tis.False(c2)\n\t\tis.Equal(42, d2)\n\t\tis.Equal(42, e2)\n\t\tis.Equal(42, f2)\n\t\tis.False(ok2)\n\n\t\tis.Equal(21, a3)\n\t\tis.Equal(\"world\", b3)\n\t\tis.True(c3)\n\t\tis.Equal(21, d3)\n\t\tis.Equal(21, e3)\n\t\tis.Equal(21, f3)\n\t\tis.True(ok3)\n\t}\n}\n\nfunc TestTryWithErrorValue(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\terr, ok := TryWithErrorValue(func() error {\n\t\t// getting error in case of panic, using recover function\n\t\tpanic(\"error\")\n\t})\n\tis.False(ok)\n\tis.Equal(\"error\", err)\n\n\terr, ok = TryWithErrorValue(func() error {\n\t\treturn errors.New(\"foo\")\n\t})\n\tis.False(ok)\n\te, isError := err.(error)\n\tis.True(isError)\n\tis.EqualError(e, \"foo\")\n\n\terr, ok = TryWithErrorValue(func() error {\n\t\treturn nil\n\t})\n\tis.True(ok)\n\tis.Nil(err)\n}\n\nfunc TestTryCatch(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tcaught := false\n\tTryCatch(func() error {\n\t\tpanic(\"error\")\n\t}, func() {\n\t\t// error was caught\n\t\tcaught = true\n\t})\n\tis.True(caught)\n\n\tcaught = false\n\tTryCatch(func() error {\n\t\treturn nil\n\t}, func() {\n\t\t// no error to be caught\n\t\tcaught = true\n\t})\n\tis.False(caught)\n}\n\nfunc TestTryCatchWithErrorValue(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tcaught := false\n\tTryCatchWithErrorValue(func() error {\n\t\tpanic(\"error\")\n\t}, func(val any) {\n\t\t// error was caught\n\t\tcaught = val == \"error\"\n\t})\n\tis.True(caught)\n\n\tcaught = false\n\tTryCatchWithErrorValue(func() error {\n\t\treturn nil\n\t}, func(val any) {\n\t\t// no error to be caught\n\t\tcaught = true\n\t})\n\tis.False(caught)\n}\n\ntype internalError struct {\n\tfoobar string\n}\n\nfunc (e *internalError) Error() string {\n\treturn \"internal error\"\n}\n\nfunc TestErrorsAs(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\terr, ok := ErrorsAs[*internalError](errors.New(\"hello world\"))\n\tis.False(ok)\n\tis.Nil(err)\n\n\terr, ok = ErrorsAs[*internalError](&internalError{foobar: \"foobar\"})\n\tis.True(ok)\n\tis.Equal(&internalError{foobar: \"foobar\"}, err)\n\n\terr, ok = ErrorsAs[*internalError](nil)\n\tis.False(ok)\n\tis.Nil(err)\n}\n\nfunc TestAssert(t *testing.T) { //nolint:paralleltest\n\t// t.Parallel()\n\tis := assert.New(t)\n\n\tis.NotPanics(func() {\n\t\tAssert(true)\n\t})\n\n\tis.NotPanics(func() {\n\t\tAssert(true, \"user defined message\")\n\t})\n\n\tis.PanicsWithValue(\"assertion failed\", func() {\n\t\tAssert(false)\n\t})\n\n\tis.PanicsWithValue(\"assertion failed: user defined message\", func() {\n\t\tAssert(false, \"user defined message\")\n\t})\n\n\t// checks that the examples in `README.md` compile\n\t{\n\t\tage := 20\n\t\tis.NotPanics(func() {\n\t\t\tAssert(age >= 15)\n\t\t})\n\t\tis.NotPanics(func() {\n\t\t\tAssert(age >= 15, \"user age must be >= 15\")\n\t\t})\n\t}\n}\n\nfunc TestAssertf(t *testing.T) { //nolint:paralleltest\n\t// t.Parallel()\n\tis := assert.New(t)\n\n\tis.NotPanics(func() {\n\t\tAssertf(true, \"user defined message\")\n\t})\n\n\tis.NotPanics(func() {\n\t\tAssertf(true, \"user defined message %d %d\", 1, 2)\n\t})\n\n\tis.PanicsWithValue(\"assertion failed: user defined message\", func() {\n\t\tAssertf(false, \"user defined message\")\n\t})\n\n\tis.PanicsWithValue(\"assertion failed: user defined message 1 2\", func() {\n\t\tAssertf(false, \"user defined message %d %d\", 1, 2)\n\t})\n\n\t// checks that the example in `README.md` compiles\n\t{\n\t\tage := 7\n\t\tis.PanicsWithValue(\"assertion failed: user age must be >= 15, got 7\", func() {\n\t\t\tAssertf(age >= 15, \"user age must be >= 15, got %d\", age)\n\t\t})\n\t}\n}\n\nfunc TestAssertfWithCustom(t *testing.T) { //nolint:paralleltest\n\toldAssertf := Assertf\n\tAssertf = func(condition bool, format string, args ...any) {\n\t\tif !condition {\n\t\t\tpanic(fmt.Errorf(\"%s: %s\", \"customErr\", fmt.Sprintf(format, args...)))\n\t\t}\n\t}\n\tdefer func() {\n\t\tAssertf = oldAssertf\n\t}()\n\n\te, ok := TryWithErrorValue(func() error {\n\t\tAssertf(false, \"user defined message\")\n\t\treturn nil\n\t})\n\tassert.False(t, ok)\n\tassert.NotNil(t, e)\n\terr, ok := e.(error)\n\tassert.True(t, ok)\n\tassert.Equal(t, \"customErr: user defined message\", err.Error())\n}\n"
  },
  {
    "path": "exp/simd/BENCHMARK.md",
    "content": "# Benchmark\n\n## Summary\n\nBenchmarks show that running SIMD operations on small datasets is slower:\n\n```txt\nBenchmarkSumInt8/small/Fallback-lo-2            \t248740710\t        5.218 ns/op\nBenchmarkSumInt8/small/AVX-x16-2                \t126181464\t        9.485 ns/op\nBenchmarkSumInt8/small/AVX2-x32-2               \t 73059427\t        14.44 ns/op\nBenchmarkSumInt8/small/AVX512-x64-2             \t 49913169\t        24.41 ns/op\n```\n\nBut SIMD is much faster on large datasets:\n\n```txt\nBenchmarkSumInt8/xlarge/Fallback-lo-2           \t  273898\t         4383 ns/op\nBenchmarkSumInt8/xlarge/AVX-x16-2               \t 6928408\t        173.1 ns/op\nBenchmarkSumInt8/xlarge/AVX2-x32-2              \t12639586\t        94.09 ns/op\nBenchmarkSumInt8/xlarge/AVX512-x64-2            \t13509693\t        89.67 ns/op\n```\n\n## Run\n\n```bash\nexport GOEXPERIMENT=simd\ncd exp/simd/\ngo test -bench ./... -run=^Benchmark -benchmem -bench\n```\n\n```bash\n# get instruction set\ncat /proc/cpuinfo\n```\n\n## Result\n\n```\narchsimd.X86: AVX=true AVX2=true AVX512=true\ngoos: linux\ngoarch: amd64\npkg: github.com/samber/lo/exp/simd\ncpu: AMD EPYC 9454P 48-Core Processor    \n\n...\n\nPASS\nok  \tgithub.com/samber/lo/exp/simd\t596.213s\n```\n\n| Benchmark                                      | Iterations | Time/op     | Bytes/op | Allocs/op   |\n| ---------------------------------------------- | ---------- | ----------- | -------- | ----------- |\n| BenchmarkContainsInt8/tiny/AVX512-x16-2        | 312359204  | 3.625 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsInt8/tiny/AVX512-x32-2        | 277194441  | 4.531 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsInt8/tiny/AVX512-x64-2        | 336853209  | 3.401 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsInt8/small/AVX512-x16-2       | 449132103  | 2.670 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsInt8/small/AVX512-x32-2       | 148648339  | 8.332 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsInt8/small/AVX512-x64-2       | 143124861  | 7.982 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsInt8/medium/AVX512-x16-2      | 276816714  | 4.302 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsInt8/medium/AVX512-x32-2      | 345774957  | 3.529 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsInt8/medium/AVX512-x64-2      | 449868722  | 2.669 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsInt8/large/AVX512-x16-2          | 100000000  | 10.68 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsInt8/large/AVX512-x32-2         | 172934200  | 6.941 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsInt8/large/AVX512-x64-2       | 280992625  | 4.384 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsInt8/xlarge/AVX512-x16-2         | 187189599  | 6.203 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsInt8/xlarge/AVX512-x32-2        | 274289563  | 4.042 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsInt8/xlarge/AVX512-x64-2      | 375048555  | 2.953 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsInt8/massive/AVX512-x16-2        | 86434948   | 14.02 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsInt8/massive/AVX512-x32-2       | 153742346  | 8.012 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsInt8/massive/AVX512-x64-2     | 259404483  | 5.214 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsInt16/tiny/AVX512-x8-2           | 270309470  | 4.315 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsInt16/tiny/AVX512-x16-2         | 264874646  | 4.281 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsInt16/tiny/AVX512-x32-2       | 328810479  | 3.593 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsInt16/small/AVX512-x8-2          | 374742561  | 3.206 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsInt16/small/AVX512-x16-2        | 449838870  | 2.678 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsInt16/small/AVX512-x32-2      | 143845734  | 8.484 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsInt16/medium/AVX512-x8-2         | 185415590  | 6.448 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsInt16/medium/AVX512-x16-2       | 273780868  | 4.268 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsInt16/medium/AVX512-x32-2     | 350067484  | 3.431 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsInt16/large/AVX512-x8-2       | 61109778   | 19.66 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsInt16/large/AVX512-x16-2      | 100000000  | 10.74 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsInt16/large/AVX512-x32-2      | 182886646  | 6.575 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsInt16/xlarge/AVX512-x8-2      | 15220682   | 71.53 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsInt16/xlarge/AVX512-x16-2     | 31876572   | 37.57 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsInt16/xlarge/AVX512-x32-2     | 61992217   | 19.55 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsInt16/massive/AVX512-x8-2     | 4372000    | 262.8 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsInt16/massive/AVX512-x16-2    | 9019658    | 131.1 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsInt16/massive/AVX512-x32-2    | 16568430   | 74.25 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsInt32/tiny/AVX512-x4-2        | 499209442  | 2.406 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsInt32/tiny/AVX512-x8-2        | 350479609  | 3.433 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsInt32/tiny/AVX512-x16-2       | 280918554  | 4.309 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsInt32/small/AVX512-x4-2       | 299561596  | 4.028 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsInt32/small/AVX512-x8-2       | 374064310  | 3.205 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsInt32/small/AVX512-x16-2      | 499219765  | 2.418 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsInt32/medium/AVX512-x4-2      | 100000000  | 10.42 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsInt32/medium/AVX512-x8-2      | 187391635  | 6.403 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsInt32/medium/AVX512-x16-2     | 307955800  | 3.875 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsInt32/large/AVX512-x4-2       | 33256420   | 36.05 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsInt32/large/AVX512-x8-2       | 62421526   | 19.23 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsInt32/large/AVX512-x16-2      | 100000000  | 10.36 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsInt32/xlarge/AVX512-x4-2      | 8328856    | 144.9 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsInt32/xlarge/AVX512-x8-2      | 17039037   | 71.14 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsInt32/xlarge/AVX512-x16-2     | 28740241   | 41.77 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsInt32/massive/AVX512-x4-2     | 3525885    | 332.3 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsInt32/massive/AVX512-x8-2     | 7318027    | 164.5 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsInt32/massive/AVX512-x16-2    | 12181366   | 99.08 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsInt64/tiny/AVX512-x2-2        | 409014308  | 2.934 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsInt64/tiny/AVX512-x4-2        | 449210791  | 2.667 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsInt64/tiny/AVX512-x8-2        | 280998146  | 4.293 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsInt64/small/AVX512-x2-2       | 195631429  | 6.172 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsInt64/small/AVX512-x4-2       | 281272394  | 4.308 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsInt64/small/AVX512-x8-2       | 408933924  | 3.044 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsInt64/medium/AVX512-x2-2      | 63006909   | 18.94 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsInt64/medium/AVX512-x4-2      | 100000000  | 10.67 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsInt64/medium/AVX512-x8-2      | 197411126  | 6.016 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsInt64/large/AVX512-x2-2       | 17098578   | 70.57 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsInt64/large/AVX512-x4-2       | 32558013   | 37.07 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsInt64/large/AVX512-x8-2       | 57629485   | 20.94 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsInt64/xlarge/AVX512-x2-2      | 4286155    | 281.8 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsInt64/xlarge/AVX512-x4-2      | 8344772    | 143.8 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsInt64/xlarge/AVX512-x8-2      | 14428276   | 83.14 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsInt64/massive/AVX512-x2-2     | 1000000    | 1012 ns/op  | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsInt64/massive/AVX512-x4-2     | 2350525    | 510.6 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsInt64/massive/AVX512-x8-2     | 3773523    | 318.1 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsUint8/tiny/AVX512-x16-2       | 338880315  | 3.332 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsUint8/tiny/AVX512-x32-2       | 320784217  | 3.559 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsUint8/tiny/AVX512-x64-2       | 341599854  | 3.331 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsUint8/small/AVX512-x16-2      | 449579424  | 2.670 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsUint8/small/AVX512-x32-2      | 140368142  | 8.648 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsUint8/small/AVX512-x64-2      | 146828888  | 8.182 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsUint8/medium/AVX512-x16-2     | 374443974  | 3.472 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsUint8/medium/AVX512-x32-2     | 449271607  | 2.672 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsUint8/medium/AVX512-x64-2     | 598525731  | 2.018 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsUint8/large/AVX512-x16-2      | 254828565  | 4.956 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsUint8/large/AVX512-x32-2      | 407777484  | 2.938 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsUint8/large/AVX512-x64-2      | 443472316  | 2.666 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsUint8/xlarge/AVX512-x16-2     | 162196827  | 7.867 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsUint8/xlarge/AVX512-x32-2     | 268324950  | 4.518 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsUint8/xlarge/AVX512-x64-2     | 400437789  | 2.952 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsUint8/massive/AVX512-x16-2    | 214548872  | 5.640 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsUint8/massive/AVX512-x32-2    | 348431553  | 3.391 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsUint8/massive/AVX512-x64-2    | 459781908  | 2.455 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsUint16/tiny/AVX512-x8-2       | 276271912  | 4.297 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsUint16/tiny/AVX512-x16-2      | 281145528  | 4.270 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsUint16/tiny/AVX512-x32-2      | 315343911  | 3.667 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsUint16/small/AVX512-x8-2      | 374632351  | 3.204 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsUint16/small/AVX512-x16-2     | 449355727  | 2.670 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsUint16/small/AVX512-x32-2     | 138088146  | 8.395 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsUint16/medium/AVX512-x8-2     | 187276191  | 6.582 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsUint16/medium/AVX512-x16-2    | 281107980  | 4.306 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsUint16/medium/AVX512-x32-2    | 358850328  | 3.516 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsUint16/large/AVX512-x8-2      | 59025931   | 19.98 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsUint16/large/AVX512-x16-2     | 100000000  | 10.68 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsUint16/large/AVX512-x32-2     | 179631354  | 6.569 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsUint16/xlarge/AVX512-x8-2     | 16576267   | 71.63 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsUint16/xlarge/AVX512-x16-2    | 32578981   | 36.96 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsUint16/xlarge/AVX512-x32-2    | 61464870   | 19.44 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsUint16/massive/AVX512-x8-2    | 2153736    | 557.4 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsUint16/massive/AVX512-x16-2   | 4225728    | 281.3 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsUint16/massive/AVX512-x32-2   | 7829936    | 145.1 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsUint32/tiny/AVX512-x4-2       | 499390296  | 2.403 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsUint32/tiny/AVX512-x8-2       | 362964080  | 3.342 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsUint32/tiny/AVX512-x16-2      | 281063364  | 4.268 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsUint32/small/AVX512-x4-2      | 293867554  | 4.004 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsUint32/small/AVX512-x8-2      | 374510434  | 3.203 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsUint32/small/AVX512-x16-2     | 499714206  | 2.402 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsUint32/medium/AVX512-x4-2     | 100000000  | 10.42 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsUint32/medium/AVX512-x8-2     | 187258657  | 6.405 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsUint32/medium/AVX512-x16-2    | 312999210  | 3.881 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsUint32/large/AVX512-x4-2      | 33298366   | 36.02 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsUint32/large/AVX512-x8-2      | 62409421   | 19.23 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsUint32/large/AVX512-x16-2     | 100000000  | 10.10 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsUint32/xlarge/AVX512-x4-2     | 7948898    | 143.6 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsUint32/xlarge/AVX512-x8-2     | 17021738   | 70.49 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsUint32/xlarge/AVX512-x16-2    | 28742320   | 41.77 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsUint32/massive/AVX512-x4-2    | 1595774    | 751.1 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsUint32/massive/AVX512-x8-2    | 3094242    | 381.1 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsUint32/massive/AVX512-x16-2   | 5080051    | 238.3 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsUint64/tiny/AVX512-x2-2       | 374760351  | 3.203 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsUint64/tiny/AVX512-x4-2       | 498763054  | 2.419 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsUint64/tiny/AVX512-x8-2       | 319635274  | 3.582 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsUint64/small/AVX512-x2-2      | 187032452  | 6.447 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsUint64/small/AVX512-x4-2      | 299546244  | 4.009 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsUint64/small/AVX512-x8-2      | 373937659  | 3.207 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsUint64/medium/AVX512-x2-2     | 62413118   | 19.23 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsUint64/medium/AVX512-x4-2     | 113978791  | 10.42 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsUint64/medium/AVX512-x8-2     | 186965330  | 6.484 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsUint64/large/AVX512-x2-2      | 17005768   | 70.57 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsUint64/large/AVX512-x4-2      | 33286495   | 36.69 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsUint64/large/AVX512-x8-2      | 61486065   | 19.93 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsUint64/xlarge/AVX512-x2-2     | 4154370    | 280.8 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsUint64/xlarge/AVX512-x4-2     | 8371358    | 148.2 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsUint64/xlarge/AVX512-x8-2     | 14193795   | 72.36 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsUint64/massive/AVX512-x2-2    | 1773937    | 676.4 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsUint64/massive/AVX512-x4-2    | 3500168    | 343.0 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsUint64/massive/AVX512-x8-2    | 7097266    | 249.3 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsFloat32/tiny/AVX512-x4-2      | 410522160  | 2.675 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsFloat32/tiny/AVX512-x8-2      | 308565882  | 3.814 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsFloat32/tiny/AVX512-x16-2     | 315331897  | 3.755 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsFloat32/small/AVX512-x4-2     | 278219434  | 4.642 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsFloat32/small/AVX512-x8-2     | 362945481  | 3.287 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsFloat32/small/AVX512-x16-2    | 408523153  | 2.941 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsFloat32/medium/AVX512-x4-2    | 100000000  | 10.77 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsFloat32/medium/AVX512-x8-2    | 186186376  | 6.409 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsFloat32/medium/AVX512-x16-2   | 264255108  | 4.619 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsFloat32/large/AVX512-x4-2      | 33028701   | 36.27 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsFloat32/large/AVX512-x8-2      | 62465360   | 19.53 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsFloat32/large/AVX512-x16-2    | 108213310  | 10.95 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsFloat32/xlarge/AVX512-x4-2    | 8359381    | 143.6 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsFloat32/xlarge/AVX512-x8-2    | 17042701   | 70.46 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsFloat32/xlarge/AVX512-x16-2   | 31806921   | 37.13 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsFloat32/massive/AVX512-x4-2   | 1000000    | 1100 ns/op  | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsFloat32/massive/AVX512-x8-2   | 2164672    | 554.4 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsFloat32/massive/AVX512-x16-2  | 4201453    | 293.9 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsFloat64/tiny/AVX512-x2-2      | 362183925  | 3.223 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsFloat64/tiny/AVX512-x4-2      | 449021466  | 2.687 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsFloat64/tiny/AVX512-x8-2      | 320176149  | 3.820 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsFloat64/small/AVX512-x2-2     | 187139116  | 6.415 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsFloat64/small/AVX512-x4-2     | 280722585  | 4.300 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsFloat64/small/AVX512-x8-2     | 335670502  | 3.472 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsFloat64/medium/AVX512-x2-2    | 62343927   | 19.23 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsFloat64/medium/AVX512-x4-2    | 112332902  | 10.69 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsFloat64/medium/AVX512-x8-2    | 179610780  | 6.741 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsFloat64/large/AVX512-x2-2     | 16996959   | 70.51 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsFloat64/large/AVX512-x4-2     | 33017950   | 36.29 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsFloat64/large/AVX512-x8-2     | 60322328   | 19.73 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsFloat64/xlarge/AVX512-x2-2    | 4141281    | 282.9 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsFloat64/xlarge/AVX512-x4-2    | 7856590    | 145.0 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsFloat64/xlarge/AVX512-x8-2    | 16623739   | 72.06 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsFloat64/massive/AVX512-x2-2   | 541202     | 2195 ns/op  | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsFloat64/massive/AVX512-x4-2   | 1000000    | 1158 ns/op  | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsFloat64/massive/AVX512-x8-2   | 2115301    | 560.4 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsWorstCase/AVX512-x4-2         | 7651734    | 145.6 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsWorstCase/AVX512-x8-2         | 14921599   | 70.49 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsWorstCase/AVX512-x16-2        | 28708478   | 41.38 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsBestCase/AVX512-x4-2          | 534237578  | 2.136 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsBestCase/AVX512-x8-2          | 561252645  | 2.159 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsBestCase/AVX512-x16-2         | 560396454  | 2.137 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsNegative/tiny/AVX512-x4-2     | 499649139  | 2.401 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsNegative/tiny/AVX512-x8-2     | 329743240  | 3.421 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsNegative/tiny/AVX512-x16-2    | 280516392  | 4.276 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsNegative/small/AVX512-x4-2    | 299373171  | 4.006 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsNegative/small/AVX512-x8-2    | 374407988  | 3.267 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsNegative/small/AVX512-x16-2   | 486948346  | 2.424 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsNegative/medium/AVX512-x4-2   | 100000000  | 10.41 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsNegative/medium/AVX512-x8-2   | 182899621  | 6.412 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsNegative/medium/AVX512-x16-2  | 311969776  | 3.829 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsNegative/large/AVX512-x4-2    | 33309816   | 36.04 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsNegative/large/AVX512-x8-2    | 59912676   | 19.74 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsNegative/large/AVX512-x16-2   | 100000000  | 10.65 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsNegative/xlarge/AVX512-x4-2   | 8346818    | 143.7 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsNegative/xlarge/AVX512-x8-2   | 16980399   | 70.54 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsNegative/xlarge/AVX512-x16-2  | 28676455   | 42.94 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsNegative/massive/AVX512-x4-2  | 1000000    | 1151 ns/op  | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsNegative/massive/AVX512-x8-2  | 2161594    | 555.2 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsNegative/massive/AVX512-x16-2 | 3549094    | 350.5 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsInt8ByWidth/AVX512-x16-2      | 331533141  | 3.222 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsInt8ByWidth/AVX512-x32-2      | 408741681  | 3.193 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsInt8ByWidth/AVX512-x64-2      | 365382873  | 3.241 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsInt64SteadyState/AVX512-x2-2  | 5722603    | 211.5 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsInt64SteadyState/AVX512-x4-2  | 11711869   | 103.1 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkContainsInt64SteadyState/AVX512-x8-2  | 19671033   | 61.36 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumInt8/small/Fallback-lo-2           | 248740710  | 5.218 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumInt8/small/AVX-x16-2               | 126181464  | 9.485 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumInt8/small/AVX2-x32-2              | 73059427   | 14.44 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumInt8/small/AVX512-x64-2            | 49913169   | 24.41 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumInt8/medium/Fallback-lo-2          | 17278075   | 69.96 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumInt8/medium/AVX-x16-2              | 100000000  | 10.58 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumInt8/medium/AVX2-x32-2             | 91620999   | 13.10 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumInt8/medium/AVX512-x64-2           | 54082130   | 22.20 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumInt8/large/Fallback-lo-2           | 2006178    | 576.3 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumInt8/large/AVX-x16-2               | 41836690   | 27.82 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumInt8/large/AVX2-x32-2              | 51735399   | 23.04 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumInt8/large/AVX512-x64-2            | 40861586   | 29.40 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumInt8/xlarge/Fallback-lo-2          | 273898     | 4383 ns/op  | 0 B/op   | 0 allocs/op |\n| BenchmarkSumInt8/xlarge/AVX-x16-2              | 6928408    | 173.1 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumInt8/xlarge/AVX2-x32-2             | 12639586   | 94.09 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumInt8/xlarge/AVX512-x64-2           | 13509693   | 89.67 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumInt16/small/Fallback-lo-2          | 249444103  | 5.012 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumInt16/small/AVX-x8-2               | 244927230  | 5.052 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumInt16/small/AVX2-x16-2             | 122088517  | 9.715 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumInt16/small/AVX512-x32-2           | 54098370   | 22.00 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumInt16/medium/Fallback-lo-2         | 15782683   | 72.54 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumInt16/medium/AVX-x8-2              | 100000000  | 10.51 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumInt16/medium/AVX2-x16-2            | 100000000  | 10.75 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumInt16/medium/AVX512-x32-2          | 56147455   | 21.38 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumInt16/large/Fallback-lo-2          | 2173214    | 598.1 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumInt16/large/AVX-x8-2               | 26319481   | 44.73 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumInt16/large/AVX2-x16-2             | 40459519   | 27.91 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumInt16/large/AVX512-x32-2           | 39359752   | 31.28 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumInt16/xlarge/Fallback-lo-2         | 273932     | 4382 ns/op  | 0 B/op   | 0 allocs/op |\n| BenchmarkSumInt16/xlarge/AVX-x8-2              | 3557265    | 331.2 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumInt16/xlarge/AVX2-x16-2            | 6930166    | 173.4 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumInt16/xlarge/AVX512-x32-2          | 12100244   | 97.01 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumInt32/small/Fallback-lo-2          | 249566539  | 4.808 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumInt32/small/AVX-x4-2               | 259250019  | 4.581 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumInt32/small/AVX2-x8-2              | 232858933  | 5.404 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumInt32/small/AVX512-x16-2           | 100000000  | 11.18 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumInt32/medium/Fallback-lo-2         | 17274441   | 72.28 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumInt32/medium/AVX-x4-2              | 58400258   | 20.56 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumInt32/medium/AVX2-x8-2             | 110851756  | 10.67 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumInt32/medium/AVX512-x16-2          | 106593603  | 11.25 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumInt32/large/Fallback-lo-2          | 2171817    | 551.8 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumInt32/large/AVX-x4-2               | 8270253    | 146.0 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumInt32/large/AVX2-x8-2              | 22234518   | 46.06 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumInt32/large/AVX512-x16-2           | 37448763   | 32.31 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumInt32/xlarge/Fallback-lo-2         | 273699     | 4559 ns/op  | 0 B/op   | 0 allocs/op |\n| BenchmarkSumInt32/xlarge/AVX-x4-2              | 1000000    | 1102 ns/op  | 0 B/op   | 0 allocs/op |\n| BenchmarkSumInt32/xlarge/AVX2-x8-2             | 3586887    | 332.4 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumInt32/xlarge/AVX512-x16-2          | 7214437    | 170.5 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumInt64/small/Fallback-lo-2          | 417473124  | 2.886 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumInt64/small/AVX-x2-2               | 287521756  | 4.169 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumInt64/small/AVX2-x4-2              | 277783513  | 4.311 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumInt64/small/AVX512-x8-2            | 172823103  | 6.993 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumInt64/medium/Fallback-lo-2         | 34022653   | 35.27 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumInt64/medium/AVX-x2-2              | 49241248   | 24.05 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumInt64/medium/AVX2-x4-2             | 78897342   | 14.58 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumInt64/medium/AVX512-x8-2           | 84361297   | 14.03 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumInt64/large/Fallback-lo-2          | 3680988    | 282.3 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumInt64/large/AVX-x2-2               | 6293607    | 170.7 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumInt64/large/AVX2-x4-2              | 12739849   | 91.28 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumInt64/large/AVX512-x8-2            | 25508130   | 46.30 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumInt64/xlarge/Fallback-lo-2         | 546321     | 2283 ns/op  | 0 B/op   | 0 allocs/op |\n| BenchmarkSumInt64/xlarge/AVX-x2-2              | 877434     | 1289 ns/op  | 0 B/op   | 0 allocs/op |\n| BenchmarkSumInt64/xlarge/AVX2-x4-2             | 1845892    | 650.4 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumInt64/xlarge/AVX512-x8-2           | 2148355    | 550.8 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumFloat32/small/Fallback-lo-2        | 411100770  | 2.951 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumFloat32/small/AVX-x4-2             | 264013596  | 4.572 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumFloat32/small/AVX2-x8-2            | 174478266  | 6.911 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumFloat32/small/AVX512-x16-2         | 61182673   | 19.78 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumFloat32/medium/Fallback-lo-2       | 33815070   | 35.68 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumFloat32/medium/AVX-x4-2            | 58238188   | 20.66 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumFloat32/medium/AVX2-x8-2           | 91316544   | 13.26 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumFloat32/medium/AVX512-x16-2        | 80046624   | 15.08 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumFloat32/large/Fallback-lo-2        | 4304168    | 278.7 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumFloat32/large/AVX-x4-2             | 6198957    | 184.8 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumFloat32/large/AVX2-x8-2            | 12260169   | 86.60 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumFloat32/large/AVX512-x16-2         | 22147112   | 45.34 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumFloat32/xlarge/Fallback-lo-2       | 546901     | 2193 ns/op  | 0 B/op   | 0 allocs/op |\n| BenchmarkSumFloat32/xlarge/AVX-x4-2            | 736503     | 1622 ns/op  | 0 B/op   | 0 allocs/op |\n| BenchmarkSumFloat32/xlarge/AVX2-x8-2           | 1493887    | 810.5 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumFloat32/xlarge/AVX512-x16-2        | 2959298    | 393.4 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumFloat64/small/Fallback-lo-2        | 410778070  | 3.043 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumFloat64/small/AVX-x2-2             | 254156008  | 4.714 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumFloat64/small/AVX2-x4-2            | 227604434  | 5.323 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumFloat64/small/AVX512-x8-2          | 170099748  | 7.115 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumFloat64/medium/Fallback-lo-2       | 33646345   | 35.78 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumFloat64/medium/AVX-x2-2            | 32931152   | 34.92 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumFloat64/medium/AVX2-x4-2           | 75389446   | 16.79 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumFloat64/medium/AVX512-x8-2         | 89826181   | 13.33 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumFloat64/large/Fallback-lo-2        | 4293837    | 302.8 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumFloat64/large/AVX-x2-2             | 3146601    | 381.4 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumFloat64/large/AVX2-x4-2            | 6373876    | 184.3 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumFloat64/large/AVX512-x8-2          | 13464712   | 88.96 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumFloat64/xlarge/Fallback-lo-2       | 545764     | 2193 ns/op  | 0 B/op   | 0 allocs/op |\n| BenchmarkSumFloat64/xlarge/AVX-x2-2            | 368846     | 3390 ns/op  | 0 B/op   | 0 allocs/op |\n| BenchmarkSumFloat64/xlarge/AVX2-x4-2           | 709940     | 1613 ns/op  | 0 B/op   | 0 allocs/op |\n| BenchmarkSumFloat64/xlarge/AVX512-x8-2         | 1480214    | 808.6 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkMeanInt32/small/Fallback-lo-2         | 411529147  | 3.043 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkMeanInt32/small/AVX-x4-2              | 204428401  | 5.872 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkMeanInt32/small/AVX2-x8-2             | 187573928  | 6.214 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkMeanInt32/small/AVX512-x16-2          | 98346700   | 12.12 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkMeanInt32/medium/Fallback-lo-2        | 33481442   | 35.72 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkMeanInt32/medium/AVX-x4-2             | 52042394   | 22.12 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkMeanInt32/medium/AVX2-x8-2            | 96288541   | 13.44 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkMeanInt32/medium/AVX512-x16-2         | 100995780  | 11.90 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkMeanInt32/large/Fallback-lo-2         | 4296570    | 289.9 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkMeanInt32/large/AVX-x4-2              | 7743022    | 146.4 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkMeanInt32/large/AVX2-x8-2             | 24355988   | 46.26 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkMeanInt32/large/AVX512-x16-2          | 37322655   | 32.89 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkMeanInt32/xlarge/Fallback-lo-2        | 547008     | 2193 ns/op  | 0 B/op   | 0 allocs/op |\n| BenchmarkMeanInt32/xlarge/AVX-x4-2             | 1087246    | 1112 ns/op  | 0 B/op   | 0 allocs/op |\n| BenchmarkMeanInt32/xlarge/AVX2-x8-2            | 1386868    | 761.9 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkMeanInt32/xlarge/AVX512-x16-2         | 7166142    | 170.7 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkMeanFloat64/small/Fallback-lo-2       | 349760005  | 3.449 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkMeanFloat64/small/AVX-x2-2            | 189674538  | 6.293 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkMeanFloat64/small/AVX2-x4-2           | 159228600  | 7.531 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkMeanFloat64/small/AVX512-x8-2         | 110196433  | 10.89 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkMeanFloat64/medium/Fallback-lo-2      | 32968618   | 36.17 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkMeanFloat64/medium/AVX-x2-2           | 30863817   | 37.69 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkMeanFloat64/medium/AVX2-x4-2          | 62428772   | 19.66 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkMeanFloat64/medium/AVX512-x8-2        | 77140984   | 15.54 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkMeanFloat64/large/Fallback-lo-2       | 4281057    | 280.6 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkMeanFloat64/large/AVX-x2-2            | 3057349    | 389.4 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkMeanFloat64/large/AVX2-x4-2           | 6509438    | 185.9 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkMeanFloat64/large/AVX512-x8-2         | 12668032   | 93.50 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkMeanFloat64/xlarge/Fallback-lo-2      | 545898     | 2288 ns/op  | 0 B/op   | 0 allocs/op |\n| BenchmarkMeanFloat64/xlarge/AVX-x2-2           | 367671     | 4048 ns/op  | 0 B/op   | 0 allocs/op |\n| BenchmarkMeanFloat64/xlarge/AVX2-x4-2          | 739941     | 1621 ns/op  | 0 B/op   | 0 allocs/op |\n| BenchmarkMeanFloat64/xlarge/AVX512-x8-2        | 1434867    | 811.3 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkMinInt32/small/AVX-x4-2               | 312338268  | 3.860 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkMinInt32/small/AVX2-x8-2              | 238034872  | 5.042 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkMinInt32/small/AVX512-x16-2           | 152600943  | 6.661 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkMinInt32/medium/AVX-x4-2              | 61051266   | 19.73 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkMinInt32/medium/AVX2-x8-2             | 91792144   | 13.11 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkMinInt32/medium/AVX512-x16-2          | 99994540   | 12.18 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkMinInt32/large/AVX-x4-2               | 8604774    | 140.5 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkMinInt32/large/AVX2-x8-2              | 15581037   | 77.56 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkMinInt32/large/AVX512-x16-2           | 30512421   | 40.24 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkMinInt32/xlarge/AVX-x4-2              | 1000000    | 1110 ns/op  | 0 B/op   | 0 allocs/op |\n| BenchmarkMinInt32/xlarge/AVX2-x8-2             | 2158272    | 557.2 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkMinInt32/xlarge/AVX512-x16-2          | 4253668    | 282.6 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkMinFloat64/small/AVX-x2-2             | 264129410  | 4.544 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkMinFloat64/small/AVX2-x4-2            | 299587609  | 4.008 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkMinFloat64/small/AVX512-x8-2          | 100000000  | 10.05 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkMinFloat64/medium/AVX-x2-2            | 32778514   | 36.93 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkMinFloat64/medium/AVX2-x4-2           | 53356347   | 20.30 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkMinFloat64/medium/AVX512-x8-2         | 74832976   | 16.21 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkMinFloat64/large/AVX-x2-2             | 3863326    | 300.0 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkMinFloat64/large/AVX2-x4-2            | 7670576    | 146.5 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkMinFloat64/large/AVX512-x8-2          | 14017984   | 78.21 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkMinFloat64/xlarge/AVX-x2-2            | 492739     | 2195 ns/op  | 0 B/op   | 0 allocs/op |\n| BenchmarkMinFloat64/xlarge/AVX2-x4-2           | 1000000    | 1103 ns/op  | 0 B/op   | 0 allocs/op |\n| BenchmarkMinFloat64/xlarge/AVX512-x8-2         | 2145290    | 560.3 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkMaxInt32/small/AVX-x4-2               | 306585705  | 3.860 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkMaxInt32/small/AVX2-x8-2              | 237347997  | 5.086 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkMaxInt32/small/AVX512-x16-2           | 201433966  | 6.130 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkMaxInt32/medium/AVX-x4-2              | 60759631   | 19.92 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkMaxInt32/medium/AVX2-x8-2             | 90934662   | 13.13 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkMaxInt32/medium/AVX512-x16-2          | 98517944   | 12.18 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkMaxInt32/large/AVX-x4-2               | 8590542    | 139.6 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkMaxInt32/large/AVX2-x8-2              | 15770372   | 77.69 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkMaxInt32/large/AVX512-x16-2           | 30197324   | 39.32 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkMaxInt32/xlarge/AVX-x4-2              | 1000000    | 1104 ns/op  | 0 B/op   | 0 allocs/op |\n| BenchmarkMaxInt32/xlarge/AVX2-x8-2             | 2152038    | 562.1 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkMaxInt32/xlarge/AVX512-x16-2          | 3917990    | 296.7 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkMaxFloat64/small/AVX-x2-2             | 249617162  | 4.816 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkMaxFloat64/small/AVX2-x4-2            | 207017514  | 5.855 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkMaxFloat64/small/AVX512-x8-2          | 66520290   | 17.74 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkMaxFloat64/medium/AVX-x2-2            | 32307492   | 36.92 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkMaxFloat64/medium/AVX2-x4-2           | 57306838   | 20.77 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkMaxFloat64/medium/AVX512-x8-2         | 56911946   | 21.12 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkMaxFloat64/large/AVX-x2-2             | 4259366    | 287.1 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkMaxFloat64/large/AVX2-x4-2            | 7905420    | 148.9 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkMaxFloat64/large/AVX512-x8-2          | 14100686   | 83.43 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkMaxFloat64/xlarge/AVX-x2-2            | 545378     | 2243 ns/op  | 0 B/op   | 0 allocs/op |\n| BenchmarkMaxFloat64/xlarge/AVX2-x4-2           | 1000000    | 1113 ns/op  | 0 B/op   | 0 allocs/op |\n| BenchmarkMaxFloat64/xlarge/AVX512-x8-2         | 2119741    | 565.7 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumInt8ByWidth/Fallback-lo-2          | 896775     | 1335 ns/op  | 0 B/op   | 0 allocs/op |\n| BenchmarkSumInt8ByWidth/AVX-x16-2              | 12557700   | 94.52 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumInt8ByWidth/AVX2-x32-2             | 18702537   | 55.03 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumInt8ByWidth/AVX512-x64-2           | 21342572   | 56.10 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumInt64SteadyState/Fallback-lo-2     | 513738     | 2195 ns/op  | 0 B/op   | 0 allocs/op |\n| BenchmarkSumInt64SteadyState/AVX-x2-2          | 928376     | 1296 ns/op  | 0 B/op   | 0 allocs/op |\n| BenchmarkSumInt64SteadyState/AVX2-x4-2         | 1836968    | 888.1 ns/op | 0 B/op   | 0 allocs/op |\n| BenchmarkSumInt64SteadyState/AVX512-x8-2       | 2141715    | 551.3 ns/op | 0 B/op   | 0 allocs/op |\n"
  },
  {
    "path": "exp/simd/README.md",
    "content": "# SIMD experiment (Go 1.26+)\n\nThis package requires **Go 1.26** with `GOEXPERIMENT=simd` and **amd64**.\n\nSee [benchmarks](./BENCHMARK.md).\n\n## CPU compatibility (avoiding SIGILL)\n\nIf you see **SIGILL: illegal instruction** when running tests, the CPU or VM does not support the SIMD instructions used by that code.\n\n### Check support on Linux\n\n```bash\n# List SIMD-related flags\ngrep -E 'avx' /proc/cpuinfo\n\n# Or with lscpu\nlscpu | grep -i avx\n```\n\n**Rough mapping:**\n\n| Tests / code      | Required flag(s)           | Typical CPUs                                                            |\n| ----------------- | -------------------------- | ----------------------------------------------------------------------- |\n| AVX (128-bit)     | `avx` (baseline on amd64)  | All amd64                                                               |\n| AVX2 (256-bit)    | `avx2`                     | Intel Haswell+, AMD Excavator+                                          |\n| AVX-512 (512-bit) | `avx512f`                  | Intel Skylake-X+, some Xeons; many AMD/consumer CPUs do **not** have it |\n\n### What the tests do\n\n- **AVX tests** (128-bit) call `requireAVX(t)` and are **skipped** if the CPU does not support AVX.\n- **AVX2 tests** call `requireAVX2(t)` and are **skipped** if the CPU does not support AVX2 (no SIGILL).\n- **AVX-512 tests** (when enabled) should call `requireAVX512(t)` and skip when AVX-512 is not available.\n\nSo on a machine without AVX2, AVX2 tests will show as skipped instead of crashing.\n\n### Run only AVX tests\n\nIf your environment does not support AVX2/AVX-512, you can still run the AVX (128-bit) tests:\n\n```bash\nGOEXPERIMENT=simd go test -run AVX ./...\n```\n"
  },
  {
    "path": "exp/simd/cpu_amd64.go",
    "content": "//go:build go1.26 && goexperiment.simd && amd64\n\npackage simd\n\nimport \"simd/archsimd\"\n\nconst (\n\tsimdLanes2  = uint(2)\n\tsimdLanes4  = uint(4)\n\tsimdLanes8  = uint(8)\n\tsimdLanes16 = uint(16)\n\tsimdLanes32 = uint(32)\n\tsimdLanes64 = uint(64)\n)\n\n// simdFeature represents the highest available SIMD instruction set\ntype simdFeature int\n\nconst (\n\tsimdFeatureNone simdFeature = iota\n\tsimdFeatureAVX\n\tsimdFeatureAVX2\n\tsimdFeatureAVX512\n)\n\n// currentSimdFeature is cached at package init to avoid repeated CPU feature checks\nvar currentSimdFeature simdFeature\n\nfunc init() {\n\tif archsimd.X86.AVX512() {\n\t\tcurrentSimdFeature = simdFeatureAVX512\n\t} else if archsimd.X86.AVX2() {\n\t\tcurrentSimdFeature = simdFeatureAVX2\n\t} else if archsimd.X86.AVX() {\n\t\tcurrentSimdFeature = simdFeatureAVX\n\t}\n}\n"
  },
  {
    "path": "exp/simd/cpu_amd64_test.go",
    "content": "//go:build go1.26 && goexperiment.simd && amd64\n\npackage simd\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"testing\"\n\n\t\"simd/archsimd\"\n)\n\n// skipHelper is a small interface implemented by both *testing.T and *testing.B\n// to allow unified CPU feature requirement checking for both tests and benchmarks.\ntype skipHelper interface {\n\tHelper()\n\tSkipf(format string, args ...any)\n}\n\n// How to check if your Linux CPU supports SIMD (avoids SIGILL):\n//\n//   grep -E 'avx' /proc/cpuinfo\n//\n// Or:  lscpu | grep -i avx\n//\n// You need:\n//   - AVX tests (128-bit):  avx in flags (baseline on amd64)\n//   - AVX2 tests (256-bit):  avx2  in flags\n//   - AVX-512 tests:        avx512f (and often avx512bw, avx512vl)\n//\n// If your CPU lacks AVX or AVX2 or AVX-512, tests that use them will be skipped automatically.\n\n// requireAVX skips the test/benchmark if the CPU does not support AVX (128-bit SIMD).\n// Use at the start of each AVX test/benchmark to avoid SIGILL on older or non-x86 systems.\nfunc requireAVX(t skipHelper) {\n\tt.Helper()\n\tif !archsimd.X86.AVX() {\n\t\tt.Skipf(\"CPU does not support AVX; skipping. Check compatibility: grep avx /proc/cpuinfo\")\n\t}\n}\n\n// requireAVX2 skips the test/benchmark if the CPU does not support AVX2 (256-bit SIMD).\n// Use at the start of each AVX2 test/benchmark to avoid SIGILL on older or non-x86 systems.\nfunc requireAVX2(t skipHelper) {\n\tt.Helper()\n\tif !archsimd.X86.AVX2() {\n\t\tt.Skipf(\"CPU does not support AVX2; skipping. Check compatibility: grep avx2 /proc/cpuinfo\")\n\t}\n}\n\n// requireAVX512 skips the test/benchmark if the CPU does not support AVX-512 Foundation.\n// Use at the start of each AVX-512 test/benchmark to avoid SIGILL on CPUs without AVX-512.\nfunc requireAVX512(t skipHelper) {\n\tt.Helper()\n\tif !archsimd.X86.AVX512() {\n\t\tt.Skipf(\"CPU does not support AVX-512; skipping. Check compatibility: grep avx512 /proc/cpuinfo\")\n\t}\n}\n\n// PrintCPUFeatures prints detected x86 SIMD features (for debugging).\n// Run: go test -run PrintCPUFeatures -v\nfunc PrintCPUFeatures(t *testing.T) {\n\tfmt.Fprintf(os.Stdout, \"X86 HasAVX=%v HasAVX2=%v HasAVX512=%v\\n\",\n\t\tarchsimd.X86.AVX(), archsimd.X86.AVX2(), archsimd.X86.AVX512())\n}\n"
  },
  {
    "path": "exp/simd/go.mod",
    "content": "module github.com/samber/lo/exp/simd\n\ngo 1.26.0\n\nrequire github.com/samber/lo v0.0.0\n\nrequire golang.org/x/text v0.22.0 // indirect\n\nreplace github.com/samber/lo => ../../\n"
  },
  {
    "path": "exp/simd/go.sum",
    "content": "github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=\ngithub.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=\ngithub.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=\ngithub.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=\ngithub.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=\ngithub.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=\ngo.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A=\ngo.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4=\ngolang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=\ngolang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=\ngopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=\ngopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=\n"
  },
  {
    "path": "exp/simd/intersect_avx512.go",
    "content": "//go:build go1.26 && goexperiment.simd && amd64\n\npackage simd\n\nimport (\n\t\"simd/archsimd\"\n)\n\n// ContainsInt8x16 checks if collection contains target using AVX SIMD and AVX-512 SIMD\nfunc ContainsInt8x16[T ~int8](collection []T, target T) bool {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn false\n\t}\n\n\tconst lanes = simdLanes16\n\ttargetVec := archsimd.BroadcastInt8x16(int8(target))\n\n\tbase := unsafeSliceInt8(collection, length)\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\ts := base[i : i+lanes]\n\t\tv := archsimd.LoadInt8x16Slice(s)\n\n\t\t// Compare for equality; Equal returns a mask, ToBits() its bitmask.\n\t\tcmp := v.Equal(targetVec)\n\t\tif cmp.ToBits() != 0 {\n\t\t\treturn true\n\t\t}\n\t}\n\n\t// Handle remaining elements\n\tfor ; i < length; i++ {\n\t\tif collection[i] == target {\n\t\t\treturn true\n\t\t}\n\t}\n\n\treturn false\n}\n\n// ContainsInt16x8 checks if collection contains target using AVX SIMD and AVX-512 SIMD\nfunc ContainsInt16x8[T ~int16](collection []T, target T) bool {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn false\n\t}\n\n\tconst lanes = simdLanes8\n\ttargetVec := archsimd.BroadcastInt16x8(int16(target))\n\n\tbase := unsafeSliceInt16(collection, length)\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\ts := base[i : i+lanes]\n\t\tv := archsimd.LoadInt16x8Slice(s)\n\n\t\tcmp := v.Equal(targetVec)\n\t\tif cmp.ToBits() != 0 {\n\t\t\treturn true\n\t\t}\n\t}\n\n\tfor ; i < length; i++ {\n\t\tif collection[i] == target {\n\t\t\treturn true\n\t\t}\n\t}\n\n\treturn false\n}\n\n// ContainsInt32x4 checks if collection contains target using AVX SIMD and AVX-512 SIMD\nfunc ContainsInt32x4[T ~int32](collection []T, target T) bool {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn false\n\t}\n\n\tconst lanes = simdLanes4\n\ttargetVec := archsimd.BroadcastInt32x4(int32(target))\n\n\tbase := unsafeSliceInt32(collection, length)\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\ts := base[i : i+lanes]\n\t\tv := archsimd.LoadInt32x4Slice(s)\n\n\t\tcmp := v.Equal(targetVec)\n\t\tif cmp.ToBits() != 0 {\n\t\t\treturn true\n\t\t}\n\t}\n\n\tfor ; i < length; i++ {\n\t\tif collection[i] == target {\n\t\t\treturn true\n\t\t}\n\t}\n\n\treturn false\n}\n\n// ContainsInt64x2 checks if collection contains target using AVX SIMD and AVX-512 SIMD\nfunc ContainsInt64x2[T ~int64](collection []T, target T) bool {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn false\n\t}\n\n\tconst lanes = simdLanes2\n\ttargetVec := archsimd.BroadcastInt64x2(int64(target))\n\n\tbase := unsafeSliceInt64(collection, length)\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\ts := base[i : i+lanes]\n\t\tv := archsimd.LoadInt64x2Slice(s)\n\n\t\tcmp := v.Equal(targetVec)\n\t\tif cmp.ToBits() != 0 {\n\t\t\treturn true\n\t\t}\n\t}\n\n\tfor ; i < length; i++ {\n\t\tif collection[i] == target {\n\t\t\treturn true\n\t\t}\n\t}\n\n\treturn false\n}\n\n// ContainsUint8x16 checks if collection contains target using AVX SIMD and AVX-512 SIMD\nfunc ContainsUint8x16[T ~uint8](collection []T, target T) bool {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn false\n\t}\n\n\tconst lanes = simdLanes16\n\ttargetVec := archsimd.BroadcastUint8x16(uint8(target))\n\n\tbase := unsafeSliceUint8(collection, length)\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\ts := base[i : i+lanes]\n\t\tv := archsimd.LoadUint8x16Slice(s)\n\n\t\tcmp := v.Equal(targetVec)\n\t\tif cmp.ToBits() != 0 {\n\t\t\treturn true\n\t\t}\n\t}\n\n\tfor ; i < length; i++ {\n\t\tif collection[i] == target {\n\t\t\treturn true\n\t\t}\n\t}\n\n\treturn false\n}\n\n// ContainsUint16x8 checks if collection contains target using AVX SIMD and AVX-512 SIMD\nfunc ContainsUint16x8[T ~uint16](collection []T, target T) bool {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn false\n\t}\n\n\tconst lanes = simdLanes8\n\ttargetVec := archsimd.BroadcastUint16x8(uint16(target))\n\n\tbase := unsafeSliceUint16(collection, length)\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\ts := base[i : i+lanes]\n\t\tv := archsimd.LoadUint16x8Slice(s)\n\n\t\tcmp := v.Equal(targetVec)\n\t\tif cmp.ToBits() != 0 {\n\t\t\treturn true\n\t\t}\n\t}\n\n\tfor ; i < length; i++ {\n\t\tif collection[i] == target {\n\t\t\treturn true\n\t\t}\n\t}\n\n\treturn false\n}\n\n// ContainsUint32x4 checks if collection contains target using AVX SIMD and AVX-512 SIMD\nfunc ContainsUint32x4[T ~uint32](collection []T, target T) bool {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn false\n\t}\n\n\tconst lanes = simdLanes4\n\ttargetVec := archsimd.BroadcastUint32x4(uint32(target))\n\n\tbase := unsafeSliceUint32(collection, length)\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\ts := base[i : i+lanes]\n\t\tv := archsimd.LoadUint32x4Slice(s)\n\n\t\tcmp := v.Equal(targetVec)\n\t\tif cmp.ToBits() != 0 {\n\t\t\treturn true\n\t\t}\n\t}\n\n\tfor ; i < length; i++ {\n\t\tif collection[i] == target {\n\t\t\treturn true\n\t\t}\n\t}\n\n\treturn false\n}\n\n// ContainsUint64x2 checks if collection contains target using AVX SIMD and AVX-512 SIMD\nfunc ContainsUint64x2[T ~uint64](collection []T, target T) bool {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn false\n\t}\n\n\tconst lanes = simdLanes2\n\ttargetVec := archsimd.BroadcastUint64x2(uint64(target))\n\n\tbase := unsafeSliceUint64(collection, length)\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\ts := base[i : i+lanes]\n\t\tv := archsimd.LoadUint64x2Slice(s)\n\n\t\tcmp := v.Equal(targetVec)\n\t\tif cmp.ToBits() != 0 {\n\t\t\treturn true\n\t\t}\n\t}\n\n\tfor ; i < length; i++ {\n\t\tif collection[i] == target {\n\t\t\treturn true\n\t\t}\n\t}\n\n\treturn false\n}\n\n// ContainsFloat32x4 checks if collection contains target using AVX SIMD and AVX-512 SIMD\nfunc ContainsFloat32x4[T ~float32](collection []T, target T) bool {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn false\n\t}\n\n\tconst lanes = simdLanes4\n\ttargetVec := archsimd.BroadcastFloat32x4(float32(target))\n\n\tbase := unsafeSliceFloat32(collection, length)\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\ts := base[i : i+lanes]\n\t\tv := archsimd.LoadFloat32x4Slice(s)\n\n\t\tcmp := v.Equal(targetVec)\n\t\tif cmp.ToBits() != 0 {\n\t\t\treturn true\n\t\t}\n\t}\n\n\tfor ; i < length; i++ {\n\t\tif collection[i] == target {\n\t\t\treturn true\n\t\t}\n\t}\n\n\treturn false\n}\n\n// ContainsFloat64x2 checks if collection contains target using AVX SIMD and AVX-512 SIMD\nfunc ContainsFloat64x2[T ~float64](collection []T, target T) bool {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn false\n\t}\n\n\tconst lanes = simdLanes2\n\ttargetVec := archsimd.BroadcastFloat64x2(float64(target))\n\n\tbase := unsafeSliceFloat64(collection, length)\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\ts := base[i : i+lanes]\n\t\tv := archsimd.LoadFloat64x2Slice(s)\n\n\t\tcmp := v.Equal(targetVec)\n\t\tif cmp.ToBits() != 0 {\n\t\t\treturn true\n\t\t}\n\t}\n\n\tfor ; i < length; i++ {\n\t\tif collection[i] == target {\n\t\t\treturn true\n\t\t}\n\t}\n\n\treturn false\n}\n\n// ContainsInt8x32 checks if collection contains target using AVX2 SIMD\nfunc ContainsInt8x32[T ~int8](collection []T, target T) bool {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn false\n\t}\n\n\tconst lanes = simdLanes32\n\ttargetVec := archsimd.BroadcastInt8x32(int8(target))\n\n\tbase := unsafeSliceInt8(collection, length)\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\ts := base[i : i+lanes]\n\t\tv := archsimd.LoadInt8x32Slice(s)\n\n\t\tcmp := v.Equal(targetVec)\n\t\tif cmp.ToBits() != 0 {\n\t\t\treturn true\n\t\t}\n\t}\n\n\tfor ; i < length; i++ {\n\t\tif collection[i] == target {\n\t\t\treturn true\n\t\t}\n\t}\n\n\treturn false\n}\n\n// ContainsInt16x16 checks if collection contains target using AVX2 SIMD\nfunc ContainsInt16x16[T ~int16](collection []T, target T) bool {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn false\n\t}\n\n\tconst lanes = simdLanes16\n\ttargetVec := archsimd.BroadcastInt16x16(int16(target))\n\n\tbase := unsafeSliceInt16(collection, length)\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\ts := base[i : i+lanes]\n\t\tv := archsimd.LoadInt16x16Slice(s)\n\n\t\tcmp := v.Equal(targetVec)\n\t\tif cmp.ToBits() != 0 {\n\t\t\treturn true\n\t\t}\n\t}\n\n\tfor ; i < length; i++ {\n\t\tif collection[i] == target {\n\t\t\treturn true\n\t\t}\n\t}\n\n\treturn false\n}\n\n// ContainsInt32x8 checks if collection contains target using AVX2 SIMD\nfunc ContainsInt32x8[T ~int32](collection []T, target T) bool {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn false\n\t}\n\n\tconst lanes = simdLanes8\n\ttargetVec := archsimd.BroadcastInt32x8(int32(target))\n\n\tbase := unsafeSliceInt32(collection, length)\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\ts := base[i : i+lanes]\n\t\tv := archsimd.LoadInt32x8Slice(s)\n\n\t\tcmp := v.Equal(targetVec)\n\t\tif cmp.ToBits() != 0 {\n\t\t\treturn true\n\t\t}\n\t}\n\n\tfor ; i < length; i++ {\n\t\tif collection[i] == target {\n\t\t\treturn true\n\t\t}\n\t}\n\n\treturn false\n}\n\n// ContainsInt64x4 checks if collection contains target using AVX2 SIMD\nfunc ContainsInt64x4[T ~int64](collection []T, target T) bool {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn false\n\t}\n\n\tconst lanes = simdLanes4\n\ttargetVec := archsimd.BroadcastInt64x4(int64(target))\n\n\tbase := unsafeSliceInt64(collection, length)\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\ts := base[i : i+lanes]\n\t\tv := archsimd.LoadInt64x4Slice(s)\n\n\t\tcmp := v.Equal(targetVec)\n\t\tif cmp.ToBits() != 0 {\n\t\t\treturn true\n\t\t}\n\t}\n\n\tfor ; i < length; i++ {\n\t\tif collection[i] == target {\n\t\t\treturn true\n\t\t}\n\t}\n\n\treturn false\n}\n\n// ContainsUint8x32 checks if collection contains target using AVX2 SIMD\nfunc ContainsUint8x32[T ~uint8](collection []T, target T) bool {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn false\n\t}\n\n\tconst lanes = simdLanes32\n\ttargetVec := archsimd.BroadcastUint8x32(uint8(target))\n\n\tbase := unsafeSliceUint8(collection, length)\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\ts := base[i : i+lanes]\n\t\tv := archsimd.LoadUint8x32Slice(s)\n\n\t\tcmp := v.Equal(targetVec)\n\t\tif cmp.ToBits() != 0 {\n\t\t\treturn true\n\t\t}\n\t}\n\n\tfor ; i < length; i++ {\n\t\tif collection[i] == target {\n\t\t\treturn true\n\t\t}\n\t}\n\n\treturn false\n}\n\n// ContainsUint16x16 checks if collection contains target using AVX2 SIMD\nfunc ContainsUint16x16[T ~uint16](collection []T, target T) bool {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn false\n\t}\n\n\tconst lanes = simdLanes16\n\ttargetVec := archsimd.BroadcastUint16x16(uint16(target))\n\n\tbase := unsafeSliceUint16(collection, length)\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\ts := base[i : i+lanes]\n\t\tv := archsimd.LoadUint16x16Slice(s)\n\n\t\tcmp := v.Equal(targetVec)\n\t\tif cmp.ToBits() != 0 {\n\t\t\treturn true\n\t\t}\n\t}\n\n\tfor ; i < length; i++ {\n\t\tif collection[i] == target {\n\t\t\treturn true\n\t\t}\n\t}\n\n\treturn false\n}\n\n// ContainsUint32x8 checks if collection contains target using AVX2 SIMD\nfunc ContainsUint32x8[T ~uint32](collection []T, target T) bool {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn false\n\t}\n\n\tconst lanes = simdLanes8\n\ttargetVec := archsimd.BroadcastUint32x8(uint32(target))\n\n\tbase := unsafeSliceUint32(collection, length)\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\ts := base[i : i+lanes]\n\t\tv := archsimd.LoadUint32x8Slice(s)\n\n\t\tcmp := v.Equal(targetVec)\n\t\tif cmp.ToBits() != 0 {\n\t\t\treturn true\n\t\t}\n\t}\n\n\tfor ; i < length; i++ {\n\t\tif collection[i] == target {\n\t\t\treturn true\n\t\t}\n\t}\n\n\treturn false\n}\n\n// ContainsUint64x4 checks if collection contains target using AVX2 SIMD\nfunc ContainsUint64x4[T ~uint64](collection []T, target T) bool {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn false\n\t}\n\n\tconst lanes = simdLanes4\n\ttargetVec := archsimd.BroadcastUint64x4(uint64(target))\n\n\tbase := unsafeSliceUint64(collection, length)\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\ts := base[i : i+lanes]\n\t\tv := archsimd.LoadUint64x4Slice(s)\n\n\t\tcmp := v.Equal(targetVec)\n\t\tif cmp.ToBits() != 0 {\n\t\t\treturn true\n\t\t}\n\t}\n\n\tfor ; i < length; i++ {\n\t\tif collection[i] == target {\n\t\t\treturn true\n\t\t}\n\t}\n\n\treturn false\n}\n\n// ContainsFloat32x8 checks if collection contains target using AVX2 SIMD\nfunc ContainsFloat32x8[T ~float32](collection []T, target T) bool {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn false\n\t}\n\n\tconst lanes = simdLanes8\n\ttargetVec := archsimd.BroadcastFloat32x8(float32(target))\n\n\tbase := unsafeSliceFloat32(collection, length)\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\ts := base[i : i+lanes]\n\t\tv := archsimd.LoadFloat32x8Slice(s)\n\n\t\tcmp := v.Equal(targetVec)\n\t\tif cmp.ToBits() != 0 {\n\t\t\treturn true\n\t\t}\n\t}\n\n\tfor ; i < length; i++ {\n\t\tif collection[i] == target {\n\t\t\treturn true\n\t\t}\n\t}\n\n\treturn false\n}\n\n// ContainsFloat64x4 checks if collection contains target using AVX2 SIMD\nfunc ContainsFloat64x4[T ~float64](collection []T, target T) bool {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn false\n\t}\n\n\tconst lanes = simdLanes4\n\ttargetVec := archsimd.BroadcastFloat64x4(float64(target))\n\n\tbase := unsafeSliceFloat64(collection, length)\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\ts := base[i : i+lanes]\n\t\tv := archsimd.LoadFloat64x4Slice(s)\n\n\t\tcmp := v.Equal(targetVec)\n\t\tif cmp.ToBits() != 0 {\n\t\t\treturn true\n\t\t}\n\t}\n\n\tfor ; i < length; i++ {\n\t\tif collection[i] == target {\n\t\t\treturn true\n\t\t}\n\t}\n\n\treturn false\n}\n\n// ContainsInt8x64 checks if collection contains target using AVX-512 SIMD\nfunc ContainsInt8x64[T ~int8](collection []T, target T) bool {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn false\n\t}\n\n\tconst lanes = simdLanes64\n\ttargetVec := archsimd.BroadcastInt8x64(int8(target))\n\n\tbase := unsafeSliceInt8(collection, length)\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\ts := base[i : i+lanes]\n\t\tv := archsimd.LoadInt8x64Slice(s)\n\n\t\tcmp := v.Equal(targetVec)\n\t\tif cmp.ToBits() != 0 {\n\t\t\treturn true\n\t\t}\n\t}\n\n\tfor ; i < length; i++ {\n\t\tif collection[i] == target {\n\t\t\treturn true\n\t\t}\n\t}\n\n\treturn false\n}\n\n// ContainsInt16x32 checks if collection contains target using AVX-512 SIMD\nfunc ContainsInt16x32[T ~int16](collection []T, target T) bool {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn false\n\t}\n\n\tconst lanes = simdLanes32\n\ttargetVec := archsimd.BroadcastInt16x32(int16(target))\n\n\tbase := unsafeSliceInt16(collection, length)\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\ts := base[i : i+lanes]\n\t\tv := archsimd.LoadInt16x32Slice(s)\n\n\t\tcmp := v.Equal(targetVec)\n\t\tif cmp.ToBits() != 0 {\n\t\t\treturn true\n\t\t}\n\t}\n\n\tfor ; i < length; i++ {\n\t\tif collection[i] == target {\n\t\t\treturn true\n\t\t}\n\t}\n\n\treturn false\n}\n\n// ContainsInt32x16 checks if collection contains target using AVX-512 SIMD\nfunc ContainsInt32x16[T ~int32](collection []T, target T) bool {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn false\n\t}\n\n\tconst lanes = simdLanes16\n\ttargetVec := archsimd.BroadcastInt32x16(int32(target))\n\n\tbase := unsafeSliceInt32(collection, length)\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\ts := base[i : i+lanes]\n\t\tv := archsimd.LoadInt32x16Slice(s)\n\n\t\tcmp := v.Equal(targetVec)\n\t\tif cmp.ToBits() != 0 {\n\t\t\treturn true\n\t\t}\n\t}\n\n\tfor ; i < length; i++ {\n\t\tif collection[i] == target {\n\t\t\treturn true\n\t\t}\n\t}\n\n\treturn false\n}\n\n// ContainsInt64x8 checks if collection contains target using AVX-512 SIMD\nfunc ContainsInt64x8[T ~int64](collection []T, target T) bool {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn false\n\t}\n\n\tconst lanes = simdLanes8\n\ttargetVec := archsimd.BroadcastInt64x8(int64(target))\n\n\tbase := unsafeSliceInt64(collection, length)\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\ts := base[i : i+lanes]\n\t\tv := archsimd.LoadInt64x8Slice(s)\n\n\t\tcmp := v.Equal(targetVec)\n\t\tif cmp.ToBits() != 0 {\n\t\t\treturn true\n\t\t}\n\t}\n\n\tfor ; i < length; i++ {\n\t\tif collection[i] == target {\n\t\t\treturn true\n\t\t}\n\t}\n\n\treturn false\n}\n\n// ContainsUint8x64 checks if collection contains target using AVX-512 SIMD\nfunc ContainsUint8x64[T ~uint8](collection []T, target T) bool {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn false\n\t}\n\n\tconst lanes = simdLanes64\n\ttargetVec := archsimd.BroadcastUint8x64(uint8(target))\n\n\tbase := unsafeSliceUint8(collection, length)\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\ts := base[i : i+lanes]\n\t\tv := archsimd.LoadUint8x64Slice(s)\n\n\t\tcmp := v.Equal(targetVec)\n\t\tif cmp.ToBits() != 0 {\n\t\t\treturn true\n\t\t}\n\t}\n\n\tfor ; i < length; i++ {\n\t\tif collection[i] == target {\n\t\t\treturn true\n\t\t}\n\t}\n\n\treturn false\n}\n\n// ContainsUint16x32 checks if collection contains target using AVX-512 SIMD\nfunc ContainsUint16x32[T ~uint16](collection []T, target T) bool {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn false\n\t}\n\n\tconst lanes = simdLanes32\n\ttargetVec := archsimd.BroadcastUint16x32(uint16(target))\n\n\tbase := unsafeSliceUint16(collection, length)\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\ts := base[i : i+lanes]\n\t\tv := archsimd.LoadUint16x32Slice(s)\n\n\t\tcmp := v.Equal(targetVec)\n\t\tif cmp.ToBits() != 0 {\n\t\t\treturn true\n\t\t}\n\t}\n\n\tfor ; i < length; i++ {\n\t\tif collection[i] == target {\n\t\t\treturn true\n\t\t}\n\t}\n\n\treturn false\n}\n\n// ContainsUint32x16 checks if collection contains target using AVX-512 SIMD\nfunc ContainsUint32x16[T ~uint32](collection []T, target T) bool {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn false\n\t}\n\n\tconst lanes = simdLanes16\n\ttargetVec := archsimd.BroadcastUint32x16(uint32(target))\n\n\tbase := unsafeSliceUint32(collection, length)\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\ts := base[i : i+lanes]\n\t\tv := archsimd.LoadUint32x16Slice(s)\n\n\t\tcmp := v.Equal(targetVec)\n\t\tif cmp.ToBits() != 0 {\n\t\t\treturn true\n\t\t}\n\t}\n\n\tfor ; i < length; i++ {\n\t\tif collection[i] == target {\n\t\t\treturn true\n\t\t}\n\t}\n\n\treturn false\n}\n\n// ContainsUint64x8 checks if collection contains target using AVX-512 SIMD\nfunc ContainsUint64x8[T ~uint64](collection []T, target T) bool {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn false\n\t}\n\n\tconst lanes = simdLanes8\n\ttargetVec := archsimd.BroadcastUint64x8(uint64(target))\n\n\tbase := unsafeSliceUint64(collection, length)\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\ts := base[i : i+lanes]\n\t\tv := archsimd.LoadUint64x8Slice(s)\n\n\t\tcmp := v.Equal(targetVec)\n\t\tif cmp.ToBits() != 0 {\n\t\t\treturn true\n\t\t}\n\t}\n\n\tfor ; i < length; i++ {\n\t\tif collection[i] == target {\n\t\t\treturn true\n\t\t}\n\t}\n\n\treturn false\n}\n\n// ContainsFloat32x16 checks if collection contains target using AVX-512 SIMD\nfunc ContainsFloat32x16[T ~float32](collection []T, target T) bool {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn false\n\t}\n\n\tconst lanes = simdLanes16\n\ttargetVec := archsimd.BroadcastFloat32x16(float32(target))\n\n\tbase := unsafeSliceFloat32(collection, length)\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\ts := base[i : i+lanes]\n\t\tv := archsimd.LoadFloat32x16Slice(s)\n\n\t\tcmp := v.Equal(targetVec)\n\t\tif cmp.ToBits() != 0 {\n\t\t\treturn true\n\t\t}\n\t}\n\n\tfor ; i < length; i++ {\n\t\tif collection[i] == target {\n\t\t\treturn true\n\t\t}\n\t}\n\n\treturn false\n}\n\n// ContainsFloat64x8 checks if collection contains target using AVX-512 SIMD\nfunc ContainsFloat64x8[T ~float64](collection []T, target T) bool {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn false\n\t}\n\n\tconst lanes = simdLanes8\n\ttargetVec := archsimd.BroadcastFloat64x8(float64(target))\n\n\tbase := unsafeSliceFloat64(collection, length)\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\ts := base[i : i+lanes]\n\t\tv := archsimd.LoadFloat64x8Slice(s)\n\n\t\tcmp := v.Equal(targetVec)\n\t\tif cmp.ToBits() != 0 {\n\t\t\treturn true\n\t\t}\n\t}\n\n\tfor ; i < length; i++ {\n\t\tif collection[i] == target {\n\t\t\treturn true\n\t\t}\n\t}\n\n\treturn false\n}\n"
  },
  {
    "path": "exp/simd/intersect_avx512_test.go",
    "content": "//go:build go1.26 && goexperiment.simd && amd64\n\npackage simd\n\nimport (\n\t\"math/rand/v2\"\n\t\"testing\"\n\n\t\"github.com/samber/lo\"\n)\n\nfunc TestAVX512ContainsInt8x16(t *testing.T) {\n\trequireAVX2(t)\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname       string\n\t\tcollection []int8\n\t\ttarget     int8\n\t\texpected   bool\n\t}{\n\t\t{\"empty\", []int8{}, 42, false},\n\t\t{\"single found\", []int8{42}, 42, true},\n\t\t{\"single not found\", []int8{42}, 10, false},\n\t\t{\"small found at start\", []int8{1, 2, 3, 4, 5}, 1, true},\n\t\t{\"small found at end\", []int8{1, 2, 3, 4, 5}, 5, true},\n\t\t{\"small found middle\", []int8{1, 2, 3, 4, 5}, 3, true},\n\t\t{\"small not found\", []int8{1, 2, 3, 4, 5}, 10, false},\n\t\t{\"exactly 16 found\", []int8{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, 8, true},\n\t\t{\"exactly 16 not found\", []int8{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, 100, false},\n\t\t{\"large found\", make([]int8, 1000), 0, true},\n\t\t{\"large not found\", make([]int8, 100), 127, false},\n\t\t{\"negative found\", []int8{-1, -2, -3, 4, 5}, -2, true},\n\t\t{\"negative not found\", []int8{-1, -2, -3, 4, 5}, -10, false},\n\t\t{\"min value\", []int8{-128, 0, 127}, -128, true},\n\t\t{\"max value\", []int8{-128, 0, 127}, 127, true},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\t// Fill large collections with random data\n\t\t\tif len(tc.collection) > 16 && tc.collection[0] == 0 {\n\t\t\t\tif tc.expected {\n\t\t\t\t\ttc.collection[100] = tc.target\n\t\t\t\t} else {\n\t\t\t\t\tfor i := range tc.collection {\n\t\t\t\t\t\ttc.collection[i] = int8(rand.IntN(256) - 128)\n\t\t\t\t\t\tif tc.collection[i] == tc.target {\n\t\t\t\t\t\t\ttc.collection[i]++\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := ContainsInt8x16(tc.collection, tc.target)\n\t\t\tif got != tc.expected {\n\t\t\t\tt.Errorf(\"ContainsInt8x16() = %v, want %v\", got, tc.expected)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestAVX512ContainsInt16x8(t *testing.T) {\n\trequireAVX2(t)\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname       string\n\t\tcollection []int16\n\t\ttarget     int16\n\t\texpected   bool\n\t}{\n\t\t{\"empty\", []int16{}, 42, false},\n\t\t{\"single found\", []int16{42}, 42, true},\n\t\t{\"single not found\", []int16{42}, 10, false},\n\t\t{\"small found\", []int16{1, 2, 3, 4, 5}, 3, true},\n\t\t{\"small not found\", []int16{1, 2, 3, 4, 5}, 10, false},\n\t\t{\"exactly 8 found\", []int16{1, 2, 3, 4, 5, 6, 7, 8}, 8, true},\n\t\t{\"exactly 8 not found\", []int16{1, 2, 3, 4, 5, 6, 7, 8}, 100, false},\n\t\t{\"large found\", make([]int16, 1000), 0, true},\n\t\t{\"large not found\", make([]int16, 100), 1000, false},\n\t\t{\"negative found\", []int16{-1, -2, -3, 4, 5}, -2, true},\n\t\t{\"min value\", []int16{-32768, 0, 32767}, -32768, true},\n\t\t{\"max value\", []int16{-32768, 0, 32767}, 32767, true},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.collection) > 8 && tc.collection[0] == 0 {\n\t\t\t\tif tc.expected {\n\t\t\t\t\ttc.collection[50] = tc.target\n\t\t\t\t} else {\n\t\t\t\t\tfor i := range tc.collection {\n\t\t\t\t\t\ttc.collection[i] = int16(rand.IntN(65536) - 32768)\n\t\t\t\t\t\tif tc.collection[i] == tc.target {\n\t\t\t\t\t\t\ttc.collection[i]++\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := ContainsInt16x8(tc.collection, tc.target)\n\t\t\tif got != tc.expected {\n\t\t\t\tt.Errorf(\"ContainsInt16x8() = %v, want %v\", got, tc.expected)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestAVX512ContainsInt32x4(t *testing.T) {\n\trequireAVX2(t)\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname       string\n\t\tcollection []int32\n\t\ttarget     int32\n\t\texpected   bool\n\t}{\n\t\t{\"empty\", []int32{}, 42, false},\n\t\t{\"single found\", []int32{42}, 42, true},\n\t\t{\"single not found\", []int32{42}, 10, false},\n\t\t{\"small found\", []int32{1, 2, 3, 4, 5}, 3, true},\n\t\t{\"small not found\", []int32{1, 2, 3, 4, 5}, 10, false},\n\t\t{\"exactly 4 found\", []int32{1, 2, 3, 4}, 4, true},\n\t\t{\"exactly 4 not found\", []int32{1, 2, 3, 4}, 100, false},\n\t\t{\"large found\", make([]int32, 1000), 0, true},\n\t\t{\"large not found\", make([]int32, 100), 100000, false},\n\t\t{\"negative found\", []int32{-1, -2, -3, 4, 5}, -2, true},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.collection) > 4 && tc.collection[0] == 0 {\n\t\t\t\tif tc.expected {\n\t\t\t\t\ttc.collection[50] = tc.target\n\t\t\t\t} else {\n\t\t\t\t\tfor i := range tc.collection {\n\t\t\t\t\t\ttc.collection[i] = rand.Int32()\n\t\t\t\t\t\tif tc.collection[i] == tc.target {\n\t\t\t\t\t\t\ttc.collection[i]++\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := ContainsInt32x4(tc.collection, tc.target)\n\t\t\tif got != tc.expected {\n\t\t\t\tt.Errorf(\"ContainsInt32x4() = %v, want %v\", got, tc.expected)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestAVX512ContainsInt64x2(t *testing.T) {\n\trequireAVX2(t)\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname       string\n\t\tcollection []int64\n\t\ttarget     int64\n\t\texpected   bool\n\t}{\n\t\t{\"empty\", []int64{}, 42, false},\n\t\t{\"single found\", []int64{42}, 42, true},\n\t\t{\"single not found\", []int64{42}, 10, false},\n\t\t{\"small found\", []int64{1, 2, 3, 4, 5}, 3, true},\n\t\t{\"small not found\", []int64{1, 2, 3, 4, 5}, 10, false},\n\t\t{\"exactly 2 found\", []int64{1, 2}, 2, true},\n\t\t{\"exactly 2 not found\", []int64{1, 2}, 100, false},\n\t\t{\"large found\", make([]int64, 1000), 0, true},\n\t\t{\"large not found\", make([]int64, 100), 1000000, false},\n\t\t{\"negative found\", []int64{-1, -2, -3, 4, 5}, -2, true},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.collection) > 2 && tc.collection[0] == 0 {\n\t\t\t\tif tc.expected {\n\t\t\t\t\ttc.collection[50] = tc.target\n\t\t\t\t} else {\n\t\t\t\t\tfor i := range tc.collection {\n\t\t\t\t\t\ttc.collection[i] = rand.Int64()\n\t\t\t\t\t\tif tc.collection[i] == tc.target {\n\t\t\t\t\t\t\ttc.collection[i]++\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := ContainsInt64x2(tc.collection, tc.target)\n\t\t\tif got != tc.expected {\n\t\t\t\tt.Errorf(\"ContainsInt64x2() = %v, want %v\", got, tc.expected)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestAVX512ContainsUint8x16(t *testing.T) {\n\trequireAVX2(t)\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname       string\n\t\tcollection []uint8\n\t\ttarget     uint8\n\t\texpected   bool\n\t}{\n\t\t{\"empty\", []uint8{}, 42, false},\n\t\t{\"single found\", []uint8{42}, 42, true},\n\t\t{\"single not found\", []uint8{42}, 10, false},\n\t\t{\"small found\", []uint8{1, 2, 3, 4, 5}, 3, true},\n\t\t{\"small not found\", []uint8{1, 2, 3, 4, 5}, 10, false},\n\t\t{\"exactly 16 found\", []uint8{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, 16, true},\n\t\t{\"exactly 16 not found\", []uint8{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, 100, false},\n\t\t{\"large found\", make([]uint8, 1000), 0, true},\n\t\t{\"large not found\", make([]uint8, 100), 255, false},\n\t\t{\"max value\", []uint8{255, 100, 50}, 255, true},\n\t\t{\"zero found\", []uint8{0, 1, 2, 3}, 0, true},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.collection) > 16 && tc.collection[0] == 0 {\n\t\t\t\tif tc.expected {\n\t\t\t\t\ttc.collection[100] = tc.target\n\t\t\t\t} else {\n\t\t\t\t\tfor i := range tc.collection {\n\t\t\t\t\t\ttc.collection[i] = uint8(rand.IntN(256))\n\t\t\t\t\t\tif tc.collection[i] == tc.target {\n\t\t\t\t\t\t\ttc.collection[i] = tc.collection[i] + 1\n\t\t\t\t\t\t\tif tc.collection[i] == 0 { // wrapped around\n\t\t\t\t\t\t\t\ttc.collection[i] = 1\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := ContainsUint8x16(tc.collection, tc.target)\n\t\t\tif got != tc.expected {\n\t\t\t\tt.Errorf(\"ContainsUint8x16() = %v, want %v\", got, tc.expected)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestAVX512ContainsUint16x8(t *testing.T) {\n\trequireAVX2(t)\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname       string\n\t\tcollection []uint16\n\t\ttarget     uint16\n\t\texpected   bool\n\t}{\n\t\t{\"empty\", []uint16{}, 42, false},\n\t\t{\"single found\", []uint16{42}, 42, true},\n\t\t{\"single not found\", []uint16{42}, 10, false},\n\t\t{\"small found\", []uint16{1, 2, 3, 4, 5}, 3, true},\n\t\t{\"small not found\", []uint16{1, 2, 3, 4, 5}, 10, false},\n\t\t{\"exactly 8 found\", []uint16{1, 2, 3, 4, 5, 6, 7, 8}, 8, true},\n\t\t{\"exactly 8 not found\", []uint16{1, 2, 3, 4, 5, 6, 7, 8}, 100, false},\n\t\t{\"large found\", make([]uint16, 1000), 0, true},\n\t\t{\"large not found\", make([]uint16, 100), 1000, false},\n\t\t{\"max value\", []uint16{65535, 1000, 500}, 65535, true},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.collection) > 8 && tc.collection[0] == 0 {\n\t\t\t\tif tc.expected {\n\t\t\t\t\ttc.collection[50] = tc.target\n\t\t\t\t} else {\n\t\t\t\t\tfor i := range tc.collection {\n\t\t\t\t\t\ttc.collection[i] = uint16(rand.IntN(65536))\n\t\t\t\t\t\tif tc.collection[i] == tc.target {\n\t\t\t\t\t\t\ttc.collection[i] = uint16((int(tc.collection[i]) + 1) % 65536)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := ContainsUint16x8(tc.collection, tc.target)\n\t\t\tif got != tc.expected {\n\t\t\t\tt.Errorf(\"ContainsUint16x8() = %v, want %v\", got, tc.expected)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestAVX512ContainsUint32x4(t *testing.T) {\n\trequireAVX2(t)\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname       string\n\t\tcollection []uint32\n\t\ttarget     uint32\n\t\texpected   bool\n\t}{\n\t\t{\"empty\", []uint32{}, 42, false},\n\t\t{\"single found\", []uint32{42}, 42, true},\n\t\t{\"single not found\", []uint32{42}, 10, false},\n\t\t{\"small found\", []uint32{1, 2, 3, 4, 5}, 3, true},\n\t\t{\"small not found\", []uint32{1, 2, 3, 4, 5}, 10, false},\n\t\t{\"exactly 4 found\", []uint32{1, 2, 3, 4}, 4, true},\n\t\t{\"exactly 4 not found\", []uint32{1, 2, 3, 4}, 100, false},\n\t\t{\"large found\", make([]uint32, 1000), 0, true},\n\t\t{\"large not found\", make([]uint32, 100), 100000, false},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.collection) > 4 && tc.collection[0] == 0 {\n\t\t\t\tif tc.expected {\n\t\t\t\t\ttc.collection[50] = tc.target\n\t\t\t\t} else {\n\t\t\t\t\tfor i := range tc.collection {\n\t\t\t\t\t\ttc.collection[i] = rand.Uint32()\n\t\t\t\t\t\tif tc.collection[i] == tc.target {\n\t\t\t\t\t\t\ttc.collection[i]++\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := ContainsUint32x4(tc.collection, tc.target)\n\t\t\tif got != tc.expected {\n\t\t\t\tt.Errorf(\"ContainsUint32x4() = %v, want %v\", got, tc.expected)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestAVX512ContainsUint64x2(t *testing.T) {\n\trequireAVX2(t)\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname       string\n\t\tcollection []uint64\n\t\ttarget     uint64\n\t\texpected   bool\n\t}{\n\t\t{\"empty\", []uint64{}, 42, false},\n\t\t{\"single found\", []uint64{42}, 42, true},\n\t\t{\"single not found\", []uint64{42}, 10, false},\n\t\t{\"small found\", []uint64{1, 2, 3, 4, 5}, 3, true},\n\t\t{\"small not found\", []uint64{1, 2, 3, 4, 5}, 10, false},\n\t\t{\"exactly 2 found\", []uint64{1, 2}, 2, true},\n\t\t{\"exactly 2 not found\", []uint64{1, 2}, 100, false},\n\t\t{\"large found\", make([]uint64, 1000), 0, true},\n\t\t{\"large not found\", make([]uint64, 100), 1000000, false},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.collection) > 2 && tc.collection[0] == 0 {\n\t\t\t\tif tc.expected {\n\t\t\t\t\ttc.collection[50] = tc.target\n\t\t\t\t} else {\n\t\t\t\t\tfor i := range tc.collection {\n\t\t\t\t\t\ttc.collection[i] = rand.Uint64()\n\t\t\t\t\t\tif tc.collection[i] == tc.target {\n\t\t\t\t\t\t\ttc.collection[i]++\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := ContainsUint64x2(tc.collection, tc.target)\n\t\t\tif got != tc.expected {\n\t\t\t\tt.Errorf(\"ContainsUint64x2() = %v, want %v\", got, tc.expected)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestAVX512ContainsFloat32x4(t *testing.T) {\n\trequireAVX2(t)\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname       string\n\t\tcollection []float32\n\t\ttarget     float32\n\t\texpected   bool\n\t}{\n\t\t{\"empty\", []float32{}, 42.5, false},\n\t\t{\"single found\", []float32{42.5}, 42.5, true},\n\t\t{\"single not found\", []float32{42.5}, 10.0, false},\n\t\t{\"small found\", []float32{1.1, 2.2, 3.3, 4.4, 5.5}, 3.3, true},\n\t\t{\"small not found\", []float32{1.1, 2.2, 3.3, 4.4, 5.5}, 10.0, false},\n\t\t{\"exactly 4 found\", []float32{1.0, 2.0, 3.0, 4.0}, 4.0, true},\n\t\t{\"exactly 4 not found\", []float32{1.0, 2.0, 3.0, 4.0}, 100.0, false},\n\t\t{\"large found\", make([]float32, 1000), 0, true},\n\t\t{\"large not found\", make([]float32, 100), 100000.0, false},\n\t\t{\"negative found\", []float32{-1.1, -2.2, 3.3, 4.4}, -2.2, true},\n\t\t{\"zeros\", []float32{0, 0, 0, 0}, 0, true},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.collection) > 4 && tc.collection[0] == 0 {\n\t\t\t\tif tc.expected {\n\t\t\t\t\ttc.collection[50] = tc.target\n\t\t\t\t} else {\n\t\t\t\t\tfor i := range tc.collection {\n\t\t\t\t\t\ttc.collection[i] = rand.Float32() * 10000\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := ContainsFloat32x4(tc.collection, tc.target)\n\t\t\tif got != tc.expected {\n\t\t\t\tt.Errorf(\"ContainsFloat32x4() = %v, want %v\", got, tc.expected)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestAVX512ContainsFloat64x2(t *testing.T) {\n\trequireAVX2(t)\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname       string\n\t\tcollection []float64\n\t\ttarget     float64\n\t\texpected   bool\n\t}{\n\t\t{\"empty\", []float64{}, 42.5, false},\n\t\t{\"single found\", []float64{42.5}, 42.5, true},\n\t\t{\"single not found\", []float64{42.5}, 10.0, false},\n\t\t{\"small found\", []float64{1.1, 2.2, 3.3, 4.4, 5.5}, 3.3, true},\n\t\t{\"small not found\", []float64{1.1, 2.2, 3.3, 4.4, 5.5}, 10.0, false},\n\t\t{\"exactly 2 found\", []float64{1.0, 2.0}, 2.0, true},\n\t\t{\"exactly 2 not found\", []float64{1.0, 2.0}, 100.0, false},\n\t\t{\"large found\", make([]float64, 1000), 0, true},\n\t\t{\"large not found\", make([]float64, 100), 100000.0, false},\n\t\t{\"negative found\", []float64{-1.1, -2.2, 3.3, 4.4}, -2.2, true},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.collection) > 2 && tc.collection[0] == 0 {\n\t\t\t\tif tc.expected {\n\t\t\t\t\ttc.collection[50] = tc.target\n\t\t\t\t} else {\n\t\t\t\t\tfor i := range tc.collection {\n\t\t\t\t\t\ttc.collection[i] = rand.Float64() * 10000\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := ContainsFloat64x2(tc.collection, tc.target)\n\t\t\tif got != tc.expected {\n\t\t\t\tt.Errorf(\"ContainsFloat64x2() = %v, want %v\", got, tc.expected)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestAVX512ContainsInt8x32(t *testing.T) {\n\trequireAVX2(t)\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname       string\n\t\tcollection []int8\n\t\ttarget     int8\n\t\texpected   bool\n\t}{\n\t\t{\"empty\", []int8{}, 42, false},\n\t\t{\"single found\", []int8{42}, 42, true},\n\t\t{\"single not found\", []int8{42}, 10, false},\n\t\t{\"small found\", []int8{1, 2, 3, 4, 5}, 3, true},\n\t\t{\"small not found\", []int8{1, 2, 3, 4, 5}, 10, false},\n\t\t{\"exactly 32 found\", make([]int8, 32), 0, true},\n\t\t{\"exactly 32 not found\", make([]int8, 32), 127, false},\n\t\t{\"large found\", make([]int8, 1000), 0, true},\n\t\t{\"large not found\", make([]int8, 100), 127, false},\n\t\t{\"negative found\", []int8{-1, -2, -3, 4, 5}, -2, true},\n\t\t{\"min value\", []int8{-128, 0, 127}, -128, true},\n\t\t{\"max value\", []int8{-128, 0, 127}, 127, true},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.collection) > 32 && tc.collection[0] == 0 {\n\t\t\t\tif tc.expected {\n\t\t\t\t\ttc.collection[100] = tc.target\n\t\t\t\t} else {\n\t\t\t\t\tfor i := range tc.collection {\n\t\t\t\t\t\ttc.collection[i] = int8(rand.IntN(256) - 128)\n\t\t\t\t\t\tif tc.collection[i] == tc.target {\n\t\t\t\t\t\t\ttc.collection[i]++\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := ContainsInt8x32(tc.collection, tc.target)\n\t\t\tif got != tc.expected {\n\t\t\t\tt.Errorf(\"ContainsInt8x32() = %v, want %v\", got, tc.expected)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestAVX512ContainsInt16x16(t *testing.T) {\n\trequireAVX2(t)\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname       string\n\t\tcollection []int16\n\t\ttarget     int16\n\t\texpected   bool\n\t}{\n\t\t{\"empty\", []int16{}, 42, false},\n\t\t{\"single found\", []int16{42}, 42, true},\n\t\t{\"single not found\", []int16{42}, 10, false},\n\t\t{\"small found\", []int16{1, 2, 3, 4, 5}, 3, true},\n\t\t{\"small not found\", []int16{1, 2, 3, 4, 5}, 10, false},\n\t\t{\"exactly 16 found\", make([]int16, 16), 0, true},\n\t\t{\"exactly 16 not found\", make([]int16, 16), 1000, false},\n\t\t{\"large found\", make([]int16, 1000), 0, true},\n\t\t{\"large not found\", make([]int16, 100), 1000, false},\n\t\t{\"negative found\", []int16{-1, -2, -3, 4, 5}, -2, true},\n\t\t{\"min value\", []int16{-32768, 0, 32767}, -32768, true},\n\t\t{\"max value\", []int16{-32768, 0, 32767}, 32767, true},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.collection) > 16 && tc.collection[0] == 0 {\n\t\t\t\tif tc.expected {\n\t\t\t\t\ttc.collection[50] = tc.target\n\t\t\t\t} else {\n\t\t\t\t\tfor i := range tc.collection {\n\t\t\t\t\t\ttc.collection[i] = int16(rand.IntN(65536) - 32768)\n\t\t\t\t\t\tif tc.collection[i] == tc.target {\n\t\t\t\t\t\t\ttc.collection[i]++\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := ContainsInt16x16(tc.collection, tc.target)\n\t\t\tif got != tc.expected {\n\t\t\t\tt.Errorf(\"ContainsInt16x16() = %v, want %v\", got, tc.expected)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestAVX512ContainsInt32x8(t *testing.T) {\n\trequireAVX2(t)\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname       string\n\t\tcollection []int32\n\t\ttarget     int32\n\t\texpected   bool\n\t}{\n\t\t{\"empty\", []int32{}, 42, false},\n\t\t{\"single found\", []int32{42}, 42, true},\n\t\t{\"single not found\", []int32{42}, 10, false},\n\t\t{\"small found\", []int32{1, 2, 3, 4, 5}, 3, true},\n\t\t{\"small not found\", []int32{1, 2, 3, 4, 5}, 10, false},\n\t\t{\"exactly 8 found\", make([]int32, 8), 0, true},\n\t\t{\"exactly 8 not found\", make([]int32, 8), 100, false},\n\t\t{\"large found\", make([]int32, 1000), 0, true},\n\t\t{\"large not found\", make([]int32, 100), 100000, false},\n\t\t{\"negative found\", []int32{-1, -2, -3, 4, 5}, -2, true},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.collection) > 8 && tc.collection[0] == 0 {\n\t\t\t\tif tc.expected {\n\t\t\t\t\ttc.collection[50] = tc.target\n\t\t\t\t} else {\n\t\t\t\t\tfor i := range tc.collection {\n\t\t\t\t\t\ttc.collection[i] = rand.Int32()\n\t\t\t\t\t\tif tc.collection[i] == tc.target {\n\t\t\t\t\t\t\ttc.collection[i]++\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := ContainsInt32x8(tc.collection, tc.target)\n\t\t\tif got != tc.expected {\n\t\t\t\tt.Errorf(\"ContainsInt32x8() = %v, want %v\", got, tc.expected)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestAVX512ContainsInt64x4(t *testing.T) {\n\trequireAVX2(t)\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname       string\n\t\tcollection []int64\n\t\ttarget     int64\n\t\texpected   bool\n\t}{\n\t\t{\"empty\", []int64{}, 42, false},\n\t\t{\"single found\", []int64{42}, 42, true},\n\t\t{\"single not found\", []int64{42}, 10, false},\n\t\t{\"small found\", []int64{1, 2, 3, 4, 5}, 3, true},\n\t\t{\"small not found\", []int64{1, 2, 3, 4, 5}, 10, false},\n\t\t{\"exactly 4 found\", make([]int64, 4), 0, true},\n\t\t{\"exactly 4 not found\", make([]int64, 4), 100, false},\n\t\t{\"large found\", make([]int64, 1000), 0, true},\n\t\t{\"large not found\", make([]int64, 100), 1000000, false},\n\t\t{\"negative found\", []int64{-1, -2, -3, 4, 5}, -2, true},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.collection) > 4 && tc.collection[0] == 0 {\n\t\t\t\tif tc.expected {\n\t\t\t\t\ttc.collection[50] = tc.target\n\t\t\t\t} else {\n\t\t\t\t\tfor i := range tc.collection {\n\t\t\t\t\t\ttc.collection[i] = rand.Int64()\n\t\t\t\t\t\tif tc.collection[i] == tc.target {\n\t\t\t\t\t\t\ttc.collection[i]++\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := ContainsInt64x4(tc.collection, tc.target)\n\t\t\tif got != tc.expected {\n\t\t\t\tt.Errorf(\"ContainsInt64x4() = %v, want %v\", got, tc.expected)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestAVX512ContainsUint8x32(t *testing.T) {\n\trequireAVX2(t)\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname       string\n\t\tcollection []uint8\n\t\ttarget     uint8\n\t\texpected   bool\n\t}{\n\t\t{\"empty\", []uint8{}, 42, false},\n\t\t{\"single found\", []uint8{42}, 42, true},\n\t\t{\"single not found\", []uint8{42}, 10, false},\n\t\t{\"small found\", []uint8{1, 2, 3, 4, 5}, 3, true},\n\t\t{\"small not found\", []uint8{1, 2, 3, 4, 5}, 10, false},\n\t\t{\"exactly 32 found\", make([]uint8, 32), 0, true},\n\t\t{\"exactly 32 not found\", make([]uint8, 32), 255, false},\n\t\t{\"large found\", make([]uint8, 1000), 0, true},\n\t\t{\"large not found\", make([]uint8, 100), 255, false},\n\t\t{\"max value\", []uint8{255, 100, 50}, 255, true},\n\t\t{\"zero found\", []uint8{0, 1, 2, 3}, 0, true},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.collection) > 32 && tc.collection[0] == 0 {\n\t\t\t\tif tc.expected {\n\t\t\t\t\ttc.collection[100] = tc.target\n\t\t\t\t} else {\n\t\t\t\t\tfor i := range tc.collection {\n\t\t\t\t\t\ttc.collection[i] = uint8(rand.IntN(256))\n\t\t\t\t\t\tif tc.collection[i] == tc.target {\n\t\t\t\t\t\t\ttc.collection[i] = tc.collection[i] + 1\n\t\t\t\t\t\t\tif tc.collection[i] == 0 { // wrapped around\n\t\t\t\t\t\t\t\ttc.collection[i] = 1\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := ContainsUint8x32(tc.collection, tc.target)\n\t\t\tif got != tc.expected {\n\t\t\t\tt.Errorf(\"ContainsUint8x32() = %v, want %v\", got, tc.expected)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestAVX512ContainsUint16x16(t *testing.T) {\n\trequireAVX2(t)\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname       string\n\t\tcollection []uint16\n\t\ttarget     uint16\n\t\texpected   bool\n\t}{\n\t\t{\"empty\", []uint16{}, 42, false},\n\t\t{\"single found\", []uint16{42}, 42, true},\n\t\t{\"single not found\", []uint16{42}, 10, false},\n\t\t{\"small found\", []uint16{1, 2, 3, 4, 5}, 3, true},\n\t\t{\"small not found\", []uint16{1, 2, 3, 4, 5}, 10, false},\n\t\t{\"exactly 16 found\", make([]uint16, 16), 0, true},\n\t\t{\"exactly 16 not found\", make([]uint16, 16), 1000, false},\n\t\t{\"large found\", make([]uint16, 1000), 0, true},\n\t\t{\"large not found\", make([]uint16, 100), 1000, false},\n\t\t{\"max value\", []uint16{65535, 1000, 500}, 65535, true},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.collection) > 16 && tc.collection[0] == 0 {\n\t\t\t\tif tc.expected {\n\t\t\t\t\ttc.collection[50] = tc.target\n\t\t\t\t} else {\n\t\t\t\t\tfor i := range tc.collection {\n\t\t\t\t\t\ttc.collection[i] = uint16(rand.IntN(65536))\n\t\t\t\t\t\tif tc.collection[i] == tc.target {\n\t\t\t\t\t\t\ttc.collection[i] = tc.collection[i] + 1\n\t\t\t\t\t\t\tif tc.collection[i] == 0 { // wrapped around\n\t\t\t\t\t\t\t\ttc.collection[i] = 1\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := ContainsUint16x16(tc.collection, tc.target)\n\t\t\tif got != tc.expected {\n\t\t\t\tt.Errorf(\"ContainsUint16x16() = %v, want %v\", got, tc.expected)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestAVX512ContainsUint32x8(t *testing.T) {\n\trequireAVX2(t)\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname       string\n\t\tcollection []uint32\n\t\ttarget     uint32\n\t\texpected   bool\n\t}{\n\t\t{\"empty\", []uint32{}, 42, false},\n\t\t{\"single found\", []uint32{42}, 42, true},\n\t\t{\"single not found\", []uint32{42}, 10, false},\n\t\t{\"small found\", []uint32{1, 2, 3, 4, 5}, 3, true},\n\t\t{\"small not found\", []uint32{1, 2, 3, 4, 5}, 10, false},\n\t\t{\"exactly 8 found\", make([]uint32, 8), 0, true},\n\t\t{\"exactly 8 not found\", make([]uint32, 8), 100, false},\n\t\t{\"large found\", make([]uint32, 1000), 0, true},\n\t\t{\"large not found\", make([]uint32, 100), 100000, false},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.collection) > 8 && tc.collection[0] == 0 {\n\t\t\t\tif tc.expected {\n\t\t\t\t\ttc.collection[50] = tc.target\n\t\t\t\t} else {\n\t\t\t\t\tfor i := range tc.collection {\n\t\t\t\t\t\ttc.collection[i] = rand.Uint32()\n\t\t\t\t\t\tif tc.collection[i] == tc.target {\n\t\t\t\t\t\t\ttc.collection[i]++\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := ContainsUint32x8(tc.collection, tc.target)\n\t\t\tif got != tc.expected {\n\t\t\t\tt.Errorf(\"ContainsUint32x8() = %v, want %v\", got, tc.expected)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestAVX512ContainsUint64x4(t *testing.T) {\n\trequireAVX2(t)\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname       string\n\t\tcollection []uint64\n\t\ttarget     uint64\n\t\texpected   bool\n\t}{\n\t\t{\"empty\", []uint64{}, 42, false},\n\t\t{\"single found\", []uint64{42}, 42, true},\n\t\t{\"single not found\", []uint64{42}, 10, false},\n\t\t{\"small found\", []uint64{1, 2, 3, 4, 5}, 3, true},\n\t\t{\"small not found\", []uint64{1, 2, 3, 4, 5}, 10, false},\n\t\t{\"exactly 4 found\", make([]uint64, 4), 0, true},\n\t\t{\"exactly 4 not found\", make([]uint64, 4), 100, false},\n\t\t{\"large found\", make([]uint64, 1000), 0, true},\n\t\t{\"large not found\", make([]uint64, 100), 1000000, false},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.collection) > 4 && tc.collection[0] == 0 {\n\t\t\t\tif tc.expected {\n\t\t\t\t\ttc.collection[50] = tc.target\n\t\t\t\t} else {\n\t\t\t\t\tfor i := range tc.collection {\n\t\t\t\t\t\ttc.collection[i] = rand.Uint64()\n\t\t\t\t\t\tif tc.collection[i] == tc.target {\n\t\t\t\t\t\t\ttc.collection[i]++\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := ContainsUint64x4(tc.collection, tc.target)\n\t\t\tif got != tc.expected {\n\t\t\t\tt.Errorf(\"ContainsUint64x4() = %v, want %v\", got, tc.expected)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestAVX512ContainsFloat32x8(t *testing.T) {\n\trequireAVX2(t)\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname       string\n\t\tcollection []float32\n\t\ttarget     float32\n\t\texpected   bool\n\t}{\n\t\t{\"empty\", []float32{}, 42.5, false},\n\t\t{\"single found\", []float32{42.5}, 42.5, true},\n\t\t{\"single not found\", []float32{42.5}, 10.0, false},\n\t\t{\"small found\", []float32{1.1, 2.2, 3.3, 4.4, 5.5}, 3.3, true},\n\t\t{\"small not found\", []float32{1.1, 2.2, 3.3, 4.4, 5.5}, 10.0, false},\n\t\t{\"exactly 8 found\", []float32{1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0}, 8.0, true},\n\t\t{\"exactly 8 not found\", []float32{1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0}, 100.0, false},\n\t\t{\"large found\", make([]float32, 1000), 0, true},\n\t\t{\"large not found\", make([]float32, 100), 100000.0, false},\n\t\t{\"negative found\", []float32{-1.1, -2.2, 3.3, 4.4}, -2.2, true},\n\t\t{\"zeros\", []float32{0, 0, 0, 0}, 0, true},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.collection) > 8 && tc.collection[0] == 0 {\n\t\t\t\tif tc.expected {\n\t\t\t\t\ttc.collection[50] = tc.target\n\t\t\t\t} else {\n\t\t\t\t\tfor i := range tc.collection {\n\t\t\t\t\t\ttc.collection[i] = rand.Float32() * 10000\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := ContainsFloat32x8(tc.collection, tc.target)\n\t\t\tif got != tc.expected {\n\t\t\t\tt.Errorf(\"ContainsFloat32x8() = %v, want %v\", got, tc.expected)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestAVX512ContainsFloat64x4(t *testing.T) {\n\trequireAVX2(t)\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname       string\n\t\tcollection []float64\n\t\ttarget     float64\n\t\texpected   bool\n\t}{\n\t\t{\"empty\", []float64{}, 42.5, false},\n\t\t{\"single found\", []float64{42.5}, 42.5, true},\n\t\t{\"single not found\", []float64{42.5}, 10.0, false},\n\t\t{\"small found\", []float64{1.1, 2.2, 3.3, 4.4, 5.5}, 3.3, true},\n\t\t{\"small not found\", []float64{1.1, 2.2, 3.3, 4.4, 5.5}, 10.0, false},\n\t\t{\"exactly 4 found\", []float64{1.0, 2.0, 3.0, 4.0}, 4.0, true},\n\t\t{\"exactly 4 not found\", []float64{1.0, 2.0, 3.0, 4.0}, 100.0, false},\n\t\t{\"large found\", make([]float64, 1000), 0, true},\n\t\t{\"large not found\", make([]float64, 100), 100000.0, false},\n\t\t{\"negative found\", []float64{-1.1, -2.2, 3.3, 4.4}, -2.2, true},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.collection) > 4 && tc.collection[0] == 0 {\n\t\t\t\tif tc.expected {\n\t\t\t\t\ttc.collection[50] = tc.target\n\t\t\t\t} else {\n\t\t\t\t\tfor i := range tc.collection {\n\t\t\t\t\t\ttc.collection[i] = rand.Float64() * 10000\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := ContainsFloat64x4(tc.collection, tc.target)\n\t\t\tif got != tc.expected {\n\t\t\t\tt.Errorf(\"ContainsFloat64x4() = %v, want %v\", got, tc.expected)\n\t\t\t}\n\t\t})\n\t}\n}\n\n// Test consistency with lo.Contains\nfunc TestAVX512ContainsConsistency(t *testing.T) {\n\trequireAVX2(t)\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname    string\n\t\tint8    []int8\n\t\tint16   []int16\n\t\tint32   []int32\n\t\tint64   []int64\n\t\tuint8   []uint8\n\t\tuint16  []uint16\n\t\tuint32  []uint32\n\t\tuint64  []uint64\n\t\tfloat32 []float32\n\t\tfloat64 []float64\n\t}{\n\t\t{\n\t\t\tname:    \"mixed\",\n\t\t\tint8:    []int8{-1, 0, 1, 2, 3},\n\t\t\tint16:   []int16{-1, 0, 1, 2, 3},\n\t\t\tint32:   []int32{-1, 0, 1, 2, 3},\n\t\t\tint64:   []int64{-1, 0, 1, 2, 3},\n\t\t\tuint8:   []uint8{0, 1, 2, 3, 4},\n\t\t\tuint16:  []uint16{0, 1, 2, 3, 4},\n\t\t\tuint32:  []uint32{0, 1, 2, 3, 4},\n\t\t\tuint64:  []uint64{0, 1, 2, 3, 4},\n\t\t\tfloat32: []float32{0.0, 1.1, 2.2, 3.3},\n\t\t\tfloat64: []float64{0.0, 1.1, 2.2, 3.3},\n\t\t},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.int8) > 0 {\n\t\t\t\tfor _, target := range tc.int8 {\n\t\t\t\t\tgot := ContainsInt8x16(tc.int8, target)\n\t\t\t\t\twant := lo.Contains(tc.int8, target)\n\t\t\t\t\tif got != want {\n\t\t\t\t\t\tt.Errorf(\"ContainsInt8x16() not consistent with lo.Contains for target %v\", target)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif len(tc.int16) > 0 {\n\t\t\t\tfor _, target := range tc.int16 {\n\t\t\t\t\tgot := ContainsInt16x8(tc.int16, target)\n\t\t\t\t\twant := lo.Contains(tc.int16, target)\n\t\t\t\t\tif got != want {\n\t\t\t\t\t\tt.Errorf(\"ContainsInt16x8() not consistent with lo.Contains for target %v\", target)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif len(tc.int32) > 0 {\n\t\t\t\tfor _, target := range tc.int32 {\n\t\t\t\t\tgot := ContainsInt32x4(tc.int32, target)\n\t\t\t\t\twant := lo.Contains(tc.int32, target)\n\t\t\t\t\tif got != want {\n\t\t\t\t\t\tt.Errorf(\"ContainsInt32x4() not consistent with lo.Contains for target %v\", target)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif len(tc.int64) > 0 {\n\t\t\t\tfor _, target := range tc.int64 {\n\t\t\t\t\tgot := ContainsInt64x2(tc.int64, target)\n\t\t\t\t\twant := lo.Contains(tc.int64, target)\n\t\t\t\t\tif got != want {\n\t\t\t\t\t\tt.Errorf(\"ContainsInt64x2() not consistent with lo.Contains for target %v\", target)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif len(tc.uint8) > 0 {\n\t\t\t\tfor _, target := range tc.uint8 {\n\t\t\t\t\tgot := ContainsUint8x16(tc.uint8, target)\n\t\t\t\t\twant := lo.Contains(tc.uint8, target)\n\t\t\t\t\tif got != want {\n\t\t\t\t\t\tt.Errorf(\"ContainsUint8x16() not consistent with lo.Contains for target %v\", target)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif len(tc.uint16) > 0 {\n\t\t\t\tfor _, target := range tc.uint16 {\n\t\t\t\t\tgot := ContainsUint16x8(tc.uint16, target)\n\t\t\t\t\twant := lo.Contains(tc.uint16, target)\n\t\t\t\t\tif got != want {\n\t\t\t\t\t\tt.Errorf(\"ContainsUint16x8() not consistent with lo.Contains for target %v\", target)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif len(tc.uint32) > 0 {\n\t\t\t\tfor _, target := range tc.uint32 {\n\t\t\t\t\tgot := ContainsUint32x4(tc.uint32, target)\n\t\t\t\t\twant := lo.Contains(tc.uint32, target)\n\t\t\t\t\tif got != want {\n\t\t\t\t\t\tt.Errorf(\"ContainsUint32x4() not consistent with lo.Contains for target %v\", target)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif len(tc.uint64) > 0 {\n\t\t\t\tfor _, target := range tc.uint64 {\n\t\t\t\t\tgot := ContainsUint64x2(tc.uint64, target)\n\t\t\t\t\twant := lo.Contains(tc.uint64, target)\n\t\t\t\t\tif got != want {\n\t\t\t\t\t\tt.Errorf(\"ContainsUint64x2() not consistent with lo.Contains for target %v\", target)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif len(tc.float32) > 0 {\n\t\t\t\tfor _, target := range tc.float32 {\n\t\t\t\t\tgot := ContainsFloat32x4(tc.float32, target)\n\t\t\t\t\twant := lo.Contains(tc.float32, target)\n\t\t\t\t\tif got != want {\n\t\t\t\t\t\tt.Errorf(\"ContainsFloat32x4() not consistent with lo.Contains for target %v\", target)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif len(tc.float64) > 0 {\n\t\t\t\tfor _, target := range tc.float64 {\n\t\t\t\t\tgot := ContainsFloat64x2(tc.float64, target)\n\t\t\t\t\twant := lo.Contains(tc.float64, target)\n\t\t\t\t\tif got != want {\n\t\t\t\t\t\tt.Errorf(\"ContainsFloat64x2() not consistent with lo.Contains for target %v\", target)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif len(tc.int8) > 0 {\n\t\t\t\tfor _, target := range tc.int8 {\n\t\t\t\t\tgot := ContainsInt8x64(tc.int8, target)\n\t\t\t\t\twant := lo.Contains(tc.int8, target)\n\t\t\t\t\tif got != want {\n\t\t\t\t\t\tt.Errorf(\"ContainsInt8x64() not consistent with lo.Contains for target %v\", target)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif len(tc.int16) > 0 {\n\t\t\t\tfor _, target := range tc.int16 {\n\t\t\t\t\tgot := ContainsInt16x32(tc.int16, target)\n\t\t\t\t\twant := lo.Contains(tc.int16, target)\n\t\t\t\t\tif got != want {\n\t\t\t\t\t\tt.Errorf(\"ContainsInt16x32() not consistent with lo.Contains for target %v\", target)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif len(tc.int32) > 0 {\n\t\t\t\tfor _, target := range tc.int32 {\n\t\t\t\t\tgot := ContainsInt32x16(tc.int32, target)\n\t\t\t\t\twant := lo.Contains(tc.int32, target)\n\t\t\t\t\tif got != want {\n\t\t\t\t\t\tt.Errorf(\"ContainsInt32x16() not consistent with lo.Contains for target %v\", target)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif len(tc.int64) > 0 {\n\t\t\t\tfor _, target := range tc.int64 {\n\t\t\t\t\tgot := ContainsInt64x8(tc.int64, target)\n\t\t\t\t\twant := lo.Contains(tc.int64, target)\n\t\t\t\t\tif got != want {\n\t\t\t\t\t\tt.Errorf(\"ContainsInt64x8() not consistent with lo.Contains for target %v\", target)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif len(tc.uint8) > 0 {\n\t\t\t\tfor _, target := range tc.uint8 {\n\t\t\t\t\tgot := ContainsUint8x64(tc.uint8, target)\n\t\t\t\t\twant := lo.Contains(tc.uint8, target)\n\t\t\t\t\tif got != want {\n\t\t\t\t\t\tt.Errorf(\"ContainsUint8x64() not consistent with lo.Contains for target %v\", target)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif len(tc.uint16) > 0 {\n\t\t\t\tfor _, target := range tc.uint16 {\n\t\t\t\t\tgot := ContainsUint16x32(tc.uint16, target)\n\t\t\t\t\twant := lo.Contains(tc.uint16, target)\n\t\t\t\t\tif got != want {\n\t\t\t\t\t\tt.Errorf(\"ContainsUint16x32() not consistent with lo.Contains for target %v\", target)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif len(tc.uint32) > 0 {\n\t\t\t\tfor _, target := range tc.uint32 {\n\t\t\t\t\tgot := ContainsUint32x16(tc.uint32, target)\n\t\t\t\t\twant := lo.Contains(tc.uint32, target)\n\t\t\t\t\tif got != want {\n\t\t\t\t\t\tt.Errorf(\"ContainsUint32x16() not consistent with lo.Contains for target %v\", target)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif len(tc.uint64) > 0 {\n\t\t\t\tfor _, target := range tc.uint64 {\n\t\t\t\t\tgot := ContainsUint64x8(tc.uint64, target)\n\t\t\t\t\twant := lo.Contains(tc.uint64, target)\n\t\t\t\t\tif got != want {\n\t\t\t\t\t\tt.Errorf(\"ContainsUint64x8() not consistent with lo.Contains for target %v\", target)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif len(tc.float32) > 0 {\n\t\t\t\tfor _, target := range tc.float32 {\n\t\t\t\t\tgot := ContainsFloat32x16(tc.float32, target)\n\t\t\t\t\twant := lo.Contains(tc.float32, target)\n\t\t\t\t\tif got != want {\n\t\t\t\t\t\tt.Errorf(\"ContainsFloat32x16() not consistent with lo.Contains for target %v\", target)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif len(tc.float64) > 0 {\n\t\t\t\tfor _, target := range tc.float64 {\n\t\t\t\t\tgot := ContainsFloat64x8(tc.float64, target)\n\t\t\t\t\twant := lo.Contains(tc.float64, target)\n\t\t\t\t\tif got != want {\n\t\t\t\t\t\tt.Errorf(\"ContainsFloat64x8() not consistent with lo.Contains for target %v\", target)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif len(tc.int8) > 0 {\n\t\t\t\tfor _, target := range tc.int8 {\n\t\t\t\t\tgot := ContainsInt8x32(tc.int8, target)\n\t\t\t\t\twant := lo.Contains(tc.int8, target)\n\t\t\t\t\tif got != want {\n\t\t\t\t\t\tt.Errorf(\"ContainsInt8x32() not consistent with lo.Contains for target %v\", target)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif len(tc.int16) > 0 {\n\t\t\t\tfor _, target := range tc.int16 {\n\t\t\t\t\tgot := ContainsInt16x16(tc.int16, target)\n\t\t\t\t\twant := lo.Contains(tc.int16, target)\n\t\t\t\t\tif got != want {\n\t\t\t\t\t\tt.Errorf(\"ContainsInt16x16() not consistent with lo.Contains for target %v\", target)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif len(tc.int32) > 0 {\n\t\t\t\tfor _, target := range tc.int32 {\n\t\t\t\t\tgot := ContainsInt32x8(tc.int32, target)\n\t\t\t\t\twant := lo.Contains(tc.int32, target)\n\t\t\t\t\tif got != want {\n\t\t\t\t\t\tt.Errorf(\"ContainsInt32x8() not consistent with lo.Contains for target %v\", target)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif len(tc.int64) > 0 {\n\t\t\t\tfor _, target := range tc.int64 {\n\t\t\t\t\tgot := ContainsInt64x4(tc.int64, target)\n\t\t\t\t\twant := lo.Contains(tc.int64, target)\n\t\t\t\t\tif got != want {\n\t\t\t\t\t\tt.Errorf(\"ContainsInt64x4() not consistent with lo.Contains for target %v\", target)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif len(tc.uint8) > 0 {\n\t\t\t\tfor _, target := range tc.uint8 {\n\t\t\t\t\tgot := ContainsUint8x32(tc.uint8, target)\n\t\t\t\t\twant := lo.Contains(tc.uint8, target)\n\t\t\t\t\tif got != want {\n\t\t\t\t\t\tt.Errorf(\"ContainsUint8x32() not consistent with lo.Contains for target %v\", target)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif len(tc.uint16) > 0 {\n\t\t\t\tfor _, target := range tc.uint16 {\n\t\t\t\t\tgot := ContainsUint16x16(tc.uint16, target)\n\t\t\t\t\twant := lo.Contains(tc.uint16, target)\n\t\t\t\t\tif got != want {\n\t\t\t\t\t\tt.Errorf(\"ContainsUint16x16() not consistent with lo.Contains for target %v\", target)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif len(tc.uint32) > 0 {\n\t\t\t\tfor _, target := range tc.uint32 {\n\t\t\t\t\tgot := ContainsUint32x8(tc.uint32, target)\n\t\t\t\t\twant := lo.Contains(tc.uint32, target)\n\t\t\t\t\tif got != want {\n\t\t\t\t\t\tt.Errorf(\"ContainsUint32x8() not consistent with lo.Contains for target %v\", target)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif len(tc.uint64) > 0 {\n\t\t\t\tfor _, target := range tc.uint64 {\n\t\t\t\t\tgot := ContainsUint64x4(tc.uint64, target)\n\t\t\t\t\twant := lo.Contains(tc.uint64, target)\n\t\t\t\t\tif got != want {\n\t\t\t\t\t\tt.Errorf(\"ContainsUint64x4() not consistent with lo.Contains for target %v\", target)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif len(tc.float32) > 0 {\n\t\t\t\tfor _, target := range tc.float32 {\n\t\t\t\t\tgot := ContainsFloat32x8(tc.float32, target)\n\t\t\t\t\twant := lo.Contains(tc.float32, target)\n\t\t\t\t\tif got != want {\n\t\t\t\t\t\tt.Errorf(\"ContainsFloat32x8() not consistent with lo.Contains for target %v\", target)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif len(tc.float64) > 0 {\n\t\t\t\tfor _, target := range tc.float64 {\n\t\t\t\t\tgot := ContainsFloat64x4(tc.float64, target)\n\t\t\t\t\twant := lo.Contains(tc.float64, target)\n\t\t\t\t\tif got != want {\n\t\t\t\t\t\tt.Errorf(\"ContainsFloat64x4() not consistent with lo.Contains for target %v\", target)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestAVX512ContainsInt8x64(t *testing.T) {\n\trequireAVX2(t)\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname       string\n\t\tcollection []int8\n\t\ttarget     int8\n\t\texpected   bool\n\t}{\n\t\t{\"empty\", []int8{}, 42, false},\n\t\t{\"single found\", []int8{42}, 42, true},\n\t\t{\"single not found\", []int8{42}, 10, false},\n\t\t{\"small found\", []int8{1, 2, 3, 4, 5}, 3, true},\n\t\t{\"small not found\", []int8{1, 2, 3, 4, 5}, 10, false},\n\t\t{\"exactly 64 found\", make([]int8, 64), 0, true},\n\t\t{\"exactly 64 not found\", make([]int8, 64), 127, false},\n\t\t{\"large found\", make([]int8, 1000), 0, true},\n\t\t{\"large not found\", make([]int8, 100), 127, false},\n\t\t{\"negative found\", []int8{-1, -2, -3, 4, 5}, -2, true},\n\t\t{\"min value\", []int8{-128, 0, 127}, -128, true},\n\t\t{\"max value\", []int8{-128, 0, 127}, 127, true},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.collection) > 64 && tc.collection[0] == 0 {\n\t\t\t\tif tc.expected {\n\t\t\t\t\ttc.collection[100] = tc.target\n\t\t\t\t} else {\n\t\t\t\t\tfor i := range tc.collection {\n\t\t\t\t\t\ttc.collection[i] = int8(rand.IntN(256) - 128)\n\t\t\t\t\t\tif tc.collection[i] == tc.target {\n\t\t\t\t\t\t\ttc.collection[i]++\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := ContainsInt8x64(tc.collection, tc.target)\n\t\t\tif got != tc.expected {\n\t\t\t\tt.Errorf(\"ContainsInt8x64() = %v, want %v\", got, tc.expected)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestAVX512ContainsInt16x32(t *testing.T) {\n\trequireAVX2(t)\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname       string\n\t\tcollection []int16\n\t\ttarget     int16\n\t\texpected   bool\n\t}{\n\t\t{\"empty\", []int16{}, 42, false},\n\t\t{\"single found\", []int16{42}, 42, true},\n\t\t{\"single not found\", []int16{42}, 10, false},\n\t\t{\"small found\", []int16{1, 2, 3, 4, 5}, 3, true},\n\t\t{\"small not found\", []int16{1, 2, 3, 4, 5}, 10, false},\n\t\t{\"exactly 32 found\", make([]int16, 32), 0, true},\n\t\t{\"exactly 32 not found\", make([]int16, 32), 1000, false},\n\t\t{\"large found\", make([]int16, 1000), 0, true},\n\t\t{\"large not found\", make([]int16, 100), 1000, false},\n\t\t{\"negative found\", []int16{-1, -2, -3, 4, 5}, -2, true},\n\t\t{\"min value\", []int16{-32768, 0, 32767}, -32768, true},\n\t\t{\"max value\", []int16{-32768, 0, 32767}, 32767, true},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.collection) > 32 && tc.collection[0] == 0 {\n\t\t\t\tif tc.expected {\n\t\t\t\t\ttc.collection[50] = tc.target\n\t\t\t\t} else {\n\t\t\t\t\tfor i := range tc.collection {\n\t\t\t\t\t\ttc.collection[i] = int16(rand.IntN(65536) - 32768)\n\t\t\t\t\t\tif tc.collection[i] == tc.target {\n\t\t\t\t\t\t\ttc.collection[i]++\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := ContainsInt16x32(tc.collection, tc.target)\n\t\t\tif got != tc.expected {\n\t\t\t\tt.Errorf(\"ContainsInt16x32() = %v, want %v\", got, tc.expected)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestAVX512ContainsInt32x16(t *testing.T) {\n\trequireAVX2(t)\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname       string\n\t\tcollection []int32\n\t\ttarget     int32\n\t\texpected   bool\n\t}{\n\t\t{\"empty\", []int32{}, 42, false},\n\t\t{\"single found\", []int32{42}, 42, true},\n\t\t{\"single not found\", []int32{42}, 10, false},\n\t\t{\"small found\", []int32{1, 2, 3, 4, 5}, 3, true},\n\t\t{\"small not found\", []int32{1, 2, 3, 4, 5}, 10, false},\n\t\t{\"exactly 16 found\", make([]int32, 16), 0, true},\n\t\t{\"exactly 16 not found\", make([]int32, 16), 100, false},\n\t\t{\"large found\", make([]int32, 1000), 0, true},\n\t\t{\"large not found\", make([]int32, 100), 100000, false},\n\t\t{\"negative found\", []int32{-1, -2, -3, 4, 5}, -2, true},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.collection) > 16 && tc.collection[0] == 0 {\n\t\t\t\tif tc.expected {\n\t\t\t\t\ttc.collection[50] = tc.target\n\t\t\t\t} else {\n\t\t\t\t\tfor i := range tc.collection {\n\t\t\t\t\t\ttc.collection[i] = rand.Int32()\n\t\t\t\t\t\tif tc.collection[i] == tc.target {\n\t\t\t\t\t\t\ttc.collection[i]++\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := ContainsInt32x16(tc.collection, tc.target)\n\t\t\tif got != tc.expected {\n\t\t\t\tt.Errorf(\"ContainsInt32x16() = %v, want %v\", got, tc.expected)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestAVX512ContainsInt64x8(t *testing.T) {\n\trequireAVX2(t)\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname       string\n\t\tcollection []int64\n\t\ttarget     int64\n\t\texpected   bool\n\t}{\n\t\t{\"empty\", []int64{}, 42, false},\n\t\t{\"single found\", []int64{42}, 42, true},\n\t\t{\"single not found\", []int64{42}, 10, false},\n\t\t{\"small found\", []int64{1, 2, 3, 4, 5}, 3, true},\n\t\t{\"small not found\", []int64{1, 2, 3, 4, 5}, 10, false},\n\t\t{\"exactly 8 found\", make([]int64, 8), 0, true},\n\t\t{\"exactly 8 not found\", make([]int64, 8), 100, false},\n\t\t{\"large found\", make([]int64, 1000), 0, true},\n\t\t{\"large not found\", make([]int64, 100), 1000000, false},\n\t\t{\"negative found\", []int64{-1, -2, -3, 4, 5}, -2, true},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.collection) > 8 && tc.collection[0] == 0 {\n\t\t\t\tif tc.expected {\n\t\t\t\t\ttc.collection[50] = tc.target\n\t\t\t\t} else {\n\t\t\t\t\tfor i := range tc.collection {\n\t\t\t\t\t\ttc.collection[i] = rand.Int64()\n\t\t\t\t\t\tif tc.collection[i] == tc.target {\n\t\t\t\t\t\t\ttc.collection[i]++\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := ContainsInt64x8(tc.collection, tc.target)\n\t\t\tif got != tc.expected {\n\t\t\t\tt.Errorf(\"ContainsInt64x8() = %v, want %v\", got, tc.expected)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestAVX512ContainsUint8x64(t *testing.T) {\n\trequireAVX2(t)\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname       string\n\t\tcollection []uint8\n\t\ttarget     uint8\n\t\texpected   bool\n\t}{\n\t\t{\"empty\", []uint8{}, 42, false},\n\t\t{\"single found\", []uint8{42}, 42, true},\n\t\t{\"single not found\", []uint8{42}, 10, false},\n\t\t{\"small found\", []uint8{1, 2, 3, 4, 5}, 3, true},\n\t\t{\"small not found\", []uint8{1, 2, 3, 4, 5}, 10, false},\n\t\t{\"exactly 64 found\", make([]uint8, 64), 0, true},\n\t\t{\"exactly 64 not found\", make([]uint8, 64), 255, false},\n\t\t{\"large found\", make([]uint8, 1000), 0, true},\n\t\t{\"large not found\", make([]uint8, 100), 255, false},\n\t\t{\"max value\", []uint8{255, 100, 50}, 255, true},\n\t\t{\"zero found\", []uint8{0, 1, 2, 3}, 0, true},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.collection) > 64 && tc.collection[0] == 0 {\n\t\t\t\tif tc.expected {\n\t\t\t\t\ttc.collection[100] = tc.target\n\t\t\t\t} else {\n\t\t\t\t\tfor i := range tc.collection {\n\t\t\t\t\t\ttc.collection[i] = uint8(rand.IntN(256))\n\t\t\t\t\t\tif tc.collection[i] == tc.target {\n\t\t\t\t\t\t\ttc.collection[i] = tc.collection[i] + 1\n\t\t\t\t\t\t\tif tc.collection[i] == 0 { // wrapped around\n\t\t\t\t\t\t\t\ttc.collection[i] = 1\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := ContainsUint8x64(tc.collection, tc.target)\n\t\t\tif got != tc.expected {\n\t\t\t\tt.Errorf(\"ContainsUint8x64() = %v, want %v\", got, tc.expected)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestAVX512ContainsUint16x32(t *testing.T) {\n\trequireAVX2(t)\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname       string\n\t\tcollection []uint16\n\t\ttarget     uint16\n\t\texpected   bool\n\t}{\n\t\t{\"empty\", []uint16{}, 42, false},\n\t\t{\"single found\", []uint16{42}, 42, true},\n\t\t{\"single not found\", []uint16{42}, 10, false},\n\t\t{\"small found\", []uint16{1, 2, 3, 4, 5}, 3, true},\n\t\t{\"small not found\", []uint16{1, 2, 3, 4, 5}, 10, false},\n\t\t{\"exactly 32 found\", make([]uint16, 32), 0, true},\n\t\t{\"exactly 32 not found\", make([]uint16, 32), 1000, false},\n\t\t{\"large found\", make([]uint16, 1000), 0, true},\n\t\t{\"large not found\", make([]uint16, 100), 1000, false},\n\t\t{\"max value\", []uint16{65535, 1000, 500}, 65535, true},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.collection) > 32 && tc.collection[0] == 0 {\n\t\t\t\tif tc.expected {\n\t\t\t\t\ttc.collection[50] = tc.target\n\t\t\t\t} else {\n\t\t\t\t\tfor i := range tc.collection {\n\t\t\t\t\t\ttc.collection[i] = uint16(rand.IntN(65536))\n\t\t\t\t\t\tif tc.collection[i] == tc.target {\n\t\t\t\t\t\t\ttc.collection[i] = tc.collection[i] + 1\n\t\t\t\t\t\t\tif tc.collection[i] == 0 { // wrapped around\n\t\t\t\t\t\t\t\ttc.collection[i] = 1\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := ContainsUint16x32(tc.collection, tc.target)\n\t\t\tif got != tc.expected {\n\t\t\t\tt.Errorf(\"ContainsUint16x32() = %v, want %v\", got, tc.expected)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestAVX512ContainsUint32x16(t *testing.T) {\n\trequireAVX2(t)\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname       string\n\t\tcollection []uint32\n\t\ttarget     uint32\n\t\texpected   bool\n\t}{\n\t\t{\"empty\", []uint32{}, 42, false},\n\t\t{\"single found\", []uint32{42}, 42, true},\n\t\t{\"single not found\", []uint32{42}, 10, false},\n\t\t{\"small found\", []uint32{1, 2, 3, 4, 5}, 3, true},\n\t\t{\"small not found\", []uint32{1, 2, 3, 4, 5}, 10, false},\n\t\t{\"exactly 16 found\", make([]uint32, 16), 0, true},\n\t\t{\"exactly 16 not found\", make([]uint32, 16), 100, false},\n\t\t{\"large found\", make([]uint32, 1000), 0, true},\n\t\t{\"large not found\", make([]uint32, 100), 100000, false},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.collection) > 16 && tc.collection[0] == 0 {\n\t\t\t\tif tc.expected {\n\t\t\t\t\ttc.collection[50] = tc.target\n\t\t\t\t} else {\n\t\t\t\t\tfor i := range tc.collection {\n\t\t\t\t\t\ttc.collection[i] = rand.Uint32()\n\t\t\t\t\t\tif tc.collection[i] == tc.target {\n\t\t\t\t\t\t\ttc.collection[i]++\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := ContainsUint32x16(tc.collection, tc.target)\n\t\t\tif got != tc.expected {\n\t\t\t\tt.Errorf(\"ContainsUint32x16() = %v, want %v\", got, tc.expected)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestAVX512ContainsUint64x8(t *testing.T) {\n\trequireAVX2(t)\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname       string\n\t\tcollection []uint64\n\t\ttarget     uint64\n\t\texpected   bool\n\t}{\n\t\t{\"empty\", []uint64{}, 42, false},\n\t\t{\"single found\", []uint64{42}, 42, true},\n\t\t{\"single not found\", []uint64{42}, 10, false},\n\t\t{\"small found\", []uint64{1, 2, 3, 4, 5}, 3, true},\n\t\t{\"small not found\", []uint64{1, 2, 3, 4, 5}, 10, false},\n\t\t{\"exactly 8 found\", make([]uint64, 8), 0, true},\n\t\t{\"exactly 8 not found\", make([]uint64, 8), 100, false},\n\t\t{\"large found\", make([]uint64, 1000), 0, true},\n\t\t{\"large not found\", make([]uint64, 100), 1000000, false},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.collection) > 8 && tc.collection[0] == 0 {\n\t\t\t\tif tc.expected {\n\t\t\t\t\ttc.collection[50] = tc.target\n\t\t\t\t} else {\n\t\t\t\t\tfor i := range tc.collection {\n\t\t\t\t\t\ttc.collection[i] = rand.Uint64()\n\t\t\t\t\t\tif tc.collection[i] == tc.target {\n\t\t\t\t\t\t\ttc.collection[i]++\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := ContainsUint64x8(tc.collection, tc.target)\n\t\t\tif got != tc.expected {\n\t\t\t\tt.Errorf(\"ContainsUint64x8() = %v, want %v\", got, tc.expected)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestAVX512ContainsFloat32x16(t *testing.T) {\n\trequireAVX2(t)\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname       string\n\t\tcollection []float32\n\t\ttarget     float32\n\t\texpected   bool\n\t}{\n\t\t{\"empty\", []float32{}, 42.5, false},\n\t\t{\"single found\", []float32{42.5}, 42.5, true},\n\t\t{\"single not found\", []float32{42.5}, 10.0, false},\n\t\t{\"small found\", []float32{1.1, 2.2, 3.3, 4.4, 5.5}, 3.3, true},\n\t\t{\"small not found\", []float32{1.1, 2.2, 3.3, 4.4, 5.5}, 10.0, false},\n\t\t{\"exactly 16 found\", []float32{1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0}, 16.0, true},\n\t\t{\"exactly 16 not found\", []float32{1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0}, 100.0, false},\n\t\t{\"large found\", make([]float32, 1000), 0, true},\n\t\t{\"large not found\", make([]float32, 100), 100000.0, false},\n\t\t{\"negative found\", []float32{-1.1, -2.2, 3.3, 4.4}, -2.2, true},\n\t\t{\"zeros\", []float32{0, 0, 0, 0}, 0, true},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.collection) > 16 && tc.collection[0] == 0 {\n\t\t\t\tif tc.expected {\n\t\t\t\t\ttc.collection[50] = tc.target\n\t\t\t\t} else {\n\t\t\t\t\tfor i := range tc.collection {\n\t\t\t\t\t\ttc.collection[i] = rand.Float32() * 10000\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := ContainsFloat32x16(tc.collection, tc.target)\n\t\t\tif got != tc.expected {\n\t\t\t\tt.Errorf(\"ContainsFloat32x16() = %v, want %v\", got, tc.expected)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestAVX512ContainsFloat64x8(t *testing.T) {\n\trequireAVX2(t)\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname       string\n\t\tcollection []float64\n\t\ttarget     float64\n\t\texpected   bool\n\t}{\n\t\t{\"empty\", []float64{}, 42.5, false},\n\t\t{\"single found\", []float64{42.5}, 42.5, true},\n\t\t{\"single not found\", []float64{42.5}, 10.0, false},\n\t\t{\"small found\", []float64{1.1, 2.2, 3.3, 4.4, 5.5}, 3.3, true},\n\t\t{\"small not found\", []float64{1.1, 2.2, 3.3, 4.4, 5.5}, 10.0, false},\n\t\t{\"exactly 8 found\", []float64{1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0}, 8.0, true},\n\t\t{\"exactly 8 not found\", []float64{1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0}, 100.0, false},\n\t\t{\"large found\", make([]float64, 1000), 0, true},\n\t\t{\"large not found\", make([]float64, 100), 100000.0, false},\n\t\t{\"negative found\", []float64{-1.1, -2.2, 3.3, 4.4}, -2.2, true},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.collection) > 8 && tc.collection[0] == 0 {\n\t\t\t\tif tc.expected {\n\t\t\t\t\ttc.collection[50] = tc.target\n\t\t\t\t} else {\n\t\t\t\t\tfor i := range tc.collection {\n\t\t\t\t\t\ttc.collection[i] = rand.Float64() * 10000\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := ContainsFloat64x8(tc.collection, tc.target)\n\t\t\tif got != tc.expected {\n\t\t\t\tt.Errorf(\"ContainsFloat64x8() = %v, want %v\", got, tc.expected)\n\t\t\t}\n\t\t})\n\t}\n}\n\n// Test type aliases work correctly\nfunc TestAVX512ContainsTypeAlias(t *testing.T) {\n\trequireAVX2(t)\n\trequireAVX512(t)\n\tinput := []myInt8{1, 2, 3, 4, 5}\n\n\ttarget := myInt8(3)\n\tgot := ContainsInt8x64(input, target)\n\tif !got {\n\t\tt.Errorf(\"ContainsInt8x64() with type alias = false, want true\")\n\t}\n\n\ttarget = myInt8(10)\n\tgot = ContainsInt8x64(input, target)\n\tif got {\n\t\tt.Errorf(\"ContainsInt8x64() with type alias = true, want false\")\n\t}\n\n\ttarget = myInt8(3)\n\tgot = ContainsInt8x16(input, target)\n\tif !got {\n\t\tt.Errorf(\"ContainsInt8x16() with type alias = false, want true\")\n\t}\n\n\ttarget = myInt8(10)\n\tgot = ContainsInt8x16(input, target)\n\tif got {\n\t\tt.Errorf(\"ContainsInt8x16() with type alias = true, want false\")\n\t}\n\n\ttarget = myInt8(3)\n\tgot = ContainsInt8x32(input, target)\n\tif !got {\n\t\tt.Errorf(\"ContainsInt8x32() with type alias = false, want true\")\n\t}\n\n\ttarget = myInt8(10)\n\tgot = ContainsInt8x32(input, target)\n\tif got {\n\t\tt.Errorf(\"ContainsInt8x32() with type alias = true, want false\")\n\t}\n}\n"
  },
  {
    "path": "exp/simd/intersect_bench_test.go",
    "content": "//go:build go1.26 && goexperiment.simd && amd64\n\npackage simd\n\nimport (\n\t\"testing\"\n)\n\n// Benchmark suite for SIMD Contains operations compared to core lo package fallbacks.\n// These benchmarks measure the performance of element lookup operations\n// across different SIMD implementations (AVX, AVX2, AVX512) and data sizes.\n\n// Benchmark sizes for Contains operations\nvar containsBenchmarkSizes = []struct {\n\tname string\n\tsize int\n}{\n\t{\"tiny\", 4},       // Smaller than AVX width (16 lanes for int8)\n\t{\"small\", 16},     // Exactly AVX width for int8\n\t{\"medium\", 64},    // Multiple of AVX, between AVX and AVX2 for int8\n\t{\"large\", 256},    // Multiple of AVX2 (32 lanes for int8)\n\t{\"xlarge\", 1024},  // Multiple of AVX512 (64 lanes for int8)\n\t{\"massive\", 8192}, // Very large dataset\n}\n\n// ============================================================================\n// CONTAINS INT8 BENCHMARKS\n// ============================================================================\n\nfunc BenchmarkContainsInt8(b *testing.B) {\n\tfor _, bs := range containsBenchmarkSizes {\n\t\tb.Run(bs.name, func(b *testing.B) {\n\t\t\tdata := generateInt8(bs.size)\n\t\t\ttarget := int8(42)\n\n\t\t\tb.Run(\"AVX512-x16\", func(b *testing.B) {\n\t\t\t\trequireAVX512(b) // ContainsInt8x16 is in intersect_avx512.go which uses AVX-512\n\t\t\t\tb.ReportAllocs()\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = ContainsInt8x16(data, target)\n\t\t\t\t}\n\t\t\t})\n\t\t\tb.Run(\"AVX512-x32\", func(b *testing.B) {\n\t\t\t\trequireAVX512(b) // ContainsInt8x32 is in intersect_avx512.go which uses AVX-512\n\t\t\t\tb.ReportAllocs()\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = ContainsInt8x32(data, target)\n\t\t\t\t}\n\t\t\t})\n\t\t\tb.Run(\"AVX512-x64\", func(b *testing.B) {\n\t\t\t\trequireAVX512(b)\n\t\t\t\tb.ReportAllocs()\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = ContainsInt8x64(data, target)\n\t\t\t\t}\n\t\t\t})\n\t\t})\n\t}\n}\n\n// ============================================================================\n// CONTAINS INT16 BENCHMARKS\n// ============================================================================\n\nfunc BenchmarkContainsInt16(b *testing.B) {\n\tfor _, bs := range containsBenchmarkSizes {\n\t\tb.Run(bs.name, func(b *testing.B) {\n\t\t\tdata := generateInt16(bs.size)\n\t\t\ttarget := int16(42)\n\n\t\t\tb.Run(\"AVX512-x8\", func(b *testing.B) {\n\t\t\t\trequireAVX512(b) // ContainsInt16x8 is in intersect_avx512.go which uses AVX-512\n\t\t\t\tb.ReportAllocs()\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = ContainsInt16x8(data, target)\n\t\t\t\t}\n\t\t\t})\n\t\t\tb.Run(\"AVX512-x16\", func(b *testing.B) {\n\t\t\t\trequireAVX512(b) // ContainsInt16x16 is in intersect_avx512.go which uses AVX-512\n\t\t\t\tb.ReportAllocs()\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = ContainsInt16x16(data, target)\n\t\t\t\t}\n\t\t\t})\n\t\t\tb.Run(\"AVX512-x32\", func(b *testing.B) {\n\t\t\t\trequireAVX512(b)\n\t\t\t\tb.ReportAllocs()\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = ContainsInt16x32(data, target)\n\t\t\t\t}\n\t\t\t})\n\t\t})\n\t}\n}\n\n// ============================================================================\n// CONTAINS INT32 BENCHMARKS\n// ============================================================================\n\nfunc BenchmarkContainsInt32(b *testing.B) {\n\tfor _, bs := range containsBenchmarkSizes {\n\t\tb.Run(bs.name, func(b *testing.B) {\n\t\t\tdata := generateInt32(bs.size)\n\t\t\ttarget := int32(42)\n\n\t\t\tb.Run(\"AVX512-x4\", func(b *testing.B) {\n\t\t\t\trequireAVX512(b) // ContainsInt32x4 is in intersect_avx512.go which uses AVX-512\n\t\t\t\tb.ReportAllocs()\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = ContainsInt32x4(data, target)\n\t\t\t\t}\n\t\t\t})\n\t\t\tb.Run(\"AVX512-x8\", func(b *testing.B) {\n\t\t\t\trequireAVX512(b) // ContainsInt32x8 is in intersect_avx512.go which uses AVX-512\n\t\t\t\tb.ReportAllocs()\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = ContainsInt32x8(data, target)\n\t\t\t\t}\n\t\t\t})\n\t\t\tb.Run(\"AVX512-x16\", func(b *testing.B) {\n\t\t\t\trequireAVX512(b)\n\t\t\t\tb.ReportAllocs()\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = ContainsInt32x16(data, target)\n\t\t\t\t}\n\t\t\t})\n\t\t})\n\t}\n}\n\n// ============================================================================\n// CONTAINS INT64 BENCHMARKS\n// ============================================================================\n\nfunc BenchmarkContainsInt64(b *testing.B) {\n\tfor _, bs := range containsBenchmarkSizes {\n\t\tb.Run(bs.name, func(b *testing.B) {\n\t\t\tdata := generateInt64(bs.size)\n\t\t\ttarget := int64(42)\n\n\t\t\tb.Run(\"AVX512-x2\", func(b *testing.B) {\n\t\t\t\trequireAVX512(b) // ContainsInt64x2 is in intersect_avx512.go which uses AVX-512\n\t\t\t\tb.ReportAllocs()\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = ContainsInt64x2(data, target)\n\t\t\t\t}\n\t\t\t})\n\t\t\tb.Run(\"AVX512-x4\", func(b *testing.B) {\n\t\t\t\trequireAVX512(b) // ContainsInt64x4 is in intersect_avx512.go which uses AVX-512\n\t\t\t\tb.ReportAllocs()\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = ContainsInt64x4(data, target)\n\t\t\t\t}\n\t\t\t})\n\t\t\tb.Run(\"AVX512-x8\", func(b *testing.B) {\n\t\t\t\trequireAVX512(b)\n\t\t\t\tb.ReportAllocs()\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = ContainsInt64x8(data, target)\n\t\t\t\t}\n\t\t\t})\n\t\t})\n\t}\n}\n\n// ============================================================================\n// CONTAINS UINT8 BENCHMARKS\n// ============================================================================\n\nfunc BenchmarkContainsUint8(b *testing.B) {\n\tfor _, bs := range containsBenchmarkSizes {\n\t\tb.Run(bs.name, func(b *testing.B) {\n\t\t\tdata := generateUint8(bs.size)\n\t\t\ttarget := uint8(255)\n\n\t\t\tb.Run(\"AVX512-x16\", func(b *testing.B) {\n\t\t\t\trequireAVX512(b) // ContainsUint8x16 is in intersect_avx512.go which uses AVX-512\n\t\t\t\tb.ReportAllocs()\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = ContainsUint8x16(data, target)\n\t\t\t\t}\n\t\t\t})\n\t\t\tb.Run(\"AVX512-x32\", func(b *testing.B) {\n\t\t\t\trequireAVX512(b) // ContainsUint8x32 is in intersect_avx512.go which uses AVX-512\n\t\t\t\tb.ReportAllocs()\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = ContainsUint8x32(data, target)\n\t\t\t\t}\n\t\t\t})\n\t\t\tb.Run(\"AVX512-x64\", func(b *testing.B) {\n\t\t\t\trequireAVX512(b)\n\t\t\t\tb.ReportAllocs()\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = ContainsUint8x64(data, target)\n\t\t\t\t}\n\t\t\t})\n\t\t})\n\t}\n}\n\n// ============================================================================\n// CONTAINS UINT16 BENCHMARKS\n// ============================================================================\n\nfunc BenchmarkContainsUint16(b *testing.B) {\n\tfor _, bs := range containsBenchmarkSizes {\n\t\tb.Run(bs.name, func(b *testing.B) {\n\t\t\tdata := generateUint16(bs.size)\n\t\t\ttarget := uint16(42)\n\n\t\t\tb.Run(\"AVX512-x8\", func(b *testing.B) {\n\t\t\t\trequireAVX512(b) // ContainsUint16x8 is in intersect_avx512.go which uses AVX-512\n\t\t\t\tb.ReportAllocs()\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = ContainsUint16x8(data, target)\n\t\t\t\t}\n\t\t\t})\n\t\t\tb.Run(\"AVX512-x16\", func(b *testing.B) {\n\t\t\t\trequireAVX512(b) // ContainsUint16x16 is in intersect_avx512.go which uses AVX-512\n\t\t\t\tb.ReportAllocs()\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = ContainsUint16x16(data, target)\n\t\t\t\t}\n\t\t\t})\n\t\t\tb.Run(\"AVX512-x32\", func(b *testing.B) {\n\t\t\t\trequireAVX512(b)\n\t\t\t\tb.ReportAllocs()\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = ContainsUint16x32(data, target)\n\t\t\t\t}\n\t\t\t})\n\t\t})\n\t}\n}\n\n// ============================================================================\n// CONTAINS UINT32 BENCHMARKS\n// ============================================================================\n\nfunc BenchmarkContainsUint32(b *testing.B) {\n\tfor _, bs := range containsBenchmarkSizes {\n\t\tb.Run(bs.name, func(b *testing.B) {\n\t\t\tdata := generateUint32(bs.size)\n\t\t\ttarget := uint32(42)\n\n\t\t\tb.Run(\"AVX512-x4\", func(b *testing.B) {\n\t\t\t\trequireAVX512(b) // ContainsUint32x4 is in intersect_avx512.go which uses AVX-512\n\t\t\t\tb.ReportAllocs()\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = ContainsUint32x4(data, target)\n\t\t\t\t}\n\t\t\t})\n\t\t\tb.Run(\"AVX512-x8\", func(b *testing.B) {\n\t\t\t\trequireAVX512(b) // ContainsUint32x8 is in intersect_avx512.go which uses AVX-512\n\t\t\t\tb.ReportAllocs()\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = ContainsUint32x8(data, target)\n\t\t\t\t}\n\t\t\t})\n\t\t\tb.Run(\"AVX512-x16\", func(b *testing.B) {\n\t\t\t\trequireAVX512(b)\n\t\t\t\tb.ReportAllocs()\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = ContainsUint32x16(data, target)\n\t\t\t\t}\n\t\t\t})\n\t\t})\n\t}\n}\n\n// ============================================================================\n// CONTAINS UINT64 BENCHMARKS\n// ============================================================================\n\nfunc BenchmarkContainsUint64(b *testing.B) {\n\tfor _, bs := range containsBenchmarkSizes {\n\t\tb.Run(bs.name, func(b *testing.B) {\n\t\t\tdata := generateUint64(bs.size)\n\t\t\ttarget := uint64(42)\n\n\t\t\tb.Run(\"AVX512-x2\", func(b *testing.B) {\n\t\t\t\trequireAVX512(b) // ContainsUint64x2 is in intersect_avx512.go which uses AVX-512\n\t\t\t\tb.ReportAllocs()\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = ContainsUint64x2(data, target)\n\t\t\t\t}\n\t\t\t})\n\t\t\tb.Run(\"AVX512-x4\", func(b *testing.B) {\n\t\t\t\trequireAVX512(b) // ContainsUint64x4 is in intersect_avx512.go which uses AVX-512\n\t\t\t\tb.ReportAllocs()\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = ContainsUint64x4(data, target)\n\t\t\t\t}\n\t\t\t})\n\t\t\tb.Run(\"AVX512-x8\", func(b *testing.B) {\n\t\t\t\trequireAVX512(b)\n\t\t\t\tb.ReportAllocs()\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = ContainsUint64x8(data, target)\n\t\t\t\t}\n\t\t\t})\n\t\t})\n\t}\n}\n\n// ============================================================================\n// CONTAINS FLOAT32 BENCHMARKS\n// ============================================================================\n\nfunc BenchmarkContainsFloat32(b *testing.B) {\n\tfor _, bs := range containsBenchmarkSizes {\n\t\tb.Run(bs.name, func(b *testing.B) {\n\t\t\tdata := generateFloat32(bs.size)\n\t\t\ttarget := float32(42.5)\n\n\t\t\tb.Run(\"AVX512-x4\", func(b *testing.B) {\n\t\t\t\trequireAVX512(b) // ContainsFloat32x4 is in intersect_avx512.go which uses AVX-512\n\t\t\t\tb.ReportAllocs()\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = ContainsFloat32x4(data, target)\n\t\t\t\t}\n\t\t\t})\n\t\t\tb.Run(\"AVX512-x8\", func(b *testing.B) {\n\t\t\t\trequireAVX512(b) // ContainsFloat32x8 is in intersect_avx512.go which uses AVX-512\n\t\t\t\tb.ReportAllocs()\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = ContainsFloat32x8(data, target)\n\t\t\t\t}\n\t\t\t})\n\t\t\tb.Run(\"AVX512-x16\", func(b *testing.B) {\n\t\t\t\trequireAVX512(b)\n\t\t\t\tb.ReportAllocs()\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = ContainsFloat32x16(data, target)\n\t\t\t\t}\n\t\t\t})\n\t\t})\n\t}\n}\n\n// ============================================================================\n// CONTAINS FLOAT64 BENCHMARKS\n// ============================================================================\n\nfunc BenchmarkContainsFloat64(b *testing.B) {\n\tfor _, bs := range containsBenchmarkSizes {\n\t\tb.Run(bs.name, func(b *testing.B) {\n\t\t\tdata := generateFloat64(bs.size)\n\t\t\ttarget := float64(42.5)\n\n\t\t\tb.Run(\"AVX512-x2\", func(b *testing.B) {\n\t\t\t\trequireAVX512(b) // ContainsFloat64x2 is in intersect_avx512.go which uses AVX-512\n\t\t\t\tb.ReportAllocs()\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = ContainsFloat64x2(data, target)\n\t\t\t\t}\n\t\t\t})\n\t\t\tb.Run(\"AVX512-x4\", func(b *testing.B) {\n\t\t\t\trequireAVX512(b) // ContainsFloat64x4 is in intersect_avx512.go which uses AVX-512\n\t\t\t\tb.ReportAllocs()\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = ContainsFloat64x4(data, target)\n\t\t\t\t}\n\t\t\t})\n\t\t\tb.Run(\"AVX512-x8\", func(b *testing.B) {\n\t\t\t\trequireAVX512(b)\n\t\t\t\tb.ReportAllocs()\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = ContainsFloat64x8(data, target)\n\t\t\t\t}\n\t\t\t})\n\t\t})\n\t}\n}\n\n// ============================================================================\n// CONTAINS WORST-CASE BENCHMARKS (target at end)\n// ============================================================================\n\n// These benchmarks test worst-case performance where target is at the very end\nfunc BenchmarkContainsWorstCase(b *testing.B) {\n\tsize := 1024\n\tdata := make([]int32, size)\n\tfor i := range data {\n\t\tdata[i] = int32(i)\n\t}\n\ttarget := int32(size - 1) // Target at the very end\n\n\tb.Run(\"AVX512-x4\", func(b *testing.B) {\n\t\trequireAVX512(b) // ContainsInt32x4 is in intersect_avx512.go which uses AVX-512\n\t\tb.ReportAllocs()\n\t\tfor i := 0; i < b.N; i++ {\n\t\t\t_ = ContainsInt32x4(data, target)\n\t\t}\n\t})\n\tb.Run(\"AVX512-x8\", func(b *testing.B) {\n\t\trequireAVX512(b) // ContainsInt32x8 is in intersect_avx512.go which uses AVX-512\n\t\tb.ReportAllocs()\n\t\tfor i := 0; i < b.N; i++ {\n\t\t\t_ = ContainsInt32x8(data, target)\n\t\t}\n\t})\n\tb.Run(\"AVX512-x16\", func(b *testing.B) {\n\t\trequireAVX512(b) // ContainsInt32x16 is in intersect_avx512.go which uses AVX-512\n\t\tb.ReportAllocs()\n\t\tfor i := 0; i < b.N; i++ {\n\t\t\t_ = ContainsInt32x16(data, target)\n\t\t}\n\t})\n}\n\n// ============================================================================\n// CONTAINS BEST-CASE BENCHMARKS (target at beginning)\n// ============================================================================\n\n// These benchmarks test best-case performance where target is at the beginning\nfunc BenchmarkContainsBestCase(b *testing.B) {\n\tsize := 1024\n\tdata := make([]int32, size)\n\tfor i := range data {\n\t\tdata[i] = int32(i)\n\t}\n\ttarget := int32(0) // Target at the very beginning\n\n\tb.Run(\"AVX512-x4\", func(b *testing.B) {\n\t\trequireAVX512(b) // ContainsInt32x4 is in intersect_avx512.go which uses AVX-512\n\t\tb.ReportAllocs()\n\t\tfor i := 0; i < b.N; i++ {\n\t\t\t_ = ContainsInt32x4(data, target)\n\t\t}\n\t})\n\tb.Run(\"AVX512-x8\", func(b *testing.B) {\n\t\trequireAVX512(b) // ContainsInt32x8 is in intersect_avx512.go which uses AVX-512\n\t\tb.ReportAllocs()\n\t\tfor i := 0; i < b.N; i++ {\n\t\t\t_ = ContainsInt32x8(data, target)\n\t\t}\n\t})\n\tb.Run(\"AVX512-x16\", func(b *testing.B) {\n\t\trequireAVX512(b) // ContainsInt32x16 is in intersect_avx512.go which uses AVX-512\n\t\tb.ReportAllocs()\n\t\tfor i := 0; i < b.N; i++ {\n\t\t\t_ = ContainsInt32x16(data, target)\n\t\t}\n\t})\n}\n\n// ============================================================================\n// CONTAINS NEGATIVE-CASE BENCHMARKS (target not present)\n// ============================================================================\n\n// These benchmarks test performance when target is not in the collection\nfunc BenchmarkContainsNegative(b *testing.B) {\n\tfor _, bs := range containsBenchmarkSizes {\n\t\tb.Run(bs.name, func(b *testing.B) {\n\t\t\tdata := generateInt32(bs.size)\n\t\t\ttarget := int32(999999) // Target that's unlikely to be in the data\n\n\t\t\tb.Run(\"AVX512-x4\", func(b *testing.B) {\n\t\t\t\trequireAVX512(b) // ContainsInt32x4 is in intersect_avx512.go which uses AVX-512\n\t\t\t\tb.ReportAllocs()\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = ContainsInt32x4(data, target)\n\t\t\t\t}\n\t\t\t})\n\t\t\tb.Run(\"AVX512-x8\", func(b *testing.B) {\n\t\t\t\trequireAVX512(b) // ContainsInt32x8 is in intersect_avx512.go which uses AVX-512\n\t\t\t\tb.ReportAllocs()\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = ContainsInt32x8(data, target)\n\t\t\t\t}\n\t\t\t})\n\t\t\tb.Run(\"AVX512-x16\", func(b *testing.B) {\n\t\t\t\trequireAVX512(b)\n\t\t\t\tb.ReportAllocs()\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = ContainsInt32x16(data, target)\n\t\t\t\t}\n\t\t\t})\n\t\t})\n\t}\n}\n\n// ============================================================================\n// CONTAINS LANE WIDTH COMPARISON BENCHMARK\n// ============================================================================\n\n// This benchmark shows how performance scales with SIMD register width\nfunc BenchmarkContainsInt8ByWidth(b *testing.B) {\n\trequireAVX512(b)\n\n\tsize := 4096\n\tdata := generateInt8(size)\n\ttarget := int8(42)\n\n\tbenchmarks := []struct {\n\t\tname string\n\t\tfn   func() bool\n\t}{\n\t\t{\"AVX512-x16\", func() bool { return ContainsInt8x16(data, target) }},\n\t\t{\"AVX512-x32\", func() bool { return ContainsInt8x32(data, target) }},\n\t\t{\"AVX512-x64\", func() bool { return ContainsInt8x64(data, target) }},\n\t}\n\n\tfor _, bm := range benchmarks {\n\t\tb.Run(bm.name, func(b *testing.B) {\n\t\t\tb.ReportAllocs()\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = bm.fn()\n\t\t\t}\n\t\t})\n\t}\n}\n\n// ============================================================================\n// STEADY STATE BENCHMARK\n// ============================================================================\n\n// This benchmark demonstrates the steady-state performance after warmup\nfunc BenchmarkContainsInt64SteadyState(b *testing.B) {\n\trequireAVX512(b)\n\n\tsize := 8192\n\tdata := generateInt64(size)\n\ttarget := int64(42)\n\n\t// Warmup phase\n\tfor i := 0; i < 1000; i++ {\n\t\tContainsInt64x2(data, target)\n\t\tContainsInt64x4(data, target)\n\t\tContainsInt64x8(data, target)\n\t}\n\n\tb.ResetTimer() // Reset timer to exclude warmup\n\n\tb.Run(\"AVX512-x2\", func(b *testing.B) {\n\t\trequireAVX512(b) // ContainsInt64x2 is in intersect_avx512.go which uses AVX-512\n\t\tb.ReportAllocs()\n\t\tfor i := 0; i < b.N; i++ {\n\t\t\t_ = ContainsInt64x2(data, target)\n\t\t}\n\t})\n\tb.Run(\"AVX512-x4\", func(b *testing.B) {\n\t\trequireAVX512(b) // ContainsInt64x4 is in intersect_avx512.go which uses AVX-512\n\t\tb.ReportAllocs()\n\t\tfor i := 0; i < b.N; i++ {\n\t\t\t_ = ContainsInt64x4(data, target)\n\t\t}\n\t})\n\tb.Run(\"AVX512-x8\", func(b *testing.B) {\n\t\trequireAVX512(b) // ContainsInt64x8 is in intersect_avx512.go which uses AVX-512\n\t\tb.ReportAllocs()\n\t\tfor i := 0; i < b.N; i++ {\n\t\t\t_ = ContainsInt64x8(data, target)\n\t\t}\n\t})\n}\n"
  },
  {
    "path": "exp/simd/math.go",
    "content": "//go:build go1.26 && goexperiment.simd && amd64\n\npackage simd\n\nimport (\n\t\"github.com/samber/lo\"\n)\n\n// SumInt8 sums a slice of int8 using the best available SIMD instruction set.\n// Overflow: The accumulation is performed using int8, which can overflow for large collections.\n// If the sum exceeds the int8 range (-128 to 127), the result will wrap around silently.\n// For collections that may overflow, consider using a wider type or handle overflow detection externally.\nfunc SumInt8[T ~int8](collection []T) T {\n\tswitch currentSimdFeature {\n\tcase simdFeatureAVX512:\n\t\treturn SumInt8x64(collection)\n\tcase simdFeatureAVX2:\n\t\treturn SumInt8x32(collection)\n\tcase simdFeatureAVX:\n\t\treturn SumInt8x16(collection)\n\tdefault:\n\t\treturn lo.Sum(collection)\n\t}\n}\n\n// SumInt16 sums a slice of int16 using the best available SIMD instruction set.\n// Overflow: The accumulation is performed using int16, which can overflow for large collections.\n// If the sum exceeds the int16 range (-32768 to 32767), the result will wrap around silently.\n// For collections that may overflow, consider using a wider type or handle overflow detection externally.\nfunc SumInt16[T ~int16](collection []T) T {\n\tswitch currentSimdFeature {\n\tcase simdFeatureAVX512:\n\t\treturn SumInt16x32(collection)\n\tcase simdFeatureAVX2:\n\t\treturn SumInt16x16(collection)\n\tcase simdFeatureAVX:\n\t\treturn SumInt16x8(collection)\n\tdefault:\n\t\treturn lo.Sum(collection)\n\t}\n}\n\n// SumInt32 sums a slice of int32 using the best available SIMD instruction set.\n// Overflow: The accumulation is performed using int32, which can overflow for very large collections.\n// If the sum exceeds the int32 range (-2147483648 to 2147483647), the result will wrap around silently.\n// For collections that may overflow, consider using SumInt64 or handle overflow detection externally.\nfunc SumInt32[T ~int32](collection []T) T {\n\tswitch currentSimdFeature {\n\tcase simdFeatureAVX512:\n\t\treturn SumInt32x16(collection)\n\tcase simdFeatureAVX2:\n\t\treturn SumInt32x8(collection)\n\tcase simdFeatureAVX:\n\t\treturn SumInt32x4(collection)\n\tdefault:\n\t\treturn lo.Sum(collection)\n\t}\n}\n\n// SumInt64 sums a slice of int64 using the best available SIMD instruction set.\n// Overflow: The accumulation is performed using int64, which can overflow for extremely large collections.\n// If the sum exceeds the int64 range, the result will wrap around silently.\n// For collections that may overflow, handle overflow detection externally (e.g., using big.Int).\nfunc SumInt64[T ~int64](collection []T) T {\n\tswitch currentSimdFeature {\n\tcase simdFeatureAVX512:\n\t\treturn SumInt64x8(collection)\n\tcase simdFeatureAVX2:\n\t\treturn SumInt64x4(collection)\n\tcase simdFeatureAVX:\n\t\treturn SumInt64x2(collection)\n\tdefault:\n\t\treturn lo.Sum(collection)\n\t}\n}\n\n// SumUint8 sums a slice of uint8 using the best available SIMD instruction set.\n// Overflow: The accumulation is performed using uint8, which can overflow for large collections.\n// If the sum exceeds the uint8 range (0 to 255), the result will wrap around silently.\n// For collections that may overflow, consider using a wider type or handle overflow detection externally.\nfunc SumUint8[T ~uint8](collection []T) T {\n\tswitch currentSimdFeature {\n\tcase simdFeatureAVX512:\n\t\treturn SumUint8x64(collection)\n\tcase simdFeatureAVX2:\n\t\treturn SumUint8x32(collection)\n\tcase simdFeatureAVX:\n\t\treturn SumUint8x16(collection)\n\tdefault:\n\t\treturn lo.Sum(collection)\n\t}\n}\n\n// SumUint16 sums a slice of uint16 using the best available SIMD instruction set.\n// Overflow: The accumulation is performed using uint16, which can overflow for large collections.\n// If the sum exceeds the uint16 range (0 to 65535), the result will wrap around silently.\n// For collections that may overflow, consider using a wider type or handle overflow detection externally.\nfunc SumUint16[T ~uint16](collection []T) T {\n\tswitch currentSimdFeature {\n\tcase simdFeatureAVX512:\n\t\treturn SumUint16x32(collection)\n\tcase simdFeatureAVX2:\n\t\treturn SumUint16x16(collection)\n\tcase simdFeatureAVX:\n\t\treturn SumUint16x8(collection)\n\tdefault:\n\t\treturn lo.Sum(collection)\n\t}\n}\n\n// SumUint32 sums a slice of uint32 using the best available SIMD instruction set.\n// Overflow: The accumulation is performed using uint32, which can overflow for very large collections.\n// If the sum exceeds the uint32 range (0 to 4294967295), the result will wrap around silently.\n// For collections that may overflow, consider using SumUint64 or handle overflow detection externally.\nfunc SumUint32[T ~uint32](collection []T) T {\n\tswitch currentSimdFeature {\n\tcase simdFeatureAVX512:\n\t\treturn SumUint32x16(collection)\n\tcase simdFeatureAVX2:\n\t\treturn SumUint32x8(collection)\n\tcase simdFeatureAVX:\n\t\treturn SumUint32x4(collection)\n\tdefault:\n\t\treturn lo.Sum(collection)\n\t}\n}\n\n// SumUint64 sums a slice of uint64 using the best available SIMD instruction set.\n// Overflow: The accumulation is performed using uint64, which can overflow for extremely large collections.\n// If the sum exceeds the uint64 range, the result will wrap around silently.\n// For collections that may overflow, handle overflow detection externally (e.g., using big.Int).\nfunc SumUint64[T ~uint64](collection []T) T {\n\tswitch currentSimdFeature {\n\tcase simdFeatureAVX512:\n\t\treturn SumUint64x8(collection)\n\tcase simdFeatureAVX2:\n\t\treturn SumUint64x4(collection)\n\tcase simdFeatureAVX:\n\t\treturn SumUint64x2(collection)\n\tdefault:\n\t\treturn lo.Sum(collection)\n\t}\n}\n\n// SumFloat32 sums a slice of float32 using the best available SIMD instruction set.\n// Overflow: The accumulation is performed using float32. Overflow will result in +/-Inf rather than wrapping.\n// For collections requiring high precision or large sums, consider using SumFloat64.\nfunc SumFloat32[T ~float32](collection []T) T {\n\tswitch currentSimdFeature {\n\tcase simdFeatureAVX512:\n\t\treturn SumFloat32x16(collection)\n\tcase simdFeatureAVX2:\n\t\treturn SumFloat32x8(collection)\n\tcase simdFeatureAVX:\n\t\treturn SumFloat32x4(collection)\n\tdefault:\n\t\treturn lo.Sum(collection)\n\t}\n}\n\n// SumFloat64 sums a slice of float64 using the best available SIMD instruction set.\n// Overflow: The accumulation is performed using float64. Overflow will result in +/-Inf rather than wrapping.\n// For collections that may overflow, handle overflow detection externally (e.g., using big.Float).\nfunc SumFloat64[T ~float64](collection []T) T {\n\tswitch currentSimdFeature {\n\tcase simdFeatureAVX512:\n\t\treturn SumFloat64x8(collection)\n\tcase simdFeatureAVX2:\n\t\treturn SumFloat64x4(collection)\n\tcase simdFeatureAVX:\n\t\treturn SumFloat64x2(collection)\n\tdefault:\n\t\treturn lo.Sum(collection)\n\t}\n}\n\n// MeanInt8 calculates the mean of a slice of int8 using the best available SIMD instruction set.\nfunc MeanInt8[T ~int8](collection []T) T {\n\tswitch currentSimdFeature {\n\tcase simdFeatureAVX512:\n\t\treturn MeanInt8x64(collection)\n\tcase simdFeatureAVX2:\n\t\treturn MeanInt8x32(collection)\n\tcase simdFeatureAVX:\n\t\treturn MeanInt8x16(collection)\n\tdefault:\n\t\treturn lo.Mean(collection)\n\t}\n}\n\n// MeanInt16 calculates the mean of a slice of int16 using the best available SIMD instruction set.\nfunc MeanInt16[T ~int16](collection []T) T {\n\tswitch currentSimdFeature {\n\tcase simdFeatureAVX512:\n\t\treturn MeanInt16x32(collection)\n\tcase simdFeatureAVX2:\n\t\treturn MeanInt16x16(collection)\n\tcase simdFeatureAVX:\n\t\treturn MeanInt16x8(collection)\n\tdefault:\n\t\treturn lo.Mean(collection)\n\t}\n}\n\n// MeanInt32 calculates the mean of a slice of int32 using the best available SIMD instruction set.\nfunc MeanInt32[T ~int32](collection []T) T {\n\tswitch currentSimdFeature {\n\tcase simdFeatureAVX512:\n\t\treturn MeanInt32x16(collection)\n\tcase simdFeatureAVX2:\n\t\treturn MeanInt32x8(collection)\n\tcase simdFeatureAVX:\n\t\treturn MeanInt32x4(collection)\n\tdefault:\n\t\treturn lo.Mean(collection)\n\t}\n}\n\n// MeanInt64 calculates the mean of a slice of int64 using the best available SIMD instruction set.\nfunc MeanInt64[T ~int64](collection []T) T {\n\tswitch currentSimdFeature {\n\tcase simdFeatureAVX512:\n\t\treturn MeanInt64x8(collection)\n\tcase simdFeatureAVX2:\n\t\treturn MeanInt64x4(collection)\n\tcase simdFeatureAVX:\n\t\treturn MeanInt64x2(collection)\n\tdefault:\n\t\treturn lo.Mean(collection)\n\t}\n}\n\n// MeanUint8 calculates the mean of a slice of uint8 using the best available SIMD instruction set.\nfunc MeanUint8[T ~uint8](collection []T) T {\n\tswitch currentSimdFeature {\n\tcase simdFeatureAVX512:\n\t\treturn MeanUint8x64(collection)\n\tcase simdFeatureAVX2:\n\t\treturn MeanUint8x32(collection)\n\tcase simdFeatureAVX:\n\t\treturn MeanUint8x16(collection)\n\tdefault:\n\t\treturn lo.Mean(collection)\n\t}\n}\n\n// MeanUint16 calculates the mean of a slice of uint16 using the best available SIMD instruction set.\nfunc MeanUint16[T ~uint16](collection []T) T {\n\tswitch currentSimdFeature {\n\tcase simdFeatureAVX512:\n\t\treturn MeanUint16x32(collection)\n\tcase simdFeatureAVX2:\n\t\treturn MeanUint16x16(collection)\n\tcase simdFeatureAVX:\n\t\treturn MeanUint16x8(collection)\n\tdefault:\n\t\treturn lo.Mean(collection)\n\t}\n}\n\n// MeanUint32 calculates the mean of a slice of uint32 using the best available SIMD instruction set.\nfunc MeanUint32[T ~uint32](collection []T) T {\n\tswitch currentSimdFeature {\n\tcase simdFeatureAVX512:\n\t\treturn MeanUint32x16(collection)\n\tcase simdFeatureAVX2:\n\t\treturn MeanUint32x8(collection)\n\tcase simdFeatureAVX:\n\t\treturn MeanUint32x4(collection)\n\tdefault:\n\t\treturn lo.Mean(collection)\n\t}\n}\n\n// MeanUint64 calculates the mean of a slice of uint64 using the best available SIMD instruction set.\nfunc MeanUint64[T ~uint64](collection []T) T {\n\tswitch currentSimdFeature {\n\tcase simdFeatureAVX512:\n\t\treturn MeanUint64x8(collection)\n\tcase simdFeatureAVX2:\n\t\treturn MeanUint64x4(collection)\n\tcase simdFeatureAVX:\n\t\treturn MeanUint64x2(collection)\n\tdefault:\n\t\treturn lo.Mean(collection)\n\t}\n}\n\n// MeanFloat32 calculates the mean of a slice of float32 using the best available SIMD instruction set.\nfunc MeanFloat32[T ~float32](collection []T) T {\n\tswitch currentSimdFeature {\n\tcase simdFeatureAVX512:\n\t\treturn MeanFloat32x16(collection)\n\tcase simdFeatureAVX2:\n\t\treturn MeanFloat32x8(collection)\n\tcase simdFeatureAVX:\n\t\treturn MeanFloat32x4(collection)\n\tdefault:\n\t\treturn lo.Mean(collection)\n\t}\n}\n\n// MeanFloat64 calculates the mean of a slice of float64 using the best available SIMD instruction set.\nfunc MeanFloat64[T ~float64](collection []T) T {\n\tswitch currentSimdFeature {\n\tcase simdFeatureAVX512:\n\t\treturn MeanFloat64x8(collection)\n\tcase simdFeatureAVX2:\n\t\treturn MeanFloat64x4(collection)\n\tcase simdFeatureAVX:\n\t\treturn MeanFloat64x2(collection)\n\tdefault:\n\t\treturn lo.Mean(collection)\n\t}\n}\n\n// MinInt8 finds the minimum value in a collection of int8 using the best available SIMD instruction set.\nfunc MinInt8[T ~int8](collection []T) T {\n\tswitch currentSimdFeature {\n\tcase simdFeatureAVX512:\n\t\treturn MinInt8x64(collection)\n\tcase simdFeatureAVX2:\n\t\treturn MinInt8x32(collection)\n\tcase simdFeatureAVX:\n\t\treturn MinInt8x16(collection)\n\tdefault:\n\t\treturn lo.Min(collection)\n\t}\n}\n\n// MinInt16 finds the minimum value in a collection of int16 using the best available SIMD instruction set.\nfunc MinInt16[T ~int16](collection []T) T {\n\tswitch currentSimdFeature {\n\tcase simdFeatureAVX512:\n\t\treturn MinInt16x32(collection)\n\tcase simdFeatureAVX2:\n\t\treturn MinInt16x16(collection)\n\tcase simdFeatureAVX:\n\t\treturn MinInt16x8(collection)\n\tdefault:\n\t\treturn lo.Min(collection)\n\t}\n}\n\n// MinInt32 finds the minimum value in a collection of int32 using the best available SIMD instruction set.\nfunc MinInt32[T ~int32](collection []T) T {\n\tswitch currentSimdFeature {\n\tcase simdFeatureAVX512:\n\t\treturn MinInt32x16(collection)\n\tcase simdFeatureAVX2:\n\t\treturn MinInt32x8(collection)\n\tcase simdFeatureAVX:\n\t\treturn MinInt32x4(collection)\n\tdefault:\n\t\treturn lo.Min(collection)\n\t}\n}\n\n// MinInt64 finds the minimum value in a collection of int64 using the best available SIMD instruction set.\nfunc MinInt64[T ~int64](collection []T) T {\n\tswitch currentSimdFeature {\n\tcase simdFeatureAVX512:\n\t\treturn MinInt64x8(collection)\n\tcase simdFeatureAVX2:\n\t\treturn MinInt64x4(collection)\n\tcase simdFeatureAVX:\n\t\t// MinInt64x2 requires AVX-512 (archsimd Int64x2.Min); use scalar fallback\n\t\tfallthrough\n\tdefault:\n\t\treturn lo.Min(collection)\n\t}\n}\n\n// MinUint8 finds the minimum value in a collection of uint8 using the best available SIMD instruction set.\nfunc MinUint8[T ~uint8](collection []T) T {\n\tswitch currentSimdFeature {\n\tcase simdFeatureAVX512:\n\t\treturn MinUint8x64(collection)\n\tcase simdFeatureAVX2:\n\t\treturn MinUint8x32(collection)\n\tcase simdFeatureAVX:\n\t\treturn MinUint8x16(collection)\n\tdefault:\n\t\treturn lo.Min(collection)\n\t}\n}\n\n// MinUint16 finds the minimum value in a collection of uint16 using the best available SIMD instruction set.\nfunc MinUint16[T ~uint16](collection []T) T {\n\tswitch currentSimdFeature {\n\tcase simdFeatureAVX512:\n\t\treturn MinUint16x32(collection)\n\tcase simdFeatureAVX2:\n\t\treturn MinUint16x16(collection)\n\tcase simdFeatureAVX:\n\t\treturn MinUint16x8(collection)\n\tdefault:\n\t\treturn lo.Min(collection)\n\t}\n}\n\n// MinUint32 finds the minimum value in a collection of uint32 using the best available SIMD instruction set.\nfunc MinUint32[T ~uint32](collection []T) T {\n\tswitch currentSimdFeature {\n\tcase simdFeatureAVX512:\n\t\treturn MinUint32x16(collection)\n\tcase simdFeatureAVX2:\n\t\treturn MinUint32x8(collection)\n\tcase simdFeatureAVX:\n\t\treturn MinUint32x4(collection)\n\tdefault:\n\t\treturn lo.Min(collection)\n\t}\n}\n\n// MinUint64 finds the minimum value in a collection of uint64 using the best available SIMD instruction set.\nfunc MinUint64[T ~uint64](collection []T) T {\n\tswitch currentSimdFeature {\n\tcase simdFeatureAVX512:\n\t\treturn MinUint64x8(collection)\n\tcase simdFeatureAVX2:\n\t\treturn MinUint64x4(collection)\n\tcase simdFeatureAVX:\n\t\t// MinUint64x2 requires AVX-512; use scalar fallback\n\t\tfallthrough\n\tdefault:\n\t\treturn lo.Min(collection)\n\t}\n}\n\n// MinFloat32 finds the minimum value in a collection of float32 using the best available SIMD instruction set.\nfunc MinFloat32[T ~float32](collection []T) T {\n\tswitch currentSimdFeature {\n\tcase simdFeatureAVX512:\n\t\treturn MinFloat32x16(collection)\n\tcase simdFeatureAVX2:\n\t\treturn MinFloat32x8(collection)\n\tcase simdFeatureAVX:\n\t\treturn MinFloat32x4(collection)\n\tdefault:\n\t\treturn lo.Min(collection)\n\t}\n}\n\n// MinFloat64 finds the minimum value in a collection of float64 using the best available SIMD instruction set.\nfunc MinFloat64[T ~float64](collection []T) T {\n\tswitch currentSimdFeature {\n\tcase simdFeatureAVX512:\n\t\treturn MinFloat64x8(collection)\n\tcase simdFeatureAVX2:\n\t\treturn MinFloat64x4(collection)\n\tcase simdFeatureAVX:\n\t\treturn MinFloat64x2(collection)\n\tdefault:\n\t\treturn lo.Min(collection)\n\t}\n}\n\n// MaxInt8 finds the maximum value in a collection of int8 using the best available SIMD instruction set.\nfunc MaxInt8[T ~int8](collection []T) T {\n\tswitch currentSimdFeature {\n\tcase simdFeatureAVX512:\n\t\treturn MaxInt8x64(collection)\n\tcase simdFeatureAVX2:\n\t\treturn MaxInt8x32(collection)\n\tcase simdFeatureAVX:\n\t\treturn MaxInt8x16(collection)\n\tdefault:\n\t\treturn lo.Max(collection)\n\t}\n}\n\n// MaxInt16 finds the maximum value in a collection of int16 using the best available SIMD instruction set.\nfunc MaxInt16[T ~int16](collection []T) T {\n\tswitch currentSimdFeature {\n\tcase simdFeatureAVX512:\n\t\treturn MaxInt16x32(collection)\n\tcase simdFeatureAVX2:\n\t\treturn MaxInt16x16(collection)\n\tcase simdFeatureAVX:\n\t\treturn MaxInt16x8(collection)\n\tdefault:\n\t\treturn lo.Max(collection)\n\t}\n}\n\n// MaxInt32 finds the maximum value in a collection of int32 using the best available SIMD instruction set.\nfunc MaxInt32[T ~int32](collection []T) T {\n\tswitch currentSimdFeature {\n\tcase simdFeatureAVX512:\n\t\treturn MaxInt32x16(collection)\n\tcase simdFeatureAVX2:\n\t\treturn MaxInt32x8(collection)\n\tcase simdFeatureAVX:\n\t\treturn MaxInt32x4(collection)\n\tdefault:\n\t\treturn lo.Max(collection)\n\t}\n}\n\n// MaxInt64 finds the maximum value in a collection of int64 using the best available SIMD instruction set.\nfunc MaxInt64[T ~int64](collection []T) T {\n\tswitch currentSimdFeature {\n\tcase simdFeatureAVX512:\n\t\treturn MaxInt64x8(collection)\n\tcase simdFeatureAVX2:\n\t\treturn MaxInt64x4(collection)\n\tcase simdFeatureAVX:\n\t\t// MaxInt64x2 requires AVX-512; use scalar fallback\n\t\tfallthrough\n\tdefault:\n\t\treturn lo.Max(collection)\n\t}\n}\n\n// MaxUint8 finds the maximum value in a collection of uint8 using the best available SIMD instruction set.\nfunc MaxUint8[T ~uint8](collection []T) T {\n\tswitch currentSimdFeature {\n\tcase simdFeatureAVX512:\n\t\treturn MaxUint8x64(collection)\n\tcase simdFeatureAVX2:\n\t\treturn MaxUint8x32(collection)\n\tcase simdFeatureAVX:\n\t\treturn MaxUint8x16(collection)\n\tdefault:\n\t\treturn lo.Max(collection)\n\t}\n}\n\n// MaxUint16 finds the maximum value in a collection of uint16 using the best available SIMD instruction set.\nfunc MaxUint16[T ~uint16](collection []T) T {\n\tswitch currentSimdFeature {\n\tcase simdFeatureAVX512:\n\t\treturn MaxUint16x32(collection)\n\tcase simdFeatureAVX2:\n\t\treturn MaxUint16x16(collection)\n\tcase simdFeatureAVX:\n\t\treturn MaxUint16x8(collection)\n\tdefault:\n\t\treturn lo.Max(collection)\n\t}\n}\n\n// MaxUint32 finds the maximum value in a collection of uint32 using the best available SIMD instruction set.\nfunc MaxUint32[T ~uint32](collection []T) T {\n\tswitch currentSimdFeature {\n\tcase simdFeatureAVX512:\n\t\treturn MaxUint32x16(collection)\n\tcase simdFeatureAVX2:\n\t\treturn MaxUint32x8(collection)\n\tcase simdFeatureAVX:\n\t\treturn MaxUint32x4(collection)\n\tdefault:\n\t\treturn lo.Max(collection)\n\t}\n}\n\n// MaxUint64 finds the maximum value in a collection of uint64 using the best available SIMD instruction set.\nfunc MaxUint64[T ~uint64](collection []T) T {\n\tswitch currentSimdFeature {\n\tcase simdFeatureAVX512:\n\t\treturn MaxUint64x8(collection)\n\tcase simdFeatureAVX2:\n\t\treturn MaxUint64x4(collection)\n\tcase simdFeatureAVX:\n\t\t// MaxUint64x2 requires AVX-512; use scalar fallback\n\t\tfallthrough\n\tdefault:\n\t\treturn lo.Max(collection)\n\t}\n}\n\n// MaxFloat32 finds the maximum value in a collection of float32 using the best available SIMD instruction set.\nfunc MaxFloat32[T ~float32](collection []T) T {\n\tswitch currentSimdFeature {\n\tcase simdFeatureAVX512:\n\t\treturn MaxFloat32x16(collection)\n\tcase simdFeatureAVX2:\n\t\treturn MaxFloat32x8(collection)\n\tcase simdFeatureAVX:\n\t\treturn MaxFloat32x4(collection)\n\tdefault:\n\t\treturn lo.Max(collection)\n\t}\n}\n\n// MaxFloat64 finds the maximum value in a collection of float64 using the best available SIMD instruction set.\nfunc MaxFloat64[T ~float64](collection []T) T {\n\tswitch currentSimdFeature {\n\tcase simdFeatureAVX512:\n\t\treturn MaxFloat64x8(collection)\n\tcase simdFeatureAVX2:\n\t\treturn MaxFloat64x4(collection)\n\tcase simdFeatureAVX:\n\t\treturn MaxFloat64x2(collection)\n\tdefault:\n\t\treturn lo.Max(collection)\n\t}\n}\n\n// ClampInt8 clamps each element in collection between min and max values using the best available SIMD instruction set.\nfunc ClampInt8[T ~int8, Slice ~[]T](collection Slice, min, max T) Slice {\n\tswitch currentSimdFeature {\n\tcase simdFeatureAVX512:\n\t\treturn ClampInt8x64(collection, min, max)\n\tcase simdFeatureAVX2:\n\t\treturn ClampInt8x32(collection, min, max)\n\tcase simdFeatureAVX:\n\t\treturn ClampInt8x16(collection, min, max)\n\tdefault:\n\t\tresult := make(Slice, len(collection))\n\t\tfor i, v := range collection {\n\t\t\tif v < min {\n\t\t\t\tresult[i] = min\n\t\t\t} else if v > max {\n\t\t\t\tresult[i] = max\n\t\t\t} else {\n\t\t\t\tresult[i] = v\n\t\t\t}\n\t\t}\n\t\treturn result\n\t}\n}\n\n// ClampInt16 clamps each element in collection between min and max values using the best available SIMD instruction set.\nfunc ClampInt16[T ~int16, Slice ~[]T](collection Slice, min, max T) Slice {\n\tswitch currentSimdFeature {\n\tcase simdFeatureAVX512:\n\t\treturn ClampInt16x32(collection, min, max)\n\tcase simdFeatureAVX2:\n\t\treturn ClampInt16x16(collection, min, max)\n\tcase simdFeatureAVX:\n\t\treturn ClampInt16x8(collection, min, max)\n\tdefault:\n\t\tresult := make(Slice, len(collection))\n\t\tfor i, v := range collection {\n\t\t\tif v < min {\n\t\t\t\tresult[i] = min\n\t\t\t} else if v > max {\n\t\t\t\tresult[i] = max\n\t\t\t} else {\n\t\t\t\tresult[i] = v\n\t\t\t}\n\t\t}\n\t\treturn result\n\t}\n}\n\n// ClampInt32 clamps each element in collection between min and max values using the best available SIMD instruction set.\nfunc ClampInt32[T ~int32, Slice ~[]T](collection Slice, min, max T) Slice {\n\tswitch currentSimdFeature {\n\tcase simdFeatureAVX512:\n\t\treturn ClampInt32x16(collection, min, max)\n\tcase simdFeatureAVX2:\n\t\treturn ClampInt32x8(collection, min, max)\n\tcase simdFeatureAVX:\n\t\treturn ClampInt32x4(collection, min, max)\n\tdefault:\n\t\tresult := make(Slice, len(collection))\n\t\tfor i, v := range collection {\n\t\t\tif v < min {\n\t\t\t\tresult[i] = min\n\t\t\t} else if v > max {\n\t\t\t\tresult[i] = max\n\t\t\t} else {\n\t\t\t\tresult[i] = v\n\t\t\t}\n\t\t}\n\t\treturn result\n\t}\n}\n\n// ClampInt64 clamps each element in collection between min and max values using the best available SIMD instruction set.\nfunc ClampInt64[T ~int64, Slice ~[]T](collection Slice, min, max T) Slice {\n\tswitch currentSimdFeature {\n\tcase simdFeatureAVX512:\n\t\treturn ClampInt64x8(collection, min, max)\n\tcase simdFeatureAVX2:\n\t\treturn ClampInt64x4(collection, min, max)\n\tcase simdFeatureAVX:\n\t\t// ClampInt64x2 requires AVX-512; use scalar fallback\n\t\tfallthrough\n\tdefault:\n\t\tresult := make(Slice, len(collection))\n\t\tfor i, v := range collection {\n\t\t\tif v < min {\n\t\t\t\tresult[i] = min\n\t\t\t} else if v > max {\n\t\t\t\tresult[i] = max\n\t\t\t} else {\n\t\t\t\tresult[i] = v\n\t\t\t}\n\t\t}\n\t\treturn result\n\t}\n}\n\n// ClampUint8 clamps each element in collection between min and max values using the best available SIMD instruction set.\nfunc ClampUint8[T ~uint8, Slice ~[]T](collection Slice, min, max T) Slice {\n\tswitch currentSimdFeature {\n\tcase simdFeatureAVX512:\n\t\treturn ClampUint8x64(collection, min, max)\n\tcase simdFeatureAVX2:\n\t\treturn ClampUint8x32(collection, min, max)\n\tcase simdFeatureAVX:\n\t\treturn ClampUint8x16(collection, min, max)\n\tdefault:\n\t\tresult := make(Slice, len(collection))\n\t\tfor i, v := range collection {\n\t\t\tif v < min {\n\t\t\t\tresult[i] = min\n\t\t\t} else if v > max {\n\t\t\t\tresult[i] = max\n\t\t\t} else {\n\t\t\t\tresult[i] = v\n\t\t\t}\n\t\t}\n\t\treturn result\n\t}\n}\n\n// ClampUint16 clamps each element in collection between min and max values using the best available SIMD instruction set.\nfunc ClampUint16[T ~uint16, Slice ~[]T](collection Slice, min, max T) Slice {\n\tswitch currentSimdFeature {\n\tcase simdFeatureAVX512:\n\t\treturn ClampUint16x32(collection, min, max)\n\tcase simdFeatureAVX2:\n\t\treturn ClampUint16x16(collection, min, max)\n\tcase simdFeatureAVX:\n\t\treturn ClampUint16x8(collection, min, max)\n\tdefault:\n\t\tresult := make(Slice, len(collection))\n\t\tfor i, v := range collection {\n\t\t\tif v < min {\n\t\t\t\tresult[i] = min\n\t\t\t} else if v > max {\n\t\t\t\tresult[i] = max\n\t\t\t} else {\n\t\t\t\tresult[i] = v\n\t\t\t}\n\t\t}\n\t\treturn result\n\t}\n}\n\n// ClampUint32 clamps each element in collection between min and max values using the best available SIMD instruction set.\nfunc ClampUint32[T ~uint32, Slice ~[]T](collection Slice, min, max T) Slice {\n\tswitch currentSimdFeature {\n\tcase simdFeatureAVX512:\n\t\treturn ClampUint32x16(collection, min, max)\n\tcase simdFeatureAVX2:\n\t\treturn ClampUint32x8(collection, min, max)\n\tcase simdFeatureAVX:\n\t\treturn ClampUint32x4(collection, min, max)\n\tdefault:\n\t\tresult := make(Slice, len(collection))\n\t\tfor i, v := range collection {\n\t\t\tif v < min {\n\t\t\t\tresult[i] = min\n\t\t\t} else if v > max {\n\t\t\t\tresult[i] = max\n\t\t\t} else {\n\t\t\t\tresult[i] = v\n\t\t\t}\n\t\t}\n\t\treturn result\n\t}\n}\n\n// ClampUint64 clamps each element in collection between min and max values using the best available SIMD instruction set.\nfunc ClampUint64[T ~uint64, Slice ~[]T](collection Slice, min, max T) Slice {\n\tswitch currentSimdFeature {\n\tcase simdFeatureAVX512:\n\t\treturn ClampUint64x8(collection, min, max)\n\tcase simdFeatureAVX2:\n\t\treturn ClampUint64x4(collection, min, max)\n\tcase simdFeatureAVX:\n\t\t// ClampUint64x2 requires AVX-512; use scalar fallback\n\t\tfallthrough\n\tdefault:\n\t\tresult := make(Slice, len(collection))\n\t\tfor i, v := range collection {\n\t\t\tif v < min {\n\t\t\t\tresult[i] = min\n\t\t\t} else if v > max {\n\t\t\t\tresult[i] = max\n\t\t\t} else {\n\t\t\t\tresult[i] = v\n\t\t\t}\n\t\t}\n\t\treturn result\n\t}\n}\n\n// ClampFloat32 clamps each element in collection between min and max values using the best available SIMD instruction set.\nfunc ClampFloat32[T ~float32, Slice ~[]T](collection Slice, min, max T) Slice {\n\tswitch currentSimdFeature {\n\tcase simdFeatureAVX512:\n\t\treturn ClampFloat32x16(collection, min, max)\n\tcase simdFeatureAVX2:\n\t\treturn ClampFloat32x8(collection, min, max)\n\tcase simdFeatureAVX:\n\t\treturn ClampFloat32x4(collection, min, max)\n\tdefault:\n\t\tresult := make(Slice, len(collection))\n\t\tfor i, v := range collection {\n\t\t\tif v < min {\n\t\t\t\tresult[i] = min\n\t\t\t} else if v > max {\n\t\t\t\tresult[i] = max\n\t\t\t} else {\n\t\t\t\tresult[i] = v\n\t\t\t}\n\t\t}\n\t\treturn result\n\t}\n}\n\n// ClampFloat64 clamps each element in collection between min and max values using the best available SIMD instruction set.\nfunc ClampFloat64[T ~float64, Slice ~[]T](collection Slice, min, max T) Slice {\n\tswitch currentSimdFeature {\n\tcase simdFeatureAVX512:\n\t\treturn ClampFloat64x8(collection, min, max)\n\tcase simdFeatureAVX2:\n\t\treturn ClampFloat64x4(collection, min, max)\n\tcase simdFeatureAVX:\n\t\treturn ClampFloat64x2(collection, min, max)\n\tdefault:\n\t\tresult := make(Slice, len(collection))\n\t\tfor i, v := range collection {\n\t\t\tif v < min {\n\t\t\t\tresult[i] = min\n\t\t\t} else if v > max {\n\t\t\t\tresult[i] = max\n\t\t\t} else {\n\t\t\t\tresult[i] = v\n\t\t\t}\n\t\t}\n\t\treturn result\n\t}\n}\n\n// SumByInt8 sums the values extracted by iteratee from a slice using the best available SIMD instruction set.\n// Overflow: The accumulation is performed using int8, which can overflow for large collections.\n// If the sum exceeds the int8 range (-128 to 127), the result will wrap around silently.\n// For collections that may overflow, consider using a wider type or handle overflow detection externally.\n// Play: https://go.dev/play/p/TBD\nfunc SumByInt8[T any, R ~int8](collection []T, iteratee func(item T) R) R {\n\tswitch currentSimdFeature {\n\tcase simdFeatureAVX512:\n\t\treturn SumByInt8x64(collection, iteratee)\n\tcase simdFeatureAVX2:\n\t\treturn SumByInt8x32(collection, iteratee)\n\tcase simdFeatureAVX:\n\t\treturn SumByInt8x16(collection, iteratee)\n\tdefault:\n\t\treturn lo.SumBy(collection, iteratee)\n\t}\n}\n\n// SumByInt16 sums the values extracted by iteratee from a slice using the best available SIMD instruction set.\n// Overflow: The accumulation is performed using int16, which can overflow for large collections.\n// If the sum exceeds the int16 range (-32768 to 32767), the result will wrap around silently.\n// For collections that may overflow, consider using a wider type or handle overflow detection externally.\n// Play: https://go.dev/play/p/TBD\nfunc SumByInt16[T any, R ~int16](collection []T, iteratee func(item T) R) R {\n\tswitch currentSimdFeature {\n\tcase simdFeatureAVX512:\n\t\treturn SumByInt16x32(collection, iteratee)\n\tcase simdFeatureAVX2:\n\t\treturn SumByInt16x16(collection, iteratee)\n\tcase simdFeatureAVX:\n\t\treturn SumByInt16x8(collection, iteratee)\n\tdefault:\n\t\treturn lo.SumBy(collection, iteratee)\n\t}\n}\n\n// SumByInt32 sums the values extracted by iteratee from a slice using the best available SIMD instruction set.\n// Overflow: The accumulation is performed using int32, which can overflow for very large collections.\n// If the sum exceeds the int32 range (-2147483648 to 2147483647), the result will wrap around silently.\n// For collections that may overflow, consider using SumByInt64 or handle overflow detection externally.\n// Play: https://go.dev/play/p/TBD\nfunc SumByInt32[T any, R ~int32](collection []T, iteratee func(item T) R) R {\n\tswitch currentSimdFeature {\n\tcase simdFeatureAVX512:\n\t\treturn SumByInt32x16(collection, iteratee)\n\tcase simdFeatureAVX2:\n\t\treturn SumByInt32x8(collection, iteratee)\n\tcase simdFeatureAVX:\n\t\treturn SumByInt32x4(collection, iteratee)\n\tdefault:\n\t\treturn lo.SumBy(collection, iteratee)\n\t}\n}\n\n// SumByInt64 sums the values extracted by iteratee from a slice using the best available SIMD instruction set.\n// Overflow: The accumulation is performed using int64, which can overflow for extremely large collections.\n// If the sum exceeds the int64 range, the result will wrap around silently.\n// For collections that may overflow, handle overflow detection externally (e.g., using big.Int).\n// Play: https://go.dev/play/p/TBD\nfunc SumByInt64[T any, R ~int64](collection []T, iteratee func(item T) R) R {\n\tswitch currentSimdFeature {\n\tcase simdFeatureAVX512:\n\t\treturn SumByInt64x8(collection, iteratee)\n\tcase simdFeatureAVX2:\n\t\treturn SumByInt64x4(collection, iteratee)\n\tcase simdFeatureAVX:\n\t\treturn SumByInt64x2(collection, iteratee)\n\tdefault:\n\t\treturn lo.SumBy(collection, iteratee)\n\t}\n}\n\n// SumByUint8 sums the values extracted by iteratee from a slice using the best available SIMD instruction set.\n// Overflow: The accumulation is performed using uint8, which can overflow for large collections.\n// If the sum exceeds the uint8 range (0 to 255), the result will wrap around silently.\n// For collections that may overflow, consider using a wider type or handle overflow detection externally.\n// Play: https://go.dev/play/p/TBD\nfunc SumByUint8[T any, R ~uint8](collection []T, iteratee func(item T) R) R {\n\tswitch currentSimdFeature {\n\tcase simdFeatureAVX512:\n\t\treturn SumByUint8x64(collection, iteratee)\n\tcase simdFeatureAVX2:\n\t\treturn SumByUint8x32(collection, iteratee)\n\tcase simdFeatureAVX:\n\t\treturn SumByUint8x16(collection, iteratee)\n\tdefault:\n\t\treturn lo.SumBy(collection, iteratee)\n\t}\n}\n\n// SumByUint16 sums the values extracted by iteratee from a slice using the best available SIMD instruction set.\n// Overflow: The accumulation is performed using uint16, which can overflow for large collections.\n// If the sum exceeds the uint16 range (0 to 65535), the result will wrap around silently.\n// For collections that may overflow, consider using a wider type or handle overflow detection externally.\n// Play: https://go.dev/play/p/TBD\nfunc SumByUint16[T any, R ~uint16](collection []T, iteratee func(item T) R) R {\n\tswitch currentSimdFeature {\n\tcase simdFeatureAVX512:\n\t\treturn SumByUint16x32(collection, iteratee)\n\tcase simdFeatureAVX2:\n\t\treturn SumByUint16x16(collection, iteratee)\n\tcase simdFeatureAVX:\n\t\treturn SumByUint16x8(collection, iteratee)\n\tdefault:\n\t\treturn lo.SumBy(collection, iteratee)\n\t}\n}\n\n// SumByUint32 sums the values extracted by iteratee from a slice using the best available SIMD instruction set.\n// Overflow: The accumulation is performed using uint32, which can overflow for very large collections.\n// If the sum exceeds the uint32 range (0 to 4294967295), the result will wrap around silently.\n// For collections that may overflow, consider using SumByUint64 or handle overflow detection externally.\n// Play: https://go.dev/play/p/TBD\nfunc SumByUint32[T any, R ~uint32](collection []T, iteratee func(item T) R) R {\n\tswitch currentSimdFeature {\n\tcase simdFeatureAVX512:\n\t\treturn SumByUint32x16(collection, iteratee)\n\tcase simdFeatureAVX2:\n\t\treturn SumByUint32x8(collection, iteratee)\n\tcase simdFeatureAVX:\n\t\treturn SumByUint32x4(collection, iteratee)\n\tdefault:\n\t\treturn lo.SumBy(collection, iteratee)\n\t}\n}\n\n// SumByUint64 sums the values extracted by iteratee from a slice using the best available SIMD instruction set.\n// Overflow: The accumulation is performed using uint64, which can overflow for extremely large collections.\n// If the sum exceeds the uint64 range, the result will wrap around silently.\n// For collections that may overflow, handle overflow detection externally (e.g., using big.Int).\n// Play: https://go.dev/play/p/TBD\nfunc SumByUint64[T any, R ~uint64](collection []T, iteratee func(item T) R) R {\n\tswitch currentSimdFeature {\n\tcase simdFeatureAVX512:\n\t\treturn SumByUint64x8(collection, iteratee)\n\tcase simdFeatureAVX2:\n\t\treturn SumByUint64x4(collection, iteratee)\n\tcase simdFeatureAVX:\n\t\treturn SumByUint64x2(collection, iteratee)\n\tdefault:\n\t\treturn lo.SumBy(collection, iteratee)\n\t}\n}\n\n// SumByFloat32 sums the values extracted by iteratee from a slice using the best available SIMD instruction set.\n// Overflow: The accumulation is performed using float32. Overflow will result in +/-Inf rather than wrapping.\n// For collections requiring high precision or large sums, consider using SumByFloat64.\n// Play: https://go.dev/play/p/TBD\nfunc SumByFloat32[T any, R ~float32](collection []T, iteratee func(item T) R) R {\n\tswitch currentSimdFeature {\n\tcase simdFeatureAVX512:\n\t\treturn SumByFloat32x16(collection, iteratee)\n\tcase simdFeatureAVX2:\n\t\treturn SumByFloat32x8(collection, iteratee)\n\tcase simdFeatureAVX:\n\t\treturn SumByFloat32x4(collection, iteratee)\n\tdefault:\n\t\treturn lo.SumBy(collection, iteratee)\n\t}\n}\n\n// SumByFloat64 sums the values extracted by iteratee from a slice using the best available SIMD instruction set.\n// Overflow: The accumulation is performed using float64. Overflow will result in +/-Inf rather than wrapping.\n// For collections that may overflow, handle overflow detection externally (e.g., using big.Float).\n// Play: https://go.dev/play/p/TBD\nfunc SumByFloat64[T any, R ~float64](collection []T, iteratee func(item T) R) R {\n\tswitch currentSimdFeature {\n\tcase simdFeatureAVX512:\n\t\treturn SumByFloat64x8(collection, iteratee)\n\tcase simdFeatureAVX2:\n\t\treturn SumByFloat64x4(collection, iteratee)\n\tcase simdFeatureAVX:\n\t\treturn SumByFloat64x2(collection, iteratee)\n\tdefault:\n\t\treturn lo.SumBy(collection, iteratee)\n\t}\n}\n\n// MeanByInt8 calculates the mean of values extracted by iteratee from a slice using the best available SIMD instruction set.\n// Play: https://go.dev/play/p/TBD\nfunc MeanByInt8[T any, R ~int8](collection []T, iteratee func(item T) R) R {\n\tswitch currentSimdFeature {\n\tcase simdFeatureAVX512:\n\t\treturn MeanByInt8x64(collection, iteratee)\n\tcase simdFeatureAVX2:\n\t\treturn MeanByInt8x32(collection, iteratee)\n\tcase simdFeatureAVX:\n\t\treturn MeanByInt8x16(collection, iteratee)\n\tdefault:\n\t\treturn lo.MeanBy(collection, iteratee)\n\t}\n}\n\n// MeanByInt16 calculates the mean of values extracted by iteratee from a slice using the best available SIMD instruction set.\n// Play: https://go.dev/play/p/TBD\nfunc MeanByInt16[T any, R ~int16](collection []T, iteratee func(item T) R) R {\n\tswitch currentSimdFeature {\n\tcase simdFeatureAVX512:\n\t\treturn MeanByInt16x32(collection, iteratee)\n\tcase simdFeatureAVX2:\n\t\treturn MeanByInt16x16(collection, iteratee)\n\tcase simdFeatureAVX:\n\t\treturn MeanByInt16x8(collection, iteratee)\n\tdefault:\n\t\treturn lo.MeanBy(collection, iteratee)\n\t}\n}\n\n// MeanByInt32 calculates the mean of values extracted by iteratee from a slice using the best available SIMD instruction set.\n// Play: https://go.dev/play/p/TBD\nfunc MeanByInt32[T any, R ~int32](collection []T, iteratee func(item T) R) R {\n\tswitch currentSimdFeature {\n\tcase simdFeatureAVX512:\n\t\treturn MeanByInt32x16(collection, iteratee)\n\tcase simdFeatureAVX2:\n\t\treturn MeanByInt32x8(collection, iteratee)\n\tcase simdFeatureAVX:\n\t\treturn MeanByInt32x4(collection, iteratee)\n\tdefault:\n\t\treturn lo.MeanBy(collection, iteratee)\n\t}\n}\n\n// MeanByInt64 calculates the mean of values extracted by iteratee from a slice using the best available SIMD instruction set.\n// Play: https://go.dev/play/p/TBD\nfunc MeanByInt64[T any, R ~int64](collection []T, iteratee func(item T) R) R {\n\tswitch currentSimdFeature {\n\tcase simdFeatureAVX512:\n\t\treturn MeanByInt64x8(collection, iteratee)\n\tcase simdFeatureAVX2:\n\t\treturn MeanByInt64x4(collection, iteratee)\n\tcase simdFeatureAVX:\n\t\treturn MeanByInt64x2(collection, iteratee)\n\tdefault:\n\t\treturn lo.MeanBy(collection, iteratee)\n\t}\n}\n\n// MeanByUint8 calculates the mean of values extracted by iteratee from a slice using the best available SIMD instruction set.\n// Play: https://go.dev/play/p/TBD\nfunc MeanByUint8[T any, R ~uint8](collection []T, iteratee func(item T) R) R {\n\tswitch currentSimdFeature {\n\tcase simdFeatureAVX512:\n\t\treturn MeanByUint8x64(collection, iteratee)\n\tcase simdFeatureAVX2:\n\t\treturn MeanByUint8x32(collection, iteratee)\n\tcase simdFeatureAVX:\n\t\treturn MeanByUint8x16(collection, iteratee)\n\tdefault:\n\t\treturn lo.MeanBy(collection, iteratee)\n\t}\n}\n\n// MeanByUint16 calculates the mean of values extracted by iteratee from a slice using the best available SIMD instruction set.\n// Play: https://go.dev/play/p/TBD\nfunc MeanByUint16[T any, R ~uint16](collection []T, iteratee func(item T) R) R {\n\tswitch currentSimdFeature {\n\tcase simdFeatureAVX512:\n\t\treturn MeanByUint16x32(collection, iteratee)\n\tcase simdFeatureAVX2:\n\t\treturn MeanByUint16x16(collection, iteratee)\n\tcase simdFeatureAVX:\n\t\treturn MeanByUint16x8(collection, iteratee)\n\tdefault:\n\t\treturn lo.MeanBy(collection, iteratee)\n\t}\n}\n\n// MeanByUint32 calculates the mean of values extracted by iteratee from a slice using the best available SIMD instruction set.\n// Play: https://go.dev/play/p/TBD\nfunc MeanByUint32[T any, R ~uint32](collection []T, iteratee func(item T) R) R {\n\tswitch currentSimdFeature {\n\tcase simdFeatureAVX512:\n\t\treturn MeanByUint32x16(collection, iteratee)\n\tcase simdFeatureAVX2:\n\t\treturn MeanByUint32x8(collection, iteratee)\n\tcase simdFeatureAVX:\n\t\treturn MeanByUint32x4(collection, iteratee)\n\tdefault:\n\t\treturn lo.MeanBy(collection, iteratee)\n\t}\n}\n\n// MeanByUint64 calculates the mean of values extracted by iteratee from a slice using the best available SIMD instruction set.\n// Play: https://go.dev/play/p/TBD\nfunc MeanByUint64[T any, R ~uint64](collection []T, iteratee func(item T) R) R {\n\tswitch currentSimdFeature {\n\tcase simdFeatureAVX512:\n\t\treturn MeanByUint64x8(collection, iteratee)\n\tcase simdFeatureAVX2:\n\t\treturn MeanByUint64x4(collection, iteratee)\n\tcase simdFeatureAVX:\n\t\treturn MeanByUint64x2(collection, iteratee)\n\tdefault:\n\t\treturn lo.MeanBy(collection, iteratee)\n\t}\n}\n\n// MeanByFloat32 calculates the mean of values extracted by iteratee from a slice using the best available SIMD instruction set.\n// Play: https://go.dev/play/p/TBD\nfunc MeanByFloat32[T any, R ~float32](collection []T, iteratee func(item T) R) R {\n\tswitch currentSimdFeature {\n\tcase simdFeatureAVX512:\n\t\treturn MeanByFloat32x16(collection, iteratee)\n\tcase simdFeatureAVX2:\n\t\treturn MeanByFloat32x8(collection, iteratee)\n\tcase simdFeatureAVX:\n\t\treturn MeanByFloat32x4(collection, iteratee)\n\tdefault:\n\t\treturn lo.MeanBy(collection, iteratee)\n\t}\n}\n\n// MeanByFloat64 calculates the mean of values extracted by iteratee from a slice using the best available SIMD instruction set.\n// Play: https://go.dev/play/p/TBD\nfunc MeanByFloat64[T any, R ~float64](collection []T, iteratee func(item T) R) R {\n\tswitch currentSimdFeature {\n\tcase simdFeatureAVX512:\n\t\treturn MeanByFloat64x8(collection, iteratee)\n\tcase simdFeatureAVX2:\n\t\treturn MeanByFloat64x4(collection, iteratee)\n\tcase simdFeatureAVX:\n\t\treturn MeanByFloat64x2(collection, iteratee)\n\tdefault:\n\t\treturn lo.MeanBy(collection, iteratee)\n\t}\n}\n"
  },
  {
    "path": "exp/simd/math_avx.go",
    "content": "//go:build go1.26 && goexperiment.simd && amd64\n\npackage simd\n\nimport (\n\t\"simd/archsimd\"\n\t\"unsafe\"\n\n\t\"github.com/samber/lo\"\n)\n\n// AVX (128-bit) SIMD sum functions - 16/8/4/2 lanes\n\n// SumInt8x16 sums a slice of int8 using AVX SIMD (Int8x16, 16 lanes).\n// Overflow: The accumulation is performed using int8, which can overflow for large collections.\n// If the sum exceeds the int8 range (-128 to 127), the result will wrap around silently.\n// For collections that may overflow, consider using a wider type or handle overflow detection externally.\nfunc SumInt8x16[T ~int8](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\tconst lanes = simdLanes16\n\n\tbase := unsafeSliceInt8(collection, length)\n\tvar acc archsimd.Int8x16\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadInt8x16Slice(base[i : i+lanes])\n\t\tacc = acc.Add(v)\n\t}\n\n\tvar buf [lanes]int8\n\tacc.Store(&buf)\n\tvar sum T\n\tfor k := uint(0); k < lanes; k++ {\n\t\tsum += T(buf[k])\n\t}\n\n\tfor ; i < length; i++ {\n\t\tsum += collection[i]\n\t}\n\n\treturn sum\n}\n\n// SumInt16x8 sums a slice of int16 using AVX SIMD (Int16x8, 8 lanes).\n// Overflow: The accumulation is performed using int16, which can overflow for large collections.\n// If the sum exceeds the int16 range (-32768 to 32767), the result will wrap around silently.\n// For collections that may overflow, consider using a wider type or handle overflow detection externally.\nfunc SumInt16x8[T ~int16](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\tconst lanes = simdLanes8\n\n\tbase := unsafeSliceInt16(collection, length)\n\tvar acc archsimd.Int16x8\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadInt16x8Slice(base[i : i+lanes])\n\t\tacc = acc.Add(v)\n\t}\n\n\tvar buf [lanes]int16\n\tacc.Store(&buf)\n\tvar sum T\n\tfor k := uint(0); k < lanes; k++ {\n\t\tsum += T(buf[k])\n\t}\n\n\tfor ; i < length; i++ {\n\t\tsum += collection[i]\n\t}\n\n\treturn sum\n}\n\n// SumInt32x4 sums a slice of int32 using AVX SIMD (Int32x4, 4 lanes).\n// Overflow: The accumulation is performed using int32, which can overflow for very large collections.\n// If the sum exceeds the int32 range (-2147483648 to 2147483647), the result will wrap around silently.\n// For collections that may overflow, consider using SumInt64x2 or handle overflow detection externally.\nfunc SumInt32x4[T ~int32](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\tconst lanes = simdLanes4\n\n\tbase := unsafeSliceInt32(collection, length)\n\tvar acc archsimd.Int32x4\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadInt32x4Slice(base[i : i+lanes])\n\t\tacc = acc.Add(v)\n\t}\n\n\tvar buf [lanes]int32\n\tacc.Store(&buf)\n\tvar sum T\n\tfor k := uint(0); k < lanes; k++ {\n\t\tsum += T(buf[k])\n\t}\n\n\tfor ; i < length; i++ {\n\t\tsum += collection[i]\n\t}\n\n\treturn sum\n}\n\n// SumInt64x2 sums a slice of int64 using AVX SIMD (Int64x2, 2 lanes).\n// Overflow: The accumulation is performed using int64, which can overflow for extremely large collections.\n// If the sum exceeds the int64 range, the result will wrap around silently.\n// For collections that may overflow, handle overflow detection externally (e.g., using big.Int).\nfunc SumInt64x2[T ~int64](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\tconst lanes = simdLanes2\n\n\tbase := unsafeSliceInt64(collection, length)\n\tvar acc archsimd.Int64x2\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadInt64x2Slice(base[i : i+lanes])\n\t\tacc = acc.Add(v)\n\t}\n\n\tvar buf [lanes]int64\n\tacc.Store(&buf)\n\tvar sum T\n\tfor k := uint(0); k < lanes; k++ {\n\t\tsum += T(buf[k])\n\t}\n\n\tfor ; i < length; i++ {\n\t\tsum += collection[i]\n\t}\n\n\treturn sum\n}\n\n// SumUint8x16 sums a slice of uint8 using AVX SIMD (Uint8x16, 16 lanes).\n// Overflow: The accumulation is performed using uint8, which can overflow for large collections.\n// If the sum exceeds the uint8 range (0 to 255), the result will wrap around silently.\n// For collections that may overflow, consider using a wider type or handle overflow detection externally.\nfunc SumUint8x16[T ~uint8](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\tconst lanes = simdLanes16\n\n\tbase := unsafeSliceUint8(collection, length)\n\tvar acc archsimd.Uint8x16\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadUint8x16Slice(base[i : i+lanes])\n\t\tacc = acc.Add(v)\n\t}\n\n\tvar buf [lanes]uint8\n\tacc.Store(&buf)\n\tvar sum T\n\tfor k := uint(0); k < lanes; k++ {\n\t\tsum += T(buf[k])\n\t}\n\n\tfor ; i < length; i++ {\n\t\tsum += collection[i]\n\t}\n\n\treturn sum\n}\n\n// SumUint16x8 sums a slice of uint16 using AVX SIMD (Uint16x8, 8 lanes).\n// Overflow: The accumulation is performed using uint16, which can overflow for large collections.\n// If the sum exceeds the uint16 range (0 to 65535), the result will wrap around silently.\n// For collections that may overflow, consider using a wider type or handle overflow detection externally.\nfunc SumUint16x8[T ~uint16](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\tconst lanes = simdLanes8\n\n\tbase := unsafeSliceUint16(collection, length)\n\tvar acc archsimd.Uint16x8\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadUint16x8Slice(base[i : i+lanes])\n\t\tacc = acc.Add(v)\n\t}\n\n\tvar buf [lanes]uint16\n\tacc.Store(&buf)\n\tvar sum T\n\tfor k := uint(0); k < lanes; k++ {\n\t\tsum += T(buf[k])\n\t}\n\n\tfor ; i < length; i++ {\n\t\tsum += collection[i]\n\t}\n\n\treturn sum\n}\n\n// SumUint32x4 sums a slice of uint32 using AVX SIMD (Uint32x4, 4 lanes).\n// Overflow: The accumulation is performed using uint32, which can overflow for very large collections.\n// If the sum exceeds the uint32 range (0 to 4294967295), the result will wrap around silently.\n// For collections that may overflow, consider using SumUint64x2 or handle overflow detection externally.\nfunc SumUint32x4[T ~uint32](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\tconst lanes = simdLanes4\n\n\tbase := unsafeSliceUint32(collection, length)\n\tvar acc archsimd.Uint32x4\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadUint32x4Slice(base[i : i+lanes])\n\t\tacc = acc.Add(v)\n\t}\n\n\tvar buf [lanes]uint32\n\tacc.Store(&buf)\n\tvar sum T\n\tfor k := uint(0); k < lanes; k++ {\n\t\tsum += T(buf[k])\n\t}\n\n\tfor ; i < length; i++ {\n\t\tsum += collection[i]\n\t}\n\n\treturn sum\n}\n\n// SumUint64x2 sums a slice of uint64 using AVX SIMD (Uint64x2, 2 lanes).\n// Overflow: The accumulation is performed using uint64, which can overflow for extremely large collections.\n// If the sum exceeds the uint64 range, the result will wrap around silently.\n// For collections that may overflow, handle overflow detection externally (e.g., using big.Int).\nfunc SumUint64x2[T ~uint64](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\tconst lanes = simdLanes2\n\n\tbase := unsafeSliceUint64(collection, length)\n\tvar acc archsimd.Uint64x2\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadUint64x2Slice(base[i : i+lanes])\n\t\tacc = acc.Add(v)\n\t}\n\n\tvar buf [lanes]uint64\n\tacc.Store(&buf)\n\tvar sum T\n\tfor k := uint(0); k < lanes; k++ {\n\t\tsum += T(buf[k])\n\t}\n\n\tfor ; i < length; i++ {\n\t\tsum += collection[i]\n\t}\n\n\treturn sum\n}\n\n// SumFloat32x4 sums a slice of float32 using AVX SIMD (Float32x4, 4 lanes).\n// Overflow: The accumulation is performed using float32. Overflow will result in +/-Inf rather than wrapping.\n// For collections requiring high precision or large sums, consider using SumFloat64x2.\nfunc SumFloat32x4[T ~float32](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\tconst lanes = simdLanes4\n\n\tbase := unsafeSliceFloat32(collection, length)\n\tvar acc archsimd.Float32x4\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadFloat32x4Slice(base[i : i+lanes])\n\t\tacc = acc.Add(v)\n\t}\n\n\tvar buf [lanes]float32\n\tacc.Store(&buf)\n\tvar sum T\n\tfor k := uint(0); k < lanes; k++ {\n\t\tsum += T(buf[k])\n\t}\n\n\tfor ; i < length; i++ {\n\t\tsum += collection[i]\n\t}\n\n\treturn sum\n}\n\n// SumFloat64x2 sums a slice of float64 using AVX SIMD (Float64x2, 2 lanes).\n// Overflow: The accumulation is performed using float64. Overflow will result in +/-Inf rather than wrapping.\n// For collections that may overflow, handle overflow detection externally (e.g., using big.Float).\nfunc SumFloat64x2[T ~float64](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\tconst lanes = simdLanes2\n\n\tbase := unsafeSliceFloat64(collection, length)\n\tvar acc archsimd.Float64x2\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadFloat64x2Slice(base[i : i+lanes])\n\t\tacc = acc.Add(v)\n\t}\n\n\tvar buf [lanes]float64\n\tacc.Store(&buf)\n\tvar sum T\n\tfor k := uint(0); k < lanes; k++ {\n\t\tsum += T(buf[k])\n\t}\n\n\tfor ; i < length; i++ {\n\t\tsum += collection[i]\n\t}\n\n\treturn sum\n}\n\n// MeanInt8x16 calculates the mean of a slice of int8 using AVX SIMD\nfunc MeanInt8x16[T ~int8](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\tsum := SumInt8x16(collection)\n\treturn sum / T(length)\n}\n\n// MeanInt16x8 calculates the mean of a slice of int16 using AVX SIMD\nfunc MeanInt16x8[T ~int16](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\tsum := SumInt16x8(collection)\n\treturn sum / T(length)\n}\n\n// MeanInt32x4 calculates the mean of a slice of int32 using AVX SIMD\nfunc MeanInt32x4[T ~int32](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\tsum := SumInt32x4(collection)\n\treturn sum / T(length)\n}\n\n// MeanInt64x2 calculates the mean of a slice of int64 using AVX SIMD\nfunc MeanInt64x2[T ~int64](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\tsum := SumInt64x2(collection)\n\treturn sum / T(length)\n}\n\n// MeanUint8x16 calculates the mean of a slice of uint8 using AVX SIMD\nfunc MeanUint8x16[T ~uint8](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\tsum := SumUint8x16(collection)\n\treturn sum / T(length)\n}\n\n// MeanUint16x8 calculates the mean of a slice of uint16 using AVX SIMD\nfunc MeanUint16x8[T ~uint16](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\tsum := SumUint16x8(collection)\n\treturn sum / T(length)\n}\n\n// MeanUint32x4 calculates the mean of a slice of uint32 using AVX SIMD\nfunc MeanUint32x4[T ~uint32](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\tsum := SumUint32x4(collection)\n\treturn sum / T(length)\n}\n\n// MeanUint64x2 calculates the mean of a slice of uint64 using AVX SIMD\nfunc MeanUint64x2[T ~uint64](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\tsum := SumUint64x2(collection)\n\treturn sum / T(length)\n}\n\n// MeanFloat32x4 calculates the mean of a slice of float32 using AVX SIMD\nfunc MeanFloat32x4[T ~float32](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\tsum := SumFloat32x4(collection)\n\n\treturn sum / T(length)\n}\n\n// MeanFloat64x2 calculates the mean of a slice of float64 using AVX SIMD\nfunc MeanFloat64x2[T ~float64](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\tsum := SumFloat64x2(collection)\n\treturn sum / T(length)\n}\n\n// ClampInt8x16 clamps each element in collection between min and max values using AVX SIMD\nfunc ClampInt8x16[T ~int8, Slice ~[]T](collection Slice, min, max T) Slice {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn collection\n\t}\n\n\tresult := make(Slice, length)\n\tconst lanes = simdLanes16\n\n\tbase := unsafeSliceInt8(collection, length)\n\n\tminVec := archsimd.BroadcastInt8x16(int8(min))\n\tmaxVec := archsimd.BroadcastInt8x16(int8(max))\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadInt8x16Slice(base[i : i+lanes])\n\n\t\tclamped := v.Max(minVec).Min(maxVec)\n\n\t\t// bearer:disable go_gosec_unsafe_unsafe\n\t\tclamped.Store((*[lanes]int8)(unsafe.Pointer(&result[i])))\n\t}\n\n\tfor ; i < length; i++ {\n\t\tval := collection[i]\n\t\tif val < min {\n\t\t\tval = min\n\t\t} else if val > max {\n\t\t\tval = max\n\t\t}\n\t\tresult[i] = val\n\t}\n\n\treturn result\n}\n\n// ClampInt16x8 clamps each element in collection between min and max values using AVX SIMD\nfunc ClampInt16x8[T ~int16, Slice ~[]T](collection Slice, min, max T) Slice {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn collection\n\t}\n\n\tresult := make(Slice, length)\n\tconst lanes = simdLanes8\n\n\tbase := unsafeSliceInt16(collection, length)\n\n\tminVec := archsimd.BroadcastInt16x8(int16(min))\n\tmaxVec := archsimd.BroadcastInt16x8(int16(max))\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadInt16x8Slice(base[i : i+lanes])\n\n\t\tclamped := v.Max(minVec).Min(maxVec)\n\n\t\t// bearer:disable go_gosec_unsafe_unsafe\n\t\tclamped.Store((*[lanes]int16)(unsafe.Pointer(&result[i])))\n\t}\n\n\tfor ; i < length; i++ {\n\t\tval := collection[i]\n\t\tif val < min {\n\t\t\tval = min\n\t\t} else if val > max {\n\t\t\tval = max\n\t\t}\n\t\tresult[i] = val\n\t}\n\n\treturn result\n}\n\n// ClampInt32x4 clamps each element in collection between min and max values using AVX SIMD\nfunc ClampInt32x4[T ~int32, Slice ~[]T](collection Slice, min, max T) Slice {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn collection\n\t}\n\n\tresult := make(Slice, length)\n\tconst lanes = simdLanes4\n\n\tbase := unsafeSliceInt32(collection, length)\n\n\tminVec := archsimd.BroadcastInt32x4(int32(min))\n\tmaxVec := archsimd.BroadcastInt32x4(int32(max))\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadInt32x4Slice(base[i : i+lanes])\n\n\t\tclamped := v.Max(minVec).Min(maxVec)\n\n\t\t// bearer:disable go_gosec_unsafe_unsafe\n\t\tclamped.Store((*[lanes]int32)(unsafe.Pointer(&result[i])))\n\t}\n\n\tfor ; i < length; i++ {\n\t\tval := collection[i]\n\t\tif val < min {\n\t\t\tval = min\n\t\t} else if val > max {\n\t\t\tval = max\n\t\t}\n\t\tresult[i] = val\n\t}\n\n\treturn result\n}\n\n// ClampUint8x16 clamps each element in collection between min and max values using AVX SIMD\nfunc ClampUint8x16[T ~uint8, Slice ~[]T](collection Slice, min, max T) Slice {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn collection\n\t}\n\n\tresult := make(Slice, length)\n\tconst lanes = simdLanes16\n\n\tbase := unsafeSliceUint8(collection, length)\n\n\tminVec := archsimd.BroadcastUint8x16(uint8(min))\n\tmaxVec := archsimd.BroadcastUint8x16(uint8(max))\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadUint8x16Slice(base[i : i+lanes])\n\n\t\tclamped := v.Max(minVec).Min(maxVec)\n\n\t\t// bearer:disable go_gosec_unsafe_unsafe\n\t\tclamped.Store((*[lanes]uint8)(unsafe.Pointer(&result[i])))\n\t}\n\n\tfor ; i < length; i++ {\n\t\tval := collection[i]\n\t\tif val < min {\n\t\t\tval = min\n\t\t} else if val > max {\n\t\t\tval = max\n\t\t}\n\t\tresult[i] = val\n\t}\n\n\treturn result\n}\n\n// ClampUint16x8 clamps each element in collection between min and max values using AVX SIMD\nfunc ClampUint16x8[T ~uint16, Slice ~[]T](collection Slice, min, max T) Slice {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn collection\n\t}\n\n\tresult := make(Slice, length)\n\tconst lanes = simdLanes8\n\n\tbase := unsafeSliceUint16(collection, length)\n\n\tminVec := archsimd.BroadcastUint16x8(uint16(min))\n\tmaxVec := archsimd.BroadcastUint16x8(uint16(max))\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadUint16x8Slice(base[i : i+lanes])\n\n\t\tclamped := v.Max(minVec).Min(maxVec)\n\n\t\t// bearer:disable go_gosec_unsafe_unsafe\n\t\tclamped.Store((*[lanes]uint16)(unsafe.Pointer(&result[i])))\n\t}\n\n\tfor ; i < length; i++ {\n\t\tval := collection[i]\n\t\tif val < min {\n\t\t\tval = min\n\t\t} else if val > max {\n\t\t\tval = max\n\t\t}\n\t\tresult[i] = val\n\t}\n\n\treturn result\n}\n\n// ClampUint32x4 clamps each element in collection between min and max values using AVX SIMD\nfunc ClampUint32x4[T ~uint32, Slice ~[]T](collection Slice, min, max T) Slice {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn collection\n\t}\n\n\tresult := make(Slice, length)\n\tconst lanes = simdLanes4\n\n\tbase := unsafeSliceUint32(collection, length)\n\n\tminVec := archsimd.BroadcastUint32x4(uint32(min))\n\tmaxVec := archsimd.BroadcastUint32x4(uint32(max))\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadUint32x4Slice(base[i : i+lanes])\n\n\t\tclamped := v.Max(minVec).Min(maxVec)\n\n\t\t// bearer:disable go_gosec_unsafe_unsafe\n\t\tclamped.Store((*[lanes]uint32)(unsafe.Pointer(&result[i])))\n\t}\n\n\tfor ; i < length; i++ {\n\t\tval := collection[i]\n\t\tif val < min {\n\t\t\tval = min\n\t\t} else if val > max {\n\t\t\tval = max\n\t\t}\n\t\tresult[i] = val\n\t}\n\n\treturn result\n}\n\n// ClampFloat32x4 clamps each element in collection between min and max values using AVX SIMD\nfunc ClampFloat32x4[T ~float32, Slice ~[]T](collection Slice, min, max T) Slice {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn collection\n\t}\n\n\tresult := make(Slice, length)\n\tconst lanes = simdLanes4\n\n\tbase := unsafeSliceFloat32(collection, length)\n\n\tminVec := archsimd.BroadcastFloat32x4(float32(min))\n\tmaxVec := archsimd.BroadcastFloat32x4(float32(max))\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadFloat32x4Slice(base[i : i+lanes])\n\n\t\tclamped := v.Max(minVec).Min(maxVec)\n\n\t\t// bearer:disable go_gosec_unsafe_unsafe\n\t\tclamped.Store((*[lanes]float32)(unsafe.Pointer(&result[i])))\n\t}\n\n\tfor ; i < length; i++ {\n\t\tval := collection[i]\n\t\tif val < min {\n\t\t\tval = min\n\t\t} else if val > max {\n\t\t\tval = max\n\t\t}\n\t\tresult[i] = val\n\t}\n\n\treturn result\n}\n\n// ClampFloat64x2 clamps each element in collection between min and max values using AVX SIMD\nfunc ClampFloat64x2[T ~float64, Slice ~[]T](collection Slice, min, max T) Slice {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn collection\n\t}\n\n\tresult := make(Slice, length)\n\tconst lanes = simdLanes2\n\n\tbase := unsafeSliceFloat64(collection, length)\n\n\tminVec := archsimd.BroadcastFloat64x2(float64(min))\n\tmaxVec := archsimd.BroadcastFloat64x2(float64(max))\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadFloat64x2Slice(base[i : i+lanes])\n\n\t\tclamped := v.Max(minVec).Min(maxVec)\n\n\t\t// bearer:disable go_gosec_unsafe_unsafe\n\t\tclamped.Store((*[lanes]float64)(unsafe.Pointer(&result[i])))\n\t}\n\n\tfor ; i < length; i++ {\n\t\tval := collection[i]\n\t\tif val < min {\n\t\t\tval = min\n\t\t} else if val > max {\n\t\t\tval = max\n\t\t}\n\t\tresult[i] = val\n\t}\n\n\treturn result\n}\n\n// MinInt8x16 finds the minimum value in a collection of int8 using AVX SIMD\nfunc MinInt8x16[T ~int8](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\n\tconst lanes = simdLanes16\n\tbase := unsafeSliceInt8(collection, length)\n\n\tvar minVec archsimd.Int8x16\n\tfirstInitialized := false\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadInt8x16Slice(base[i : i+lanes])\n\n\t\tif !firstInitialized {\n\t\t\tminVec = v\n\t\t\tfirstInitialized = true\n\t\t} else {\n\t\t\tminVec = minVec.Min(v)\n\t\t}\n\t}\n\n\t// Find minimum in the vector (only if we processed any vectors)\n\tvar minVal int8\n\tif firstInitialized {\n\t\tvar buf [lanes]int8\n\t\tminVec.Store(&buf)\n\t\tminVal = min(\n\t\t\tbuf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7],\n\t\t\tbuf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15],\n\t\t)\n\t}\n\n\t// Handle remaining elements\n\tfor ; i < length; i++ {\n\t\tif !firstInitialized || collection[i] < T(minVal) {\n\t\t\tminVal = int8(collection[i])\n\t\t\tfirstInitialized = true\n\t\t}\n\t}\n\n\treturn T(minVal)\n}\n\n// MinInt16x8 finds the minimum value in a collection of int16 using AVX SIMD\nfunc MinInt16x8[T ~int16](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\n\tconst lanes = simdLanes8\n\tbase := unsafeSliceInt16(collection, length)\n\n\tvar minVec archsimd.Int16x8\n\tfirstInitialized := false\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadInt16x8Slice(base[i : i+lanes])\n\n\t\tif !firstInitialized {\n\t\t\tminVec = v\n\t\t\tfirstInitialized = true\n\t\t} else {\n\t\t\tminVec = minVec.Min(v)\n\t\t}\n\t}\n\n\t// Find minimum in the vector (only if we processed any vectors)\n\tvar minVal int16\n\tif firstInitialized {\n\t\tvar buf [lanes]int16\n\t\tminVec.Store(&buf)\n\t\tminVal = min(buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7])\n\t}\n\n\t// Handle remaining elements\n\tfor ; i < length; i++ {\n\t\tif !firstInitialized || collection[i] < T(minVal) {\n\t\t\tminVal = int16(collection[i])\n\t\t\tfirstInitialized = true\n\t\t}\n\t}\n\n\treturn T(minVal)\n}\n\n// MinInt32x4 finds the minimum value in a collection of int32 using AVX SIMD\nfunc MinInt32x4[T ~int32](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\n\tconst lanes = simdLanes4\n\tbase := unsafeSliceInt32(collection, length)\n\n\tvar minVec archsimd.Int32x4\n\tfirstInitialized := false\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadInt32x4Slice(base[i : i+lanes])\n\n\t\tif !firstInitialized {\n\t\t\tminVec = v\n\t\t\tfirstInitialized = true\n\t\t} else {\n\t\t\tminVec = minVec.Min(v)\n\t\t}\n\t}\n\n\t// Find minimum in the vector (only if we processed any vectors)\n\tvar minVal int32\n\tif firstInitialized {\n\t\tvar buf [lanes]int32\n\t\tminVec.Store(&buf)\n\t\tminVal = min(buf[0], buf[1], buf[2], buf[3])\n\t}\n\n\t// Handle remaining elements\n\tfor ; i < length; i++ {\n\t\tif !firstInitialized || collection[i] < T(minVal) {\n\t\t\tminVal = int32(collection[i])\n\t\t\tfirstInitialized = true\n\t\t}\n\t}\n\n\treturn T(minVal)\n}\n\n// MinUint8x16 finds the minimum value in a collection of uint8 using AVX SIMD\nfunc MinUint8x16[T ~uint8](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\n\tconst lanes = simdLanes16\n\tbase := unsafeSliceUint8(collection, length)\n\n\tvar minVec archsimd.Uint8x16\n\tfirstInitialized := false\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadUint8x16Slice(base[i : i+lanes])\n\n\t\tif !firstInitialized {\n\t\t\tminVec = v\n\t\t\tfirstInitialized = true\n\t\t} else {\n\t\t\tminVec = minVec.Min(v)\n\t\t}\n\t}\n\n\t// Find minimum in the vector (only if we processed any vectors)\n\tvar minVal uint8\n\tif firstInitialized {\n\t\tvar buf [lanes]uint8\n\t\tminVec.Store(&buf)\n\t\tminVal = min(\n\t\t\tbuf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7],\n\t\t\tbuf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15],\n\t\t)\n\t}\n\n\t// Handle remaining elements\n\tfor ; i < length; i++ {\n\t\tif !firstInitialized || collection[i] < T(minVal) {\n\t\t\tminVal = uint8(collection[i])\n\t\t\tfirstInitialized = true\n\t\t}\n\t}\n\n\treturn T(minVal)\n}\n\n// MinUint16x8 finds the minimum value in a collection of uint16 using AVX SIMD\nfunc MinUint16x8[T ~uint16](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\n\tconst lanes = simdLanes8\n\tbase := unsafeSliceUint16(collection, length)\n\n\tvar minVec archsimd.Uint16x8\n\tfirstInitialized := false\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadUint16x8Slice(base[i : i+lanes])\n\n\t\tif !firstInitialized {\n\t\t\tminVec = v\n\t\t\tfirstInitialized = true\n\t\t} else {\n\t\t\tminVec = minVec.Min(v)\n\t\t}\n\t}\n\n\t// Find minimum in the vector (only if we processed any vectors)\n\tvar minVal uint16\n\tif firstInitialized {\n\t\tvar buf [lanes]uint16\n\t\tminVec.Store(&buf)\n\t\tminVal = min(buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7])\n\t}\n\n\t// Handle remaining elements\n\tfor ; i < length; i++ {\n\t\tif !firstInitialized || collection[i] < T(minVal) {\n\t\t\tminVal = uint16(collection[i])\n\t\t\tfirstInitialized = true\n\t\t}\n\t}\n\n\treturn T(minVal)\n}\n\n// MinUint32x4 finds the minimum value in a collection of uint32 using AVX SIMD\nfunc MinUint32x4[T ~uint32](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\n\tconst lanes = simdLanes4\n\tbase := unsafeSliceUint32(collection, length)\n\n\tvar minVec archsimd.Uint32x4\n\tfirstInitialized := false\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadUint32x4Slice(base[i : i+lanes])\n\n\t\tif !firstInitialized {\n\t\t\tminVec = v\n\t\t\tfirstInitialized = true\n\t\t} else {\n\t\t\tminVec = minVec.Min(v)\n\t\t}\n\t}\n\n\t// Find minimum in the vector (only if we processed any vectors)\n\tvar minVal uint32\n\tif firstInitialized {\n\t\tvar buf [lanes]uint32\n\t\tminVec.Store(&buf)\n\t\tminVal = min(buf[0], buf[1], buf[2], buf[3])\n\t}\n\n\t// Handle remaining elements\n\tfor ; i < length; i++ {\n\t\tif !firstInitialized || collection[i] < T(minVal) {\n\t\t\tminVal = uint32(collection[i])\n\t\t\tfirstInitialized = true\n\t\t}\n\t}\n\n\treturn T(minVal)\n}\n\n// MinFloat32x4 finds the minimum value in a collection of float32 using AVX SIMD\nfunc MinFloat32x4[T ~float32](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\n\tconst lanes = simdLanes4\n\tbase := unsafeSliceFloat32(collection, length)\n\n\tvar minVec archsimd.Float32x4\n\tfirstInitialized := false\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadFloat32x4Slice(base[i : i+lanes])\n\n\t\tif !firstInitialized {\n\t\t\tminVec = v\n\t\t\tfirstInitialized = true\n\t\t} else {\n\t\t\tminVec = minVec.Min(v)\n\t\t}\n\t}\n\n\t// Find minimum in the vector (only if we processed any vectors)\n\tvar minVal float32\n\tif firstInitialized {\n\t\tvar buf [lanes]float32\n\t\tminVec.Store(&buf)\n\t\tminVal = min(buf[0], buf[1], buf[2], buf[3])\n\t}\n\n\t// Handle remaining elements\n\tfor ; i < length; i++ {\n\t\tif !firstInitialized || collection[i] < T(minVal) {\n\t\t\tminVal = float32(collection[i])\n\t\t\tfirstInitialized = true\n\t\t}\n\t}\n\n\treturn T(minVal)\n}\n\n// MinFloat64x2 finds the minimum value in a collection of float64 using AVX SIMD\nfunc MinFloat64x2[T ~float64](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\n\tconst lanes = simdLanes2\n\tbase := unsafeSliceFloat64(collection, length)\n\n\tvar minVec archsimd.Float64x2\n\tfirstInitialized := false\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadFloat64x2Slice(base[i : i+lanes])\n\n\t\tif !firstInitialized {\n\t\t\tminVec = v\n\t\t\tfirstInitialized = true\n\t\t} else {\n\t\t\tminVec = minVec.Min(v)\n\t\t}\n\t}\n\n\t// Find minimum in the vector (only if we processed any vectors)\n\tvar minVal float64\n\tif firstInitialized {\n\t\tvar buf [lanes]float64\n\t\tminVec.Store(&buf)\n\t\tminVal = min(buf[0], buf[1])\n\t}\n\n\t// Handle remaining elements\n\tfor ; i < length; i++ {\n\t\tif !firstInitialized || collection[i] < T(minVal) {\n\t\t\tminVal = float64(collection[i])\n\t\t\tfirstInitialized = true\n\t\t}\n\t}\n\n\treturn T(minVal)\n}\n\n// MaxInt8x16 finds the maximum value in a collection of int8 using AVX SIMD\nfunc MaxInt8x16[T ~int8](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\n\tconst lanes = simdLanes16\n\tbase := unsafeSliceInt8(collection, length)\n\n\tvar maxVec archsimd.Int8x16\n\tfirstInitialized := false\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadInt8x16Slice(base[i : i+lanes])\n\n\t\tif !firstInitialized {\n\t\t\tmaxVec = v\n\t\t\tfirstInitialized = true\n\t\t} else {\n\t\t\tmaxVec = maxVec.Max(v)\n\t\t}\n\t}\n\n\t// Find maximum in the vector (only if we processed any vectors)\n\tvar maxVal int8\n\tif firstInitialized {\n\t\tvar buf [lanes]int8\n\t\tmaxVec.Store(&buf)\n\t\tmaxVal = max(\n\t\t\tbuf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7],\n\t\t\tbuf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15],\n\t\t)\n\t}\n\n\t// Handle remaining elements\n\tfor ; i < length; i++ {\n\t\tif !firstInitialized || collection[i] > T(maxVal) {\n\t\t\tmaxVal = int8(collection[i])\n\t\t\tfirstInitialized = true\n\t\t}\n\t}\n\n\treturn T(maxVal)\n}\n\n// MaxInt16x8 finds the maximum value in a collection of int16 using AVX SIMD\nfunc MaxInt16x8[T ~int16](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\n\tconst lanes = simdLanes8\n\tbase := unsafeSliceInt16(collection, length)\n\n\tvar maxVec archsimd.Int16x8\n\tfirstInitialized := false\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadInt16x8Slice(base[i : i+lanes])\n\n\t\tif !firstInitialized {\n\t\t\tmaxVec = v\n\t\t\tfirstInitialized = true\n\t\t} else {\n\t\t\tmaxVec = maxVec.Max(v)\n\t\t}\n\t}\n\n\t// Find maximum in the vector (only if we processed any vectors)\n\tvar maxVal int16\n\tif firstInitialized {\n\t\tvar buf [lanes]int16\n\t\tmaxVec.Store(&buf)\n\t\tmaxVal = max(buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7])\n\t}\n\n\t// Handle remaining elements\n\tfor ; i < length; i++ {\n\t\tif !firstInitialized || collection[i] > T(maxVal) {\n\t\t\tmaxVal = int16(collection[i])\n\t\t\tfirstInitialized = true\n\t\t}\n\t}\n\n\treturn T(maxVal)\n}\n\n// MaxInt32x4 finds the maximum value in a collection of int32 using AVX SIMD\nfunc MaxInt32x4[T ~int32](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\n\tconst lanes = simdLanes4\n\tbase := unsafeSliceInt32(collection, length)\n\n\tvar maxVec archsimd.Int32x4\n\tfirstInitialized := false\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadInt32x4Slice(base[i : i+lanes])\n\n\t\tif !firstInitialized {\n\t\t\tmaxVec = v\n\t\t\tfirstInitialized = true\n\t\t} else {\n\t\t\tmaxVec = maxVec.Max(v)\n\t\t}\n\t}\n\n\t// Find maximum in the vector (only if we processed any vectors)\n\tvar maxVal int32\n\tif firstInitialized {\n\t\tvar buf [lanes]int32\n\t\tmaxVec.Store(&buf)\n\t\tmaxVal = max(buf[0], buf[1], buf[2], buf[3])\n\t}\n\n\t// Handle remaining elements\n\tfor ; i < length; i++ {\n\t\tif !firstInitialized || collection[i] > T(maxVal) {\n\t\t\tmaxVal = int32(collection[i])\n\t\t\tfirstInitialized = true\n\t\t}\n\t}\n\n\treturn T(maxVal)\n}\n\n// MaxUint8x16 finds the maximum value in a collection of uint8 using AVX SIMD\nfunc MaxUint8x16[T ~uint8](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\n\tconst lanes = simdLanes16\n\tbase := unsafeSliceUint8(collection, length)\n\n\tvar maxVec archsimd.Uint8x16\n\tfirstInitialized := false\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadUint8x16Slice(base[i : i+lanes])\n\n\t\tif !firstInitialized {\n\t\t\tmaxVec = v\n\t\t\tfirstInitialized = true\n\t\t} else {\n\t\t\tmaxVec = maxVec.Max(v)\n\t\t}\n\t}\n\n\t// Find maximum in the vector (only if we processed any vectors)\n\tvar maxVal uint8\n\tif firstInitialized {\n\t\tvar buf [lanes]uint8\n\t\tmaxVec.Store(&buf)\n\t\tmaxVal = max(\n\t\t\tbuf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7],\n\t\t\tbuf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15],\n\t\t)\n\t}\n\n\t// Handle remaining elements\n\tfor ; i < length; i++ {\n\t\tif !firstInitialized || collection[i] > T(maxVal) {\n\t\t\tmaxVal = uint8(collection[i])\n\t\t\tfirstInitialized = true\n\t\t}\n\t}\n\n\treturn T(maxVal)\n}\n\n// MaxUint16x8 finds the maximum value in a collection of uint16 using AVX SIMD\nfunc MaxUint16x8[T ~uint16](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\n\tconst lanes = simdLanes8\n\tbase := unsafeSliceUint16(collection, length)\n\n\tvar maxVec archsimd.Uint16x8\n\tfirstInitialized := false\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadUint16x8Slice(base[i : i+lanes])\n\n\t\tif !firstInitialized {\n\t\t\tmaxVec = v\n\t\t\tfirstInitialized = true\n\t\t} else {\n\t\t\tmaxVec = maxVec.Max(v)\n\t\t}\n\t}\n\n\t// Find maximum in the vector (only if we processed any vectors)\n\tvar maxVal uint16\n\tif firstInitialized {\n\t\tvar buf [lanes]uint16\n\t\tmaxVec.Store(&buf)\n\t\tmaxVal = max(buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7])\n\t}\n\n\t// Handle remaining elements\n\tfor ; i < length; i++ {\n\t\tif !firstInitialized || collection[i] > T(maxVal) {\n\t\t\tmaxVal = uint16(collection[i])\n\t\t\tfirstInitialized = true\n\t\t}\n\t}\n\n\treturn T(maxVal)\n}\n\n// MaxUint32x4 finds the maximum value in a collection of uint32 using AVX SIMD\nfunc MaxUint32x4[T ~uint32](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\n\tconst lanes = simdLanes4\n\tbase := unsafeSliceUint32(collection, length)\n\n\tvar maxVec archsimd.Uint32x4\n\tfirstInitialized := false\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadUint32x4Slice(base[i : i+lanes])\n\n\t\tif !firstInitialized {\n\t\t\tmaxVec = v\n\t\t\tfirstInitialized = true\n\t\t} else {\n\t\t\tmaxVec = maxVec.Max(v)\n\t\t}\n\t}\n\n\t// Find maximum in the vector (only if we processed any vectors)\n\tvar maxVal uint32\n\tif firstInitialized {\n\t\tvar buf [lanes]uint32\n\t\tmaxVec.Store(&buf)\n\t\tmaxVal = max(buf[0], buf[1], buf[2], buf[3])\n\t}\n\n\t// Handle remaining elements\n\tfor ; i < length; i++ {\n\t\tif !firstInitialized || collection[i] > T(maxVal) {\n\t\t\tmaxVal = uint32(collection[i])\n\t\t\tfirstInitialized = true\n\t\t}\n\t}\n\n\treturn T(maxVal)\n}\n\n// MaxFloat32x4 finds the maximum value in a collection of float32 using AVX SIMD\nfunc MaxFloat32x4[T ~float32](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\n\tconst lanes = simdLanes4\n\tbase := unsafeSliceFloat32(collection, length)\n\n\tvar maxVec archsimd.Float32x4\n\tfirstInitialized := false\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadFloat32x4Slice(base[i : i+lanes])\n\n\t\tif !firstInitialized {\n\t\t\tmaxVec = v\n\t\t\tfirstInitialized = true\n\t\t} else {\n\t\t\tmaxVec = maxVec.Max(v)\n\t\t}\n\t}\n\n\t// Find maximum in the vector (only if we processed any vectors)\n\tvar maxVal float32\n\tif firstInitialized {\n\t\tvar buf [lanes]float32\n\t\tmaxVec.Store(&buf)\n\t\tmaxVal = max(buf[0], buf[1], buf[2], buf[3])\n\t}\n\n\t// Handle remaining elements\n\tfor ; i < length; i++ {\n\t\tif !firstInitialized || collection[i] > T(maxVal) {\n\t\t\tmaxVal = float32(collection[i])\n\t\t\tfirstInitialized = true\n\t\t}\n\t}\n\n\treturn T(maxVal)\n}\n\n// MaxFloat64x2 finds the maximum value in a collection of float64 using AVX SIMD\nfunc MaxFloat64x2[T ~float64](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\n\tconst lanes = simdLanes2\n\tbase := unsafeSliceFloat64(collection, length)\n\n\tvar maxVec archsimd.Float64x2\n\tfirstInitialized := false\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadFloat64x2Slice(base[i : i+lanes])\n\n\t\tif !firstInitialized {\n\t\t\tmaxVec = v\n\t\t\tfirstInitialized = true\n\t\t} else {\n\t\t\tmaxVec = maxVec.Max(v)\n\t\t}\n\t}\n\n\t// Find maximum in the vector (only if we processed any vectors)\n\tvar maxVal float64\n\tif firstInitialized {\n\t\tvar buf [lanes]float64\n\t\tmaxVec.Store(&buf)\n\t\tmaxVal = max(buf[0], buf[1])\n\t}\n\n\t// Handle remaining elements\n\tfor ; i < length; i++ {\n\t\tif !firstInitialized || collection[i] > T(maxVal) {\n\t\t\tmaxVal = float64(collection[i])\n\t\t\tfirstInitialized = true\n\t\t}\n\t}\n\n\treturn T(maxVal)\n}\n\n// AVX (128-bit) SIMD sumBy functions - 16/8/4/2 lanes\n// These implementations use lo.Map to apply the iteratee, then chain with SIMD sum functions.\n\n// SumByInt8x16 sums the values extracted by iteratee from a slice using AVX SIMD.\nfunc SumByInt8x16[T any, R ~int8](collection []T, iteratee func(item T) R) R {\n\tmapped := lo.Map(collection, func(item T, _ int) R { return iteratee(item) })\n\treturn SumInt8x16(mapped)\n}\n\n// SumByInt16x8 sums the values extracted by iteratee from a slice using AVX SIMD.\nfunc SumByInt16x8[T any, R ~int16](collection []T, iteratee func(item T) R) R {\n\tmapped := lo.Map(collection, func(item T, _ int) R { return iteratee(item) })\n\treturn SumInt16x8(mapped)\n}\n\n// SumByInt32x4 sums the values extracted by iteratee from a slice using AVX SIMD.\nfunc SumByInt32x4[T any, R ~int32](collection []T, iteratee func(item T) R) R {\n\tmapped := lo.Map(collection, func(item T, _ int) R { return iteratee(item) })\n\treturn SumInt32x4(mapped)\n}\n\n// SumByInt64x2 sums the values extracted by iteratee from a slice using AVX SIMD.\nfunc SumByInt64x2[T any, R ~int64](collection []T, iteratee func(item T) R) R {\n\tmapped := lo.Map(collection, func(item T, _ int) R { return iteratee(item) })\n\treturn SumInt64x2(mapped)\n}\n\n// SumByUint8x16 sums the values extracted by iteratee from a slice using AVX SIMD.\nfunc SumByUint8x16[T any, R ~uint8](collection []T, iteratee func(item T) R) R {\n\tmapped := lo.Map(collection, func(item T, _ int) R { return iteratee(item) })\n\treturn SumUint8x16(mapped)\n}\n\n// SumByUint16x8 sums the values extracted by iteratee from a slice using AVX SIMD.\nfunc SumByUint16x8[T any, R ~uint16](collection []T, iteratee func(item T) R) R {\n\tmapped := lo.Map(collection, func(item T, _ int) R { return iteratee(item) })\n\treturn SumUint16x8(mapped)\n}\n\n// SumByUint32x4 sums the values extracted by iteratee from a slice using AVX SIMD.\nfunc SumByUint32x4[T any, R ~uint32](collection []T, iteratee func(item T) R) R {\n\tmapped := lo.Map(collection, func(item T, _ int) R { return iteratee(item) })\n\treturn SumUint32x4(mapped)\n}\n\n// SumByUint64x2 sums the values extracted by iteratee from a slice using AVX SIMD.\nfunc SumByUint64x2[T any, R ~uint64](collection []T, iteratee func(item T) R) R {\n\tmapped := lo.Map(collection, func(item T, _ int) R { return iteratee(item) })\n\treturn SumUint64x2(mapped)\n}\n\n// SumByFloat32x4 sums the values extracted by iteratee from a slice using AVX SIMD.\nfunc SumByFloat32x4[T any, R ~float32](collection []T, iteratee func(item T) R) R {\n\tmapped := lo.Map(collection, func(item T, _ int) R { return iteratee(item) })\n\treturn SumFloat32x4(mapped)\n}\n\n// SumByFloat64x2 sums the values extracted by iteratee from a slice using AVX SIMD.\nfunc SumByFloat64x2[T any, R ~float64](collection []T, iteratee func(item T) R) R {\n\tmapped := lo.Map(collection, func(item T, _ int) R { return iteratee(item) })\n\treturn SumFloat64x2(mapped)\n}\n\n// AVX (128-bit) SIMD meanBy functions - 16/8/4/2 lanes\n// These implementations use lo.Map to apply the iteratee, then chain with SIMD mean functions.\n\n// MeanByInt8x16 calculates the mean of values extracted by iteratee from a slice using AVX SIMD.\nfunc MeanByInt8x16[T any, R ~int8](collection []T, iteratee func(item T) R) R {\n\tmapped := lo.Map(collection, func(item T, _ int) R { return iteratee(item) })\n\treturn MeanInt8x16(mapped)\n}\n\n// MeanByInt16x8 calculates the mean of values extracted by iteratee from a slice using AVX SIMD.\nfunc MeanByInt16x8[T any, R ~int16](collection []T, iteratee func(item T) R) R {\n\tmapped := lo.Map(collection, func(item T, _ int) R { return iteratee(item) })\n\treturn MeanInt16x8(mapped)\n}\n\n// MeanByInt32x4 calculates the mean of values extracted by iteratee from a slice using AVX SIMD.\nfunc MeanByInt32x4[T any, R ~int32](collection []T, iteratee func(item T) R) R {\n\tmapped := lo.Map(collection, func(item T, _ int) R { return iteratee(item) })\n\treturn MeanInt32x4(mapped)\n}\n\n// MeanByInt64x2 calculates the mean of values extracted by iteratee from a slice using AVX SIMD.\nfunc MeanByInt64x2[T any, R ~int64](collection []T, iteratee func(item T) R) R {\n\tmapped := lo.Map(collection, func(item T, _ int) R { return iteratee(item) })\n\treturn MeanInt64x2(mapped)\n}\n\n// MeanByUint8x16 calculates the mean of values extracted by iteratee from a slice using AVX SIMD.\nfunc MeanByUint8x16[T any, R ~uint8](collection []T, iteratee func(item T) R) R {\n\tmapped := lo.Map(collection, func(item T, _ int) R { return iteratee(item) })\n\treturn MeanUint8x16(mapped)\n}\n\n// MeanByUint16x8 calculates the mean of values extracted by iteratee from a slice using AVX SIMD.\nfunc MeanByUint16x8[T any, R ~uint16](collection []T, iteratee func(item T) R) R {\n\tmapped := lo.Map(collection, func(item T, _ int) R { return iteratee(item) })\n\treturn MeanUint16x8(mapped)\n}\n\n// MeanByUint32x4 calculates the mean of values extracted by iteratee from a slice using AVX SIMD.\nfunc MeanByUint32x4[T any, R ~uint32](collection []T, iteratee func(item T) R) R {\n\tmapped := lo.Map(collection, func(item T, _ int) R { return iteratee(item) })\n\treturn MeanUint32x4(mapped)\n}\n\n// MeanByUint64x2 calculates the mean of values extracted by iteratee from a slice using AVX SIMD.\nfunc MeanByUint64x2[T any, R ~uint64](collection []T, iteratee func(item T) R) R {\n\tmapped := lo.Map(collection, func(item T, _ int) R { return iteratee(item) })\n\treturn MeanUint64x2(mapped)\n}\n\n// MeanByFloat32x4 calculates the mean of values extracted by iteratee from a slice using AVX SIMD.\nfunc MeanByFloat32x4[T any, R ~float32](collection []T, iteratee func(item T) R) R {\n\tmapped := lo.Map(collection, func(item T, _ int) R { return iteratee(item) })\n\treturn MeanFloat32x4(mapped)\n}\n\n// MeanByFloat64x2 calculates the mean of values extracted by iteratee from a slice using AVX SIMD.\nfunc MeanByFloat64x2[T any, R ~float64](collection []T, iteratee func(item T) R) R {\n\tmapped := lo.Map(collection, func(item T, _ int) R { return iteratee(item) })\n\treturn MeanFloat64x2(mapped)\n}\n"
  },
  {
    "path": "exp/simd/math_avx2.go",
    "content": "//go:build go1.26 && goexperiment.simd && amd64\n\npackage simd\n\nimport (\n\t\"simd/archsimd\"\n\t\"unsafe\"\n\n\t\"github.com/samber/lo\"\n)\n\n// AVX2 (256-bit) SIMD sum functions - 32/16/8/4 lanes\n\n// SumInt8x32 sums a slice of int8 using AVX2 SIMD (Int8x32, 32 lanes).\n// Overflow: The accumulation is performed using int8, which can overflow for large collections.\n// If the sum exceeds the int8 range (-128 to 127), the result will wrap around silently.\n// For collections that may overflow, consider using a wider type or handle overflow detection externally.\nfunc SumInt8x32[T ~int8](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\tconst lanes = simdLanes32\n\n\tbase := unsafeSliceInt8(collection, length)\n\tvar acc archsimd.Int8x32\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadInt8x32Slice(base[i : i+lanes])\n\t\tacc = acc.Add(v)\n\t}\n\n\tvar buf [lanes]int8\n\tacc.Store(&buf)\n\tvar sum T\n\tfor k := uint(0); k < lanes; k++ {\n\t\tsum += T(buf[k])\n\t}\n\n\tfor ; i < length; i++ {\n\t\tsum += collection[i]\n\t}\n\n\treturn sum\n}\n\n// SumInt16x16 sums a slice of int16 using AVX2 SIMD (Int16x16, 16 lanes).\n// Overflow: The accumulation is performed using int16, which can overflow for large collections.\n// If the sum exceeds the int16 range (-32768 to 32767), the result will wrap around silently.\n// For collections that may overflow, consider using a wider type or handle overflow detection externally.\nfunc SumInt16x16[T ~int16](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\tconst lanes = simdLanes16\n\n\tbase := unsafeSliceInt16(collection, length)\n\tvar acc archsimd.Int16x16\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadInt16x16Slice(base[i : i+lanes])\n\t\tacc = acc.Add(v)\n\t}\n\n\tvar buf [lanes]int16\n\tacc.Store(&buf)\n\tvar sum T\n\tfor k := uint(0); k < lanes; k++ {\n\t\tsum += T(buf[k])\n\t}\n\n\tfor ; i < length; i++ {\n\t\tsum += collection[i]\n\t}\n\n\treturn sum\n}\n\n// SumInt32x8 sums a slice of int32 using AVX2 SIMD (Int32x8, 8 lanes).\n// Overflow: The accumulation is performed using int32, which can overflow for very large collections.\n// If the sum exceeds the int32 range (-2147483648 to 2147483647), the result will wrap around silently.\n// For collections that may overflow, consider using SumInt64x4 or handle overflow detection externally.\nfunc SumInt32x8[T ~int32](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\tconst lanes = simdLanes8\n\n\tbase := unsafeSliceInt32(collection, length)\n\tvar acc archsimd.Int32x8\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadInt32x8Slice(base[i : i+lanes])\n\t\tacc = acc.Add(v)\n\t}\n\n\tvar buf [lanes]int32\n\tacc.Store(&buf)\n\tvar sum T\n\tfor k := uint(0); k < lanes; k++ {\n\t\tsum += T(buf[k])\n\t}\n\n\tfor ; i < length; i++ {\n\t\tsum += collection[i]\n\t}\n\n\treturn sum\n}\n\n// SumInt64x4 sums a slice of int64 using AVX2 SIMD (Int64x4, 4 lanes).\n// Overflow: The accumulation is performed using int64, which can overflow for extremely large collections.\n// If the sum exceeds the int64 range, the result will wrap around silently.\n// For collections that may overflow, handle overflow detection externally (e.g., using big.Int).\nfunc SumInt64x4[T ~int64](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\tconst lanes = simdLanes4\n\n\tbase := unsafeSliceInt64(collection, length)\n\tvar acc archsimd.Int64x4\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadInt64x4Slice(base[i : i+lanes])\n\t\tacc = acc.Add(v)\n\t}\n\n\tvar buf [lanes]int64\n\tacc.Store(&buf)\n\tvar sum T\n\tfor k := uint(0); k < lanes; k++ {\n\t\tsum += T(buf[k])\n\t}\n\n\tfor ; i < length; i++ {\n\t\tsum += collection[i]\n\t}\n\n\treturn sum\n}\n\n// SumUint8x32 sums a slice of uint8 using AVX2 SIMD (Uint8x32, 32 lanes).\n// Overflow: The accumulation is performed using uint8, which can overflow for large collections.\n// If the sum exceeds the uint8 range (0 to 255), the result will wrap around silently.\n// For collections that may overflow, consider using a wider type or handle overflow detection externally.\nfunc SumUint8x32[T ~uint8](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\tconst lanes = simdLanes32\n\n\tbase := unsafeSliceUint8(collection, length)\n\tvar acc archsimd.Uint8x32\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadUint8x32Slice(base[i : i+lanes])\n\t\tacc = acc.Add(v)\n\t}\n\n\tvar buf [lanes]uint8\n\tacc.Store(&buf)\n\tvar sum T\n\tfor k := uint(0); k < lanes; k++ {\n\t\tsum += T(buf[k])\n\t}\n\n\tfor ; i < length; i++ {\n\t\tsum += collection[i]\n\t}\n\n\treturn sum\n}\n\n// SumUint16x16 sums a slice of uint16 using AVX2 SIMD (Uint16x16, 16 lanes).\n// Overflow: The accumulation is performed using uint16, which can overflow for large collections.\n// If the sum exceeds the uint16 range (0 to 65535), the result will wrap around silently.\n// For collections that may overflow, consider using a wider type or handle overflow detection externally.\nfunc SumUint16x16[T ~uint16](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\tconst lanes = simdLanes16\n\n\tbase := unsafeSliceUint16(collection, length)\n\tvar acc archsimd.Uint16x16\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadUint16x16Slice(base[i : i+lanes])\n\t\tacc = acc.Add(v)\n\t}\n\n\tvar buf [lanes]uint16\n\tacc.Store(&buf)\n\tvar sum T\n\tfor k := uint(0); k < lanes; k++ {\n\t\tsum += T(buf[k])\n\t}\n\n\tfor ; i < length; i++ {\n\t\tsum += collection[i]\n\t}\n\n\treturn sum\n}\n\n// SumUint32x8 sums a slice of uint32 using AVX2 SIMD (Uint32x8, 8 lanes).\n// Overflow: The accumulation is performed using uint32, which can overflow for very large collections.\n// If the sum exceeds the uint32 range (0 to 4294967295), the result will wrap around silently.\n// For collections that may overflow, consider using SumUint64x4 or handle overflow detection externally.\nfunc SumUint32x8[T ~uint32](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\tconst lanes = simdLanes8\n\n\tbase := unsafeSliceUint32(collection, length)\n\tvar acc archsimd.Uint32x8\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadUint32x8Slice(base[i : i+lanes])\n\t\tacc = acc.Add(v)\n\t}\n\n\tvar buf [lanes]uint32\n\tacc.Store(&buf)\n\tvar sum T\n\tfor k := uint(0); k < lanes; k++ {\n\t\tsum += T(buf[k])\n\t}\n\n\tfor ; i < length; i++ {\n\t\tsum += collection[i]\n\t}\n\n\treturn sum\n}\n\n// SumUint64x4 sums a slice of uint64 using AVX2 SIMD (Uint64x4, 4 lanes).\n// Overflow: The accumulation is performed using uint64, which can overflow for extremely large collections.\n// If the sum exceeds the uint64 range, the result will wrap around silently.\n// For collections that may overflow, handle overflow detection externally (e.g., using big.Int).\nfunc SumUint64x4[T ~uint64](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\tconst lanes = simdLanes4\n\n\tbase := unsafeSliceUint64(collection, length)\n\tvar acc archsimd.Uint64x4\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadUint64x4Slice(base[i : i+lanes])\n\t\tacc = acc.Add(v)\n\t}\n\n\tvar buf [lanes]uint64\n\tacc.Store(&buf)\n\tvar sum T\n\tfor k := uint(0); k < lanes; k++ {\n\t\tsum += T(buf[k])\n\t}\n\n\tfor ; i < length; i++ {\n\t\tsum += collection[i]\n\t}\n\n\treturn sum\n}\n\n// SumFloat32x8 sums a slice of float32 using AVX2 SIMD (Float32x8, 8 lanes).\n// Overflow: The accumulation is performed using float32. Overflow will result in +/-Inf rather than wrapping.\n// For collections requiring high precision or large sums, consider using SumFloat64x4.\nfunc SumFloat32x8[T ~float32](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\tconst lanes = simdLanes8\n\n\tbase := unsafeSliceFloat32(collection, length)\n\tvar acc archsimd.Float32x8\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadFloat32x8Slice(base[i : i+lanes])\n\t\tacc = acc.Add(v)\n\t}\n\n\tvar buf [lanes]float32\n\tacc.Store(&buf)\n\tvar sum T\n\tfor k := uint(0); k < lanes; k++ {\n\t\tsum += T(buf[k])\n\t}\n\n\tfor ; i < length; i++ {\n\t\tsum += collection[i]\n\t}\n\n\treturn sum\n}\n\n// SumFloat64x4 sums a slice of float64 using AVX2 SIMD (Float64x4, 4 lanes).\n// Overflow: The accumulation is performed using float64. Overflow will result in +/-Inf rather than wrapping.\n// For collections that may overflow, handle overflow detection externally (e.g., using big.Float).\nfunc SumFloat64x4[T ~float64](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\tconst lanes = simdLanes4\n\n\tbase := unsafeSliceFloat64(collection, length)\n\tvar acc archsimd.Float64x4\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadFloat64x4Slice(base[i : i+lanes])\n\t\tacc = acc.Add(v)\n\t}\n\n\tvar buf [lanes]float64\n\tacc.Store(&buf)\n\tvar sum T\n\tfor k := uint(0); k < lanes; k++ {\n\t\tsum += T(buf[k])\n\t}\n\n\tfor ; i < length; i++ {\n\t\tsum += collection[i]\n\t}\n\n\treturn sum\n}\n\n// MeanInt8x32 calculates the mean of a slice of int8 using AVX2 SIMD\nfunc MeanInt8x32[T ~int8](collection []T) T {\n\tif T(len(collection)) == 0 {\n\t\treturn 0\n\t}\n\tsum := SumInt8x32(collection)\n\treturn sum / T(len(collection))\n}\n\n// MeanInt16x16 calculates the mean of a slice of int16 using AVX2 SIMD\nfunc MeanInt16x16[T ~int16](collection []T) T {\n\tif T(len(collection)) == 0 {\n\t\treturn 0\n\t}\n\tsum := SumInt16x16(collection)\n\treturn sum / T(len(collection))\n}\n\n// MeanInt32x8 calculates the mean of a slice of int32 using AVX2 SIMD\nfunc MeanInt32x8[T ~int32](collection []T) T {\n\tif T(len(collection)) == 0 {\n\t\treturn 0\n\t}\n\tsum := SumInt32x8(collection)\n\treturn sum / T(len(collection))\n}\n\n// MeanInt64x4 calculates the mean of a slice of int64 using AVX2 SIMD\nfunc MeanInt64x4[T ~int64](collection []T) T {\n\tif T(len(collection)) == 0 {\n\t\treturn 0\n\t}\n\tsum := SumInt64x4(collection)\n\treturn sum / T(len(collection))\n}\n\n// MeanUint8x32 calculates the mean of a slice of uint8 using AVX2 SIMD\nfunc MeanUint8x32[T ~uint8](collection []T) T {\n\tif T(len(collection)) == 0 {\n\t\treturn 0\n\t}\n\tsum := SumUint8x32(collection)\n\treturn sum / T(len(collection))\n}\n\n// MeanUint16x16 calculates the mean of a slice of uint16 using AVX2 SIMD\nfunc MeanUint16x16[T ~uint16](collection []T) T {\n\tif T(len(collection)) == 0 {\n\t\treturn 0\n\t}\n\tsum := SumUint16x16(collection)\n\treturn sum / T(len(collection))\n}\n\n// MeanUint32x8 calculates the mean of a slice of uint32 using AVX2 SIMD\nfunc MeanUint32x8[T ~uint32](collection []T) T {\n\tif T(len(collection)) == 0 {\n\t\treturn 0\n\t}\n\tsum := SumUint32x8(collection)\n\treturn sum / T(len(collection))\n}\n\n// MeanUint64x4 calculates the mean of a slice of uint64 using AVX2 SIMD\nfunc MeanUint64x4[T ~uint64](collection []T) T {\n\tif T(len(collection)) == 0 {\n\t\treturn 0\n\t}\n\tsum := SumUint64x4(collection)\n\treturn sum / T(len(collection))\n}\n\n// MeanFloat32x8 calculates the mean of a slice of float32 using AVX2 SIMD\nfunc MeanFloat32x8[T ~float32](collection []T) T {\n\tif T(len(collection)) == 0 {\n\t\treturn 0\n\t}\n\tsum := SumFloat32x8(collection)\n\treturn sum / T(len(collection))\n}\n\n// MeanFloat64x4 calculates the mean of a slice of float64 using AVX2 SIMD\nfunc MeanFloat64x4[T ~float64](collection []T) T {\n\tif T(len(collection)) == 0 {\n\t\treturn 0\n\t}\n\tsum := SumFloat64x4(collection)\n\treturn sum / T(len(collection))\n}\n\n// ClampInt8x32 clamps each element in collection between min and max values using AVX2 SIMD\nfunc ClampInt8x32[T ~int8, Slice ~[]T](collection Slice, min, max T) Slice {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn collection\n\t}\n\n\tresult := make(Slice, length)\n\tconst lanes = simdLanes32\n\n\tbase := unsafeSliceInt8(collection, length)\n\tminVec := archsimd.BroadcastInt8x32(int8(min))\n\tmaxVec := archsimd.BroadcastInt8x32(int8(max))\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadInt8x32Slice(base[i : i+lanes])\n\n\t\tclamped := v.Max(minVec).Min(maxVec)\n\n\t\t// bearer:disable go_gosec_unsafe_unsafe\n\t\tclamped.Store((*[lanes]int8)(unsafe.Pointer(&result[i])))\n\t}\n\n\tfor ; i < length; i++ {\n\t\tval := collection[i]\n\t\tif val < min {\n\t\t\tval = min\n\t\t} else if val > max {\n\t\t\tval = max\n\t\t}\n\t\tresult[i] = val\n\t}\n\n\treturn result\n}\n\n// ClampInt16x16 clamps each element in collection between min and max values using AVX2 SIMD\nfunc ClampInt16x16[T ~int16, Slice ~[]T](collection Slice, min, max T) Slice {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn collection\n\t}\n\n\tresult := make(Slice, length)\n\tconst lanes = simdLanes16\n\n\tbase := unsafeSliceInt16(collection, length)\n\tminVec := archsimd.BroadcastInt16x16(int16(min))\n\tmaxVec := archsimd.BroadcastInt16x16(int16(max))\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadInt16x16Slice(base[i : i+lanes])\n\n\t\tclamped := v.Max(minVec).Min(maxVec)\n\n\t\t// bearer:disable go_gosec_unsafe_unsafe\n\t\tclamped.Store((*[lanes]int16)(unsafe.Pointer(&result[i])))\n\t}\n\n\tfor ; i < length; i++ {\n\t\tval := collection[i]\n\t\tif val < min {\n\t\t\tval = min\n\t\t} else if val > max {\n\t\t\tval = max\n\t\t}\n\t\tresult[i] = val\n\t}\n\n\treturn result\n}\n\n// ClampInt32x8 clamps each element in collection between min and max values using AVX2 SIMD\nfunc ClampInt32x8[T ~int32, Slice ~[]T](collection Slice, min, max T) Slice {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn collection\n\t}\n\n\tresult := make(Slice, length)\n\tconst lanes = simdLanes8\n\n\tbase := unsafeSliceInt32(collection, length)\n\tminVec := archsimd.BroadcastInt32x8(int32(min))\n\tmaxVec := archsimd.BroadcastInt32x8(int32(max))\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadInt32x8Slice(base[i : i+lanes])\n\n\t\tclamped := v.Max(minVec).Min(maxVec)\n\n\t\t// bearer:disable go_gosec_unsafe_unsafe\n\t\tclamped.Store((*[lanes]int32)(unsafe.Pointer(&result[i])))\n\t}\n\n\tfor ; i < length; i++ {\n\t\tval := collection[i]\n\t\tif val < min {\n\t\t\tval = min\n\t\t} else if val > max {\n\t\t\tval = max\n\t\t}\n\t\tresult[i] = val\n\t}\n\n\treturn result\n}\n\n// ClampInt64x4 clamps each element in collection between min and max values using AVX2 SIMD and AVX-512 SIMD.\nfunc ClampInt64x4[T ~int64, Slice ~[]T](collection Slice, min, max T) Slice {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn collection\n\t}\n\n\tresult := make(Slice, length)\n\tconst lanes = simdLanes4\n\n\tbase := unsafeSliceInt64(collection, length)\n\tminVec := archsimd.BroadcastInt64x4(int64(min))\n\tmaxVec := archsimd.BroadcastInt64x4(int64(max))\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadInt64x4Slice(base[i : i+lanes])\n\n\t\tclamped := v.Max(minVec).Min(maxVec)\n\n\t\t// bearer:disable go_gosec_unsafe_unsafe\n\t\tclamped.Store((*[lanes]int64)(unsafe.Pointer(&result[i])))\n\t}\n\n\tfor ; i < length; i++ {\n\t\tval := collection[i]\n\t\tif val < min {\n\t\t\tval = min\n\t\t} else if val > max {\n\t\t\tval = max\n\t\t}\n\t\tresult[i] = val\n\t}\n\n\treturn result\n}\n\n// ClampUint8x32 clamps each element in collection between min and max values using AVX2 SIMD\nfunc ClampUint8x32[T ~uint8, Slice ~[]T](collection Slice, min, max T) Slice {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn collection\n\t}\n\n\tresult := make(Slice, length)\n\tconst lanes = simdLanes32\n\n\tbase := unsafeSliceUint8(collection, length)\n\tminVec := archsimd.BroadcastUint8x32(uint8(min))\n\tmaxVec := archsimd.BroadcastUint8x32(uint8(max))\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadUint8x32Slice(base[i : i+lanes])\n\n\t\tclamped := v.Max(minVec).Min(maxVec)\n\n\t\t// bearer:disable go_gosec_unsafe_unsafe\n\t\tclamped.Store((*[lanes]uint8)(unsafe.Pointer(&result[i])))\n\t}\n\n\tfor ; i < length; i++ {\n\t\tval := collection[i]\n\t\tif val < min {\n\t\t\tval = min\n\t\t} else if val > max {\n\t\t\tval = max\n\t\t}\n\t\tresult[i] = val\n\t}\n\n\treturn result\n}\n\n// ClampUint16x16 clamps each element in collection between min and max values using AVX2 SIMD\nfunc ClampUint16x16[T ~uint16, Slice ~[]T](collection Slice, min, max T) Slice {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn collection\n\t}\n\n\tresult := make(Slice, length)\n\tconst lanes = simdLanes16\n\n\tbase := unsafeSliceUint16(collection, length)\n\tminVec := archsimd.BroadcastUint16x16(uint16(min))\n\tmaxVec := archsimd.BroadcastUint16x16(uint16(max))\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadUint16x16Slice(base[i : i+lanes])\n\n\t\tclamped := v.Max(minVec).Min(maxVec)\n\n\t\t// bearer:disable go_gosec_unsafe_unsafe\n\t\tclamped.Store((*[lanes]uint16)(unsafe.Pointer(&result[i])))\n\t}\n\n\tfor ; i < length; i++ {\n\t\tval := collection[i]\n\t\tif val < min {\n\t\t\tval = min\n\t\t} else if val > max {\n\t\t\tval = max\n\t\t}\n\t\tresult[i] = val\n\t}\n\n\treturn result\n}\n\n// ClampUint32x8 clamps each element in collection between min and max values using AVX2 SIMD\nfunc ClampUint32x8[T ~uint32, Slice ~[]T](collection Slice, min, max T) Slice {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn collection\n\t}\n\n\tresult := make(Slice, length)\n\tconst lanes = simdLanes8\n\n\tbase := unsafeSliceUint32(collection, length)\n\tminVec := archsimd.BroadcastUint32x8(uint32(min))\n\tmaxVec := archsimd.BroadcastUint32x8(uint32(max))\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadUint32x8Slice(base[i : i+lanes])\n\n\t\tclamped := v.Max(minVec).Min(maxVec)\n\n\t\t// bearer:disable go_gosec_unsafe_unsafe\n\t\tclamped.Store((*[lanes]uint32)(unsafe.Pointer(&result[i])))\n\t}\n\n\tfor ; i < length; i++ {\n\t\tval := collection[i]\n\t\tif val < min {\n\t\t\tval = min\n\t\t} else if val > max {\n\t\t\tval = max\n\t\t}\n\t\tresult[i] = val\n\t}\n\n\treturn result\n}\n\n// ClampUint64x4 clamps each element in collection between min and max values using AVX2 SIMD and AVX-512 SIMD.\nfunc ClampUint64x4[T ~uint64, Slice ~[]T](collection Slice, min, max T) Slice {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn collection\n\t}\n\n\tresult := make(Slice, length)\n\tconst lanes = simdLanes4\n\n\tbase := unsafeSliceUint64(collection, length)\n\tminVec := archsimd.BroadcastUint64x4(uint64(min))\n\tmaxVec := archsimd.BroadcastUint64x4(uint64(max))\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadUint64x4Slice(base[i : i+lanes])\n\n\t\tclamped := v.Max(minVec).Min(maxVec)\n\n\t\t// bearer:disable go_gosec_unsafe_unsafe\n\t\tclamped.Store((*[lanes]uint64)(unsafe.Pointer(&result[i])))\n\t}\n\n\tfor ; i < length; i++ {\n\t\tval := collection[i]\n\t\tif val < min {\n\t\t\tval = min\n\t\t} else if val > max {\n\t\t\tval = max\n\t\t}\n\t\tresult[i] = val\n\t}\n\n\treturn result\n}\n\n// ClampFloat32x8 clamps each element in collection between min and max values using AVX2 SIMD\nfunc ClampFloat32x8[T ~float32, Slice ~[]T](collection Slice, min, max T) Slice {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn collection\n\t}\n\n\tresult := make(Slice, length)\n\tconst lanes = simdLanes8\n\n\tbase := unsafeSliceFloat32(collection, length)\n\tminVec := archsimd.BroadcastFloat32x8(float32(min))\n\tmaxVec := archsimd.BroadcastFloat32x8(float32(max))\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadFloat32x8Slice(base[i : i+lanes])\n\n\t\tclamped := v.Max(minVec).Min(maxVec)\n\n\t\t// bearer:disable go_gosec_unsafe_unsafe\n\t\tclamped.Store((*[lanes]float32)(unsafe.Pointer(&result[i])))\n\t}\n\n\tfor ; i < length; i++ {\n\t\tval := collection[i]\n\t\tif val < min {\n\t\t\tval = min\n\t\t} else if val > max {\n\t\t\tval = max\n\t\t}\n\t\tresult[i] = val\n\t}\n\n\treturn result\n}\n\n// ClampFloat64x4 clamps each element in collection between min and max values using AVX2 SIMD\nfunc ClampFloat64x4[T ~float64, Slice ~[]T](collection Slice, min, max T) Slice {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn collection\n\t}\n\n\tresult := make(Slice, length)\n\tconst lanes = simdLanes4\n\n\tbase := unsafeSliceFloat64(collection, length)\n\tminVec := archsimd.BroadcastFloat64x4(float64(min))\n\tmaxVec := archsimd.BroadcastFloat64x4(float64(max))\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadFloat64x4Slice(base[i : i+lanes])\n\n\t\tclamped := v.Max(minVec).Min(maxVec)\n\n\t\t// bearer:disable go_gosec_unsafe_unsafe\n\t\tclamped.Store((*[lanes]float64)(unsafe.Pointer(&result[i])))\n\t}\n\n\tfor ; i < length; i++ {\n\t\tval := collection[i]\n\t\tif val < min {\n\t\t\tval = min\n\t\t} else if val > max {\n\t\t\tval = max\n\t\t}\n\t\tresult[i] = val\n\t}\n\n\treturn result\n}\n\n// MinInt8x32 finds the minimum value in a collection of int8 using AVX2 SIMD\nfunc MinInt8x32[T ~int8](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\n\tconst lanes = simdLanes32\n\n\tbase := unsafeSliceInt8(collection, length)\n\tvar minVec archsimd.Int8x32\n\tfirstInitialized := false\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadInt8x32Slice(base[i : i+lanes])\n\n\t\tif !firstInitialized {\n\t\t\tminVec = v\n\t\t\tfirstInitialized = true\n\t\t} else {\n\t\t\tminVec = minVec.Min(v)\n\t\t}\n\t}\n\n\t// Find minimum in the vector (only if we processed any vectors)\n\tvar minVal int8\n\tif firstInitialized {\n\t\tvar buf [lanes]int8\n\t\tminVec.Store(&buf)\n\t\tminVal = min(\n\t\t\tbuf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7],\n\t\t\tbuf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15],\n\t\t\tbuf[16], buf[17], buf[18], buf[19], buf[20], buf[21], buf[22], buf[23],\n\t\t\tbuf[24], buf[25], buf[26], buf[27], buf[28], buf[29], buf[30], buf[31],\n\t\t)\n\t}\n\n\t// Handle remaining elements\n\tfor ; i < length; i++ {\n\t\tif !firstInitialized || collection[i] < T(minVal) {\n\t\t\tminVal = int8(collection[i])\n\t\t\tfirstInitialized = true\n\t\t}\n\t}\n\n\treturn T(minVal)\n}\n\n// MinInt16x16 finds the minimum value in a collection of int16 using AVX2 SIMD\nfunc MinInt16x16[T ~int16](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\n\tconst lanes = simdLanes16\n\n\tbase := unsafeSliceInt16(collection, length)\n\tvar minVec archsimd.Int16x16\n\tfirstInitialized := false\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadInt16x16Slice(base[i : i+lanes])\n\n\t\tif !firstInitialized {\n\t\t\tminVec = v\n\t\t\tfirstInitialized = true\n\t\t} else {\n\t\t\tminVec = minVec.Min(v)\n\t\t}\n\t}\n\n\t// Find minimum in the vector (only if we processed any vectors)\n\tvar minVal int16\n\tif firstInitialized {\n\t\tvar buf [lanes]int16\n\t\tminVec.Store(&buf)\n\t\tminVal = min(\n\t\t\tbuf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7],\n\t\t\tbuf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15],\n\t\t)\n\t}\n\n\t// Handle remaining elements\n\tfor ; i < length; i++ {\n\t\tif !firstInitialized || collection[i] < T(minVal) {\n\t\t\tminVal = int16(collection[i])\n\t\t\tfirstInitialized = true\n\t\t}\n\t}\n\n\treturn T(minVal)\n}\n\n// MinInt32x8 finds the minimum value in a collection of int32 using AVX2 SIMD\nfunc MinInt32x8[T ~int32](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\n\tconst lanes = simdLanes8\n\n\tbase := unsafeSliceInt32(collection, length)\n\tvar minVec archsimd.Int32x8\n\tfirstInitialized := false\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadInt32x8Slice(base[i : i+lanes])\n\n\t\tif !firstInitialized {\n\t\t\tminVec = v\n\t\t\tfirstInitialized = true\n\t\t} else {\n\t\t\tminVec = minVec.Min(v)\n\t\t}\n\t}\n\n\t// Find minimum in the vector (only if we processed any vectors)\n\tvar minVal int32\n\tif firstInitialized {\n\t\tvar buf [lanes]int32\n\t\tminVec.Store(&buf)\n\t\tminVal = min(buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7])\n\t}\n\n\t// Handle remaining elements\n\tfor ; i < length; i++ {\n\t\tif !firstInitialized || collection[i] < T(minVal) {\n\t\t\tminVal = int32(collection[i])\n\t\t\tfirstInitialized = true\n\t\t}\n\t}\n\n\treturn T(minVal)\n}\n\n// MinInt64x4 finds the minimum value in a collection of int64 using AVX2 SIMD\nfunc MinInt64x4[T ~int64](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\n\tconst lanes = simdLanes4\n\n\tbase := unsafeSliceInt64(collection, length)\n\tvar minVec archsimd.Int64x4\n\tfirstInitialized := false\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadInt64x4Slice(base[i : i+lanes])\n\n\t\tif !firstInitialized {\n\t\t\tminVec = v\n\t\t\tfirstInitialized = true\n\t\t} else {\n\t\t\tminVec = minVec.Min(v)\n\t\t}\n\t}\n\n\t// Find minimum in the vector (only if we processed any vectors)\n\tvar minVal int64\n\tif firstInitialized {\n\t\tvar buf [lanes]int64\n\t\tminVec.Store(&buf)\n\t\tminVal = min(buf[0], buf[1], buf[2], buf[3])\n\t}\n\n\t// Handle remaining elements\n\tfor ; i < length; i++ {\n\t\tif !firstInitialized || collection[i] < T(minVal) {\n\t\t\tminVal = int64(collection[i])\n\t\t\tfirstInitialized = true\n\t\t}\n\t}\n\n\treturn T(minVal)\n}\n\n// MinUint8x32 finds the minimum value in a collection of uint8 using AVX2 SIMD\nfunc MinUint8x32[T ~uint8](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\n\tconst lanes = simdLanes32\n\n\tbase := unsafeSliceUint8(collection, length)\n\tvar minVec archsimd.Uint8x32\n\tfirstInitialized := false\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadUint8x32Slice(base[i : i+lanes])\n\n\t\tif !firstInitialized {\n\t\t\tminVec = v\n\t\t\tfirstInitialized = true\n\t\t} else {\n\t\t\tminVec = minVec.Min(v)\n\t\t}\n\t}\n\n\t// Find minimum in the vector (only if we processed any vectors)\n\tvar minVal uint8\n\tif firstInitialized {\n\t\tvar buf [lanes]uint8\n\t\tminVec.Store(&buf)\n\t\tminVal = min(\n\t\t\tbuf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7],\n\t\t\tbuf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15],\n\t\t\tbuf[16], buf[17], buf[18], buf[19], buf[20], buf[21], buf[22], buf[23],\n\t\t\tbuf[24], buf[25], buf[26], buf[27], buf[28], buf[29], buf[30], buf[31],\n\t\t)\n\t}\n\n\t// Handle remaining elements\n\tfor ; i < length; i++ {\n\t\tif !firstInitialized || collection[i] < T(minVal) {\n\t\t\tminVal = uint8(collection[i])\n\t\t\tfirstInitialized = true\n\t\t}\n\t}\n\n\treturn T(minVal)\n}\n\n// MinUint16x16 finds the minimum value in a collection of uint16 using AVX2 SIMD\nfunc MinUint16x16[T ~uint16](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\n\tconst lanes = simdLanes16\n\n\tbase := unsafeSliceUint16(collection, length)\n\tvar minVec archsimd.Uint16x16\n\tfirstInitialized := false\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadUint16x16Slice(base[i : i+lanes])\n\n\t\tif !firstInitialized {\n\t\t\tminVec = v\n\t\t\tfirstInitialized = true\n\t\t} else {\n\t\t\tminVec = minVec.Min(v)\n\t\t}\n\t}\n\n\t// Find minimum in the vector (only if we processed any vectors)\n\tvar minVal uint16\n\tif firstInitialized {\n\t\tvar buf [lanes]uint16\n\t\tminVec.Store(&buf)\n\t\tminVal = min(\n\t\t\tbuf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7],\n\t\t\tbuf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15],\n\t\t)\n\t}\n\n\t// Handle remaining elements\n\tfor ; i < length; i++ {\n\t\tif !firstInitialized || collection[i] < T(minVal) {\n\t\t\tminVal = uint16(collection[i])\n\t\t\tfirstInitialized = true\n\t\t}\n\t}\n\n\treturn T(minVal)\n}\n\n// MinUint32x8 finds the minimum value in a collection of uint32 using AVX2 SIMD\nfunc MinUint32x8[T ~uint32](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\n\tconst lanes = simdLanes8\n\n\tbase := unsafeSliceUint32(collection, length)\n\tvar minVec archsimd.Uint32x8\n\tfirstInitialized := false\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadUint32x8Slice(base[i : i+lanes])\n\n\t\tif !firstInitialized {\n\t\t\tminVec = v\n\t\t\tfirstInitialized = true\n\t\t} else {\n\t\t\tminVec = minVec.Min(v)\n\t\t}\n\t}\n\n\t// Find minimum in the vector (only if we processed any vectors)\n\tvar minVal uint32\n\tif firstInitialized {\n\t\tvar buf [lanes]uint32\n\t\tminVec.Store(&buf)\n\t\tminVal = min(buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7])\n\t}\n\n\t// Handle remaining elements\n\tfor ; i < length; i++ {\n\t\tif !firstInitialized || collection[i] < T(minVal) {\n\t\t\tminVal = uint32(collection[i])\n\t\t\tfirstInitialized = true\n\t\t}\n\t}\n\n\treturn T(minVal)\n}\n\n// MinUint64x4 finds the minimum value in a collection of uint64 using AVX2 SIMD\nfunc MinUint64x4[T ~uint64](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\n\tconst lanes = simdLanes4\n\n\tbase := unsafeSliceUint64(collection, length)\n\tvar minVec archsimd.Uint64x4\n\tfirstInitialized := false\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadUint64x4Slice(base[i : i+lanes])\n\n\t\tif !firstInitialized {\n\t\t\tminVec = v\n\t\t\tfirstInitialized = true\n\t\t} else {\n\t\t\tminVec = minVec.Min(v)\n\t\t}\n\t}\n\n\t// Find minimum in the vector (only if we processed any vectors)\n\tvar minVal uint64\n\tif firstInitialized {\n\t\tvar buf [lanes]uint64\n\t\tminVec.Store(&buf)\n\t\tminVal = min(buf[0], buf[1], buf[2], buf[3])\n\t}\n\n\t// Handle remaining elements\n\tfor ; i < length; i++ {\n\t\tif !firstInitialized || collection[i] < T(minVal) {\n\t\t\tminVal = uint64(collection[i])\n\t\t\tfirstInitialized = true\n\t\t}\n\t}\n\n\treturn T(minVal)\n}\n\n// MinFloat32x8 finds the minimum value in a collection of float32 using AVX2 SIMD\nfunc MinFloat32x8[T ~float32](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\n\tconst lanes = simdLanes8\n\n\tbase := unsafeSliceFloat32(collection, length)\n\tvar minVec archsimd.Float32x8\n\tfirstInitialized := false\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadFloat32x8Slice(base[i : i+lanes])\n\n\t\tif !firstInitialized {\n\t\t\tminVec = v\n\t\t\tfirstInitialized = true\n\t\t} else {\n\t\t\tminVec = minVec.Min(v)\n\t\t}\n\t}\n\n\t// Find minimum in the vector (only if we processed any vectors)\n\tvar minVal float32\n\tif firstInitialized {\n\t\tvar buf [lanes]float32\n\t\tminVec.Store(&buf)\n\t\tminVal = min(buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7])\n\t}\n\n\t// Handle remaining elements\n\tfor ; i < length; i++ {\n\t\tif !firstInitialized || collection[i] < T(minVal) {\n\t\t\tminVal = float32(collection[i])\n\t\t\tfirstInitialized = true\n\t\t}\n\t}\n\n\treturn T(minVal)\n}\n\n// MinFloat64x4 finds the minimum value in a collection of float64 using AVX2 SIMD\nfunc MinFloat64x4[T ~float64](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\n\tconst lanes = simdLanes4\n\n\tbase := unsafeSliceFloat64(collection, length)\n\tvar minVec archsimd.Float64x4\n\tfirstInitialized := false\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadFloat64x4Slice(base[i : i+lanes])\n\n\t\tif !firstInitialized {\n\t\t\tminVec = v\n\t\t\tfirstInitialized = true\n\t\t} else {\n\t\t\tminVec = minVec.Min(v)\n\t\t}\n\t}\n\n\t// Find minimum in the vector (only if we processed any vectors)\n\tvar minVal float64\n\tif firstInitialized {\n\t\tvar buf [lanes]float64\n\t\tminVec.Store(&buf)\n\t\tminVal = min(buf[0], buf[1], buf[2], buf[3])\n\t}\n\n\t// Handle remaining elements\n\tfor ; i < length; i++ {\n\t\tif !firstInitialized || collection[i] < T(minVal) {\n\t\t\tminVal = float64(collection[i])\n\t\t\tfirstInitialized = true\n\t\t}\n\t}\n\n\treturn T(minVal)\n}\n\n// MaxInt8x32 finds the maximum value in a collection of int8 using AVX2 SIMD\nfunc MaxInt8x32[T ~int8](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\n\tconst lanes = simdLanes32\n\n\tbase := unsafeSliceInt8(collection, length)\n\tvar maxVec archsimd.Int8x32\n\tfirstInitialized := false\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadInt8x32Slice(base[i : i+lanes])\n\n\t\tif !firstInitialized {\n\t\t\tmaxVec = v\n\t\t\tfirstInitialized = true\n\t\t} else {\n\t\t\tmaxVec = maxVec.Max(v)\n\t\t}\n\t}\n\n\t// Find maximum in the vector (only if we processed any vectors)\n\tvar maxVal int8\n\tif firstInitialized {\n\t\tvar buf [lanes]int8\n\t\tmaxVec.Store(&buf)\n\t\tmaxVal = max(\n\t\t\tbuf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7],\n\t\t\tbuf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15],\n\t\t\tbuf[16], buf[17], buf[18], buf[19], buf[20], buf[21], buf[22], buf[23],\n\t\t\tbuf[24], buf[25], buf[26], buf[27], buf[28], buf[29], buf[30], buf[31],\n\t\t)\n\t}\n\n\t// Handle remaining elements\n\tfor ; i < length; i++ {\n\t\tif !firstInitialized || collection[i] > T(maxVal) {\n\t\t\tmaxVal = int8(collection[i])\n\t\t\tfirstInitialized = true\n\t\t}\n\t}\n\n\treturn T(maxVal)\n}\n\n// MaxInt16x16 finds the maximum value in a collection of int16 using AVX2 SIMD\nfunc MaxInt16x16[T ~int16](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\n\tconst lanes = simdLanes16\n\n\tbase := unsafeSliceInt16(collection, length)\n\tvar maxVec archsimd.Int16x16\n\tfirstInitialized := false\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadInt16x16Slice(base[i : i+lanes])\n\n\t\tif !firstInitialized {\n\t\t\tmaxVec = v\n\t\t\tfirstInitialized = true\n\t\t} else {\n\t\t\tmaxVec = maxVec.Max(v)\n\t\t}\n\t}\n\n\t// Find maximum in the vector (only if we processed any vectors)\n\tvar maxVal int16\n\tif firstInitialized {\n\t\tvar buf [lanes]int16\n\t\tmaxVec.Store(&buf)\n\t\tmaxVal = max(\n\t\t\tbuf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7],\n\t\t\tbuf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15],\n\t\t)\n\t}\n\n\t// Handle remaining elements\n\tfor ; i < length; i++ {\n\t\tif !firstInitialized || collection[i] > T(maxVal) {\n\t\t\tmaxVal = int16(collection[i])\n\t\t\tfirstInitialized = true\n\t\t}\n\t}\n\n\treturn T(maxVal)\n}\n\n// MaxInt32x8 finds the maximum value in a collection of int32 using AVX2 SIMD\nfunc MaxInt32x8[T ~int32](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\n\tconst lanes = simdLanes8\n\n\tbase := unsafeSliceInt32(collection, length)\n\tvar maxVec archsimd.Int32x8\n\tfirstInitialized := false\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadInt32x8Slice(base[i : i+lanes])\n\n\t\tif !firstInitialized {\n\t\t\tmaxVec = v\n\t\t\tfirstInitialized = true\n\t\t} else {\n\t\t\tmaxVec = maxVec.Max(v)\n\t\t}\n\t}\n\n\t// Find maximum in the vector (only if we processed any vectors)\n\tvar maxVal int32\n\tif firstInitialized {\n\t\tvar buf [lanes]int32\n\t\tmaxVec.Store(&buf)\n\t\tmaxVal = max(buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7])\n\t}\n\n\t// Handle remaining elements\n\tfor ; i < length; i++ {\n\t\tif !firstInitialized || collection[i] > T(maxVal) {\n\t\t\tmaxVal = int32(collection[i])\n\t\t\tfirstInitialized = true\n\t\t}\n\t}\n\n\treturn T(maxVal)\n}\n\n// MaxInt64x4 finds the maximum value in a collection of int64 using AVX2 SIMD\nfunc MaxInt64x4[T ~int64](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\n\tconst lanes = simdLanes4\n\n\tbase := unsafeSliceInt64(collection, length)\n\tvar maxVec archsimd.Int64x4\n\tfirstInitialized := false\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadInt64x4Slice(base[i : i+lanes])\n\n\t\tif !firstInitialized {\n\t\t\tmaxVec = v\n\t\t\tfirstInitialized = true\n\t\t} else {\n\t\t\tmaxVec = maxVec.Max(v)\n\t\t}\n\t}\n\n\t// Find maximum in the vector (only if we processed any vectors)\n\tvar maxVal int64\n\tif firstInitialized {\n\t\tvar buf [lanes]int64\n\t\tmaxVec.Store(&buf)\n\t\tmaxVal = max(buf[0], buf[1], buf[2], buf[3])\n\t}\n\n\t// Handle remaining elements\n\tfor ; i < length; i++ {\n\t\tif !firstInitialized || collection[i] > T(maxVal) {\n\t\t\tmaxVal = int64(collection[i])\n\t\t\tfirstInitialized = true\n\t\t}\n\t}\n\n\treturn T(maxVal)\n}\n\n// MaxUint8x32 finds the maximum value in a collection of uint8 using AVX2 SIMD\nfunc MaxUint8x32[T ~uint8](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\n\tconst lanes = simdLanes32\n\n\tbase := unsafeSliceUint8(collection, length)\n\tvar maxVec archsimd.Uint8x32\n\tfirstInitialized := false\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadUint8x32Slice(base[i : i+lanes])\n\n\t\tif !firstInitialized {\n\t\t\tmaxVec = v\n\t\t\tfirstInitialized = true\n\t\t} else {\n\t\t\tmaxVec = maxVec.Max(v)\n\t\t}\n\t}\n\n\t// Find maximum in the vector (only if we processed any vectors)\n\tvar maxVal uint8\n\tif firstInitialized {\n\t\tvar buf [lanes]uint8\n\t\tmaxVec.Store(&buf)\n\t\tmaxVal = max(\n\t\t\tbuf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7],\n\t\t\tbuf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15],\n\t\t\tbuf[16], buf[17], buf[18], buf[19], buf[20], buf[21], buf[22], buf[23],\n\t\t\tbuf[24], buf[25], buf[26], buf[27], buf[28], buf[29], buf[30], buf[31],\n\t\t)\n\t}\n\n\t// Handle remaining elements\n\tfor ; i < length; i++ {\n\t\tif !firstInitialized || collection[i] > T(maxVal) {\n\t\t\tmaxVal = uint8(collection[i])\n\t\t\tfirstInitialized = true\n\t\t}\n\t}\n\n\treturn T(maxVal)\n}\n\n// MaxUint16x16 finds the maximum value in a collection of uint16 using AVX2 SIMD\nfunc MaxUint16x16[T ~uint16](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\n\tconst lanes = simdLanes16\n\n\tbase := unsafeSliceUint16(collection, length)\n\tvar maxVec archsimd.Uint16x16\n\tfirstInitialized := false\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadUint16x16Slice(base[i : i+lanes])\n\n\t\tif !firstInitialized {\n\t\t\tmaxVec = v\n\t\t\tfirstInitialized = true\n\t\t} else {\n\t\t\tmaxVec = maxVec.Max(v)\n\t\t}\n\t}\n\n\t// Find maximum in the vector (only if we processed any vectors)\n\tvar maxVal uint16\n\tif firstInitialized {\n\t\tvar buf [lanes]uint16\n\t\tmaxVec.Store(&buf)\n\t\tmaxVal = max(\n\t\t\tbuf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7],\n\t\t\tbuf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15],\n\t\t)\n\t}\n\n\t// Handle remaining elements\n\tfor ; i < length; i++ {\n\t\tif !firstInitialized || collection[i] > T(maxVal) {\n\t\t\tmaxVal = uint16(collection[i])\n\t\t\tfirstInitialized = true\n\t\t}\n\t}\n\n\treturn T(maxVal)\n}\n\n// MaxUint32x8 finds the maximum value in a collection of uint32 using AVX2 SIMD\nfunc MaxUint32x8[T ~uint32](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\n\tconst lanes = simdLanes8\n\n\tbase := unsafeSliceUint32(collection, length)\n\tvar maxVec archsimd.Uint32x8\n\tfirstInitialized := false\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadUint32x8Slice(base[i : i+lanes])\n\n\t\tif !firstInitialized {\n\t\t\tmaxVec = v\n\t\t\tfirstInitialized = true\n\t\t} else {\n\t\t\tmaxVec = maxVec.Max(v)\n\t\t}\n\t}\n\n\t// Find maximum in the vector (only if we processed any vectors)\n\tvar maxVal uint32\n\tif firstInitialized {\n\t\tvar buf [lanes]uint32\n\t\tmaxVec.Store(&buf)\n\t\tmaxVal = max(buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7])\n\t}\n\n\t// Handle remaining elements\n\tfor ; i < length; i++ {\n\t\tif !firstInitialized || collection[i] > T(maxVal) {\n\t\t\tmaxVal = uint32(collection[i])\n\t\t\tfirstInitialized = true\n\t\t}\n\t}\n\n\treturn T(maxVal)\n}\n\n// MaxUint64x4 finds the maximum value in a collection of uint64 using AVX2 SIMD\nfunc MaxUint64x4[T ~uint64](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\n\tconst lanes = simdLanes4\n\n\tbase := unsafeSliceUint64(collection, length)\n\tvar maxVec archsimd.Uint64x4\n\tfirstInitialized := false\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadUint64x4Slice(base[i : i+lanes])\n\n\t\tif !firstInitialized {\n\t\t\tmaxVec = v\n\t\t\tfirstInitialized = true\n\t\t} else {\n\t\t\tmaxVec = maxVec.Max(v)\n\t\t}\n\t}\n\n\t// Find maximum in the vector (only if we processed any vectors)\n\tvar maxVal uint64\n\tif firstInitialized {\n\t\tvar buf [lanes]uint64\n\t\tmaxVec.Store(&buf)\n\t\tmaxVal = max(buf[0], buf[1], buf[2], buf[3])\n\t}\n\n\t// Handle remaining elements\n\tfor ; i < length; i++ {\n\t\tif !firstInitialized || collection[i] > T(maxVal) {\n\t\t\tmaxVal = uint64(collection[i])\n\t\t\tfirstInitialized = true\n\t\t}\n\t}\n\n\treturn T(maxVal)\n}\n\n// MaxFloat32x8 finds the maximum value in a collection of float32 using AVX2 SIMD\nfunc MaxFloat32x8[T ~float32](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\n\tconst lanes = simdLanes8\n\n\tbase := unsafeSliceFloat32(collection, length)\n\tvar maxVec archsimd.Float32x8\n\tfirstInitialized := false\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadFloat32x8Slice(base[i : i+lanes])\n\n\t\tif !firstInitialized {\n\t\t\tmaxVec = v\n\t\t\tfirstInitialized = true\n\t\t} else {\n\t\t\tmaxVec = maxVec.Max(v)\n\t\t}\n\t}\n\n\t// Find maximum in the vector (only if we processed any vectors)\n\tvar maxVal float32\n\tif firstInitialized {\n\t\tvar buf [lanes]float32\n\t\tmaxVec.Store(&buf)\n\t\tmaxVal = max(buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7])\n\t}\n\n\t// Handle remaining elements\n\tfor ; i < length; i++ {\n\t\tif !firstInitialized || collection[i] > T(maxVal) {\n\t\t\tmaxVal = float32(collection[i])\n\t\t\tfirstInitialized = true\n\t\t}\n\t}\n\n\treturn T(maxVal)\n}\n\n// MaxFloat64x4 finds the maximum value in a collection of float64 using AVX2 SIMD\nfunc MaxFloat64x4[T ~float64](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\n\tconst lanes = simdLanes4\n\n\tbase := unsafeSliceFloat64(collection, length)\n\tvar maxVec archsimd.Float64x4\n\tfirstInitialized := false\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadFloat64x4Slice(base[i : i+lanes])\n\n\t\tif !firstInitialized {\n\t\t\tmaxVec = v\n\t\t\tfirstInitialized = true\n\t\t} else {\n\t\t\tmaxVec = maxVec.Max(v)\n\t\t}\n\t}\n\n\t// Find maximum in the vector (only if we processed any vectors)\n\tvar maxVal float64\n\tif firstInitialized {\n\t\tvar buf [lanes]float64\n\t\tmaxVec.Store(&buf)\n\t\tmaxVal = max(buf[0], buf[1], buf[2], buf[3])\n\t}\n\n\t// Handle remaining elements\n\tfor ; i < length; i++ {\n\t\tif !firstInitialized || collection[i] > T(maxVal) {\n\t\t\tmaxVal = float64(collection[i])\n\t\t\tfirstInitialized = true\n\t\t}\n\t}\n\n\treturn T(maxVal)\n}\n\n// AVX2 (256-bit) SIMD sumBy functions - 32/16/8/4 lanes\n// These implementations use lo.Map to apply the iteratee, then chain with SIMD sum functions.\n\n// SumByInt8x32 sums the values extracted by iteratee from a slice using AVX2 SIMD.\nfunc SumByInt8x32[T any, R ~int8](collection []T, iteratee func(item T) R) R {\n\tmapped := lo.Map(collection, func(item T, _ int) R { return iteratee(item) })\n\treturn SumInt8x32(mapped)\n}\n\n// SumByInt16x16 sums the values extracted by iteratee from a slice using AVX2 SIMD.\nfunc SumByInt16x16[T any, R ~int16](collection []T, iteratee func(item T) R) R {\n\tmapped := lo.Map(collection, func(item T, _ int) R { return iteratee(item) })\n\treturn SumInt16x16(mapped)\n}\n\n// SumByInt32x8 sums the values extracted by iteratee from a slice using AVX2 SIMD.\nfunc SumByInt32x8[T any, R ~int32](collection []T, iteratee func(item T) R) R {\n\tmapped := lo.Map(collection, func(item T, _ int) R { return iteratee(item) })\n\treturn SumInt32x8(mapped)\n}\n\n// SumByInt64x4 sums the values extracted by iteratee from a slice using AVX2 SIMD.\nfunc SumByInt64x4[T any, R ~int64](collection []T, iteratee func(item T) R) R {\n\tmapped := lo.Map(collection, func(item T, _ int) R { return iteratee(item) })\n\treturn SumInt64x4(mapped)\n}\n\n// SumByUint8x32 sums the values extracted by iteratee from a slice using AVX2 SIMD.\nfunc SumByUint8x32[T any, R ~uint8](collection []T, iteratee func(item T) R) R {\n\tmapped := lo.Map(collection, func(item T, _ int) R { return iteratee(item) })\n\treturn SumUint8x32(mapped)\n}\n\n// SumByUint16x16 sums the values extracted by iteratee from a slice using AVX2 SIMD.\nfunc SumByUint16x16[T any, R ~uint16](collection []T, iteratee func(item T) R) R {\n\tmapped := lo.Map(collection, func(item T, _ int) R { return iteratee(item) })\n\treturn SumUint16x16(mapped)\n}\n\n// SumByUint32x8 sums the values extracted by iteratee from a slice using AVX2 SIMD.\nfunc SumByUint32x8[T any, R ~uint32](collection []T, iteratee func(item T) R) R {\n\tmapped := lo.Map(collection, func(item T, _ int) R { return iteratee(item) })\n\treturn SumUint32x8(mapped)\n}\n\n// SumByUint64x4 sums the values extracted by iteratee from a slice using AVX2 SIMD.\nfunc SumByUint64x4[T any, R ~uint64](collection []T, iteratee func(item T) R) R {\n\tmapped := lo.Map(collection, func(item T, _ int) R { return iteratee(item) })\n\treturn SumUint64x4(mapped)\n}\n\n// SumByFloat32x8 sums the values extracted by iteratee from a slice using AVX2 SIMD.\nfunc SumByFloat32x8[T any, R ~float32](collection []T, iteratee func(item T) R) R {\n\tmapped := lo.Map(collection, func(item T, _ int) R { return iteratee(item) })\n\treturn SumFloat32x8(mapped)\n}\n\n// SumByFloat64x4 sums the values extracted by iteratee from a slice using AVX2 SIMD.\nfunc SumByFloat64x4[T any, R ~float64](collection []T, iteratee func(item T) R) R {\n\tmapped := lo.Map(collection, func(item T, _ int) R { return iteratee(item) })\n\treturn SumFloat64x4(mapped)\n}\n\n// AVX2 (256-bit) SIMD meanBy functions - 32/16/8/4 lanes\n// These implementations use lo.Map to apply the iteratee, then chain with SIMD mean functions.\n\n// MeanByInt8x32 calculates the mean of values extracted by iteratee from a slice using AVX2 SIMD.\nfunc MeanByInt8x32[T any, R ~int8](collection []T, iteratee func(item T) R) R {\n\tmapped := lo.Map(collection, func(item T, _ int) R { return iteratee(item) })\n\treturn MeanInt8x32(mapped)\n}\n\n// MeanByInt16x16 calculates the mean of values extracted by iteratee from a slice using AVX2 SIMD.\nfunc MeanByInt16x16[T any, R ~int16](collection []T, iteratee func(item T) R) R {\n\tmapped := lo.Map(collection, func(item T, _ int) R { return iteratee(item) })\n\treturn MeanInt16x16(mapped)\n}\n\n// MeanByInt32x8 calculates the mean of values extracted by iteratee from a slice using AVX2 SIMD.\nfunc MeanByInt32x8[T any, R ~int32](collection []T, iteratee func(item T) R) R {\n\tmapped := lo.Map(collection, func(item T, _ int) R { return iteratee(item) })\n\treturn MeanInt32x8(mapped)\n}\n\n// MeanByInt64x4 calculates the mean of values extracted by iteratee from a slice using AVX2 SIMD.\nfunc MeanByInt64x4[T any, R ~int64](collection []T, iteratee func(item T) R) R {\n\tmapped := lo.Map(collection, func(item T, _ int) R { return iteratee(item) })\n\treturn MeanInt64x4(mapped)\n}\n\n// MeanByUint8x32 calculates the mean of values extracted by iteratee from a slice using AVX2 SIMD.\nfunc MeanByUint8x32[T any, R ~uint8](collection []T, iteratee func(item T) R) R {\n\tmapped := lo.Map(collection, func(item T, _ int) R { return iteratee(item) })\n\treturn MeanUint8x32(mapped)\n}\n\n// MeanByUint16x16 calculates the mean of values extracted by iteratee from a slice using AVX2 SIMD.\nfunc MeanByUint16x16[T any, R ~uint16](collection []T, iteratee func(item T) R) R {\n\tmapped := lo.Map(collection, func(item T, _ int) R { return iteratee(item) })\n\treturn MeanUint16x16(mapped)\n}\n\n// MeanByUint32x8 calculates the mean of values extracted by iteratee from a slice using AVX2 SIMD.\nfunc MeanByUint32x8[T any, R ~uint32](collection []T, iteratee func(item T) R) R {\n\tmapped := lo.Map(collection, func(item T, _ int) R { return iteratee(item) })\n\treturn MeanUint32x8(mapped)\n}\n\n// MeanByUint64x4 calculates the mean of values extracted by iteratee from a slice using AVX2 SIMD.\nfunc MeanByUint64x4[T any, R ~uint64](collection []T, iteratee func(item T) R) R {\n\tmapped := lo.Map(collection, func(item T, _ int) R { return iteratee(item) })\n\treturn MeanUint64x4(mapped)\n}\n\n// MeanByFloat32x8 calculates the mean of values extracted by iteratee from a slice using AVX2 SIMD.\nfunc MeanByFloat32x8[T any, R ~float32](collection []T, iteratee func(item T) R) R {\n\tmapped := lo.Map(collection, func(item T, _ int) R { return iteratee(item) })\n\treturn MeanFloat32x8(mapped)\n}\n\n// MeanByFloat64x4 calculates the mean of values extracted by iteratee from a slice using AVX2 SIMD.\nfunc MeanByFloat64x4[T any, R ~float64](collection []T, iteratee func(item T) R) R {\n\tmapped := lo.Map(collection, func(item T, _ int) R { return iteratee(item) })\n\treturn MeanFloat64x4(mapped)\n}\n"
  },
  {
    "path": "exp/simd/math_avx2_test.go",
    "content": "//go:build go1.26 && goexperiment.simd && amd64\n\npackage simd\n\nimport (\n\t\"math/rand/v2\"\n\t\"testing\"\n\n\t\"github.com/samber/lo\"\n)\n\nfunc TestSumInt8x32(t *testing.T) {\n\trequireAVX2(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []int8\n\t}{\n\t\t{\"empty\", []int8{}},\n\t\t{\"single\", []int8{42}},\n\t\t{\"small\", []int8{1, 2, 3, 4, 5}},\n\t\t{\"exactly 32\", make([]int8, 32)},\n\t\t{\"large\", make([]int8, 1000)},\n\t\t{\"negative\", []int8{-1, -2, -3, 4, 5}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = int8(rand.IntN(256) - 128)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := SumInt8x32(tc.input)\n\t\t\twant := lo.Sum(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"SumInt8x32() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestSumInt16x16(t *testing.T) {\n\trequireAVX2(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []int16\n\t}{\n\t\t{\"empty\", []int16{}},\n\t\t{\"single\", []int16{42}},\n\t\t{\"small\", []int16{1, 2, 3, 4, 5}},\n\t\t{\"exactly 16\", make([]int16, 16)},\n\t\t{\"large\", make([]int16, 1000)},\n\t\t{\"negative\", []int16{-1, -2, -3, 4, 5}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = int16(rand.IntN(65536) - 32768)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := SumInt16x16(tc.input)\n\t\t\twant := lo.Sum(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"SumInt16x16() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestSumInt32x8(t *testing.T) {\n\trequireAVX2(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []int32\n\t}{\n\t\t{\"empty\", []int32{}},\n\t\t{\"single\", []int32{42}},\n\t\t{\"small\", []int32{1, 2, 3, 4, 5}},\n\t\t{\"exactly 8\", make([]int32, 8)},\n\t\t{\"large\", make([]int32, 1000)},\n\t\t{\"negative\", []int32{-1, -2, -3, 4, 5}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = int32(rand.Int32())\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := SumInt32x8(tc.input)\n\t\t\twant := lo.Sum(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"SumInt32x8() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestSumInt64x4(t *testing.T) {\n\trequireAVX2(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []int64\n\t}{\n\t\t{\"empty\", []int64{}},\n\t\t{\"single\", []int64{42}},\n\t\t{\"small\", []int64{1, 2, 3, 4, 5}},\n\t\t{\"exactly 4\", make([]int64, 4)},\n\t\t{\"large\", make([]int64, 1000)},\n\t\t{\"negative\", []int64{-1, -2, -3, 4, 5}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Int64()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := SumInt64x4(tc.input)\n\t\t\twant := lo.Sum(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"SumInt64x4() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestSumUint8x32(t *testing.T) {\n\trequireAVX2(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []uint8\n\t}{\n\t\t{\"empty\", []uint8{}},\n\t\t{\"single\", []uint8{42}},\n\t\t{\"small\", []uint8{1, 2, 3, 4, 5}},\n\t\t{\"exactly 32\", make([]uint8, 32)},\n\t\t{\"large\", make([]uint8, 1000)},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = uint8(rand.IntN(256))\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := SumUint8x32(tc.input)\n\t\t\twant := lo.Sum(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"SumUint8x32() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestSumUint16x16(t *testing.T) {\n\trequireAVX2(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []uint16\n\t}{\n\t\t{\"empty\", []uint16{}},\n\t\t{\"single\", []uint16{42}},\n\t\t{\"small\", []uint16{1, 2, 3, 4, 5}},\n\t\t{\"exactly 16\", make([]uint16, 16)},\n\t\t{\"large\", make([]uint16, 1000)},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = uint16(rand.IntN(65536))\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := SumUint16x16(tc.input)\n\t\t\twant := lo.Sum(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"SumUint16x16() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestSumUint32x8(t *testing.T) {\n\trequireAVX2(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []uint32\n\t}{\n\t\t{\"empty\", []uint32{}},\n\t\t{\"single\", []uint32{42}},\n\t\t{\"small\", []uint32{1, 2, 3, 4, 5}},\n\t\t{\"exactly 8\", make([]uint32, 8)},\n\t\t{\"large\", make([]uint32, 1000)},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Uint32()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := SumUint32x8(tc.input)\n\t\t\twant := lo.Sum(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"SumUint32x8() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestSumUint64x4(t *testing.T) {\n\trequireAVX2(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []uint64\n\t}{\n\t\t{\"empty\", []uint64{}},\n\t\t{\"single\", []uint64{42}},\n\t\t{\"small\", []uint64{1, 2, 3, 4, 5}},\n\t\t{\"exactly 4\", make([]uint64, 4)},\n\t\t{\"large\", make([]uint64, 1000)},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Uint64()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := SumUint64x4(tc.input)\n\t\t\twant := lo.Sum(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"SumUint64x4() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestSumFloat32x8(t *testing.T) {\n\trequireAVX2(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []float32\n\t}{\n\t\t{\"empty\", []float32{}},\n\t\t{\"single\", []float32{42.5}},\n\t\t{\"small\", []float32{1.1, 2.2, 3.3, 4.4, 5.5}},\n\t\t{\"exactly 8\", make([]float32, 8)},\n\t\t{\"large\", make([]float32, 1000)},\n\t\t{\"negative\", []float32{-1.1, -2.2, 3.3, 4.4}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Float32()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := SumFloat32x8(tc.input)\n\t\t\twant := lo.Sum(tc.input)\n\n\t\t\tconst epsilon = 1e-3\n\t\t\tif diff := got - want; diff < -epsilon || diff > epsilon {\n\t\t\t\tt.Errorf(\"SumFloat32x8() = %v, want %v (diff: %v)\", got, want, diff)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestSumFloat64x4(t *testing.T) {\n\trequireAVX2(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []float64\n\t}{\n\t\t{\"empty\", []float64{}},\n\t\t{\"single\", []float64{42.5}},\n\t\t{\"small\", []float64{1.1, 2.2, 3.3, 4.4, 5.5}},\n\t\t{\"exactly 4\", make([]float64, 4)},\n\t\t{\"large\", make([]float64, 1000)},\n\t\t{\"negative\", []float64{-1.1, -2.2, 3.3, 4.4}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Float64()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := SumFloat64x4(tc.input)\n\t\t\twant := lo.Sum(tc.input)\n\n\t\t\tconst epsilon = 1e-3\n\t\t\tif diff := got - want; diff < -epsilon || diff > epsilon {\n\t\t\t\tt.Errorf(\"SumFloat64x4() = %v, want %v (diff: %v)\", got, want, diff)\n\t\t\t}\n\t\t})\n\t}\n}\n\n// Test type aliases work correctly\nfunc TestAVX2TypeAlias(t *testing.T) {\n\trequireAVX2(t)\n\tinput := []myInt16{1, 2, 3, 4, 5}\n\tgot := SumInt16x16(input)\n\twant := lo.Sum(input)\n\n\tif got != want {\n\t\tt.Errorf(\"SumInt16x16() with type alias = %v, want %v\", got, want)\n\t}\n}\n\nfunc TestMeanInt8x32(t *testing.T) {\n\trequireAVX2(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []int8\n\t}{\n\t\t{\"empty\", []int8{}},\n\t\t{\"single\", []int8{42}},\n\t\t{\"small\", []int8{1, 2, 3, 4, 5}},\n\t\t{\"exactly 32\", make([]int8, 32)},\n\t\t{\"large\", make([]int8, 1000)},\n\t\t{\"negative\", []int8{-1, -2, -3, 4, 5}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = int8(rand.IntN(256) - 128)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MeanInt8x32(tc.input)\n\t\t\twant := lo.Mean(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MeanInt8x32() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMeanInt16x16(t *testing.T) {\n\trequireAVX2(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []int16\n\t}{\n\t\t{\"empty\", []int16{}},\n\t\t{\"single\", []int16{42}},\n\t\t{\"small\", []int16{1, 2, 3, 4, 5}},\n\t\t{\"exactly 16\", make([]int16, 16)},\n\t\t{\"large\", make([]int16, 1000)},\n\t\t{\"negative\", []int16{-1, -2, -3, 4, 5}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = int16(rand.IntN(65536) - 32768)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MeanInt16x16(tc.input)\n\t\t\twant := lo.Mean(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MeanInt16x16() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMeanInt32x8(t *testing.T) {\n\trequireAVX2(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []int32\n\t}{\n\t\t{\"empty\", []int32{}},\n\t\t{\"single\", []int32{42}},\n\t\t{\"small\", []int32{1, 2, 3, 4, 5}},\n\t\t{\"exactly 8\", make([]int32, 8)},\n\t\t{\"large\", make([]int32, 1000)},\n\t\t{\"negative\", []int32{-1, -2, -3, 4, 5}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = int32(rand.Int32())\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MeanInt32x8(tc.input)\n\t\t\twant := lo.Mean(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MeanInt32x8() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMeanInt64x4(t *testing.T) {\n\trequireAVX2(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []int64\n\t}{\n\t\t{\"empty\", []int64{}},\n\t\t{\"single\", []int64{42}},\n\t\t{\"small\", []int64{1, 2, 3, 4, 5}},\n\t\t{\"exactly 4\", make([]int64, 4)},\n\t\t{\"large\", make([]int64, 1000)},\n\t\t{\"negative\", []int64{-1, -2, -3, 4, 5}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Int64()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MeanInt64x4(tc.input)\n\t\t\twant := lo.Mean(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MeanInt64x4() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMeanUint8x32(t *testing.T) {\n\trequireAVX2(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []uint8\n\t}{\n\t\t{\"empty\", []uint8{}},\n\t\t{\"single\", []uint8{42}},\n\t\t{\"small\", []uint8{1, 2, 3, 4, 5}},\n\t\t{\"exactly 32\", make([]uint8, 32)},\n\t\t{\"large\", make([]uint8, 1000)},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = uint8(rand.IntN(256))\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MeanUint8x32(tc.input)\n\t\t\twant := lo.Mean(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MeanUint8x32() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMeanUint16x16(t *testing.T) {\n\trequireAVX2(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []uint16\n\t}{\n\t\t{\"empty\", []uint16{}},\n\t\t{\"single\", []uint16{42}},\n\t\t{\"small\", []uint16{1, 2, 3, 4, 5}},\n\t\t{\"exactly 16\", make([]uint16, 16)},\n\t\t{\"large\", make([]uint16, 1000)},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = uint16(rand.IntN(65536))\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MeanUint16x16(tc.input)\n\t\t\twant := lo.Mean(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MeanUint16x16() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMeanUint32x8(t *testing.T) {\n\trequireAVX2(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []uint32\n\t}{\n\t\t{\"empty\", []uint32{}},\n\t\t{\"single\", []uint32{42}},\n\t\t{\"small\", []uint32{1, 2, 3, 4, 5}},\n\t\t{\"exactly 8\", make([]uint32, 8)},\n\t\t{\"large\", make([]uint32, 1000)},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Uint32()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MeanUint32x8(tc.input)\n\t\t\twant := lo.Mean(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MeanUint32x8() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMeanUint64x4(t *testing.T) {\n\trequireAVX2(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []uint64\n\t}{\n\t\t{\"empty\", []uint64{}},\n\t\t{\"single\", []uint64{42}},\n\t\t{\"small\", []uint64{1, 2, 3, 4, 5}},\n\t\t{\"exactly 4\", make([]uint64, 4)},\n\t\t{\"large\", make([]uint64, 1000)},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Uint64()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MeanUint64x4(tc.input)\n\t\t\twant := lo.Mean(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MeanUint64x4() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMeanFloat32x8(t *testing.T) {\n\trequireAVX2(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []float32\n\t}{\n\t\t{\"empty\", []float32{}},\n\t\t{\"single\", []float32{42.5}},\n\t\t{\"small\", []float32{1.1, 2.2, 3.3, 4.4, 5.5}},\n\t\t{\"exactly 8\", make([]float32, 8)},\n\t\t{\"large\", make([]float32, 1000)},\n\t\t{\"negative\", []float32{-1.1, -2.2, 3.3, 4.4}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Float32()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MeanFloat32x8(tc.input)\n\t\t\twant := lo.Mean(tc.input)\n\n\t\t\tconst epsilon = 1e-3\n\t\t\tif diff := got - want; diff < -epsilon || diff > epsilon {\n\t\t\t\tt.Errorf(\"MeanFloat32x8() = %v, want %v (diff: %v)\", got, want, diff)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMeanFloat64x4(t *testing.T) {\n\trequireAVX2(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []float64\n\t}{\n\t\t{\"empty\", []float64{}},\n\t\t{\"single\", []float64{42.5}},\n\t\t{\"small\", []float64{1.1, 2.2, 3.3, 4.4, 5.5}},\n\t\t{\"exactly 4\", make([]float64, 4)},\n\t\t{\"large\", make([]float64, 1000)},\n\t\t{\"negative\", []float64{-1.1, -2.2, 3.3, 4.4}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Float64()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MeanFloat64x4(tc.input)\n\t\t\twant := lo.Mean(tc.input)\n\n\t\t\tconst epsilon = 1e-3\n\t\t\tif diff := got - want; diff < -epsilon || diff > epsilon {\n\t\t\t\tt.Errorf(\"MeanFloat64x4() = %v, want %v (diff: %v)\", got, want, diff)\n\t\t\t}\n\t\t})\n\t}\n}\n\n// Test type aliases work correctly\nfunc TestAVX2MeanTypeAlias(t *testing.T) {\n\trequireAVX2(t)\n\tinput := []myInt16{1, 2, 3, 4, 5}\n\tgot := MeanInt16x16(input)\n\twant := lo.Mean(input)\n\n\tif got != want {\n\t\tt.Errorf(\"MeanInt16x16() with type alias = %v, want %v\", got, want)\n\t}\n}\n\nfunc TestClampInt8x32(t *testing.T) {\n\trequireAVX2(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []int8\n\t\tmin   int8\n\t\tmax   int8\n\t}{\n\t\t{\"empty\", []int8{}, -10, 10},\n\t\t{\"single\", []int8{42}, -10, 10},\n\t\t{\"small\", []int8{1, 2, 3, 4, 5}, 2, 4},\n\t\t{\"exactly 32\", make([]int8, 32), 5, 10},\n\t\t{\"large\", make([]int8, 1000), -5, 5},\n\t\t{\"all below min\", []int8{-10, -20, -30}, -5, 10},\n\t\t{\"all above max\", []int8{20, 30, 40}, -10, 10},\n\t\t{\"already clamped\", []int8{5, 6, 7}, 5, 10},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = int8(rand.IntN(256) - 128)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := ClampInt8x32(tc.input, tc.min, tc.max)\n\n\t\t\tif len(got) != len(tc.input) {\n\t\t\t\tt.Errorf(\"ClampInt8x32() returned length %d, want %d\", len(got), len(tc.input))\n\t\t\t}\n\n\t\t\tfor i, v := range got {\n\t\t\t\tif v < tc.min || v > tc.max {\n\t\t\t\t\tt.Errorf(\"ClampInt8x32()[%d] = %v, outside range [%v, %v]\", i, v, tc.min, tc.max)\n\t\t\t\t}\n\t\t\t\toriginal := tc.input[i]\n\t\t\t\texpected := original\n\t\t\t\tif expected < tc.min {\n\t\t\t\t\texpected = tc.min\n\t\t\t\t} else if expected > tc.max {\n\t\t\t\t\texpected = tc.max\n\t\t\t\t}\n\t\t\t\tif v != expected {\n\t\t\t\t\tt.Errorf(\"ClampInt8x32()[%d] = %v, want %v (original: %v)\", i, v, expected, original)\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestClampInt16x16(t *testing.T) {\n\trequireAVX2(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []int16\n\t\tmin   int16\n\t\tmax   int16\n\t}{\n\t\t{\"empty\", []int16{}, -100, 100},\n\t\t{\"single\", []int16{42}, -10, 10},\n\t\t{\"small\", []int16{1, 2, 3, 4, 5}, 2, 4},\n\t\t{\"exactly 16\", make([]int16, 16), 50, 100},\n\t\t{\"large\", make([]int16, 1000), -50, 50},\n\t\t{\"all below min\", []int16{-100, -200, -300}, -50, 100},\n\t\t{\"all above max\", []int16{200, 300, 400}, -100, 100},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = int16(rand.IntN(65536) - 32768)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := ClampInt16x16(tc.input, tc.min, tc.max)\n\n\t\t\tif len(got) != len(tc.input) {\n\t\t\t\tt.Errorf(\"ClampInt16x16() returned length %d, want %d\", len(got), len(tc.input))\n\t\t\t}\n\n\t\t\tfor i, v := range got {\n\t\t\t\tif v < tc.min || v > tc.max {\n\t\t\t\t\tt.Errorf(\"ClampInt16x16()[%d] = %v, outside range [%v, %v]\", i, v, tc.min, tc.max)\n\t\t\t\t}\n\t\t\t\toriginal := tc.input[i]\n\t\t\t\texpected := original\n\t\t\t\tif expected < tc.min {\n\t\t\t\t\texpected = tc.min\n\t\t\t\t} else if expected > tc.max {\n\t\t\t\t\texpected = tc.max\n\t\t\t\t}\n\t\t\t\tif v != expected {\n\t\t\t\t\tt.Errorf(\"ClampInt16x16()[%d] = %v, want %v (original: %v)\", i, v, expected, original)\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestClampInt32x8(t *testing.T) {\n\trequireAVX2(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []int32\n\t\tmin   int32\n\t\tmax   int32\n\t}{\n\t\t{\"empty\", []int32{}, -100, 100},\n\t\t{\"single\", []int32{42}, -10, 10},\n\t\t{\"small\", []int32{1, 2, 3, 4, 5}, 2, 4},\n\t\t{\"exactly 8\", make([]int32, 8), 50, 100},\n\t\t{\"large\", make([]int32, 1000), -50, 50},\n\t\t{\"negative range\", []int32{-100, -50, 0, 50, 100}, -30, -10},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Int32()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := ClampInt32x8(tc.input, tc.min, tc.max)\n\n\t\t\tif len(got) != len(tc.input) {\n\t\t\t\tt.Errorf(\"ClampInt32x8() returned length %d, want %d\", len(got), len(tc.input))\n\t\t\t}\n\n\t\t\tfor i, v := range got {\n\t\t\t\tif v < tc.min || v > tc.max {\n\t\t\t\t\tt.Errorf(\"ClampInt32x8()[%d] = %v, outside range [%v, %v]\", i, v, tc.min, tc.max)\n\t\t\t\t}\n\t\t\t\toriginal := tc.input[i]\n\t\t\t\texpected := original\n\t\t\t\tif expected < tc.min {\n\t\t\t\t\texpected = tc.min\n\t\t\t\t} else if expected > tc.max {\n\t\t\t\t\texpected = tc.max\n\t\t\t\t}\n\t\t\t\tif v != expected {\n\t\t\t\t\tt.Errorf(\"ClampInt32x8()[%d] = %v, want %v (original: %v)\", i, v, expected, original)\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestClampInt64x4(t *testing.T) {\n\trequireAVX2(t)\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []int64\n\t\tmin   int64\n\t\tmax   int64\n\t}{\n\t\t{\"empty\", []int64{}, -100, 100},\n\t\t{\"single\", []int64{42}, -10, 10},\n\t\t{\"small\", []int64{1, 2, 3, 4, 5}, 2, 4},\n\t\t{\"exactly 4\", make([]int64, 4), 50, 100},\n\t\t{\"large\", make([]int64, 1000), -50, 50},\n\t\t{\"all below min\", []int64{-1000, -2000, -3000}, -500, 100},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Int64()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := ClampInt64x4(tc.input, tc.min, tc.max)\n\n\t\t\tif len(got) != len(tc.input) {\n\t\t\t\tt.Errorf(\"ClampInt64x4() returned length %d, want %d\", len(got), len(tc.input))\n\t\t\t}\n\n\t\t\tfor i, v := range got {\n\t\t\t\tif v < tc.min || v > tc.max {\n\t\t\t\t\tt.Errorf(\"ClampInt64x4()[%d] = %v, outside range [%v, %v]\", i, v, tc.min, tc.max)\n\t\t\t\t}\n\t\t\t\toriginal := tc.input[i]\n\t\t\t\texpected := original\n\t\t\t\tif expected < tc.min {\n\t\t\t\t\texpected = tc.min\n\t\t\t\t} else if expected > tc.max {\n\t\t\t\t\texpected = tc.max\n\t\t\t\t}\n\t\t\t\tif v != expected {\n\t\t\t\t\tt.Errorf(\"ClampInt64x4()[%d] = %v, want %v (original: %v)\", i, v, expected, original)\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestClampUint8x32(t *testing.T) {\n\trequireAVX2(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []uint8\n\t\tmin   uint8\n\t\tmax   uint8\n\t}{\n\t\t{\"empty\", []uint8{}, 10, 100},\n\t\t{\"single\", []uint8{42}, 10, 100},\n\t\t{\"small\", []uint8{1, 2, 3, 4, 5}, 2, 4},\n\t\t{\"exactly 32\", make([]uint8, 32), 50, 100},\n\t\t{\"large\", make([]uint8, 1000), 50, 200},\n\t\t{\"all below min\", []uint8{1, 2, 3}, 10, 100},\n\t\t{\"all above max\", []uint8{200, 225, 250}, 50, 150},\n\t\t{\"max values\", []uint8{255, 255, 255}, 100, 200},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = uint8(rand.IntN(256))\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := ClampUint8x32(tc.input, tc.min, tc.max)\n\n\t\t\tif len(got) != len(tc.input) {\n\t\t\t\tt.Errorf(\"ClampUint8x32() returned length %d, want %d\", len(got), len(tc.input))\n\t\t\t}\n\n\t\t\tfor i, v := range got {\n\t\t\t\tif v < tc.min || v > tc.max {\n\t\t\t\t\tt.Errorf(\"ClampUint8x32()[%d] = %v, outside range [%v, %v]\", i, v, tc.min, tc.max)\n\t\t\t\t}\n\t\t\t\toriginal := tc.input[i]\n\t\t\t\texpected := original\n\t\t\t\tif expected < tc.min {\n\t\t\t\t\texpected = tc.min\n\t\t\t\t} else if expected > tc.max {\n\t\t\t\t\texpected = tc.max\n\t\t\t\t}\n\t\t\t\tif v != expected {\n\t\t\t\t\tt.Errorf(\"ClampUint8x32()[%d] = %v, want %v (original: %v)\", i, v, expected, original)\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestClampUint16x16(t *testing.T) {\n\trequireAVX2(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []uint16\n\t\tmin   uint16\n\t\tmax   uint16\n\t}{\n\t\t{\"empty\", []uint16{}, 100, 1000},\n\t\t{\"single\", []uint16{42}, 10, 100},\n\t\t{\"small\", []uint16{1, 2, 3, 4, 5}, 2, 4},\n\t\t{\"exactly 16\", make([]uint16, 16), 500, 1000},\n\t\t{\"large\", make([]uint16, 1000), 500, 5000},\n\t\t{\"all below min\", []uint16{1, 2, 3}, 10, 100},\n\t\t{\"all above max\", []uint16{2000, 3000, 4000}, 100, 1000},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = uint16(rand.IntN(65536))\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := ClampUint16x16(tc.input, tc.min, tc.max)\n\n\t\t\tif len(got) != len(tc.input) {\n\t\t\t\tt.Errorf(\"ClampUint16x16() returned length %d, want %d\", len(got), len(tc.input))\n\t\t\t}\n\n\t\t\tfor i, v := range got {\n\t\t\t\tif v < tc.min || v > tc.max {\n\t\t\t\t\tt.Errorf(\"ClampUint16x16()[%d] = %v, outside range [%v, %v]\", i, v, tc.min, tc.max)\n\t\t\t\t}\n\t\t\t\toriginal := tc.input[i]\n\t\t\t\texpected := original\n\t\t\t\tif expected < tc.min {\n\t\t\t\t\texpected = tc.min\n\t\t\t\t} else if expected > tc.max {\n\t\t\t\t\texpected = tc.max\n\t\t\t\t}\n\t\t\t\tif v != expected {\n\t\t\t\t\tt.Errorf(\"ClampUint16x16()[%d] = %v, want %v (original: %v)\", i, v, expected, original)\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestClampUint32x8(t *testing.T) {\n\trequireAVX2(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []uint32\n\t\tmin   uint32\n\t\tmax   uint32\n\t}{\n\t\t{\"empty\", []uint32{}, 100, 1000},\n\t\t{\"single\", []uint32{42}, 10, 100},\n\t\t{\"small\", []uint32{1, 2, 3, 4, 5}, 2, 4},\n\t\t{\"exactly 8\", make([]uint32, 8), 500, 1000},\n\t\t{\"large\", make([]uint32, 1000), 500, 5000},\n\t\t{\"all below min\", []uint32{1, 2, 3}, 10, 100},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Uint32()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := ClampUint32x8(tc.input, tc.min, tc.max)\n\n\t\t\tif len(got) != len(tc.input) {\n\t\t\t\tt.Errorf(\"ClampUint32x8() returned length %d, want %d\", len(got), len(tc.input))\n\t\t\t}\n\n\t\t\tfor i, v := range got {\n\t\t\t\tif v < tc.min || v > tc.max {\n\t\t\t\t\tt.Errorf(\"ClampUint32x8()[%d] = %v, outside range [%v, %v]\", i, v, tc.min, tc.max)\n\t\t\t\t}\n\t\t\t\toriginal := tc.input[i]\n\t\t\t\texpected := original\n\t\t\t\tif expected < tc.min {\n\t\t\t\t\texpected = tc.min\n\t\t\t\t} else if expected > tc.max {\n\t\t\t\t\texpected = tc.max\n\t\t\t\t}\n\t\t\t\tif v != expected {\n\t\t\t\t\tt.Errorf(\"ClampUint32x8()[%d] = %v, want %v (original: %v)\", i, v, expected, original)\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestClampUint64x4(t *testing.T) {\n\trequireAVX2(t)\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []uint64\n\t\tmin   uint64\n\t\tmax   uint64\n\t}{\n\t\t{\"empty\", []uint64{}, 100, 1000},\n\t\t{\"single\", []uint64{42}, 10, 100},\n\t\t{\"small\", []uint64{1, 2, 3, 4, 5}, 2, 4},\n\t\t{\"exactly 4\", make([]uint64, 4), 500, 1000},\n\t\t{\"large\", make([]uint64, 1000), 500, 5000},\n\t\t{\"all below min\", []uint64{1, 2, 3}, 10, 100},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Uint64()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := ClampUint64x4(tc.input, tc.min, tc.max)\n\n\t\t\tif len(got) != len(tc.input) {\n\t\t\t\tt.Errorf(\"ClampUint64x4() returned length %d, want %d\", len(got), len(tc.input))\n\t\t\t}\n\n\t\t\tfor i, v := range got {\n\t\t\t\tif v < tc.min || v > tc.max {\n\t\t\t\t\tt.Errorf(\"ClampUint64x4()[%d] = %v, outside range [%v, %v]\", i, v, tc.min, tc.max)\n\t\t\t\t}\n\t\t\t\toriginal := tc.input[i]\n\t\t\t\texpected := original\n\t\t\t\tif expected < tc.min {\n\t\t\t\t\texpected = tc.min\n\t\t\t\t} else if expected > tc.max {\n\t\t\t\t\texpected = tc.max\n\t\t\t\t}\n\t\t\t\tif v != expected {\n\t\t\t\t\tt.Errorf(\"ClampUint64x4()[%d] = %v, want %v (original: %v)\", i, v, expected, original)\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestClampFloat32x8(t *testing.T) {\n\trequireAVX2(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []float32\n\t\tmin   float32\n\t\tmax   float32\n\t}{\n\t\t{\"empty\", []float32{}, -10.0, 10.0},\n\t\t{\"single\", []float32{42.5}, -10.0, 10.0},\n\t\t{\"small\", []float32{1.1, 2.2, 3.3, 4.4, 5.5}, 2.0, 4.0},\n\t\t{\"exactly 8\", make([]float32, 8), -5.0, 10.0},\n\t\t{\"large\", make([]float32, 1000), -5.0, 5.0},\n\t\t{\"negative range\", []float32{-10.0, -5.0, 0.0, 5.0, 10.0}, -3.0, -1.0},\n\t\t{\"all below min\", []float32{-20.0, -30.0, -40.0}, -10.0, 10.0},\n\t\t{\"all above max\", []float32{20.0, 30.0, 40.0}, -10.0, 10.0},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Float32()*200 - 100\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := ClampFloat32x8(tc.input, tc.min, tc.max)\n\n\t\t\tif len(got) != len(tc.input) {\n\t\t\t\tt.Errorf(\"ClampFloat32x8() returned length %d, want %d\", len(got), len(tc.input))\n\t\t\t}\n\n\t\t\tconst epsilon = 1e-3\n\t\t\tfor i, v := range got {\n\t\t\t\tif v < tc.min-epsilon || v > tc.max+epsilon {\n\t\t\t\t\tt.Errorf(\"ClampFloat32x8()[%d] = %v, outside range [%v, %v]\", i, v, tc.min, tc.max)\n\t\t\t\t}\n\t\t\t\toriginal := tc.input[i]\n\t\t\t\texpected := original\n\t\t\t\tif expected < tc.min {\n\t\t\t\t\texpected = tc.min\n\t\t\t\t} else if expected > tc.max {\n\t\t\t\t\texpected = tc.max\n\t\t\t\t}\n\t\t\t\tif diff := v - expected; diff < -epsilon || diff > epsilon {\n\t\t\t\t\tt.Errorf(\"ClampFloat32x8()[%d] = %v, want %v (original: %v, diff: %v)\", i, v, expected, original, diff)\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestClampFloat64x4(t *testing.T) {\n\trequireAVX2(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []float64\n\t\tmin   float64\n\t\tmax   float64\n\t}{\n\t\t{\"empty\", []float64{}, -10.0, 10.0},\n\t\t{\"single\", []float64{42.5}, -10.0, 10.0},\n\t\t{\"small\", []float64{1.1, 2.2, 3.3, 4.4, 5.5}, 2.0, 4.0},\n\t\t{\"exactly 4\", make([]float64, 4), -5.0, 10.0},\n\t\t{\"large\", make([]float64, 1000), -5.0, 5.0},\n\t\t{\"negative range\", []float64{-10.0, -5.0, 0.0, 5.0, 10.0}, -3.0, -1.0},\n\t\t{\"all below min\", []float64{-20.0, -30.0, -40.0}, -10.0, 10.0},\n\t\t{\"all above max\", []float64{20.0, 30.0, 40.0}, -10.0, 10.0},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Float64()*200 - 100\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := ClampFloat64x4(tc.input, tc.min, tc.max)\n\n\t\t\tif len(got) != len(tc.input) {\n\t\t\t\tt.Errorf(\"ClampFloat64x4() returned length %d, want %d\", len(got), len(tc.input))\n\t\t\t}\n\n\t\t\tconst epsilon = 1e-3\n\t\t\tfor i, v := range got {\n\t\t\t\tif v < tc.min-epsilon || v > tc.max+epsilon {\n\t\t\t\t\tt.Errorf(\"ClampFloat64x4()[%d] = %v, outside range [%v, %v]\", i, v, tc.min, tc.max)\n\t\t\t\t}\n\t\t\t\toriginal := tc.input[i]\n\t\t\t\texpected := original\n\t\t\t\tif expected < tc.min {\n\t\t\t\t\texpected = tc.min\n\t\t\t\t} else if expected > tc.max {\n\t\t\t\t\texpected = tc.max\n\t\t\t\t}\n\t\t\t\tif diff := v - expected; diff < -epsilon || diff > epsilon {\n\t\t\t\t\tt.Errorf(\"ClampFloat64x4()[%d] = %v, want %v (original: %v, diff: %v)\", i, v, expected, original, diff)\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\n// Test type aliases work correctly\nfunc TestAVX2ClampTypeAlias(t *testing.T) {\n\trequireAVX2(t)\n\tinput := []myInt32{-5, 0, 10, 15, 20}\n\tmin := myInt32(0)\n\tmax := myInt32(10)\n\tgot := ClampInt32x8(input, min, max)\n\n\tfor i, v := range got {\n\t\tif v < min || v > max {\n\t\t\tt.Errorf(\"ClampInt32x8()[%d] with type alias = %v, outside range [%v, %v]\", i, v, min, max)\n\t\t}\n\t\toriginal := input[i]\n\t\texpected := original\n\t\tif expected < min {\n\t\t\texpected = min\n\t\t} else if expected > max {\n\t\t\texpected = max\n\t\t}\n\t\tif v != expected {\n\t\t\tt.Errorf(\"ClampInt32x8()[%d] with type alias = %v, want %v (original: %v)\", i, v, expected, original)\n\t\t}\n\t}\n}\n\nfunc TestMinInt8x32(t *testing.T) {\n\trequireAVX2(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []int8\n\t}{\n\t\t{\"empty\", []int8{}},\n\t\t{\"single\", []int8{42}},\n\t\t{\"small\", []int8{1, 2, 3, 4, 5}},\n\t\t{\"exactly 32\", make([]int8, 32)},\n\t\t{\"large\", make([]int8, 1000)},\n\t\t{\"negative\", []int8{-1, -2, -3, 4, 5}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = int8(rand.IntN(256) - 128)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MinInt8x32(tc.input)\n\t\t\twant := lo.Min(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MinInt8x32() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMinInt16x16(t *testing.T) {\n\trequireAVX2(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []int16\n\t}{\n\t\t{\"empty\", []int16{}},\n\t\t{\"single\", []int16{42}},\n\t\t{\"small\", []int16{1, 2, 3, 4, 5}},\n\t\t{\"exactly 16\", make([]int16, 16)},\n\t\t{\"large\", make([]int16, 1000)},\n\t\t{\"negative\", []int16{-1, -2, -3, 4, 5}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = int16(rand.IntN(65536) - 32768)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MinInt16x16(tc.input)\n\t\t\twant := lo.Min(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MinInt16x16() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMinInt32x8(t *testing.T) {\n\trequireAVX2(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []int32\n\t}{\n\t\t{\"empty\", []int32{}},\n\t\t{\"single\", []int32{42}},\n\t\t{\"small\", []int32{1, 2, 3, 4, 5}},\n\t\t{\"exactly 8\", make([]int32, 8)},\n\t\t{\"large\", make([]int32, 1000)},\n\t\t{\"negative\", []int32{-1, -2, -3, 4, 5}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Int32()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MinInt32x8(tc.input)\n\t\t\twant := lo.Min(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MinInt32x8() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMinInt64x4(t *testing.T) {\n\trequireAVX2(t)\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []int64\n\t}{\n\t\t{\"empty\", []int64{}},\n\t\t{\"single\", []int64{42}},\n\t\t{\"small\", []int64{1, 2, 3, 4, 5}},\n\t\t{\"exactly 4\", make([]int64, 4)},\n\t\t{\"large\", make([]int64, 1000)},\n\t\t{\"negative\", []int64{-1, -2, -3, 4, 5}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Int64()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MinInt64x4(tc.input)\n\t\t\twant := lo.Min(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MinInt64x4() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMinUint8x32(t *testing.T) {\n\trequireAVX2(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []uint8\n\t}{\n\t\t{\"empty\", []uint8{}},\n\t\t{\"single\", []uint8{42}},\n\t\t{\"small\", []uint8{1, 2, 3, 4, 5}},\n\t\t{\"exactly 32\", make([]uint8, 32)},\n\t\t{\"large\", make([]uint8, 1000)},\n\t\t{\"max values\", []uint8{255, 100, 50}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = uint8(rand.IntN(256))\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MinUint8x32(tc.input)\n\t\t\twant := lo.Min(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MinUint8x32() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMinUint16x16(t *testing.T) {\n\trequireAVX2(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []uint16\n\t}{\n\t\t{\"empty\", []uint16{}},\n\t\t{\"single\", []uint16{42}},\n\t\t{\"small\", []uint16{1, 2, 3, 4, 5}},\n\t\t{\"exactly 16\", make([]uint16, 16)},\n\t\t{\"large\", make([]uint16, 1000)},\n\t\t{\"max values\", []uint16{65535, 1000, 500}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = uint16(rand.IntN(65536))\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MinUint16x16(tc.input)\n\t\t\twant := lo.Min(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MinUint16x16() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMinUint32x8(t *testing.T) {\n\trequireAVX2(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []uint32\n\t}{\n\t\t{\"empty\", []uint32{}},\n\t\t{\"single\", []uint32{42}},\n\t\t{\"small\", []uint32{1, 2, 3, 4, 5}},\n\t\t{\"exactly 8\", make([]uint32, 8)},\n\t\t{\"large\", make([]uint32, 1000)},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Uint32()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MinUint32x8(tc.input)\n\t\t\twant := lo.Min(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MinUint32x8() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMinUint64x4(t *testing.T) {\n\trequireAVX2(t)\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []uint64\n\t}{\n\t\t{\"empty\", []uint64{}},\n\t\t{\"single\", []uint64{42}},\n\t\t{\"small\", []uint64{1, 2, 3, 4, 5}},\n\t\t{\"exactly 4\", make([]uint64, 4)},\n\t\t{\"large\", make([]uint64, 1000)},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Uint64()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MinUint64x4(tc.input)\n\t\t\twant := lo.Min(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MinUint64x4() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMinFloat32x8(t *testing.T) {\n\trequireAVX2(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []float32\n\t}{\n\t\t{\"empty\", []float32{}},\n\t\t{\"single\", []float32{42.5}},\n\t\t{\"small\", []float32{1.1, 2.2, 3.3, 4.4, 5.5}},\n\t\t{\"exactly 8\", make([]float32, 8)},\n\t\t{\"large\", make([]float32, 1000)},\n\t\t{\"negative\", []float32{-1.1, -2.2, 3.3, 4.4}},\n\t\t{\"zeros\", []float32{0, 0, 0, 0}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Float32()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MinFloat32x8(tc.input)\n\t\t\twant := lo.Min(tc.input)\n\n\t\t\tconst epsilon = 1e-3\n\t\t\tif diff := got - want; diff < -epsilon || diff > epsilon {\n\t\t\t\tt.Errorf(\"MinFloat32x8() = %v, want %v (diff: %v)\", got, want, diff)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMinFloat64x4(t *testing.T) {\n\trequireAVX2(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []float64\n\t}{\n\t\t{\"empty\", []float64{}},\n\t\t{\"single\", []float64{42.5}},\n\t\t{\"small\", []float64{1.1, 2.2, 3.3, 4.4, 5.5}},\n\t\t{\"exactly 4\", []float64{1.0, 2.0, 3.0, 4.0}},\n\t\t{\"large\", make([]float64, 1000)},\n\t\t{\"negative\", []float64{-1.1, -2.2, 3.3, 4.4}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Float64()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MinFloat64x4(tc.input)\n\t\t\twant := lo.Min(tc.input)\n\n\t\t\tconst epsilon = 1e-3\n\t\t\tif diff := got - want; diff < -epsilon || diff > epsilon {\n\t\t\t\tt.Errorf(\"MinFloat64x4() = %v, want %v (diff: %v)\", got, want, diff)\n\t\t\t}\n\t\t})\n\t}\n}\n\n// Test type aliases work correctly\nfunc TestAVX2MinTypeAlias(t *testing.T) {\n\trequireAVX2(t)\n\tinput := []myInt32{5, 2, 8, 1, 9}\n\tgot := MinInt32x8(input)\n\twant := myInt32(1)\n\n\tif got != want {\n\t\tt.Errorf(\"MinInt32x8() with type alias = %v, want %v\", got, want)\n\t}\n}\n\nfunc TestMaxInt8x32(t *testing.T) {\n\trequireAVX2(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []int8\n\t}{\n\t\t{\"empty\", []int8{}},\n\t\t{\"single\", []int8{42}},\n\t\t{\"small\", []int8{1, 2, 3, 4, 5}},\n\t\t{\"exactly 32\", make([]int8, 32)},\n\t\t{\"large\", make([]int8, 1000)},\n\t\t{\"negative\", []int8{-1, -2, -3, 4, 5}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = int8(rand.IntN(256) - 128)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MaxInt8x32(tc.input)\n\t\t\twant := lo.Max(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MaxInt8x32() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMaxInt16x16(t *testing.T) {\n\trequireAVX2(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []int16\n\t}{\n\t\t{\"empty\", []int16{}},\n\t\t{\"single\", []int16{42}},\n\t\t{\"small\", []int16{1, 2, 3, 4, 5}},\n\t\t{\"exactly 16\", make([]int16, 16)},\n\t\t{\"large\", make([]int16, 1000)},\n\t\t{\"negative\", []int16{-1, -2, -3, 4, 5}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = int16(rand.IntN(65536) - 32768)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MaxInt16x16(tc.input)\n\t\t\twant := lo.Max(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MaxInt16x16() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMaxInt32x8(t *testing.T) {\n\trequireAVX2(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []int32\n\t}{\n\t\t{\"empty\", []int32{}},\n\t\t{\"single\", []int32{42}},\n\t\t{\"small\", []int32{1, 2, 3, 4, 5}},\n\t\t{\"exactly 8\", make([]int32, 8)},\n\t\t{\"large\", make([]int32, 1000)},\n\t\t{\"negative\", []int32{-1, -2, -3, 4, 5}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Int32()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MaxInt32x8(tc.input)\n\t\t\twant := lo.Max(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MaxInt32x8() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMaxInt64x4(t *testing.T) {\n\trequireAVX2(t)\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []int64\n\t}{\n\t\t{\"empty\", []int64{}},\n\t\t{\"single\", []int64{42}},\n\t\t{\"small\", []int64{1, 2, 3, 4, 5}},\n\t\t{\"exactly 4\", make([]int64, 4)},\n\t\t{\"large\", make([]int64, 1000)},\n\t\t{\"negative\", []int64{-1, -2, -3, 4, 5}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Int64()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MaxInt64x4(tc.input)\n\t\t\twant := lo.Max(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MaxInt64x4() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMaxUint8x32(t *testing.T) {\n\trequireAVX2(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []uint8\n\t}{\n\t\t{\"empty\", []uint8{}},\n\t\t{\"single\", []uint8{42}},\n\t\t{\"small\", []uint8{1, 2, 3, 4, 5}},\n\t\t{\"exactly 32\", make([]uint8, 32)},\n\t\t{\"large\", make([]uint8, 1000)},\n\t\t{\"max values\", []uint8{255, 100, 50}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = uint8(rand.IntN(256))\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MaxUint8x32(tc.input)\n\t\t\twant := lo.Max(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MaxUint8x32() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMaxUint16x16(t *testing.T) {\n\trequireAVX2(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []uint16\n\t}{\n\t\t{\"empty\", []uint16{}},\n\t\t{\"single\", []uint16{42}},\n\t\t{\"small\", []uint16{1, 2, 3, 4, 5}},\n\t\t{\"exactly 16\", make([]uint16, 16)},\n\t\t{\"large\", make([]uint16, 1000)},\n\t\t{\"max values\", []uint16{65535, 1000, 500}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = uint16(rand.IntN(65536))\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MaxUint16x16(tc.input)\n\t\t\twant := lo.Max(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MaxUint16x16() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMaxUint32x8(t *testing.T) {\n\trequireAVX2(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []uint32\n\t}{\n\t\t{\"empty\", []uint32{}},\n\t\t{\"single\", []uint32{42}},\n\t\t{\"small\", []uint32{1, 2, 3, 4, 5}},\n\t\t{\"exactly 8\", make([]uint32, 8)},\n\t\t{\"large\", make([]uint32, 1000)},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Uint32()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MaxUint32x8(tc.input)\n\t\t\twant := lo.Max(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MaxUint32x8() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMaxUint64x4(t *testing.T) {\n\trequireAVX2(t)\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []uint64\n\t}{\n\t\t{\"empty\", []uint64{}},\n\t\t{\"single\", []uint64{42}},\n\t\t{\"small\", []uint64{1, 2, 3, 4, 5}},\n\t\t{\"exactly 4\", make([]uint64, 4)},\n\t\t{\"large\", make([]uint64, 1000)},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Uint64()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MaxUint64x4(tc.input)\n\t\t\twant := lo.Max(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MaxUint64x4() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMaxFloat32x8(t *testing.T) {\n\trequireAVX2(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []float32\n\t}{\n\t\t{\"empty\", []float32{}},\n\t\t{\"single\", []float32{42.5}},\n\t\t{\"small\", []float32{1.1, 2.2, 3.3, 4.4, 5.5}},\n\t\t{\"exactly 8\", make([]float32, 8)},\n\t\t{\"large\", make([]float32, 1000)},\n\t\t{\"negative\", []float32{-1.1, -2.2, 3.3, 4.4}},\n\t\t{\"zeros\", []float32{0, 0, 0, 0}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Float32()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MaxFloat32x8(tc.input)\n\t\t\twant := lo.Max(tc.input)\n\n\t\t\tconst epsilon = 1e-3\n\t\t\tif diff := got - want; diff < -epsilon || diff > epsilon {\n\t\t\t\tt.Errorf(\"MaxFloat32x8() = %v, want %v (diff: %v)\", got, want, diff)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMaxFloat64x4(t *testing.T) {\n\trequireAVX2(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []float64\n\t}{\n\t\t{\"empty\", []float64{}},\n\t\t{\"single\", []float64{42.5}},\n\t\t{\"small\", []float64{1.1, 2.2, 3.3, 4.4, 5.5}},\n\t\t{\"exactly 4\", []float64{1.0, 2.0, 3.0, 4.0}},\n\t\t{\"large\", make([]float64, 1000)},\n\t\t{\"negative\", []float64{-1.1, -2.2, 3.3, 4.4}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Float64()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MaxFloat64x4(tc.input)\n\t\t\twant := lo.Max(tc.input)\n\n\t\t\tconst epsilon = 1e-3\n\t\t\tif diff := got - want; diff < -epsilon || diff > epsilon {\n\t\t\t\tt.Errorf(\"MaxFloat64x4() = %v, want %v (diff: %v)\", got, want, diff)\n\t\t\t}\n\t\t})\n\t}\n}\n\n// Test type aliases work correctly\nfunc TestAVX2MaxTypeAlias(t *testing.T) {\n\trequireAVX2(t)\n\tinput := []myInt32{5, 2, 8, 1, 9}\n\tgot := MaxInt32x8(input)\n\twant := myInt32(9)\n\n\tif got != want {\n\t\tt.Errorf(\"MaxInt32x8() with type alias = %v, want %v\", got, want)\n\t}\n}\n\n// SumBy tests\n\ntype avx2Item struct {\n\tValue      int8\n\tWeight     int8\n\tMultiplier int8\n}\n\nfunc TestSumByInt8x32(t *testing.T) {\n\trequireAVX2(t)\n\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []avx2Item\n\t}{\n\t\t{\"empty\", []avx2Item{}},\n\t\t{\"single\", []avx2Item{{Value: 42}}},\n\t\t{\"small\", []avx2Item{{Value: 1}, {Value: 2}, {Value: 3}, {Value: 4}, {Value: 5}}},\n\t\t{\"exactly 32\", make([]avx2Item, 32)},\n\t\t{\"large\", make([]avx2Item, 1000)},\n\t\t{\"negative\", []avx2Item{{Value: -1}, {Value: -2}, {Value: -3}, {Value: 4}, {Value: 5}}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0].Value == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i].Value = int8(rand.IntN(256) - 128)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Using Value field as the iteratee\n\t\t\tgot := SumByInt8x32(tc.input, func(i avx2Item) int8 { return i.Value })\n\t\t\twant := lo.Sum(lo.Map(tc.input, func(i avx2Item, _ int) int8 { return i.Value }))\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"SumByInt8x32() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestSumByInt16x16(t *testing.T) {\n\trequireAVX2(t)\n\n\ttype avx2ItemInt16 struct {\n\t\tValue int16\n\t}\n\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []avx2ItemInt16\n\t}{\n\t\t{\"empty\", []avx2ItemInt16{}},\n\t\t{\"single\", []avx2ItemInt16{{Value: 42}}},\n\t\t{\"small\", []avx2ItemInt16{{1}, {2}, {3}, {4}, {5}}},\n\t\t{\"exactly 16\", make([]avx2ItemInt16, 16)},\n\t\t{\"large\", make([]avx2ItemInt16, 1000)},\n\t\t{\"negative\", []avx2ItemInt16{{-1}, {-2}, {-3}, {4}, {5}}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0].Value == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i].Value = int16(rand.IntN(65536) - 32768)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := SumByInt16x16(tc.input, func(i avx2ItemInt16) int16 { return i.Value })\n\t\t\twant := lo.Sum(lo.Map(tc.input, func(i avx2ItemInt16, _ int) int16 { return i.Value }))\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"SumByInt16x16() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestSumByInt32x8(t *testing.T) {\n\trequireAVX2(t)\n\n\ttype avx2ItemInt32 struct {\n\t\tValue int32\n\t}\n\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []avx2ItemInt32\n\t}{\n\t\t{\"empty\", []avx2ItemInt32{}},\n\t\t{\"single\", []avx2ItemInt32{{Value: 42}}},\n\t\t{\"small\", []avx2ItemInt32{{1}, {2}, {3}, {4}, {5}}},\n\t\t{\"exactly 8\", make([]avx2ItemInt32, 8)},\n\t\t{\"large\", make([]avx2ItemInt32, 1000)},\n\t\t{\"negative\", []avx2ItemInt32{{-1}, {-2}, {-3}, {4}, {5}}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0].Value == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i].Value = rand.Int32()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := SumByInt32x8(tc.input, func(i avx2ItemInt32) int32 { return i.Value })\n\t\t\twant := lo.Sum(lo.Map(tc.input, func(i avx2ItemInt32, _ int) int32 { return i.Value }))\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"SumByInt32x8() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestSumByInt64x4(t *testing.T) {\n\trequireAVX2(t)\n\n\ttype avx2ItemInt64 struct {\n\t\tValue int64\n\t}\n\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []avx2ItemInt64\n\t}{\n\t\t{\"empty\", []avx2ItemInt64{}},\n\t\t{\"single\", []avx2ItemInt64{{Value: 42}}},\n\t\t{\"small\", []avx2ItemInt64{{1}, {2}, {3}, {4}, {5}}},\n\t\t{\"exactly 4\", []avx2ItemInt64{{1}, {2}, {3}, {4}}},\n\t\t{\"large\", make([]avx2ItemInt64, 1000)},\n\t\t{\"negative\", []avx2ItemInt64{{-1}, {-2}, {-3}, {4}, {5}}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0].Value == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i].Value = rand.Int64()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := SumByInt64x4(tc.input, func(i avx2ItemInt64) int64 { return i.Value })\n\t\t\twant := lo.Sum(lo.Map(tc.input, func(i avx2ItemInt64, _ int) int64 { return i.Value }))\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"SumByInt64x4() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestSumByUint8x32(t *testing.T) {\n\trequireAVX2(t)\n\n\ttype avx2ItemUint8 struct {\n\t\tValue uint8\n\t}\n\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []avx2ItemUint8\n\t}{\n\t\t{\"empty\", []avx2ItemUint8{}},\n\t\t{\"single\", []avx2ItemUint8{{Value: 42}}},\n\t\t{\"small\", []avx2ItemUint8{{1}, {2}, {3}, {4}, {5}}},\n\t\t{\"exactly 32\", make([]avx2ItemUint8, 32)},\n\t\t{\"large\", make([]avx2ItemUint8, 1000)},\n\t\t{\"max values\", []avx2ItemUint8{{Value: 255}, {Value: 255}, {Value: 1}}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0].Value == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i].Value = uint8(rand.IntN(256))\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := SumByUint8x32(tc.input, func(i avx2ItemUint8) uint8 { return i.Value })\n\t\t\twant := lo.Sum(lo.Map(tc.input, func(i avx2ItemUint8, _ int) uint8 { return i.Value }))\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"SumByUint8x32() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestSumByUint16x16(t *testing.T) {\n\trequireAVX2(t)\n\n\ttype avx2ItemUint16 struct {\n\t\tValue uint16\n\t}\n\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []avx2ItemUint16\n\t}{\n\t\t{\"empty\", []avx2ItemUint16{}},\n\t\t{\"single\", []avx2ItemUint16{{Value: 42}}},\n\t\t{\"small\", []avx2ItemUint16{{1}, {2}, {3}, {4}, {5}}},\n\t\t{\"exactly 16\", make([]avx2ItemUint16, 16)},\n\t\t{\"large\", make([]avx2ItemUint16, 1000)},\n\t\t{\"max values\", []avx2ItemUint16{{Value: 65535}, {Value: 1}}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0].Value == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i].Value = uint16(rand.IntN(65536))\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := SumByUint16x16(tc.input, func(i avx2ItemUint16) uint16 { return i.Value })\n\t\t\twant := lo.Sum(lo.Map(tc.input, func(i avx2ItemUint16, _ int) uint16 { return i.Value }))\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"SumByUint16x16() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestSumByUint32x8(t *testing.T) {\n\trequireAVX2(t)\n\n\ttype avx2ItemUint32 struct {\n\t\tValue uint32\n\t}\n\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []avx2ItemUint32\n\t}{\n\t\t{\"empty\", []avx2ItemUint32{}},\n\t\t{\"single\", []avx2ItemUint32{{Value: 42}}},\n\t\t{\"small\", []avx2ItemUint32{{1}, {2}, {3}, {4}, {5}}},\n\t\t{\"exactly 8\", make([]avx2ItemUint32, 8)},\n\t\t{\"large\", make([]avx2ItemUint32, 1000)},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0].Value == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i].Value = rand.Uint32()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := SumByUint32x8(tc.input, func(i avx2ItemUint32) uint32 { return i.Value })\n\t\t\twant := lo.Sum(lo.Map(tc.input, func(i avx2ItemUint32, _ int) uint32 { return i.Value }))\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"SumByUint32x8() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestSumByUint64x4(t *testing.T) {\n\trequireAVX2(t)\n\n\ttype avx2ItemUint64 struct {\n\t\tValue uint64\n\t}\n\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []avx2ItemUint64\n\t}{\n\t\t{\"empty\", []avx2ItemUint64{}},\n\t\t{\"single\", []avx2ItemUint64{{Value: 42}}},\n\t\t{\"small\", []avx2ItemUint64{{1}, {2}, {3}, {4}, {5}}},\n\t\t{\"exactly 4\", []avx2ItemUint64{{1}, {2}, {3}, {4}}},\n\t\t{\"large\", make([]avx2ItemUint64, 1000)},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0].Value == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i].Value = rand.Uint64()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := SumByUint64x4(tc.input, func(i avx2ItemUint64) uint64 { return i.Value })\n\t\t\twant := lo.Sum(lo.Map(tc.input, func(i avx2ItemUint64, _ int) uint64 { return i.Value }))\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"SumByUint64x4() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestSumByFloat32x8(t *testing.T) {\n\trequireAVX2(t)\n\n\ttype avx2ItemFloat32 struct {\n\t\tValue float32\n\t}\n\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []avx2ItemFloat32\n\t}{\n\t\t{\"empty\", []avx2ItemFloat32{}},\n\t\t{\"single\", []avx2ItemFloat32{{Value: 42.5}}},\n\t\t{\"small\", []avx2ItemFloat32{{1.1}, {2.2}, {3.3}, {4.4}, {5.5}}},\n\t\t{\"exactly 8\", make([]avx2ItemFloat32, 8)},\n\t\t{\"large\", make([]avx2ItemFloat32, 1000)},\n\t\t{\"negative\", []avx2ItemFloat32{{-1.1}, {-2.2}, {3.3}, {4.4}}},\n\t\t{\"zeros\", []avx2ItemFloat32{{0}, {0}, {0}, {0}}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0].Value == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i].Value = rand.Float32()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := SumByFloat32x8(tc.input, func(i avx2ItemFloat32) float32 { return i.Value })\n\t\t\twant := lo.Sum(lo.Map(tc.input, func(i avx2ItemFloat32, _ int) float32 { return i.Value }))\n\n\t\t\tconst epsilon = 1e-3\n\t\t\tif diff := got - want; diff < -epsilon || diff > epsilon {\n\t\t\t\tt.Errorf(\"SumByFloat32x8() = %v, want %v (diff: %v)\", got, want, diff)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestSumByFloat64x4(t *testing.T) {\n\trequireAVX2(t)\n\n\ttype avx2ItemFloat64 struct {\n\t\tValue float64\n\t}\n\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []avx2ItemFloat64\n\t}{\n\t\t{\"empty\", []avx2ItemFloat64{}},\n\t\t{\"single\", []avx2ItemFloat64{{Value: 42.5}}},\n\t\t{\"small\", []avx2ItemFloat64{{1.1}, {2.2}, {3.3}, {4.4}, {5.5}}},\n\t\t{\"exactly 4\", []avx2ItemFloat64{{1.0}, {2.0}, {3.0}, {4.0}}},\n\t\t{\"large\", make([]avx2ItemFloat64, 1000)},\n\t\t{\"negative\", []avx2ItemFloat64{{-1.1}, {-2.2}, {3.3}, {4.4}}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0].Value == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i].Value = rand.Float64()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := SumByFloat64x4(tc.input, func(i avx2ItemFloat64) float64 { return i.Value })\n\t\t\twant := lo.Sum(lo.Map(tc.input, func(i avx2ItemFloat64, _ int) float64 { return i.Value }))\n\n\t\t\tconst epsilon = 1e-3\n\t\t\tif diff := got - want; diff < -epsilon || diff > epsilon {\n\t\t\t\tt.Errorf(\"SumByFloat64x4() = %v, want %v (diff: %v)\", got, want, diff)\n\t\t\t}\n\t\t})\n\t}\n}\n\n// Test type alias works correctly for SumBy\nfunc TestAVX2SumByTypeAlias(t *testing.T) {\n\trequireAVX2(t)\n\n\ttype myAVX2Item struct {\n\t\tValue myInt8\n\t}\n\n\tinput := []myAVX2Item{{Value: 1}, {Value: 2}, {Value: 3}, {Value: 4}, {Value: 5}}\n\tgot := SumByInt8x32(input, func(i myAVX2Item) myInt8 { return i.Value })\n\twant := myInt8(15)\n\n\tif got != want {\n\t\tt.Errorf(\"SumByInt8x32() with type alias = %v, want %v\", got, want)\n\t}\n}\n\n// MeanBy tests\n\nfunc TestMeanByInt8x32(t *testing.T) {\n\trequireAVX2(t)\n\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []avx2Item\n\t}{\n\t\t{\"empty\", []avx2Item{}},\n\t\t{\"single\", []avx2Item{{Value: 42}}},\n\t\t{\"small\", []avx2Item{{Value: 1}, {Value: 2}, {Value: 3}, {Value: 4}, {Value: 5}}},\n\t\t{\"exactly 32\", make([]avx2Item, 32)},\n\t\t{\"large\", make([]avx2Item, 1000)},\n\t\t{\"negative\", []avx2Item{{Value: -1}, {Value: -2}, {Value: -3}, {Value: 4}, {Value: 5}}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0].Value == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i].Value = int8(rand.IntN(256) - 128)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MeanByInt8x32(tc.input, func(i avx2Item) int8 { return i.Value })\n\t\t\twant := lo.Mean(lo.Map(tc.input, func(i avx2Item, _ int) int8 { return i.Value }))\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MeanByInt8x32() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMeanByInt16x16(t *testing.T) {\n\trequireAVX2(t)\n\n\ttype avx2ItemInt16 struct {\n\t\tValue int16\n\t}\n\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []avx2ItemInt16\n\t}{\n\t\t{\"empty\", []avx2ItemInt16{}},\n\t\t{\"single\", []avx2ItemInt16{{Value: 42}}},\n\t\t{\"small\", []avx2ItemInt16{{1}, {2}, {3}, {4}, {5}}},\n\t\t{\"exactly 16\", make([]avx2ItemInt16, 16)},\n\t\t{\"large\", make([]avx2ItemInt16, 1000)},\n\t\t{\"negative\", []avx2ItemInt16{{-1}, {-2}, {-3}, {4}, {5}}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0].Value == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i].Value = int16(rand.IntN(65536) - 32768)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MeanByInt16x16(tc.input, func(i avx2ItemInt16) int16 { return i.Value })\n\t\t\twant := lo.Mean(lo.Map(tc.input, func(i avx2ItemInt16, _ int) int16 { return i.Value }))\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MeanByInt16x16() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMeanByInt32x8(t *testing.T) {\n\trequireAVX2(t)\n\n\ttype avx2ItemInt32 struct {\n\t\tValue int32\n\t}\n\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []avx2ItemInt32\n\t}{\n\t\t{\"empty\", []avx2ItemInt32{}},\n\t\t{\"single\", []avx2ItemInt32{{Value: 42}}},\n\t\t{\"small\", []avx2ItemInt32{{1}, {2}, {3}, {4}, {5}}},\n\t\t{\"exactly 8\", make([]avx2ItemInt32, 8)},\n\t\t{\"large\", make([]avx2ItemInt32, 1000)},\n\t\t{\"negative\", []avx2ItemInt32{{-1}, {-2}, {-3}, {4}, {5}}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0].Value == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i].Value = rand.Int32()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MeanByInt32x8(tc.input, func(i avx2ItemInt32) int32 { return i.Value })\n\t\t\twant := lo.Mean(lo.Map(tc.input, func(i avx2ItemInt32, _ int) int32 { return i.Value }))\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MeanByInt32x8() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMeanByInt64x4(t *testing.T) {\n\trequireAVX2(t)\n\n\ttype avx2ItemInt64 struct {\n\t\tValue int64\n\t}\n\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []avx2ItemInt64\n\t}{\n\t\t{\"empty\", []avx2ItemInt64{}},\n\t\t{\"single\", []avx2ItemInt64{{Value: 42}}},\n\t\t{\"small\", []avx2ItemInt64{{1}, {2}, {3}, {4}, {5}}},\n\t\t{\"exactly 4\", []avx2ItemInt64{{1}, {2}, {3}, {4}}},\n\t\t{\"large\", make([]avx2ItemInt64, 1000)},\n\t\t{\"negative\", []avx2ItemInt64{{-1}, {-2}, {-3}, {4}, {5}}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0].Value == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i].Value = rand.Int64()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MeanByInt64x4(tc.input, func(i avx2ItemInt64) int64 { return i.Value })\n\t\t\twant := lo.Mean(lo.Map(tc.input, func(i avx2ItemInt64, _ int) int64 { return i.Value }))\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MeanByInt64x4() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMeanByUint8x32(t *testing.T) {\n\trequireAVX2(t)\n\n\ttype avx2ItemUint8 struct {\n\t\tValue uint8\n\t}\n\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []avx2ItemUint8\n\t}{\n\t\t{\"empty\", []avx2ItemUint8{}},\n\t\t{\"single\", []avx2ItemUint8{{Value: 42}}},\n\t\t{\"small\", []avx2ItemUint8{{1}, {2}, {3}, {4}, {5}}},\n\t\t{\"exactly 32\", make([]avx2ItemUint8, 32)},\n\t\t{\"large\", make([]avx2ItemUint8, 1000)},\n\t\t{\"max values\", []avx2ItemUint8{{Value: 255}, {Value: 255}, {Value: 1}}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0].Value == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i].Value = uint8(rand.IntN(256))\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MeanByUint8x32(tc.input, func(i avx2ItemUint8) uint8 { return i.Value })\n\t\t\twant := lo.Mean(lo.Map(tc.input, func(i avx2ItemUint8, _ int) uint8 { return i.Value }))\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MeanByUint8x32() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMeanByUint16x16(t *testing.T) {\n\trequireAVX2(t)\n\n\ttype avx2ItemUint16 struct {\n\t\tValue uint16\n\t}\n\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []avx2ItemUint16\n\t}{\n\t\t{\"empty\", []avx2ItemUint16{}},\n\t\t{\"single\", []avx2ItemUint16{{Value: 42}}},\n\t\t{\"small\", []avx2ItemUint16{{1}, {2}, {3}, {4}, {5}}},\n\t\t{\"exactly 16\", make([]avx2ItemUint16, 16)},\n\t\t{\"large\", make([]avx2ItemUint16, 1000)},\n\t\t{\"max values\", []avx2ItemUint16{{Value: 65535}, {Value: 1}}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0].Value == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i].Value = uint16(rand.IntN(65536))\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MeanByUint16x16(tc.input, func(i avx2ItemUint16) uint16 { return i.Value })\n\t\t\twant := lo.Mean(lo.Map(tc.input, func(i avx2ItemUint16, _ int) uint16 { return i.Value }))\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MeanByUint16x16() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMeanByUint32x8(t *testing.T) {\n\trequireAVX2(t)\n\n\ttype avx2ItemUint32 struct {\n\t\tValue uint32\n\t}\n\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []avx2ItemUint32\n\t}{\n\t\t{\"empty\", []avx2ItemUint32{}},\n\t\t{\"single\", []avx2ItemUint32{{Value: 42}}},\n\t\t{\"small\", []avx2ItemUint32{{1}, {2}, {3}, {4}, {5}}},\n\t\t{\"exactly 8\", make([]avx2ItemUint32, 8)},\n\t\t{\"large\", make([]avx2ItemUint32, 1000)},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0].Value == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i].Value = rand.Uint32()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MeanByUint32x8(tc.input, func(i avx2ItemUint32) uint32 { return i.Value })\n\t\t\twant := lo.Mean(lo.Map(tc.input, func(i avx2ItemUint32, _ int) uint32 { return i.Value }))\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MeanByUint32x8() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMeanByUint64x4(t *testing.T) {\n\trequireAVX2(t)\n\n\ttype avx2ItemUint64 struct {\n\t\tValue uint64\n\t}\n\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []avx2ItemUint64\n\t}{\n\t\t{\"empty\", []avx2ItemUint64{}},\n\t\t{\"single\", []avx2ItemUint64{{Value: 42}}},\n\t\t{\"small\", []avx2ItemUint64{{1}, {2}, {3}, {4}, {5}}},\n\t\t{\"exactly 4\", []avx2ItemUint64{{1}, {2}, {3}, {4}}},\n\t\t{\"large\", make([]avx2ItemUint64, 1000)},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0].Value == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i].Value = rand.Uint64()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MeanByUint64x4(tc.input, func(i avx2ItemUint64) uint64 { return i.Value })\n\t\t\twant := lo.Mean(lo.Map(tc.input, func(i avx2ItemUint64, _ int) uint64 { return i.Value }))\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MeanByUint64x4() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMeanByFloat32x8(t *testing.T) {\n\trequireAVX2(t)\n\n\ttype avx2ItemFloat32 struct {\n\t\tValue float32\n\t}\n\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []avx2ItemFloat32\n\t}{\n\t\t{\"empty\", []avx2ItemFloat32{}},\n\t\t{\"single\", []avx2ItemFloat32{{Value: 42.5}}},\n\t\t{\"small\", []avx2ItemFloat32{{1.1}, {2.2}, {3.3}, {4.4}, {5.5}}},\n\t\t{\"exactly 8\", make([]avx2ItemFloat32, 8)},\n\t\t{\"large\", make([]avx2ItemFloat32, 1000)},\n\t\t{\"negative\", []avx2ItemFloat32{{-1.1}, {-2.2}, {3.3}, {4.4}}},\n\t\t{\"zeros\", []avx2ItemFloat32{{0}, {0}, {0}, {0}}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0].Value == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i].Value = rand.Float32()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MeanByFloat32x8(tc.input, func(i avx2ItemFloat32) float32 { return i.Value })\n\t\t\twant := lo.Mean(lo.Map(tc.input, func(i avx2ItemFloat32, _ int) float32 { return i.Value }))\n\n\t\t\tconst epsilon = 1e-3\n\t\t\tif diff := got - want; diff < -epsilon || diff > epsilon {\n\t\t\t\tt.Errorf(\"MeanByFloat32x8() = %v, want %v (diff: %v)\", got, want, diff)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMeanByFloat64x4(t *testing.T) {\n\trequireAVX2(t)\n\n\ttype avx2ItemFloat64 struct {\n\t\tValue float64\n\t}\n\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []avx2ItemFloat64\n\t}{\n\t\t{\"empty\", []avx2ItemFloat64{}},\n\t\t{\"single\", []avx2ItemFloat64{{Value: 42.5}}},\n\t\t{\"small\", []avx2ItemFloat64{{1.1}, {2.2}, {3.3}, {4.4}, {5.5}}},\n\t\t{\"exactly 4\", []avx2ItemFloat64{{1.0}, {2.0}, {3.0}, {4.0}}},\n\t\t{\"large\", make([]avx2ItemFloat64, 1000)},\n\t\t{\"negative\", []avx2ItemFloat64{{-1.1}, {-2.2}, {3.3}, {4.4}}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0].Value == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i].Value = rand.Float64()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MeanByFloat64x4(tc.input, func(i avx2ItemFloat64) float64 { return i.Value })\n\t\t\twant := lo.Mean(lo.Map(tc.input, func(i avx2ItemFloat64, _ int) float64 { return i.Value }))\n\n\t\t\tconst epsilon = 1e-3\n\t\t\tif diff := got - want; diff < -epsilon || diff > epsilon {\n\t\t\t\tt.Errorf(\"MeanByFloat64x4() = %v, want %v (diff: %v)\", got, want, diff)\n\t\t\t}\n\t\t})\n\t}\n}\n\n// Test type alias works correctly for MeanBy\nfunc TestAVX2MeanByTypeAlias(t *testing.T) {\n\trequireAVX2(t)\n\n\ttype myAVX2Item struct {\n\t\tValue myInt8\n\t}\n\n\tinput := []myAVX2Item{{Value: 1}, {Value: 2}, {Value: 3}, {Value: 4}, {Value: 5}}\n\tgot := MeanByInt8x32(input, func(i myAVX2Item) myInt8 { return i.Value })\n\twant := myInt8(3)\n\n\tif got != want {\n\t\tt.Errorf(\"MeanByInt8x32() with type alias = %v, want %v\", got, want)\n\t}\n}\n"
  },
  {
    "path": "exp/simd/math_avx512.go",
    "content": "//go:build go1.26 && goexperiment.simd && amd64\n\npackage simd\n\nimport (\n\t\"simd/archsimd\"\n\t\"unsafe\"\n\n\t\"github.com/samber/lo\"\n)\n\n// AVX-512 (512-bit) SIMD sum functions - 64/32/16/8 lanes\n\n// SumInt8x64 sums a slice of int8 using AVX-512 SIMD (Int8x64, 64 lanes).\n// Overflow: The accumulation is performed using int8, which can overflow for large collections.\n// If the sum exceeds the int8 range (-128 to 127), the result will wrap around silently.\n// For collections that may overflow, consider using a wider type or handle overflow detection externally.\nfunc SumInt8x64[T ~int8](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\tconst lanes = simdLanes64\n\n\tbase := unsafeSliceInt8(collection, length)\n\tvar acc archsimd.Int8x64\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadInt8x64Slice(base[i : i+lanes])\n\t\tacc = acc.Add(v)\n\t}\n\n\tvar buf [lanes]int8\n\tacc.Store(&buf)\n\tvar sum T\n\tfor k := uint(0); k < lanes; k++ {\n\t\tsum += T(buf[k])\n\t}\n\n\tfor ; i < length; i++ {\n\t\tsum += collection[i]\n\t}\n\n\treturn sum\n}\n\n// SumInt16x32 sums a slice of int16 using AVX-512 SIMD (Int16x32, 32 lanes).\n// Overflow: The accumulation is performed using int16, which can overflow for large collections.\n// If the sum exceeds the int16 range (-32768 to 32767), the result will wrap around silently.\n// For collections that may overflow, consider using a wider type or handle overflow detection externally.\nfunc SumInt16x32[T ~int16](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\tconst lanes = simdLanes32\n\n\tbase := unsafeSliceInt16(collection, length)\n\tvar acc archsimd.Int16x32\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadInt16x32Slice(base[i : i+lanes])\n\t\tacc = acc.Add(v)\n\t}\n\n\tvar buf [lanes]int16\n\tacc.Store(&buf)\n\tvar sum T\n\tfor k := uint(0); k < lanes; k++ {\n\t\tsum += T(buf[k])\n\t}\n\n\tfor ; i < length; i++ {\n\t\tsum += collection[i]\n\t}\n\n\treturn sum\n}\n\n// SumInt32x16 sums a slice of int32 using AVX-512 SIMD (Int32x16, 16 lanes).\n// Overflow: The accumulation is performed using int32, which can overflow for very large collections.\n// If the sum exceeds the int32 range (-2147483648 to 2147483647), the result will wrap around silently.\n// For collections that may overflow, consider using SumInt64x8 or handle overflow detection externally.\nfunc SumInt32x16[T ~int32](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\tconst lanes = simdLanes16\n\n\tbase := unsafeSliceInt32(collection, length)\n\tvar acc archsimd.Int32x16\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadInt32x16Slice(base[i : i+lanes])\n\t\tacc = acc.Add(v)\n\t}\n\n\tvar buf [lanes]int32\n\tacc.Store(&buf)\n\tvar sum T\n\tfor k := uint(0); k < lanes; k++ {\n\t\tsum += T(buf[k])\n\t}\n\n\tfor ; i < length; i++ {\n\t\tsum += collection[i]\n\t}\n\n\treturn sum\n}\n\n// SumInt64x8 sums a slice of int64 using AVX-512 SIMD (Int64x8, 8 lanes).\n// Overflow: The accumulation is performed using int64, which can overflow for extremely large collections.\n// If the sum exceeds the int64 range, the result will wrap around silently.\n// For collections that may overflow, handle overflow detection externally (e.g., using big.Int).\nfunc SumInt64x8[T ~int64](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\tconst lanes = simdLanes8\n\n\tbase := unsafeSliceInt64(collection, length)\n\tvar acc archsimd.Int64x8\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadInt64x8Slice(base[i : i+lanes])\n\t\tacc = acc.Add(v)\n\t}\n\n\tvar buf [lanes]int64\n\tacc.Store(&buf)\n\tvar sum T\n\tfor k := uint(0); k < lanes; k++ {\n\t\tsum += T(buf[k])\n\t}\n\n\tfor ; i < length; i++ {\n\t\tsum += collection[i]\n\t}\n\n\treturn sum\n}\n\n// SumUint8x64 sums a slice of uint8 using AVX-512 SIMD (Uint8x64, 64 lanes).\n// Overflow: The accumulation is performed using uint8, which can overflow for large collections.\n// If the sum exceeds the uint8 range (0 to 255), the result will wrap around silently.\n// For collections that may overflow, consider using a wider type or handle overflow detection externally.\nfunc SumUint8x64[T ~uint8](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\tconst lanes = simdLanes64\n\n\tbase := unsafeSliceUint8(collection, length)\n\tvar acc archsimd.Uint8x64\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadUint8x64Slice(base[i : i+lanes])\n\t\tacc = acc.Add(v)\n\t}\n\n\tvar buf [lanes]uint8\n\tacc.Store(&buf)\n\tvar sum T\n\tfor k := uint(0); k < lanes; k++ {\n\t\tsum += T(buf[k])\n\t}\n\n\tfor ; i < length; i++ {\n\t\tsum += collection[i]\n\t}\n\n\treturn sum\n}\n\n// SumUint16x32 sums a slice of uint16 using AVX-512 SIMD (Uint16x32, 32 lanes).\n// Overflow: The accumulation is performed using uint16, which can overflow for large collections.\n// If the sum exceeds the uint16 range (0 to 65535), the result will wrap around silently.\n// For collections that may overflow, consider using a wider type or handle overflow detection externally.\nfunc SumUint16x32[T ~uint16](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\tconst lanes = simdLanes32\n\n\tbase := unsafeSliceUint16(collection, length)\n\tvar acc archsimd.Uint16x32\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadUint16x32Slice(base[i : i+lanes])\n\t\tacc = acc.Add(v)\n\t}\n\n\tvar buf [lanes]uint16\n\tacc.Store(&buf)\n\tvar sum T\n\tfor k := uint(0); k < lanes; k++ {\n\t\tsum += T(buf[k])\n\t}\n\n\tfor ; i < length; i++ {\n\t\tsum += collection[i]\n\t}\n\n\treturn sum\n}\n\n// SumUint32x16 sums a slice of uint32 using AVX-512 SIMD (Uint32x16, 16 lanes).\n// Overflow: The accumulation is performed using uint32, which can overflow for very large collections.\n// If the sum exceeds the uint32 range (0 to 4294967295), the result will wrap around silently.\n// For collections that may overflow, consider using SumUint64x8 or handle overflow detection externally.\nfunc SumUint32x16[T ~uint32](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\tconst lanes = simdLanes16\n\n\tbase := unsafeSliceUint32(collection, length)\n\tvar acc archsimd.Uint32x16\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadUint32x16Slice(base[i : i+lanes])\n\t\tacc = acc.Add(v)\n\t}\n\n\tvar buf [lanes]uint32\n\tacc.Store(&buf)\n\tvar sum T\n\tfor k := uint(0); k < lanes; k++ {\n\t\tsum += T(buf[k])\n\t}\n\n\tfor ; i < length; i++ {\n\t\tsum += collection[i]\n\t}\n\n\treturn sum\n}\n\n// SumUint64x8 sums a slice of uint64 using AVX-512 SIMD (Uint64x8, 8 lanes).\n// Overflow: The accumulation is performed using uint64, which can overflow for extremely large collections.\n// If the sum exceeds the uint64 range, the result will wrap around silently.\n// For collections that may overflow, handle overflow detection externally (e.g., using big.Int).\nfunc SumUint64x8[T ~uint64](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\tconst lanes = simdLanes8\n\n\tbase := unsafeSliceUint64(collection, length)\n\tvar acc archsimd.Uint64x8\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadUint64x8Slice(base[i : i+lanes])\n\t\tacc = acc.Add(v)\n\t}\n\n\tvar buf [lanes]uint64\n\tacc.Store(&buf)\n\tvar sum T\n\tfor k := uint(0); k < lanes; k++ {\n\t\tsum += T(buf[k])\n\t}\n\n\tfor ; i < length; i++ {\n\t\tsum += collection[i]\n\t}\n\n\treturn sum\n}\n\n// SumFloat32x16 sums a slice of float32 using AVX-512 SIMD (Float32x16, 16 lanes).\n// Overflow: The accumulation is performed using float32. Overflow will result in +/-Inf rather than wrapping.\n// For collections requiring high precision or large sums, consider using SumFloat64x8.\nfunc SumFloat32x16[T ~float32](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\tconst lanes = simdLanes16\n\n\tbase := unsafeSliceFloat32(collection, length)\n\tvar acc archsimd.Float32x16\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadFloat32x16Slice(base[i : i+lanes])\n\t\tacc = acc.Add(v)\n\t}\n\n\tvar buf [lanes]float32\n\tacc.Store(&buf)\n\tvar sum T\n\tfor k := uint(0); k < lanes; k++ {\n\t\tsum += T(buf[k])\n\t}\n\n\tfor ; i < length; i++ {\n\t\tsum += collection[i]\n\t}\n\n\treturn sum\n}\n\n// SumFloat64x8 sums a slice of float64 using AVX-512 SIMD (Float64x8, 8 lanes).\n// Overflow: The accumulation is performed using float64. Overflow will result in +/-Inf rather than wrapping.\n// For collections that may overflow, handle overflow detection externally (e.g., using big.Float).\nfunc SumFloat64x8[T ~float64](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\tconst lanes = simdLanes8\n\n\tbase := unsafeSliceFloat64(collection, length)\n\tvar acc archsimd.Float64x8\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadFloat64x8Slice(base[i : i+lanes])\n\t\tacc = acc.Add(v)\n\t}\n\n\tvar buf [lanes]float64\n\tacc.Store(&buf)\n\tvar sum T\n\tfor k := uint(0); k < lanes; k++ {\n\t\tsum += T(buf[k])\n\t}\n\n\tfor ; i < length; i++ {\n\t\tsum += collection[i]\n\t}\n\n\treturn sum\n}\n\n// MeanInt8x64 calculates the mean of a slice of int8 using AVX-512 SIMD\nfunc MeanInt8x64[T ~int8](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\tsum := SumInt8x64(collection)\n\treturn sum / T(length)\n}\n\n// MeanInt16x32 calculates the mean of a slice of int16 using AVX-512 SIMD\nfunc MeanInt16x32[T ~int16](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\tsum := SumInt16x32(collection)\n\treturn sum / T(length)\n}\n\n// MeanInt32x16 calculates the mean of a slice of int32 using AVX-512 SIMD\nfunc MeanInt32x16[T ~int32](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\tsum := SumInt32x16(collection)\n\treturn sum / T(length)\n}\n\n// MeanInt64x8 calculates the mean of a slice of int64 using AVX-512 SIMD\nfunc MeanInt64x8[T ~int64](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\tsum := SumInt64x8(collection)\n\treturn sum / T(length)\n}\n\n// MeanUint8x64 calculates the mean of a slice of uint8 using AVX-512 SIMD\nfunc MeanUint8x64[T ~uint8](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\tsum := SumUint8x64(collection)\n\treturn sum / T(length)\n}\n\n// MeanUint16x32 calculates the mean of a slice of uint16 using AVX-512 SIMD\nfunc MeanUint16x32[T ~uint16](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\tsum := SumUint16x32(collection)\n\treturn sum / T(length)\n}\n\n// MeanUint32x16 calculates the mean of a slice of uint32 using AVX-512 SIMD\nfunc MeanUint32x16[T ~uint32](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\tsum := SumUint32x16(collection)\n\treturn sum / T(length)\n}\n\n// MeanUint64x8 calculates the mean of a slice of uint64 using AVX-512 SIMD\nfunc MeanUint64x8[T ~uint64](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\tsum := SumUint64x8(collection)\n\treturn sum / T(length)\n}\n\n// MeanFloat32x16 calculates the mean of a slice of float32 using AVX-512 SIMD\nfunc MeanFloat32x16[T ~float32](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\tsum := SumFloat32x16(collection)\n\treturn sum / T(length)\n}\n\n// MeanFloat64x8 calculates the mean of a slice of float64 using AVX-512 SIMD\nfunc MeanFloat64x8[T ~float64](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\tsum := SumFloat64x8(collection)\n\treturn sum / T(length)\n}\n\n// ClampInt8x64 clamps each element in collection between min and max values using AVX-512 SIMD\nfunc ClampInt8x64[T ~int8, Slice ~[]T](collection Slice, min, max T) Slice {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn collection\n\t}\n\n\tresult := make(Slice, length)\n\tconst lanes = simdLanes64\n\n\tminVec := archsimd.BroadcastInt8x64(int8(min))\n\tmaxVec := archsimd.BroadcastInt8x64(int8(max))\n\n\tbase := unsafeSliceInt8(collection, length)\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tc := base[i : i+lanes]\n\t\tv := archsimd.LoadInt8x64Slice(c)\n\n\t\tclamped := v.Max(minVec).Min(maxVec)\n\n\t\t// bearer:disable go_gosec_unsafe_unsafe\n\t\tclamped.Store((*[lanes]int8)(unsafe.Pointer(&result[i])))\n\t}\n\n\tfor ; i < length; i++ {\n\t\tval := collection[i]\n\t\tif val < min {\n\t\t\tval = min\n\t\t} else if val > max {\n\t\t\tval = max\n\t\t}\n\t\tresult[i] = val\n\t}\n\n\treturn result\n}\n\n// ClampInt16x32 clamps each element in collection between min and max values using AVX-512 SIMD\nfunc ClampInt16x32[T ~int16, Slice ~[]T](collection Slice, min, max T) Slice {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn collection\n\t}\n\n\tresult := make(Slice, length)\n\tconst lanes = simdLanes32\n\n\tminVec := archsimd.BroadcastInt16x32(int16(min))\n\tmaxVec := archsimd.BroadcastInt16x32(int16(max))\n\n\tbase := unsafeSliceInt16(collection, length)\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tc := base[i : i+lanes]\n\t\tv := archsimd.LoadInt16x32Slice(c)\n\n\t\tclamped := v.Max(minVec).Min(maxVec)\n\n\t\t// bearer:disable go_gosec_unsafe_unsafe\n\t\tclamped.Store((*[lanes]int16)(unsafe.Pointer(&result[i])))\n\t}\n\n\tfor ; i < length; i++ {\n\t\tval := collection[i]\n\t\tif val < min {\n\t\t\tval = min\n\t\t} else if val > max {\n\t\t\tval = max\n\t\t}\n\t\tresult[i] = val\n\t}\n\n\treturn result\n}\n\n// ClampInt32x16 clamps each element in collection between min and max values using AVX-512 SIMD\nfunc ClampInt32x16[T ~int32, Slice ~[]T](collection Slice, min, max T) Slice {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn collection\n\t}\n\n\tresult := make(Slice, length)\n\tconst lanes = simdLanes16\n\n\tminVec := archsimd.BroadcastInt32x16(int32(min))\n\tmaxVec := archsimd.BroadcastInt32x16(int32(max))\n\n\tbase := unsafeSliceInt32(collection, length)\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tc := base[i : i+lanes]\n\t\tv := archsimd.LoadInt32x16Slice(c)\n\n\t\tclamped := v.Max(minVec).Min(maxVec)\n\n\t\t// bearer:disable go_gosec_unsafe_unsafe\n\t\tclamped.Store((*[lanes]int32)(unsafe.Pointer(&result[i])))\n\t}\n\n\tfor ; i < length; i++ {\n\t\tval := collection[i]\n\t\tif val < min {\n\t\t\tval = min\n\t\t} else if val > max {\n\t\t\tval = max\n\t\t}\n\t\tresult[i] = val\n\t}\n\n\treturn result\n}\n\n// ClampInt64x2 clamps each element in collection between min and max values using AVX-512 SIMD.\n// Int64x2 Min/Max operations in archsimd require AVX-512 (VPMAXSQ/VPMINSQ).\nfunc ClampInt64x2[T ~int64, Slice ~[]T](collection Slice, min, max T) Slice {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn collection\n\t}\n\n\tresult := make(Slice, length)\n\tconst lanes = simdLanes2\n\n\tbase := unsafeSliceInt64(collection, length)\n\n\tminVec := archsimd.BroadcastInt64x2(int64(min))\n\tmaxVec := archsimd.BroadcastInt64x2(int64(max))\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadInt64x2Slice(base[i : i+lanes])\n\n\t\tclamped := v.Max(minVec).Min(maxVec)\n\n\t\t// bearer:disable go_gosec_unsafe_unsafe\n\t\tclamped.Store((*[lanes]int64)(unsafe.Pointer(&result[i])))\n\t}\n\n\tfor ; i < length; i++ {\n\t\tval := collection[i]\n\t\tif val < min {\n\t\t\tval = min\n\t\t} else if val > max {\n\t\t\tval = max\n\t\t}\n\t\tresult[i] = val\n\t}\n\n\treturn result\n}\n\n// ClampUint64x2 clamps each element in collection between min and max values using AVX-512 SIMD.\n// Uint64x2 Min/Max operations in archsimd require AVX-512.\nfunc ClampUint64x2[T ~uint64, Slice ~[]T](collection Slice, min, max T) Slice {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn collection\n\t}\n\n\tresult := make(Slice, length)\n\tconst lanes = simdLanes2\n\n\tbase := unsafeSliceUint64(collection, length)\n\n\tminVec := archsimd.BroadcastUint64x2(uint64(min))\n\tmaxVec := archsimd.BroadcastUint64x2(uint64(max))\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadUint64x2Slice(base[i : i+lanes])\n\n\t\tclamped := v.Max(minVec).Min(maxVec)\n\n\t\t// bearer:disable go_gosec_unsafe_unsafe\n\t\tclamped.Store((*[lanes]uint64)(unsafe.Pointer(&result[i])))\n\t}\n\n\tfor ; i < length; i++ {\n\t\tval := collection[i]\n\t\tif val < min {\n\t\t\tval = min\n\t\t} else if val > max {\n\t\t\tval = max\n\t\t}\n\t\tresult[i] = val\n\t}\n\n\treturn result\n}\n\n// ClampInt64x8 clamps each element in collection between min and max values using AVX-512 SIMD\nfunc ClampInt64x8[T ~int64, Slice ~[]T](collection Slice, min, max T) Slice {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn collection\n\t}\n\n\tresult := make(Slice, length)\n\tconst lanes = simdLanes8\n\n\tminVec := archsimd.BroadcastInt64x8(int64(min))\n\tmaxVec := archsimd.BroadcastInt64x8(int64(max))\n\n\tbase := unsafeSliceInt64(collection, length)\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tc := base[i : i+lanes]\n\t\tv := archsimd.LoadInt64x8Slice(c)\n\n\t\tclamped := v.Max(minVec).Min(maxVec)\n\n\t\t// bearer:disable go_gosec_unsafe_unsafe\n\t\tclamped.Store((*[lanes]int64)(unsafe.Pointer(&result[i])))\n\t}\n\n\tfor ; i < length; i++ {\n\t\tval := collection[i]\n\t\tif val < min {\n\t\t\tval = min\n\t\t} else if val > max {\n\t\t\tval = max\n\t\t}\n\t\tresult[i] = val\n\t}\n\n\treturn result\n}\n\n// ClampUint8x64 clamps each element in collection between min and max values using AVX-512 SIMD\nfunc ClampUint8x64[T ~uint8, Slice ~[]T](collection Slice, min, max T) Slice {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn collection\n\t}\n\n\tresult := make(Slice, length)\n\tconst lanes = simdLanes64\n\n\tminVec := archsimd.BroadcastUint8x64(uint8(min))\n\tmaxVec := archsimd.BroadcastUint8x64(uint8(max))\n\n\tbase := unsafeSliceUint8(collection, length)\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tc := base[i : i+lanes]\n\t\tv := archsimd.LoadUint8x64Slice(c)\n\n\t\tclamped := v.Max(minVec).Min(maxVec)\n\n\t\t// bearer:disable go_gosec_unsafe_unsafe\n\t\tclamped.Store((*[lanes]uint8)(unsafe.Pointer(&result[i])))\n\t}\n\n\tfor ; i < length; i++ {\n\t\tval := collection[i]\n\t\tif val < min {\n\t\t\tval = min\n\t\t} else if val > max {\n\t\t\tval = max\n\t\t}\n\t\tresult[i] = val\n\t}\n\n\treturn result\n}\n\n// ClampUint16x32 clamps each element in collection between min and max values using AVX-512 SIMD\nfunc ClampUint16x32[T ~uint16, Slice ~[]T](collection Slice, min, max T) Slice {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn collection\n\t}\n\n\tresult := make(Slice, length)\n\tconst lanes = simdLanes32\n\n\tminVec := archsimd.BroadcastUint16x32(uint16(min))\n\tmaxVec := archsimd.BroadcastUint16x32(uint16(max))\n\n\tbase := unsafeSliceUint16(collection, length)\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tc := base[i : i+lanes]\n\t\tv := archsimd.LoadUint16x32Slice(c)\n\n\t\tclamped := v.Max(minVec).Min(maxVec)\n\n\t\t// bearer:disable go_gosec_unsafe_unsafe\n\t\tclamped.Store((*[lanes]uint16)(unsafe.Pointer(&result[i])))\n\t}\n\n\tfor ; i < length; i++ {\n\t\tval := collection[i]\n\t\tif val < min {\n\t\t\tval = min\n\t\t} else if val > max {\n\t\t\tval = max\n\t\t}\n\t\tresult[i] = val\n\t}\n\n\treturn result\n}\n\n// ClampUint32x16 clamps each element in collection between min and max values using AVX-512 SIMD\nfunc ClampUint32x16[T ~uint32, Slice ~[]T](collection Slice, min, max T) Slice {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn collection\n\t}\n\n\tresult := make(Slice, length)\n\tconst lanes = simdLanes16\n\n\tminVec := archsimd.BroadcastUint32x16(uint32(min))\n\tmaxVec := archsimd.BroadcastUint32x16(uint32(max))\n\n\tbase := unsafeSliceUint32(collection, length)\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tc := base[i : i+lanes]\n\t\tv := archsimd.LoadUint32x16Slice(c)\n\n\t\tclamped := v.Max(minVec).Min(maxVec)\n\n\t\t// bearer:disable go_gosec_unsafe_unsafe\n\t\tclamped.Store((*[lanes]uint32)(unsafe.Pointer(&result[i])))\n\t}\n\n\tfor ; i < length; i++ {\n\t\tval := collection[i]\n\t\tif val < min {\n\t\t\tval = min\n\t\t} else if val > max {\n\t\t\tval = max\n\t\t}\n\t\tresult[i] = val\n\t}\n\n\treturn result\n}\n\n// ClampUint64x8 clamps each element in collection between min and max values using AVX-512 SIMD\nfunc ClampUint64x8[T ~uint64, Slice ~[]T](collection Slice, min, max T) Slice {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn collection\n\t}\n\n\tresult := make(Slice, length)\n\tconst lanes = simdLanes8\n\n\tminVec := archsimd.BroadcastUint64x8(uint64(min))\n\tmaxVec := archsimd.BroadcastUint64x8(uint64(max))\n\n\tbase := unsafeSliceUint64(collection, length)\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tc := base[i : i+lanes]\n\t\tv := archsimd.LoadUint64x8Slice(c)\n\n\t\tclamped := v.Max(minVec).Min(maxVec)\n\n\t\t// bearer:disable go_gosec_unsafe_unsafe\n\t\tclamped.Store((*[lanes]uint64)(unsafe.Pointer(&result[i])))\n\t}\n\n\tfor ; i < length; i++ {\n\t\tval := collection[i]\n\t\tif val < min {\n\t\t\tval = min\n\t\t} else if val > max {\n\t\t\tval = max\n\t\t}\n\t\tresult[i] = val\n\t}\n\n\treturn result\n}\n\n// ClampFloat32x16 clamps each element in collection between min and max values using AVX-512 SIMD\nfunc ClampFloat32x16[T ~float32, Slice ~[]T](collection Slice, min, max T) Slice {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn collection\n\t}\n\n\tresult := make(Slice, length)\n\tconst lanes = simdLanes16\n\n\tminVec := archsimd.BroadcastFloat32x16(float32(min))\n\tmaxVec := archsimd.BroadcastFloat32x16(float32(max))\n\n\tbase := unsafeSliceFloat32(collection, length)\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tc := base[i : i+lanes]\n\t\tv := archsimd.LoadFloat32x16Slice(c)\n\n\t\tclamped := v.Max(minVec).Min(maxVec)\n\n\t\t// bearer:disable go_gosec_unsafe_unsafe\n\t\tclamped.Store((*[lanes]float32)(unsafe.Pointer(&result[i])))\n\t}\n\n\tfor ; i < length; i++ {\n\t\tval := collection[i]\n\t\tif val < min {\n\t\t\tval = min\n\t\t} else if val > max {\n\t\t\tval = max\n\t\t}\n\t\tresult[i] = val\n\t}\n\n\treturn result\n}\n\n// ClampFloat64x8 clamps each element in collection between min and max values using AVX-512 SIMD\nfunc ClampFloat64x8[T ~float64, Slice ~[]T](collection Slice, min, max T) Slice {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn collection\n\t}\n\n\tresult := make(Slice, length)\n\tconst lanes = simdLanes8\n\n\tminVec := archsimd.BroadcastFloat64x8(float64(min))\n\tmaxVec := archsimd.BroadcastFloat64x8(float64(max))\n\n\tbase := unsafeSliceFloat64(collection, length)\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tc := base[i : i+lanes]\n\t\tv := archsimd.LoadFloat64x8Slice(c)\n\n\t\tclamped := v.Max(minVec).Min(maxVec)\n\n\t\t// bearer:disable go_gosec_unsafe_unsafe\n\t\tclamped.Store((*[lanes]float64)(unsafe.Pointer(&result[i])))\n\t}\n\n\tfor ; i < length; i++ {\n\t\tval := collection[i]\n\t\tif val < min {\n\t\t\tval = min\n\t\t} else if val > max {\n\t\t\tval = max\n\t\t}\n\t\tresult[i] = val\n\t}\n\n\treturn result\n}\n\n// MinInt8x64 finds the minimum value in a collection of int8 using AVX-512 SIMD\nfunc MinInt8x64[T ~int8](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\n\tconst lanes = simdLanes64\n\n\tbase := unsafeSliceInt8(collection, length)\n\n\tvar minVec archsimd.Int8x64\n\tfirstInitialized := false\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadInt8x64Slice(base[i : i+lanes])\n\n\t\tif !firstInitialized {\n\t\t\tminVec = v\n\t\t\tfirstInitialized = true\n\t\t} else {\n\t\t\tminVec = minVec.Min(v)\n\t\t}\n\t}\n\n\t// Find minimum in the vector (only if we processed any vectors)\n\tvar minVal int8\n\tif firstInitialized {\n\t\tvar buf [lanes]int8\n\t\tminVec.Store(&buf)\n\t\tminVal = min(\n\t\t\tbuf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7],\n\t\t\tbuf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15],\n\t\t\tbuf[16], buf[17], buf[18], buf[19], buf[20], buf[21], buf[22], buf[23],\n\t\t\tbuf[24], buf[25], buf[26], buf[27], buf[28], buf[29], buf[30], buf[31],\n\t\t\tbuf[32], buf[33], buf[34], buf[35], buf[36], buf[37], buf[38], buf[39],\n\t\t\tbuf[40], buf[41], buf[42], buf[43], buf[44], buf[45], buf[46], buf[47],\n\t\t\tbuf[48], buf[49], buf[50], buf[51], buf[52], buf[53], buf[54], buf[55],\n\t\t\tbuf[56], buf[57], buf[58], buf[59], buf[60], buf[61], buf[62], buf[63],\n\t\t)\n\t}\n\n\t// Handle remaining elements\n\tfor ; i < length; i++ {\n\t\tif !firstInitialized || collection[i] < T(minVal) {\n\t\t\tminVal = int8(collection[i])\n\t\t\tfirstInitialized = true\n\t\t}\n\t}\n\n\treturn T(minVal)\n}\n\n// MinInt16x32 finds the minimum value in a collection of int16 using AVX-512 SIMD\nfunc MinInt16x32[T ~int16](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\n\tconst lanes = simdLanes32\n\n\tbase := unsafeSliceInt16(collection, length)\n\n\tvar minVec archsimd.Int16x32\n\tfirstInitialized := false\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadInt16x32Slice(base[i : i+lanes])\n\n\t\tif !firstInitialized {\n\t\t\tminVec = v\n\t\t\tfirstInitialized = true\n\t\t} else {\n\t\t\tminVec = minVec.Min(v)\n\t\t}\n\t}\n\n\t// Find minimum in the vector (only if we processed any vectors)\n\tvar minVal int16\n\tif firstInitialized {\n\t\tvar buf [lanes]int16\n\t\tminVec.Store(&buf)\n\t\tminVal = min(\n\t\t\tbuf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7],\n\t\t\tbuf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15],\n\t\t\tbuf[16], buf[17], buf[18], buf[19], buf[20], buf[21], buf[22], buf[23],\n\t\t\tbuf[24], buf[25], buf[26], buf[27], buf[28], buf[29], buf[30], buf[31],\n\t\t)\n\t}\n\n\t// Handle remaining elements\n\tfor ; i < length; i++ {\n\t\tif !firstInitialized || collection[i] < T(minVal) {\n\t\t\tminVal = int16(collection[i])\n\t\t\tfirstInitialized = true\n\t\t}\n\t}\n\n\treturn T(minVal)\n}\n\n// MinInt32x16 finds the minimum value in a collection of int32 using AVX-512 SIMD\nfunc MinInt32x16[T ~int32](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\n\tconst lanes = simdLanes16\n\n\tbase := unsafeSliceInt32(collection, length)\n\n\tvar minVec archsimd.Int32x16\n\tfirstInitialized := false\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadInt32x16Slice(base[i : i+lanes])\n\n\t\tif !firstInitialized {\n\t\t\tminVec = v\n\t\t\tfirstInitialized = true\n\t\t} else {\n\t\t\tminVec = minVec.Min(v)\n\t\t}\n\t}\n\n\t// Find minimum in the vector (only if we processed any vectors)\n\tvar minVal int32\n\tif firstInitialized {\n\t\tvar buf [lanes]int32\n\t\tminVec.Store(&buf)\n\t\tminVal = min(\n\t\t\tbuf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7],\n\t\t\tbuf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15],\n\t\t)\n\t}\n\n\t// Handle remaining elements\n\tfor ; i < length; i++ {\n\t\tif !firstInitialized || collection[i] < T(minVal) {\n\t\t\tminVal = int32(collection[i])\n\t\t\tfirstInitialized = true\n\t\t}\n\t}\n\n\treturn T(minVal)\n}\n\n// MinInt64x2 finds the minimum value in a collection of int64 using AVX-512 SIMD.\n// Int64x2 Min operations in archsimd require AVX-512.\nfunc MinInt64x2[T ~int64](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\n\tconst lanes = simdLanes2\n\tbase := unsafeSliceInt64(collection, length)\n\n\tvar minVec archsimd.Int64x2\n\tfirstInitialized := false\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadInt64x2Slice(base[i : i+lanes])\n\n\t\tif !firstInitialized {\n\t\t\tminVec = v\n\t\t\tfirstInitialized = true\n\t\t} else {\n\t\t\tminVec = minVec.Min(v)\n\t\t}\n\t}\n\n\t// Find minimum in the vector (only if we processed any vectors)\n\tvar minVal int64\n\tif firstInitialized {\n\t\tvar buf [lanes]int64\n\t\tminVec.Store(&buf)\n\t\tminVal = min(buf[0], buf[1])\n\t}\n\n\t// Handle remaining elements\n\tfor ; i < length; i++ {\n\t\tif !firstInitialized || collection[i] < T(minVal) {\n\t\t\tminVal = int64(collection[i])\n\t\t\tfirstInitialized = true\n\t\t}\n\t}\n\n\treturn T(minVal)\n}\n\n// MinUint64x2 finds the minimum value in a collection of uint64 using AVX-512 SIMD.\n// Uint64x2 Min operations in archsimd require AVX-512.\nfunc MinUint64x2[T ~uint64](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\n\tconst lanes = simdLanes2\n\tbase := unsafeSliceUint64(collection, length)\n\n\tvar minVec archsimd.Uint64x2\n\tfirstInitialized := false\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadUint64x2Slice(base[i : i+lanes])\n\n\t\tif !firstInitialized {\n\t\t\tminVec = v\n\t\t\tfirstInitialized = true\n\t\t} else {\n\t\t\tminVec = minVec.Min(v)\n\t\t}\n\t}\n\n\t// Find minimum in the vector (only if we processed any vectors)\n\tvar minVal uint64\n\tif firstInitialized {\n\t\tvar buf [lanes]uint64\n\t\tminVec.Store(&buf)\n\t\tminVal = min(buf[0], buf[1])\n\t}\n\n\t// Handle remaining elements\n\tfor ; i < length; i++ {\n\t\tif !firstInitialized || collection[i] < T(minVal) {\n\t\t\tminVal = uint64(collection[i])\n\t\t\tfirstInitialized = true\n\t\t}\n\t}\n\n\treturn T(minVal)\n}\n\n// MinInt64x8 finds the minimum value in a collection of int64 using AVX-512 SIMD\nfunc MinInt64x8[T ~int64](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\n\tconst lanes = simdLanes8\n\n\tbase := unsafeSliceInt64(collection, length)\n\n\tvar minVec archsimd.Int64x8\n\tfirstInitialized := false\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadInt64x8Slice(base[i : i+lanes])\n\n\t\tif !firstInitialized {\n\t\t\tminVec = v\n\t\t\tfirstInitialized = true\n\t\t} else {\n\t\t\tminVec = minVec.Min(v)\n\t\t}\n\t}\n\n\t// Find minimum in the vector (only if we processed any vectors)\n\tvar minVal int64\n\tif firstInitialized {\n\t\tvar buf [lanes]int64\n\t\tminVec.Store(&buf)\n\t\tminVal = min(buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7])\n\t}\n\n\t// Handle remaining elements\n\tfor ; i < length; i++ {\n\t\tif !firstInitialized || collection[i] < T(minVal) {\n\t\t\tminVal = int64(collection[i])\n\t\t\tfirstInitialized = true\n\t\t}\n\t}\n\n\treturn T(minVal)\n}\n\n// MinUint8x64 finds the minimum value in a collection of uint8 using AVX-512 SIMD\nfunc MinUint8x64[T ~uint8](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\n\tconst lanes = simdLanes64\n\n\tbase := unsafeSliceUint8(collection, length)\n\n\tvar minVec archsimd.Uint8x64\n\tfirstInitialized := false\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadUint8x64Slice(base[i : i+lanes])\n\n\t\tif !firstInitialized {\n\t\t\tminVec = v\n\t\t\tfirstInitialized = true\n\t\t} else {\n\t\t\tminVec = minVec.Min(v)\n\t\t}\n\t}\n\n\t// Find minimum in the vector (only if we processed any vectors)\n\tvar minVal uint8\n\tif firstInitialized {\n\t\tvar buf [lanes]uint8\n\t\tminVec.Store(&buf)\n\t\tminVal = min(\n\t\t\tbuf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7],\n\t\t\tbuf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15],\n\t\t\tbuf[16], buf[17], buf[18], buf[19], buf[20], buf[21], buf[22], buf[23],\n\t\t\tbuf[24], buf[25], buf[26], buf[27], buf[28], buf[29], buf[30], buf[31],\n\t\t\tbuf[32], buf[33], buf[34], buf[35], buf[36], buf[37], buf[38], buf[39],\n\t\t\tbuf[40], buf[41], buf[42], buf[43], buf[44], buf[45], buf[46], buf[47],\n\t\t\tbuf[48], buf[49], buf[50], buf[51], buf[52], buf[53], buf[54], buf[55],\n\t\t\tbuf[56], buf[57], buf[58], buf[59], buf[60], buf[61], buf[62], buf[63],\n\t\t)\n\t}\n\n\t// Handle remaining elements\n\tfor ; i < length; i++ {\n\t\tif !firstInitialized || collection[i] < T(minVal) {\n\t\t\tminVal = uint8(collection[i])\n\t\t\tfirstInitialized = true\n\t\t}\n\t}\n\n\treturn T(minVal)\n}\n\n// MinUint16x32 finds the minimum value in a collection of uint16 using AVX-512 SIMD\nfunc MinUint16x32[T ~uint16](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\n\tconst lanes = simdLanes32\n\n\tbase := unsafeSliceUint16(collection, length)\n\n\tvar minVec archsimd.Uint16x32\n\tfirstInitialized := false\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadUint16x32Slice(base[i : i+lanes])\n\n\t\tif !firstInitialized {\n\t\t\tminVec = v\n\t\t\tfirstInitialized = true\n\t\t} else {\n\t\t\tminVec = minVec.Min(v)\n\t\t}\n\t}\n\n\t// Find minimum in the vector (only if we processed any vectors)\n\tvar minVal uint16\n\tif firstInitialized {\n\t\tvar buf [lanes]uint16\n\t\tminVec.Store(&buf)\n\t\tminVal = min(\n\t\t\tbuf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7],\n\t\t\tbuf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15],\n\t\t\tbuf[16], buf[17], buf[18], buf[19], buf[20], buf[21], buf[22], buf[23],\n\t\t\tbuf[24], buf[25], buf[26], buf[27], buf[28], buf[29], buf[30], buf[31],\n\t\t)\n\t}\n\n\t// Handle remaining elements\n\tfor ; i < length; i++ {\n\t\tif !firstInitialized || collection[i] < T(minVal) {\n\t\t\tminVal = uint16(collection[i])\n\t\t\tfirstInitialized = true\n\t\t}\n\t}\n\n\treturn T(minVal)\n}\n\n// MinUint32x16 finds the minimum value in a collection of uint32 using AVX-512 SIMD\nfunc MinUint32x16[T ~uint32](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\n\tconst lanes = simdLanes16\n\n\tbase := unsafeSliceUint32(collection, length)\n\n\tvar minVec archsimd.Uint32x16\n\tfirstInitialized := false\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadUint32x16Slice(base[i : i+lanes])\n\n\t\tif !firstInitialized {\n\t\t\tminVec = v\n\t\t\tfirstInitialized = true\n\t\t} else {\n\t\t\tminVec = minVec.Min(v)\n\t\t}\n\t}\n\n\t// Find minimum in the vector (only if we processed any vectors)\n\tvar minVal uint32\n\tif firstInitialized {\n\t\tvar buf [lanes]uint32\n\t\tminVec.Store(&buf)\n\t\tminVal = min(\n\t\t\tbuf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7],\n\t\t\tbuf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15],\n\t\t)\n\t}\n\n\t// Handle remaining elements\n\tfor ; i < length; i++ {\n\t\tif !firstInitialized || collection[i] < T(minVal) {\n\t\t\tminVal = uint32(collection[i])\n\t\t\tfirstInitialized = true\n\t\t}\n\t}\n\n\treturn T(minVal)\n}\n\n// MinUint64x8 finds the minimum value in a collection of uint64 using AVX-512 SIMD\nfunc MinUint64x8[T ~uint64](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\n\tconst lanes = simdLanes8\n\n\tbase := unsafeSliceUint64(collection, length)\n\n\tvar minVec archsimd.Uint64x8\n\tfirstInitialized := false\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadUint64x8Slice(base[i : i+lanes])\n\n\t\tif !firstInitialized {\n\t\t\tminVec = v\n\t\t\tfirstInitialized = true\n\t\t} else {\n\t\t\tminVec = minVec.Min(v)\n\t\t}\n\t}\n\n\t// Find minimum in the vector (only if we processed any vectors)\n\tvar minVal uint64\n\tif firstInitialized {\n\t\tvar buf [lanes]uint64\n\t\tminVec.Store(&buf)\n\t\tminVal = min(buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7])\n\t}\n\n\t// Handle remaining elements\n\tfor ; i < length; i++ {\n\t\tif !firstInitialized || collection[i] < T(minVal) {\n\t\t\tminVal = uint64(collection[i])\n\t\t\tfirstInitialized = true\n\t\t}\n\t}\n\n\treturn T(minVal)\n}\n\n// MinFloat32x16 finds the minimum value in a collection of float32 using AVX-512 SIMD\nfunc MinFloat32x16[T ~float32](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\n\tconst lanes = simdLanes16\n\n\tbase := unsafeSliceFloat32(collection, length)\n\n\tvar minVec archsimd.Float32x16\n\tfirstInitialized := false\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadFloat32x16Slice(base[i : i+lanes])\n\n\t\tif !firstInitialized {\n\t\t\tminVec = v\n\t\t\tfirstInitialized = true\n\t\t} else {\n\t\t\tminVec = minVec.Min(v)\n\t\t}\n\t}\n\n\t// Find minimum in the vector (only if we processed any vectors)\n\tvar minVal float32\n\tif firstInitialized {\n\t\tvar buf [lanes]float32\n\t\tminVec.Store(&buf)\n\t\tminVal = min(\n\t\t\tbuf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7],\n\t\t\tbuf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15],\n\t\t)\n\t}\n\n\t// Handle remaining elements\n\tfor ; i < length; i++ {\n\t\tif !firstInitialized || collection[i] < T(minVal) {\n\t\t\tminVal = float32(collection[i])\n\t\t\tfirstInitialized = true\n\t\t}\n\t}\n\n\treturn T(minVal)\n}\n\n// MinFloat64x8 finds the minimum value in a collection of float64 using AVX-512 SIMD\nfunc MinFloat64x8[T ~float64](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\n\tconst lanes = simdLanes8\n\n\tbase := unsafeSliceFloat64(collection, length)\n\n\tvar minVec archsimd.Float64x8\n\tfirstInitialized := false\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadFloat64x8Slice(base[i : i+lanes])\n\n\t\tif !firstInitialized {\n\t\t\tminVec = v\n\t\t\tfirstInitialized = true\n\t\t} else {\n\t\t\tminVec = minVec.Min(v)\n\t\t}\n\t}\n\n\t// Find minimum in the vector (only if we processed any vectors)\n\tvar minVal float64\n\tif firstInitialized {\n\t\tvar buf [lanes]float64\n\t\tminVec.Store(&buf)\n\t\tminVal = min(buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7])\n\t}\n\n\t// Handle remaining elements\n\tfor ; i < length; i++ {\n\t\tif !firstInitialized || collection[i] < T(minVal) {\n\t\t\tminVal = float64(collection[i])\n\t\t\tfirstInitialized = true\n\t\t}\n\t}\n\n\treturn T(minVal)\n}\n\n// MaxInt8x64 finds the maximum value in a collection of int8 using AVX-512 SIMD\nfunc MaxInt8x64[T ~int8](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\n\tconst lanes = simdLanes64\n\n\tbase := unsafeSliceInt8(collection, length)\n\n\tvar maxVec archsimd.Int8x64\n\tfirstInitialized := false\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadInt8x64Slice(base[i : i+lanes])\n\n\t\tif !firstInitialized {\n\t\t\tmaxVec = v\n\t\t\tfirstInitialized = true\n\t\t} else {\n\t\t\tmaxVec = maxVec.Max(v)\n\t\t}\n\t}\n\n\t// Find maximum in the vector (only if we processed any vectors)\n\tvar maxVal int8\n\tif firstInitialized {\n\t\tvar buf [lanes]int8\n\t\tmaxVec.Store(&buf)\n\t\tmaxVal = max(\n\t\t\tbuf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7],\n\t\t\tbuf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15],\n\t\t\tbuf[16], buf[17], buf[18], buf[19], buf[20], buf[21], buf[22], buf[23],\n\t\t\tbuf[24], buf[25], buf[26], buf[27], buf[28], buf[29], buf[30], buf[31],\n\t\t\tbuf[32], buf[33], buf[34], buf[35], buf[36], buf[37], buf[38], buf[39],\n\t\t\tbuf[40], buf[41], buf[42], buf[43], buf[44], buf[45], buf[46], buf[47],\n\t\t\tbuf[48], buf[49], buf[50], buf[51], buf[52], buf[53], buf[54], buf[55],\n\t\t\tbuf[56], buf[57], buf[58], buf[59], buf[60], buf[61], buf[62], buf[63],\n\t\t)\n\t}\n\n\t// Handle remaining elements\n\tfor ; i < length; i++ {\n\t\tif !firstInitialized || collection[i] > T(maxVal) {\n\t\t\tmaxVal = int8(collection[i])\n\t\t\tfirstInitialized = true\n\t\t}\n\t}\n\n\treturn T(maxVal)\n}\n\n// MaxInt16x32 finds the maximum value in a collection of int16 using AVX-512 SIMD\nfunc MaxInt16x32[T ~int16](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\n\tconst lanes = simdLanes32\n\n\tbase := unsafeSliceInt16(collection, length)\n\n\tvar maxVec archsimd.Int16x32\n\tfirstInitialized := false\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadInt16x32Slice(base[i : i+lanes])\n\n\t\tif !firstInitialized {\n\t\t\tmaxVec = v\n\t\t\tfirstInitialized = true\n\t\t} else {\n\t\t\tmaxVec = maxVec.Max(v)\n\t\t}\n\t}\n\n\t// Find maximum in the vector (only if we processed any vectors)\n\tvar maxVal int16\n\tif firstInitialized {\n\t\tvar buf [lanes]int16\n\t\tmaxVec.Store(&buf)\n\t\tmaxVal = max(\n\t\t\tbuf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7],\n\t\t\tbuf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15],\n\t\t\tbuf[16], buf[17], buf[18], buf[19], buf[20], buf[21], buf[22], buf[23],\n\t\t\tbuf[24], buf[25], buf[26], buf[27], buf[28], buf[29], buf[30], buf[31],\n\t\t)\n\t}\n\n\t// Handle remaining elements\n\tfor ; i < length; i++ {\n\t\tif !firstInitialized || collection[i] > T(maxVal) {\n\t\t\tmaxVal = int16(collection[i])\n\t\t\tfirstInitialized = true\n\t\t}\n\t}\n\n\treturn T(maxVal)\n}\n\n// MaxInt32x16 finds the maximum value in a collection of int32 using AVX-512 SIMD\nfunc MaxInt32x16[T ~int32](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\n\tconst lanes = simdLanes16\n\n\tbase := unsafeSliceInt32(collection, length)\n\n\tvar maxVec archsimd.Int32x16\n\tfirstInitialized := false\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadInt32x16Slice(base[i : i+lanes])\n\n\t\tif !firstInitialized {\n\t\t\tmaxVec = v\n\t\t\tfirstInitialized = true\n\t\t} else {\n\t\t\tmaxVec = maxVec.Max(v)\n\t\t}\n\t}\n\n\t// Find maximum in the vector (only if we processed any vectors)\n\tvar maxVal int32\n\tif firstInitialized {\n\t\tvar buf [lanes]int32\n\t\tmaxVec.Store(&buf)\n\t\tmaxVal = max(\n\t\t\tbuf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7],\n\t\t\tbuf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15],\n\t\t)\n\t}\n\n\t// Handle remaining elements\n\tfor ; i < length; i++ {\n\t\tif !firstInitialized || collection[i] > T(maxVal) {\n\t\t\tmaxVal = int32(collection[i])\n\t\t\tfirstInitialized = true\n\t\t}\n\t}\n\n\treturn T(maxVal)\n}\n\n// MaxInt64x2 finds the maximum value in a collection of int64 using AVX-512 SIMD.\n// Int64x2 Max operations in archsimd require AVX-512.\nfunc MaxInt64x2[T ~int64](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\n\tconst lanes = simdLanes2\n\tbase := unsafeSliceInt64(collection, length)\n\n\tvar maxVec archsimd.Int64x2\n\tfirstInitialized := false\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadInt64x2Slice(base[i : i+lanes])\n\n\t\tif !firstInitialized {\n\t\t\tmaxVec = v\n\t\t\tfirstInitialized = true\n\t\t} else {\n\t\t\tmaxVec = maxVec.Max(v)\n\t\t}\n\t}\n\n\t// Find maximum in the vector (only if we processed any vectors)\n\tvar maxVal int64\n\tif firstInitialized {\n\t\tvar buf [lanes]int64\n\t\tmaxVec.Store(&buf)\n\t\tmaxVal = max(buf[0], buf[1])\n\t}\n\n\t// Handle remaining elements\n\tfor ; i < length; i++ {\n\t\tif !firstInitialized || collection[i] > T(maxVal) {\n\t\t\tmaxVal = int64(collection[i])\n\t\t\tfirstInitialized = true\n\t\t}\n\t}\n\n\treturn T(maxVal)\n}\n\n// MaxUint64x2 finds the maximum value in a collection of uint64 using AVX-512 SIMD.\n// Uint64x2 Max operations in archsimd require AVX-512.\nfunc MaxUint64x2[T ~uint64](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\n\tconst lanes = simdLanes2\n\tbase := unsafeSliceUint64(collection, length)\n\n\tvar maxVec archsimd.Uint64x2\n\tfirstInitialized := false\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadUint64x2Slice(base[i : i+lanes])\n\n\t\tif !firstInitialized {\n\t\t\tmaxVec = v\n\t\t\tfirstInitialized = true\n\t\t} else {\n\t\t\tmaxVec = maxVec.Max(v)\n\t\t}\n\t}\n\n\t// Find maximum in the vector (only if we processed any vectors)\n\tvar maxVal uint64\n\tif firstInitialized {\n\t\tvar buf [lanes]uint64\n\t\tmaxVec.Store(&buf)\n\t\tmaxVal = max(buf[0], buf[1])\n\t}\n\n\t// Handle remaining elements\n\tfor ; i < length; i++ {\n\t\tif !firstInitialized || collection[i] > T(maxVal) {\n\t\t\tmaxVal = uint64(collection[i])\n\t\t\tfirstInitialized = true\n\t\t}\n\t}\n\n\treturn T(maxVal)\n}\n\n// MaxInt64x8 finds the maximum value in a collection of int64 using AVX-512 SIMD\nfunc MaxInt64x8[T ~int64](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\n\tconst lanes = simdLanes8\n\n\tbase := unsafeSliceInt64(collection, length)\n\n\tvar maxVec archsimd.Int64x8\n\tfirstInitialized := false\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadInt64x8Slice(base[i : i+lanes])\n\n\t\tif !firstInitialized {\n\t\t\tmaxVec = v\n\t\t\tfirstInitialized = true\n\t\t} else {\n\t\t\tmaxVec = maxVec.Max(v)\n\t\t}\n\t}\n\n\t// Find maximum in the vector (only if we processed any vectors)\n\tvar maxVal int64\n\tif firstInitialized {\n\t\tvar buf [lanes]int64\n\t\tmaxVec.Store(&buf)\n\t\tmaxVal = max(buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7])\n\t}\n\n\t// Handle remaining elements\n\tfor ; i < length; i++ {\n\t\tif !firstInitialized || collection[i] > T(maxVal) {\n\t\t\tmaxVal = int64(collection[i])\n\t\t\tfirstInitialized = true\n\t\t}\n\t}\n\n\treturn T(maxVal)\n}\n\n// MaxUint8x64 finds the maximum value in a collection of uint8 using AVX-512 SIMD\nfunc MaxUint8x64[T ~uint8](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\n\tconst lanes = simdLanes64\n\n\tbase := unsafeSliceUint8(collection, length)\n\n\tvar maxVec archsimd.Uint8x64\n\tfirstInitialized := false\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadUint8x64Slice(base[i : i+lanes])\n\n\t\tif !firstInitialized {\n\t\t\tmaxVec = v\n\t\t\tfirstInitialized = true\n\t\t} else {\n\t\t\tmaxVec = maxVec.Max(v)\n\t\t}\n\t}\n\n\t// Find maximum in the vector (only if we processed any vectors)\n\tvar maxVal uint8\n\tif firstInitialized {\n\t\tvar buf [lanes]uint8\n\t\tmaxVec.Store(&buf)\n\t\tmaxVal = max(\n\t\t\tbuf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7],\n\t\t\tbuf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15],\n\t\t\tbuf[16], buf[17], buf[18], buf[19], buf[20], buf[21], buf[22], buf[23],\n\t\t\tbuf[24], buf[25], buf[26], buf[27], buf[28], buf[29], buf[30], buf[31],\n\t\t\tbuf[32], buf[33], buf[34], buf[35], buf[36], buf[37], buf[38], buf[39],\n\t\t\tbuf[40], buf[41], buf[42], buf[43], buf[44], buf[45], buf[46], buf[47],\n\t\t\tbuf[48], buf[49], buf[50], buf[51], buf[52], buf[53], buf[54], buf[55],\n\t\t\tbuf[56], buf[57], buf[58], buf[59], buf[60], buf[61], buf[62], buf[63],\n\t\t)\n\t}\n\n\t// Handle remaining elements\n\tfor ; i < length; i++ {\n\t\tif !firstInitialized || collection[i] > T(maxVal) {\n\t\t\tmaxVal = uint8(collection[i])\n\t\t\tfirstInitialized = true\n\t\t}\n\t}\n\n\treturn T(maxVal)\n}\n\n// MaxUint16x32 finds the maximum value in a collection of uint16 using AVX-512 SIMD\nfunc MaxUint16x32[T ~uint16](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\n\tconst lanes = simdLanes32\n\n\tbase := unsafeSliceUint16(collection, length)\n\n\tvar maxVec archsimd.Uint16x32\n\tfirstInitialized := false\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadUint16x32Slice(base[i : i+lanes])\n\n\t\tif !firstInitialized {\n\t\t\tmaxVec = v\n\t\t\tfirstInitialized = true\n\t\t} else {\n\t\t\tmaxVec = maxVec.Max(v)\n\t\t}\n\t}\n\n\t// Find maximum in the vector (only if we processed any vectors)\n\tvar maxVal uint16\n\tif firstInitialized {\n\t\tvar buf [lanes]uint16\n\t\tmaxVec.Store(&buf)\n\t\tmaxVal = max(\n\t\t\tbuf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7],\n\t\t\tbuf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15],\n\t\t\tbuf[16], buf[17], buf[18], buf[19], buf[20], buf[21], buf[22], buf[23],\n\t\t\tbuf[24], buf[25], buf[26], buf[27], buf[28], buf[29], buf[30], buf[31],\n\t\t)\n\t}\n\n\t// Handle remaining elements\n\tfor ; i < length; i++ {\n\t\tif !firstInitialized || collection[i] > T(maxVal) {\n\t\t\tmaxVal = uint16(collection[i])\n\t\t\tfirstInitialized = true\n\t\t}\n\t}\n\n\treturn T(maxVal)\n}\n\n// MaxUint32x16 finds the maximum value in a collection of uint32 using AVX-512 SIMD\nfunc MaxUint32x16[T ~uint32](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\n\tconst lanes = simdLanes16\n\n\tbase := unsafeSliceUint32(collection, length)\n\n\tvar maxVec archsimd.Uint32x16\n\tfirstInitialized := false\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadUint32x16Slice(base[i : i+lanes])\n\n\t\tif !firstInitialized {\n\t\t\tmaxVec = v\n\t\t\tfirstInitialized = true\n\t\t} else {\n\t\t\tmaxVec = maxVec.Max(v)\n\t\t}\n\t}\n\n\t// Find maximum in the vector (only if we processed any vectors)\n\tvar maxVal uint32\n\tif firstInitialized {\n\t\tvar buf [lanes]uint32\n\t\tmaxVec.Store(&buf)\n\t\tmaxVal = max(\n\t\t\tbuf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7],\n\t\t\tbuf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15],\n\t\t)\n\t}\n\n\t// Handle remaining elements\n\tfor ; i < length; i++ {\n\t\tif !firstInitialized || collection[i] > T(maxVal) {\n\t\t\tmaxVal = uint32(collection[i])\n\t\t\tfirstInitialized = true\n\t\t}\n\t}\n\n\treturn T(maxVal)\n}\n\n// MaxUint64x8 finds the maximum value in a collection of uint64 using AVX-512 SIMD\nfunc MaxUint64x8[T ~uint64](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\n\tconst lanes = simdLanes8\n\n\tbase := unsafeSliceUint64(collection, length)\n\n\tvar maxVec archsimd.Uint64x8\n\tfirstInitialized := false\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadUint64x8Slice(base[i : i+lanes])\n\n\t\tif !firstInitialized {\n\t\t\tmaxVec = v\n\t\t\tfirstInitialized = true\n\t\t} else {\n\t\t\tmaxVec = maxVec.Max(v)\n\t\t}\n\t}\n\n\t// Find maximum in the vector (only if we processed any vectors)\n\tvar maxVal uint64\n\tif firstInitialized {\n\t\tvar buf [lanes]uint64\n\t\tmaxVec.Store(&buf)\n\t\tmaxVal = max(buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7])\n\t}\n\n\t// Handle remaining elements\n\tfor ; i < length; i++ {\n\t\tif !firstInitialized || collection[i] > T(maxVal) {\n\t\t\tmaxVal = uint64(collection[i])\n\t\t\tfirstInitialized = true\n\t\t}\n\t}\n\n\treturn T(maxVal)\n}\n\n// MaxFloat32x16 finds the maximum value in a collection of float32 using AVX-512 SIMD\nfunc MaxFloat32x16[T ~float32](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\n\tconst lanes = simdLanes16\n\n\tbase := unsafeSliceFloat32(collection, length)\n\n\tvar maxVec archsimd.Float32x16\n\tfirstInitialized := false\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadFloat32x16Slice(base[i : i+lanes])\n\n\t\tif !firstInitialized {\n\t\t\tmaxVec = v\n\t\t\tfirstInitialized = true\n\t\t} else {\n\t\t\tmaxVec = maxVec.Max(v)\n\t\t}\n\t}\n\n\t// Find maximum in the vector (only if we processed any vectors)\n\tvar maxVal float32\n\tif firstInitialized {\n\t\tvar buf [lanes]float32\n\t\tmaxVec.Store(&buf)\n\t\tmaxVal = max(\n\t\t\tbuf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7],\n\t\t\tbuf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15],\n\t\t)\n\t}\n\n\t// Handle remaining elements\n\tfor ; i < length; i++ {\n\t\tif !firstInitialized || collection[i] > T(maxVal) {\n\t\t\tmaxVal = float32(collection[i])\n\t\t\tfirstInitialized = true\n\t\t}\n\t}\n\n\treturn T(maxVal)\n}\n\n// MaxFloat64x8 finds the maximum value in a collection of float64 using AVX-512 SIMD\nfunc MaxFloat64x8[T ~float64](collection []T) T {\n\tlength := uint(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\n\tconst lanes = simdLanes8\n\n\tbase := unsafeSliceFloat64(collection, length)\n\n\tvar maxVec archsimd.Float64x8\n\tfirstInitialized := false\n\n\ti := uint(0)\n\tfor ; i+lanes <= length; i += lanes {\n\t\tv := archsimd.LoadFloat64x8Slice(base[i : i+lanes])\n\n\t\tif !firstInitialized {\n\t\t\tmaxVec = v\n\t\t\tfirstInitialized = true\n\t\t} else {\n\t\t\tmaxVec = maxVec.Max(v)\n\t\t}\n\t}\n\n\t// Find maximum in the vector (only if we processed any vectors)\n\tvar maxVal float64\n\tif firstInitialized {\n\t\tvar buf [lanes]float64\n\t\tmaxVec.Store(&buf)\n\t\tmaxVal = max(buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7])\n\t}\n\n\t// Handle remaining elements\n\tfor ; i < length; i++ {\n\t\tif !firstInitialized || collection[i] > T(maxVal) {\n\t\t\tmaxVal = float64(collection[i])\n\t\t\tfirstInitialized = true\n\t\t}\n\t}\n\n\treturn T(maxVal)\n}\n\n// AVX-512 (512-bit) SIMD sumBy functions - 64/32/16/8 lanes\n// These implementations use lo.Map to apply the iteratee, then chain with SIMD sum functions.\n\n// SumByInt8x64 sums the values extracted by iteratee from a slice using AVX-512 SIMD.\nfunc SumByInt8x64[T any, R ~int8](collection []T, iteratee func(item T) R) R {\n\tmapped := lo.Map(collection, func(item T, _ int) R { return iteratee(item) })\n\treturn SumInt8x64(mapped)\n}\n\n// SumByInt16x32 sums the values extracted by iteratee from a slice using AVX-512 SIMD.\nfunc SumByInt16x32[T any, R ~int16](collection []T, iteratee func(item T) R) R {\n\tmapped := lo.Map(collection, func(item T, _ int) R { return iteratee(item) })\n\treturn SumInt16x32(mapped)\n}\n\n// SumByInt32x16 sums the values extracted by iteratee from a slice using AVX-512 SIMD.\nfunc SumByInt32x16[T any, R ~int32](collection []T, iteratee func(item T) R) R {\n\tmapped := lo.Map(collection, func(item T, _ int) R { return iteratee(item) })\n\treturn SumInt32x16(mapped)\n}\n\n// SumByInt64x8 sums the values extracted by iteratee from a slice using AVX-512 SIMD.\nfunc SumByInt64x8[T any, R ~int64](collection []T, iteratee func(item T) R) R {\n\tmapped := lo.Map(collection, func(item T, _ int) R { return iteratee(item) })\n\treturn SumInt64x8(mapped)\n}\n\n// SumByUint8x64 sums the values extracted by iteratee from a slice using AVX-512 SIMD.\nfunc SumByUint8x64[T any, R ~uint8](collection []T, iteratee func(item T) R) R {\n\tmapped := lo.Map(collection, func(item T, _ int) R { return iteratee(item) })\n\treturn SumUint8x64(mapped)\n}\n\n// SumByUint16x32 sums the values extracted by iteratee from a slice using AVX-512 SIMD.\nfunc SumByUint16x32[T any, R ~uint16](collection []T, iteratee func(item T) R) R {\n\tmapped := lo.Map(collection, func(item T, _ int) R { return iteratee(item) })\n\treturn SumUint16x32(mapped)\n}\n\n// SumByUint32x16 sums the values extracted by iteratee from a slice using AVX-512 SIMD.\nfunc SumByUint32x16[T any, R ~uint32](collection []T, iteratee func(item T) R) R {\n\tmapped := lo.Map(collection, func(item T, _ int) R { return iteratee(item) })\n\treturn SumUint32x16(mapped)\n}\n\n// SumByUint64x8 sums the values extracted by iteratee from a slice using AVX-512 SIMD.\nfunc SumByUint64x8[T any, R ~uint64](collection []T, iteratee func(item T) R) R {\n\tmapped := lo.Map(collection, func(item T, _ int) R { return iteratee(item) })\n\treturn SumUint64x8(mapped)\n}\n\n// SumByFloat32x16 sums the values extracted by iteratee from a slice using AVX-512 SIMD.\nfunc SumByFloat32x16[T any, R ~float32](collection []T, iteratee func(item T) R) R {\n\tmapped := lo.Map(collection, func(item T, _ int) R { return iteratee(item) })\n\treturn SumFloat32x16(mapped)\n}\n\n// SumByFloat64x8 sums the values extracted by iteratee from a slice using AVX-512 SIMD.\nfunc SumByFloat64x8[T any, R ~float64](collection []T, iteratee func(item T) R) R {\n\tmapped := lo.Map(collection, func(item T, _ int) R { return iteratee(item) })\n\treturn SumFloat64x8(mapped)\n}\n\n// AVX-512 (512-bit) SIMD meanBy functions - 64/32/16/8 lanes\n// These implementations use lo.Map to apply the iteratee, then chain with SIMD mean functions.\n\n// MeanByInt8x64 calculates the mean of values extracted by iteratee from a slice using AVX-512 SIMD.\nfunc MeanByInt8x64[T any, R ~int8](collection []T, iteratee func(item T) R) R {\n\tmapped := lo.Map(collection, func(item T, _ int) R { return iteratee(item) })\n\treturn MeanInt8x64(mapped)\n}\n\n// MeanByInt16x32 calculates the mean of values extracted by iteratee from a slice using AVX-512 SIMD.\nfunc MeanByInt16x32[T any, R ~int16](collection []T, iteratee func(item T) R) R {\n\tmapped := lo.Map(collection, func(item T, _ int) R { return iteratee(item) })\n\treturn MeanInt16x32(mapped)\n}\n\n// MeanByInt32x16 calculates the mean of values extracted by iteratee from a slice using AVX-512 SIMD.\nfunc MeanByInt32x16[T any, R ~int32](collection []T, iteratee func(item T) R) R {\n\tmapped := lo.Map(collection, func(item T, _ int) R { return iteratee(item) })\n\treturn MeanInt32x16(mapped)\n}\n\n// MeanByInt64x8 calculates the mean of values extracted by iteratee from a slice using AVX-512 SIMD.\nfunc MeanByInt64x8[T any, R ~int64](collection []T, iteratee func(item T) R) R {\n\tmapped := lo.Map(collection, func(item T, _ int) R { return iteratee(item) })\n\treturn MeanInt64x8(mapped)\n}\n\n// MeanByUint8x64 calculates the mean of values extracted by iteratee from a slice using AVX-512 SIMD.\nfunc MeanByUint8x64[T any, R ~uint8](collection []T, iteratee func(item T) R) R {\n\tmapped := lo.Map(collection, func(item T, _ int) R { return iteratee(item) })\n\treturn MeanUint8x64(mapped)\n}\n\n// MeanByUint16x32 calculates the mean of values extracted by iteratee from a slice using AVX-512 SIMD.\nfunc MeanByUint16x32[T any, R ~uint16](collection []T, iteratee func(item T) R) R {\n\tmapped := lo.Map(collection, func(item T, _ int) R { return iteratee(item) })\n\treturn MeanUint16x32(mapped)\n}\n\n// MeanByUint32x16 calculates the mean of values extracted by iteratee from a slice using AVX-512 SIMD.\nfunc MeanByUint32x16[T any, R ~uint32](collection []T, iteratee func(item T) R) R {\n\tmapped := lo.Map(collection, func(item T, _ int) R { return iteratee(item) })\n\treturn MeanUint32x16(mapped)\n}\n\n// MeanByUint64x8 calculates the mean of values extracted by iteratee from a slice using AVX-512 SIMD.\nfunc MeanByUint64x8[T any, R ~uint64](collection []T, iteratee func(item T) R) R {\n\tmapped := lo.Map(collection, func(item T, _ int) R { return iteratee(item) })\n\treturn MeanUint64x8(mapped)\n}\n\n// MeanByFloat32x16 calculates the mean of values extracted by iteratee from a slice using AVX-512 SIMD.\nfunc MeanByFloat32x16[T any, R ~float32](collection []T, iteratee func(item T) R) R {\n\tmapped := lo.Map(collection, func(item T, _ int) R { return iteratee(item) })\n\treturn MeanFloat32x16(mapped)\n}\n\n// MeanByFloat64x8 calculates the mean of values extracted by iteratee from a slice using AVX-512 SIMD.\nfunc MeanByFloat64x8[T any, R ~float64](collection []T, iteratee func(item T) R) R {\n\tmapped := lo.Map(collection, func(item T, _ int) R { return iteratee(item) })\n\treturn MeanFloat64x8(mapped)\n}\n"
  },
  {
    "path": "exp/simd/math_avx512_test.go",
    "content": "//go:build go1.26 && goexperiment.simd && amd64\n\npackage simd\n\nimport (\n\t\"math/rand/v2\"\n\t\"testing\"\n\n\t\"github.com/samber/lo\"\n)\n\nfunc TestSumInt8x64(t *testing.T) {\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []int8\n\t}{\n\t\t{\"empty\", []int8{}},\n\t\t{\"single\", []int8{42}},\n\t\t{\"small\", []int8{1, 2, 3, 4, 5}},\n\t\t{\"exactly 64\", make([]int8, 64)},\n\t\t{\"large\", make([]int8, 1000)},\n\t\t{\"negative\", []int8{-1, -2, -3, 4, 5}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = int8(rand.IntN(256) - 128)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := SumInt8x64(tc.input)\n\t\t\twant := lo.Sum(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"SumInt8x64() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestSumInt16x32(t *testing.T) {\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []int16\n\t}{\n\t\t{\"empty\", []int16{}},\n\t\t{\"single\", []int16{42}},\n\t\t{\"small\", []int16{1, 2, 3, 4, 5}},\n\t\t{\"exactly 32\", make([]int16, 32)},\n\t\t{\"large\", make([]int16, 1000)},\n\t\t{\"negative\", []int16{-1, -2, -3, 4, 5}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = int16(rand.IntN(65536) - 32768)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := SumInt16x32(tc.input)\n\t\t\twant := lo.Sum(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"SumInt16x32() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestSumInt32x16(t *testing.T) {\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []int32\n\t}{\n\t\t{\"empty\", []int32{}},\n\t\t{\"single\", []int32{42}},\n\t\t{\"small\", []int32{1, 2, 3, 4, 5}},\n\t\t{\"exactly 16\", make([]int32, 16)},\n\t\t{\"large\", make([]int32, 1000)},\n\t\t{\"negative\", []int32{-1, -2, -3, 4, 5}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = int32(rand.Int32())\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := SumInt32x16(tc.input)\n\t\t\twant := lo.Sum(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"SumInt32x16() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestSumInt64x8(t *testing.T) {\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []int64\n\t}{\n\t\t{\"empty\", []int64{}},\n\t\t{\"single\", []int64{42}},\n\t\t{\"small\", []int64{1, 2, 3, 4, 5}},\n\t\t{\"exactly 8\", make([]int64, 8)},\n\t\t{\"large\", make([]int64, 1000)},\n\t\t{\"negative\", []int64{-1, -2, -3, 4, 5}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Int64()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := SumInt64x8(tc.input)\n\t\t\twant := lo.Sum(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"SumInt64x8() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestSumUint8x64(t *testing.T) {\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []uint8\n\t}{\n\t\t{\"empty\", []uint8{}},\n\t\t{\"single\", []uint8{42}},\n\t\t{\"small\", []uint8{1, 2, 3, 4, 5}},\n\t\t{\"exactly 64\", make([]uint8, 64)},\n\t\t{\"large\", make([]uint8, 1000)},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = uint8(rand.IntN(256))\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := SumUint8x64(tc.input)\n\t\t\twant := lo.Sum(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"SumUint8x64() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestSumUint16x32(t *testing.T) {\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []uint16\n\t}{\n\t\t{\"empty\", []uint16{}},\n\t\t{\"single\", []uint16{42}},\n\t\t{\"small\", []uint16{1, 2, 3, 4, 5}},\n\t\t{\"exactly 32\", make([]uint16, 32)},\n\t\t{\"large\", make([]uint16, 1000)},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = uint16(rand.IntN(65536))\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := SumUint16x32(tc.input)\n\t\t\twant := lo.Sum(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"SumUint16x32() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestSumUint32x16(t *testing.T) {\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []uint32\n\t}{\n\t\t{\"empty\", []uint32{}},\n\t\t{\"single\", []uint32{42}},\n\t\t{\"small\", []uint32{1, 2, 3, 4, 5}},\n\t\t{\"exactly 16\", make([]uint32, 16)},\n\t\t{\"large\", make([]uint32, 1000)},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Uint32()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := SumUint32x16(tc.input)\n\t\t\twant := lo.Sum(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"SumUint32x16() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestSumUint64x8(t *testing.T) {\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []uint64\n\t}{\n\t\t{\"empty\", []uint64{}},\n\t\t{\"single\", []uint64{42}},\n\t\t{\"small\", []uint64{1, 2, 3, 4, 5}},\n\t\t{\"exactly 8\", make([]uint64, 8)},\n\t\t{\"large\", make([]uint64, 1000)},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Uint64()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := SumUint64x8(tc.input)\n\t\t\twant := lo.Sum(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"SumUint64x8() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestSumFloat32x16(t *testing.T) {\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []float32\n\t}{\n\t\t{\"empty\", []float32{}},\n\t\t{\"single\", []float32{42.5}},\n\t\t{\"small\", []float32{1.1, 2.2, 3.3, 4.4, 5.5}},\n\t\t{\"exactly 16\", make([]float32, 16)},\n\t\t{\"large\", make([]float32, 1000)},\n\t\t{\"negative\", []float32{-1.1, -2.2, 3.3, 4.4}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Float32()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := SumFloat32x16(tc.input)\n\t\t\twant := lo.Sum(tc.input)\n\n\t\t\tconst epsilon = 1e-3\n\t\t\tif diff := got - want; diff < -epsilon || diff > epsilon {\n\t\t\t\tt.Errorf(\"SumFloat32x16() = %v, want %v (diff: %v)\", got, want, diff)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestSumFloat64x8(t *testing.T) {\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []float64\n\t}{\n\t\t{\"empty\", []float64{}},\n\t\t{\"single\", []float64{42.5}},\n\t\t{\"small\", []float64{1.1, 2.2, 3.3, 4.4, 5.5}},\n\t\t{\"exactly 8\", make([]float64, 8)},\n\t\t{\"large\", make([]float64, 1000)},\n\t\t{\"negative\", []float64{-1.1, -2.2, 3.3, 4.4}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Float64()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := SumFloat64x8(tc.input)\n\t\t\twant := lo.Sum(tc.input)\n\n\t\t\tconst epsilon = 1e-3\n\t\t\tif diff := got - want; diff < -epsilon || diff > epsilon {\n\t\t\t\tt.Errorf(\"SumFloat64x8() = %v, want %v (diff: %v)\", got, want, diff)\n\t\t\t}\n\t\t})\n\t}\n}\n\n// Test type aliases work correctly\nfunc TestAVX512TypeAlias(t *testing.T) {\n\trequireAVX512(t)\n\tinput := []myInt32{1, 2, 3, 4, 5}\n\tgot := SumInt32x16(input)\n\twant := lo.Sum(input)\n\n\tif got != want {\n\t\tt.Errorf(\"SumInt32x16() with type alias = %v, want %v\", got, want)\n\t}\n}\n\nfunc TestMeanInt8x64(t *testing.T) {\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []int8\n\t}{\n\t\t{\"empty\", []int8{}},\n\t\t{\"single\", []int8{42}},\n\t\t{\"small\", []int8{1, 2, 3, 4, 5}},\n\t\t{\"exactly 64\", make([]int8, 64)},\n\t\t{\"large\", make([]int8, 1000)},\n\t\t{\"negative\", []int8{-1, -2, -3, 4, 5}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = int8(rand.IntN(256) - 128)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MeanInt8x64(tc.input)\n\t\t\twant := lo.Mean(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MeanInt8x64() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMeanInt16x32(t *testing.T) {\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []int16\n\t}{\n\t\t{\"empty\", []int16{}},\n\t\t{\"single\", []int16{42}},\n\t\t{\"small\", []int16{1, 2, 3, 4, 5}},\n\t\t{\"exactly 32\", make([]int16, 32)},\n\t\t{\"large\", make([]int16, 1000)},\n\t\t{\"negative\", []int16{-1, -2, -3, 4, 5}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = int16(rand.IntN(65536) - 32768)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MeanInt16x32(tc.input)\n\t\t\twant := lo.Mean(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MeanInt16x32() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMeanInt32x16(t *testing.T) {\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []int32\n\t}{\n\t\t{\"empty\", []int32{}},\n\t\t{\"single\", []int32{42}},\n\t\t{\"small\", []int32{1, 2, 3, 4, 5}},\n\t\t{\"exactly 16\", make([]int32, 16)},\n\t\t{\"large\", make([]int32, 1000)},\n\t\t{\"negative\", []int32{-1, -2, -3, 4, 5}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = int32(rand.Int32())\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MeanInt32x16(tc.input)\n\t\t\twant := lo.Mean(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MeanInt32x16() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMeanInt64x8(t *testing.T) {\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []int64\n\t}{\n\t\t{\"empty\", []int64{}},\n\t\t{\"single\", []int64{42}},\n\t\t{\"small\", []int64{1, 2, 3, 4, 5}},\n\t\t{\"exactly 8\", make([]int64, 8)},\n\t\t{\"large\", make([]int64, 1000)},\n\t\t{\"negative\", []int64{-1, -2, -3, 4, 5}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Int64()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MeanInt64x8(tc.input)\n\t\t\twant := lo.Mean(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MeanInt64x8() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMeanUint8x64(t *testing.T) {\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []uint8\n\t}{\n\t\t{\"empty\", []uint8{}},\n\t\t{\"single\", []uint8{42}},\n\t\t{\"small\", []uint8{1, 2, 3, 4, 5}},\n\t\t{\"exactly 64\", make([]uint8, 64)},\n\t\t{\"large\", make([]uint8, 1000)},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = uint8(rand.IntN(256))\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MeanUint8x64(tc.input)\n\t\t\twant := lo.Mean(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MeanUint8x64() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMeanUint16x32(t *testing.T) {\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []uint16\n\t}{\n\t\t{\"empty\", []uint16{}},\n\t\t{\"single\", []uint16{42}},\n\t\t{\"small\", []uint16{1, 2, 3, 4, 5}},\n\t\t{\"exactly 32\", make([]uint16, 32)},\n\t\t{\"large\", make([]uint16, 1000)},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = uint16(rand.IntN(65536))\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MeanUint16x32(tc.input)\n\t\t\twant := lo.Mean(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MeanUint16x32() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMeanUint32x16(t *testing.T) {\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []uint32\n\t}{\n\t\t{\"empty\", []uint32{}},\n\t\t{\"single\", []uint32{42}},\n\t\t{\"small\", []uint32{1, 2, 3, 4, 5}},\n\t\t{\"exactly 16\", make([]uint32, 16)},\n\t\t{\"large\", make([]uint32, 1000)},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Uint32()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MeanUint32x16(tc.input)\n\t\t\twant := lo.Mean(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MeanUint32x16() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMeanUint64x8(t *testing.T) {\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []uint64\n\t}{\n\t\t{\"empty\", []uint64{}},\n\t\t{\"single\", []uint64{42}},\n\t\t{\"small\", []uint64{1, 2, 3, 4, 5}},\n\t\t{\"exactly 8\", make([]uint64, 8)},\n\t\t{\"large\", make([]uint64, 1000)},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Uint64()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MeanUint64x8(tc.input)\n\t\t\twant := lo.Mean(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MeanUint64x8() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMeanFloat32x16(t *testing.T) {\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []float32\n\t}{\n\t\t{\"empty\", []float32{}},\n\t\t{\"single\", []float32{42.5}},\n\t\t{\"small\", []float32{1.1, 2.2, 3.3, 4.4, 5.5}},\n\t\t{\"exactly 16\", make([]float32, 16)},\n\t\t{\"large\", make([]float32, 1000)},\n\t\t{\"negative\", []float32{-1.1, -2.2, 3.3, 4.4}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Float32()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MeanFloat32x16(tc.input)\n\t\t\twant := lo.Mean(tc.input)\n\n\t\t\tconst epsilon = 1e-3\n\t\t\tif diff := got - want; diff < -epsilon || diff > epsilon {\n\t\t\t\tt.Errorf(\"MeanFloat32x16() = %v, want %v (diff: %v)\", got, want, diff)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMeanFloat64x8(t *testing.T) {\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []float64\n\t}{\n\t\t{\"empty\", []float64{}},\n\t\t{\"single\", []float64{42.5}},\n\t\t{\"small\", []float64{1.1, 2.2, 3.3, 4.4, 5.5}},\n\t\t{\"exactly 8\", make([]float64, 8)},\n\t\t{\"large\", make([]float64, 1000)},\n\t\t{\"negative\", []float64{-1.1, -2.2, 3.3, 4.4}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Float64()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MeanFloat64x8(tc.input)\n\t\t\twant := lo.Mean(tc.input)\n\n\t\t\tconst epsilon = 1e-3\n\t\t\tif diff := got - want; diff < -epsilon || diff > epsilon {\n\t\t\t\tt.Errorf(\"MeanFloat64x8() = %v, want %v (diff: %v)\", got, want, diff)\n\t\t\t}\n\t\t})\n\t}\n}\n\n// Test type aliases work correctly\nfunc TestAVX512MeanTypeAlias(t *testing.T) {\n\trequireAVX512(t)\n\tinput := []myInt32{1, 2, 3, 4, 5}\n\tgot := MeanInt32x16(input)\n\twant := lo.Mean(input)\n\n\tif got != want {\n\t\tt.Errorf(\"MeanInt32x16() with type alias = %v, want %v\", got, want)\n\t}\n}\n\nfunc TestClampInt8x64(t *testing.T) {\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []int8\n\t\tmin   int8\n\t\tmax   int8\n\t}{\n\t\t{\"empty\", []int8{}, -10, 10},\n\t\t{\"single\", []int8{42}, -10, 10},\n\t\t{\"small\", []int8{1, 2, 3, 4, 5}, 2, 4},\n\t\t{\"exactly 64\", make([]int8, 64), 5, 10},\n\t\t{\"large\", make([]int8, 1000), -5, 5},\n\t\t{\"all below min\", []int8{-10, -20, -30}, -5, 10},\n\t\t{\"all above max\", []int8{20, 30, 40}, -10, 10},\n\t\t{\"already clamped\", []int8{5, 6, 7}, 5, 10},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = int8(rand.IntN(256) - 128)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := ClampInt8x64(tc.input, tc.min, tc.max)\n\n\t\t\tif len(got) != len(tc.input) {\n\t\t\t\tt.Errorf(\"ClampInt8x64() returned length %d, want %d\", len(got), len(tc.input))\n\t\t\t}\n\n\t\t\tfor i, v := range got {\n\t\t\t\tif v < tc.min || v > tc.max {\n\t\t\t\t\tt.Errorf(\"ClampInt8x64()[%d] = %v, outside range [%v, %v]\", i, v, tc.min, tc.max)\n\t\t\t\t}\n\t\t\t\toriginal := tc.input[i]\n\t\t\t\texpected := original\n\t\t\t\tif expected < tc.min {\n\t\t\t\t\texpected = tc.min\n\t\t\t\t} else if expected > tc.max {\n\t\t\t\t\texpected = tc.max\n\t\t\t\t}\n\t\t\t\tif v != expected {\n\t\t\t\t\tt.Errorf(\"ClampInt8x64()[%d] = %v, want %v (original: %v)\", i, v, expected, original)\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestClampInt16x32(t *testing.T) {\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []int16\n\t\tmin   int16\n\t\tmax   int16\n\t}{\n\t\t{\"empty\", []int16{}, -100, 100},\n\t\t{\"single\", []int16{42}, -10, 10},\n\t\t{\"small\", []int16{1, 2, 3, 4, 5}, 2, 4},\n\t\t{\"exactly 32\", make([]int16, 32), 50, 100},\n\t\t{\"large\", make([]int16, 1000), -50, 50},\n\t\t{\"all below min\", []int16{-100, -200, -300}, -50, 100},\n\t\t{\"all above max\", []int16{200, 300, 400}, -100, 100},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = int16(rand.IntN(65536) - 32768)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := ClampInt16x32(tc.input, tc.min, tc.max)\n\n\t\t\tif len(got) != len(tc.input) {\n\t\t\t\tt.Errorf(\"ClampInt16x32() returned length %d, want %d\", len(got), len(tc.input))\n\t\t\t}\n\n\t\t\tfor i, v := range got {\n\t\t\t\tif v < tc.min || v > tc.max {\n\t\t\t\t\tt.Errorf(\"ClampInt16x32()[%d] = %v, outside range [%v, %v]\", i, v, tc.min, tc.max)\n\t\t\t\t}\n\t\t\t\toriginal := tc.input[i]\n\t\t\t\texpected := original\n\t\t\t\tif expected < tc.min {\n\t\t\t\t\texpected = tc.min\n\t\t\t\t} else if expected > tc.max {\n\t\t\t\t\texpected = tc.max\n\t\t\t\t}\n\t\t\t\tif v != expected {\n\t\t\t\t\tt.Errorf(\"ClampInt16x32()[%d] = %v, want %v (original: %v)\", i, v, expected, original)\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestClampInt32x16(t *testing.T) {\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []int32\n\t\tmin   int32\n\t\tmax   int32\n\t}{\n\t\t{\"empty\", []int32{}, -100, 100},\n\t\t{\"single\", []int32{42}, -10, 10},\n\t\t{\"small\", []int32{1, 2, 3, 4, 5}, 2, 4},\n\t\t{\"exactly 16\", make([]int32, 16), 50, 100},\n\t\t{\"large\", make([]int32, 1000), -50, 50},\n\t\t{\"negative range\", []int32{-100, -50, 0, 50, 100}, -30, -10},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Int32()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := ClampInt32x16(tc.input, tc.min, tc.max)\n\n\t\t\tif len(got) != len(tc.input) {\n\t\t\t\tt.Errorf(\"ClampInt32x16() returned length %d, want %d\", len(got), len(tc.input))\n\t\t\t}\n\n\t\t\tfor i, v := range got {\n\t\t\t\tif v < tc.min || v > tc.max {\n\t\t\t\t\tt.Errorf(\"ClampInt32x16()[%d] = %v, outside range [%v, %v]\", i, v, tc.min, tc.max)\n\t\t\t\t}\n\t\t\t\toriginal := tc.input[i]\n\t\t\t\texpected := original\n\t\t\t\tif expected < tc.min {\n\t\t\t\t\texpected = tc.min\n\t\t\t\t} else if expected > tc.max {\n\t\t\t\t\texpected = tc.max\n\t\t\t\t}\n\t\t\t\tif v != expected {\n\t\t\t\t\tt.Errorf(\"ClampInt32x16()[%d] = %v, want %v (original: %v)\", i, v, expected, original)\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestClampInt64x2(t *testing.T) {\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []int64\n\t\tmin   int64\n\t\tmax   int64\n\t}{\n\t\t{\"empty\", []int64{}, -100, 100},\n\t\t{\"single\", []int64{42}, -10, 10},\n\t\t{\"small\", []int64{1, 2, 3, 4, 5}, 2, 4},\n\t\t{\"exactly 2\", []int64{-100, 200}, -50, 50},\n\t\t{\"large\", make([]int64, 1000), -50, 50},\n\t\t{\"all below min\", []int64{-1000, -2000, -3000}, -500, 100},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Int64()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := ClampInt64x2(tc.input, tc.min, tc.max)\n\n\t\t\tif len(got) != len(tc.input) {\n\t\t\t\tt.Errorf(\"ClampInt64x2() returned length %d, want %d\", len(got), len(tc.input))\n\t\t\t}\n\n\t\t\tfor i, v := range got {\n\t\t\t\tif v < tc.min || v > tc.max {\n\t\t\t\t\tt.Errorf(\"ClampInt64x2()[%d] = %v, outside range [%v, %v]\", i, v, tc.min, tc.max)\n\t\t\t\t}\n\t\t\t\toriginal := tc.input[i]\n\t\t\t\texpected := original\n\t\t\t\tif expected < tc.min {\n\t\t\t\t\texpected = tc.min\n\t\t\t\t} else if expected > tc.max {\n\t\t\t\t\texpected = tc.max\n\t\t\t\t}\n\t\t\t\tif v != expected {\n\t\t\t\t\tt.Errorf(\"ClampInt64x2()[%d] = %v, want %v (original: %v)\", i, v, expected, original)\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestClampInt64x8(t *testing.T) {\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []int64\n\t\tmin   int64\n\t\tmax   int64\n\t}{\n\t\t{\"empty\", []int64{}, -100, 100},\n\t\t{\"single\", []int64{42}, -10, 10},\n\t\t{\"small\", []int64{1, 2, 3, 4, 5}, 2, 4},\n\t\t{\"exactly 8\", make([]int64, 8), 50, 100},\n\t\t{\"large\", make([]int64, 1000), -50, 50},\n\t\t{\"all below min\", []int64{-1000, -2000, -3000}, -500, 100},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Int64()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := ClampInt64x8(tc.input, tc.min, tc.max)\n\n\t\t\tif len(got) != len(tc.input) {\n\t\t\t\tt.Errorf(\"ClampInt64x8() returned length %d, want %d\", len(got), len(tc.input))\n\t\t\t}\n\n\t\t\tfor i, v := range got {\n\t\t\t\tif v < tc.min || v > tc.max {\n\t\t\t\t\tt.Errorf(\"ClampInt64x8()[%d] = %v, outside range [%v, %v]\", i, v, tc.min, tc.max)\n\t\t\t\t}\n\t\t\t\toriginal := tc.input[i]\n\t\t\t\texpected := original\n\t\t\t\tif expected < tc.min {\n\t\t\t\t\texpected = tc.min\n\t\t\t\t} else if expected > tc.max {\n\t\t\t\t\texpected = tc.max\n\t\t\t\t}\n\t\t\t\tif v != expected {\n\t\t\t\t\tt.Errorf(\"ClampInt64x8()[%d] = %v, want %v (original: %v)\", i, v, expected, original)\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestClampUint8x64(t *testing.T) {\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []uint8\n\t\tmin   uint8\n\t\tmax   uint8\n\t}{\n\t\t{\"empty\", []uint8{}, 10, 100},\n\t\t{\"single\", []uint8{42}, 10, 100},\n\t\t{\"small\", []uint8{1, 2, 3, 4, 5}, 2, 4},\n\t\t{\"exactly 64\", make([]uint8, 64), 50, 100},\n\t\t{\"large\", make([]uint8, 1000), 50, 200},\n\t\t{\"all below min\", []uint8{1, 2, 3}, 10, 100},\n\t\t{\"all above max\", []uint8{200, 225, 250}, 50, 150},\n\t\t{\"max values\", []uint8{255, 255, 255}, 100, 200},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = uint8(rand.IntN(256))\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := ClampUint8x64(tc.input, tc.min, tc.max)\n\n\t\t\tif len(got) != len(tc.input) {\n\t\t\t\tt.Errorf(\"ClampUint8x64() returned length %d, want %d\", len(got), len(tc.input))\n\t\t\t}\n\n\t\t\tfor i, v := range got {\n\t\t\t\tif v < tc.min || v > tc.max {\n\t\t\t\t\tt.Errorf(\"ClampUint8x64()[%d] = %v, outside range [%v, %v]\", i, v, tc.min, tc.max)\n\t\t\t\t}\n\t\t\t\toriginal := tc.input[i]\n\t\t\t\texpected := original\n\t\t\t\tif expected < tc.min {\n\t\t\t\t\texpected = tc.min\n\t\t\t\t} else if expected > tc.max {\n\t\t\t\t\texpected = tc.max\n\t\t\t\t}\n\t\t\t\tif v != expected {\n\t\t\t\t\tt.Errorf(\"ClampUint8x64()[%d] = %v, want %v (original: %v)\", i, v, expected, original)\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestClampUint16x32(t *testing.T) {\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []uint16\n\t\tmin   uint16\n\t\tmax   uint16\n\t}{\n\t\t{\"empty\", []uint16{}, 100, 1000},\n\t\t{\"single\", []uint16{42}, 10, 100},\n\t\t{\"small\", []uint16{1, 2, 3, 4, 5}, 2, 4},\n\t\t{\"exactly 32\", make([]uint16, 32), 500, 1000},\n\t\t{\"large\", make([]uint16, 1000), 500, 5000},\n\t\t{\"all below min\", []uint16{1, 2, 3}, 10, 100},\n\t\t{\"all above max\", []uint16{2000, 3000, 4000}, 100, 1000},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = uint16(rand.IntN(65536))\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := ClampUint16x32(tc.input, tc.min, tc.max)\n\n\t\t\tif len(got) != len(tc.input) {\n\t\t\t\tt.Errorf(\"ClampUint16x32() returned length %d, want %d\", len(got), len(tc.input))\n\t\t\t}\n\n\t\t\tfor i, v := range got {\n\t\t\t\tif v < tc.min || v > tc.max {\n\t\t\t\t\tt.Errorf(\"ClampUint16x32()[%d] = %v, outside range [%v, %v]\", i, v, tc.min, tc.max)\n\t\t\t\t}\n\t\t\t\toriginal := tc.input[i]\n\t\t\t\texpected := original\n\t\t\t\tif expected < tc.min {\n\t\t\t\t\texpected = tc.min\n\t\t\t\t} else if expected > tc.max {\n\t\t\t\t\texpected = tc.max\n\t\t\t\t}\n\t\t\t\tif v != expected {\n\t\t\t\t\tt.Errorf(\"ClampUint16x32()[%d] = %v, want %v (original: %v)\", i, v, expected, original)\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestClampUint32x16(t *testing.T) {\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []uint32\n\t\tmin   uint32\n\t\tmax   uint32\n\t}{\n\t\t{\"empty\", []uint32{}, 100, 1000},\n\t\t{\"single\", []uint32{42}, 10, 100},\n\t\t{\"small\", []uint32{1, 2, 3, 4, 5}, 2, 4},\n\t\t{\"exactly 16\", make([]uint32, 16), 500, 1000},\n\t\t{\"large\", make([]uint32, 1000), 500, 5000},\n\t\t{\"all below min\", []uint32{1, 2, 3}, 10, 100},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Uint32()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := ClampUint32x16(tc.input, tc.min, tc.max)\n\n\t\t\tif len(got) != len(tc.input) {\n\t\t\t\tt.Errorf(\"ClampUint32x16() returned length %d, want %d\", len(got), len(tc.input))\n\t\t\t}\n\n\t\t\tfor i, v := range got {\n\t\t\t\tif v < tc.min || v > tc.max {\n\t\t\t\t\tt.Errorf(\"ClampUint32x16()[%d] = %v, outside range [%v, %v]\", i, v, tc.min, tc.max)\n\t\t\t\t}\n\t\t\t\toriginal := tc.input[i]\n\t\t\t\texpected := original\n\t\t\t\tif expected < tc.min {\n\t\t\t\t\texpected = tc.min\n\t\t\t\t} else if expected > tc.max {\n\t\t\t\t\texpected = tc.max\n\t\t\t\t}\n\t\t\t\tif v != expected {\n\t\t\t\t\tt.Errorf(\"ClampUint32x16()[%d] = %v, want %v (original: %v)\", i, v, expected, original)\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestClampUint64x2(t *testing.T) {\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []uint64\n\t\tmin   uint64\n\t\tmax   uint64\n\t}{\n\t\t{\"empty\", []uint64{}, 100, 1000},\n\t\t{\"single\", []uint64{42}, 10, 100},\n\t\t{\"small\", []uint64{1, 2, 3, 4, 5}, 2, 4},\n\t\t{\"exactly 2\", []uint64{50, 2000}, 100, 1000},\n\t\t{\"large\", make([]uint64, 1000), 500, 5000},\n\t\t{\"all below min\", []uint64{1, 2, 3}, 10, 100},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Uint64()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := ClampUint64x2(tc.input, tc.min, tc.max)\n\n\t\t\tif len(got) != len(tc.input) {\n\t\t\t\tt.Errorf(\"ClampUint64x2() returned length %d, want %d\", len(got), len(tc.input))\n\t\t\t}\n\n\t\t\tfor i, v := range got {\n\t\t\t\tif v < tc.min || v > tc.max {\n\t\t\t\t\tt.Errorf(\"ClampUint64x2()[%d] = %v, outside range [%v, %v]\", i, v, tc.min, tc.max)\n\t\t\t\t}\n\t\t\t\toriginal := tc.input[i]\n\t\t\t\texpected := original\n\t\t\t\tif expected < tc.min {\n\t\t\t\t\texpected = tc.min\n\t\t\t\t} else if expected > tc.max {\n\t\t\t\t\texpected = tc.max\n\t\t\t\t}\n\t\t\t\tif v != expected {\n\t\t\t\t\tt.Errorf(\"ClampUint64x2()[%d] = %v, want %v (original: %v)\", i, v, expected, original)\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestClampUint64x8(t *testing.T) {\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []uint64\n\t\tmin   uint64\n\t\tmax   uint64\n\t}{\n\t\t{\"empty\", []uint64{}, 100, 1000},\n\t\t{\"single\", []uint64{42}, 10, 100},\n\t\t{\"small\", []uint64{1, 2, 3, 4, 5}, 2, 4},\n\t\t{\"exactly 8\", make([]uint64, 8), 500, 1000},\n\t\t{\"large\", make([]uint64, 1000), 500, 5000},\n\t\t{\"all below min\", []uint64{1, 2, 3}, 10, 100},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Uint64()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := ClampUint64x8(tc.input, tc.min, tc.max)\n\n\t\t\tif len(got) != len(tc.input) {\n\t\t\t\tt.Errorf(\"ClampUint64x8() returned length %d, want %d\", len(got), len(tc.input))\n\t\t\t}\n\n\t\t\tfor i, v := range got {\n\t\t\t\tif v < tc.min || v > tc.max {\n\t\t\t\t\tt.Errorf(\"ClampUint64x8()[%d] = %v, outside range [%v, %v]\", i, v, tc.min, tc.max)\n\t\t\t\t}\n\t\t\t\toriginal := tc.input[i]\n\t\t\t\texpected := original\n\t\t\t\tif expected < tc.min {\n\t\t\t\t\texpected = tc.min\n\t\t\t\t} else if expected > tc.max {\n\t\t\t\t\texpected = tc.max\n\t\t\t\t}\n\t\t\t\tif v != expected {\n\t\t\t\t\tt.Errorf(\"ClampUint64x8()[%d] = %v, want %v (original: %v)\", i, v, expected, original)\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestClampFloat32x16(t *testing.T) {\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []float32\n\t\tmin   float32\n\t\tmax   float32\n\t}{\n\t\t{\"empty\", []float32{}, -10.0, 10.0},\n\t\t{\"single\", []float32{42.5}, -10.0, 10.0},\n\t\t{\"small\", []float32{1.1, 2.2, 3.3, 4.4, 5.5}, 2.0, 4.0},\n\t\t{\"exactly 16\", make([]float32, 16), -5.0, 10.0},\n\t\t{\"large\", make([]float32, 1000), -5.0, 5.0},\n\t\t{\"negative range\", []float32{-10.0, -5.0, 0.0, 5.0, 10.0}, -3.0, -1.0},\n\t\t{\"all below min\", []float32{-20.0, -30.0, -40.0}, -10.0, 10.0},\n\t\t{\"all above max\", []float32{20.0, 30.0, 40.0}, -10.0, 10.0},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Float32()*200 - 100\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := ClampFloat32x16(tc.input, tc.min, tc.max)\n\n\t\t\tif len(got) != len(tc.input) {\n\t\t\t\tt.Errorf(\"ClampFloat32x16() returned length %d, want %d\", len(got), len(tc.input))\n\t\t\t}\n\n\t\t\tconst epsilon = 1e-3\n\t\t\tfor i, v := range got {\n\t\t\t\tif v < tc.min-epsilon || v > tc.max+epsilon {\n\t\t\t\t\tt.Errorf(\"ClampFloat32x16()[%d] = %v, outside range [%v, %v]\", i, v, tc.min, tc.max)\n\t\t\t\t}\n\t\t\t\toriginal := tc.input[i]\n\t\t\t\texpected := original\n\t\t\t\tif expected < tc.min {\n\t\t\t\t\texpected = tc.min\n\t\t\t\t} else if expected > tc.max {\n\t\t\t\t\texpected = tc.max\n\t\t\t\t}\n\t\t\t\tif diff := v - expected; diff < -epsilon || diff > epsilon {\n\t\t\t\t\tt.Errorf(\"ClampFloat32x16()[%d] = %v, want %v (original: %v, diff: %v)\", i, v, expected, original, diff)\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestClampFloat64x8(t *testing.T) {\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []float64\n\t\tmin   float64\n\t\tmax   float64\n\t}{\n\t\t{\"empty\", []float64{}, -10.0, 10.0},\n\t\t{\"single\", []float64{42.5}, -10.0, 10.0},\n\t\t{\"small\", []float64{1.1, 2.2, 3.3, 4.4, 5.5}, 2.0, 4.0},\n\t\t{\"exactly 8\", make([]float64, 8), -5.0, 10.0},\n\t\t{\"large\", make([]float64, 1000), -5.0, 5.0},\n\t\t{\"negative range\", []float64{-10.0, -5.0, 0.0, 5.0, 10.0}, -3.0, -1.0},\n\t\t{\"all below min\", []float64{-20.0, -30.0, -40.0}, -10.0, 10.0},\n\t\t{\"all above max\", []float64{20.0, 30.0, 40.0}, -10.0, 10.0},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Float64()*200 - 100\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := ClampFloat64x8(tc.input, tc.min, tc.max)\n\n\t\t\tif len(got) != len(tc.input) {\n\t\t\t\tt.Errorf(\"ClampFloat64x8() returned length %d, want %d\", len(got), len(tc.input))\n\t\t\t}\n\n\t\t\tconst epsilon = 1e-3\n\t\t\tfor i, v := range got {\n\t\t\t\tif v < tc.min-epsilon || v > tc.max+epsilon {\n\t\t\t\t\tt.Errorf(\"ClampFloat64x8()[%d] = %v, outside range [%v, %v]\", i, v, tc.min, tc.max)\n\t\t\t\t}\n\t\t\t\toriginal := tc.input[i]\n\t\t\t\texpected := original\n\t\t\t\tif expected < tc.min {\n\t\t\t\t\texpected = tc.min\n\t\t\t\t} else if expected > tc.max {\n\t\t\t\t\texpected = tc.max\n\t\t\t\t}\n\t\t\t\tif diff := v - expected; diff < -epsilon || diff > epsilon {\n\t\t\t\t\tt.Errorf(\"ClampFloat64x8()[%d] = %v, want %v (original: %v, diff: %v)\", i, v, expected, original, diff)\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\n// Test type aliases work correctly\nfunc TestAVX512ClampTypeAlias(t *testing.T) {\n\trequireAVX512(t)\n\tinput := []myInt32{-5, 0, 10, 15, 20}\n\tmin := myInt32(0)\n\tmax := myInt32(10)\n\tgot := ClampInt32x16(input, min, max)\n\n\tfor i, v := range got {\n\t\tif v < min || v > max {\n\t\t\tt.Errorf(\"ClampInt32x16()[%d] with type alias = %v, outside range [%v, %v]\", i, v, min, max)\n\t\t}\n\t\toriginal := input[i]\n\t\texpected := original\n\t\tif expected < min {\n\t\t\texpected = min\n\t\t} else if expected > max {\n\t\t\texpected = max\n\t\t}\n\t\tif v != expected {\n\t\t\tt.Errorf(\"ClampInt32x16()[%d] with type alias = %v, want %v (original: %v)\", i, v, expected, original)\n\t\t}\n\t}\n}\n\nfunc TestMinInt8x64(t *testing.T) {\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []int8\n\t}{\n\t\t{\"empty\", []int8{}},\n\t\t{\"single\", []int8{42}},\n\t\t{\"small\", []int8{1, 2, 3, 4, 5}},\n\t\t{\"exactly 64\", make([]int8, 64)},\n\t\t{\"large\", make([]int8, 1000)},\n\t\t{\"negative\", []int8{-1, -2, -3, 4, 5}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = int8(rand.IntN(256) - 128)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MinInt8x64(tc.input)\n\t\t\twant := lo.Min(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MinInt8x64() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMinInt16x32(t *testing.T) {\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []int16\n\t}{\n\t\t{\"empty\", []int16{}},\n\t\t{\"single\", []int16{42}},\n\t\t{\"small\", []int16{1, 2, 3, 4, 5}},\n\t\t{\"exactly 32\", make([]int16, 32)},\n\t\t{\"large\", make([]int16, 1000)},\n\t\t{\"negative\", []int16{-1, -2, -3, 4, 5}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = int16(rand.IntN(65536) - 32768)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MinInt16x32(tc.input)\n\t\t\twant := lo.Min(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MinInt16x32() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMinInt32x16(t *testing.T) {\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []int32\n\t}{\n\t\t{\"empty\", []int32{}},\n\t\t{\"single\", []int32{42}},\n\t\t{\"small\", []int32{1, 2, 3, 4, 5}},\n\t\t{\"exactly 16\", make([]int32, 16)},\n\t\t{\"large\", make([]int32, 1000)},\n\t\t{\"negative\", []int32{-1, -2, -3, 4, 5}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Int32()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MinInt32x16(tc.input)\n\t\t\twant := lo.Min(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MinInt32x16() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMinInt64x2(t *testing.T) {\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []int64\n\t}{\n\t\t{\"empty\", []int64{}},\n\t\t{\"single\", []int64{42}},\n\t\t{\"small\", []int64{1, 2, 3, 4, 5}},\n\t\t{\"exactly 2\", []int64{1, 2}},\n\t\t{\"large\", make([]int64, 1000)},\n\t\t{\"negative\", []int64{-1, -2, -3, 4, 5}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Int64()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MinInt64x2(tc.input)\n\t\t\twant := lo.Min(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MinInt64x2() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMinInt64x8(t *testing.T) {\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []int64\n\t}{\n\t\t{\"empty\", []int64{}},\n\t\t{\"single\", []int64{42}},\n\t\t{\"small\", []int64{1, 2, 3, 4, 5}},\n\t\t{\"exactly 8\", make([]int64, 8)},\n\t\t{\"large\", make([]int64, 1000)},\n\t\t{\"negative\", []int64{-1, -2, -3, 4, 5}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Int64()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MinInt64x8(tc.input)\n\t\t\twant := lo.Min(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MinInt64x8() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMinUint8x64(t *testing.T) {\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []uint8\n\t}{\n\t\t{\"empty\", []uint8{}},\n\t\t{\"single\", []uint8{42}},\n\t\t{\"small\", []uint8{1, 2, 3, 4, 5}},\n\t\t{\"exactly 64\", make([]uint8, 64)},\n\t\t{\"large\", make([]uint8, 1000)},\n\t\t{\"max values\", []uint8{255, 100, 50}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = uint8(rand.IntN(256))\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MinUint8x64(tc.input)\n\t\t\twant := lo.Min(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MinUint8x64() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMinUint16x32(t *testing.T) {\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []uint16\n\t}{\n\t\t{\"empty\", []uint16{}},\n\t\t{\"single\", []uint16{42}},\n\t\t{\"small\", []uint16{1, 2, 3, 4, 5}},\n\t\t{\"exactly 32\", make([]uint16, 32)},\n\t\t{\"large\", make([]uint16, 1000)},\n\t\t{\"max values\", []uint16{65535, 1000, 500}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = uint16(rand.IntN(65536))\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MinUint16x32(tc.input)\n\t\t\twant := lo.Min(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MinUint16x32() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMinUint32x16(t *testing.T) {\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []uint32\n\t}{\n\t\t{\"empty\", []uint32{}},\n\t\t{\"single\", []uint32{42}},\n\t\t{\"small\", []uint32{1, 2, 3, 4, 5}},\n\t\t{\"exactly 16\", make([]uint32, 16)},\n\t\t{\"large\", make([]uint32, 1000)},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Uint32()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MinUint32x16(tc.input)\n\t\t\twant := lo.Min(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MinUint32x16() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMinUint64x2(t *testing.T) {\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []uint64\n\t}{\n\t\t{\"empty\", []uint64{}},\n\t\t{\"single\", []uint64{42}},\n\t\t{\"small\", []uint64{1, 2, 3, 4, 5}},\n\t\t{\"exactly 2\", []uint64{1, 2}},\n\t\t{\"large\", make([]uint64, 1000)},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Uint64()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MinUint64x2(tc.input)\n\t\t\twant := lo.Min(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MinUint64x2() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMinUint64x8(t *testing.T) {\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []uint64\n\t}{\n\t\t{\"empty\", []uint64{}},\n\t\t{\"single\", []uint64{42}},\n\t\t{\"small\", []uint64{1, 2, 3, 4, 5}},\n\t\t{\"exactly 8\", make([]uint64, 8)},\n\t\t{\"large\", make([]uint64, 1000)},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Uint64()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MinUint64x8(tc.input)\n\t\t\twant := lo.Min(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MinUint64x8() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMinFloat32x16(t *testing.T) {\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []float32\n\t}{\n\t\t{\"empty\", []float32{}},\n\t\t{\"single\", []float32{42.5}},\n\t\t{\"small\", []float32{1.1, 2.2, 3.3, 4.4, 5.5}},\n\t\t{\"exactly 16\", make([]float32, 16)},\n\t\t{\"large\", make([]float32, 1000)},\n\t\t{\"negative\", []float32{-1.1, -2.2, 3.3, 4.4}},\n\t\t{\"zeros\", []float32{0, 0, 0, 0}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Float32()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MinFloat32x16(tc.input)\n\t\t\twant := lo.Min(tc.input)\n\n\t\t\tconst epsilon = 1e-3\n\t\t\tif diff := got - want; diff < -epsilon || diff > epsilon {\n\t\t\t\tt.Errorf(\"MinFloat32x16() = %v, want %v (diff: %v)\", got, want, diff)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMinFloat64x8(t *testing.T) {\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []float64\n\t}{\n\t\t{\"empty\", []float64{}},\n\t\t{\"single\", []float64{42.5}},\n\t\t{\"small\", []float64{1.1, 2.2, 3.3, 4.4, 5.5}},\n\t\t{\"exactly 8\", []float64{1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0}},\n\t\t{\"large\", make([]float64, 1000)},\n\t\t{\"negative\", []float64{-1.1, -2.2, 3.3, 4.4}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Float64()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MinFloat64x8(tc.input)\n\t\t\twant := lo.Min(tc.input)\n\n\t\t\tconst epsilon = 1e-3\n\t\t\tif diff := got - want; diff < -epsilon || diff > epsilon {\n\t\t\t\tt.Errorf(\"MinFloat64x8() = %v, want %v (diff: %v)\", got, want, diff)\n\t\t\t}\n\t\t})\n\t}\n}\n\n// Test type aliases work correctly\nfunc TestAVX512MinTypeAlias(t *testing.T) {\n\trequireAVX512(t)\n\tinput := []myInt32{5, 2, 8, 1, 9}\n\tgot := MinInt32x16(input)\n\twant := myInt32(1)\n\n\tif got != want {\n\t\tt.Errorf(\"MinInt32x16() with type alias = %v, want %v\", got, want)\n\t}\n}\n\nfunc TestMaxInt8x64(t *testing.T) {\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []int8\n\t}{\n\t\t{\"empty\", []int8{}},\n\t\t{\"single\", []int8{42}},\n\t\t{\"small\", []int8{1, 2, 3, 4, 5}},\n\t\t{\"exactly 64\", make([]int8, 64)},\n\t\t{\"large\", make([]int8, 1000)},\n\t\t{\"negative\", []int8{-1, -2, -3, 4, 5}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = int8(rand.IntN(256) - 128)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MaxInt8x64(tc.input)\n\t\t\twant := lo.Max(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MaxInt8x64() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMaxInt16x32(t *testing.T) {\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []int16\n\t}{\n\t\t{\"empty\", []int16{}},\n\t\t{\"single\", []int16{42}},\n\t\t{\"small\", []int16{1, 2, 3, 4, 5}},\n\t\t{\"exactly 32\", make([]int16, 32)},\n\t\t{\"large\", make([]int16, 1000)},\n\t\t{\"negative\", []int16{-1, -2, -3, 4, 5}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = int16(rand.IntN(65536) - 32768)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MaxInt16x32(tc.input)\n\t\t\twant := lo.Max(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MaxInt16x32() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMaxInt32x16(t *testing.T) {\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []int32\n\t}{\n\t\t{\"empty\", []int32{}},\n\t\t{\"single\", []int32{42}},\n\t\t{\"small\", []int32{1, 2, 3, 4, 5}},\n\t\t{\"exactly 16\", make([]int32, 16)},\n\t\t{\"large\", make([]int32, 1000)},\n\t\t{\"negative\", []int32{-1, -2, -3, 4, 5}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Int32()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MaxInt32x16(tc.input)\n\t\t\twant := lo.Max(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MaxInt32x16() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMaxInt64x2(t *testing.T) {\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []int64\n\t}{\n\t\t{\"empty\", []int64{}},\n\t\t{\"single\", []int64{42}},\n\t\t{\"small\", []int64{1, 2, 3, 4, 5}},\n\t\t{\"exactly 2\", []int64{1, 2}},\n\t\t{\"large\", make([]int64, 1000)},\n\t\t{\"negative\", []int64{-1, -2, -3, 4, 5}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Int64()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MaxInt64x2(tc.input)\n\t\t\twant := lo.Max(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MaxInt64x2() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMaxInt64x8(t *testing.T) {\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []int64\n\t}{\n\t\t{\"empty\", []int64{}},\n\t\t{\"single\", []int64{42}},\n\t\t{\"small\", []int64{1, 2, 3, 4, 5}},\n\t\t{\"exactly 8\", make([]int64, 8)},\n\t\t{\"large\", make([]int64, 1000)},\n\t\t{\"negative\", []int64{-1, -2, -3, 4, 5}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Int64()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MaxInt64x8(tc.input)\n\t\t\twant := lo.Max(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MaxInt64x8() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMaxUint8x64(t *testing.T) {\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []uint8\n\t}{\n\t\t{\"empty\", []uint8{}},\n\t\t{\"single\", []uint8{42}},\n\t\t{\"small\", []uint8{1, 2, 3, 4, 5}},\n\t\t{\"exactly 64\", make([]uint8, 64)},\n\t\t{\"large\", make([]uint8, 1000)},\n\t\t{\"max values\", []uint8{255, 100, 50}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = uint8(rand.IntN(256))\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MaxUint8x64(tc.input)\n\t\t\twant := lo.Max(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MaxUint8x64() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMaxUint16x32(t *testing.T) {\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []uint16\n\t}{\n\t\t{\"empty\", []uint16{}},\n\t\t{\"single\", []uint16{42}},\n\t\t{\"small\", []uint16{1, 2, 3, 4, 5}},\n\t\t{\"exactly 32\", make([]uint16, 32)},\n\t\t{\"large\", make([]uint16, 1000)},\n\t\t{\"max values\", []uint16{65535, 1000, 500}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = uint16(rand.IntN(65536))\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MaxUint16x32(tc.input)\n\t\t\twant := lo.Max(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MaxUint16x32() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMaxUint32x16(t *testing.T) {\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []uint32\n\t}{\n\t\t{\"empty\", []uint32{}},\n\t\t{\"single\", []uint32{42}},\n\t\t{\"small\", []uint32{1, 2, 3, 4, 5}},\n\t\t{\"exactly 16\", make([]uint32, 16)},\n\t\t{\"large\", make([]uint32, 1000)},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Uint32()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MaxUint32x16(tc.input)\n\t\t\twant := lo.Max(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MaxUint32x16() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMaxUint64x2(t *testing.T) {\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []uint64\n\t}{\n\t\t{\"empty\", []uint64{}},\n\t\t{\"single\", []uint64{42}},\n\t\t{\"small\", []uint64{1, 2, 3, 4, 5}},\n\t\t{\"exactly 2\", []uint64{1, 2}},\n\t\t{\"large\", make([]uint64, 1000)},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Uint64()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MaxUint64x2(tc.input)\n\t\t\twant := lo.Max(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MaxUint64x2() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMaxUint64x8(t *testing.T) {\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []uint64\n\t}{\n\t\t{\"empty\", []uint64{}},\n\t\t{\"single\", []uint64{42}},\n\t\t{\"small\", []uint64{1, 2, 3, 4, 5}},\n\t\t{\"exactly 8\", make([]uint64, 8)},\n\t\t{\"large\", make([]uint64, 1000)},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Uint64()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MaxUint64x8(tc.input)\n\t\t\twant := lo.Max(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MaxUint64x8() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMaxFloat32x16(t *testing.T) {\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []float32\n\t}{\n\t\t{\"empty\", []float32{}},\n\t\t{\"single\", []float32{42.5}},\n\t\t{\"small\", []float32{1.1, 2.2, 3.3, 4.4, 5.5}},\n\t\t{\"exactly 16\", make([]float32, 16)},\n\t\t{\"large\", make([]float32, 1000)},\n\t\t{\"negative\", []float32{-1.1, -2.2, 3.3, 4.4}},\n\t\t{\"zeros\", []float32{0, 0, 0, 0}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Float32()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MaxFloat32x16(tc.input)\n\t\t\twant := lo.Max(tc.input)\n\n\t\t\tconst epsilon = 1e-3\n\t\t\tif diff := got - want; diff < -epsilon || diff > epsilon {\n\t\t\t\tt.Errorf(\"MaxFloat32x16() = %v, want %v (diff: %v)\", got, want, diff)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMaxFloat64x8(t *testing.T) {\n\trequireAVX512(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []float64\n\t}{\n\t\t{\"empty\", []float64{}},\n\t\t{\"single\", []float64{42.5}},\n\t\t{\"small\", []float64{1.1, 2.2, 3.3, 4.4, 5.5}},\n\t\t{\"exactly 8\", []float64{1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0}},\n\t\t{\"large\", make([]float64, 1000)},\n\t\t{\"negative\", []float64{-1.1, -2.2, 3.3, 4.4}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Float64()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MaxFloat64x8(tc.input)\n\t\t\twant := lo.Max(tc.input)\n\n\t\t\tconst epsilon = 1e-3\n\t\t\tif diff := got - want; diff < -epsilon || diff > epsilon {\n\t\t\t\tt.Errorf(\"MaxFloat64x8() = %v, want %v (diff: %v)\", got, want, diff)\n\t\t\t}\n\t\t})\n\t}\n}\n\n// Test type aliases work correctly\nfunc TestAVX512MaxTypeAlias(t *testing.T) {\n\trequireAVX512(t)\n\tinput := []myInt32{5, 2, 8, 1, 9}\n\tgot := MaxInt32x16(input)\n\twant := myInt32(9)\n\n\tif got != want {\n\t\tt.Errorf(\"MaxInt32x16() with type alias = %v, want %v\", got, want)\n\t}\n}\n\n// SumBy tests\n\ntype avx512Item struct {\n\tValue      int8\n\tWeight     int8\n\tMultiplier int8\n}\n\nfunc TestSumByInt8x64(t *testing.T) {\n\trequireAVX512(t)\n\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []avx512Item\n\t}{\n\t\t{\"empty\", []avx512Item{}},\n\t\t{\"single\", []avx512Item{{Value: 42}}},\n\t\t{\"small\", []avx512Item{{Value: 1}, {Value: 2}, {Value: 3}, {Value: 4}, {Value: 5}}},\n\t\t{\"exactly 64\", make([]avx512Item, 64)},\n\t\t{\"large\", make([]avx512Item, 1000)},\n\t\t{\"negative\", []avx512Item{{Value: -1}, {Value: -2}, {Value: -3}, {Value: 4}, {Value: 5}}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0].Value == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i].Value = int8(rand.IntN(256) - 128)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Using Value field as the iteratee\n\t\t\tgot := SumByInt8x64(tc.input, func(i avx512Item) int8 { return i.Value })\n\t\t\twant := lo.Sum(lo.Map(tc.input, func(i avx512Item, _ int) int8 { return i.Value }))\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"SumByInt8x64() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestSumByInt16x32(t *testing.T) {\n\trequireAVX512(t)\n\n\ttype avx512ItemInt16 struct {\n\t\tValue int16\n\t}\n\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []avx512ItemInt16\n\t}{\n\t\t{\"empty\", []avx512ItemInt16{}},\n\t\t{\"single\", []avx512ItemInt16{{Value: 42}}},\n\t\t{\"small\", []avx512ItemInt16{{1}, {2}, {3}, {4}, {5}}},\n\t\t{\"exactly 32\", make([]avx512ItemInt16, 32)},\n\t\t{\"large\", make([]avx512ItemInt16, 1000)},\n\t\t{\"negative\", []avx512ItemInt16{{-1}, {-2}, {-3}, {4}, {5}}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0].Value == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i].Value = int16(rand.IntN(65536) - 32768)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := SumByInt16x32(tc.input, func(i avx512ItemInt16) int16 { return i.Value })\n\t\t\twant := lo.Sum(lo.Map(tc.input, func(i avx512ItemInt16, _ int) int16 { return i.Value }))\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"SumByInt16x32() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestSumByInt32x16(t *testing.T) {\n\trequireAVX512(t)\n\n\ttype avx512ItemInt32 struct {\n\t\tValue int32\n\t}\n\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []avx512ItemInt32\n\t}{\n\t\t{\"empty\", []avx512ItemInt32{}},\n\t\t{\"single\", []avx512ItemInt32{{Value: 42}}},\n\t\t{\"small\", []avx512ItemInt32{{1}, {2}, {3}, {4}, {5}}},\n\t\t{\"exactly 16\", make([]avx512ItemInt32, 16)},\n\t\t{\"large\", make([]avx512ItemInt32, 1000)},\n\t\t{\"negative\", []avx512ItemInt32{{-1}, {-2}, {-3}, {4}, {5}}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0].Value == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i].Value = rand.Int32()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := SumByInt32x16(tc.input, func(i avx512ItemInt32) int32 { return i.Value })\n\t\t\twant := lo.Sum(lo.Map(tc.input, func(i avx512ItemInt32, _ int) int32 { return i.Value }))\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"SumByInt32x16() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestSumByInt64x8(t *testing.T) {\n\trequireAVX512(t)\n\n\ttype avx512ItemInt64 struct {\n\t\tValue int64\n\t}\n\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []avx512ItemInt64\n\t}{\n\t\t{\"empty\", []avx512ItemInt64{}},\n\t\t{\"single\", []avx512ItemInt64{{Value: 42}}},\n\t\t{\"small\", []avx512ItemInt64{{1}, {2}, {3}, {4}, {5}}},\n\t\t{\"exactly 8\", make([]avx512ItemInt64, 8)},\n\t\t{\"large\", make([]avx512ItemInt64, 1000)},\n\t\t{\"negative\", []avx512ItemInt64{{-1}, {-2}, {-3}, {4}, {5}}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0].Value == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i].Value = rand.Int64()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := SumByInt64x8(tc.input, func(i avx512ItemInt64) int64 { return i.Value })\n\t\t\twant := lo.Sum(lo.Map(tc.input, func(i avx512ItemInt64, _ int) int64 { return i.Value }))\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"SumByInt64x8() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestSumByUint8x64(t *testing.T) {\n\trequireAVX512(t)\n\n\ttype avx512ItemUint8 struct {\n\t\tValue uint8\n\t}\n\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []avx512ItemUint8\n\t}{\n\t\t{\"empty\", []avx512ItemUint8{}},\n\t\t{\"single\", []avx512ItemUint8{{Value: 42}}},\n\t\t{\"small\", []avx512ItemUint8{{1}, {2}, {3}, {4}, {5}}},\n\t\t{\"exactly 64\", make([]avx512ItemUint8, 64)},\n\t\t{\"large\", make([]avx512ItemUint8, 1000)},\n\t\t{\"max values\", []avx512ItemUint8{{Value: 255}, {Value: 255}, {Value: 1}}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0].Value == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i].Value = uint8(rand.IntN(256))\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := SumByUint8x64(tc.input, func(i avx512ItemUint8) uint8 { return i.Value })\n\t\t\twant := lo.Sum(lo.Map(tc.input, func(i avx512ItemUint8, _ int) uint8 { return i.Value }))\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"SumByUint8x64() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestSumByUint16x32(t *testing.T) {\n\trequireAVX512(t)\n\n\ttype avx512ItemUint16 struct {\n\t\tValue uint16\n\t}\n\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []avx512ItemUint16\n\t}{\n\t\t{\"empty\", []avx512ItemUint16{}},\n\t\t{\"single\", []avx512ItemUint16{{Value: 42}}},\n\t\t{\"small\", []avx512ItemUint16{{1}, {2}, {3}, {4}, {5}}},\n\t\t{\"exactly 32\", make([]avx512ItemUint16, 32)},\n\t\t{\"large\", make([]avx512ItemUint16, 1000)},\n\t\t{\"max values\", []avx512ItemUint16{{Value: 65535}, {Value: 1}}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0].Value == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i].Value = uint16(rand.IntN(65536))\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := SumByUint16x32(tc.input, func(i avx512ItemUint16) uint16 { return i.Value })\n\t\t\twant := lo.Sum(lo.Map(tc.input, func(i avx512ItemUint16, _ int) uint16 { return i.Value }))\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"SumByUint16x32() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestSumByUint32x16(t *testing.T) {\n\trequireAVX512(t)\n\n\ttype avx512ItemUint32 struct {\n\t\tValue uint32\n\t}\n\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []avx512ItemUint32\n\t}{\n\t\t{\"empty\", []avx512ItemUint32{}},\n\t\t{\"single\", []avx512ItemUint32{{Value: 42}}},\n\t\t{\"small\", []avx512ItemUint32{{1}, {2}, {3}, {4}, {5}}},\n\t\t{\"exactly 16\", make([]avx512ItemUint32, 16)},\n\t\t{\"large\", make([]avx512ItemUint32, 1000)},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0].Value == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i].Value = rand.Uint32()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := SumByUint32x16(tc.input, func(i avx512ItemUint32) uint32 { return i.Value })\n\t\t\twant := lo.Sum(lo.Map(tc.input, func(i avx512ItemUint32, _ int) uint32 { return i.Value }))\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"SumByUint32x16() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestSumByUint64x8(t *testing.T) {\n\trequireAVX512(t)\n\n\ttype avx512ItemUint64 struct {\n\t\tValue uint64\n\t}\n\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []avx512ItemUint64\n\t}{\n\t\t{\"empty\", []avx512ItemUint64{}},\n\t\t{\"single\", []avx512ItemUint64{{Value: 42}}},\n\t\t{\"small\", []avx512ItemUint64{{1}, {2}, {3}, {4}, {5}}},\n\t\t{\"exactly 8\", make([]avx512ItemUint64, 8)},\n\t\t{\"large\", make([]avx512ItemUint64, 1000)},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0].Value == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i].Value = rand.Uint64()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := SumByUint64x8(tc.input, func(i avx512ItemUint64) uint64 { return i.Value })\n\t\t\twant := lo.Sum(lo.Map(tc.input, func(i avx512ItemUint64, _ int) uint64 { return i.Value }))\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"SumByUint64x8() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestSumByFloat32x16(t *testing.T) {\n\trequireAVX512(t)\n\n\ttype avx512ItemFloat32 struct {\n\t\tValue float32\n\t}\n\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []avx512ItemFloat32\n\t}{\n\t\t{\"empty\", []avx512ItemFloat32{}},\n\t\t{\"single\", []avx512ItemFloat32{{Value: 42.5}}},\n\t\t{\"small\", []avx512ItemFloat32{{1.1}, {2.2}, {3.3}, {4.4}, {5.5}}},\n\t\t{\"exactly 16\", make([]avx512ItemFloat32, 16)},\n\t\t{\"large\", make([]avx512ItemFloat32, 1000)},\n\t\t{\"negative\", []avx512ItemFloat32{{-1.1}, {-2.2}, {3.3}, {4.4}}},\n\t\t{\"zeros\", []avx512ItemFloat32{{0}, {0}, {0}, {0}}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0].Value == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i].Value = rand.Float32()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := SumByFloat32x16(tc.input, func(i avx512ItemFloat32) float32 { return i.Value })\n\t\t\twant := lo.Sum(lo.Map(tc.input, func(i avx512ItemFloat32, _ int) float32 { return i.Value }))\n\n\t\t\tconst epsilon = 1e-3\n\t\t\tif diff := got - want; diff < -epsilon || diff > epsilon {\n\t\t\t\tt.Errorf(\"SumByFloat32x16() = %v, want %v (diff: %v)\", got, want, diff)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestSumByFloat64x8(t *testing.T) {\n\trequireAVX512(t)\n\n\ttype avx512ItemFloat64 struct {\n\t\tValue float64\n\t}\n\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []avx512ItemFloat64\n\t}{\n\t\t{\"empty\", []avx512ItemFloat64{}},\n\t\t{\"single\", []avx512ItemFloat64{{Value: 42.5}}},\n\t\t{\"small\", []avx512ItemFloat64{{1.1}, {2.2}, {3.3}, {4.4}, {5.5}}},\n\t\t{\"exactly 8\", make([]avx512ItemFloat64, 8)},\n\t\t{\"large\", make([]avx512ItemFloat64, 1000)},\n\t\t{\"negative\", []avx512ItemFloat64{{-1.1}, {-2.2}, {3.3}, {4.4}}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0].Value == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i].Value = rand.Float64()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := SumByFloat64x8(tc.input, func(i avx512ItemFloat64) float64 { return i.Value })\n\t\t\twant := lo.Sum(lo.Map(tc.input, func(i avx512ItemFloat64, _ int) float64 { return i.Value }))\n\n\t\t\tconst epsilon = 1e-3\n\t\t\tif diff := got - want; diff < -epsilon || diff > epsilon {\n\t\t\t\tt.Errorf(\"SumByFloat64x8() = %v, want %v (diff: %v)\", got, want, diff)\n\t\t\t}\n\t\t})\n\t}\n}\n\n// Test type alias works correctly for SumBy\nfunc TestAVX512SumByTypeAlias(t *testing.T) {\n\trequireAVX512(t)\n\n\ttype myAVX512Item struct {\n\t\tValue myInt8\n\t}\n\n\tinput := []myAVX512Item{{Value: 1}, {Value: 2}, {Value: 3}, {Value: 4}, {Value: 5}}\n\tgot := SumByInt8x64(input, func(i myAVX512Item) myInt8 { return i.Value })\n\twant := myInt8(15)\n\n\tif got != want {\n\t\tt.Errorf(\"SumByInt8x64() with type alias = %v, want %v\", got, want)\n\t}\n}\n\n// MeanBy tests\n\nfunc TestMeanByInt8x64(t *testing.T) {\n\trequireAVX512(t)\n\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []avx512Item\n\t}{\n\t\t{\"empty\", []avx512Item{}},\n\t\t{\"single\", []avx512Item{{Value: 42}}},\n\t\t{\"small\", []avx512Item{{Value: 1}, {Value: 2}, {Value: 3}, {Value: 4}, {Value: 5}}},\n\t\t{\"exactly 64\", make([]avx512Item, 64)},\n\t\t{\"large\", make([]avx512Item, 1000)},\n\t\t{\"negative\", []avx512Item{{Value: -1}, {Value: -2}, {Value: -3}, {Value: 4}, {Value: 5}}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0].Value == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i].Value = int8(rand.IntN(256) - 128)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MeanByInt8x64(tc.input, func(i avx512Item) int8 { return i.Value })\n\t\t\twant := lo.Mean(lo.Map(tc.input, func(i avx512Item, _ int) int8 { return i.Value }))\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MeanByInt8x64() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMeanByInt16x32(t *testing.T) {\n\trequireAVX512(t)\n\n\ttype avx512ItemInt16 struct {\n\t\tValue int16\n\t}\n\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []avx512ItemInt16\n\t}{\n\t\t{\"empty\", []avx512ItemInt16{}},\n\t\t{\"single\", []avx512ItemInt16{{Value: 42}}},\n\t\t{\"small\", []avx512ItemInt16{{1}, {2}, {3}, {4}, {5}}},\n\t\t{\"exactly 32\", make([]avx512ItemInt16, 32)},\n\t\t{\"large\", make([]avx512ItemInt16, 1000)},\n\t\t{\"negative\", []avx512ItemInt16{{-1}, {-2}, {-3}, {4}, {5}}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0].Value == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i].Value = int16(rand.IntN(65536) - 32768)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MeanByInt16x32(tc.input, func(i avx512ItemInt16) int16 { return i.Value })\n\t\t\twant := lo.Mean(lo.Map(tc.input, func(i avx512ItemInt16, _ int) int16 { return i.Value }))\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MeanByInt16x32() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMeanByInt32x16(t *testing.T) {\n\trequireAVX512(t)\n\n\ttype avx512ItemInt32 struct {\n\t\tValue int32\n\t}\n\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []avx512ItemInt32\n\t}{\n\t\t{\"empty\", []avx512ItemInt32{}},\n\t\t{\"single\", []avx512ItemInt32{{Value: 42}}},\n\t\t{\"small\", []avx512ItemInt32{{1}, {2}, {3}, {4}, {5}}},\n\t\t{\"exactly 16\", make([]avx512ItemInt32, 16)},\n\t\t{\"large\", make([]avx512ItemInt32, 1000)},\n\t\t{\"negative\", []avx512ItemInt32{{-1}, {-2}, {-3}, {4}, {5}}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0].Value == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i].Value = rand.Int32()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MeanByInt32x16(tc.input, func(i avx512ItemInt32) int32 { return i.Value })\n\t\t\twant := lo.Mean(lo.Map(tc.input, func(i avx512ItemInt32, _ int) int32 { return i.Value }))\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MeanByInt32x16() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMeanByInt64x8(t *testing.T) {\n\trequireAVX512(t)\n\n\ttype avx512ItemInt64 struct {\n\t\tValue int64\n\t}\n\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []avx512ItemInt64\n\t}{\n\t\t{\"empty\", []avx512ItemInt64{}},\n\t\t{\"single\", []avx512ItemInt64{{Value: 42}}},\n\t\t{\"small\", []avx512ItemInt64{{1}, {2}, {3}, {4}, {5}}},\n\t\t{\"exactly 8\", make([]avx512ItemInt64, 8)},\n\t\t{\"large\", make([]avx512ItemInt64, 1000)},\n\t\t{\"negative\", []avx512ItemInt64{{-1}, {-2}, {-3}, {4}, {5}}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0].Value == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i].Value = rand.Int64()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MeanByInt64x8(tc.input, func(i avx512ItemInt64) int64 { return i.Value })\n\t\t\twant := lo.Mean(lo.Map(tc.input, func(i avx512ItemInt64, _ int) int64 { return i.Value }))\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MeanByInt64x8() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMeanByUint8x64(t *testing.T) {\n\trequireAVX512(t)\n\n\ttype avx512ItemUint8 struct {\n\t\tValue uint8\n\t}\n\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []avx512ItemUint8\n\t}{\n\t\t{\"empty\", []avx512ItemUint8{}},\n\t\t{\"single\", []avx512ItemUint8{{Value: 42}}},\n\t\t{\"small\", []avx512ItemUint8{{1}, {2}, {3}, {4}, {5}}},\n\t\t{\"exactly 64\", make([]avx512ItemUint8, 64)},\n\t\t{\"large\", make([]avx512ItemUint8, 1000)},\n\t\t{\"max values\", []avx512ItemUint8{{Value: 255}, {Value: 255}, {Value: 1}}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0].Value == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i].Value = uint8(rand.IntN(256))\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MeanByUint8x64(tc.input, func(i avx512ItemUint8) uint8 { return i.Value })\n\t\t\twant := lo.Mean(lo.Map(tc.input, func(i avx512ItemUint8, _ int) uint8 { return i.Value }))\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MeanByUint8x64() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMeanByUint16x32(t *testing.T) {\n\trequireAVX512(t)\n\n\ttype avx512ItemUint16 struct {\n\t\tValue uint16\n\t}\n\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []avx512ItemUint16\n\t}{\n\t\t{\"empty\", []avx512ItemUint16{}},\n\t\t{\"single\", []avx512ItemUint16{{Value: 42}}},\n\t\t{\"small\", []avx512ItemUint16{{1}, {2}, {3}, {4}, {5}}},\n\t\t{\"exactly 32\", make([]avx512ItemUint16, 32)},\n\t\t{\"large\", make([]avx512ItemUint16, 1000)},\n\t\t{\"max values\", []avx512ItemUint16{{Value: 65535}, {Value: 1}}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0].Value == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i].Value = uint16(rand.IntN(65536))\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MeanByUint16x32(tc.input, func(i avx512ItemUint16) uint16 { return i.Value })\n\t\t\twant := lo.Mean(lo.Map(tc.input, func(i avx512ItemUint16, _ int) uint16 { return i.Value }))\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MeanByUint16x32() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMeanByUint32x16(t *testing.T) {\n\trequireAVX512(t)\n\n\ttype avx512ItemUint32 struct {\n\t\tValue uint32\n\t}\n\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []avx512ItemUint32\n\t}{\n\t\t{\"empty\", []avx512ItemUint32{}},\n\t\t{\"single\", []avx512ItemUint32{{Value: 42}}},\n\t\t{\"small\", []avx512ItemUint32{{1}, {2}, {3}, {4}, {5}}},\n\t\t{\"exactly 16\", make([]avx512ItemUint32, 16)},\n\t\t{\"large\", make([]avx512ItemUint32, 1000)},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0].Value == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i].Value = rand.Uint32()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MeanByUint32x16(tc.input, func(i avx512ItemUint32) uint32 { return i.Value })\n\t\t\twant := lo.Mean(lo.Map(tc.input, func(i avx512ItemUint32, _ int) uint32 { return i.Value }))\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MeanByUint32x16() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMeanByUint64x8(t *testing.T) {\n\trequireAVX512(t)\n\n\ttype avx512ItemUint64 struct {\n\t\tValue uint64\n\t}\n\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []avx512ItemUint64\n\t}{\n\t\t{\"empty\", []avx512ItemUint64{}},\n\t\t{\"single\", []avx512ItemUint64{{Value: 42}}},\n\t\t{\"small\", []avx512ItemUint64{{1}, {2}, {3}, {4}, {5}}},\n\t\t{\"exactly 8\", make([]avx512ItemUint64, 8)},\n\t\t{\"large\", make([]avx512ItemUint64, 1000)},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0].Value == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i].Value = rand.Uint64()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MeanByUint64x8(tc.input, func(i avx512ItemUint64) uint64 { return i.Value })\n\t\t\twant := lo.Mean(lo.Map(tc.input, func(i avx512ItemUint64, _ int) uint64 { return i.Value }))\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MeanByUint64x8() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMeanByFloat32x16(t *testing.T) {\n\trequireAVX512(t)\n\n\ttype avx512ItemFloat32 struct {\n\t\tValue float32\n\t}\n\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []avx512ItemFloat32\n\t}{\n\t\t{\"empty\", []avx512ItemFloat32{}},\n\t\t{\"single\", []avx512ItemFloat32{{Value: 42.5}}},\n\t\t{\"small\", []avx512ItemFloat32{{1.1}, {2.2}, {3.3}, {4.4}, {5.5}}},\n\t\t{\"exactly 16\", make([]avx512ItemFloat32, 16)},\n\t\t{\"large\", make([]avx512ItemFloat32, 1000)},\n\t\t{\"negative\", []avx512ItemFloat32{{-1.1}, {-2.2}, {3.3}, {4.4}}},\n\t\t{\"zeros\", []avx512ItemFloat32{{0}, {0}, {0}, {0}}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0].Value == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i].Value = rand.Float32()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MeanByFloat32x16(tc.input, func(i avx512ItemFloat32) float32 { return i.Value })\n\t\t\twant := lo.Mean(lo.Map(tc.input, func(i avx512ItemFloat32, _ int) float32 { return i.Value }))\n\n\t\t\tconst epsilon = 1e-3\n\t\t\tif diff := got - want; diff < -epsilon || diff > epsilon {\n\t\t\t\tt.Errorf(\"MeanByFloat32x16() = %v, want %v (diff: %v)\", got, want, diff)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMeanByFloat64x8(t *testing.T) {\n\trequireAVX512(t)\n\n\ttype avx512ItemFloat64 struct {\n\t\tValue float64\n\t}\n\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []avx512ItemFloat64\n\t}{\n\t\t{\"empty\", []avx512ItemFloat64{}},\n\t\t{\"single\", []avx512ItemFloat64{{Value: 42.5}}},\n\t\t{\"small\", []avx512ItemFloat64{{1.1}, {2.2}, {3.3}, {4.4}, {5.5}}},\n\t\t{\"exactly 8\", make([]avx512ItemFloat64, 8)},\n\t\t{\"large\", make([]avx512ItemFloat64, 1000)},\n\t\t{\"negative\", []avx512ItemFloat64{{-1.1}, {-2.2}, {3.3}, {4.4}}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0].Value == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i].Value = rand.Float64()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MeanByFloat64x8(tc.input, func(i avx512ItemFloat64) float64 { return i.Value })\n\t\t\twant := lo.Mean(lo.Map(tc.input, func(i avx512ItemFloat64, _ int) float64 { return i.Value }))\n\n\t\t\tconst epsilon = 1e-3\n\t\t\tif diff := got - want; diff < -epsilon || diff > epsilon {\n\t\t\t\tt.Errorf(\"MeanByFloat64x8() = %v, want %v (diff: %v)\", got, want, diff)\n\t\t\t}\n\t\t})\n\t}\n}\n\n// Test type alias works correctly for MeanBy\nfunc TestAVX512MeanByTypeAlias(t *testing.T) {\n\trequireAVX512(t)\n\n\ttype myAVX512Item struct {\n\t\tValue myInt8\n\t}\n\n\tinput := []myAVX512Item{{Value: 1}, {Value: 2}, {Value: 3}, {Value: 4}, {Value: 5}}\n\tgot := MeanByInt8x64(input, func(i myAVX512Item) myInt8 { return i.Value })\n\twant := myInt8(3)\n\n\tif got != want {\n\t\tt.Errorf(\"MeanByInt8x64() with type alias = %v, want %v\", got, want)\n\t}\n}\n"
  },
  {
    "path": "exp/simd/math_avx_test.go",
    "content": "//go:build go1.26 && goexperiment.simd && amd64\n\npackage simd\n\nimport (\n\t\"math/rand/v2\"\n\t\"testing\"\n\n\t\"github.com/samber/lo\"\n)\n\nfunc TestSumInt8x16(t *testing.T) {\n\trequireAVX(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []int8\n\t}{\n\t\t{\"empty\", []int8{}},\n\t\t{\"single\", []int8{42}},\n\t\t{\"small\", []int8{1, 2, 3, 4, 5}},\n\t\t{\"exactly 16\", make([]int8, 16)},\n\t\t{\"large\", make([]int8, 1000)},\n\t\t{\"negative\", []int8{-1, -2, -3, 4, 5}},\n\t\t{\"mixed\", []int8{-128, 0, 127, 1, -1}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = int8(rand.IntN(256) - 128)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := SumInt8x16(tc.input)\n\t\t\twant := lo.Sum(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"SumInt8x16() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestSumInt16x8(t *testing.T) {\n\trequireAVX(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []int16\n\t}{\n\t\t{\"empty\", []int16{}},\n\t\t{\"single\", []int16{42}},\n\t\t{\"small\", []int16{1, 2, 3, 4, 5}},\n\t\t{\"exactly 8\", make([]int16, 8)},\n\t\t{\"large\", make([]int16, 1000)},\n\t\t{\"negative\", []int16{-1, -2, -3, 4, 5}},\n\t\t{\"mixed\", []int16{-32768, 0, 32767, 1, -1}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = int16(rand.IntN(65536) - 32768)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := SumInt16x8(tc.input)\n\t\t\twant := lo.Sum(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"SumInt16x8() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestSumInt32x4(t *testing.T) {\n\trequireAVX(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []int32\n\t}{\n\t\t{\"empty\", []int32{}},\n\t\t{\"single\", []int32{42}},\n\t\t{\"small\", []int32{1, 2, 3, 4, 5}},\n\t\t{\"exactly 4\", make([]int32, 4)},\n\t\t{\"large\", make([]int32, 1000)},\n\t\t{\"negative\", []int32{-1, -2, -3, 4, 5}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = int32(rand.Int32())\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := SumInt32x4(tc.input)\n\t\t\twant := lo.Sum(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"SumInt32x4() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestSumInt64x2(t *testing.T) {\n\trequireAVX(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []int64\n\t}{\n\t\t{\"empty\", []int64{}},\n\t\t{\"single\", []int64{42}},\n\t\t{\"small\", []int64{1, 2, 3, 4, 5}},\n\t\t{\"exactly 2\", []int64{1, 2}},\n\t\t{\"large\", make([]int64, 1000)},\n\t\t{\"negative\", []int64{-1, -2, -3, 4, 5}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Int64()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := SumInt64x2(tc.input)\n\t\t\twant := lo.Sum(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"SumInt64x2() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestSumUint8x16(t *testing.T) {\n\trequireAVX(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []uint8\n\t}{\n\t\t{\"empty\", []uint8{}},\n\t\t{\"single\", []uint8{42}},\n\t\t{\"small\", []uint8{1, 2, 3, 4, 5}},\n\t\t{\"exactly 16\", make([]uint8, 16)},\n\t\t{\"large\", make([]uint8, 1000)},\n\t\t{\"max values\", []uint8{255, 255, 1}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = uint8(rand.IntN(256))\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := SumUint8x16(tc.input)\n\t\t\twant := lo.Sum(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"SumUint8x16() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestSumUint16x8(t *testing.T) {\n\trequireAVX(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []uint16\n\t}{\n\t\t{\"empty\", []uint16{}},\n\t\t{\"single\", []uint16{42}},\n\t\t{\"small\", []uint16{1, 2, 3, 4, 5}},\n\t\t{\"exactly 8\", make([]uint16, 8)},\n\t\t{\"large\", make([]uint16, 1000)},\n\t\t{\"max values\", []uint16{65535, 1}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = uint16(rand.IntN(65536))\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := SumUint16x8(tc.input)\n\t\t\twant := lo.Sum(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"SumUint16x8() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestSumUint32x4(t *testing.T) {\n\trequireAVX(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []uint32\n\t}{\n\t\t{\"empty\", []uint32{}},\n\t\t{\"single\", []uint32{42}},\n\t\t{\"small\", []uint32{1, 2, 3, 4, 5}},\n\t\t{\"exactly 4\", make([]uint32, 4)},\n\t\t{\"large\", make([]uint32, 1000)},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Uint32()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := SumUint32x4(tc.input)\n\t\t\twant := lo.Sum(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"SumUint32x4() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestSumUint64x2(t *testing.T) {\n\trequireAVX(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []uint64\n\t}{\n\t\t{\"empty\", []uint64{}},\n\t\t{\"single\", []uint64{42}},\n\t\t{\"small\", []uint64{1, 2, 3, 4, 5}},\n\t\t{\"exactly 2\", []uint64{1, 2}},\n\t\t{\"large\", make([]uint64, 1000)},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Uint64()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := SumUint64x2(tc.input)\n\t\t\twant := lo.Sum(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"SumUint64x2() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestSumFloat32x4(t *testing.T) {\n\trequireAVX(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []float32\n\t}{\n\t\t{\"empty\", []float32{}},\n\t\t{\"single\", []float32{42.5}},\n\t\t{\"small\", []float32{1.1, 2.2, 3.3, 4.4, 5.5}},\n\t\t{\"exactly 4\", []float32{1.0, 2.0, 3.0, 4.0}},\n\t\t{\"large\", make([]float32, 1000)},\n\t\t{\"negative\", []float32{-1.1, -2.2, 3.3, 4.4}},\n\t\t{\"zeros\", []float32{0, 0, 0, 0}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Float32()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := SumFloat32x4(tc.input)\n\t\t\twant := lo.Sum(tc.input)\n\n\t\t\tconst epsilon = 1e-3\n\t\t\tif diff := got - want; diff < -epsilon || diff > epsilon {\n\t\t\t\tt.Errorf(\"SumFloat32x4() = %v, want %v (diff: %v)\", got, want, diff)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestSumFloat64x2(t *testing.T) {\n\trequireAVX(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []float64\n\t}{\n\t\t{\"empty\", []float64{}},\n\t\t{\"single\", []float64{42.5}},\n\t\t{\"small\", []float64{1.1, 2.2, 3.3, 4.4, 5.5}},\n\t\t{\"exactly 2\", []float64{1.0, 2.0}},\n\t\t{\"large\", make([]float64, 1000)},\n\t\t{\"negative\", []float64{-1.1, -2.2, 3.3, 4.4}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Float64()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := SumFloat64x2(tc.input)\n\t\t\twant := lo.Sum(tc.input)\n\n\t\t\tconst epsilon = 1e-3\n\t\t\tif diff := got - want; diff < -epsilon || diff > epsilon {\n\t\t\t\tt.Errorf(\"SumFloat64x2() = %v, want %v (diff: %v)\", got, want, diff)\n\t\t\t}\n\t\t})\n\t}\n}\n\n// Test type aliases work correctly\nfunc TestAVXTypeAlias(t *testing.T) {\n\trequireAVX(t)\n\tinput := []myInt8{1, 2, 3, 4, 5}\n\tgot := SumInt8x16(input)\n\twant := lo.Sum(input)\n\n\tif got != want {\n\t\tt.Errorf(\"SumInt8x16() with type alias = %v, want %v\", got, want)\n\t}\n}\n\nfunc TestClampInt8x16(t *testing.T) {\n\trequireAVX(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []int8\n\t\tmin   int8\n\t\tmax   int8\n\t}{\n\t\t{\"empty\", []int8{}, -10, 10},\n\t\t{\"single\", []int8{42}, -10, 10},\n\t\t{\"small\", []int8{1, 2, 3, 4, 5}, 2, 4},\n\t\t{\"exactly 16\", make([]int8, 16), 5, 10},\n\t\t{\"large\", make([]int8, 1000), -5, 5},\n\t\t{\"all below min\", []int8{-10, -20, -30}, -5, 10},\n\t\t{\"all above max\", []int8{20, 30, 40}, -10, 10},\n\t\t{\"already clamped\", []int8{5, 6, 7}, 5, 10},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = int8(rand.IntN(256) - 128)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := ClampInt8x16(tc.input, tc.min, tc.max)\n\n\t\t\tif len(got) != len(tc.input) {\n\t\t\t\tt.Errorf(\"ClampInt8x16() returned length %d, want %d\", len(got), len(tc.input))\n\t\t\t}\n\n\t\t\tfor i, v := range got {\n\t\t\t\tif v < tc.min || v > tc.max {\n\t\t\t\t\tt.Errorf(\"ClampInt8x16()[%d] = %v, outside range [%v, %v]\", i, v, tc.min, tc.max)\n\t\t\t\t}\n\t\t\t\t// Check that the value was properly clamped from the original\n\t\t\t\toriginal := tc.input[i]\n\t\t\t\texpected := original\n\t\t\t\tif expected < tc.min {\n\t\t\t\t\texpected = tc.min\n\t\t\t\t} else if expected > tc.max {\n\t\t\t\t\texpected = tc.max\n\t\t\t\t}\n\t\t\t\tif v != expected {\n\t\t\t\t\tt.Errorf(\"ClampInt8x16()[%d] = %v, want %v (original: %v)\", i, v, expected, original)\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestClampInt16x8(t *testing.T) {\n\trequireAVX(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []int16\n\t\tmin   int16\n\t\tmax   int16\n\t}{\n\t\t{\"empty\", []int16{}, -100, 100},\n\t\t{\"single\", []int16{42}, -10, 10},\n\t\t{\"small\", []int16{1, 2, 3, 4, 5}, 2, 4},\n\t\t{\"exactly 8\", make([]int16, 8), 50, 100},\n\t\t{\"large\", make([]int16, 1000), -50, 50},\n\t\t{\"all below min\", []int16{-100, -200, -300}, -50, 100},\n\t\t{\"all above max\", []int16{200, 300, 400}, -100, 100},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = int16(rand.IntN(65536) - 32768)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := ClampInt16x8(tc.input, tc.min, tc.max)\n\n\t\t\tif len(got) != len(tc.input) {\n\t\t\t\tt.Errorf(\"ClampInt16x8() returned length %d, want %d\", len(got), len(tc.input))\n\t\t\t}\n\n\t\t\tfor i, v := range got {\n\t\t\t\tif v < tc.min || v > tc.max {\n\t\t\t\t\tt.Errorf(\"ClampInt16x8()[%d] = %v, outside range [%v, %v]\", i, v, tc.min, tc.max)\n\t\t\t\t}\n\t\t\t\toriginal := tc.input[i]\n\t\t\t\texpected := original\n\t\t\t\tif expected < tc.min {\n\t\t\t\t\texpected = tc.min\n\t\t\t\t} else if expected > tc.max {\n\t\t\t\t\texpected = tc.max\n\t\t\t\t}\n\t\t\t\tif v != expected {\n\t\t\t\t\tt.Errorf(\"ClampInt16x8()[%d] = %v, want %v (original: %v)\", i, v, expected, original)\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestClampInt32x4(t *testing.T) {\n\trequireAVX(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []int32\n\t\tmin   int32\n\t\tmax   int32\n\t}{\n\t\t{\"empty\", []int32{}, -100, 100},\n\t\t{\"single\", []int32{42}, -10, 10},\n\t\t{\"small\", []int32{1, 2, 3, 4, 5}, 2, 4},\n\t\t{\"exactly 4\", []int32{1, 100, -50, 200}, 0, 100},\n\t\t{\"large\", make([]int32, 1000), -50, 50},\n\t\t{\"negative range\", []int32{-100, -50, 0, 50, 100}, -30, -10},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Int32()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := ClampInt32x4(tc.input, tc.min, tc.max)\n\n\t\t\tif len(got) != len(tc.input) {\n\t\t\t\tt.Errorf(\"ClampInt32x4() returned length %d, want %d\", len(got), len(tc.input))\n\t\t\t}\n\n\t\t\tfor i, v := range got {\n\t\t\t\tif v < tc.min || v > tc.max {\n\t\t\t\t\tt.Errorf(\"ClampInt32x4()[%d] = %v, outside range [%v, %v]\", i, v, tc.min, tc.max)\n\t\t\t\t}\n\t\t\t\toriginal := tc.input[i]\n\t\t\t\texpected := original\n\t\t\t\tif expected < tc.min {\n\t\t\t\t\texpected = tc.min\n\t\t\t\t} else if expected > tc.max {\n\t\t\t\t\texpected = tc.max\n\t\t\t\t}\n\t\t\t\tif v != expected {\n\t\t\t\t\tt.Errorf(\"ClampInt32x4()[%d] = %v, want %v (original: %v)\", i, v, expected, original)\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestClampUint8x16(t *testing.T) {\n\trequireAVX(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []uint8\n\t\tmin   uint8\n\t\tmax   uint8\n\t}{\n\t\t{\"empty\", []uint8{}, 10, 100},\n\t\t{\"single\", []uint8{42}, 10, 100},\n\t\t{\"small\", []uint8{1, 2, 3, 4, 5}, 2, 4},\n\t\t{\"exactly 16\", make([]uint8, 16), 50, 100},\n\t\t{\"large\", make([]uint8, 1000), 50, 200},\n\t\t{\"all below min\", []uint8{1, 2, 3}, 10, 100},\n\t\t{\"all above max\", []uint8{200, 225, 250}, 50, 150},\n\t\t{\"max values\", []uint8{255, 255, 255}, 100, 200},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = uint8(rand.IntN(256))\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := ClampUint8x16(tc.input, tc.min, tc.max)\n\n\t\t\tif len(got) != len(tc.input) {\n\t\t\t\tt.Errorf(\"ClampUint8x16() returned length %d, want %d\", len(got), len(tc.input))\n\t\t\t}\n\n\t\t\tfor i, v := range got {\n\t\t\t\tif v < tc.min || v > tc.max {\n\t\t\t\t\tt.Errorf(\"ClampUint8x16()[%d] = %v, outside range [%v, %v]\", i, v, tc.min, tc.max)\n\t\t\t\t}\n\t\t\t\toriginal := tc.input[i]\n\t\t\t\texpected := original\n\t\t\t\tif expected < tc.min {\n\t\t\t\t\texpected = tc.min\n\t\t\t\t} else if expected > tc.max {\n\t\t\t\t\texpected = tc.max\n\t\t\t\t}\n\t\t\t\tif v != expected {\n\t\t\t\t\tt.Errorf(\"ClampUint8x16()[%d] = %v, want %v (original: %v)\", i, v, expected, original)\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestClampUint16x8(t *testing.T) {\n\trequireAVX(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []uint16\n\t\tmin   uint16\n\t\tmax   uint16\n\t}{\n\t\t{\"empty\", []uint16{}, 100, 1000},\n\t\t{\"single\", []uint16{42}, 10, 100},\n\t\t{\"small\", []uint16{1, 2, 3, 4, 5}, 2, 4},\n\t\t{\"exactly 8\", make([]uint16, 8), 500, 1000},\n\t\t{\"large\", make([]uint16, 1000), 500, 5000},\n\t\t{\"all below min\", []uint16{1, 2, 3}, 10, 100},\n\t\t{\"all above max\", []uint16{2000, 3000, 4000}, 100, 1000},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = uint16(rand.IntN(65536))\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := ClampUint16x8(tc.input, tc.min, tc.max)\n\n\t\t\tif len(got) != len(tc.input) {\n\t\t\t\tt.Errorf(\"ClampUint16x8() returned length %d, want %d\", len(got), len(tc.input))\n\t\t\t}\n\n\t\t\tfor i, v := range got {\n\t\t\t\tif v < tc.min || v > tc.max {\n\t\t\t\t\tt.Errorf(\"ClampUint16x8()[%d] = %v, outside range [%v, %v]\", i, v, tc.min, tc.max)\n\t\t\t\t}\n\t\t\t\toriginal := tc.input[i]\n\t\t\t\texpected := original\n\t\t\t\tif expected < tc.min {\n\t\t\t\t\texpected = tc.min\n\t\t\t\t} else if expected > tc.max {\n\t\t\t\t\texpected = tc.max\n\t\t\t\t}\n\t\t\t\tif v != expected {\n\t\t\t\t\tt.Errorf(\"ClampUint16x8()[%d] = %v, want %v (original: %v)\", i, v, expected, original)\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestClampUint32x4(t *testing.T) {\n\trequireAVX(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []uint32\n\t\tmin   uint32\n\t\tmax   uint32\n\t}{\n\t\t{\"empty\", []uint32{}, 100, 1000},\n\t\t{\"single\", []uint32{42}, 10, 100},\n\t\t{\"small\", []uint32{1, 2, 3, 4, 5}, 2, 4},\n\t\t{\"exactly 4\", []uint32{1, 1000, 50, 2000}, 100, 1000},\n\t\t{\"large\", make([]uint32, 1000), 500, 5000},\n\t\t{\"all below min\", []uint32{1, 2, 3}, 10, 100},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Uint32()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := ClampUint32x4(tc.input, tc.min, tc.max)\n\n\t\t\tif len(got) != len(tc.input) {\n\t\t\t\tt.Errorf(\"ClampUint32x4() returned length %d, want %d\", len(got), len(tc.input))\n\t\t\t}\n\n\t\t\tfor i, v := range got {\n\t\t\t\tif v < tc.min || v > tc.max {\n\t\t\t\t\tt.Errorf(\"ClampUint32x4()[%d] = %v, outside range [%v, %v]\", i, v, tc.min, tc.max)\n\t\t\t\t}\n\t\t\t\toriginal := tc.input[i]\n\t\t\t\texpected := original\n\t\t\t\tif expected < tc.min {\n\t\t\t\t\texpected = tc.min\n\t\t\t\t} else if expected > tc.max {\n\t\t\t\t\texpected = tc.max\n\t\t\t\t}\n\t\t\t\tif v != expected {\n\t\t\t\t\tt.Errorf(\"ClampUint32x4()[%d] = %v, want %v (original: %v)\", i, v, expected, original)\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestClampFloat32x4(t *testing.T) {\n\trequireAVX(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []float32\n\t\tmin   float32\n\t\tmax   float32\n\t}{\n\t\t{\"empty\", []float32{}, -10.0, 10.0},\n\t\t{\"single\", []float32{42.5}, -10.0, 10.0},\n\t\t{\"small\", []float32{1.1, 2.2, 3.3, 4.4, 5.5}, 2.0, 4.0},\n\t\t{\"exactly 4\", []float32{1.0, 10.0, -5.0, 20.0}, -5.0, 10.0},\n\t\t{\"large\", make([]float32, 1000), -5.0, 5.0},\n\t\t{\"negative range\", []float32{-10.0, -5.0, 0.0, 5.0, 10.0}, -3.0, -1.0},\n\t\t{\"all below min\", []float32{-20.0, -30.0, -40.0}, -10.0, 10.0},\n\t\t{\"all above max\", []float32{20.0, 30.0, 40.0}, -10.0, 10.0},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Float32()*200 - 100\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := ClampFloat32x4(tc.input, tc.min, tc.max)\n\n\t\t\tif len(got) != len(tc.input) {\n\t\t\t\tt.Errorf(\"ClampFloat32x4() returned length %d, want %d\", len(got), len(tc.input))\n\t\t\t}\n\n\t\t\tconst epsilon = 1e-3\n\t\t\tfor i, v := range got {\n\t\t\t\tif v < tc.min-epsilon || v > tc.max+epsilon {\n\t\t\t\t\tt.Errorf(\"ClampFloat32x4()[%d] = %v, outside range [%v, %v]\", i, v, tc.min, tc.max)\n\t\t\t\t}\n\t\t\t\toriginal := tc.input[i]\n\t\t\t\texpected := original\n\t\t\t\tif expected < tc.min {\n\t\t\t\t\texpected = tc.min\n\t\t\t\t} else if expected > tc.max {\n\t\t\t\t\texpected = tc.max\n\t\t\t\t}\n\t\t\t\tif diff := v - expected; diff < -epsilon || diff > epsilon {\n\t\t\t\t\tt.Errorf(\"ClampFloat32x4()[%d] = %v, want %v (original: %v, diff: %v)\", i, v, expected, original, diff)\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestClampFloat64x2(t *testing.T) {\n\trequireAVX(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []float64\n\t\tmin   float64\n\t\tmax   float64\n\t}{\n\t\t{\"empty\", []float64{}, -10.0, 10.0},\n\t\t{\"single\", []float64{42.5}, -10.0, 10.0},\n\t\t{\"small\", []float64{1.1, 2.2, 3.3, 4.4, 5.5}, 2.0, 4.0},\n\t\t{\"exactly 2\", []float64{-100.0, 200.0}, -50.0, 50.0},\n\t\t{\"large\", make([]float64, 1000), -5.0, 5.0},\n\t\t{\"negative range\", []float64{-10.0, -5.0, 0.0, 5.0, 10.0}, -3.0, -1.0},\n\t\t{\"all below min\", []float64{-20.0, -30.0, -40.0}, -10.0, 10.0},\n\t\t{\"all above max\", []float64{20.0, 30.0, 40.0}, -10.0, 10.0},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Float64()*200 - 100\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := ClampFloat64x2(tc.input, tc.min, tc.max)\n\n\t\t\tif len(got) != len(tc.input) {\n\t\t\t\tt.Errorf(\"ClampFloat64x2() returned length %d, want %d\", len(got), len(tc.input))\n\t\t\t}\n\n\t\t\tconst epsilon = 1e-3\n\t\t\tfor i, v := range got {\n\t\t\t\tif v < tc.min-epsilon || v > tc.max+epsilon {\n\t\t\t\t\tt.Errorf(\"ClampFloat64x2()[%d] = %v, outside range [%v, %v]\", i, v, tc.min, tc.max)\n\t\t\t\t}\n\t\t\t\toriginal := tc.input[i]\n\t\t\t\texpected := original\n\t\t\t\tif expected < tc.min {\n\t\t\t\t\texpected = tc.min\n\t\t\t\t} else if expected > tc.max {\n\t\t\t\t\texpected = tc.max\n\t\t\t\t}\n\t\t\t\tif diff := v - expected; diff < -epsilon || diff > epsilon {\n\t\t\t\t\tt.Errorf(\"ClampFloat64x2()[%d] = %v, want %v (original: %v, diff: %v)\", i, v, expected, original, diff)\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\n// Test type aliases work correctly\nfunc TestAVXClampTypeAlias(t *testing.T) {\n\trequireAVX(t)\n\tinput := []myInt8{-5, 0, 10, 15, 20}\n\tmin := myInt8(0)\n\tmax := myInt8(10)\n\tgot := ClampInt8x16(input, min, max)\n\n\tfor i, v := range got {\n\t\tif v < min || v > max {\n\t\t\tt.Errorf(\"ClampInt8x16()[%d] with type alias = %v, outside range [%v, %v]\", i, v, min, max)\n\t\t}\n\t\toriginal := input[i]\n\t\texpected := original\n\t\tif expected < min {\n\t\t\texpected = min\n\t\t} else if expected > max {\n\t\t\texpected = max\n\t\t}\n\t\tif v != expected {\n\t\t\tt.Errorf(\"ClampInt8x16()[%d] with type alias = %v, want %v (original: %v)\", i, v, expected, original)\n\t\t}\n\t}\n}\n\nfunc TestMeanInt8x16(t *testing.T) {\n\trequireAVX(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []int8\n\t}{\n\t\t{\"empty\", []int8{}},\n\t\t{\"single\", []int8{42}},\n\t\t{\"small\", []int8{1, 2, 3, 4, 5}},\n\t\t{\"exactly 16\", make([]int8, 16)},\n\t\t{\"large\", make([]int8, 1000)},\n\t\t{\"negative\", []int8{-1, -2, -3, 4, 5}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = int8(rand.IntN(256) - 128)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MeanInt8x16(tc.input)\n\t\t\twant := lo.Mean(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MeanInt8x16() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMeanInt16x8(t *testing.T) {\n\trequireAVX(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []int16\n\t}{\n\t\t{\"empty\", []int16{}},\n\t\t{\"single\", []int16{42}},\n\t\t{\"small\", []int16{1, 2, 3, 4, 5}},\n\t\t{\"exactly 8\", make([]int16, 8)},\n\t\t{\"large\", make([]int16, 1000)},\n\t\t{\"negative\", []int16{-1, -2, -3, 4, 5}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = int16(rand.IntN(65536) - 32768)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MeanInt16x8(tc.input)\n\t\t\twant := lo.Mean(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MeanInt16x8() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMeanInt32x4(t *testing.T) {\n\trequireAVX(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []int32\n\t}{\n\t\t{\"empty\", []int32{}},\n\t\t{\"single\", []int32{42}},\n\t\t{\"small\", []int32{1, 2, 3, 4, 5}},\n\t\t{\"exactly 4\", make([]int32, 4)},\n\t\t{\"large\", make([]int32, 1000)},\n\t\t{\"negative\", []int32{-1, -2, -3, 4, 5}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = int32(rand.Int32())\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MeanInt32x4(tc.input)\n\t\t\twant := lo.Mean(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MeanInt32x4() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMeanInt64x2(t *testing.T) {\n\trequireAVX(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []int64\n\t}{\n\t\t{\"empty\", []int64{}},\n\t\t{\"single\", []int64{42}},\n\t\t{\"small\", []int64{1, 2, 3, 4, 5}},\n\t\t{\"exactly 2\", []int64{1, 2}},\n\t\t{\"large\", make([]int64, 1000)},\n\t\t{\"negative\", []int64{-1, -2, -3, 4, 5}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Int64()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MeanInt64x2(tc.input)\n\t\t\twant := lo.Mean(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MeanInt64x2() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMeanUint8x16(t *testing.T) {\n\trequireAVX(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []uint8\n\t}{\n\t\t{\"empty\", []uint8{}},\n\t\t{\"single\", []uint8{42}},\n\t\t{\"small\", []uint8{1, 2, 3, 4, 5}},\n\t\t{\"exactly 16\", make([]uint8, 16)},\n\t\t{\"large\", make([]uint8, 1000)},\n\t\t{\"max values\", []uint8{255, 255, 1}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = uint8(rand.IntN(256))\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MeanUint8x16(tc.input)\n\t\t\twant := lo.Mean(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MeanUint8x16() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMeanUint16x8(t *testing.T) {\n\trequireAVX(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []uint16\n\t}{\n\t\t{\"empty\", []uint16{}},\n\t\t{\"single\", []uint16{42}},\n\t\t{\"small\", []uint16{1, 2, 3, 4, 5}},\n\t\t{\"exactly 8\", make([]uint16, 8)},\n\t\t{\"large\", make([]uint16, 1000)},\n\t\t{\"max values\", []uint16{65535, 1}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = uint16(rand.IntN(65536))\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MeanUint16x8(tc.input)\n\t\t\twant := lo.Mean(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MeanUint16x8() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMeanUint32x4(t *testing.T) {\n\trequireAVX(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []uint32\n\t}{\n\t\t{\"empty\", []uint32{}},\n\t\t{\"single\", []uint32{42}},\n\t\t{\"small\", []uint32{1, 2, 3, 4, 5}},\n\t\t{\"exactly 4\", make([]uint32, 4)},\n\t\t{\"large\", make([]uint32, 1000)},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Uint32()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MeanUint32x4(tc.input)\n\t\t\twant := lo.Mean(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MeanUint32x4() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMeanUint64x2(t *testing.T) {\n\trequireAVX(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []uint64\n\t}{\n\t\t{\"empty\", []uint64{}},\n\t\t{\"single\", []uint64{42}},\n\t\t{\"small\", []uint64{1, 2, 3, 4, 5}},\n\t\t{\"exactly 2\", []uint64{1, 2}},\n\t\t{\"large\", make([]uint64, 1000)},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Uint64()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MeanUint64x2(tc.input)\n\t\t\twant := lo.Mean(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MeanUint64x2() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMeanFloat32x4(t *testing.T) {\n\trequireAVX(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []float32\n\t}{\n\t\t{\"empty\", []float32{}},\n\t\t{\"single\", []float32{42.5}},\n\t\t{\"small\", []float32{1.1, 2.2, 3.3, 4.4, 5.5}},\n\t\t{\"exactly 4\", []float32{1.0, 2.0, 3.0, 4.0}},\n\t\t{\"large\", make([]float32, 1000)},\n\t\t{\"negative\", []float32{-1.1, -2.2, 3.3, 4.4}},\n\t\t{\"zeros\", []float32{0, 0, 0, 0}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Float32()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MeanFloat32x4(tc.input)\n\t\t\twant := lo.Mean(tc.input)\n\n\t\t\tconst epsilon = 1e-3\n\t\t\tif diff := got - want; diff < -epsilon || diff > epsilon {\n\t\t\t\tt.Errorf(\"MeanFloat32x4() = %v, want %v (diff: %v)\", got, want, diff)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMeanFloat64x2(t *testing.T) {\n\trequireAVX(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []float64\n\t}{\n\t\t{\"empty\", []float64{}},\n\t\t{\"single\", []float64{42.5}},\n\t\t{\"small\", []float64{1.1, 2.2, 3.3, 4.4, 5.5}},\n\t\t{\"exactly 2\", []float64{1.0, 2.0}},\n\t\t{\"large\", make([]float64, 1000)},\n\t\t{\"negative\", []float64{-1.1, -2.2, 3.3, 4.4}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Float64()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MeanFloat64x2(tc.input)\n\t\t\twant := lo.Mean(tc.input)\n\n\t\t\tconst epsilon = 1e-3\n\t\t\tif diff := got - want; diff < -epsilon || diff > epsilon {\n\t\t\t\tt.Errorf(\"MeanFloat64x2() = %v, want %v (diff: %v)\", got, want, diff)\n\t\t\t}\n\t\t})\n\t}\n}\n\n// Test type aliases work correctly\nfunc TestAVXMeanTypeAlias(t *testing.T) {\n\trequireAVX(t)\n\tinput := []myInt8{1, 2, 3, 4, 5}\n\tgot := MeanInt8x16(input)\n\twant := lo.Mean(input)\n\n\tif got != want {\n\t\tt.Errorf(\"MeanInt8x16() with type alias = %v, want %v\", got, want)\n\t}\n}\n\nfunc TestMinInt8x16(t *testing.T) {\n\trequireAVX(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []int8\n\t}{\n\t\t{\"empty\", []int8{}},\n\t\t{\"single\", []int8{42}},\n\t\t{\"small\", []int8{1, 2, 3, 4, 5}},\n\t\t{\"exactly 16\", make([]int8, 16)},\n\t\t{\"large\", make([]int8, 1000)},\n\t\t{\"negative\", []int8{-1, -2, -3, 4, 5}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = int8(rand.IntN(256) - 128)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MinInt8x16(tc.input)\n\t\t\twant := lo.Min(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MinInt8x16() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMinInt16x8(t *testing.T) {\n\trequireAVX(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []int16\n\t}{\n\t\t{\"empty\", []int16{}},\n\t\t{\"single\", []int16{42}},\n\t\t{\"small\", []int16{1, 2, 3, 4, 5}},\n\t\t{\"exactly 8\", make([]int16, 8)},\n\t\t{\"large\", make([]int16, 1000)},\n\t\t{\"negative\", []int16{-1, -2, -3, 4, 5}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = int16(rand.IntN(65536) - 32768)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MinInt16x8(tc.input)\n\t\t\twant := lo.Min(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MinInt16x8() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMinInt32x4(t *testing.T) {\n\trequireAVX(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []int32\n\t}{\n\t\t{\"empty\", []int32{}},\n\t\t{\"single\", []int32{42}},\n\t\t{\"small\", []int32{1, 2, 3, 4, 5}},\n\t\t{\"exactly 4\", []int32{1, 2, 3, 4}},\n\t\t{\"large\", make([]int32, 1000)},\n\t\t{\"negative\", []int32{-1, -2, -3, 4, 5}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Int32()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MinInt32x4(tc.input)\n\t\t\twant := lo.Min(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MinInt32x4() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMinUint8x16(t *testing.T) {\n\trequireAVX(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []uint8\n\t}{\n\t\t{\"empty\", []uint8{}},\n\t\t{\"single\", []uint8{42}},\n\t\t{\"small\", []uint8{1, 2, 3, 4, 5}},\n\t\t{\"exactly 16\", make([]uint8, 16)},\n\t\t{\"large\", make([]uint8, 1000)},\n\t\t{\"max values\", []uint8{255, 100, 50}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = uint8(rand.IntN(256))\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MinUint8x16(tc.input)\n\t\t\twant := lo.Min(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MinUint8x16() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMinUint16x8(t *testing.T) {\n\trequireAVX(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []uint16\n\t}{\n\t\t{\"empty\", []uint16{}},\n\t\t{\"single\", []uint16{42}},\n\t\t{\"small\", []uint16{1, 2, 3, 4, 5}},\n\t\t{\"exactly 8\", make([]uint16, 8)},\n\t\t{\"large\", make([]uint16, 1000)},\n\t\t{\"max values\", []uint16{65535, 1000, 500}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = uint16(rand.IntN(65536))\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MinUint16x8(tc.input)\n\t\t\twant := lo.Min(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MinUint16x8() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMinUint32x4(t *testing.T) {\n\trequireAVX(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []uint32\n\t}{\n\t\t{\"empty\", []uint32{}},\n\t\t{\"single\", []uint32{42}},\n\t\t{\"small\", []uint32{1, 2, 3, 4, 5}},\n\t\t{\"exactly 4\", []uint32{1, 2, 3, 4}},\n\t\t{\"large\", make([]uint32, 1000)},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Uint32()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MinUint32x4(tc.input)\n\t\t\twant := lo.Min(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MinUint32x4() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMinFloat32x4(t *testing.T) {\n\trequireAVX(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []float32\n\t}{\n\t\t{\"empty\", []float32{}},\n\t\t{\"single\", []float32{42.5}},\n\t\t{\"small\", []float32{1.1, 2.2, 3.3, 4.4, 5.5}},\n\t\t{\"exactly 4\", []float32{1.0, 2.0, 3.0, 4.0}},\n\t\t{\"large\", make([]float32, 1000)},\n\t\t{\"negative\", []float32{-1.1, -2.2, 3.3, 4.4}},\n\t\t{\"zeros\", []float32{0, 0, 0, 0}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Float32()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MinFloat32x4(tc.input)\n\t\t\twant := lo.Min(tc.input)\n\n\t\t\tconst epsilon = 1e-3\n\t\t\tif diff := got - want; diff < -epsilon || diff > epsilon {\n\t\t\t\tt.Errorf(\"MinFloat32x4() = %v, want %v (diff: %v)\", got, want, diff)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMinFloat64x2(t *testing.T) {\n\trequireAVX(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []float64\n\t}{\n\t\t{\"empty\", []float64{}},\n\t\t{\"single\", []float64{42.5}},\n\t\t{\"small\", []float64{1.1, 2.2, 3.3, 4.4, 5.5}},\n\t\t{\"exactly 2\", []float64{1.0, 2.0}},\n\t\t{\"large\", make([]float64, 1000)},\n\t\t{\"negative\", []float64{-1.1, -2.2, 3.3, 4.4}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Float64()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MinFloat64x2(tc.input)\n\t\t\twant := lo.Min(tc.input)\n\n\t\t\tconst epsilon = 1e-3\n\t\t\tif diff := got - want; diff < -epsilon || diff > epsilon {\n\t\t\t\tt.Errorf(\"MinFloat64x2() = %v, want %v (diff: %v)\", got, want, diff)\n\t\t\t}\n\t\t})\n\t}\n}\n\n// Test type aliases work correctly\nfunc TestAVXMinTypeAlias(t *testing.T) {\n\trequireAVX(t)\n\tinput := []myInt8{5, 2, 8, 1, 9}\n\tgot := MinInt8x16(input)\n\twant := myInt8(1)\n\n\tif got != want {\n\t\tt.Errorf(\"MinInt8x16() with type alias = %v, want %v\", got, want)\n\t}\n}\n\nfunc TestMaxInt8x16(t *testing.T) {\n\trequireAVX(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []int8\n\t}{\n\t\t{\"empty\", []int8{}},\n\t\t{\"single\", []int8{42}},\n\t\t{\"small\", []int8{1, 2, 3, 4, 5}},\n\t\t{\"exactly 16\", make([]int8, 16)},\n\t\t{\"large\", make([]int8, 1000)},\n\t\t{\"negative\", []int8{-1, -2, -3, 4, 5}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = int8(rand.IntN(256) - 128)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MaxInt8x16(tc.input)\n\t\t\twant := lo.Max(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MaxInt8x16() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMaxInt16x8(t *testing.T) {\n\trequireAVX(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []int16\n\t}{\n\t\t{\"empty\", []int16{}},\n\t\t{\"single\", []int16{42}},\n\t\t{\"small\", []int16{1, 2, 3, 4, 5}},\n\t\t{\"exactly 8\", make([]int16, 8)},\n\t\t{\"large\", make([]int16, 1000)},\n\t\t{\"negative\", []int16{-1, -2, -3, 4, 5}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = int16(rand.IntN(65536) - 32768)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MaxInt16x8(tc.input)\n\t\t\twant := lo.Max(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MaxInt16x8() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMaxInt32x4(t *testing.T) {\n\trequireAVX(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []int32\n\t}{\n\t\t{\"empty\", []int32{}},\n\t\t{\"single\", []int32{42}},\n\t\t{\"small\", []int32{1, 2, 3, 4, 5}},\n\t\t{\"exactly 4\", []int32{1, 2, 3, 4}},\n\t\t{\"large\", make([]int32, 1000)},\n\t\t{\"negative\", []int32{-1, -2, -3, 4, 5}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Int32()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MaxInt32x4(tc.input)\n\t\t\twant := lo.Max(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MaxInt32x4() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMaxUint8x16(t *testing.T) {\n\trequireAVX(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []uint8\n\t}{\n\t\t{\"empty\", []uint8{}},\n\t\t{\"single\", []uint8{42}},\n\t\t{\"small\", []uint8{1, 2, 3, 4, 5}},\n\t\t{\"exactly 16\", make([]uint8, 16)},\n\t\t{\"large\", make([]uint8, 1000)},\n\t\t{\"max values\", []uint8{255, 100, 50}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = uint8(rand.IntN(256))\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MaxUint8x16(tc.input)\n\t\t\twant := lo.Max(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MaxUint8x16() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMaxUint16x8(t *testing.T) {\n\trequireAVX(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []uint16\n\t}{\n\t\t{\"empty\", []uint16{}},\n\t\t{\"single\", []uint16{42}},\n\t\t{\"small\", []uint16{1, 2, 3, 4, 5}},\n\t\t{\"exactly 8\", make([]uint16, 8)},\n\t\t{\"large\", make([]uint16, 1000)},\n\t\t{\"max values\", []uint16{65535, 1000, 500}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = uint16(rand.IntN(65536))\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MaxUint16x8(tc.input)\n\t\t\twant := lo.Max(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MaxUint16x8() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMaxUint32x4(t *testing.T) {\n\trequireAVX(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []uint32\n\t}{\n\t\t{\"empty\", []uint32{}},\n\t\t{\"single\", []uint32{42}},\n\t\t{\"small\", []uint32{1, 2, 3, 4, 5}},\n\t\t{\"exactly 4\", []uint32{1, 2, 3, 4}},\n\t\t{\"large\", make([]uint32, 1000)},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Uint32()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MaxUint32x4(tc.input)\n\t\t\twant := lo.Max(tc.input)\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MaxUint32x4() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMaxFloat32x4(t *testing.T) {\n\trequireAVX(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []float32\n\t}{\n\t\t{\"empty\", []float32{}},\n\t\t{\"single\", []float32{42.5}},\n\t\t{\"small\", []float32{1.1, 2.2, 3.3, 4.4, 5.5}},\n\t\t{\"exactly 4\", []float32{1.0, 2.0, 3.0, 4.0}},\n\t\t{\"large\", make([]float32, 1000)},\n\t\t{\"negative\", []float32{-1.1, -2.2, 3.3, 4.4}},\n\t\t{\"zeros\", []float32{0, 0, 0, 0}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Float32()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MaxFloat32x4(tc.input)\n\t\t\twant := lo.Max(tc.input)\n\n\t\t\tconst epsilon = 1e-3\n\t\t\tif diff := got - want; diff < -epsilon || diff > epsilon {\n\t\t\t\tt.Errorf(\"MaxFloat32x4() = %v, want %v (diff: %v)\", got, want, diff)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMaxFloat64x2(t *testing.T) {\n\trequireAVX(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []float64\n\t}{\n\t\t{\"empty\", []float64{}},\n\t\t{\"single\", []float64{42.5}},\n\t\t{\"small\", []float64{1.1, 2.2, 3.3, 4.4, 5.5}},\n\t\t{\"exactly 2\", []float64{1.0, 2.0}},\n\t\t{\"large\", make([]float64, 1000)},\n\t\t{\"negative\", []float64{-1.1, -2.2, 3.3, 4.4}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0] == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i] = rand.Float64()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MaxFloat64x2(tc.input)\n\t\t\twant := lo.Max(tc.input)\n\n\t\t\tconst epsilon = 1e-3\n\t\t\tif diff := got - want; diff < -epsilon || diff > epsilon {\n\t\t\t\tt.Errorf(\"MaxFloat64x2() = %v, want %v (diff: %v)\", got, want, diff)\n\t\t\t}\n\t\t})\n\t}\n}\n\n// Test type aliases work correctly\nfunc TestAVXMaxTypeAlias(t *testing.T) {\n\trequireAVX(t)\n\tinput := []myInt8{5, 2, 8, 1, 9}\n\tgot := MaxInt8x16(input)\n\twant := myInt8(9)\n\n\tif got != want {\n\t\tt.Errorf(\"MaxInt8x16() with type alias = %v, want %v\", got, want)\n\t}\n}\n\n// SumBy tests\n\ntype item struct {\n\tValue      int8\n\tWeight     int8\n\tMultiplier int8\n}\n\nfunc TestSumByInt8x16(t *testing.T) {\n\trequireAVX(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []item\n\t}{\n\t\t{\"empty\", []item{}},\n\t\t{\"single\", []item{{Value: 42}}},\n\t\t{\"small\", []item{{Value: 1}, {Value: 2}, {Value: 3}, {Value: 4}, {Value: 5}}},\n\t\t{\"exactly 16\", make([]item, 16)},\n\t\t{\"large\", make([]item, 1000)},\n\t\t{\"negative\", []item{{Value: -1}, {Value: -2}, {Value: -3}, {Value: 4}, {Value: 5}}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0].Value == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i].Value = int8(rand.IntN(256) - 128)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Using Value field as the iteratee\n\t\t\tgot := SumByInt8x16(tc.input, func(i item) int8 { return i.Value })\n\t\t\twant := lo.Sum(lo.Map(tc.input, func(i item, _ int) int8 { return i.Value }))\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"SumByInt8x16() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestSumByInt16x8(t *testing.T) {\n\trequireAVX(t)\n\ttype itemInt16 struct {\n\t\tValue int16\n\t}\n\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []itemInt16\n\t}{\n\t\t{\"empty\", []itemInt16{}},\n\t\t{\"single\", []itemInt16{{Value: 42}}},\n\t\t{\"small\", []itemInt16{{1}, {2}, {3}, {4}, {5}}},\n\t\t{\"exactly 8\", make([]itemInt16, 8)},\n\t\t{\"large\", make([]itemInt16, 1000)},\n\t\t{\"negative\", []itemInt16{{-1}, {-2}, {-3}, {4}, {5}}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0].Value == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i].Value = int16(rand.IntN(65536) - 32768)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := SumByInt16x8(tc.input, func(i itemInt16) int16 { return i.Value })\n\t\t\twant := lo.Sum(lo.Map(tc.input, func(i itemInt16, _ int) int16 { return i.Value }))\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"SumByInt16x8() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestSumByInt32x4(t *testing.T) {\n\trequireAVX(t)\n\ttype itemInt32 struct {\n\t\tValue int32\n\t}\n\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []itemInt32\n\t}{\n\t\t{\"empty\", []itemInt32{}},\n\t\t{\"single\", []itemInt32{{Value: 42}}},\n\t\t{\"small\", []itemInt32{{1}, {2}, {3}, {4}, {5}}},\n\t\t{\"exactly 4\", []itemInt32{{1}, {2}, {3}, {4}}},\n\t\t{\"large\", make([]itemInt32, 1000)},\n\t\t{\"negative\", []itemInt32{{-1}, {-2}, {-3}, {4}, {5}}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0].Value == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i].Value = rand.Int32()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := SumByInt32x4(tc.input, func(i itemInt32) int32 { return i.Value })\n\t\t\twant := lo.Sum(lo.Map(tc.input, func(i itemInt32, _ int) int32 { return i.Value }))\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"SumByInt32x4() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestSumByInt64x2(t *testing.T) {\n\trequireAVX(t)\n\ttype itemInt64 struct {\n\t\tValue int64\n\t}\n\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []itemInt64\n\t}{\n\t\t{\"empty\", []itemInt64{}},\n\t\t{\"single\", []itemInt64{{Value: 42}}},\n\t\t{\"small\", []itemInt64{{1}, {2}, {3}, {4}, {5}}},\n\t\t{\"exactly 2\", []itemInt64{{1}, {2}}},\n\t\t{\"large\", make([]itemInt64, 1000)},\n\t\t{\"negative\", []itemInt64{{-1}, {-2}, {-3}, {4}, {5}}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0].Value == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i].Value = rand.Int64()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := SumByInt64x2(tc.input, func(i itemInt64) int64 { return i.Value })\n\t\t\twant := lo.Sum(lo.Map(tc.input, func(i itemInt64, _ int) int64 { return i.Value }))\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"SumByInt64x2() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestSumByUint8x16(t *testing.T) {\n\trequireAVX(t)\n\ttype itemUint8 struct {\n\t\tValue uint8\n\t}\n\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []itemUint8\n\t}{\n\t\t{\"empty\", []itemUint8{}},\n\t\t{\"single\", []itemUint8{{Value: 42}}},\n\t\t{\"small\", []itemUint8{{1}, {2}, {3}, {4}, {5}}},\n\t\t{\"exactly 16\", make([]itemUint8, 16)},\n\t\t{\"large\", make([]itemUint8, 1000)},\n\t\t{\"max values\", []itemUint8{{Value: 255}, {Value: 255}, {Value: 1}}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0].Value == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i].Value = uint8(rand.IntN(256))\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := SumByUint8x16(tc.input, func(i itemUint8) uint8 { return i.Value })\n\t\t\twant := lo.Sum(lo.Map(tc.input, func(i itemUint8, _ int) uint8 { return i.Value }))\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"SumByUint8x16() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestSumByUint16x8(t *testing.T) {\n\trequireAVX(t)\n\ttype itemUint16 struct {\n\t\tValue uint16\n\t}\n\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []itemUint16\n\t}{\n\t\t{\"empty\", []itemUint16{}},\n\t\t{\"single\", []itemUint16{{Value: 42}}},\n\t\t{\"small\", []itemUint16{{1}, {2}, {3}, {4}, {5}}},\n\t\t{\"exactly 8\", make([]itemUint16, 8)},\n\t\t{\"large\", make([]itemUint16, 1000)},\n\t\t{\"max values\", []itemUint16{{Value: 65535}, {Value: 1}}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0].Value == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i].Value = uint16(rand.IntN(65536))\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := SumByUint16x8(tc.input, func(i itemUint16) uint16 { return i.Value })\n\t\t\twant := lo.Sum(lo.Map(tc.input, func(i itemUint16, _ int) uint16 { return i.Value }))\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"SumByUint16x8() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestSumByUint32x4(t *testing.T) {\n\trequireAVX(t)\n\ttype itemUint32 struct {\n\t\tValue uint32\n\t}\n\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []itemUint32\n\t}{\n\t\t{\"empty\", []itemUint32{}},\n\t\t{\"single\", []itemUint32{{Value: 42}}},\n\t\t{\"small\", []itemUint32{{1}, {2}, {3}, {4}, {5}}},\n\t\t{\"exactly 4\", []itemUint32{{1}, {2}, {3}, {4}}},\n\t\t{\"large\", make([]itemUint32, 1000)},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0].Value == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i].Value = rand.Uint32()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := SumByUint32x4(tc.input, func(i itemUint32) uint32 { return i.Value })\n\t\t\twant := lo.Sum(lo.Map(tc.input, func(i itemUint32, _ int) uint32 { return i.Value }))\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"SumByUint32x4() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestSumByUint64x2(t *testing.T) {\n\trequireAVX(t)\n\ttype itemUint64 struct {\n\t\tValue uint64\n\t}\n\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []itemUint64\n\t}{\n\t\t{\"empty\", []itemUint64{}},\n\t\t{\"single\", []itemUint64{{Value: 42}}},\n\t\t{\"small\", []itemUint64{{1}, {2}, {3}, {4}, {5}}},\n\t\t{\"exactly 2\", []itemUint64{{1}, {2}}},\n\t\t{\"large\", make([]itemUint64, 1000)},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0].Value == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i].Value = rand.Uint64()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := SumByUint64x2(tc.input, func(i itemUint64) uint64 { return i.Value })\n\t\t\twant := lo.Sum(lo.Map(tc.input, func(i itemUint64, _ int) uint64 { return i.Value }))\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"SumByUint64x2() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestSumByFloat32x4(t *testing.T) {\n\trequireAVX(t)\n\ttype itemFloat32 struct {\n\t\tValue float32\n\t}\n\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []itemFloat32\n\t}{\n\t\t{\"empty\", []itemFloat32{}},\n\t\t{\"single\", []itemFloat32{{Value: 42.5}}},\n\t\t{\"small\", []itemFloat32{{1.1}, {2.2}, {3.3}, {4.4}, {5.5}}},\n\t\t{\"exactly 4\", []itemFloat32{{1.0}, {2.0}, {3.0}, {4.0}}},\n\t\t{\"large\", make([]itemFloat32, 1000)},\n\t\t{\"negative\", []itemFloat32{{-1.1}, {-2.2}, {3.3}, {4.4}}},\n\t\t{\"zeros\", []itemFloat32{{0}, {0}, {0}, {0}}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0].Value == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i].Value = rand.Float32()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := SumByFloat32x4(tc.input, func(i itemFloat32) float32 { return i.Value })\n\t\t\twant := lo.Sum(lo.Map(tc.input, func(i itemFloat32, _ int) float32 { return i.Value }))\n\n\t\t\tconst epsilon = 1e-3\n\t\t\tif diff := got - want; diff < -epsilon || diff > epsilon {\n\t\t\t\tt.Errorf(\"SumByFloat32x4() = %v, want %v (diff: %v)\", got, want, diff)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestSumByFloat64x2(t *testing.T) {\n\trequireAVX(t)\n\ttype itemFloat64 struct {\n\t\tValue float64\n\t}\n\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []itemFloat64\n\t}{\n\t\t{\"empty\", []itemFloat64{}},\n\t\t{\"single\", []itemFloat64{{Value: 42.5}}},\n\t\t{\"small\", []itemFloat64{{1.1}, {2.2}, {3.3}, {4.4}, {5.5}}},\n\t\t{\"exactly 2\", []itemFloat64{{1.0}, {2.0}}},\n\t\t{\"large\", make([]itemFloat64, 1000)},\n\t\t{\"negative\", []itemFloat64{{-1.1}, {-2.2}, {3.3}, {4.4}}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0].Value == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i].Value = rand.Float64()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := SumByFloat64x2(tc.input, func(i itemFloat64) float64 { return i.Value })\n\t\t\twant := lo.Sum(lo.Map(tc.input, func(i itemFloat64, _ int) float64 { return i.Value }))\n\n\t\t\tconst epsilon = 1e-3\n\t\t\tif diff := got - want; diff < -epsilon || diff > epsilon {\n\t\t\t\tt.Errorf(\"SumByFloat64x2() = %v, want %v (diff: %v)\", got, want, diff)\n\t\t\t}\n\t\t})\n\t}\n}\n\n// Test type alias works correctly for SumBy\nfunc TestAVXSumByTypeAlias(t *testing.T) {\n\trequireAVX(t)\n\ttype myItem struct {\n\t\tValue myInt8\n\t}\n\n\tinput := []myItem{{Value: 1}, {Value: 2}, {Value: 3}, {Value: 4}, {Value: 5}}\n\tgot := SumByInt8x16(input, func(i myItem) myInt8 { return i.Value })\n\twant := myInt8(15)\n\n\tif got != want {\n\t\tt.Errorf(\"SumByInt8x16() with type alias = %v, want %v\", got, want)\n\t}\n}\n\n// MeanBy tests\n\nfunc TestMeanByInt8x16(t *testing.T) {\n\trequireAVX(t)\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []item\n\t}{\n\t\t{\"empty\", []item{}},\n\t\t{\"single\", []item{{Value: 42}}},\n\t\t{\"small\", []item{{Value: 1}, {Value: 2}, {Value: 3}, {Value: 4}, {Value: 5}}},\n\t\t{\"exactly 16\", make([]item, 16)},\n\t\t{\"large\", make([]item, 1000)},\n\t\t{\"negative\", []item{{Value: -1}, {Value: -2}, {Value: -3}, {Value: 4}, {Value: 5}}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0].Value == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i].Value = int8(rand.IntN(256) - 128)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MeanByInt8x16(tc.input, func(i item) int8 { return i.Value })\n\t\t\twant := lo.Mean(lo.Map(tc.input, func(i item, _ int) int8 { return i.Value }))\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MeanByInt8x16() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMeanByInt16x8(t *testing.T) {\n\trequireAVX(t)\n\ttype itemInt16 struct {\n\t\tValue int16\n\t}\n\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []itemInt16\n\t}{\n\t\t{\"empty\", []itemInt16{}},\n\t\t{\"single\", []itemInt16{{Value: 42}}},\n\t\t{\"small\", []itemInt16{{1}, {2}, {3}, {4}, {5}}},\n\t\t{\"exactly 8\", make([]itemInt16, 8)},\n\t\t{\"large\", make([]itemInt16, 1000)},\n\t\t{\"negative\", []itemInt16{{-1}, {-2}, {-3}, {4}, {5}}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0].Value == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i].Value = int16(rand.IntN(65536) - 32768)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MeanByInt16x8(tc.input, func(i itemInt16) int16 { return i.Value })\n\t\t\twant := lo.Mean(lo.Map(tc.input, func(i itemInt16, _ int) int16 { return i.Value }))\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MeanByInt16x8() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMeanByInt32x4(t *testing.T) {\n\trequireAVX(t)\n\ttype itemInt32 struct {\n\t\tValue int32\n\t}\n\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []itemInt32\n\t}{\n\t\t{\"empty\", []itemInt32{}},\n\t\t{\"single\", []itemInt32{{Value: 42}}},\n\t\t{\"small\", []itemInt32{{1}, {2}, {3}, {4}, {5}}},\n\t\t{\"exactly 4\", []itemInt32{{1}, {2}, {3}, {4}}},\n\t\t{\"large\", make([]itemInt32, 1000)},\n\t\t{\"negative\", []itemInt32{{-1}, {-2}, {-3}, {4}, {5}}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0].Value == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i].Value = rand.Int32()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MeanByInt32x4(tc.input, func(i itemInt32) int32 { return i.Value })\n\t\t\twant := lo.Mean(lo.Map(tc.input, func(i itemInt32, _ int) int32 { return i.Value }))\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MeanByInt32x4() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMeanByInt64x2(t *testing.T) {\n\trequireAVX(t)\n\ttype itemInt64 struct {\n\t\tValue int64\n\t}\n\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []itemInt64\n\t}{\n\t\t{\"empty\", []itemInt64{}},\n\t\t{\"single\", []itemInt64{{Value: 42}}},\n\t\t{\"small\", []itemInt64{{1}, {2}, {3}, {4}, {5}}},\n\t\t{\"exactly 2\", []itemInt64{{1}, {2}}},\n\t\t{\"large\", make([]itemInt64, 1000)},\n\t\t{\"negative\", []itemInt64{{-1}, {-2}, {-3}, {4}, {5}}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0].Value == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i].Value = rand.Int64()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MeanByInt64x2(tc.input, func(i itemInt64) int64 { return i.Value })\n\t\t\twant := lo.Mean(lo.Map(tc.input, func(i itemInt64, _ int) int64 { return i.Value }))\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MeanByInt64x2() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMeanByUint8x16(t *testing.T) {\n\trequireAVX(t)\n\ttype itemUint8 struct {\n\t\tValue uint8\n\t}\n\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []itemUint8\n\t}{\n\t\t{\"empty\", []itemUint8{}},\n\t\t{\"single\", []itemUint8{{Value: 42}}},\n\t\t{\"small\", []itemUint8{{1}, {2}, {3}, {4}, {5}}},\n\t\t{\"exactly 16\", make([]itemUint8, 16)},\n\t\t{\"large\", make([]itemUint8, 1000)},\n\t\t{\"max values\", []itemUint8{{Value: 255}, {Value: 255}, {Value: 1}}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0].Value == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i].Value = uint8(rand.IntN(256))\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MeanByUint8x16(tc.input, func(i itemUint8) uint8 { return i.Value })\n\t\t\twant := lo.Mean(lo.Map(tc.input, func(i itemUint8, _ int) uint8 { return i.Value }))\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MeanByUint8x16() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMeanByUint16x8(t *testing.T) {\n\trequireAVX(t)\n\ttype itemUint16 struct {\n\t\tValue uint16\n\t}\n\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []itemUint16\n\t}{\n\t\t{\"empty\", []itemUint16{}},\n\t\t{\"single\", []itemUint16{{Value: 42}}},\n\t\t{\"small\", []itemUint16{{1}, {2}, {3}, {4}, {5}}},\n\t\t{\"exactly 8\", make([]itemUint16, 8)},\n\t\t{\"large\", make([]itemUint16, 1000)},\n\t\t{\"max values\", []itemUint16{{Value: 65535}, {Value: 1}}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0].Value == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i].Value = uint16(rand.IntN(65536))\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MeanByUint16x8(tc.input, func(i itemUint16) uint16 { return i.Value })\n\t\t\twant := lo.Mean(lo.Map(tc.input, func(i itemUint16, _ int) uint16 { return i.Value }))\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MeanByUint16x8() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMeanByUint32x4(t *testing.T) {\n\trequireAVX(t)\n\ttype itemUint32 struct {\n\t\tValue uint32\n\t}\n\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []itemUint32\n\t}{\n\t\t{\"empty\", []itemUint32{}},\n\t\t{\"single\", []itemUint32{{Value: 42}}},\n\t\t{\"small\", []itemUint32{{1}, {2}, {3}, {4}, {5}}},\n\t\t{\"exactly 4\", []itemUint32{{1}, {2}, {3}, {4}}},\n\t\t{\"large\", make([]itemUint32, 1000)},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0].Value == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i].Value = rand.Uint32()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MeanByUint32x4(tc.input, func(i itemUint32) uint32 { return i.Value })\n\t\t\twant := lo.Mean(lo.Map(tc.input, func(i itemUint32, _ int) uint32 { return i.Value }))\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MeanByUint32x4() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMeanByUint64x2(t *testing.T) {\n\trequireAVX(t)\n\ttype itemUint64 struct {\n\t\tValue uint64\n\t}\n\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []itemUint64\n\t}{\n\t\t{\"empty\", []itemUint64{}},\n\t\t{\"single\", []itemUint64{{Value: 42}}},\n\t\t{\"small\", []itemUint64{{1}, {2}, {3}, {4}, {5}}},\n\t\t{\"exactly 2\", []itemUint64{{1}, {2}}},\n\t\t{\"large\", make([]itemUint64, 1000)},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0].Value == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i].Value = rand.Uint64()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MeanByUint64x2(tc.input, func(i itemUint64) uint64 { return i.Value })\n\t\t\twant := lo.Mean(lo.Map(tc.input, func(i itemUint64, _ int) uint64 { return i.Value }))\n\n\t\t\tif got != want {\n\t\t\t\tt.Errorf(\"MeanByUint64x2() = %v, want %v\", got, want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMeanByFloat32x4(t *testing.T) {\n\trequireAVX(t)\n\ttype itemFloat32 struct {\n\t\tValue float32\n\t}\n\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []itemFloat32\n\t}{\n\t\t{\"empty\", []itemFloat32{}},\n\t\t{\"single\", []itemFloat32{{Value: 42.5}}},\n\t\t{\"small\", []itemFloat32{{1.1}, {2.2}, {3.3}, {4.4}, {5.5}}},\n\t\t{\"exactly 4\", []itemFloat32{{1.0}, {2.0}, {3.0}, {4.0}}},\n\t\t{\"large\", make([]itemFloat32, 1000)},\n\t\t{\"negative\", []itemFloat32{{-1.1}, {-2.2}, {3.3}, {4.4}}},\n\t\t{\"zeros\", []itemFloat32{{0}, {0}, {0}, {0}}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0].Value == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i].Value = rand.Float32()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MeanByFloat32x4(tc.input, func(i itemFloat32) float32 { return i.Value })\n\t\t\twant := lo.Mean(lo.Map(tc.input, func(i itemFloat32, _ int) float32 { return i.Value }))\n\n\t\t\tconst epsilon = 1e-3\n\t\t\tif diff := got - want; diff < -epsilon || diff > epsilon {\n\t\t\t\tt.Errorf(\"MeanByFloat32x4() = %v, want %v (diff: %v)\", got, want, diff)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMeanByFloat64x2(t *testing.T) {\n\trequireAVX(t)\n\ttype itemFloat64 struct {\n\t\tValue float64\n\t}\n\n\ttestCases := []struct {\n\t\tname  string\n\t\tinput []itemFloat64\n\t}{\n\t\t{\"empty\", []itemFloat64{}},\n\t\t{\"single\", []itemFloat64{{Value: 42.5}}},\n\t\t{\"small\", []itemFloat64{{1.1}, {2.2}, {3.3}, {4.4}, {5.5}}},\n\t\t{\"exactly 2\", []itemFloat64{{1.0}, {2.0}}},\n\t\t{\"large\", make([]itemFloat64, 1000)},\n\t\t{\"negative\", []itemFloat64{{-1.1}, {-2.2}, {3.3}, {4.4}}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif len(tc.input) > 0 && tc.input[0].Value == 0 && len(tc.input) > 6 {\n\t\t\t\tfor i := range tc.input {\n\t\t\t\t\ttc.input[i].Value = rand.Float64()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tgot := MeanByFloat64x2(tc.input, func(i itemFloat64) float64 { return i.Value })\n\t\t\twant := lo.Mean(lo.Map(tc.input, func(i itemFloat64, _ int) float64 { return i.Value }))\n\n\t\t\tconst epsilon = 1e-3\n\t\t\tif diff := got - want; diff < -epsilon || diff > epsilon {\n\t\t\t\tt.Errorf(\"MeanByFloat64x2() = %v, want %v (diff: %v)\", got, want, diff)\n\t\t\t}\n\t\t})\n\t}\n}\n\n// Test type alias works correctly for MeanBy\nfunc TestAVXMeanByTypeAlias(t *testing.T) {\n\trequireAVX(t)\n\ttype myItem struct {\n\t\tValue myInt8\n\t}\n\n\tinput := []myItem{{Value: 1}, {Value: 2}, {Value: 3}, {Value: 4}, {Value: 5}}\n\tgot := MeanByInt8x16(input, func(i myItem) myInt8 { return i.Value })\n\twant := myInt8(3)\n\n\tif got != want {\n\t\tt.Errorf(\"MeanByInt8x16() with type alias = %v, want %v\", got, want)\n\t}\n}\n"
  },
  {
    "path": "exp/simd/math_bench_test.go",
    "content": "//go:build go1.26 && goexperiment.simd && amd64\n\npackage simd\n\nimport (\n\t\"math/rand\"\n\t\"simd/archsimd\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/samber/lo\"\n)\n\n// Benchmark suite for SIMD math operations compared to core lo package fallbacks.\n// These benchmarks measure the performance of Sum, Mean, Min, and Max operations\n// across different SIMD implementations (AVX, AVX2, AVX512) and data sizes.\n\n// Benchmark sizes to demonstrate performance characteristics at different scales\nvar benchmarkSizes = []struct {\n\tname string\n\tsize int\n}{\n\t{\"small\", 8},     // Smaller than AVX width (16 lanes for int8)\n\t{\"medium\", 128},  // Between AVX (16) and AVX2 (32) width for int8\n\t{\"large\", 1024},  // Well above SIMD register widths\n\t{\"xlarge\", 8192}, // Large dataset for real-world performance\n}\n\nfunc init() {\n\t// Seeded for reproducibility\n\trand.Seed(time.Now().UnixNano())\n}\n\n// Helper function to generate random test data\ntype benchDataGenerator[T any] func(n int) []T\n\nfunc generateInt8(n int) []int8 {\n\tdata := make([]int8, n)\n\tfor i := range data {\n\t\tdata[i] = int8(rand.Intn(127) - 64)\n\t}\n\treturn data\n}\n\nfunc generateInt16(n int) []int16 {\n\tdata := make([]int16, n)\n\tfor i := range data {\n\t\tdata[i] = int16(rand.Intn(32767) - 16384)\n\t}\n\treturn data\n}\n\nfunc generateInt32(n int) []int32 {\n\tdata := make([]int32, n)\n\tfor i := range data {\n\t\tdata[i] = int32(rand.Intn(1000) - 500)\n\t}\n\treturn data\n}\n\nfunc generateInt64(n int) []int64 {\n\tdata := make([]int64, n)\n\tfor i := range data {\n\t\tdata[i] = rand.Int63() % 10000\n\t}\n\treturn data\n}\n\nfunc generateUint8(n int) []uint8 {\n\tdata := make([]uint8, n)\n\tfor i := range data {\n\t\tdata[i] = uint8(rand.Uint32() % 256)\n\t}\n\treturn data\n}\n\nfunc generateUint16(n int) []uint16 {\n\tdata := make([]uint16, n)\n\tfor i := range data {\n\t\tdata[i] = uint16(rand.Uint32() % 65536)\n\t}\n\treturn data\n}\n\nfunc generateUint32(n int) []uint32 {\n\tdata := make([]uint32, n)\n\tfor i := range data {\n\t\tdata[i] = rand.Uint32() % 10000\n\t}\n\treturn data\n}\n\nfunc generateUint64(n int) []uint64 {\n\tdata := make([]uint64, n)\n\tfor i := range data {\n\t\tdata[i] = rand.Uint64() % 10000\n\t}\n\treturn data\n}\n\nfunc generateFloat32(n int) []float32 {\n\tdata := make([]float32, n)\n\tfor i := range data {\n\t\tdata[i] = rand.Float32()*100 - 50\n\t}\n\treturn data\n}\n\nfunc generateFloat64(n int) []float64 {\n\tdata := make([]float64, n)\n\tfor i := range data {\n\t\tdata[i] = rand.Float64()*100 - 50\n\t}\n\treturn data\n}\n\n// ============================================================================\n// SUM BENCHMARKS\n// ============================================================================\n\nfunc BenchmarkSumInt8(b *testing.B) {\n\tfor _, bs := range benchmarkSizes {\n\t\tb.Run(bs.name, func(b *testing.B) {\n\t\t\tdata := generateInt8(bs.size)\n\t\t\tb.Run(\"Fallback-lo\", func(b *testing.B) {\n\t\t\t\tb.ReportAllocs()\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = lo.Sum(data)\n\t\t\t\t}\n\t\t\t})\n\t\t\tb.Run(\"AVX-x16\", func(b *testing.B) {\n\t\t\t\trequireAVX(b)\n\t\t\t\tb.ReportAllocs()\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = SumInt8x16(data)\n\t\t\t\t}\n\t\t\t})\n\t\t\tb.Run(\"AVX2-x32\", func(b *testing.B) {\n\t\t\t\trequireAVX2(b)\n\t\t\t\tb.ReportAllocs()\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = SumInt8x32(data)\n\t\t\t\t}\n\t\t\t})\n\t\t\tb.Run(\"AVX512-x64\", func(b *testing.B) {\n\t\t\t\trequireAVX512(b)\n\t\t\t\tb.ReportAllocs()\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = SumInt8x64(data)\n\t\t\t\t}\n\t\t\t})\n\t\t})\n\t}\n}\n\nfunc BenchmarkSumInt16(b *testing.B) {\n\tfor _, bs := range benchmarkSizes {\n\t\tb.Run(bs.name, func(b *testing.B) {\n\t\t\tdata := generateInt16(bs.size)\n\t\t\tb.Run(\"Fallback-lo\", func(b *testing.B) {\n\t\t\t\tb.ReportAllocs()\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = lo.Sum(data)\n\t\t\t\t}\n\t\t\t})\n\t\t\tb.Run(\"AVX-x8\", func(b *testing.B) {\n\t\t\t\trequireAVX(b)\n\t\t\t\tb.ReportAllocs()\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = SumInt16x8(data)\n\t\t\t\t}\n\t\t\t})\n\t\t\tb.Run(\"AVX2-x16\", func(b *testing.B) {\n\t\t\t\trequireAVX2(b)\n\t\t\t\tb.ReportAllocs()\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = SumInt16x16(data)\n\t\t\t\t}\n\t\t\t})\n\t\t\tb.Run(\"AVX512-x32\", func(b *testing.B) {\n\t\t\t\trequireAVX512(b)\n\t\t\t\tb.ReportAllocs()\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = SumInt16x32(data)\n\t\t\t\t}\n\t\t\t})\n\t\t})\n\t}\n}\n\nfunc BenchmarkSumInt32(b *testing.B) {\n\tfor _, bs := range benchmarkSizes {\n\t\tb.Run(bs.name, func(b *testing.B) {\n\t\t\tdata := generateInt32(bs.size)\n\t\t\tb.Run(\"Fallback-lo\", func(b *testing.B) {\n\t\t\t\tb.ReportAllocs()\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = lo.Sum(data)\n\t\t\t\t}\n\t\t\t})\n\t\t\tb.Run(\"AVX-x4\", func(b *testing.B) {\n\t\t\t\trequireAVX(b)\n\t\t\t\tb.ReportAllocs()\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = SumInt32x4(data)\n\t\t\t\t}\n\t\t\t})\n\t\t\tb.Run(\"AVX2-x8\", func(b *testing.B) {\n\t\t\t\trequireAVX2(b)\n\t\t\t\tb.ReportAllocs()\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = SumInt32x8(data)\n\t\t\t\t}\n\t\t\t})\n\t\t\tb.Run(\"AVX512-x16\", func(b *testing.B) {\n\t\t\t\trequireAVX512(b)\n\t\t\t\tb.ReportAllocs()\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = SumInt32x16(data)\n\t\t\t\t}\n\t\t\t})\n\t\t})\n\t}\n}\n\nfunc BenchmarkSumInt64(b *testing.B) {\n\tfor _, bs := range benchmarkSizes {\n\t\tb.Run(bs.name, func(b *testing.B) {\n\t\t\tdata := generateInt64(bs.size)\n\t\t\tb.Run(\"Fallback-lo\", func(b *testing.B) {\n\t\t\t\tb.ReportAllocs()\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = lo.Sum(data)\n\t\t\t\t}\n\t\t\t})\n\t\t\tb.Run(\"AVX-x2\", func(b *testing.B) {\n\t\t\t\trequireAVX(b)\n\t\t\t\tb.ReportAllocs()\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = SumInt64x2(data)\n\t\t\t\t}\n\t\t\t})\n\t\t\tb.Run(\"AVX2-x4\", func(b *testing.B) {\n\t\t\t\trequireAVX2(b)\n\t\t\t\tb.ReportAllocs()\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = SumInt64x4(data)\n\t\t\t\t}\n\t\t\t})\n\t\t\tb.Run(\"AVX512-x8\", func(b *testing.B) {\n\t\t\t\trequireAVX512(b)\n\t\t\t\tb.ReportAllocs()\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = SumInt64x8(data)\n\t\t\t\t}\n\t\t\t})\n\t\t})\n\t}\n}\n\nfunc BenchmarkSumFloat32(b *testing.B) {\n\tfor _, bs := range benchmarkSizes {\n\t\tb.Run(bs.name, func(b *testing.B) {\n\t\t\tdata := generateFloat32(bs.size)\n\t\t\tb.Run(\"Fallback-lo\", func(b *testing.B) {\n\t\t\t\tb.ReportAllocs()\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = lo.Sum(data)\n\t\t\t\t}\n\t\t\t})\n\t\t\tb.Run(\"AVX-x4\", func(b *testing.B) {\n\t\t\t\trequireAVX(b)\n\t\t\t\tb.ReportAllocs()\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = SumFloat32x4(data)\n\t\t\t\t}\n\t\t\t})\n\t\t\tb.Run(\"AVX2-x8\", func(b *testing.B) {\n\t\t\t\trequireAVX2(b)\n\t\t\t\tb.ReportAllocs()\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = SumFloat32x8(data)\n\t\t\t\t}\n\t\t\t})\n\t\t\tb.Run(\"AVX512-x16\", func(b *testing.B) {\n\t\t\t\trequireAVX512(b)\n\t\t\t\tb.ReportAllocs()\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = SumFloat32x16(data)\n\t\t\t\t}\n\t\t\t})\n\t\t})\n\t}\n}\n\nfunc BenchmarkSumFloat64(b *testing.B) {\n\tfor _, bs := range benchmarkSizes {\n\t\tb.Run(bs.name, func(b *testing.B) {\n\t\t\tdata := generateFloat64(bs.size)\n\t\t\tb.Run(\"Fallback-lo\", func(b *testing.B) {\n\t\t\t\tb.ReportAllocs()\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = lo.Sum(data)\n\t\t\t\t}\n\t\t\t})\n\t\t\tb.Run(\"AVX-x2\", func(b *testing.B) {\n\t\t\t\trequireAVX(b)\n\t\t\t\tb.ReportAllocs()\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = SumFloat64x2(data)\n\t\t\t\t}\n\t\t\t})\n\t\t\tb.Run(\"AVX2-x4\", func(b *testing.B) {\n\t\t\t\trequireAVX2(b)\n\t\t\t\tb.ReportAllocs()\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = SumFloat64x4(data)\n\t\t\t\t}\n\t\t\t})\n\t\t\tb.Run(\"AVX512-x8\", func(b *testing.B) {\n\t\t\t\trequireAVX512(b)\n\t\t\t\tb.ReportAllocs()\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = SumFloat64x8(data)\n\t\t\t\t}\n\t\t\t})\n\t\t})\n\t}\n}\n\n// ============================================================================\n// MEAN BENCHMARKS\n// ============================================================================\n\nfunc BenchmarkMeanInt32(b *testing.B) {\n\tfor _, bs := range benchmarkSizes {\n\t\tb.Run(bs.name, func(b *testing.B) {\n\t\t\tdata := generateInt32(bs.size)\n\t\t\tb.Run(\"Fallback-lo\", func(b *testing.B) {\n\t\t\t\tb.ReportAllocs()\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = lo.Mean(data)\n\t\t\t\t}\n\t\t\t})\n\t\t\tb.Run(\"AVX-x4\", func(b *testing.B) {\n\t\t\t\trequireAVX(b)\n\t\t\t\tb.ReportAllocs()\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = MeanInt32x4(data)\n\t\t\t\t}\n\t\t\t})\n\t\t\tb.Run(\"AVX2-x8\", func(b *testing.B) {\n\t\t\t\trequireAVX2(b)\n\t\t\t\tb.ReportAllocs()\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = MeanInt32x8(data)\n\t\t\t\t}\n\t\t\t})\n\t\t\tb.Run(\"AVX512-x16\", func(b *testing.B) {\n\t\t\t\trequireAVX512(b)\n\t\t\t\tb.ReportAllocs()\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = MeanInt32x16(data)\n\t\t\t\t}\n\t\t\t})\n\t\t})\n\t}\n}\n\nfunc BenchmarkMeanFloat64(b *testing.B) {\n\tfor _, bs := range benchmarkSizes {\n\t\tb.Run(bs.name, func(b *testing.B) {\n\t\t\tdata := generateFloat64(bs.size)\n\t\t\tb.Run(\"Fallback-lo\", func(b *testing.B) {\n\t\t\t\tb.ReportAllocs()\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = lo.Mean(data)\n\t\t\t\t}\n\t\t\t})\n\t\t\tb.Run(\"AVX-x2\", func(b *testing.B) {\n\t\t\t\trequireAVX(b)\n\t\t\t\tb.ReportAllocs()\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = MeanFloat64x2(data)\n\t\t\t\t}\n\t\t\t})\n\t\t\tb.Run(\"AVX2-x4\", func(b *testing.B) {\n\t\t\t\trequireAVX2(b)\n\t\t\t\tb.ReportAllocs()\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = MeanFloat64x4(data)\n\t\t\t\t}\n\t\t\t})\n\t\t\tb.Run(\"AVX512-x8\", func(b *testing.B) {\n\t\t\t\trequireAVX512(b)\n\t\t\t\tb.ReportAllocs()\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = MeanFloat64x8(data)\n\t\t\t\t}\n\t\t\t})\n\t\t})\n\t}\n}\n\n// ============================================================================\n// MIN BENCHMARKS\n// ============================================================================\n\nfunc BenchmarkMinInt32(b *testing.B) {\n\tfor _, bs := range benchmarkSizes {\n\t\tb.Run(bs.name, func(b *testing.B) {\n\t\t\tdata := generateInt32(bs.size)\n\t\t\tb.Run(\"AVX-x4\", func(b *testing.B) {\n\t\t\t\trequireAVX(b)\n\t\t\t\tb.ReportAllocs()\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = MinInt32x4(data)\n\t\t\t\t}\n\t\t\t})\n\t\t\tb.Run(\"AVX2-x8\", func(b *testing.B) {\n\t\t\t\trequireAVX2(b)\n\t\t\t\tb.ReportAllocs()\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = MinInt32x8(data)\n\t\t\t\t}\n\t\t\t})\n\t\t\tb.Run(\"AVX512-x16\", func(b *testing.B) {\n\t\t\t\trequireAVX512(b)\n\t\t\t\tb.ReportAllocs()\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = MinInt32x16(data)\n\t\t\t\t}\n\t\t\t})\n\t\t})\n\t}\n}\n\nfunc BenchmarkMinFloat64(b *testing.B) {\n\tfor _, bs := range benchmarkSizes {\n\t\tb.Run(bs.name, func(b *testing.B) {\n\t\t\tdata := generateFloat64(bs.size)\n\t\t\tb.Run(\"AVX-x2\", func(b *testing.B) {\n\t\t\t\trequireAVX(b)\n\t\t\t\tb.ReportAllocs()\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = MinFloat64x2(data)\n\t\t\t\t}\n\t\t\t})\n\t\t\tb.Run(\"AVX2-x4\", func(b *testing.B) {\n\t\t\t\trequireAVX2(b)\n\t\t\t\tb.ReportAllocs()\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = MinFloat64x4(data)\n\t\t\t\t}\n\t\t\t})\n\t\t\tb.Run(\"AVX512-x8\", func(b *testing.B) {\n\t\t\t\trequireAVX512(b)\n\t\t\t\tb.ReportAllocs()\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = MinFloat64x8(data)\n\t\t\t\t}\n\t\t\t})\n\t\t})\n\t}\n}\n\n// ============================================================================\n// MAX BENCHMARKS\n// ============================================================================\n\nfunc BenchmarkMaxInt32(b *testing.B) {\n\tfor _, bs := range benchmarkSizes {\n\t\tb.Run(bs.name, func(b *testing.B) {\n\t\t\tdata := generateInt32(bs.size)\n\t\t\tb.Run(\"AVX-x4\", func(b *testing.B) {\n\t\t\t\trequireAVX(b)\n\t\t\t\tb.ReportAllocs()\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = MaxInt32x4(data)\n\t\t\t\t}\n\t\t\t})\n\t\t\tb.Run(\"AVX2-x8\", func(b *testing.B) {\n\t\t\t\trequireAVX2(b)\n\t\t\t\tb.ReportAllocs()\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = MaxInt32x8(data)\n\t\t\t\t}\n\t\t\t})\n\t\t\tb.Run(\"AVX512-x16\", func(b *testing.B) {\n\t\t\t\trequireAVX512(b)\n\t\t\t\tb.ReportAllocs()\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = MaxInt32x16(data)\n\t\t\t\t}\n\t\t\t})\n\t\t})\n\t}\n}\n\nfunc BenchmarkMaxFloat64(b *testing.B) {\n\tfor _, bs := range benchmarkSizes {\n\t\tb.Run(bs.name, func(b *testing.B) {\n\t\t\tdata := generateFloat64(bs.size)\n\t\t\tb.Run(\"AVX-x2\", func(b *testing.B) {\n\t\t\t\trequireAVX(b)\n\t\t\t\tb.ReportAllocs()\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = MaxFloat64x2(data)\n\t\t\t\t}\n\t\t\t})\n\t\t\tb.Run(\"AVX2-x4\", func(b *testing.B) {\n\t\t\t\trequireAVX2(b)\n\t\t\t\tb.ReportAllocs()\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = MaxFloat64x4(data)\n\t\t\t\t}\n\t\t\t})\n\t\t\tb.Run(\"AVX512-x8\", func(b *testing.B) {\n\t\t\t\trequireAVX512(b)\n\t\t\t\tb.ReportAllocs()\n\t\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t\t_ = MaxFloat64x8(data)\n\t\t\t\t}\n\t\t\t})\n\t\t})\n\t}\n}\n\n// ============================================================================\n// LANE WIDTH COMPARISON BENCHMARKS\n// ============================================================================\n\n// These benchmarks show how performance scales with SIMD register width\nfunc BenchmarkSumInt8ByWidth(b *testing.B) {\n\tsize := 4096 // Large enough to see differences across implementations\n\tdata := generateInt8(size)\n\n\tbenchmarks := []struct {\n\t\tname string\n\t\tfn   func() int8\n\t}{\n\t\t{\"Fallback-lo\", func() int8 { return lo.Sum(data) }},\n\t\t{\"AVX-x16\", func() int8 { return SumInt8x16(data) }},\n\t\t{\"AVX2-x32\", func() int8 { return SumInt8x32(data) }},\n\t\t{\"AVX512-x64\", func() int8 { return SumInt8x64(data) }},\n\t}\n\n\tfor _, bm := range benchmarks {\n\t\tb.Run(bm.name, func(b *testing.B) {\n\t\t\tif bm.name == \"AVX-x16\" {\n\t\t\t\trequireAVX(b)\n\t\t\t}\n\t\t\tif bm.name == \"AVX2-x32\" {\n\t\t\t\trequireAVX2(b)\n\t\t\t}\n\t\t\tif bm.name == \"AVX512-x64\" {\n\t\t\t\trequireAVX512(b)\n\t\t\t}\n\t\t\tb.ReportAllocs()\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = bm.fn()\n\t\t\t}\n\t\t})\n\t}\n}\n\n// ============================================================================\n// COMPARATIVE BENCHMARK WITH WARMUP\n// ============================================================================\n\n// This benchmark demonstrates the steady-state performance after warmup\nfunc BenchmarkSumInt64SteadyState(b *testing.B) {\n\tsize := 8192\n\tdata := generateInt64(size)\n\n\t// Warmup phase to ensure JIT compilation if applicable\n\tfor i := 0; i < 1000; i++ {\n\t\tlo.Sum(data)\n\t\tSumInt64x2(data)\n\t\tif archsimd.X86.AVX2() {\n\t\t\tSumInt64x4(data)\n\t\t}\n\t\tif archsimd.X86.AVX512() {\n\t\t\tSumInt64x8(data)\n\t\t}\n\t}\n\n\tb.ResetTimer() // Reset timer to exclude warmup\n\n\tb.Run(\"Fallback-lo\", func(b *testing.B) {\n\t\tb.ReportAllocs()\n\t\tfor i := 0; i < b.N; i++ {\n\t\t\t_ = lo.Sum(data)\n\t\t}\n\t})\n\tb.Run(\"AVX-x2\", func(b *testing.B) {\n\t\trequireAVX(b)\n\t\tb.ReportAllocs()\n\t\tfor i := 0; i < b.N; i++ {\n\t\t\t_ = SumInt64x2(data)\n\t\t}\n\t})\n\tb.Run(\"AVX2-x4\", func(b *testing.B) {\n\t\trequireAVX2(b)\n\t\tb.ReportAllocs()\n\t\tfor i := 0; i < b.N; i++ {\n\t\t\t_ = SumInt64x4(data)\n\t\t}\n\t})\n\tb.Run(\"AVX512-x8\", func(b *testing.B) {\n\t\trequireAVX512(b)\n\t\tb.ReportAllocs()\n\t\tfor i := 0; i < b.N; i++ {\n\t\t\t_ = SumInt64x8(data)\n\t\t}\n\t})\n}\n"
  },
  {
    "path": "exp/simd/simd.go",
    "content": "package simd\n\n// Empty file to satisfy the build constraint for non-supported architectures.\n"
  },
  {
    "path": "exp/simd/simd_test.go",
    "content": "//go:build go1.26 && goexperiment.simd && amd64\n\npackage simd\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"strings\"\n\n\t\"simd/archsimd\"\n)\n\nfunc init() {\n\tfor _, arg := range os.Args {\n\t\tif strings.HasPrefix(arg, \"-test.bench=\") {\n\t\t\tbench := strings.TrimPrefix(arg, \"-test.bench=\")\n\t\t\tif bench != \"\" && bench != \"none\" {\n\t\t\t\tfmt.Fprintf(os.Stdout, \"archsimd.X86: AVX=%v AVX2=%v AVX512=%v\\n\",\n\t\t\t\t\tarchsimd.X86.AVX(), archsimd.X86.AVX2(), archsimd.X86.AVX512())\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n}\n\n// Type aliases for testing\ntype (\n\tmyInt8    int8\n\tmyInt16   int16\n\tmyInt32   int32\n\tmyInt64   int64\n\tmyUint8   uint8\n\tmyUint16  uint16\n\tmyUint32  uint32\n\tmyUint64  uint64\n\tmyFloat32 float32\n\tmyFloat64 float64\n)\n"
  },
  {
    "path": "exp/simd/unsafe.go",
    "content": "//go:build go1.26 && goexperiment.simd && amd64\n\npackage simd\n\nimport \"unsafe\"\n\n// unsafeSliceInt8 converts a []T (where T ~int8) to []int8 via unsafe operations.\n// This helper reduces code duplication and the risk of copy-paste errors.\n//\n//go:nosplit\nfunc unsafeSliceInt8[T ~int8](collection []T, length uint) []int8 {\n\t// bearer:disable go_gosec_unsafe_unsafe\n\treturn unsafe.Slice((*int8)(unsafe.Pointer(&collection[0])), length)\n}\n\n// unsafeSliceInt16 converts a []T (where T ~int16) to []int16 via unsafe operations.\n//\n//go:nosplit\nfunc unsafeSliceInt16[T ~int16](collection []T, length uint) []int16 {\n\t// bearer:disable go_gosec_unsafe_unsafe\n\treturn unsafe.Slice((*int16)(unsafe.Pointer(&collection[0])), length)\n}\n\n// unsafeSliceInt32 converts a []T (where T ~int32) to []int32 via unsafe operations.\n//\n//go:nosplit\nfunc unsafeSliceInt32[T ~int32](collection []T, length uint) []int32 {\n\t// bearer:disable go_gosec_unsafe_unsafe\n\treturn unsafe.Slice((*int32)(unsafe.Pointer(&collection[0])), length)\n}\n\n// unsafeSliceInt64 converts a []T (where T ~int64) to []int64 via unsafe operations.\n//\n//go:nosplit\nfunc unsafeSliceInt64[T ~int64](collection []T, length uint) []int64 {\n\t// bearer:disable go_gosec_unsafe_unsafe\n\treturn unsafe.Slice((*int64)(unsafe.Pointer(&collection[0])), length)\n}\n\n// unsafeSliceUint8 converts a []T (where T ~uint8) to []uint8 via unsafe operations.\n//\n//go:nosplit\nfunc unsafeSliceUint8[T ~uint8](collection []T, length uint) []uint8 {\n\t// bearer:disable go_gosec_unsafe_unsafe\n\treturn unsafe.Slice((*uint8)(unsafe.Pointer(&collection[0])), length)\n}\n\n// unsafeSliceUint16 converts a []T (where T ~uint16) to []uint16 via unsafe operations.\n//\n//go:nosplit\nfunc unsafeSliceUint16[T ~uint16](collection []T, length uint) []uint16 {\n\t// bearer:disable go_gosec_unsafe_unsafe\n\treturn unsafe.Slice((*uint16)(unsafe.Pointer(&collection[0])), length)\n}\n\n// unsafeSliceUint32 converts a []T (where T ~uint32) to []uint32 via unsafe operations.\n//\n//go:nosplit\nfunc unsafeSliceUint32[T ~uint32](collection []T, length uint) []uint32 {\n\t// bearer:disable go_gosec_unsafe_unsafe\n\treturn unsafe.Slice((*uint32)(unsafe.Pointer(&collection[0])), length)\n}\n\n// unsafeSliceUint64 converts a []T (where T ~uint64) to []uint64 via unsafe operations.\n//\n//go:nosplit\nfunc unsafeSliceUint64[T ~uint64](collection []T, length uint) []uint64 {\n\t// bearer:disable go_gosec_unsafe_unsafe\n\treturn unsafe.Slice((*uint64)(unsafe.Pointer(&collection[0])), length)\n}\n\n// unsafeSliceFloat32 converts a []T (where T ~float32) to []float32 via unsafe operations.\n//\n//go:nosplit\nfunc unsafeSliceFloat32[T ~float32](collection []T, length uint) []float32 {\n\t// bearer:disable go_gosec_unsafe_unsafe\n\treturn unsafe.Slice((*float32)(unsafe.Pointer(&collection[0])), length)\n}\n\n// unsafeSliceFloat64 converts a []T (where T ~float64) to []float64 via unsafe operations.\n//\n//go:nosplit\nfunc unsafeSliceFloat64[T ~float64](collection []T, length uint) []float64 {\n\t// bearer:disable go_gosec_unsafe_unsafe\n\treturn unsafe.Slice((*float64)(unsafe.Pointer(&collection[0])), length)\n}\n"
  },
  {
    "path": "find.go",
    "content": "package lo\n\nimport (\n\t\"time\"\n\n\t\"github.com/samber/lo/internal/constraints\"\n\t\"github.com/samber/lo/internal/xrand\"\n)\n\n// IndexOf returns the index at which the first occurrence of a value is found in a slice or -1\n// if the value cannot be found.\n// Play: https://go.dev/play/p/Eo7W0lvKTky\nfunc IndexOf[T comparable](collection []T, element T) int {\n\tfor i := range collection {\n\t\tif collection[i] == element {\n\t\t\treturn i\n\t\t}\n\t}\n\n\treturn -1\n}\n\n// LastIndexOf returns the index at which the last occurrence of a value is found in a slice or -1\n// if the value cannot be found.\n// Play: https://go.dev/play/p/Eo7W0lvKTky\nfunc LastIndexOf[T comparable](collection []T, element T) int {\n\tlength := len(collection)\n\n\tfor i := length - 1; i >= 0; i-- {\n\t\tif collection[i] == element {\n\t\t\treturn i\n\t\t}\n\t}\n\n\treturn -1\n}\n\n// HasPrefix returns true if the collection has the prefix.\n// Play: https://go.dev/play/p/SrljzVDpMQM\nfunc HasPrefix[T comparable](collection, prefix []T) bool {\n\tif len(collection) < len(prefix) {\n\t\treturn false\n\t}\n\n\tfor i := range prefix {\n\t\tif collection[i] != prefix[i] {\n\t\t\treturn false\n\t\t}\n\t}\n\n\treturn true\n}\n\n// HasSuffix returns true if the collection has the suffix.\n// Play: https://go.dev/play/p/bJeLetQNAON\nfunc HasSuffix[T comparable](collection, suffix []T) bool {\n\tif len(collection) < len(suffix) {\n\t\treturn false\n\t}\n\n\tfor i := range suffix {\n\t\tif collection[len(collection)-len(suffix)+i] != suffix[i] {\n\t\t\treturn false\n\t\t}\n\t}\n\n\treturn true\n}\n\n// Find searches for an element in a slice based on a predicate. Returns element and true if element was found.\n// Play: https://go.dev/play/p/Eo7W0lvKTky\nfunc Find[T any](collection []T, predicate func(item T) bool) (T, bool) {\n\tfor i := range collection {\n\t\tif predicate(collection[i]) {\n\t\t\treturn collection[i], true\n\t\t}\n\t}\n\n\tvar result T\n\treturn result, false\n}\n\n// FindErr searches for an element in a slice based on a predicate that can return an error.\n// Returns the element and nil error if the element is found.\n// Returns zero value and nil error if the element is not found.\n// If the predicate returns an error, iteration stops immediately and returns zero value and the error.\n// Play: https://go.dev/play/p/XK-qtpQWXJ9\nfunc FindErr[T any](collection []T, predicate func(item T) (bool, error)) (T, error) {\n\tfor i := range collection {\n\t\tmatches, err := predicate(collection[i])\n\t\tif err != nil {\n\t\t\tvar result T\n\t\t\treturn result, err\n\t\t}\n\t\tif matches {\n\t\t\treturn collection[i], nil\n\t\t}\n\t}\n\n\tvar result T\n\treturn result, nil\n}\n\n// FindIndexOf searches for an element in a slice based on a predicate and returns the index and true.\n// Returns -1 and false if the element is not found.\n// Play: https://go.dev/play/p/XWSEM4Ic_t0\nfunc FindIndexOf[T any](collection []T, predicate func(item T) bool) (T, int, bool) {\n\tfor i := range collection {\n\t\tif predicate(collection[i]) {\n\t\t\treturn collection[i], i, true\n\t\t}\n\t}\n\n\tvar result T\n\treturn result, -1, false\n}\n\n// FindLastIndexOf searches for the last element in a slice based on a predicate and returns the index and true.\n// Returns -1 and false if the element is not found.\n// Play: https://go.dev/play/p/2VhPMiQvX-D\nfunc FindLastIndexOf[T any](collection []T, predicate func(item T) bool) (T, int, bool) {\n\tlength := len(collection)\n\n\tfor i := length - 1; i >= 0; i-- {\n\t\tif predicate(collection[i]) {\n\t\t\treturn collection[i], i, true\n\t\t}\n\t}\n\n\tvar result T\n\treturn result, -1, false\n}\n\n// FindOrElse searches for an element in a slice based on a predicate. Returns the element if found or a given fallback value otherwise.\n// Play: https://go.dev/play/p/Eo7W0lvKTky\nfunc FindOrElse[T any](collection []T, fallback T, predicate func(item T) bool) T {\n\tfor i := range collection {\n\t\tif predicate(collection[i]) {\n\t\t\treturn collection[i]\n\t\t}\n\t}\n\n\treturn fallback\n}\n\n// FindKey returns the key of the first value matching.\n// Play: https://go.dev/play/p/Bg0w1VDPYXx\nfunc FindKey[K, V comparable](object map[K]V, value V) (K, bool) {\n\tfor k, v := range object {\n\t\tif v == value {\n\t\t\treturn k, true\n\t\t}\n\t}\n\n\treturn Empty[K](), false\n}\n\n// FindKeyBy returns the key of the first element predicate returns true for.\n// Play: https://go.dev/play/p/9IbiPElcyo8\nfunc FindKeyBy[K comparable, V any](object map[K]V, predicate func(key K, value V) bool) (K, bool) {\n\tfor k, v := range object {\n\t\tif predicate(k, v) {\n\t\t\treturn k, true\n\t\t}\n\t}\n\n\treturn Empty[K](), false\n}\n\n// FindUniques returns a slice with all the elements that appear in the collection only once.\n// The order of result values is determined by the order they occur in the collection.\n// Play: https://go.dev/play/p/NV5vMK_2Z_n\nfunc FindUniques[T comparable, Slice ~[]T](collection Slice) Slice {\n\tisDupl := make(map[T]bool, len(collection))\n\n\tduplicates := 0\n\n\tfor i := range collection {\n\t\tduplicated, seen := isDupl[collection[i]]\n\t\tif !duplicated {\n\t\t\tisDupl[collection[i]] = seen\n\n\t\t\tif seen {\n\t\t\t\tduplicates++\n\t\t\t}\n\t\t}\n\t}\n\n\tresult := make(Slice, 0, len(isDupl)-duplicates)\n\n\tfor i := range collection {\n\t\tif duplicated := isDupl[collection[i]]; !duplicated {\n\t\t\tresult = append(result, collection[i])\n\t\t}\n\t}\n\n\treturn result\n}\n\n// FindUniquesBy returns a slice with all the elements that appear in the collection only once.\n// The order of result values is determined by the order they occur in the slice. It accepts `iteratee` which is\n// invoked for each element in the slice to generate the criterion by which uniqueness is computed.\n// Play: https://go.dev/play/p/2vmxCs4kW_m\nfunc FindUniquesBy[T any, U comparable, Slice ~[]T](collection Slice, iteratee func(item T) U) Slice {\n\tisDupl := make(map[U]bool, len(collection))\n\n\tduplicates := 0\n\n\tfor i := range collection {\n\t\tkey := iteratee(collection[i])\n\n\t\tduplicated, seen := isDupl[key]\n\t\tif !duplicated {\n\t\t\tisDupl[key] = seen\n\n\t\t\tif seen {\n\t\t\t\tduplicates++\n\t\t\t}\n\t\t}\n\t}\n\n\tresult := make(Slice, 0, len(isDupl)-duplicates)\n\n\tfor i := range collection {\n\t\tkey := iteratee(collection[i])\n\n\t\tif duplicated := isDupl[key]; !duplicated {\n\t\t\tresult = append(result, collection[i])\n\t\t}\n\t}\n\n\treturn result\n}\n\n// FindDuplicates returns a slice with the first occurrence of each duplicated element in the collection.\n// The order of result values is determined by the order they occur in the collection.\n// Play: https://go.dev/play/p/muFgL_XBwoP\nfunc FindDuplicates[T comparable, Slice ~[]T](collection Slice) Slice {\n\tisDupl := make(map[T]bool, len(collection))\n\n\tduplicates := 0\n\n\tfor i := range collection {\n\t\tduplicated, seen := isDupl[collection[i]]\n\t\tif !duplicated {\n\t\t\tisDupl[collection[i]] = seen\n\n\t\t\tif seen {\n\t\t\t\tduplicates++\n\t\t\t}\n\t\t}\n\t}\n\n\tresult := make(Slice, 0, duplicates)\n\n\tfor i := range collection {\n\t\tif duplicated := isDupl[collection[i]]; duplicated {\n\t\t\tresult = append(result, collection[i])\n\t\t\tisDupl[collection[i]] = false\n\t\t}\n\t}\n\n\treturn result\n}\n\n// FindDuplicatesBy returns a slice with the first occurrence of each duplicated element in the collection.\n// The order of result values is determined by the order they occur in the slice. It accepts `iteratee` which is\n// invoked for each element in the slice to generate the criterion by which uniqueness is computed.\n// Play: https://go.dev/play/p/LKdYdNHuGJG\nfunc FindDuplicatesBy[T any, U comparable, Slice ~[]T](collection Slice, iteratee func(item T) U) Slice {\n\tisDupl := make(map[U]bool, len(collection))\n\n\tduplicates := 0\n\n\tfor i := range collection {\n\t\tkey := iteratee(collection[i])\n\n\t\tduplicated, seen := isDupl[key]\n\t\tif !duplicated {\n\t\t\tisDupl[key] = seen\n\n\t\t\tif seen {\n\t\t\t\tduplicates++\n\t\t\t}\n\t\t}\n\t}\n\n\tresult := make(Slice, 0, duplicates)\n\n\tfor i := range collection {\n\t\tkey := iteratee(collection[i])\n\n\t\tif duplicated := isDupl[key]; duplicated {\n\t\t\tresult = append(result, collection[i])\n\t\t\tisDupl[key] = false\n\t\t}\n\t}\n\n\treturn result\n}\n\n// FindDuplicatesByErr returns a slice with the first occurrence of each duplicated element in the collection.\n// The order of result values is determined by the order they occur in the slice. It accepts `iteratee` which is\n// invoked for each element in the slice to generate the criterion by which uniqueness is computed.\n// If the iteratee returns an error, iteration stops immediately and the error is returned with a nil slice.\n// Play: https://go.dev/play/p/HiVILQqdFP0\nfunc FindDuplicatesByErr[T any, U comparable, Slice ~[]T](collection Slice, iteratee func(item T) (U, error)) (Slice, error) {\n\tisDupl := make(map[U]bool, len(collection))\n\n\tduplicates := 0\n\n\t// First pass: identify duplicates\n\tfor i := range collection {\n\t\tkey, err := iteratee(collection[i])\n\t\tif err != nil {\n\t\t\tvar result Slice\n\t\t\treturn result, err\n\t\t}\n\n\t\tduplicated, seen := isDupl[key]\n\t\tif !duplicated {\n\t\t\tisDupl[key] = seen\n\n\t\t\tif seen {\n\t\t\t\tduplicates++\n\t\t\t}\n\t\t}\n\t}\n\n\tresult := make(Slice, 0, duplicates)\n\n\t// Second pass: collect first occurrences of duplicates\n\tfor i := range collection {\n\t\tkey, err := iteratee(collection[i])\n\t\tif err != nil {\n\t\t\tvar result Slice\n\t\t\treturn result, err\n\t\t}\n\n\t\tif duplicated := isDupl[key]; duplicated {\n\t\t\tresult = append(result, collection[i])\n\t\t\tisDupl[key] = false\n\t\t}\n\t}\n\n\treturn result, nil\n}\n\n// Min search the minimum value of a collection.\n// Returns zero value when the collection is empty.\n// Play: https://go.dev/play/p/fJFLwpY8eMN\nfunc Min[T constraints.Ordered](collection []T) T {\n\tvar mIn T\n\n\tif len(collection) == 0 {\n\t\treturn mIn\n\t}\n\n\tmIn = collection[0]\n\n\tfor i := 1; i < len(collection); i++ {\n\t\titem := collection[i]\n\n\t\tif item < mIn {\n\t\t\tmIn = item\n\t\t}\n\t}\n\n\treturn mIn\n}\n\n// MinIndex search the minimum value of a collection and the index of the minimum value.\n// Returns (zero value, -1) when the collection is empty.\n// Play: https://go.dev/play/p/RxAidik4p50\nfunc MinIndex[T constraints.Ordered](collection []T) (T, int) {\n\tvar (\n\t\tmIn   T\n\t\tindex int\n\t)\n\n\tif len(collection) == 0 {\n\t\treturn mIn, -1\n\t}\n\n\tmIn = collection[0]\n\n\tfor i := 1; i < len(collection); i++ {\n\t\titem := collection[i]\n\n\t\tif item < mIn {\n\t\t\tmIn = item\n\t\t\tindex = i\n\t\t}\n\t}\n\n\treturn mIn, index\n}\n\n// MinBy search the minimum value of a collection using the given comparison function.\n// If several values of the collection are equal to the smallest value, returns the first such value.\n// Returns zero value when the collection is empty.\n// Play: https://go.dev/play/p/-B1PsrHVnfx\nfunc MinBy[T any](collection []T, less func(a, b T) bool) T {\n\tvar mIn T\n\n\tif len(collection) == 0 {\n\t\treturn mIn\n\t}\n\n\tmIn = collection[0]\n\n\tfor i := 1; i < len(collection); i++ {\n\t\titem := collection[i]\n\n\t\tif less(item, mIn) {\n\t\t\tmIn = item\n\t\t}\n\t}\n\n\treturn mIn\n}\n\n// MinByErr search the minimum value of a collection using the given comparison function.\n// If several values of the collection are equal to the smallest value, returns the first such value.\n// Returns zero value and nil error when the collection is empty.\n// If the comparison function returns an error, iteration stops and the error is returned.\n// Play: https://go.dev/play/p/nvDYGS8q895\nfunc MinByErr[T any](collection []T, less func(a, b T) (bool, error)) (T, error) {\n\tvar mIn T\n\n\tif len(collection) == 0 {\n\t\treturn mIn, nil\n\t}\n\n\tmIn = collection[0]\n\n\tfor i := 1; i < len(collection); i++ {\n\t\titem := collection[i]\n\n\t\tisLess, err := less(item, mIn)\n\t\tif err != nil {\n\t\t\tvar zero T\n\t\t\treturn zero, err\n\t\t}\n\t\tif isLess {\n\t\t\tmIn = item\n\t\t}\n\t}\n\n\treturn mIn, nil\n}\n\n// MinIndexBy search the minimum value of a collection using the given comparison function and the index of the minimum value.\n// If several values of the collection are equal to the smallest value, returns the first such value.\n// Returns (zero value, -1) when the collection is empty.\n// Play: https://go.dev/play/p/zwwPRqWhnUY\nfunc MinIndexBy[T any](collection []T, less func(a, b T) bool) (T, int) {\n\tvar (\n\t\tmIn   T\n\t\tindex int\n\t)\n\n\tif len(collection) == 0 {\n\t\treturn mIn, -1\n\t}\n\n\tmIn = collection[0]\n\n\tfor i := 1; i < len(collection); i++ {\n\t\titem := collection[i]\n\n\t\tif less(item, mIn) {\n\t\t\tmIn = item\n\t\t\tindex = i\n\t\t}\n\t}\n\n\treturn mIn, index\n}\n\n// MinIndexByErr search the minimum value of a collection using the given comparison function and the index of the minimum value.\n// If several values of the collection are equal to the smallest value, returns the first such value.\n// Returns (zero value, -1) when the collection is empty.\n// Comparison function can return an error to stop iteration immediately.\n// Play: https://go.dev/play/p/MUqi_NvTKM1\nfunc MinIndexByErr[T any](collection []T, less func(a, b T) (bool, error)) (T, int, error) {\n\tvar (\n\t\tmIn   T\n\t\tindex int\n\t)\n\n\tif len(collection) == 0 {\n\t\treturn mIn, -1, nil\n\t}\n\n\tmIn = collection[0]\n\n\tfor i := 1; i < len(collection); i++ {\n\t\titem := collection[i]\n\n\t\tisLess, err := less(item, mIn)\n\t\tif err != nil {\n\t\t\tvar zero T\n\t\t\treturn zero, -1, err\n\t\t}\n\n\t\tif isLess {\n\t\t\tmIn = item\n\t\t\tindex = i\n\t\t}\n\t}\n\n\treturn mIn, index, nil\n}\n\n// Earliest search the minimum time.Time of a collection.\n// Returns zero value when the collection is empty.\n// Play: https://go.dev/play/p/pRyy0c6hsBs\nfunc Earliest(times ...time.Time) time.Time {\n\tvar mIn time.Time\n\n\tif len(times) == 0 {\n\t\treturn mIn\n\t}\n\n\tmIn = times[0]\n\n\tfor i := 1; i < len(times); i++ {\n\t\titem := times[i]\n\n\t\tif item.Before(mIn) {\n\t\t\tmIn = item\n\t\t}\n\t}\n\n\treturn mIn\n}\n\n// EarliestBy search the minimum time.Time of a collection using the given iteratee function.\n// Returns zero value when the collection is empty.\n// Play: https://go.dev/play/p/0XvCF6vuLXC\nfunc EarliestBy[T any](collection []T, iteratee func(item T) time.Time) T {\n\tvar earliest T\n\n\tif len(collection) == 0 {\n\t\treturn earliest\n\t}\n\n\tearliest = collection[0]\n\tearliestTime := iteratee(collection[0])\n\n\tfor i := 1; i < len(collection); i++ {\n\t\titemTime := iteratee(collection[i])\n\n\t\tif itemTime.Before(earliestTime) {\n\t\t\tearliest = collection[i]\n\t\t\tearliestTime = itemTime\n\t\t}\n\t}\n\n\treturn earliest\n}\n\n// EarliestByErr search the minimum time.Time of a collection using the given iteratee function.\n// Returns zero value and nil error when the collection is empty.\n// If the iteratee returns an error, iteration stops and the error is returned.\n// Play: https://go.dev/play/p/zJUBUj7ANvq\nfunc EarliestByErr[T any](collection []T, iteratee func(item T) (time.Time, error)) (T, error) {\n\tvar earliest T\n\n\tif len(collection) == 0 {\n\t\treturn earliest, nil\n\t}\n\n\tearliestTime, err := iteratee(collection[0])\n\tif err != nil {\n\t\treturn earliest, err\n\t}\n\tearliest = collection[0]\n\n\tfor i := 1; i < len(collection); i++ {\n\t\titemTime, err := iteratee(collection[i])\n\t\tif err != nil {\n\t\t\treturn earliest, err\n\t\t}\n\n\t\tif itemTime.Before(earliestTime) {\n\t\t\tearliest = collection[i]\n\t\t\tearliestTime = itemTime\n\t\t}\n\t}\n\n\treturn earliest, nil\n}\n\n// Max searches the maximum value of a collection.\n// Returns zero value when the collection is empty.\n// Play: https://go.dev/play/p/wYvG8gRRFw-\nfunc Max[T constraints.Ordered](collection []T) T {\n\tvar mAx T\n\n\tif len(collection) == 0 {\n\t\treturn mAx\n\t}\n\n\tmAx = collection[0]\n\n\tfor i := 1; i < len(collection); i++ {\n\t\titem := collection[i]\n\n\t\tif item > mAx {\n\t\t\tmAx = item\n\t\t}\n\t}\n\n\treturn mAx\n}\n\n// MaxIndex searches the maximum value of a collection and the index of the maximum value.\n// Returns (zero value, -1) when the collection is empty.\n// Play: https://go.dev/play/p/RFkB4Mzb1qt\nfunc MaxIndex[T constraints.Ordered](collection []T) (T, int) {\n\tvar (\n\t\tmAx   T\n\t\tindex int\n\t)\n\n\tif len(collection) == 0 {\n\t\treturn mAx, -1\n\t}\n\n\tmAx = collection[0]\n\n\tfor i := 1; i < len(collection); i++ {\n\t\titem := collection[i]\n\n\t\tif item > mAx {\n\t\t\tmAx = item\n\t\t\tindex = i\n\t\t}\n\t}\n\n\treturn mAx, index\n}\n\n// MaxBy search the maximum value of a collection using the given comparison function.\n// If several values of the collection are equal to the greatest value, returns the first such value.\n// Returns zero value when the collection is empty.\n//\n// Note: the comparison function is inconsistent with most languages, since we use the opposite of the usual convention.\n// See https://github.com/samber/lo/issues/129\n//\n// Play: https://go.dev/play/p/PJCc-ThrwX1\nfunc MaxBy[T any](collection []T, greater func(a, b T) bool) T {\n\tvar mAx T\n\n\tif len(collection) == 0 {\n\t\treturn mAx\n\t}\n\n\tmAx = collection[0]\n\n\tfor i := 1; i < len(collection); i++ {\n\t\titem := collection[i]\n\n\t\tif greater(item, mAx) {\n\t\t\tmAx = item\n\t\t}\n\t}\n\n\treturn mAx\n}\n\n// MaxByErr search the maximum value of a collection using the given comparison function.\n// If several values of the collection are equal to the greatest value, returns the first such value.\n// Returns zero value and nil error when the collection is empty.\n// If the comparison function returns an error, iteration stops and the error is returned.\n//\n// Note: the comparison function is inconsistent with most languages, since we use the opposite of the usual convention.\n// See https://github.com/samber/lo/issues/129\n//\n// Play: https://go.dev/play/p/s-63-6_9zqM\nfunc MaxByErr[T any](collection []T, greater func(a, b T) (bool, error)) (T, error) {\n\tvar mAx T\n\n\tif len(collection) == 0 {\n\t\treturn mAx, nil\n\t}\n\n\tmAx = collection[0]\n\n\tfor i := 1; i < len(collection); i++ {\n\t\titem := collection[i]\n\n\t\tisGreater, err := greater(item, mAx)\n\t\tif err != nil {\n\t\t\treturn mAx, err\n\t\t}\n\t\tif isGreater {\n\t\t\tmAx = item\n\t\t}\n\t}\n\n\treturn mAx, nil\n}\n\n// MaxIndexBy search the maximum value of a collection using the given comparison function and the index of the maximum value.\n// If several values of the collection are equal to the greatest value, returns the first such value.\n// Returns (zero value, -1) when the collection is empty.\n//\n// Note: the comparison function is inconsistent with most languages, since we use the opposite of the usual convention.\n// See https://github.com/samber/lo/issues/129\n//\n// Play: https://go.dev/play/p/5yd4W7pe2QJ\nfunc MaxIndexBy[T any](collection []T, greater func(a, b T) bool) (T, int) {\n\tvar (\n\t\tmAx   T\n\t\tindex int\n\t)\n\n\tif len(collection) == 0 {\n\t\treturn mAx, -1\n\t}\n\n\tmAx = collection[0]\n\n\tfor i := 1; i < len(collection); i++ {\n\t\titem := collection[i]\n\n\t\tif greater(item, mAx) {\n\t\t\tmAx = item\n\t\t\tindex = i\n\t\t}\n\t}\n\n\treturn mAx, index\n}\n\n// MaxIndexByErr search the maximum value of a collection using the given comparison function and the index of the maximum value.\n// If several values of the collection are equal to the greatest value, returns the first such value.\n// Returns (zero value, -1, nil) when the collection is empty.\n// If the comparison function returns an error, iteration stops and the error is returned.\n//\n// Note: the comparison function is inconsistent with most languages, since we use the opposite of the usual convention.\n// See https://github.com/samber/lo/issues/129\nfunc MaxIndexByErr[T any](collection []T, greater func(a, b T) (bool, error)) (T, int, error) {\n\tvar (\n\t\tmAx   T\n\t\tindex int\n\t)\n\n\tif len(collection) == 0 {\n\t\treturn mAx, -1, nil\n\t}\n\n\tmAx = collection[0]\n\n\tfor i := 1; i < len(collection); i++ {\n\t\titem := collection[i]\n\n\t\tisGreater, err := greater(item, mAx)\n\t\tif err != nil {\n\t\t\tvar zero T\n\t\t\treturn zero, -1, err\n\t\t}\n\t\tif isGreater {\n\t\t\tmAx = item\n\t\t\tindex = i\n\t\t}\n\t}\n\n\treturn mAx, index, nil\n}\n\n// Latest search the maximum time.Time of a collection.\n// Returns zero value when the collection is empty.\n// Play: https://go.dev/play/p/dBfdf5s8s-Y\nfunc Latest(times ...time.Time) time.Time {\n\tvar mAx time.Time\n\n\tif len(times) == 0 {\n\t\treturn mAx\n\t}\n\n\tmAx = times[0]\n\n\tfor i := 1; i < len(times); i++ {\n\t\titem := times[i]\n\n\t\tif item.After(mAx) {\n\t\t\tmAx = item\n\t\t}\n\t}\n\n\treturn mAx\n}\n\n// LatestBy search the maximum time.Time of a collection using the given iteratee function.\n// Returns zero value when the collection is empty.\n// Play: https://go.dev/play/p/p1HA8XumaMU\nfunc LatestBy[T any](collection []T, iteratee func(item T) time.Time) T {\n\tvar latest T\n\n\tif len(collection) == 0 {\n\t\treturn latest\n\t}\n\n\tlatest = collection[0]\n\tlatestTime := iteratee(collection[0])\n\n\tfor i := 1; i < len(collection); i++ {\n\t\titemTime := iteratee(collection[i])\n\n\t\tif itemTime.After(latestTime) {\n\t\t\tlatest = collection[i]\n\t\t\tlatestTime = itemTime\n\t\t}\n\t}\n\n\treturn latest\n}\n\n// LatestByErr search the maximum time.Time of a collection using the given iteratee function.\n// Returns zero value and nil error when the collection is empty.\n// If the iteratee returns an error, iteration stops and the error is returned.\n// Play: https://go.dev/play/p/WpBUptwnxuG\nfunc LatestByErr[T any](collection []T, iteratee func(item T) (time.Time, error)) (T, error) {\n\tvar latest T\n\n\tif len(collection) == 0 {\n\t\treturn latest, nil\n\t}\n\n\tlatestTime, err := iteratee(collection[0])\n\tif err != nil {\n\t\treturn latest, err\n\t}\n\tlatest = collection[0]\n\n\tfor i := 1; i < len(collection); i++ {\n\t\titemTime, err := iteratee(collection[i])\n\t\tif err != nil {\n\t\t\treturn latest, err\n\t\t}\n\n\t\tif itemTime.After(latestTime) {\n\t\t\tlatest = collection[i]\n\t\t\tlatestTime = itemTime\n\t\t}\n\t}\n\n\treturn latest, nil\n}\n\n// First returns the first element of a collection and check for availability of the first element.\n// Play: https://go.dev/play/p/94lu5X6_cbf\nfunc First[T any](collection []T) (T, bool) {\n\tlength := len(collection)\n\n\tif length == 0 {\n\t\tvar t T\n\t\treturn t, false\n\t}\n\n\treturn collection[0], true\n}\n\n// FirstOrEmpty returns the first element of a collection or zero value if empty.\n// Play: https://go.dev/play/p/i200n9wgrDA\nfunc FirstOrEmpty[T any](collection []T) T {\n\ti, _ := First(collection)\n\treturn i\n}\n\n// FirstOr returns the first element of a collection or the fallback value if empty.\n// Play: https://go.dev/play/p/x9CxQyRFXeZ\nfunc FirstOr[T any](collection []T, fallback T) T {\n\ti, ok := First(collection)\n\tif !ok {\n\t\treturn fallback\n\t}\n\n\treturn i\n}\n\n// Last returns the last element of a collection or error if empty.\n// Play: https://go.dev/play/p/ul45Z0y2EFO\nfunc Last[T any](collection []T) (T, bool) {\n\tlength := len(collection)\n\n\tif length == 0 {\n\t\tvar t T\n\t\treturn t, false\n\t}\n\n\treturn collection[length-1], true\n}\n\n// LastOrEmpty returns the last element of a collection or zero value if empty.\n// Play: https://go.dev/play/p/ul45Z0y2EFO\nfunc LastOrEmpty[T any](collection []T) T {\n\ti, _ := Last(collection)\n\treturn i\n}\n\n// LastOr returns the last element of a collection or the fallback value if empty.\n// Play: https://go.dev/play/p/ul45Z0y2EFO\nfunc LastOr[T any](collection []T, fallback T) T {\n\ti, ok := Last(collection)\n\tif !ok {\n\t\treturn fallback\n\t}\n\n\treturn i\n}\n\n// Nth returns the element at index `nth` of collection. If `nth` is negative, the nth element\n// from the end is returned. An error is returned when nth is out of slice bounds.\n// Play: https://go.dev/play/p/mNFI9-kIZZ5\nfunc Nth[T any, N constraints.Integer](collection []T, nth N) (T, error) {\n\tvalue, ok := sliceNth(collection, nth)\n\n\treturn value, Validate(ok, \"nth: %d out of slice bounds\", nth)\n}\n\nfunc sliceNth[T any, N constraints.Integer](collection []T, nth N) (T, bool) {\n\tn := int(nth)\n\tl := len(collection)\n\tif n >= l || -n > l {\n\t\treturn Empty[T](), false\n\t}\n\n\tif n >= 0 {\n\t\treturn collection[n], true\n\t}\n\treturn collection[l+n], true\n}\n\n// NthOr returns the element at index `nth` of collection.\n// If `nth` is negative, it returns the nth element from the end.\n// If `nth` is out of slice bounds, it returns the fallback value instead of an error.\n// Play: https://go.dev/play/p/njKcNhBBVsF\nfunc NthOr[T any, N constraints.Integer](collection []T, nth N, fallback T) T {\n\tvalue, ok := sliceNth(collection, nth)\n\tif !ok {\n\t\treturn fallback\n\t}\n\treturn value\n}\n\n// NthOrEmpty returns the element at index `nth` of collection.\n// If `nth` is negative, it returns the nth element from the end.\n// If `nth` is out of slice bounds, it returns the zero value (empty value) for that type.\n// Play: https://go.dev/play/p/sHoh88KWt6B\nfunc NthOrEmpty[T any, N constraints.Integer](collection []T, nth N) T {\n\tvalue, _ := sliceNth(collection, nth)\n\treturn value\n}\n\n// randomIntGenerator is a function that should return a random integer in the range [0, n)\n// where n is the argument passed to the randomIntGenerator.\ntype randomIntGenerator func(n int) int\n\n// Sample returns a random item from collection.\n// Play: https://go.dev/play/p/vCcSJbh5s6l\nfunc Sample[T any](collection []T) T {\n\treturn SampleBy(collection, xrand.IntN)\n}\n\n// SampleBy returns a random item from collection, using randomIntGenerator as the random index generator.\n// Play: https://go.dev/play/p/HDmKmMgq0XN\nfunc SampleBy[T any](collection []T, randomIntGenerator randomIntGenerator) T {\n\tsize := len(collection)\n\tif size == 0 {\n\t\treturn Empty[T]()\n\t}\n\treturn collection[randomIntGenerator(size)]\n}\n\n// Samples returns N random unique items from collection.\n// Play: https://go.dev/play/p/QYRD8aufD0C\nfunc Samples[T any, Slice ~[]T](collection Slice, count int) Slice {\n\treturn SamplesBy(collection, count, xrand.IntN)\n}\n\n// SamplesBy returns N random unique items from collection, using randomIntGenerator as the random index generator.\n// Play: https://go.dev/play/p/Dy9bGDhD_Gw\nfunc SamplesBy[T any, Slice ~[]T](collection Slice, count int, randomIntGenerator randomIntGenerator) Slice {\n\tif count <= 0 {\n\t\treturn Slice{}\n\t}\n\n\tsize := len(collection)\n\n\tif size < count {\n\t\tcount = size\n\t}\n\n\tindexes := Range(size)\n\tresults := make(Slice, count)\n\n\tfor i := range results {\n\t\tn := len(indexes)\n\n\t\tindex := randomIntGenerator(n)\n\t\tresults[i] = collection[indexes[index]]\n\n\t\t// Removes index.\n\t\t// It is faster to swap with last element and remove it.\n\t\tindexes[index] = indexes[n-1]\n\t\tindexes = indexes[:n-1]\n\t}\n\n\treturn results\n}\n"
  },
  {
    "path": "find_test.go",
    "content": "package lo\n\nimport (\n\t\"errors\"\n\t\"math/rand\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestIndexOf(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := IndexOf([]int{0, 1, 2, 1, 2, 3}, 2)\n\tresult2 := IndexOf([]int{0, 1, 2, 1, 2, 3}, 6)\n\n\tis.Equal(2, result1)\n\tis.Equal(-1, result2)\n}\n\nfunc TestLastIndexOf(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := LastIndexOf([]int{0, 1, 2, 1, 2, 3}, 2)\n\tresult2 := LastIndexOf([]int{0, 1, 2, 1, 2, 3}, 6)\n\n\tis.Equal(4, result1)\n\tis.Equal(-1, result2)\n}\n\nfunc TestHasPrefix(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tis.True(HasPrefix([]int{1, 2, 3, 4}, []int{1, 2}))\n\tis.False(HasPrefix([]int{1, 2, 3, 4}, []int{42}))\n\tis.True(HasPrefix([]int{1, 2, 3, 4}, nil))\n}\n\nfunc TestHasSuffix(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tis.True(HasSuffix([]int{1, 2, 3, 4}, []int{3, 4}))\n\tis.False(HasSuffix([]int{1, 2, 3, 4}, []int{42}))\n\tis.True(HasSuffix([]int{1, 2, 3, 4}, nil))\n}\n\nfunc TestFind(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tindex := 0\n\tresult1, ok1 := Find([]string{\"a\", \"b\", \"c\", \"d\"}, func(item string) bool {\n\t\tis.Equal([]string{\"a\", \"b\", \"c\", \"d\"}[index], item)\n\t\tindex++\n\t\treturn item == \"b\"\n\t})\n\n\tresult2, ok2 := Find([]string{\"foobar\"}, func(item string) bool {\n\t\tis.Equal(\"foobar\", item)\n\t\treturn item == \"b\"\n\t})\n\n\tis.True(ok1)\n\tis.Equal(\"b\", result1)\n\tis.False(ok2)\n\tis.Empty(result2)\n}\n\nfunc TestFindErr(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\ttestErr := assert.AnError\n\n\t// Test normal operation (no error) - table driven\n\ttests := []struct {\n\t\tname     string\n\t\tinput    []string\n\t\texpected string\n\t}{\n\t\t{\n\t\t\tname:     \"finds matching element\",\n\t\t\tinput:    []string{\"a\", \"b\", \"c\", \"d\"},\n\t\t\texpected: \"b\",\n\t\t},\n\t\t{\n\t\t\tname:     \"element not found\",\n\t\t\tinput:    []string{\"foobar\"},\n\t\t\texpected: \"\",\n\t\t},\n\t\t{\n\t\t\tname:     \"empty collection\",\n\t\t\tinput:    []string{},\n\t\t\texpected: \"\",\n\t\t},\n\t\t{\n\t\t\tname:     \"single element found\",\n\t\t\tinput:    []string{\"b\"},\n\t\t\texpected: \"b\",\n\t\t},\n\t\t{\n\t\t\tname:     \"single element not found\",\n\t\t\tinput:    []string{\"a\"},\n\t\t\texpected: \"\",\n\t\t},\n\t\t{\n\t\t\tname:     \"finds first match\",\n\t\t\tinput:    []string{\"a\", \"b\", \"c\", \"b\"},\n\t\t\texpected: \"b\", // first \"b\"\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\ttt := tt\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\n\t\t\tresult, err := FindErr(tt.input, func(item string) (bool, error) {\n\t\t\t\treturn item == \"b\", nil\n\t\t\t})\n\t\t\tis.NoError(err)\n\t\t\tis.Equal(tt.expected, result)\n\t\t})\n\t}\n\n\t// Test error cases - table driven with callback count verification\n\terrorTests := []struct {\n\t\tname          string\n\t\tinput         []string\n\t\terrorAt       string\n\t\texpectedCalls int\n\t}{\n\t\t{\n\t\t\tname:          \"error at first element\",\n\t\t\tinput:         []string{\"b\", \"c\", \"d\"},\n\t\t\terrorAt:       \"b\",\n\t\t\texpectedCalls: 1,\n\t\t},\n\t\t{\n\t\t\tname:          \"error at second element\",\n\t\t\tinput:         []string{\"a\", \"b\", \"c\"},\n\t\t\terrorAt:       \"b\",\n\t\t\texpectedCalls: 2,\n\t\t},\n\t\t{\n\t\t\tname:          \"error at third element\",\n\t\t\tinput:         []string{\"a\", \"c\", \"b\"},\n\t\t\terrorAt:       \"b\",\n\t\t\texpectedCalls: 3,\n\t\t},\n\t}\n\n\tfor _, tt := range errorTests {\n\t\ttt := tt\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\n\t\t\tcallbackCount := 0\n\t\t\tresult, err := FindErr(tt.input, func(item string) (bool, error) {\n\t\t\t\tcallbackCount++\n\t\t\t\tif item == tt.errorAt {\n\t\t\t\t\treturn false, testErr\n\t\t\t\t}\n\t\t\t\treturn item == \"b\", nil\n\t\t\t})\n\t\t\tis.ErrorIs(err, testErr)\n\t\t\tis.Equal(tt.expectedCalls, callbackCount, \"callback count mismatch - iteration didn't stop early\")\n\t\t\tis.Empty(result, \"zero value should be returned on error\")\n\t\t})\n\t}\n}\n\nfunc TestFindIndexOf(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tindex := 0\n\titem1, index1, ok1 := FindIndexOf([]string{\"a\", \"b\", \"c\", \"d\", \"b\"}, func(item string) bool {\n\t\tis.Equal([]string{\"a\", \"b\", \"c\", \"d\", \"b\"}[index], item)\n\t\tindex++\n\t\treturn item == \"b\"\n\t})\n\titem2, index2, ok2 := FindIndexOf([]string{\"foobar\"}, func(item string) bool {\n\t\tis.Equal(\"foobar\", item)\n\t\treturn item == \"b\"\n\t})\n\n\tis.Equal(\"b\", item1)\n\tis.True(ok1)\n\tis.Equal(1, index1)\n\tis.Empty(item2)\n\tis.False(ok2)\n\tis.Equal(-1, index2)\n}\n\nfunc TestFindLastIndexOf(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tindex := 0\n\titem1, index1, ok1 := FindLastIndexOf([]string{\"a\", \"b\", \"c\", \"d\", \"b\"}, func(item string) bool {\n\t\tis.Equal([]string{\"b\", \"d\", \"c\", \"b\", \"a\"}[index], item)\n\t\tindex++\n\t\treturn item == \"b\"\n\t})\n\titem2, index2, ok2 := FindLastIndexOf([]string{\"foobar\"}, func(item string) bool {\n\t\tis.Equal(\"foobar\", item)\n\t\treturn item == \"b\"\n\t})\n\n\tis.Equal(\"b\", item1)\n\tis.True(ok1)\n\tis.Equal(4, index1)\n\tis.Empty(item2)\n\tis.False(ok2)\n\tis.Equal(-1, index2)\n}\n\nfunc TestFindOrElse(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tindex := 0\n\tresult1 := FindOrElse([]string{\"a\", \"b\", \"c\", \"d\"}, \"x\", func(item string) bool {\n\t\tis.Equal([]string{\"a\", \"b\", \"c\", \"d\"}[index], item)\n\t\tindex++\n\t\treturn item == \"b\"\n\t})\n\tresult2 := FindOrElse([]string{\"foobar\"}, \"x\", func(item string) bool {\n\t\tis.Equal(\"foobar\", item)\n\t\treturn item == \"b\"\n\t})\n\n\tis.Equal(\"b\", result1)\n\tis.Equal(\"x\", result2)\n}\n\nfunc TestFindKey(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1, ok1 := FindKey(map[string]int{\"foo\": 1, \"bar\": 2, \"baz\": 3}, 2)\n\tis.Equal(\"bar\", result1)\n\tis.True(ok1)\n\n\tresult2, ok2 := FindKey(map[string]int{\"foo\": 1, \"bar\": 2, \"baz\": 3}, 42)\n\tis.Empty(result2)\n\tis.False(ok2)\n\n\ttype test struct {\n\t\tfoobar string\n\t}\n\n\tresult3, ok3 := FindKey(map[string]test{\"foo\": {\"foo\"}, \"bar\": {\"bar\"}, \"baz\": {\"baz\"}}, test{\"foo\"})\n\tis.Equal(\"foo\", result3)\n\tis.True(ok3)\n\n\tresult4, ok4 := FindKey(map[string]test{\"foo\": {\"foo\"}, \"bar\": {\"bar\"}, \"baz\": {\"baz\"}}, test{\"hello world\"})\n\tis.Empty(result4)\n\tis.False(ok4)\n}\n\nfunc TestFindKeyBy(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1, ok1 := FindKeyBy(map[string]int{\"foo\": 1, \"bar\": 2, \"baz\": 3}, func(k string, v int) bool {\n\t\treturn k == \"foo\"\n\t})\n\tis.Equal(\"foo\", result1)\n\tis.True(ok1)\n\n\tresult2, ok2 := FindKeyBy(map[string]int{\"foo\": 1, \"bar\": 2, \"baz\": 3}, func(k string, v int) bool {\n\t\treturn false\n\t})\n\tis.Empty(result2)\n\tis.False(ok2)\n}\n\nfunc TestFindUniques(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := FindUniques([]int{1, 2, 3})\n\tis.Equal([]int{1, 2, 3}, result1)\n\n\tresult2 := FindUniques([]int{1, 2, 2, 3, 1, 2})\n\tis.Equal([]int{3}, result2)\n\n\tresult3 := FindUniques([]int{1, 2, 2, 1})\n\tis.Empty(result3)\n\n\tresult4 := FindUniques([]int{})\n\tis.Empty(result4)\n\n\ttype myStrings []string\n\tallStrings := myStrings{\"\", \"foo\", \"bar\"}\n\tnonempty := FindUniques(allStrings)\n\tis.IsType(nonempty, allStrings, \"type preserved\")\n}\n\nfunc TestFindUniquesBy(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := FindUniquesBy([]int{0, 1, 2}, func(i int) int {\n\t\treturn i % 3\n\t})\n\tis.Equal([]int{0, 1, 2}, result1)\n\n\tresult2 := FindUniquesBy([]int{0, 1, 2, 3, 4}, func(i int) int {\n\t\treturn i % 3\n\t})\n\tis.Equal([]int{2}, result2)\n\n\tresult3 := FindUniquesBy([]int{0, 1, 2, 3, 4, 5}, func(i int) int {\n\t\treturn i % 3\n\t})\n\tis.Empty(result3)\n\n\tresult4 := FindUniquesBy([]int{}, func(i int) int {\n\t\treturn i % 3\n\t})\n\tis.Empty(result4)\n\n\ttype myStrings []string\n\tallStrings := myStrings{\"\", \"foo\", \"bar\"}\n\tnonempty := FindUniquesBy(allStrings, func(i string) string {\n\t\treturn i\n\t})\n\tis.IsType(nonempty, allStrings, \"type preserved\")\n}\n\nfunc TestFindDuplicates(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := FindDuplicates([]int{1, 2, 2, 1, 2, 3})\n\tis.Equal([]int{1, 2}, result1)\n\n\tresult2 := FindDuplicates([]int{1, 2, 3})\n\tis.Empty(result2)\n\n\tresult3 := FindDuplicates([]int{})\n\tis.Empty(result3)\n\n\ttype myStrings []string\n\tallStrings := myStrings{\"\", \"foo\", \"bar\"}\n\tnonempty := FindDuplicates(allStrings)\n\tis.IsType(nonempty, allStrings, \"type preserved\")\n}\n\nfunc TestFindDuplicatesBy(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := FindDuplicatesBy([]int{3, 4, 5, 6, 7}, func(i int) int {\n\t\treturn i % 3\n\t})\n\tis.Equal([]int{3, 4}, result1)\n\n\tresult2 := FindDuplicatesBy([]int{0, 1, 2, 3, 4}, func(i int) int {\n\t\treturn i % 5\n\t})\n\tis.Empty(result2)\n\n\tresult3 := FindDuplicatesBy([]int{}, func(i int) int {\n\t\treturn i % 3\n\t})\n\tis.Empty(result3)\n\n\ttype myStrings []string\n\tallStrings := myStrings{\"\", \"foo\", \"bar\"}\n\tnonempty := FindDuplicatesBy(allStrings, func(i string) string {\n\t\treturn i\n\t})\n\tis.IsType(nonempty, allStrings, \"type preserved\")\n}\n\nfunc TestFindDuplicatesByErr(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\t// Table-driven tests for normal operation\n\ttests := []struct {\n\t\tname     string\n\t\tinput    []int\n\t\texpected []int\n\t}{\n\t\t{\n\t\t\tname:     \"finds duplicates by key\",\n\t\t\tinput:    []int{3, 4, 5, 6, 7},\n\t\t\texpected: []int{3, 4},\n\t\t},\n\t\t{\n\t\t\tname:     \"no duplicates\",\n\t\t\tinput:    []int{0, 1, 2, 3, 4},\n\t\t\texpected: []int{0, 1},\n\t\t},\n\t\t{\n\t\t\tname:     \"empty collection\",\n\t\t\tinput:    []int{},\n\t\t\texpected: []int{},\n\t\t},\n\t\t{\n\t\t\tname:     \"all duplicates\",\n\t\t\tinput:    []int{0, 3, 6, 9},\n\t\t\texpected: []int{0},\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\ttt := tt\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\n\t\t\tresult, err := FindDuplicatesByErr(tt.input, func(i int) (int, error) {\n\t\t\t\treturn i % 3, nil\n\t\t\t})\n\t\t\tis.NoError(err)\n\t\t\tis.Equal(tt.expected, result)\n\t\t})\n\t}\n\n\t// Table-driven tests with callback count verification for early return\n\ttestErr := errors.New(\"test error\")\n\n\terrorTests := []struct {\n\t\tname          string\n\t\tinput         []int\n\t\terrorAt       int\n\t\texpectedCalls int\n\t}{\n\t\t{\n\t\t\tname:          \"error in first pass at element 0\",\n\t\t\tinput:         []int{3, 4, 5},\n\t\t\terrorAt:       0,\n\t\t\texpectedCalls: 1,\n\t\t},\n\t\t{\n\t\t\tname:          \"error in first pass at element 2\",\n\t\t\tinput:         []int{3, 4, 5},\n\t\t\terrorAt:       2,\n\t\t\texpectedCalls: 3,\n\t\t},\n\t\t{\n\t\t\tname:          \"error in second pass at first duplicate\",\n\t\t\tinput:         []int{3, 4, 5, 6},\n\t\t\terrorAt:       3,\n\t\t\texpectedCalls: 4, // First pass completes (4 items), error at first item of second pass\n\t\t},\n\t}\n\n\tfor _, tt := range errorTests {\n\t\ttt := tt\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\n\t\t\tcallbackCount := 0\n\t\t\tresult, err := FindDuplicatesByErr(tt.input, func(i int) (int, error) {\n\t\t\t\tcallbackCount++\n\t\t\t\tif i == tt.input[tt.errorAt] {\n\t\t\t\t\treturn 0, testErr\n\t\t\t\t}\n\t\t\t\treturn i % 3, nil\n\t\t\t})\n\t\t\tis.ErrorIs(err, testErr)\n\t\t\tis.Equal(tt.expectedCalls, callbackCount, \"callback count mismatch - iteration didn't stop early\")\n\t\t\tis.Nil(result, \"nil should be returned on error\")\n\t\t})\n\t}\n\n\t// Test type preservation\n\ttype myStrings []string\n\tallStrings := myStrings{\"a\", \"b\", \"a\", \"c\", \"b\"}\n\tresult, err := FindDuplicatesByErr(allStrings, func(s string) (string, error) {\n\t\treturn s, nil\n\t})\n\tis.NoError(err)\n\tis.IsType(result, allStrings, \"type preserved\")\n}\n\nfunc TestMin(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := Min([]int{1, 2, 3})\n\tresult2 := Min([]int{3, 2, 1})\n\tresult3 := Min([]time.Duration{time.Second, time.Minute, time.Hour})\n\tresult4 := Min([]int{})\n\n\tis.Equal(1, result1)\n\tis.Equal(1, result2)\n\tis.Equal(time.Second, result3)\n\tis.Zero(result4)\n}\n\nfunc TestMinIndex(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1, index1 := MinIndex([]int{1, 2, 3})\n\tresult2, index2 := MinIndex([]int{3, 2, 1})\n\tresult3, index3 := MinIndex([]time.Duration{time.Second, time.Minute, time.Hour})\n\tresult4, index4 := MinIndex([]int{})\n\n\tis.Equal(1, result1)\n\tis.Zero(index1)\n\n\tis.Equal(1, result2)\n\tis.Equal(2, index2)\n\n\tis.Equal(time.Second, result3)\n\tis.Zero(index3)\n\n\tis.Zero(result4)\n\tis.Equal(-1, index4)\n}\n\nfunc TestMinBy(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := MinBy([]string{\"s1\", \"string2\", \"s3\"}, func(item, mIn string) bool {\n\t\treturn len(item) < len(mIn)\n\t})\n\tresult2 := MinBy([]string{\"string1\", \"string2\", \"s3\"}, func(item, mIn string) bool {\n\t\treturn len(item) < len(mIn)\n\t})\n\tresult3 := MinBy([]string{}, func(item, mIn string) bool {\n\t\treturn len(item) < len(mIn)\n\t})\n\n\tis.Equal(\"s1\", result1)\n\tis.Equal(\"s3\", result2)\n\tis.Empty(result3)\n}\n\nfunc TestMinByErr(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\ttestErr := assert.AnError\n\n\t// Test normal operation (no error) - table driven\n\ttests := []struct {\n\t\tname     string\n\t\tinput    []string\n\t\texpected string\n\t}{\n\t\t{\n\t\t\tname:     \"finds min by length - first match\",\n\t\t\tinput:    []string{\"s1\", \"string2\", \"s3\"},\n\t\t\texpected: \"s1\",\n\t\t},\n\t\t{\n\t\t\tname:     \"finds min by length - third match\",\n\t\t\tinput:    []string{\"string1\", \"string2\", \"s3\"},\n\t\t\texpected: \"s3\",\n\t\t},\n\t\t{\n\t\t\tname:     \"empty collection\",\n\t\t\tinput:    []string{},\n\t\t\texpected: \"\",\n\t\t},\n\t\t{\n\t\t\tname:     \"single element\",\n\t\t\tinput:    []string{\"single\"},\n\t\t\texpected: \"single\",\n\t\t},\n\t\t{\n\t\t\tname:     \"all equal length\",\n\t\t\tinput:    []string{\"a\", \"b\", \"c\"},\n\t\t\texpected: \"a\", // first minimal value\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\ttt := tt\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\n\t\t\tresult, err := MinByErr(tt.input, func(item, mIn string) (bool, error) {\n\t\t\t\treturn len(item) < len(mIn), nil\n\t\t\t})\n\t\t\tis.NoError(err)\n\t\t\tis.Equal(tt.expected, result)\n\t\t})\n\t}\n\n\t// Test error cases - table driven\n\terrorTests := []struct {\n\t\tname          string\n\t\tinput         []string\n\t\terrorAt       string\n\t\texpectedCalls int\n\t}{\n\t\t{\n\t\t\tname:          \"error at second comparison\",\n\t\t\tinput:         []string{\"a\", \"bb\", \"ccc\"},\n\t\t\terrorAt:       \"bb\",\n\t\t\texpectedCalls: 1, // Only first comparison (initial element vs second)\n\t\t},\n\t\t{\n\t\t\tname:          \"error at third comparison\",\n\t\t\tinput:         []string{\"a\", \"bb\", \"ccc\"},\n\t\t\terrorAt:       \"ccc\",\n\t\t\texpectedCalls: 2, // First two comparisons\n\t\t},\n\t}\n\n\tfor _, tt := range errorTests {\n\t\ttt := tt\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\n\t\t\tcallbackCount := 0\n\t\t\tresult, err := MinByErr(tt.input, func(item, mIn string) (bool, error) {\n\t\t\t\tcallbackCount++\n\t\t\t\tif item == tt.errorAt {\n\t\t\t\t\treturn false, testErr\n\t\t\t\t}\n\t\t\t\treturn len(item) < len(mIn), nil\n\t\t\t})\n\t\t\tis.ErrorIs(err, testErr)\n\t\t\tis.Equal(tt.expectedCalls, callbackCount)\n\t\t\tis.Empty(result) // Zero value on error\n\t\t})\n\t}\n}\n\nfunc TestMinIndexBy(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1, index1 := MinIndexBy([]string{\"s1\", \"string2\", \"s3\"}, func(item, mIn string) bool {\n\t\treturn len(item) < len(mIn)\n\t})\n\tresult2, index2 := MinIndexBy([]string{\"string1\", \"string2\", \"s3\"}, func(item, mIn string) bool {\n\t\treturn len(item) < len(mIn)\n\t})\n\tresult3, index3 := MinIndexBy([]string{}, func(item, mIn string) bool {\n\t\treturn len(item) < len(mIn)\n\t})\n\n\tis.Equal(\"s1\", result1)\n\tis.Zero(index1)\n\n\tis.Equal(\"s3\", result2)\n\tis.Equal(2, index2)\n\n\tis.Empty(result3)\n\tis.Equal(-1, index3)\n}\n\nfunc TestMinIndexByErr(t *testing.T) {\n\tt.Parallel()\n\n\ttests := []struct {\n\t\tname                  string\n\t\tinput                 []string\n\t\tless                  func(a, b string) (bool, error)\n\t\twantValue             string\n\t\twantIndex             int\n\t\twantErr               bool\n\t\terrMsg                string\n\t\texpectedCallbackCount int\n\t}{\n\t\t{\n\t\t\tname:                  \"empty slice\",\n\t\t\tinput:                 []string{},\n\t\t\tless:                  func(a, b string) (bool, error) { return len(a) < len(b), nil },\n\t\t\twantValue:             \"\",\n\t\t\twantIndex:             -1,\n\t\t\twantErr:               false,\n\t\t\texpectedCallbackCount: 0,\n\t\t},\n\t\t{\n\t\t\tname:                  \"success case\",\n\t\t\tinput:                 []string{\"s1\", \"string2\", \"s3\"},\n\t\t\tless:                  func(a, b string) (bool, error) { return len(a) < len(b), nil },\n\t\t\twantValue:             \"s1\",\n\t\t\twantIndex:             0,\n\t\t\twantErr:               false,\n\t\t\texpectedCallbackCount: 2,\n\t\t},\n\t\t{\n\t\t\tname:  \"error on first comparison\",\n\t\t\tinput: []string{\"s1\", \"string2\", \"s3\"},\n\t\t\tless: func(a, b string) (bool, error) {\n\t\t\t\treturn false, errors.New(\"comparison error\")\n\t\t\t},\n\t\t\twantValue:             \"\",\n\t\t\twantIndex:             -1,\n\t\t\twantErr:               true,\n\t\t\terrMsg:                \"comparison error\",\n\t\t\texpectedCallbackCount: 1,\n\t\t},\n\t\t{\n\t\t\tname:  \"error on second comparison\",\n\t\t\tinput: []string{\"a\", \"bb\", \"ccc\", \"error\", \"e\"},\n\t\t\tless: func(a, b string) (bool, error) {\n\t\t\t\tif a == \"error\" || b == \"error\" {\n\t\t\t\t\treturn false, errors.New(\"error value encountered\")\n\t\t\t\t}\n\t\t\t\treturn len(a) < len(b), nil\n\t\t\t},\n\t\t\twantValue:             \"\",\n\t\t\twantIndex:             -1,\n\t\t\twantErr:               true,\n\t\t\terrMsg:                \"error value encountered\",\n\t\t\texpectedCallbackCount: 3,\n\t\t},\n\t\t{\n\t\t\tname:                  \"single element\",\n\t\t\tinput:                 []string{\"single\"},\n\t\t\tless:                  func(a, b string) (bool, error) { return len(a) < len(b), nil },\n\t\t\twantValue:             \"single\",\n\t\t\twantIndex:             0,\n\t\t\twantErr:               false,\n\t\t\texpectedCallbackCount: 0,\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\ttt := tt\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\n\t\t\tcallbackCount := 0\n\t\t\twrappedLess := func(a, b string) (bool, error) {\n\t\t\t\tcallbackCount++\n\t\t\t\treturn tt.less(a, b)\n\t\t\t}\n\n\t\t\tvalue, index, err := MinIndexByErr(tt.input, wrappedLess)\n\n\t\t\tif tt.wantErr {\n\t\t\t\tassert.Error(t, err)\n\t\t\t\tif tt.errMsg != \"\" {\n\t\t\t\t\tassert.Equal(t, tt.errMsg, err.Error())\n\t\t\t\t}\n\t\t\t\tassert.Empty(t, value)\n\t\t\t\tassert.Equal(t, -1, index)\n\t\t\t} else {\n\t\t\t\tassert.NoError(t, err)\n\t\t\t\tassert.Equal(t, tt.wantValue, value)\n\t\t\t\tassert.Equal(t, tt.wantIndex, index)\n\t\t\t}\n\n\t\t\tassert.Equal(t, tt.expectedCallbackCount, callbackCount, \"callback count mismatch\")\n\t\t})\n\t}\n}\n\nfunc TestEarliest(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\ta := time.Now()\n\tb := a.Add(time.Hour)\n\tresult1 := Earliest(a, b)\n\tresult2 := Earliest()\n\n\tis.Equal(a, result1)\n\tis.Zero(result2)\n}\n\nfunc TestEarliestBy(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\ttype foo struct {\n\t\tbar time.Time\n\t}\n\n\tt1 := time.Now()\n\tt2 := t1.Add(time.Hour)\n\tt3 := t1.Add(-time.Hour)\n\tresult1 := EarliestBy([]foo{{t1}, {t2}, {t3}}, func(i foo) time.Time {\n\t\treturn i.bar\n\t})\n\tresult2 := EarliestBy([]foo{{t1}}, func(i foo) time.Time {\n\t\treturn i.bar\n\t})\n\tresult3 := EarliestBy([]foo{}, func(i foo) time.Time {\n\t\treturn i.bar\n\t})\n\n\tis.Equal(foo{t3}, result1)\n\tis.Equal(foo{t1}, result2)\n\tis.Zero(result3)\n}\n\nfunc TestEarliestByErr(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\ttestErr := assert.AnError\n\n\ttype foo struct {\n\t\tbar time.Time\n\t}\n\n\tt1 := time.Now()\n\tt2 := t1.Add(time.Hour)\n\tt3 := t1.Add(-time.Hour)\n\n\t// Test normal operation (no error) - table driven\n\ttests := []struct {\n\t\tname     string\n\t\tinput    []foo\n\t\texpected foo\n\t}{\n\t\t{\n\t\t\tname:     \"finds earliest time\",\n\t\t\tinput:    []foo{{t1}, {t2}, {t3}},\n\t\t\texpected: foo{t3},\n\t\t},\n\t\t{\n\t\t\tname:     \"single element\",\n\t\t\tinput:    []foo{{t1}},\n\t\t\texpected: foo{t1},\n\t\t},\n\t\t{\n\t\t\tname:     \"empty collection\",\n\t\t\tinput:    []foo{},\n\t\t\texpected: foo{},\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\ttt := tt\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\n\t\t\tresult, err := EarliestByErr(tt.input, func(i foo) (time.Time, error) {\n\t\t\t\treturn i.bar, nil\n\t\t\t})\n\t\t\tis.NoError(err)\n\t\t\tis.Equal(tt.expected, result)\n\t\t})\n\t}\n\n\t// Test error cases - table driven\n\terrorTests := []struct {\n\t\tname          string\n\t\tinput         []foo\n\t\terrorAt       int\n\t\texpectedCalls int\n\t}{\n\t\t{\n\t\t\tname:          \"error at first element\",\n\t\t\tinput:         []foo{{t1}, {t2}, {t3}},\n\t\t\terrorAt:       0,\n\t\t\texpectedCalls: 1, // Only first callback\n\t\t},\n\t\t{\n\t\t\tname:          \"error at second element\",\n\t\t\tinput:         []foo{{t1}, {t2}, {t3}},\n\t\t\terrorAt:       1,\n\t\t\texpectedCalls: 2, // First two callbacks\n\t\t},\n\t\t{\n\t\t\tname:          \"error at third element\",\n\t\t\tinput:         []foo{{t1}, {t2}, {t3}},\n\t\t\terrorAt:       2,\n\t\t\texpectedCalls: 3, // All three callbacks\n\t\t},\n\t}\n\n\tfor _, tt := range errorTests {\n\t\ttt := tt\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\n\t\t\tcallbackCount := 0\n\t\t\t_, err := EarliestByErr(tt.input, func(i foo) (time.Time, error) {\n\t\t\t\tcallbackCount++\n\t\t\t\tif len(tt.input) > 0 && i == tt.input[tt.errorAt] {\n\t\t\t\t\treturn time.Time{}, testErr\n\t\t\t\t}\n\t\t\t\treturn i.bar, nil\n\t\t\t})\n\t\t\tis.ErrorIs(err, testErr)\n\t\t\tis.Equal(tt.expectedCalls, callbackCount)\n\t\t})\n\t}\n}\n\nfunc TestMax(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := Max([]int{1, 2, 3})\n\tresult2 := Max([]int{3, 2, 1})\n\tresult3 := Max([]time.Duration{time.Second, time.Minute, time.Hour})\n\tresult4 := Max([]int{})\n\n\tis.Equal(3, result1)\n\tis.Equal(3, result2)\n\tis.Equal(time.Hour, result3)\n\tis.Zero(result4)\n}\n\nfunc TestMaxIndex(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1, index1 := MaxIndex([]int{1, 2, 3})\n\tresult2, index2 := MaxIndex([]int{3, 2, 1})\n\tresult3, index3 := MaxIndex([]time.Duration{time.Second, time.Minute, time.Hour})\n\tresult4, index4 := MaxIndex([]int{})\n\n\tis.Equal(3, result1)\n\tis.Equal(2, index1)\n\n\tis.Equal(3, result2)\n\tis.Zero(index2)\n\n\tis.Equal(time.Hour, result3)\n\tis.Equal(2, index3)\n\n\tis.Zero(result4)\n\tis.Equal(-1, index4)\n}\n\nfunc TestMaxBy(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := MaxBy([]string{\"s1\", \"string2\", \"s3\"}, func(item, mAx string) bool {\n\t\treturn len(item) > len(mAx)\n\t})\n\tresult2 := MaxBy([]string{\"string1\", \"string2\", \"s3\"}, func(item, mAx string) bool {\n\t\treturn len(item) > len(mAx)\n\t})\n\tresult3 := MaxBy([]string{}, func(item, mAx string) bool {\n\t\treturn len(item) > len(mAx)\n\t})\n\n\tis.Equal(\"string2\", result1)\n\tis.Equal(\"string1\", result2)\n\tis.Empty(result3)\n}\n\nfunc TestMaxByErr(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\ttestErr := assert.AnError\n\n\t// Test normal operation (no error) - table driven\n\ttests := []struct {\n\t\tname     string\n\t\tinput    []string\n\t\texpected string\n\t}{\n\t\t{\n\t\t\tname:     \"finds max by length - second match\",\n\t\t\tinput:    []string{\"s1\", \"string2\", \"s3\"},\n\t\t\texpected: \"string2\",\n\t\t},\n\t\t{\n\t\t\tname:     \"finds max by length - first match\",\n\t\t\tinput:    []string{\"string1\", \"string2\", \"s3\"},\n\t\t\texpected: \"string1\",\n\t\t},\n\t\t{\n\t\t\tname:     \"empty collection\",\n\t\t\tinput:    []string{},\n\t\t\texpected: \"\",\n\t\t},\n\t\t{\n\t\t\tname:     \"single element\",\n\t\t\tinput:    []string{\"single\"},\n\t\t\texpected: \"single\",\n\t\t},\n\t\t{\n\t\t\tname:     \"all equal length\",\n\t\t\tinput:    []string{\"a\", \"b\", \"c\"},\n\t\t\texpected: \"a\", // first maximal value\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\ttt := tt\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\n\t\t\tresult, err := MaxByErr(tt.input, func(item, mAx string) (bool, error) {\n\t\t\t\treturn len(item) > len(mAx), nil\n\t\t\t})\n\t\t\tis.NoError(err)\n\t\t\tis.Equal(tt.expected, result)\n\t\t})\n\t}\n\n\t// Test error cases - table driven\n\terrorTests := []struct {\n\t\tname          string\n\t\tinput         []string\n\t\terrorAt       string\n\t\texpectedCalls int\n\t}{\n\t\t{\n\t\t\tname:          \"error at second comparison\",\n\t\t\tinput:         []string{\"a\", \"bb\", \"ccc\"},\n\t\t\terrorAt:       \"bb\",\n\t\t\texpectedCalls: 1, // Only first comparison (initial element vs second)\n\t\t},\n\t\t{\n\t\t\tname:          \"error at third comparison\",\n\t\t\tinput:         []string{\"a\", \"bb\", \"ccc\"},\n\t\t\terrorAt:       \"ccc\",\n\t\t\texpectedCalls: 2, // First two comparisons\n\t\t},\n\t}\n\n\tfor _, tt := range errorTests {\n\t\ttt := tt\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\n\t\t\tcallbackCount := 0\n\t\t\tresult, err := MaxByErr(tt.input, func(item, mAx string) (bool, error) {\n\t\t\t\tcallbackCount++\n\t\t\t\tif item == tt.errorAt {\n\t\t\t\t\treturn false, testErr\n\t\t\t\t}\n\t\t\t\treturn len(item) > len(mAx), nil\n\t\t\t})\n\t\t\tis.ErrorIs(err, testErr)\n\t\t\tis.Equal(tt.expectedCalls, callbackCount)\n\t\t\t// Result should be the current max at the time of error\n\t\t\tif tt.expectedCalls == 1 {\n\t\t\t\tis.Equal(\"a\", result) // Still the first element\n\t\t\t} else {\n\t\t\t\tis.Equal(\"bb\", result) // \"bb\" became max after second comparison\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMaxIndexBy(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1, index1 := MaxIndexBy([]string{\"s1\", \"string2\", \"s3\"}, func(item, mAx string) bool {\n\t\treturn len(item) > len(mAx)\n\t})\n\tresult2, index2 := MaxIndexBy([]string{\"string1\", \"string2\", \"s3\"}, func(item, mAx string) bool {\n\t\treturn len(item) > len(mAx)\n\t})\n\tresult3, index3 := MaxIndexBy([]string{}, func(item, mAx string) bool {\n\t\treturn len(item) > len(mAx)\n\t})\n\n\tis.Equal(\"string2\", result1)\n\tis.Equal(1, index1)\n\n\tis.Equal(\"string1\", result2)\n\tis.Zero(index2)\n\n\tis.Empty(result3)\n\tis.Equal(-1, index3)\n}\n\nfunc TestMaxIndexByErr(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\ttestErr := assert.AnError\n\n\t// Test normal operation (no error) - table driven\n\ttests := []struct {\n\t\tname           string\n\t\tinput          []string\n\t\texpectedResult string\n\t\texpectedIndex  int\n\t}{\n\t\t{\n\t\t\tname:           \"finds max by length - second match\",\n\t\t\tinput:          []string{\"s1\", \"string2\", \"s3\"},\n\t\t\texpectedResult: \"string2\",\n\t\t\texpectedIndex:  1,\n\t\t},\n\t\t{\n\t\t\tname:           \"finds max by length - first match\",\n\t\t\tinput:          []string{\"string1\", \"string2\", \"s3\"},\n\t\t\texpectedResult: \"string1\",\n\t\t\texpectedIndex:  0,\n\t\t},\n\t\t{\n\t\t\tname:           \"empty collection\",\n\t\t\tinput:          []string{},\n\t\t\texpectedResult: \"\",\n\t\t\texpectedIndex:  -1,\n\t\t},\n\t\t{\n\t\t\tname:           \"single element\",\n\t\t\tinput:          []string{\"single\"},\n\t\t\texpectedResult: \"single\",\n\t\t\texpectedIndex:  0,\n\t\t},\n\t\t{\n\t\t\tname:           \"all equal length\",\n\t\t\tinput:          []string{\"a\", \"b\", \"c\"},\n\t\t\texpectedResult: \"a\", // first maximal value\n\t\t\texpectedIndex:  0,\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\ttt := tt\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\n\t\t\tresult, index, err := MaxIndexByErr(tt.input, func(item, mAx string) (bool, error) {\n\t\t\t\treturn len(item) > len(mAx), nil\n\t\t\t})\n\t\t\tis.NoError(err)\n\t\t\tis.Equal(tt.expectedResult, result)\n\t\t\tis.Equal(tt.expectedIndex, index)\n\t\t})\n\t}\n\n\t// Test error cases - table driven\n\terrorTests := []struct {\n\t\tname           string\n\t\tinput          []string\n\t\terrorAt        string\n\t\texpectedCalls  int\n\t\texpectedResult string\n\t\texpectedIndex  int\n\t}{\n\t\t{\n\t\t\tname:           \"error at second comparison\",\n\t\t\tinput:          []string{\"a\", \"bb\", \"ccc\"},\n\t\t\terrorAt:        \"bb\",\n\t\t\texpectedCalls:  1, // Only first comparison (initial element vs second)\n\t\t\texpectedResult: \"\",\n\t\t\texpectedIndex:  -1,\n\t\t},\n\t\t{\n\t\t\tname:           \"error at third comparison\",\n\t\t\tinput:          []string{\"a\", \"bb\", \"ccc\"},\n\t\t\terrorAt:        \"ccc\",\n\t\t\texpectedCalls:  2, // First two comparisons\n\t\t\texpectedResult: \"\",\n\t\t\texpectedIndex:  -1,\n\t\t},\n\t}\n\n\tfor _, tt := range errorTests {\n\t\ttt := tt\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\n\t\t\tcallbackCount := 0\n\t\t\tresult, index, err := MaxIndexByErr(tt.input, func(item, mAx string) (bool, error) {\n\t\t\t\tcallbackCount++\n\t\t\t\tif item == tt.errorAt {\n\t\t\t\t\treturn false, testErr\n\t\t\t\t}\n\t\t\t\treturn len(item) > len(mAx), nil\n\t\t\t})\n\t\t\tis.ErrorIs(err, testErr)\n\t\t\tis.Equal(tt.expectedCalls, callbackCount)\n\t\t\tis.Equal(tt.expectedResult, result)\n\t\t\tis.Equal(tt.expectedIndex, index)\n\t\t})\n\t}\n}\n\nfunc TestLatest(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\ta := time.Now()\n\tb := a.Add(time.Hour)\n\tresult1 := Latest(a, b)\n\tresult2 := Latest()\n\n\tis.Equal(b, result1)\n\tis.Zero(result2)\n}\n\nfunc TestLatestBy(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\ttype foo struct {\n\t\tbar time.Time\n\t}\n\n\tt1 := time.Now()\n\tt2 := t1.Add(time.Hour)\n\tt3 := t1.Add(-time.Hour)\n\tresult1 := LatestBy([]foo{{t1}, {t2}, {t3}}, func(i foo) time.Time {\n\t\treturn i.bar\n\t})\n\tresult2 := LatestBy([]foo{{t1}}, func(i foo) time.Time {\n\t\treturn i.bar\n\t})\n\tresult3 := LatestBy([]foo{}, func(i foo) time.Time {\n\t\treturn i.bar\n\t})\n\n\tis.Equal(foo{t2}, result1)\n\tis.Equal(foo{t1}, result2)\n\tis.Zero(result3)\n}\n\nfunc TestLatestByErr(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\ttestErr := assert.AnError\n\n\ttype foo struct {\n\t\tbar time.Time\n\t}\n\n\tt1 := time.Now()\n\tt2 := t1.Add(time.Hour)\n\tt3 := t1.Add(-time.Hour)\n\n\t// Test normal operation (no error) - table driven\n\ttests := []struct {\n\t\tname     string\n\t\tinput    []foo\n\t\texpected foo\n\t}{\n\t\t{\n\t\t\tname:     \"finds latest time\",\n\t\t\tinput:    []foo{{t1}, {t2}, {t3}},\n\t\t\texpected: foo{t2},\n\t\t},\n\t\t{\n\t\t\tname:     \"single element\",\n\t\t\tinput:    []foo{{t1}},\n\t\t\texpected: foo{t1},\n\t\t},\n\t\t{\n\t\t\tname:     \"empty collection\",\n\t\t\tinput:    []foo{},\n\t\t\texpected: foo{},\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\ttt := tt\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\n\t\t\tresult, err := LatestByErr(tt.input, func(i foo) (time.Time, error) {\n\t\t\t\treturn i.bar, nil\n\t\t\t})\n\t\t\tis.NoError(err)\n\t\t\tis.Equal(tt.expected, result)\n\t\t})\n\t}\n\n\t// Test error cases - table driven\n\terrorTests := []struct {\n\t\tname          string\n\t\tinput         []foo\n\t\terrorAt       int\n\t\texpectedCalls int\n\t}{\n\t\t{\n\t\t\tname:          \"error at first element\",\n\t\t\tinput:         []foo{{t1}, {t2}, {t3}},\n\t\t\terrorAt:       0,\n\t\t\texpectedCalls: 1, // Only first callback\n\t\t},\n\t\t{\n\t\t\tname:          \"error at second element\",\n\t\t\tinput:         []foo{{t1}, {t2}, {t3}},\n\t\t\terrorAt:       1,\n\t\t\texpectedCalls: 2, // First two callbacks\n\t\t},\n\t\t{\n\t\t\tname:          \"error at third element\",\n\t\t\tinput:         []foo{{t1}, {t2}, {t3}},\n\t\t\terrorAt:       2,\n\t\t\texpectedCalls: 3, // All three callbacks\n\t\t},\n\t}\n\n\tfor _, tt := range errorTests {\n\t\ttt := tt\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\n\t\t\tcallbackCount := 0\n\t\t\t_, err := LatestByErr(tt.input, func(i foo) (time.Time, error) {\n\t\t\t\tcallbackCount++\n\t\t\t\tif len(tt.input) > 0 && i == tt.input[tt.errorAt] {\n\t\t\t\t\treturn time.Time{}, testErr\n\t\t\t\t}\n\t\t\t\treturn i.bar, nil\n\t\t\t})\n\t\t\tis.ErrorIs(err, testErr)\n\t\t\tis.Equal(tt.expectedCalls, callbackCount)\n\t\t})\n\t}\n}\n\nfunc TestFirst(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1, ok1 := First([]int{1, 2, 3})\n\tresult2, ok2 := First([]int{})\n\n\tis.Equal(1, result1)\n\tis.True(ok1)\n\tis.Zero(result2)\n\tis.False(ok2)\n}\n\nfunc TestFirstOrEmpty(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := FirstOrEmpty([]int{1, 2, 3})\n\tresult2 := FirstOrEmpty([]int{})\n\tresult3 := FirstOrEmpty([]string{})\n\n\tis.Equal(1, result1)\n\tis.Zero(result2)\n\tis.Empty(result3)\n}\n\nfunc TestFirstOr(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := FirstOr([]int{1, 2, 3}, 63)\n\tresult2 := FirstOr([]int{}, 23)\n\tresult3 := FirstOr([]string{}, \"test\")\n\n\tis.Equal(1, result1)\n\tis.Equal(23, result2)\n\tis.Equal(\"test\", result3)\n}\n\nfunc TestLast(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1, ok1 := Last([]int{1, 2, 3})\n\tresult2, ok2 := Last([]int{})\n\n\tis.Equal(3, result1)\n\tis.True(ok1)\n\tis.Zero(result2)\n\tis.False(ok2)\n}\n\nfunc TestLastOrEmpty(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := LastOrEmpty([]int{1, 2, 3})\n\tresult2 := LastOrEmpty([]int{})\n\tresult3 := LastOrEmpty([]string{})\n\n\tis.Equal(3, result1)\n\tis.Zero(result2)\n\tis.Empty(result3)\n}\n\nfunc TestLastOr(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := LastOr([]int{1, 2, 3}, 63)\n\tresult2 := LastOr([]int{}, 23)\n\tresult3 := LastOr([]string{}, \"test\")\n\n\tis.Equal(3, result1)\n\tis.Equal(23, result2)\n\tis.Equal(\"test\", result3)\n}\n\nfunc TestNth(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1, err1 := Nth([]int{0, 1, 2, 3}, 2)\n\tresult2, err2 := Nth([]int{0, 1, 2, 3}, -2)\n\tresult3, err3 := Nth([]int{0, 1, 2, 3}, 42)\n\tresult4, err4 := Nth([]int{}, 0)\n\tresult5, err5 := Nth([]int{42}, 0)\n\tresult6, err6 := Nth([]int{42}, -1)\n\n\tis.Equal(2, result1)\n\tis.NoError(err1)\n\tis.Equal(2, result2)\n\tis.NoError(err2)\n\tis.Zero(result3)\n\tis.EqualError(err3, \"nth: 42 out of slice bounds\")\n\tis.Zero(result4)\n\tis.EqualError(err4, \"nth: 0 out of slice bounds\")\n\tis.Equal(42, result5)\n\tis.NoError(err5)\n\tis.Equal(42, result6)\n\tis.NoError(err6)\n}\n\nfunc TestNthOr(t *testing.T) {\n\tt.Parallel()\n\n\tt.Run(\"Integers\", func(t *testing.T) {\n\t\tt.Parallel()\n\t\tis := assert.New(t)\n\n\t\tconst defaultValue = -1\n\t\tintSlice := []int{10, 20, 30, 40, 50}\n\n\t\tis.Equal(30, NthOr(intSlice, 2, defaultValue))\n\t\tis.Equal(50, NthOr(intSlice, -1, defaultValue))\n\t\tis.Equal(defaultValue, NthOr(intSlice, 5, defaultValue))\n\t})\n\n\tt.Run(\"Strings\", func(t *testing.T) {\n\t\tt.Parallel()\n\t\tis := assert.New(t)\n\n\t\tconst defaultValue = \"none\"\n\t\tstrSlice := []string{\"apple\", \"banana\", \"cherry\", \"date\"}\n\n\t\tis.Equal(\"banana\", NthOr(strSlice, 1, defaultValue))      // Index 1, expected \"banana\"\n\t\tis.Equal(\"cherry\", NthOr(strSlice, -2, defaultValue))     // Negative index -2, expected \"cherry\"\n\t\tis.Equal(defaultValue, NthOr(strSlice, 10, defaultValue)) // Out of bounds, fallback \"none\"\n\t})\n\n\tt.Run(\"Structs\", func(t *testing.T) {\n\t\tt.Parallel()\n\t\tis := assert.New(t)\n\n\t\ttype User struct {\n\t\t\tID   int\n\t\t\tName string\n\t\t}\n\t\tuserSlice := []User{\n\t\t\t{ID: 1, Name: \"Alice\"},\n\t\t\t{ID: 2, Name: \"Bob\"},\n\t\t\t{ID: 3, Name: \"Charlie\"},\n\t\t}\n\n\t\texpectedUser := User{ID: 1, Name: \"Alice\"}\n\t\tis.Equal(expectedUser, NthOr(userSlice, 0, User{ID: 0, Name: \"Unknown\"}))\n\n\t\texpectedUser = User{ID: 3, Name: \"Charlie\"}\n\t\tis.Equal(expectedUser, NthOr(userSlice, -1, User{ID: 0, Name: \"Unknown\"}))\n\n\t\texpectedUser = User{ID: 0, Name: \"Unknown\"}\n\t\tis.Equal(expectedUser, NthOr(userSlice, 10, User{ID: 0, Name: \"Unknown\"}))\n\t})\n}\n\nfunc TestNthOrEmpty(t *testing.T) {\n\tt.Parallel()\n\n\tt.Run(\"Integers\", func(t *testing.T) {\n\t\tt.Parallel()\n\t\tis := assert.New(t)\n\n\t\tintSlice := []int{10, 20, 30, 40, 50}\n\n\t\tis.Equal(30, NthOrEmpty(intSlice, 2))\n\t\tis.Equal(50, NthOrEmpty(intSlice, -1))\n\t\tis.Zero(NthOrEmpty(intSlice, 10))\n\t})\n\n\tt.Run(\"Strings\", func(t *testing.T) {\n\t\tt.Parallel()\n\t\tis := assert.New(t)\n\n\t\tstrSlice := []string{\"apple\", \"banana\", \"cherry\", \"date\"}\n\n\t\tis.Equal(\"banana\", NthOrEmpty(strSlice, 1))\n\t\tis.Equal(\"cherry\", NthOrEmpty(strSlice, -2))\n\t\tis.Empty(NthOrEmpty(strSlice, 10))\n\t})\n\n\tt.Run(\"Structs\", func(t *testing.T) {\n\t\tt.Parallel()\n\t\tis := assert.New(t)\n\n\t\ttype User struct {\n\t\t\tID   int\n\t\t\tName string\n\t\t}\n\t\tuserSlice := []User{\n\t\t\t{ID: 1, Name: \"Alice\"},\n\t\t\t{ID: 2, Name: \"Bob\"},\n\t\t\t{ID: 3, Name: \"Charlie\"},\n\t\t}\n\n\t\texpectedUser := User{ID: 1, Name: \"Alice\"}\n\t\tis.Equal(expectedUser, NthOrEmpty(userSlice, 0))\n\n\t\texpectedUser = User{ID: 3, Name: \"Charlie\"}\n\t\tis.Equal(expectedUser, NthOrEmpty(userSlice, -1))\n\n\t\tis.Zero(NthOrEmpty(userSlice, 10))\n\t})\n}\n\nfunc TestSample(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := Sample([]string{\"a\", \"b\", \"c\"})\n\tresult2 := Sample([]string{})\n\n\tis.True(Contains([]string{\"a\", \"b\", \"c\"}, result1))\n\tis.Empty(result2)\n}\n\nfunc TestSampleBy(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tr := rand.New(rand.NewSource(42))\n\n\tresult1 := SampleBy([]string{\"a\", \"b\", \"c\"}, r.Intn)\n\tresult2 := SampleBy([]string{}, rand.Intn)\n\n\tis.True(Contains([]string{\"a\", \"b\", \"c\"}, result1))\n\tis.Empty(result2)\n}\n\nfunc TestSamples(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := Samples([]string{\"a\", \"b\", \"c\"}, 3)\n\tresult2 := Samples([]string{}, 3)\n\n\tis.ElementsMatch(result1, []string{\"a\", \"b\", \"c\"})\n\tis.Empty(result2)\n\n\ttype myStrings []string\n\tallStrings := myStrings{\"\", \"foo\", \"bar\"}\n\tnonempty := Samples(allStrings, 2)\n\tis.IsType(nonempty, allStrings, \"type preserved\")\n}\n\nfunc TestSamplesBy(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tr := rand.New(rand.NewSource(42))\n\n\tresult1 := SamplesBy([]string{\"a\", \"b\", \"c\"}, 3, r.Intn)\n\tresult2 := SamplesBy([]string{}, 3, r.Intn)\n\tresult3 := SamplesBy([]string{\"a\", \"b\", \"c\"}, 3, func(n int) int { return n - 1 })\n\tresult4 := SamplesBy([]string{\"a\", \"b\", \"c\"}, 3, func(int) int { return 0 })\n\tresult5 := SamplesBy([]string{\"a\", \"b\", \"c\"}, 0, func(int) int { return 1 })\n\tresult6 := SamplesBy([]string{\"a\", \"b\", \"c\"}, -1, nil)\n\n\t// index out of range [1] with length 1\n\tis.Panics(func() {\n\t\tSamplesBy([]string{\"a\", \"b\", \"c\"}, 3, func(int) int { return 1 })\n\t})\n\n\tis.ElementsMatch(result1, []string{\"a\", \"b\", \"c\"})\n\tis.Empty(result2)\n\tis.Equal([]string{\"c\", \"b\", \"a\"}, result3)\n\tis.Equal([]string{\"a\", \"c\", \"b\"}, result4)\n\tis.Empty(result5)\n\tis.Empty(result6)\n\n\ttype myStrings []string\n\tallStrings := myStrings{\"\", \"foo\", \"bar\"}\n\tnonempty := SamplesBy(allStrings, 2, r.Intn)\n\tis.IsType(nonempty, allStrings, \"type preserved\")\n}\n"
  },
  {
    "path": "func.go",
    "content": "package lo\n\n// Partial returns new function that, when called, has its first argument set to the provided value.\n// Play: https://go.dev/play/p/Sy1gAQiQZ3v\nfunc Partial[T1, T2, R any](f func(a T1, b T2) R, arg1 T1) func(T2) R {\n\treturn func(t2 T2) R {\n\t\treturn f(arg1, t2)\n\t}\n}\n\n// Partial1 returns new function that, when called, has its first argument set to the provided value.\n// Play: https://go.dev/play/p/D-ASTXCLBzw\nfunc Partial1[T1, T2, R any](f func(T1, T2) R, arg1 T1) func(T2) R {\n\treturn Partial(f, arg1)\n}\n\n// Partial2 returns new function that, when called, has its first argument set to the provided value.\n// Play: https://go.dev/play/p/-xiPjy4JChJ\nfunc Partial2[T1, T2, T3, R any](f func(T1, T2, T3) R, arg1 T1) func(T2, T3) R {\n\treturn func(t2 T2, t3 T3) R {\n\t\treturn f(arg1, t2, t3)\n\t}\n}\n\n// Partial3 returns new function that, when called, has its first argument set to the provided value.\n// Play: https://go.dev/play/p/zWtSutpI26m\nfunc Partial3[T1, T2, T3, T4, R any](f func(T1, T2, T3, T4) R, arg1 T1) func(T2, T3, T4) R {\n\treturn func(t2 T2, t3 T3, t4 T4) R {\n\t\treturn f(arg1, t2, t3, t4)\n\t}\n}\n\n// Partial4 returns new function that, when called, has its first argument set to the provided value.\n// Play: https://go.dev/play/p/kBrnnMTcJm0\nfunc Partial4[T1, T2, T3, T4, T5, R any](f func(T1, T2, T3, T4, T5) R, arg1 T1) func(T2, T3, T4, T5) R {\n\treturn func(t2 T2, t3 T3, t4 T4, t5 T5) R {\n\t\treturn f(arg1, t2, t3, t4, t5)\n\t}\n}\n\n// Partial5 returns new function that, when called, has its first argument set to the provided value.\n// Play: https://go.dev/play/p/7Is7K2y_VC3\nfunc Partial5[T1, T2, T3, T4, T5, T6, R any](f func(T1, T2, T3, T4, T5, T6) R, arg1 T1) func(T2, T3, T4, T5, T6) R {\n\treturn func(t2 T2, t3 T3, t4 T4, t5 T5, t6 T6) R {\n\t\treturn f(arg1, t2, t3, t4, t5, t6)\n\t}\n}\n"
  },
  {
    "path": "func_test.go",
    "content": "package lo\n\nimport (\n\t\"strconv\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestPartial(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tadd := func(x float64, y int) string {\n\t\treturn strconv.Itoa(int(x) + y)\n\t}\n\tf := Partial(add, 5)\n\tis.Equal(\"15\", f(10))\n\tis.Equal(\"0\", f(-5))\n}\n\nfunc TestPartial1(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tadd := func(x float64, y int) string {\n\t\treturn strconv.Itoa(int(x) + y)\n\t}\n\tf := Partial1(add, 5)\n\tis.Equal(\"15\", f(10))\n\tis.Equal(\"0\", f(-5))\n}\n\nfunc TestPartial2(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tadd := func(x float64, y, z int) string {\n\t\treturn strconv.Itoa(int(x) + y + z)\n\t}\n\tf := Partial2(add, 5)\n\tis.Equal(\"24\", f(10, 9))\n\tis.Equal(\"8\", f(-5, 8))\n}\n\nfunc TestPartial3(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tadd := func(x float64, y, z int, a float32) string {\n\t\treturn strconv.Itoa(int(x) + y + z + int(a))\n\t}\n\tf := Partial3(add, 5)\n\tis.Equal(\"21\", f(10, 9, -3))\n\tis.Equal(\"15\", f(-5, 8, 7))\n}\n\nfunc TestPartial4(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tadd := func(x float64, y, z int, a float32, b int32) string {\n\t\treturn strconv.Itoa(int(x) + y + z + int(a) + int(b))\n\t}\n\tf := Partial4(add, 5)\n\tis.Equal(\"21\", f(10, 9, -3, 0))\n\tis.Equal(\"14\", f(-5, 8, 7, -1))\n}\n\nfunc TestPartial5(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tadd := func(x float64, y, z int, a float32, b int32, c int) string {\n\t\treturn strconv.Itoa(int(x) + y + z + int(a) + int(b) + c)\n\t}\n\tf := Partial5(add, 5)\n\tis.Equal(\"26\", f(10, 9, -3, 0, 5))\n\tis.Equal(\"21\", f(-5, 8, 7, -1, 7))\n}\n"
  },
  {
    "path": "go.mod",
    "content": "module github.com/samber/lo\n\ngo 1.18\n\n//\n// Dev dependencies are excluded from releases. Please check CI.\n//\n\nrequire (\n\tgithub.com/stretchr/testify v1.11.1\n\tgithub.com/thoas/go-funk v0.9.3\n\tgo.uber.org/goleak v1.2.1\n\tgolang.org/x/text v0.22.0\n)\n\nrequire (\n\tgithub.com/davecgh/go-spew v1.1.1 // indirect\n\tgithub.com/kr/text v0.2.0 // indirect\n\tgithub.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect\n\tgithub.com/pmezard/go-difflib v1.0.0 // indirect\n\tgopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect\n\tgopkg.in/yaml.v3 v3.0.1 // indirect\n)\n"
  },
  {
    "path": "go.sum",
    "content": "github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=\ngithub.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=\ngithub.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=\ngithub.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=\ngithub.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=\ngithub.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=\ngithub.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=\ngithub.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=\ngithub.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=\ngithub.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=\ngithub.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=\ngithub.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=\ngithub.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=\ngithub.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=\ngithub.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=\ngithub.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=\ngithub.com/thoas/go-funk v0.9.3 h1:7+nAEx3kn5ZJcnDm2Bh23N2yOtweO14bi//dvRtgLpw=\ngithub.com/thoas/go-funk v0.9.3/go.mod h1:+IWnUfUmFO1+WVYQWQtIJHeRRdaIyyYglZN7xzUPe4Q=\ngo.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A=\ngo.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4=\ngolang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=\ngolang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=\ngopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=\ngopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=\ngopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=\ngopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=\ngopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=\ngopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=\n"
  },
  {
    "path": "internal/constraints/README.md",
    "content": "\n# Constraints\n\nThis package is for Go 1.18 retrocompatiblity purpose.\n"
  },
  {
    "path": "internal/constraints/constraints.go",
    "content": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package constraints defines a set of useful constraints to be used\n// with type parameters.\npackage constraints\n\n// Signed is a constraint that permits any signed integer type.\n// If future releases of Go add new predeclared signed integer types,\n// this constraint will be modified to include them.\ntype Signed interface {\n\t~int | ~int8 | ~int16 | ~int32 | ~int64\n}\n\n// Unsigned is a constraint that permits any unsigned integer type.\n// If future releases of Go add new predeclared unsigned integer types,\n// this constraint will be modified to include them.\ntype Unsigned interface {\n\t~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr\n}\n\n// Integer is a constraint that permits any integer type.\n// If future releases of Go add new predeclared integer types,\n// this constraint will be modified to include them.\ntype Integer interface {\n\tSigned | Unsigned\n}\n\n// Float is a constraint that permits any floating-point type.\n// If future releases of Go add new predeclared floating-point types,\n// this constraint will be modified to include them.\ntype Float interface {\n\t~float32 | ~float64\n}\n\n// Complex is a constraint that permits any complex numeric type.\n// If future releases of Go add new predeclared complex numeric types,\n// this constraint will be modified to include them.\ntype Complex interface {\n\t~complex64 | ~complex128\n}\n"
  },
  {
    "path": "internal/constraints/ordered_go118.go",
    "content": "//go:build !go1.21\n\npackage constraints\n\n// Ordered is a constraint that permits any ordered type: any type\n// that supports the operators < <= >= >.\n// If future releases of Go add new ordered types,\n// this constraint will be modified to include them.\ntype Ordered interface {\n\tInteger | Float | ~string\n}\n"
  },
  {
    "path": "internal/constraints/ordered_go121.go",
    "content": "//go:build go1.21\n\npackage constraints\n\nimport (\n\t\"cmp\"\n)\n\n// Ordered is a constraint that permits any ordered type: any type\n// that supports the operators < <= >= >.\n// If future releases of Go add new ordered types,\n// this constraint will be modified to include them.\ntype Ordered = cmp.Ordered\n"
  },
  {
    "path": "internal/xrand/ordered_go118.go",
    "content": "//go:build !go1.22\n\npackage xrand\n\nimport \"math/rand\"\n\n// Shuffle returns a slice of shuffled values. Uses the Fisher-Yates shuffle algorithm.\nfunc Shuffle(n int, swap func(i, j int)) {\n\trand.Shuffle(n, swap)\n}\n\n// IntN returns, as an int, a pseudo-random number in the half-open interval [0,n)\n// from the default Source.\n// It panics if n <= 0.\nfunc IntN(n int) int {\n\t// bearer:disable go_gosec_crypto_weak_random\n\treturn rand.Intn(n)\n}\n\n// Int64 returns a non-negative pseudo-random 63-bit integer as an int64\n// from the default Source.\nfunc Int64() int64 {\n\t// bearer:disable go_gosec_crypto_weak_random\n\tn := rand.Int63()\n\n\t// bearer:disable go_gosec_crypto_weak_random\n\tif rand.Intn(2) == 0 {\n\t\treturn -n\n\t}\n\n\treturn n\n}\n"
  },
  {
    "path": "internal/xrand/ordered_go122.go",
    "content": "//go:build go1.22\n\npackage xrand\n\nimport \"math/rand/v2\"\n\n// Shuffle returns a slice of shuffled values. Uses the Fisher-Yates shuffle algorithm.\nfunc Shuffle(n int, swap func(i, j int)) {\n\trand.Shuffle(n, swap)\n}\n\n// IntN returns, as an int, a pseudo-random number in the half-open interval [0,n)\n// from the default Source.\n// It panics if n <= 0.\nfunc IntN(n int) int {\n\treturn rand.IntN(n)\n}\n\n// Int64 returns a non-negative pseudo-random 63-bit integer as an int64\n// from the default Source.\nfunc Int64() int64 {\n\treturn rand.Int64()\n}\n"
  },
  {
    "path": "internal/xtime/README.md",
    "content": "\n# xtime\n\nLightweight mock for time package.\n\nA dedicated package such as [jonboulle/clockwork](https://github.com/jonboulle/clockwork/) would be better, but I would rather limit dependencies for this package. `clockwork` does not support Go 1.18 anymore.\n"
  },
  {
    "path": "internal/xtime/fake.go",
    "content": "//nolint:revive\npackage xtime\n\nimport (\n\t\"time\"\n)\n\nfunc NewFakeClock() *FakeClock {\n\treturn NewFakeClockAt(time.Now())\n}\n\nfunc NewFakeClockAt(t time.Time) *FakeClock {\n\treturn &FakeClock{\n\t\ttime: t,\n\t}\n}\n\ntype FakeClock struct {\n\t_ noCopy\n\n\t// Not protected by a mutex. If a warning is thrown in your tests,\n\t// just disable parallel tests.\n\ttime time.Time\n}\n\nfunc (c *FakeClock) Now() time.Time {\n\treturn c.time\n}\n\nfunc (c *FakeClock) Since(t time.Time) time.Duration {\n\treturn c.time.Sub(t)\n}\n\nfunc (c *FakeClock) Until(t time.Time) time.Duration {\n\treturn t.Sub(c.time)\n}\n\nfunc (c *FakeClock) Sleep(d time.Duration) {\n\tc.time = c.time.Add(d)\n}\n"
  },
  {
    "path": "internal/xtime/noCopy.go",
    "content": "package xtime\n\n// noCopy may be added to structs which must not be copied\n// after the first use.\n//\n// See https://golang.org/issues/8005#issuecomment-190753527\n// for details.\n//\n// Note that it must not be embedded, due to the Lock and Unlock methods.\ntype noCopy struct{}\n\n// Lock is a no-op used by -copylocks checker from `go vet`.\nfunc (*noCopy) Lock()   {}\nfunc (*noCopy) Unlock() {}\n"
  },
  {
    "path": "internal/xtime/real.go",
    "content": "//nolint:revive\npackage xtime\n\nimport (\n\t\"time\"\n)\n\nfunc NewRealClock() *RealClock {\n\treturn &RealClock{}\n}\n\ntype RealClock struct {\n\t_ noCopy\n}\n\nfunc (c *RealClock) Now() time.Time {\n\treturn time.Now()\n}\n\nfunc (c *RealClock) Since(t time.Time) time.Duration {\n\treturn time.Since(t)\n}\n\nfunc (c *RealClock) Until(t time.Time) time.Duration {\n\treturn time.Until(t)\n}\n\nfunc (c *RealClock) Sleep(d time.Duration) {\n\ttime.Sleep(d)\n}\n"
  },
  {
    "path": "internal/xtime/time.go",
    "content": "//nolint:revive\npackage xtime\n\nimport \"time\"\n\nvar clock Clock = &RealClock{}\n\nfunc SetClock(c Clock) {\n\tclock = c\n}\n\nfunc Now() time.Time {\n\treturn clock.Now()\n}\n\nfunc Since(t time.Time) time.Duration {\n\treturn clock.Since(t)\n}\n\nfunc Until(t time.Time) time.Duration {\n\treturn clock.Until(t)\n}\n\nfunc Sleep(d time.Duration) {\n\tclock.Sleep(d)\n}\n\ntype Clock interface {\n\tNow() time.Time\n\tSince(t time.Time) time.Duration\n\tUntil(t time.Time) time.Duration\n\tSleep(d time.Duration)\n}\n"
  },
  {
    "path": "intersect.go",
    "content": "package lo\n\n// Contains returns true if an element is present in a collection.\n// Play: https://go.dev/play/p/W1EvyqY6t9j\nfunc Contains[T comparable](collection []T, element T) bool {\n\tfor i := range collection {\n\t\tif collection[i] == element {\n\t\t\treturn true\n\t\t}\n\t}\n\n\treturn false\n}\n\n// ContainsBy returns true if predicate function return true.\n// Play: https://go.dev/play/p/W1EvyqY6t9j\nfunc ContainsBy[T any](collection []T, predicate func(item T) bool) bool {\n\tfor i := range collection {\n\t\tif predicate(collection[i]) {\n\t\t\treturn true\n\t\t}\n\t}\n\n\treturn false\n}\n\n// Every returns true if all elements of a subset are contained in a collection or if the subset is empty.\n// Play: https://go.dev/play/p/W1EvyqY6t9j\nfunc Every[T comparable](collection, subset []T) bool {\n\tif len(subset) == 0 {\n\t\treturn true\n\t}\n\n\tseen := Keyify(collection)\n\n\tfor _, item := range subset {\n\t\tif _, ok := seen[item]; !ok {\n\t\t\treturn false\n\t\t}\n\t}\n\n\treturn true\n}\n\n// EveryBy returns true if the predicate returns true for all elements in the collection or if the collection is empty.\n// Play: https://go.dev/play/p/dn1-vhHsq9x\nfunc EveryBy[T any](collection []T, predicate func(item T) bool) bool {\n\tfor i := range collection {\n\t\tif !predicate(collection[i]) {\n\t\t\treturn false\n\t\t}\n\t}\n\n\treturn true\n}\n\n// Some returns true if at least 1 element of a subset is contained in a collection.\n// If the subset is empty Some returns false.\n// Play: https://go.dev/play/p/Lj4ceFkeT9V\nfunc Some[T comparable](collection, subset []T) bool {\n\tif len(subset) == 0 {\n\t\treturn false\n\t}\n\n\tseen := Keyify(subset)\n\tfor i := range collection {\n\t\tif _, ok := seen[collection[i]]; ok {\n\t\t\treturn true\n\t\t}\n\t}\n\n\treturn false\n}\n\n// SomeBy returns true if the predicate returns true for any of the elements in the collection.\n// If the collection is empty SomeBy returns false.\n// Play: https://go.dev/play/p/DXF-TORBudx\nfunc SomeBy[T any](collection []T, predicate func(item T) bool) bool {\n\tfor i := range collection {\n\t\tif predicate(collection[i]) {\n\t\t\treturn true\n\t\t}\n\t}\n\n\treturn false\n}\n\n// None returns true if no element of a subset is contained in a collection or if the subset is empty.\n// Play: https://go.dev/play/p/fye7JsmxzPV\nfunc None[T comparable](collection, subset []T) bool {\n\tif len(subset) == 0 {\n\t\treturn true\n\t}\n\n\tseen := Keyify(subset)\n\tfor i := range collection {\n\t\tif _, ok := seen[collection[i]]; ok {\n\t\t\treturn false\n\t\t}\n\t}\n\n\treturn true\n}\n\n// NoneBy returns true if the predicate returns true for none of the elements in the collection or if the collection is empty.\n// Play: https://go.dev/play/p/O64WZ32H58S\nfunc NoneBy[T any](collection []T, predicate func(item T) bool) bool {\n\tfor i := range collection {\n\t\tif predicate(collection[i]) {\n\t\t\treturn false\n\t\t}\n\t}\n\n\treturn true\n}\n\n// Intersect returns the intersection between collections.\n// Play: https://go.dev/play/p/uuElL9X9e58\nfunc Intersect[T comparable, Slice ~[]T](lists ...Slice) Slice {\n\tif len(lists) == 0 {\n\t\treturn Slice{}\n\t}\n\n\tlast := lists[len(lists)-1]\n\n\tseen := make(map[T]bool, len(last))\n\n\tfor _, item := range last {\n\t\tseen[item] = false\n\t}\n\n\tfor i := len(lists) - 2; i > 0 && len(seen) != 0; i-- {\n\t\tfor _, item := range lists[i] {\n\t\t\tif _, ok := seen[item]; ok {\n\t\t\t\tseen[item] = true\n\t\t\t}\n\t\t}\n\n\t\tfor k, v := range seen {\n\t\t\tif v {\n\t\t\t\tseen[k] = false\n\t\t\t} else {\n\t\t\t\tdelete(seen, k)\n\t\t\t}\n\t\t}\n\t}\n\n\tresult := make(Slice, 0, len(seen))\n\n\tfor _, item := range lists[0] {\n\t\tif _, ok := seen[item]; ok {\n\t\t\tresult = append(result, item)\n\t\t\tdelete(seen, item)\n\t\t}\n\t}\n\n\treturn result\n}\n\n// IntersectBy returns the intersection between two collections using a custom key selector function.\n// Play: https://go.dev/play/p/uWF8y2-zmtf\nfunc IntersectBy[T any, K comparable, Slice ~[]T](transform func(T) K, lists ...Slice) Slice {\n\tif len(lists) == 0 {\n\t\treturn Slice{}\n\t}\n\n\tlast := lists[len(lists)-1]\n\n\tseen := make(map[K]bool, len(last))\n\n\tfor _, item := range last {\n\t\tk := transform(item)\n\t\tseen[k] = false\n\t}\n\n\tfor i := len(lists) - 2; i > 0 && len(seen) != 0; i-- {\n\t\tfor _, item := range lists[i] {\n\t\t\tk := transform(item)\n\t\t\tif _, ok := seen[k]; ok {\n\t\t\t\tseen[k] = true\n\t\t\t}\n\t\t}\n\n\t\tfor k, v := range seen {\n\t\t\tif v {\n\t\t\t\tseen[k] = false\n\t\t\t} else {\n\t\t\t\tdelete(seen, k)\n\t\t\t}\n\t\t}\n\t}\n\n\tresult := make(Slice, 0, len(seen))\n\n\tfor _, item := range lists[0] {\n\t\tk := transform(item)\n\t\tif _, ok := seen[k]; ok {\n\t\t\tresult = append(result, item)\n\t\t\tdelete(seen, k)\n\t\t}\n\t}\n\n\treturn result\n}\n\n// Difference returns the difference between two collections.\n// The first value is the collection of elements absent from list2.\n// The second value is the collection of elements absent from list1.\n// Play: https://go.dev/play/p/pKE-JgzqRpz\nfunc Difference[T comparable, Slice ~[]T](list1, list2 Slice) (Slice, Slice) {\n\tleft := make(Slice, 0, len(list1))\n\tright := make(Slice, 0, len(list2))\n\n\tseenLeft := Keyify(list1)\n\tseenRight := Keyify(list2)\n\n\tfor i := range list1 {\n\t\tif _, ok := seenRight[list1[i]]; !ok {\n\t\t\tleft = append(left, list1[i])\n\t\t}\n\t}\n\n\tfor i := range list2 {\n\t\tif _, ok := seenLeft[list2[i]]; !ok {\n\t\t\tright = append(right, list2[i])\n\t\t}\n\t}\n\n\treturn left, right\n}\n\n// Union returns all distinct elements from given collections.\n// result returns will not change the order of elements relatively.\n// Play: https://go.dev/play/p/-hsqZNTH0ej\nfunc Union[T comparable, Slice ~[]T](lists ...Slice) Slice {\n\tvar capLen int\n\n\tfor _, list := range lists {\n\t\tcapLen += len(list)\n\t}\n\n\tresult := make(Slice, 0, capLen)\n\tseen := make(map[T]struct{}, capLen)\n\n\tfor i := range lists {\n\t\tfor j := range lists[i] {\n\t\t\tif _, ok := seen[lists[i][j]]; !ok {\n\t\t\t\tseen[lists[i][j]] = struct{}{}\n\t\t\t\tresult = append(result, lists[i][j])\n\t\t\t}\n\t\t}\n\t}\n\n\treturn result\n}\n\n// Without returns a slice excluding all given values.\n// Play: https://go.dev/play/p/PcAVtYJsEsS\nfunc Without[T comparable, Slice ~[]T](collection Slice, exclude ...T) Slice {\n\texcludeMap := Keyify(exclude)\n\n\tresult := make(Slice, 0, len(collection))\n\tfor i := range collection {\n\t\tif _, ok := excludeMap[collection[i]]; !ok {\n\t\t\tresult = append(result, collection[i])\n\t\t}\n\t}\n\treturn result\n}\n\n// WithoutBy filters a slice by excluding elements whose extracted keys match any in the exclude list.\n// Returns a new slice containing only the elements whose keys are not in the exclude list.\n// Play: https://go.dev/play/p/VgWJOF01NbJ\nfunc WithoutBy[T any, K comparable, Slice ~[]T](collection Slice, iteratee func(item T) K, exclude ...K) Slice {\n\texcludeMap := Keyify(exclude)\n\n\tresult := make(Slice, 0, len(collection))\n\tfor _, item := range collection {\n\t\tif _, ok := excludeMap[iteratee(item)]; !ok {\n\t\t\tresult = append(result, item)\n\t\t}\n\t}\n\treturn result\n}\n\n// WithoutByErr filters a slice by excluding elements whose extracted keys match any in the exclude list.\n// It returns the first error returned by the iteratee.\nfunc WithoutByErr[T any, K comparable, Slice ~[]T](collection Slice, iteratee func(item T) (K, error), exclude ...K) (Slice, error) {\n\texcludeMap := Keyify(exclude)\n\n\tresult := make(Slice, 0, len(collection))\n\tfor _, item := range collection {\n\t\tkey, err := iteratee(item)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tif _, ok := excludeMap[key]; !ok {\n\t\t\tresult = append(result, item)\n\t\t}\n\t}\n\treturn result, nil\n}\n\n// WithoutEmpty returns a slice excluding zero values.\n//\n// Deprecated: Use lo.Compact instead.\n// Play: https://go.dev/play/p/iZvYJWuniJm\nfunc WithoutEmpty[T comparable, Slice ~[]T](collection Slice) Slice {\n\treturn Compact(collection)\n}\n\n// WithoutNth returns a slice excluding the nth value.\n// Play: https://go.dev/play/p/5g3F9R2H1xL\nfunc WithoutNth[T any, Slice ~[]T](collection Slice, nths ...int) Slice {\n\ttoRemove := Keyify(nths)\n\n\tresult := make(Slice, 0, len(collection))\n\tfor i := range collection {\n\t\tif _, ok := toRemove[i]; !ok {\n\t\t\tresult = append(result, collection[i])\n\t\t}\n\t}\n\n\treturn result\n}\n\n// ElementsMatch returns true if lists contain the same set of elements (including empty set).\n// If there are duplicate elements, the number of occurrences in each list should match.\n// The order of elements is not checked.\n// Play: https://go.dev/play/p/XWSEM4Ic_t0\nfunc ElementsMatch[T comparable, Slice ~[]T](list1, list2 Slice) bool {\n\treturn ElementsMatchBy(list1, list2, func(item T) T { return item })\n}\n\n// ElementsMatchBy returns true if lists contain the same set of elements' keys (including empty set).\n// If there are duplicate keys, the number of occurrences in each list should match.\n// The order of elements is not checked.\n// Play: https://go.dev/play/p/XWSEM4Ic_t0\nfunc ElementsMatchBy[T any, K comparable](list1, list2 []T, iteratee func(item T) K) bool {\n\tif len(list1) != len(list2) {\n\t\treturn false\n\t}\n\n\tif len(list1) == 0 {\n\t\treturn true\n\t}\n\n\tcounters := make(map[K]int, len(list1))\n\n\tfor _, el := range list1 {\n\t\tcounters[iteratee(el)]++\n\t}\n\n\tfor _, el := range list2 {\n\t\tcounters[iteratee(el)]--\n\t}\n\n\tfor _, count := range counters {\n\t\tif count != 0 {\n\t\t\treturn false\n\t\t}\n\t}\n\n\treturn true\n}\n"
  },
  {
    "path": "intersect_test.go",
    "content": "package lo\n\nimport (\n\t\"errors\"\n\t\"strconv\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestContains(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := Contains([]int{0, 1, 2, 3, 4, 5}, 5)\n\tresult2 := Contains([]int{0, 1, 2, 3, 4, 5}, 6)\n\n\tis.True(result1)\n\tis.False(result2)\n}\n\nfunc TestContainsBy(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\ttype a struct {\n\t\tA int\n\t\tB string\n\t}\n\n\ta1 := []a{{A: 1, B: \"1\"}, {A: 2, B: \"2\"}, {A: 3, B: \"3\"}}\n\tresult1 := ContainsBy(a1, func(t a) bool { return t.A == 1 && t.B == \"2\" })\n\tresult2 := ContainsBy(a1, func(t a) bool { return t.A == 2 && t.B == \"2\" })\n\n\ta2 := []string{\"aaa\", \"bbb\", \"ccc\"}\n\tresult3 := ContainsBy(a2, func(t string) bool { return t == \"ccc\" })\n\tresult4 := ContainsBy(a2, func(t string) bool { return t == \"ddd\" })\n\n\tis.False(result1)\n\tis.True(result2)\n\tis.True(result3)\n\tis.False(result4)\n}\n\nfunc TestEvery(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := Every([]int{0, 1, 2, 3, 4, 5}, []int{0, 2})\n\tresult2 := Every([]int{0, 1, 2, 3, 4, 5}, []int{0, 6})\n\tresult3 := Every([]int{0, 1, 2, 3, 4, 5}, []int{-1, 6})\n\tresult4 := Every([]int{0, 1, 2, 3, 4, 5}, []int{})\n\n\tis.True(result1)\n\tis.False(result2)\n\tis.False(result3)\n\tis.True(result4)\n}\n\nfunc TestEveryBy(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := EveryBy([]int{1, 2, 3, 4}, func(x int) bool {\n\t\treturn x < 5\n\t})\n\n\tis.True(result1)\n\n\tresult2 := EveryBy([]int{1, 2, 3, 4}, func(x int) bool {\n\t\treturn x < 3\n\t})\n\n\tis.False(result2)\n\n\tresult3 := EveryBy([]int{1, 2, 3, 4}, func(x int) bool {\n\t\treturn x < 0\n\t})\n\n\tis.False(result3)\n\n\tresult4 := EveryBy([]int{}, func(x int) bool {\n\t\treturn x < 5\n\t})\n\n\tis.True(result4)\n}\n\nfunc TestSome(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := Some([]int{0, 1, 2, 3, 4, 5}, []int{0, 2})\n\tresult2 := Some([]int{0, 1, 2, 3, 4, 5}, []int{0, 6})\n\tresult3 := Some([]int{0, 1, 2, 3, 4, 5}, []int{-1, 6})\n\tresult4 := Some([]int{0, 1, 2, 3, 4, 5}, []int{})\n\n\tis.True(result1)\n\tis.True(result2)\n\tis.False(result3)\n\tis.False(result4)\n}\n\nfunc TestSomeBy(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := SomeBy([]int{1, 2, 3, 4}, func(x int) bool {\n\t\treturn x < 5\n\t})\n\n\tis.True(result1)\n\n\tresult2 := SomeBy([]int{1, 2, 3, 4}, func(x int) bool {\n\t\treturn x < 3\n\t})\n\n\tis.True(result2)\n\n\tresult3 := SomeBy([]int{1, 2, 3, 4}, func(x int) bool {\n\t\treturn x < 0\n\t})\n\n\tis.False(result3)\n\n\tresult4 := SomeBy([]int{}, func(x int) bool {\n\t\treturn x < 5\n\t})\n\n\tis.False(result4)\n}\n\nfunc TestNone(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := None([]int{0, 1, 2, 3, 4, 5}, []int{0, 2})\n\tresult2 := None([]int{0, 1, 2, 3, 4, 5}, []int{0, 6})\n\tresult3 := None([]int{0, 1, 2, 3, 4, 5}, []int{-1, 6})\n\tresult4 := None([]int{0, 1, 2, 3, 4, 5}, []int{})\n\n\tis.False(result1)\n\tis.False(result2)\n\tis.True(result3)\n\tis.True(result4)\n}\n\nfunc TestNoneBy(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := NoneBy([]int{1, 2, 3, 4}, func(x int) bool {\n\t\treturn x < 5\n\t})\n\n\tis.False(result1)\n\n\tresult2 := NoneBy([]int{1, 2, 3, 4}, func(x int) bool {\n\t\treturn x < 3\n\t})\n\n\tis.False(result2)\n\n\tresult3 := NoneBy([]int{1, 2, 3, 4}, func(x int) bool {\n\t\treturn x < 0\n\t})\n\n\tis.True(result3)\n\n\tresult4 := NoneBy([]int{}, func(x int) bool {\n\t\treturn x < 5\n\t})\n\n\tis.True(result4)\n}\n\nfunc TestIntersect(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult0 := Intersect[int, []int]()\n\tresult1 := Intersect([]int{1})\n\tresult2 := Intersect([]int{0, 1, 2, 3, 4, 5}, []int{0, 2})\n\tresult3 := Intersect([]int{0, 1, 2, 3, 4, 5}, []int{0, 6})\n\tresult4 := Intersect([]int{0, 1, 2, 3, 4, 5}, []int{-1, 6})\n\tresult5 := Intersect([]int{0, 6}, []int{0, 1, 2, 3, 4, 5})\n\tresult6 := Intersect([]int{0, 6, 0}, []int{0, 1, 2, 3, 4, 5})\n\tresult7 := Intersect([]int{0, 6, 0, 3}, []int{0, 1, 2, 3, 4, 5}, []int{0, 6})\n\tresult8 := Intersect([]int{0, 6, 0, 3}, []int{0, 1, 2, 3, 4, 5}, []int{1, 6})\n\tresult9 := Intersect([]int{0, 1, 1}, []int{2}, []int{3})\n\tresultA := Intersect([]int{0, 1, 1})\n\n\tis.Empty(result0)\n\tis.ElementsMatch([]int{1}, result1)\n\tis.ElementsMatch([]int{0, 2}, result2)\n\tis.ElementsMatch([]int{0}, result3)\n\tis.Empty(result4)\n\tis.ElementsMatch([]int{0}, result5)\n\tis.ElementsMatch([]int{0}, result6)\n\tis.ElementsMatch([]int{0}, result7)\n\tis.Empty(result8)\n\tis.Empty(result9)\n\tis.ElementsMatch([]int{0, 1}, resultA)\n\n\ttype myStrings []string\n\tallStrings := myStrings{\"\", \"foo\", \"bar\"}\n\tnonempty := Intersect(allStrings, allStrings)\n\tis.IsType(nonempty, allStrings, \"type preserved\")\n}\n\nfunc TestIntersectBy(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\ttype User struct {\n\t\tID   int\n\t\tName string\n\t}\n\n\tlist1 := []User{\n\t\t{ID: 1, Name: \"Alice\"},\n\t\t{ID: 2, Name: \"Bob\"},\n\t\t{ID: 3, Name: \"Charlie\"},\n\t}\n\n\tlist2 := []User{\n\t\t{ID: 2, Name: \"Robert\"},\n\t\t{ID: 3, Name: \"Charlie\"},\n\t\t{ID: 4, Name: \"Alice\"},\n\t}\n\n\tintersectByID := IntersectBy(func(u User) int {\n\t\treturn u.ID\n\t}, list1, list2)\n\tis.ElementsMatch(intersectByID, []User{{ID: 2, Name: \"Bob\"}, {ID: 3, Name: \"Charlie\"}})\n\n\tintersectByName := IntersectBy(func(u User) string {\n\t\treturn u.Name\n\t}, list1, list2)\n\tis.ElementsMatch(intersectByName, []User{{ID: 3, Name: \"Charlie\"}, {ID: 1, Name: \"Alice\"}})\n\n\tintersectByIDAndName := IntersectBy(func(u User) string {\n\t\treturn strconv.Itoa(u.ID) + u.Name\n\t}, list1, list2)\n\tis.ElementsMatch(intersectByIDAndName, []User{{ID: 3, Name: \"Charlie\"}})\n\n\tresult := IntersectBy(strconv.Itoa, []int{0, 6, 0, 3}, []int{0, 1, 2, 3, 4, 5}, []int{0, 6})\n\tis.ElementsMatch(result, []int{0})\n\n\tresult = IntersectBy(strconv.Itoa, []int{0, 1, 1})\n\tis.ElementsMatch(result, []int{0, 1})\n}\n\nfunc TestDifference(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tleft1, right1 := Difference([]int{0, 1, 2, 3, 4, 5}, []int{0, 2, 6})\n\tis.Equal([]int{1, 3, 4, 5}, left1)\n\tis.Equal([]int{6}, right1)\n\n\tleft2, right2 := Difference([]int{1, 2, 3, 4, 5}, []int{0, 6})\n\tis.Equal([]int{1, 2, 3, 4, 5}, left2)\n\tis.Equal([]int{0, 6}, right2)\n\n\tleft3, right3 := Difference([]int{0, 1, 2, 3, 4, 5}, []int{0, 1, 2, 3, 4, 5})\n\tis.Empty(left3)\n\tis.Empty(right3)\n\n\ttype myStrings []string\n\tallStrings := myStrings{\"\", \"foo\", \"bar\"}\n\ta, b := Difference(allStrings, allStrings)\n\tis.IsType(a, allStrings, \"type preserved\")\n\tis.IsType(b, allStrings, \"type preserved\")\n}\n\nfunc TestUnion(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := Union([]int{0, 1, 2, 3, 4, 5}, []int{0, 2, 10})\n\tresult2 := Union([]int{0, 1, 2, 3, 4, 5}, []int{6, 7})\n\tresult3 := Union([]int{0, 1, 2, 3, 4, 5}, []int{})\n\tresult4 := Union([]int{0, 1, 2}, []int{0, 1, 2, 3, 3})\n\tresult5 := Union([]int{0, 1, 2}, []int{0, 1, 2})\n\tresult6 := Union([]int{}, []int{})\n\tis.Equal([]int{0, 1, 2, 3, 4, 5, 10}, result1)\n\tis.Equal([]int{0, 1, 2, 3, 4, 5, 6, 7}, result2)\n\tis.Equal([]int{0, 1, 2, 3, 4, 5}, result3)\n\tis.Equal([]int{0, 1, 2, 3}, result4)\n\tis.Equal([]int{0, 1, 2}, result5)\n\tis.Empty(result6)\n\n\tresult11 := Union([]int{0, 1, 2, 3, 4, 5}, []int{0, 2, 10}, []int{0, 1, 11})\n\tresult12 := Union([]int{0, 1, 2, 3, 4, 5}, []int{6, 7}, []int{8, 9})\n\tresult13 := Union([]int{0, 1, 2, 3, 4, 5}, []int{}, []int{})\n\tresult14 := Union([]int{0, 1, 2}, []int{0, 1, 2}, []int{0, 1, 2})\n\tresult15 := Union([]int{}, []int{}, []int{})\n\tis.Equal([]int{0, 1, 2, 3, 4, 5, 10, 11}, result11)\n\tis.Equal([]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, result12)\n\tis.Equal([]int{0, 1, 2, 3, 4, 5}, result13)\n\tis.Equal([]int{0, 1, 2}, result14)\n\tis.Empty(result15)\n\n\ttype myStrings []string\n\tallStrings := myStrings{\"\", \"foo\", \"bar\"}\n\tnonempty := Union(allStrings, allStrings)\n\tis.IsType(nonempty, allStrings, \"type preserved\")\n}\n\nfunc TestWithout(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := Without([]int{0, 2, 10}, 0, 1, 2, 3, 4, 5)\n\tresult2 := Without([]int{0, 7}, 0, 1, 2, 3, 4, 5)\n\tresult3 := Without([]int{}, 0, 1, 2, 3, 4, 5)\n\tresult4 := Without([]int{0, 1, 2}, 0, 1, 2)\n\tresult5 := Without([]int{})\n\tis.Equal([]int{10}, result1)\n\tis.Equal([]int{7}, result2)\n\tis.Empty(result3)\n\tis.Empty(result4)\n\tis.Empty(result5)\n\n\ttype myStrings []string\n\tallStrings := myStrings{\"\", \"foo\", \"bar\"}\n\tnonempty := Without(allStrings, \"\")\n\tis.IsType(nonempty, allStrings, \"type preserved\")\n}\n\nfunc TestWithoutBy(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\ttype User struct {\n\t\tName string\n\t\tAge  int\n\t}\n\n\tresult1 := WithoutBy([]User{{Name: \"nick\"}, {Name: \"peter\"}},\n\t\tfunc(item User) string {\n\t\t\treturn item.Name\n\t\t}, \"nick\", \"lily\")\n\tresult2 := WithoutBy([]User{}, func(item User) int { return item.Age }, 1, 2, 3)\n\tresult3 := WithoutBy([]User{}, func(item User) string { return item.Name })\n\tis.Equal([]User{{Name: \"peter\"}}, result1)\n\tis.Empty(result2)\n\tis.Empty(result3)\n\n\ttype myStrings []string\n\tallStrings := myStrings{\"\", \"foo\", \"bar\"}\n\tnonempty := WithoutBy(allStrings, func(s string) string {\n\t\treturn s\n\t})\n\tis.IsType(nonempty, allStrings, \"type preserved\")\n}\n\nfunc TestWithoutByErr(t *testing.T) {\n\tt.Parallel()\n\n\ttype User struct {\n\t\tName string\n\t\tAge  int\n\t}\n\n\ttests := []struct {\n\t\tname          string\n\t\tinput         []User\n\t\titeratee      func(User) (string, error)\n\t\texclude       []string\n\t\twant          []User\n\t\twantErr       string\n\t\twantCallCount int\n\t}{\n\t\t{\n\t\t\tname:  \"exclude by name\",\n\t\t\tinput: []User{{Name: \"nick\"}, {Name: \"peter\"}},\n\t\t\titeratee: func(item User) (string, error) {\n\t\t\t\treturn item.Name, nil\n\t\t\t},\n\t\t\texclude:       []string{\"nick\", \"lily\"},\n\t\t\twant:          []User{{Name: \"peter\"}},\n\t\t\twantErr:       \"\",\n\t\t\twantCallCount: 2,\n\t\t},\n\t\t{\n\t\t\tname:  \"empty exclude list\",\n\t\t\tinput: []User{{Name: \"nick\"}, {Name: \"peter\"}},\n\t\t\titeratee: func(item User) (string, error) {\n\t\t\t\treturn item.Name, nil\n\t\t\t},\n\t\t\texclude:       []string{},\n\t\t\twant:          []User{{Name: \"nick\"}, {Name: \"peter\"}},\n\t\t\twantErr:       \"\",\n\t\t\twantCallCount: 2,\n\t\t},\n\t\t{\n\t\t\tname:  \"error on second element\",\n\t\t\tinput: []User{{Name: \"nick\"}, {Name: \"peter\"}, {Name: \"lily\"}},\n\t\t\titeratee: func(item User) (string, error) {\n\t\t\t\tif item.Name == \"peter\" {\n\t\t\t\t\treturn \"\", errors.New(\"peter not allowed\")\n\t\t\t\t}\n\t\t\t\treturn item.Name, nil\n\t\t\t},\n\t\t\texclude:       []string{\"nick\"},\n\t\t\twant:          nil,\n\t\t\twantErr:       \"peter not allowed\",\n\t\t\twantCallCount: 2, // stops early at error\n\t\t},\n\t\t{\n\t\t\tname:  \"error on first element\",\n\t\t\tinput: []User{{Name: \"nick\"}, {Name: \"peter\"}},\n\t\t\titeratee: func(item User) (string, error) {\n\t\t\t\treturn \"\", errors.New(\"first element error\")\n\t\t\t},\n\t\t\texclude:       []string{\"nick\"},\n\t\t\twant:          nil,\n\t\t\twantErr:       \"first element error\",\n\t\t\twantCallCount: 1,\n\t\t},\n\t\t{\n\t\t\tname:  \"all excluded\",\n\t\t\tinput: []User{{Name: \"nick\"}, {Name: \"peter\"}},\n\t\t\titeratee: func(item User) (string, error) {\n\t\t\t\treturn item.Name, nil\n\t\t\t},\n\t\t\texclude:       []string{\"nick\", \"peter\", \"lily\"},\n\t\t\twant:          []User{},\n\t\t\twantErr:       \"\",\n\t\t\twantCallCount: 2,\n\t\t},\n\t\t{\n\t\t\tname:  \"none excluded\",\n\t\t\tinput: []User{{Name: \"nick\"}, {Name: \"peter\"}},\n\t\t\titeratee: func(item User) (string, error) {\n\t\t\t\treturn item.Name, nil\n\t\t\t},\n\t\t\texclude:       []string{\"alice\"},\n\t\t\twant:          []User{{Name: \"nick\"}, {Name: \"peter\"}},\n\t\t\twantErr:       \"\",\n\t\t\twantCallCount: 2,\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\ttt := tt // capture range variable\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\tis := assert.New(t)\n\n\t\t\tcallCount := 0\n\t\t\twrappedIteratee := func(item User) (string, error) {\n\t\t\t\tcallCount++\n\t\t\t\treturn tt.iteratee(item)\n\t\t\t}\n\n\t\t\tgot, err := WithoutByErr(tt.input, wrappedIteratee, tt.exclude...)\n\n\t\t\tif tt.wantErr != \"\" {\n\t\t\t\tis.Error(err)\n\t\t\t\tis.Equal(tt.wantErr, err.Error())\n\t\t\t\tis.Nil(got)\n\t\t\t\tif tt.wantCallCount > 0 {\n\t\t\t\t\tis.Equal(tt.wantCallCount, callCount, \"should stop early on error\")\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tis.NoError(err)\n\t\t\t\tis.Equal(tt.want, got)\n\t\t\t\tis.Equal(tt.wantCallCount, callCount)\n\t\t\t}\n\t\t})\n\t}\n\n\tt.Run(\"type preserved\", func(t *testing.T) {\n\t\tt.Parallel()\n\t\tis := assert.New(t)\n\n\t\ttype myStrings []string\n\t\tallStrings := myStrings{\"\", \"foo\", \"bar\"}\n\t\tnonempty, err := WithoutByErr(allStrings, func(s string) (string, error) {\n\t\t\treturn s, nil\n\t\t})\n\n\t\tis.NoError(err)\n\t\tis.IsType(nonempty, allStrings, \"type preserved\")\n\t})\n}\n\nfunc TestWithoutEmpty(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := WithoutEmpty([]int{0, 1, 2})\n\tresult2 := WithoutEmpty([]int{1, 2})\n\tresult3 := WithoutEmpty([]int{})\n\tresult4 := WithoutEmpty([]*int{ToPtr(0), ToPtr(1), nil, ToPtr(2)})\n\tis.Equal([]int{1, 2}, result1)\n\tis.Equal([]int{1, 2}, result2)\n\tis.Empty(result3)\n\tis.Equal([]*int{ToPtr(0), ToPtr(1), ToPtr(2)}, result4)\n\n\ttype myStrings []string\n\tallStrings := myStrings{\"\", \"foo\", \"bar\"}\n\tnonempty := WithoutEmpty(allStrings)\n\tis.IsType(nonempty, allStrings, \"type preserved\")\n}\n\nfunc TestWithoutNth(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := WithoutNth([]int{5, 6, 7}, 1, 0)\n\tis.Equal([]int{7}, result1)\n\n\tresult2 := WithoutNth([]int{1, 2})\n\tis.Equal([]int{1, 2}, result2)\n\n\tresult3 := WithoutNth([]int{})\n\tis.Empty(result3)\n\n\tresult4 := WithoutNth([]int{0, 1, 2, 3}, -1, 4)\n\tis.Equal([]int{0, 1, 2, 3}, result4)\n\n\ttype myStrings []string\n\tallStrings := myStrings{\"\", \"foo\", \"bar\"}\n\tnonempty := WithoutNth(allStrings)\n\tis.IsType(nonempty, allStrings, \"type preserved\")\n\n\t// This works for non-comparable as well\n\tresult5 := WithoutNth([]func() int{func() int { return 1 }, func() int { return 2 }, func() int { return 3 }}, 1)\n\tis.Equal([]int{1, 3}, Map(result5, func(f func() int, _ int) int { return f() }))\n}\n\nfunc TestElementsMatch(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tis.False(ElementsMatch([]int{}, []int{1}))\n\tis.False(ElementsMatch([]int{1}, []int{2}))\n\tis.False(ElementsMatch([]int{1}, []int{1, 2}))\n\tis.False(ElementsMatch([]int{1, 1, 2}, []int{2, 2, 1}))\n\n\tis.True(ElementsMatch([]int{}, nil))\n\tis.True(ElementsMatch([]int{1}, []int{1}))\n\tis.True(ElementsMatch([]int{1, 1}, []int{1, 1}))\n\tis.True(ElementsMatch([]int{1, 2}, []int{2, 1}))\n\tis.True(ElementsMatch([]int{1, 1, 2}, []int{1, 2, 1}))\n}\n\nfunc TestElementsMatchBy(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\ttype someType struct {\n\t\tkey string\n\t}\n\n\tis.True(ElementsMatchBy(\n\t\t[]someType{{key: \"a\"}, {key: \"b\"}},\n\t\t[]someType{{key: \"b\"}, {key: \"a\"}},\n\t\tfunc(item someType) string { return item.key },\n\t))\n}\n"
  },
  {
    "path": "it/channel.go",
    "content": "//go:build go1.23\n\npackage it\n\nimport (\n\t\"iter\"\n\n\t\"github.com/samber/lo\"\n)\n\n// SeqToChannel returns a read-only channel of collection elements.\n// Play: https://go.dev/play/p/id3jqJPffT6\nfunc SeqToChannel[T any](bufferSize int, collection iter.Seq[T]) <-chan T {\n\tch := make(chan T, bufferSize)\n\n\tgo func() {\n\t\tfor item := range collection {\n\t\t\tch <- item\n\t\t}\n\n\t\tclose(ch)\n\t}()\n\n\treturn ch\n}\n\n// SeqToChannel2 returns a read-only channel of collection elements.\n// Play: https://go.dev/play/p/rpJdVnXUaG-\nfunc SeqToChannel2[K, V any](bufferSize int, collection iter.Seq2[K, V]) <-chan lo.Tuple2[K, V] {\n\tch := make(chan lo.Tuple2[K, V], bufferSize)\n\n\tgo func() {\n\t\tfor k, v := range collection {\n\t\t\tch <- lo.Tuple2[K, V]{A: k, B: v}\n\t\t}\n\n\t\tclose(ch)\n\t}()\n\n\treturn ch\n}\n\n// ChannelToSeq returns a sequence built from channels items. Blocks until channel closes.\n// Play: https://go.dev/play/p/IXqSs2Ooqpm\nfunc ChannelToSeq[T any](ch <-chan T) iter.Seq[T] {\n\treturn func(yield func(T) bool) {\n\t\tfor item := range ch {\n\t\t\tif !yield(item) {\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "it/channel_test.go",
    "content": "//go:build go1.23\n\npackage it\n\nimport (\n\t\"maps\"\n\t\"slices\"\n\t\"testing\"\n\n\t\"github.com/samber/lo\"\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestSeqToChannel(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tch := SeqToChannel(2, values(1, 2, 3))\n\n\tr1, ok1 := <-ch\n\tr2, ok2 := <-ch\n\tr3, ok3 := <-ch\n\tis.True(ok1)\n\tis.Equal(1, r1)\n\tis.True(ok2)\n\tis.Equal(2, r2)\n\tis.True(ok3)\n\tis.Equal(3, r3)\n\n\t_, ok4 := <-ch\n\tis.False(ok4)\n}\n\nfunc TestSeqToChannel2(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tch := SeqToChannel2(2, maps.All(map[string]int{\"a\": 1, \"b\": 2, \"c\": 3}))\n\n\tr1, ok1 := <-ch\n\tr2, ok2 := <-ch\n\tr3, ok3 := <-ch\n\tis.True(ok1)\n\tis.True(ok2)\n\tis.True(ok3)\n\tis.ElementsMatch([]lo.Tuple2[string, int]{{A: \"a\", B: 1}, {A: \"b\", B: 2}, {A: \"c\", B: 3}}, []lo.Tuple2[string, int]{r1, r2, r3})\n\n\t_, ok4 := <-ch\n\tis.False(ok4)\n}\n\nfunc TestChannelToSeq(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tch := SeqToChannel(2, values(1, 2, 3))\n\titems := ChannelToSeq(ch)\n\n\tis.Equal([]int{1, 2, 3}, slices.Collect(items))\n}\n"
  },
  {
    "path": "it/find.go",
    "content": "//go:build go1.23\n\npackage it\n\nimport (\n\t\"iter\"\n\t\"slices\"\n\t\"time\"\n\n\t\"github.com/samber/lo\"\n\t\"github.com/samber/lo/internal/constraints\"\n\t\"github.com/samber/lo/internal/xrand\"\n)\n\n// IndexOf returns the index at which the first occurrence of a value is found in a sequence or -1\n// if the value cannot be found.\n// Will iterate through the entire sequence if element is not found.\n// Play: https://go.dev/play/p/1OZHU2yfb-m\nfunc IndexOf[T comparable](collection iter.Seq[T], element T) int {\n\tvar i int\n\tfor item := range collection {\n\t\tif item == element {\n\t\t\treturn i\n\t\t}\n\t\ti++\n\t}\n\n\treturn -1\n}\n\n// LastIndexOf returns the index at which the last occurrence of a value is found in a sequence or -1\n// if the value cannot be found.\n// Will iterate through the entire sequence.\n// Play: https://go.dev/play/p/QPATR3VC5wT\nfunc LastIndexOf[T comparable](collection iter.Seq[T], element T) int {\n\tindex := -1\n\tvar i int\n\tfor item := range collection {\n\t\tif item == element {\n\t\t\tindex = i\n\t\t}\n\t\ti++\n\t}\n\n\treturn index\n}\n\n// HasPrefix returns true if the collection has the prefix.\n// Will iterate at most the size of prefix.\n// Play: https://go.dev/play/p/Fyj6uq-G5IH\nfunc HasPrefix[T comparable](collection iter.Seq[T], prefix ...T) bool {\n\tif len(prefix) == 0 {\n\t\treturn true\n\t}\n\n\tvar i int\n\n\tfor item := range collection {\n\t\tif item != prefix[i] {\n\t\t\treturn false\n\t\t}\n\t\ti++\n\t\tif i == len(prefix) {\n\t\t\treturn true\n\t\t}\n\t}\n\n\treturn false\n}\n\n// HasSuffix returns true if the collection has the suffix.\n// Will iterate through the entire sequence and allocate a slice the size of suffix.\n// Play: https://go.dev/play/p/r6bF9Rmq5S0\nfunc HasSuffix[T comparable](collection iter.Seq[T], suffix ...T) bool {\n\tif len(suffix) == 0 {\n\t\treturn true\n\t}\n\n\tn := len(suffix)\n\tbuf := make([]T, n)\n\tvar i int\n\n\tfor buf[i%n] = range collection {\n\t\ti++\n\t}\n\n\tif i < n {\n\t\treturn false\n\t}\n\n\tfor j := range suffix {\n\t\tif suffix[j] != buf[(i+j)%n] {\n\t\t\treturn false\n\t\t}\n\t}\n\n\treturn true\n}\n\n// Find searches for an element in a sequence based on a predicate. Returns element and true if element was found.\n// Will iterate through the entire sequence if predicate never returns true.\n// Play: https://go.dev/play/p/4w28pF_l58a\nfunc Find[T any](collection iter.Seq[T], predicate func(item T) bool) (T, bool) {\n\tfor item := range collection {\n\t\tif predicate(item) {\n\t\t\treturn item, true\n\t\t}\n\t}\n\n\treturn lo.Empty[T](), false\n}\n\n// FindIndexOf searches for an element in a sequence based on a predicate and returns the index and true.\n// Returns -1 and false if the element is not found.\n// Will iterate through the entire sequence if predicate never returns true.\n// Play: https://go.dev/play/p/ihchBAEkhXO\nfunc FindIndexOf[T any](collection iter.Seq[T], predicate func(item T) bool) (T, int, bool) {\n\tvar i int\n\tfor item := range collection {\n\t\tif predicate(item) {\n\t\t\treturn item, i, true\n\t\t}\n\t\ti++\n\t}\n\n\treturn lo.Empty[T](), -1, false\n}\n\n// FindLastIndexOf searches for the last element in a sequence based on a predicate and returns the index and true.\n// Returns -1 and false if the element is not found.\n// Will iterate through the entire sequence.\n// Play: https://go.dev/play/p/ezz6hXaC4Md\nfunc FindLastIndexOf[T any](collection iter.Seq[T], predicate func(item T) bool) (T, int, bool) {\n\tvar result T\n\tindex := -1\n\tvar ok bool\n\n\tvar i int\n\tfor item := range collection {\n\t\tif predicate(item) {\n\t\t\tresult = item\n\t\t\tindex = i\n\t\t\tok = true\n\t\t}\n\t\ti++\n\t}\n\n\treturn result, index, ok\n}\n\n// FindOrElse searches for an element in a sequence based on a predicate. Returns the element if found or a given fallback value otherwise.\n// Will iterate through the entire sequence if predicate never returns true.\n// Play: https://go.dev/play/p/1harvaiGMfI\nfunc FindOrElse[T any](collection iter.Seq[T], fallback T, predicate func(item T) bool) T {\n\tif result, ok := Find(collection, predicate); ok {\n\t\treturn result\n\t}\n\n\treturn fallback\n}\n\n// FindUniques returns a sequence with all the elements that appear in the collection only once.\n// The order of result values is determined by the order they occur in the collection.\n// Will iterate through the entire sequence before yielding and allocate a map large enough to hold all distinct elements.\n// Long heterogeneous input sequences can cause excessive memory usage.\n// Play: https://go.dev/play/p/O8dwXEbT56F\nfunc FindUniques[T comparable, I ~func(func(T) bool)](collection I) I {\n\treturn FindUniquesBy(collection, func(item T) T { return item })\n}\n\n// FindUniquesBy returns a sequence with all the elements that appear in the collection only once.\n// The order of result values is determined by the order they occur in the sequence. A transform function is\n// invoked for each element in the sequence to generate the criterion by which uniqueness is computed.\n// Will iterate through the entire sequence before yielding and allocate a map large enough to hold all distinct transformed elements.\n// Long heterogeneous input sequences can cause excessive memory usage.\n// Play: https://go.dev/play/p/TiwGIzeDuML\nfunc FindUniquesBy[T any, U comparable, I ~func(func(T) bool)](collection I, transform func(item T) U) I {\n\treturn func(yield func(T) bool) {\n\t\tisDupl := make(map[U]bool)\n\n\t\tfor item := range collection {\n\t\t\tkey := transform(item)\n\n\t\t\tduplicated, seen := isDupl[key]\n\t\t\tif !duplicated {\n\t\t\t\tisDupl[key] = seen\n\t\t\t}\n\t\t}\n\n\t\tfor item := range collection {\n\t\t\tkey := transform(item)\n\n\t\t\tif duplicated := isDupl[key]; !duplicated && !yield(item) {\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}\n}\n\n// FindDuplicates returns a sequence with the first occurrence of each duplicated element in the collection.\n// The order of result values is determined by the order duplicates occur in the collection.\n// Will allocate a map large enough to hold all distinct elements.\n// Long heterogeneous input sequences can cause excessive memory usage.\n// Play: https://go.dev/play/p/dw-VLQXKijT\nfunc FindDuplicates[T comparable, I ~func(func(T) bool)](collection I) I {\n\treturn FindDuplicatesBy(collection, func(item T) T { return item })\n}\n\n// FindDuplicatesBy returns a sequence with the first occurrence of each duplicated element in the collection.\n// The order of result values is determined by the order duplicates occur in the sequence. A transform function is\n// invoked for each element in the sequence to generate the criterion by which uniqueness is computed.\n// Will allocate a map large enough to hold all distinct transformed elements.\n// Long heterogeneous input sequences can cause excessive memory usage.\n// Play: https://go.dev/play/p/tm1tZdC93OH\nfunc FindDuplicatesBy[T any, U comparable, I ~func(func(T) bool)](collection I, transform func(item T) U) I {\n\treturn func(yield func(T) bool) {\n\t\tisDupl := make(map[U]lo.Tuple2[T, bool])\n\n\t\tfor item := range collection {\n\t\t\tkey := transform(item)\n\n\t\t\tif duplicated, ok := isDupl[key]; !ok {\n\t\t\t\tisDupl[key] = lo.Tuple2[T, bool]{A: item}\n\t\t\t} else if !duplicated.B {\n\t\t\t\tif !yield(duplicated.A) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tisDupl[key] = lo.Tuple2[T, bool]{A: item, B: true}\n\t\t\t}\n\t\t}\n\t}\n}\n\n// Min search the minimum value of a collection.\n// Returns zero value when the collection is empty.\n// Will iterate through the entire sequence.\n// Play: https://go.dev/play/p/0VihyYEaM-M\nfunc Min[T constraints.Ordered](collection iter.Seq[T]) T {\n\treturn MinBy(collection, func(a, b T) bool { return a < b })\n}\n\n// MinIndex search the minimum value of a collection and the index of the minimum value.\n// Returns (zero value, -1) when the collection is empty.\n// Will iterate through the entire sequence.\n// Play: https://go.dev/play/p/70ncPxECj6l\nfunc MinIndex[T constraints.Ordered](collection iter.Seq[T]) (T, int) {\n\treturn MinIndexBy(collection, func(a, b T) bool { return a < b })\n}\n\n// MinBy search the minimum value of a collection using the given comparison function.\n// If several values of the collection are equal to the smallest value, returns the first such value.\n// Returns zero value when the collection is empty.\n// Will iterate through the entire sequence.\n// Play: https://go.dev/play/p/J5koo8khN-g\nfunc MinBy[T any](collection iter.Seq[T], comparison func(a, b T) bool) T {\n\tfirst := true\n\tvar mIn T\n\n\tfor item := range collection {\n\t\tif first {\n\t\t\tmIn = item\n\t\t\tfirst = false\n\t\t} else if comparison(item, mIn) {\n\t\t\tmIn = item\n\t\t}\n\t}\n\n\treturn mIn\n}\n\n// MinIndexBy search the minimum value of a collection using the given comparison function and the index of the minimum value.\n// If several values of the collection are equal to the smallest value, returns the first such value.\n// Returns (zero value, -1) when the collection is empty.\n// Will iterate through the entire sequence.\n// Play: https://go.dev/play/p/blldzWJpqVa\nfunc MinIndexBy[T any](collection iter.Seq[T], comparison func(a, b T) bool) (T, int) {\n\tvar mIn T\n\tindex := -1\n\n\tvar i int\n\tfor item := range collection {\n\t\tif i == 0 || comparison(item, mIn) {\n\t\t\tmIn = item\n\t\t\tindex = i\n\t\t}\n\t\ti++\n\t}\n\n\treturn mIn, index\n}\n\n// Earliest search the minimum time.Time of a collection.\n// Returns zero value when the collection is empty.\n// Will iterate through the entire sequence.\n// Play: https://go.dev/play/p/fI6_S10H7Py\nfunc Earliest(times iter.Seq[time.Time]) time.Time {\n\treturn MinBy(times, func(a, b time.Time) bool { return a.Before(b) })\n}\n\n// EarliestBy search the minimum time.Time of a collection using the given transform function.\n// Returns zero value when the collection is empty.\n// Will iterate through the entire sequence.\n// Play: https://go.dev/play/p/y_Pf3Jmw-B4\nfunc EarliestBy[T any](collection iter.Seq[T], transform func(item T) time.Time) T {\n\treturn MinBy(collection, func(a, b T) bool { return transform(a).Before(transform(b)) })\n}\n\n// Max searches the maximum value of a collection.\n// Returns zero value when the collection is empty.\n// Will iterate through the entire sequence.\n// Play: https://go.dev/play/p/C2ZtW2bsBZ6\nfunc Max[T constraints.Ordered](collection iter.Seq[T]) T {\n\treturn MaxBy(collection, func(a, b T) bool { return a > b })\n}\n\n// MaxIndex searches the maximum value of a collection and the index of the maximum value.\n// Returns (zero value, -1) when the collection is empty.\n// Will iterate through the entire sequence.\n// Play: https://go.dev/play/p/zeu2wUvhl5e\nfunc MaxIndex[T constraints.Ordered](collection iter.Seq[T]) (T, int) {\n\treturn MaxIndexBy(collection, func(a, b T) bool { return a > b })\n}\n\n// MaxBy search the maximum value of a collection using the given comparison function.\n// If several values of the collection are equal to the greatest value, returns the first such value.\n// Returns zero value when the collection is empty.\n// Will iterate through the entire sequence.\n// Play: https://go.dev/play/p/yBhXFJb5oxC\nfunc MaxBy[T any](collection iter.Seq[T], comparison func(a, b T) bool) T {\n\tfirst := true\n\tvar mAx T\n\n\tfor item := range collection {\n\t\tif first {\n\t\t\tmAx = item\n\t\t\tfirst = false\n\t\t} else if comparison(item, mAx) {\n\t\t\tmAx = item\n\t\t}\n\t}\n\n\treturn mAx\n}\n\n// MaxIndexBy search the maximum value of a collection using the given comparison function and the index of the maximum value.\n// If several values of the collection are equal to the greatest value, returns the first such value.\n// Returns (zero value, -1) when the collection is empty.\n// Will iterate through the entire sequence.\n// Play: https://go.dev/play/p/MXyE6BTILjx\nfunc MaxIndexBy[T any](collection iter.Seq[T], comparison func(a, b T) bool) (T, int) {\n\tvar mAx T\n\tindex := -1\n\n\tvar i int\n\tfor item := range collection {\n\t\tif i == 0 || comparison(item, mAx) {\n\t\t\tmAx = item\n\t\t\tindex = i\n\t\t}\n\t\ti++\n\t}\n\n\treturn mAx, index\n}\n\n// Latest search the maximum time.Time of a collection.\n// Returns zero value when the collection is empty.\n// Will iterate through the entire sequence.\n// Play: https://go.dev/play/p/r5Yq6ATSHoH\nfunc Latest(times iter.Seq[time.Time]) time.Time {\n\treturn MaxBy(times, func(a, b time.Time) bool { return a.After(b) })\n}\n\n// LatestBy search the maximum time.Time of a collection using the given transform function.\n// Returns zero value when the collection is empty.\n// Will iterate through the entire sequence.\n// Play: https://go.dev/play/p/o_daRzHrDUU\nfunc LatestBy[T any](collection iter.Seq[T], transform func(item T) time.Time) T {\n\treturn MaxBy(collection, func(a, b T) bool { return transform(a).After(transform(b)) })\n}\n\n// First returns the first element of a collection and check for availability of the first element.\n// Will iterate at most once.\n// Play: https://go.dev/play/p/EhNyrc8jPfY\nfunc First[T any](collection iter.Seq[T]) (T, bool) {\n\tfor item := range collection {\n\t\treturn item, true\n\t}\n\n\treturn lo.Empty[T](), false\n}\n\n// FirstOrEmpty returns the first element of a collection or zero value if empty.\n// Will iterate at most once.\n// Play: https://go.dev/play/p/NTUTgPCfevx\nfunc FirstOrEmpty[T any](collection iter.Seq[T]) T {\n\ti, _ := First(collection)\n\treturn i\n}\n\n// FirstOr returns the first element of a collection or the fallback value if empty.\n// Will iterate at most once.\n// Play: https://go.dev/play/p/wGFXI5NHkE2\nfunc FirstOr[T any](collection iter.Seq[T], fallback T) T {\n\tif i, ok := First(collection); ok {\n\t\treturn i\n\t}\n\n\treturn fallback\n}\n\n// Last returns the last element of a collection or error if empty.\n// Will iterate through the entire sequence.\n// Play: https://go.dev/play/p/eGZV-sSmn_Q\nfunc Last[T any](collection iter.Seq[T]) (T, bool) {\n\tvar t T\n\tvar ok bool\n\tfor item := range collection {\n\t\tt = item\n\t\tok = true\n\t}\n\n\treturn t, ok\n}\n\n// LastOrEmpty returns the last element of a collection or zero value if empty.\n// Will iterate through the entire sequence.\n// Play: https://go.dev/play/p/teODFK4YqM4\nfunc LastOrEmpty[T any](collection iter.Seq[T]) T {\n\ti, _ := Last(collection)\n\treturn i\n}\n\n// LastOr returns the last element of a collection or the fallback value if empty.\n// Will iterate through the entire sequence.\n// Play: https://go.dev/play/p/HNubjW2Mrxs\nfunc LastOr[T any](collection iter.Seq[T], fallback T) T {\n\tif i, ok := Last(collection); ok {\n\t\treturn i\n\t}\n\n\treturn fallback\n}\n\n// Nth returns the element at index `nth` of collection. An error is returned when nth is out of bounds.\n// Will iterate n times through the sequence.\n// Play: https://go.dev/play/p/FqgCobsKqva\nfunc Nth[T any, N constraints.Integer](collection iter.Seq[T], nth N) (T, error) {\n\tvalue, ok := seqNth(collection, nth)\n\n\treturn value, lo.Validate(ok, \"nth: %d out of bounds\", nth)\n}\n\nfunc seqNth[T any, N constraints.Integer](collection iter.Seq[T], nth N) (T, bool) {\n\tif nth >= 0 {\n\t\tvar i N\n\t\tfor item := range collection {\n\t\t\tif i == nth {\n\t\t\t\treturn item, true\n\t\t\t}\n\t\t\ti++\n\t\t}\n\t}\n\n\treturn lo.Empty[T](), false\n}\n\n// NthOr returns the element at index `nth` of collection.\n// If `nth` is out of bounds, it returns the fallback value instead of an error.\n// Will iterate n times through the sequence.\n// Play: https://go.dev/play/p/MNweuhpy4Ym\nfunc NthOr[T any, N constraints.Integer](collection iter.Seq[T], nth N, fallback T) T {\n\tvalue, ok := seqNth(collection, nth)\n\tif !ok {\n\t\treturn fallback\n\t}\n\treturn value\n}\n\n// NthOrEmpty returns the element at index `nth` of collection.\n// If `nth` is out of bounds, it returns the zero value (empty value) for that type.\n// Will iterate n times through the sequence.\n// Play: https://go.dev/play/p/pC0Zhu3EUhe\nfunc NthOrEmpty[T any, N constraints.Integer](collection iter.Seq[T], nth N) T {\n\tvalue, _ := seqNth(collection, nth)\n\treturn value\n}\n\n// Sample returns a random item from collection.\n// Will iterate through the entire sequence and allocate a slice large enough to hold all elements.\n// Long input sequences can cause excessive memory usage.\n// Play: https://go.dev/play/p/YDJVX0UXYDi\nfunc Sample[T any](collection iter.Seq[T]) T {\n\treturn SampleBy(collection, xrand.IntN)\n}\n\n// SampleBy returns a random item from collection, using randomIntGenerator as the random index generator.\n// Will iterate through the entire sequence and allocate a slice large enough to hold all elements.\n// Long input sequences can cause excessive memory usage.\n// Play: https://go.dev/play/p/QQooySxORib\nfunc SampleBy[T any](collection iter.Seq[T], randomIntGenerator func(int) int) T {\n\tslice := slices.Collect(collection)\n\treturn lo.SampleBy(slice, randomIntGenerator)\n}\n\n// Samples returns N random unique items from collection.\n// Will iterate through the entire sequence and allocate a slice large enough to hold all elements.\n// Long input sequences can cause excessive memory usage.\n// Play: https://go.dev/play/p/GUTFx9LQ8pP\nfunc Samples[T any, I ~func(func(T) bool)](collection I, count int) I {\n\treturn SamplesBy(collection, count, xrand.IntN)\n}\n\n// SamplesBy returns N random unique items from collection, using randomIntGenerator as the random index generator.\n// Will iterate through the entire sequence and allocate a slice large enough to hold all elements.\n// Long input sequences can cause excessive memory usage.\n// Play: https://go.dev/play/p/fX2FEtixrVG\nfunc SamplesBy[T any, I ~func(func(T) bool)](collection I, count int, randomIntGenerator func(int) int) I {\n\tslice := slices.Collect(iter.Seq[T](collection))\n\tseq := lo.SamplesBy(slice, count, randomIntGenerator)\n\treturn I(slices.Values(seq))\n}\n"
  },
  {
    "path": "it/find_example_test.go",
    "content": "//go:build go1.23\n\npackage it\n\nimport (\n\t\"fmt\"\n\t\"slices\"\n\t\"time\"\n)\n\nfunc ExampleIndexOf() {\n\tlist := slices.Values([]string{\"foo\", \"bar\", \"baz\"})\n\n\tresult := IndexOf(list, \"bar\")\n\n\tfmt.Printf(\"%d\", result)\n\t// Output: 1\n}\n\nfunc ExampleIndexOf_notFound() {\n\tlist := slices.Values([]string{\"foo\", \"bar\", \"baz\"})\n\n\tresult := IndexOf(list, \"qux\")\n\n\tfmt.Printf(\"%d\", result)\n\t// Output: -1\n}\n\nfunc ExampleLastIndexOf() {\n\tlist := slices.Values([]string{\"foo\", \"bar\", \"baz\", \"bar\"})\n\n\tresult := LastIndexOf(list, \"bar\")\n\n\tfmt.Printf(\"%d\", result)\n\t// Output: 3\n}\n\nfunc ExampleLastIndexOf_notFound() {\n\tlist := slices.Values([]string{\"foo\", \"bar\", \"baz\"})\n\n\tresult := LastIndexOf(list, \"qux\")\n\n\tfmt.Printf(\"%d\", result)\n\t// Output: -1\n}\n\nfunc ExampleFind() {\n\ttype User struct {\n\t\tName string\n\t\tAge  int\n\t}\n\n\tusers := slices.Values([]User{\n\t\t{Name: \"Alice\", Age: 25},\n\t\t{Name: \"Bob\", Age: 30},\n\t\t{Name: \"Charlie\", Age: 35},\n\t})\n\n\tresult, found := Find(users, func(user User) bool {\n\t\treturn user.Age > 30\n\t})\n\n\tfmt.Printf(\"%s %t\", result.Name, found)\n\t// Output: Charlie true\n}\n\nfunc ExampleFind_notFound() {\n\tlist := slices.Values([]int{1, 2, 3, 4, 5})\n\n\tresult, found := Find(list, func(n int) bool {\n\t\treturn n > 10\n\t})\n\n\tfmt.Printf(\"%d %t\", result, found)\n\t// Output: 0 false\n}\n\nfunc ExampleFindIndexOf() {\n\tlist := slices.Values([]int{1, 2, 3, 4, 5})\n\n\tresult, index, found := FindIndexOf(list, func(n int) bool {\n\t\treturn n > 2\n\t})\n\n\tfmt.Printf(\"%d %d %t\", result, index, found)\n\t// Output: 3 2 true\n}\n\nfunc ExampleFindIndexOf_notFound() {\n\tlist := slices.Values([]int{1, 2, 3, 4, 5})\n\n\tresult, index, found := FindIndexOf(list, func(n int) bool {\n\t\treturn n > 10\n\t})\n\n\tfmt.Printf(\"%d %d %t\", result, index, found)\n\t// Output: 0 -1 false\n}\n\nfunc ExampleFindLastIndexOf() {\n\tlist := slices.Values([]int{1, 2, 3, 4, 3, 5})\n\n\tresult, index, found := FindLastIndexOf(list, func(n int) bool {\n\t\treturn n == 3\n\t})\n\n\tfmt.Printf(\"%d %d %t\", result, index, found)\n\t// Output: 3 4 true\n}\n\nfunc ExampleFindLastIndexOf_notFound() {\n\tlist := slices.Values([]int{1, 2, 3, 4, 5})\n\n\tresult, index, found := FindLastIndexOf(list, func(n int) bool {\n\t\treturn n > 10\n\t})\n\n\tfmt.Printf(\"%d %d %t\", result, index, found)\n\t// Output: 0 -1 false\n}\n\nfunc ExampleFindOrElse() {\n\tlist := slices.Values([]int{1, 2, 3, 4, 5})\n\n\tresult := FindOrElse(list, -1, func(n int) bool {\n\t\treturn n > 10\n\t})\n\n\tfmt.Printf(\"%d\", result)\n\t// Output: -1\n}\n\nfunc ExampleFindOrElse_found() {\n\tlist := slices.Values([]int{1, 2, 3, 4, 5})\n\n\tresult := FindOrElse(list, -1, func(n int) bool {\n\t\treturn n > 3\n\t})\n\n\tfmt.Printf(\"%d\", result)\n\t// Output: 4\n}\n\nfunc ExampleFindUniques() {\n\tlist := slices.Values([]int{1, 2, 2, 3, 3, 3, 4, 5})\n\n\tresult := FindUniques(list)\n\n\tfmt.Printf(\"%v\", slices.Collect(result))\n\t// Output: [1 4 5]\n}\n\nfunc ExampleFindUniquesBy() {\n\ttype User struct {\n\t\tName string\n\t\tAge  int\n\t}\n\n\tusers := slices.Values([]User{\n\t\t{Name: \"Alice\", Age: 25},\n\t\t{Name: \"Bob\", Age: 30},\n\t\t{Name: \"Charlie\", Age: 25},\n\t\t{Name: \"David\", Age: 30},\n\t\t{Name: \"Eve\", Age: 35},\n\t})\n\n\tresult := FindUniquesBy(users, func(user User) int {\n\t\treturn user.Age\n\t})\n\n\tfmt.Printf(\"%d\", len(slices.Collect(result)))\n\t// Output: 1\n}\n\nfunc ExampleFindDuplicates() {\n\tlist := slices.Values([]int{1, 2, 2, 3, 3, 3, 4, 5})\n\n\tresult := FindDuplicates(list)\n\n\tfmt.Printf(\"%v\", slices.Collect(result))\n\t// Output: [2 3]\n}\n\nfunc ExampleFindDuplicatesBy() {\n\ttype User struct {\n\t\tName string\n\t\tAge  int\n\t}\n\n\tusers := slices.Values([]User{\n\t\t{Name: \"Alice\", Age: 25},\n\t\t{Name: \"Bob\", Age: 30},\n\t\t{Name: \"Charlie\", Age: 25},\n\t\t{Name: \"David\", Age: 30},\n\t\t{Name: \"Eve\", Age: 35},\n\t})\n\n\tresult := FindDuplicatesBy(users, func(user User) int {\n\t\treturn user.Age\n\t})\n\n\tfmt.Printf(\"%d\", len(slices.Collect(result)))\n\t// Output: 2\n}\n\nfunc ExampleMin() {\n\tlist := slices.Values([]int{3, 1, 4, 1, 5, 9, 2, 6})\n\n\tresult := Min(list)\n\n\tfmt.Printf(\"%d\", result)\n\t// Output: 1\n}\n\nfunc ExampleMin_empty() {\n\tlist := slices.Values([]int{})\n\n\tresult := Min(list)\n\n\tfmt.Printf(\"%d\", result)\n\t// Output: 0\n}\n\nfunc ExampleMinIndex() {\n\tlist := slices.Values([]int{3, 1, 4, 1, 5, 9, 2, 6})\n\n\tresult, index := MinIndex(list)\n\n\tfmt.Printf(\"%d %d\", result, index)\n\t// Output: 1 1\n}\n\nfunc ExampleMinIndex_empty() {\n\tlist := slices.Values([]int{})\n\n\tresult, index := MinIndex(list)\n\n\tfmt.Printf(\"%d %d\", result, index)\n\t// Output: 0 -1\n}\n\nfunc ExampleMinBy() {\n\ttype User struct {\n\t\tName string\n\t\tAge  int\n\t}\n\n\tusers := slices.Values([]User{\n\t\t{Name: \"Alice\", Age: 25},\n\t\t{Name: \"Bob\", Age: 30},\n\t\t{Name: \"Charlie\", Age: 35},\n\t})\n\n\tresult := MinBy(users, func(a, b User) bool {\n\t\treturn a.Age < b.Age\n\t})\n\n\tfmt.Printf(\"%s\", result.Name)\n\t// Output: Alice\n}\n\nfunc ExampleMinIndexBy() {\n\ttype User struct {\n\t\tName string\n\t\tAge  int\n\t}\n\n\tusers := slices.Values([]User{\n\t\t{Name: \"Alice\", Age: 25},\n\t\t{Name: \"Bob\", Age: 30},\n\t\t{Name: \"Charlie\", Age: 35},\n\t})\n\n\tresult, index := MinIndexBy(users, func(a, b User) bool {\n\t\treturn a.Age < b.Age\n\t})\n\n\tfmt.Printf(\"%s %d\", result.Name, index)\n\t// Output: Alice 0\n}\n\nfunc ExampleEarliest() {\n\tnow := time.Now()\n\tpast := now.Add(-time.Hour)\n\tfuture := now.Add(time.Hour)\n\n\tresult := Earliest(slices.Values([]time.Time{future, now, past}))\n\n\tfmt.Printf(\"%t\", result.Equal(past))\n\t// Output: true\n}\n\nfunc ExampleEarliestBy() {\n\ttype Event struct {\n\t\tName string\n\t\tTime time.Time\n\t}\n\n\tnow := time.Now()\n\tevents := slices.Values([]Event{\n\t\t{Name: \"Event A\", Time: now.Add(time.Hour)},\n\t\t{Name: \"Event B\", Time: now},\n\t\t{Name: \"Event C\", Time: now.Add(-time.Hour)},\n\t})\n\n\tresult := EarliestBy(events, func(event Event) time.Time {\n\t\treturn event.Time\n\t})\n\n\tfmt.Printf(\"%s\", result.Name)\n\t// Output: Event C\n}\n\nfunc ExampleMax() {\n\tlist := slices.Values([]int{3, 1, 4, 1, 5, 9, 2, 6})\n\n\tresult := Max(list)\n\n\tfmt.Printf(\"%d\", result)\n\t// Output: 9\n}\n\nfunc ExampleMax_empty() {\n\tlist := slices.Values([]int{})\n\n\tresult := Max(list)\n\n\tfmt.Printf(\"%d\", result)\n\t// Output: 0\n}\n\nfunc ExampleMaxIndex() {\n\tlist := slices.Values([]int{3, 1, 4, 1, 5, 9, 2, 6})\n\n\tresult, index := MaxIndex(list)\n\n\tfmt.Printf(\"%d %d\", result, index)\n\t// Output: 9 5\n}\n\nfunc ExampleMaxIndex_empty() {\n\tlist := slices.Values([]int{})\n\n\tresult, index := MaxIndex(list)\n\n\tfmt.Printf(\"%d %d\", result, index)\n\t// Output: 0 -1\n}\n\nfunc ExampleMaxBy() {\n\ttype User struct {\n\t\tName string\n\t\tAge  int\n\t}\n\n\tusers := slices.Values([]User{\n\t\t{Name: \"Alice\", Age: 25},\n\t\t{Name: \"Bob\", Age: 30},\n\t\t{Name: \"Charlie\", Age: 35},\n\t})\n\n\tresult := MaxBy(users, func(a, b User) bool {\n\t\treturn a.Age > b.Age\n\t})\n\n\tfmt.Printf(\"%s\", result.Name)\n\t// Output: Charlie\n}\n\nfunc ExampleMaxIndexBy() {\n\ttype User struct {\n\t\tName string\n\t\tAge  int\n\t}\n\n\tusers := slices.Values([]User{\n\t\t{Name: \"Alice\", Age: 25},\n\t\t{Name: \"Bob\", Age: 30},\n\t\t{Name: \"Charlie\", Age: 35},\n\t})\n\n\tresult, index := MaxIndexBy(users, func(a, b User) bool {\n\t\treturn a.Age > b.Age\n\t})\n\n\tfmt.Printf(\"%s %d\", result.Name, index)\n\t// Output: Charlie 2\n}\n\nfunc ExampleLatest() {\n\tnow := time.Now()\n\tpast := now.Add(-time.Hour)\n\tfuture := now.Add(time.Hour)\n\n\tresult := Latest(slices.Values([]time.Time{future, now, past}))\n\n\tfmt.Printf(\"%t\", result.Equal(future))\n\t// Output: true\n}\n\nfunc ExampleLatestBy() {\n\ttype Event struct {\n\t\tName string\n\t\tTime time.Time\n\t}\n\n\tnow := time.Now()\n\tevents := slices.Values([]Event{\n\t\t{Name: \"Event A\", Time: now.Add(time.Hour)},\n\t\t{Name: \"Event B\", Time: now},\n\t\t{Name: \"Event C\", Time: now.Add(-time.Hour)},\n\t})\n\n\tresult := LatestBy(events, func(event Event) time.Time {\n\t\treturn event.Time\n\t})\n\n\tfmt.Printf(\"%s\", result.Name)\n\t// Output: Event A\n}\n\nfunc ExampleFirst() {\n\tlist := slices.Values([]int{1, 2, 3, 4, 5})\n\n\tresult, found := First(list)\n\n\tfmt.Printf(\"%d %t\", result, found)\n\t// Output: 1 true\n}\n\nfunc ExampleFirst_empty() {\n\tlist := slices.Values([]int{})\n\n\tresult, found := First(list)\n\n\tfmt.Printf(\"%d %t\", result, found)\n\t// Output: 0 false\n}\n\nfunc ExampleFirstOrEmpty() {\n\tlist := slices.Values([]int{1, 2, 3, 4, 5})\n\n\tresult := FirstOrEmpty(list)\n\n\tfmt.Printf(\"%d\", result)\n\t// Output: 1\n}\n\nfunc ExampleFirstOrEmpty_empty() {\n\tlist := slices.Values([]int{})\n\n\tresult := FirstOrEmpty(list)\n\n\tfmt.Printf(\"%d\", result)\n\t// Output: 0\n}\n\nfunc ExampleFirstOr() {\n\tlist := slices.Values([]int{1, 2, 3, 4, 5})\n\n\tresult := FirstOr(list, -1)\n\n\tfmt.Printf(\"%d\", result)\n\t// Output: 1\n}\n\nfunc ExampleFirstOr_empty() {\n\tlist := slices.Values([]int{})\n\n\tresult := FirstOr(list, -1)\n\n\tfmt.Printf(\"%d\", result)\n\t// Output: -1\n}\n\nfunc ExampleLast() {\n\tlist := slices.Values([]int{1, 2, 3, 4, 5})\n\n\tresult, found := Last(list)\n\n\tfmt.Printf(\"%d %t\", result, found)\n\t// Output: 5 true\n}\n\nfunc ExampleLast_empty() {\n\tlist := slices.Values([]int{})\n\n\tresult, found := Last(list)\n\n\tfmt.Printf(\"%d %t\", result, found)\n\t// Output: 0 false\n}\n\nfunc ExampleLastOrEmpty() {\n\tlist := slices.Values([]int{1, 2, 3, 4, 5})\n\n\tresult := LastOrEmpty(list)\n\n\tfmt.Printf(\"%d\", result)\n\t// Output: 5\n}\n\nfunc ExampleLastOrEmpty_empty() {\n\tlist := slices.Values([]int{})\n\n\tresult := LastOrEmpty(list)\n\n\tfmt.Printf(\"%d\", result)\n\t// Output: 0\n}\n\nfunc ExampleLastOr() {\n\tlist := slices.Values([]int{1, 2, 3, 4, 5})\n\n\tresult := LastOr(list, -1)\n\n\tfmt.Printf(\"%d\", result)\n\t// Output: 5\n}\n\nfunc ExampleLastOr_empty() {\n\tlist := slices.Values([]int{})\n\n\tresult := LastOr(list, -1)\n\n\tfmt.Printf(\"%d\", result)\n\t// Output: -1\n}\n\nfunc ExampleNth() {\n\tlist := slices.Values([]int{1, 2, 3, 4, 5})\n\n\tresult, err := Nth(list, 2)\n\n\tfmt.Printf(\"%d %v\", result, err)\n\t// Output: 3 <nil>\n}\n\nfunc ExampleNth_outOfBounds() {\n\tlist := slices.Values([]int{1, 2, 3, 4, 5})\n\n\tresult, err := Nth(list, 10)\n\n\tfmt.Printf(\"%d %v\", result, err)\n\t// Output: 0 nth: 10 out of bounds\n}\n\nfunc ExampleNthOr() {\n\tlist := slices.Values([]int{1, 2, 3, 4, 5})\n\n\tresult := NthOr(list, 2, -1)\n\n\tfmt.Printf(\"%d\", result)\n\t// Output: 3\n}\n\nfunc ExampleNthOr_outOfBounds() {\n\tlist := slices.Values([]int{1, 2, 3, 4, 5})\n\n\tresult := NthOr(list, 10, -1)\n\n\tfmt.Printf(\"%d\", result)\n\t// Output: -1\n}\n\nfunc ExampleNthOrEmpty() {\n\tlist := slices.Values([]int{1, 2, 3, 4, 5})\n\n\tresult := NthOrEmpty(list, 2)\n\n\tfmt.Printf(\"%d\", result)\n\t// Output: 3\n}\n\nfunc ExampleNthOrEmpty_outOfBounds() {\n\tlist := slices.Values([]int{1, 2, 3, 4, 5})\n\n\tresult := NthOrEmpty(list, 10)\n\n\tfmt.Printf(\"%d\", result)\n\t// Output: 0\n}\n"
  },
  {
    "path": "it/find_test.go",
    "content": "//go:build go1.23\n\npackage it\n\nimport (\n\t\"iter\"\n\t\"slices\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/stretchr/testify/assert\"\n\n\t\"github.com/samber/lo/internal/xrand\"\n)\n\nfunc TestIndexOf(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := IndexOf(values(0, 1, 2, 1, 2, 3), 2)\n\tresult2 := IndexOf(values(0, 1, 2, 1, 2, 3), 6)\n\n\tis.Equal(2, result1)\n\tis.Equal(-1, result2)\n}\n\nfunc TestLastIndexOf(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := LastIndexOf(values(0, 1, 2, 1, 2, 3), 2)\n\tresult2 := LastIndexOf(values(0, 1, 2, 1, 2, 3), 6)\n\n\tis.Equal(4, result1)\n\tis.Equal(-1, result2)\n}\n\nfunc TestHasPrefix(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tis.True(HasPrefix(values(1, 2, 3, 4), 1, 2, 3, 4))\n\tis.True(HasPrefix(values(1, 2, 3, 4), 1, 2))\n\tis.False(HasPrefix(values(1, 2, 3, 4), 42))\n\tis.False(HasPrefix(values(1, 2), 1, 2, 3, 4))\n\tis.True(HasPrefix(values(1, 2, 3, 4)))\n}\n\nfunc TestHasSuffix(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tis.True(HasSuffix(values(1, 2, 3, 4), 1, 2, 3, 4))\n\tis.True(HasSuffix(values(1, 2, 3, 4), 3, 4))\n\tis.True(HasSuffix(values(1, 2, 3, 4, 5), 3, 4, 5))\n\tis.False(HasSuffix(values(1, 2, 3, 4), 42))\n\tis.False(HasSuffix(values(1, 2), 1, 2, 3, 4))\n\tis.True(HasSuffix(values(1, 2, 3, 4)))\n\tis.False(HasSuffix(values(0), 0, 0))\n}\n\nfunc TestFind(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tindex := 0\n\tresult1, ok1 := Find(values(\"a\", \"b\", \"c\", \"d\"), func(item string) bool {\n\t\tis.Equal([]string{\"a\", \"b\", \"c\", \"d\"}[index], item)\n\t\tindex++\n\t\treturn item == \"b\"\n\t})\n\n\tresult2, ok2 := Find(values(\"foobar\"), func(item string) bool {\n\t\tis.Equal(\"foobar\", item)\n\t\treturn item == \"b\"\n\t})\n\n\tis.True(ok1)\n\tis.Equal(\"b\", result1)\n\tis.False(ok2)\n\tis.Empty(result2)\n}\n\nfunc TestFindIndexOf(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tindex := 0\n\titem1, index1, ok1 := FindIndexOf(values(\"a\", \"b\", \"c\", \"d\", \"b\"), func(item string) bool {\n\t\tis.Equal([]string{\"a\", \"b\", \"c\", \"d\", \"b\"}[index], item)\n\t\tindex++\n\t\treturn item == \"b\"\n\t})\n\titem2, index2, ok2 := FindIndexOf(values(\"foobar\"), func(item string) bool {\n\t\tis.Equal(\"foobar\", item)\n\t\treturn item == \"b\"\n\t})\n\n\tis.Equal(\"b\", item1)\n\tis.True(ok1)\n\tis.Equal(1, index1)\n\tis.Empty(item2)\n\tis.False(ok2)\n\tis.Equal(-1, index2)\n}\n\nfunc TestFindLastIndexOf(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\titem1, index1, ok1 := FindLastIndexOf(values(\"a\", \"b\", \"c\", \"d\", \"b\"), func(item string) bool {\n\t\treturn item == \"b\"\n\t})\n\titem2, index2, ok2 := FindLastIndexOf(values(\"foobar\"), func(item string) bool {\n\t\treturn item == \"b\"\n\t})\n\n\tis.Equal(\"b\", item1)\n\tis.True(ok1)\n\tis.Equal(4, index1)\n\tis.Empty(item2)\n\tis.False(ok2)\n\tis.Equal(-1, index2)\n}\n\nfunc TestFindOrElse(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tindex := 0\n\tresult1 := FindOrElse(values(\"a\", \"b\", \"c\", \"d\"), \"x\", func(item string) bool {\n\t\tis.Equal([]string{\"a\", \"b\", \"c\", \"d\"}[index], item)\n\t\tindex++\n\t\treturn item == \"b\"\n\t})\n\tresult2 := FindOrElse(values(\"foobar\"), \"x\", func(item string) bool {\n\t\tis.Equal(\"foobar\", item)\n\t\treturn item == \"b\"\n\t})\n\n\tis.Equal(\"b\", result1)\n\tis.Equal(\"x\", result2)\n}\n\nfunc TestFindUniques(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := FindUniques(values(1, 2, 3))\n\tis.Equal([]int{1, 2, 3}, slices.Collect(result1))\n\n\tresult2 := FindUniques(values(1, 2, 2, 3, 1, 2))\n\tis.Equal([]int{3}, slices.Collect(result2))\n\n\tresult3 := FindUniques(values(1, 2, 2, 1))\n\tis.Empty(slices.Collect(result3))\n\n\tresult4 := FindUniques(values[int]())\n\tis.Empty(slices.Collect(result4))\n\n\ttype myStrings iter.Seq[string]\n\tallStrings := myStrings(values(\"\", \"foo\", \"bar\"))\n\tnonempty := FindUniques(allStrings)\n\tis.IsType(nonempty, allStrings, \"type preserved\")\n}\n\nfunc TestFindUniquesBy(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := FindUniquesBy(values(0, 1, 2), func(i int) int {\n\t\treturn i % 3\n\t})\n\tis.Equal([]int{0, 1, 2}, slices.Collect(result1))\n\n\tresult2 := FindUniquesBy(values(0, 1, 2, 3, 4), func(i int) int {\n\t\treturn i % 3\n\t})\n\tis.Equal([]int{2}, slices.Collect(result2))\n\n\tresult3 := FindUniquesBy(values(0, 1, 2, 3, 4, 5), func(i int) int {\n\t\treturn i % 3\n\t})\n\tis.Empty(slices.Collect(result3))\n\n\tresult4 := FindUniquesBy(values[int](), func(i int) int {\n\t\treturn i % 3\n\t})\n\tis.Empty(slices.Collect(result4))\n\n\ttype myStrings iter.Seq[string]\n\tallStrings := myStrings(values(\"\", \"foo\", \"bar\"))\n\tnonempty := FindUniquesBy(allStrings, func(i string) string {\n\t\treturn i\n\t})\n\tis.IsType(nonempty, allStrings, \"type preserved\")\n}\n\nfunc TestFindDuplicates(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := FindDuplicates(values(1, 2, 2, 1, 2, 3))\n\tis.Equal([]int{2, 1}, slices.Collect(result1))\n\n\tresult2 := FindDuplicates(values(1, 2, 3))\n\tis.Empty(slices.Collect(result2))\n\n\tresult3 := FindDuplicates(values[int]())\n\tis.Empty(slices.Collect(result3))\n\n\ttype myStrings iter.Seq[string]\n\tallStrings := myStrings(values(\"\", \"foo\", \"bar\"))\n\tnonempty := FindDuplicates(allStrings)\n\tis.IsType(nonempty, allStrings, \"type preserved\")\n}\n\nfunc TestFindDuplicatesBy(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := FindDuplicatesBy(values(3, 4, 5, 6, 7), func(i int) int {\n\t\treturn i % 3\n\t})\n\tis.Equal([]int{3, 4}, slices.Collect(result1))\n\n\tresult2 := FindDuplicatesBy(values(0, 1, 2, 3, 4), func(i int) int {\n\t\treturn i % 5\n\t})\n\tis.Empty(slices.Collect(result2))\n\n\tresult3 := FindDuplicatesBy(values[int](), func(i int) int {\n\t\treturn i % 3\n\t})\n\tis.Empty(slices.Collect(result3))\n\n\ttype myStrings iter.Seq[string]\n\tallStrings := myStrings(values(\"\", \"foo\", \"bar\"))\n\tnonempty := FindDuplicatesBy(allStrings, func(i string) string {\n\t\treturn i\n\t})\n\tis.IsType(nonempty, allStrings, \"type preserved\")\n}\n\nfunc TestMin(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := Min(values(1, 2, 3))\n\tresult2 := Min(values(3, 2, 1))\n\tresult3 := Min(values(time.Second, time.Minute, time.Hour))\n\tresult4 := Min(values[int]())\n\n\tis.Equal(1, result1)\n\tis.Equal(1, result2)\n\tis.Equal(time.Second, result3)\n\tis.Zero(result4)\n}\n\nfunc TestMinIndex(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1, index1 := MinIndex(values(1, 2, 3))\n\tresult2, index2 := MinIndex(values(3, 2, 1))\n\tresult3, index3 := MinIndex(values(time.Second, time.Minute, time.Hour))\n\tresult4, index4 := MinIndex(values[int]())\n\n\tis.Equal(1, result1)\n\tis.Zero(index1)\n\n\tis.Equal(1, result2)\n\tis.Equal(2, index2)\n\n\tis.Equal(time.Second, result3)\n\tis.Zero(index3)\n\n\tis.Zero(result4)\n\tis.Equal(-1, index4)\n}\n\nfunc TestMinBy(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := MinBy(values(\"s1\", \"string2\", \"s3\"), func(item, mIn string) bool {\n\t\treturn len(item) < len(mIn)\n\t})\n\tresult2 := MinBy(values(\"string1\", \"string2\", \"s3\"), func(item, mIn string) bool {\n\t\treturn len(item) < len(mIn)\n\t})\n\tresult3 := MinBy(values[string](), func(item, mIn string) bool {\n\t\treturn len(item) < len(mIn)\n\t})\n\n\tis.Equal(\"s1\", result1)\n\tis.Equal(\"s3\", result2)\n\tis.Empty(result3)\n}\n\nfunc TestMinIndexBy(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1, index1 := MinIndexBy(values(\"s1\", \"string2\", \"s3\"), func(item, mIn string) bool {\n\t\treturn len(item) < len(mIn)\n\t})\n\tresult2, index2 := MinIndexBy(values(\"string1\", \"string2\", \"s3\"), func(item, mIn string) bool {\n\t\treturn len(item) < len(mIn)\n\t})\n\tresult3, index3 := MinIndexBy(values[string](), func(item, mIn string) bool {\n\t\treturn len(item) < len(mIn)\n\t})\n\n\tis.Equal(\"s1\", result1)\n\tis.Zero(index1)\n\n\tis.Equal(\"s3\", result2)\n\tis.Equal(2, index2)\n\n\tis.Empty(result3)\n\tis.Equal(-1, index3)\n}\n\nfunc TestEarliest(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\ta := time.Now()\n\tb := a.Add(time.Hour)\n\tresult1 := Earliest(values(a, b))\n\tresult2 := Earliest(values[time.Time]())\n\n\tis.Equal(a, result1)\n\tis.Zero(result2)\n}\n\nfunc TestEarliestBy(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\ttype foo struct {\n\t\tbar time.Time\n\t}\n\n\tt1 := time.Now()\n\tt2 := t1.Add(time.Hour)\n\tt3 := t1.Add(-time.Hour)\n\tresult1 := EarliestBy(values(foo{t1}, foo{t2}, foo{t3}), func(i foo) time.Time {\n\t\treturn i.bar\n\t})\n\tresult2 := EarliestBy(values(foo{t1}), func(i foo) time.Time {\n\t\treturn i.bar\n\t})\n\tresult3 := EarliestBy(values[foo](), func(i foo) time.Time {\n\t\treturn i.bar\n\t})\n\n\tis.Equal(foo{t3}, result1)\n\tis.Equal(foo{t1}, result2)\n\tis.Zero(result3)\n}\n\nfunc TestMax(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := Max(values(1, 2, 3))\n\tresult2 := Max(values(3, 2, 1))\n\tresult3 := Max(values(time.Second, time.Minute, time.Hour))\n\tresult4 := Max(values[int]())\n\n\tis.Equal(3, result1)\n\tis.Equal(3, result2)\n\tis.Equal(time.Hour, result3)\n\tis.Zero(result4)\n}\n\nfunc TestMaxIndex(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1, index1 := MaxIndex(values(1, 2, 3))\n\tresult2, index2 := MaxIndex(values(3, 2, 1))\n\tresult3, index3 := MaxIndex(values(time.Second, time.Minute, time.Hour))\n\tresult4, index4 := MaxIndex(values[int]())\n\n\tis.Equal(3, result1)\n\tis.Equal(2, index1)\n\n\tis.Equal(3, result2)\n\tis.Zero(index2)\n\n\tis.Equal(time.Hour, result3)\n\tis.Equal(2, index3)\n\n\tis.Zero(result4)\n\tis.Equal(-1, index4)\n}\n\nfunc TestMaxBy(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := MaxBy(values(\"s1\", \"string2\", \"s3\"), func(item, mAx string) bool {\n\t\treturn len(item) > len(mAx)\n\t})\n\tresult2 := MaxBy(values(\"string1\", \"string2\", \"s3\"), func(item, mAx string) bool {\n\t\treturn len(item) > len(mAx)\n\t})\n\tresult3 := MaxBy(values[string](), func(item, mAx string) bool {\n\t\treturn len(item) > len(mAx)\n\t})\n\n\tis.Equal(\"string2\", result1)\n\tis.Equal(\"string1\", result2)\n\tis.Empty(result3)\n}\n\nfunc TestMaxIndexBy(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1, index1 := MaxIndexBy(values(\"s1\", \"string2\", \"s3\"), func(item, mAx string) bool {\n\t\treturn len(item) > len(mAx)\n\t})\n\tresult2, index2 := MaxIndexBy(values(\"string1\", \"string2\", \"s3\"), func(item, mAx string) bool {\n\t\treturn len(item) > len(mAx)\n\t})\n\tresult3, index3 := MaxIndexBy(values[string](), func(item, mAx string) bool {\n\t\treturn len(item) > len(mAx)\n\t})\n\n\tis.Equal(\"string2\", result1)\n\tis.Equal(1, index1)\n\n\tis.Equal(\"string1\", result2)\n\tis.Zero(index2)\n\n\tis.Empty(result3)\n\tis.Equal(-1, index3)\n}\n\nfunc TestLatest(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\ta := time.Now()\n\tb := a.Add(time.Hour)\n\tresult1 := Latest(values(a, b))\n\tresult2 := Latest(values[time.Time]())\n\n\tis.Equal(b, result1)\n\tis.Zero(result2)\n}\n\nfunc TestLatestBy(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\ttype foo struct {\n\t\tbar time.Time\n\t}\n\n\tt1 := time.Now()\n\tt2 := t1.Add(time.Hour)\n\tt3 := t1.Add(-time.Hour)\n\tresult1 := LatestBy(values(foo{t1}, foo{t2}, foo{t3}), func(i foo) time.Time {\n\t\treturn i.bar\n\t})\n\tresult2 := LatestBy(values(foo{t1}), func(i foo) time.Time {\n\t\treturn i.bar\n\t})\n\tresult3 := LatestBy(values[foo](), func(i foo) time.Time {\n\t\treturn i.bar\n\t})\n\n\tis.Equal(foo{t2}, result1)\n\tis.Equal(foo{t1}, result2)\n\tis.Zero(result3)\n}\n\nfunc TestFirst(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1, ok1 := First(values(1, 2, 3))\n\tresult2, ok2 := First(values[int]())\n\n\tis.Equal(1, result1)\n\tis.True(ok1)\n\tis.Zero(result2)\n\tis.False(ok2)\n}\n\nfunc TestFirstOrEmpty(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := FirstOrEmpty(values(1, 2, 3))\n\tresult2 := FirstOrEmpty(values[int]())\n\tresult3 := FirstOrEmpty(values[string]())\n\n\tis.Equal(1, result1)\n\tis.Zero(result2)\n\tis.Empty(result3)\n}\n\nfunc TestFirstOr(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := FirstOr(values(1, 2, 3), 63)\n\tresult2 := FirstOr(values[int](), 23)\n\tresult3 := FirstOr(values[string](), \"test\")\n\n\tis.Equal(1, result1)\n\tis.Equal(23, result2)\n\tis.Equal(\"test\", result3)\n}\n\nfunc TestLast(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1, ok1 := Last(values(1, 2, 3))\n\tresult2, ok2 := Last(values[int]())\n\n\tis.Equal(3, result1)\n\tis.True(ok1)\n\tis.Zero(result2)\n\tis.False(ok2)\n}\n\nfunc TestLastOrEmpty(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := LastOrEmpty(values(1, 2, 3))\n\tresult2 := LastOrEmpty(values[int]())\n\tresult3 := LastOrEmpty(values[string]())\n\n\tis.Equal(3, result1)\n\tis.Zero(result2)\n\tis.Empty(result3)\n}\n\nfunc TestLastOr(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := LastOr(values(1, 2, 3), 63)\n\tresult2 := LastOr(values[int](), 23)\n\tresult3 := LastOr(values[string](), \"test\")\n\n\tis.Equal(3, result1)\n\tis.Equal(23, result2)\n\tis.Equal(\"test\", result3)\n}\n\nfunc TestNth(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1, err1 := Nth(values(0, 1, 2, 3), 2)\n\tresult2, err2 := Nth(values(0, 1, 2, 3), -2)\n\tresult3, err3 := Nth(values(0, 1, 2, 3), 42)\n\tresult4, err4 := Nth(values[int](), 0)\n\tresult5, err5 := Nth(values(42), 0)\n\tresult6, err6 := Nth(values(42), -1)\n\n\tis.Equal(2, result1)\n\tis.NoError(err1)\n\tis.Zero(result2)\n\tis.EqualError(err2, \"nth: -2 out of bounds\")\n\tis.Zero(result3)\n\tis.EqualError(err3, \"nth: 42 out of bounds\")\n\tis.Zero(result4)\n\tis.EqualError(err4, \"nth: 0 out of bounds\")\n\tis.Equal(42, result5)\n\tis.NoError(err5)\n\tis.Zero(result6)\n\tis.EqualError(err6, \"nth: -1 out of bounds\")\n}\n\nfunc TestNthOr(t *testing.T) {\n\tt.Parallel()\n\n\tt.Run(\"Integers\", func(t *testing.T) {\n\t\tt.Parallel()\n\t\tis := assert.New(t)\n\n\t\tconst defaultValue = -1\n\t\tints := values(10, 20, 30, 40, 50)\n\n\t\tis.Equal(30, NthOr(ints, 2, defaultValue))\n\t\tis.Equal(defaultValue, NthOr(ints, -1, defaultValue))\n\t\tis.Equal(defaultValue, NthOr(ints, 5, defaultValue))\n\t})\n\n\tt.Run(\"Strings\", func(t *testing.T) {\n\t\tt.Parallel()\n\t\tis := assert.New(t)\n\n\t\tconst defaultValue = \"none\"\n\t\tstrs := values(\"apple\", \"banana\", \"cherry\", \"date\")\n\n\t\tis.Equal(\"banana\", NthOr(strs, 1, defaultValue))      // Index 1, expected \"banana\"\n\t\tis.Equal(defaultValue, NthOr(strs, -2, defaultValue)) // Negative index -2, expected \"cherry\"\n\t\tis.Equal(defaultValue, NthOr(strs, 10, defaultValue)) // Out of bounds, fallback \"none\"\n\t})\n\n\tt.Run(\"Structs\", func(t *testing.T) {\n\t\tt.Parallel()\n\t\tis := assert.New(t)\n\n\t\ttype User struct {\n\t\t\tID   int\n\t\t\tName string\n\t\t}\n\t\tusers := values(\n\t\t\tUser{ID: 1, Name: \"Alice\"},\n\t\t\tUser{ID: 2, Name: \"Bob\"},\n\t\t\tUser{ID: 3, Name: \"Charlie\"},\n\t\t)\n\t\tdefaultValue := User{ID: 0, Name: \"Unknown\"}\n\n\t\tis.Equal(User{ID: 1, Name: \"Alice\"}, NthOr(users, 0, defaultValue))\n\t\tis.Equal(defaultValue, NthOr(users, -1, defaultValue))\n\t\tis.Equal(defaultValue, NthOr(users, 10, defaultValue))\n\t})\n}\n\nfunc TestNthOrEmpty(t *testing.T) {\n\tt.Parallel()\n\n\tt.Run(\"Integers\", func(t *testing.T) {\n\t\tt.Parallel()\n\t\tis := assert.New(t)\n\n\t\tints := values(10, 20, 30, 40, 50)\n\n\t\tis.Equal(30, NthOrEmpty(ints, 2))\n\t\tis.Zero(NthOrEmpty(ints, -1))\n\t\tis.Zero(NthOrEmpty(ints, 10))\n\t})\n\n\tt.Run(\"Strings\", func(t *testing.T) {\n\t\tt.Parallel()\n\t\tis := assert.New(t)\n\n\t\tstrs := values(\"apple\", \"banana\", \"cherry\", \"date\")\n\n\t\tis.Equal(\"banana\", NthOrEmpty(strs, 1))\n\t\tis.Empty(NthOrEmpty(strs, -2))\n\t\tis.Empty(NthOrEmpty(strs, 10))\n\t})\n\n\tt.Run(\"Structs\", func(t *testing.T) {\n\t\tt.Parallel()\n\t\tis := assert.New(t)\n\n\t\ttype User struct {\n\t\t\tID   int\n\t\t\tName string\n\t\t}\n\t\tusers := values(\n\t\t\tUser{ID: 1, Name: \"Alice\"},\n\t\t\tUser{ID: 2, Name: \"Bob\"},\n\t\t\tUser{ID: 3, Name: \"Charlie\"},\n\t\t)\n\n\t\tis.Equal(User{ID: 1, Name: \"Alice\"}, NthOrEmpty(users, 0))\n\t\tis.Zero(NthOrEmpty(users, -1))\n\t\tis.Zero(NthOrEmpty(users, 10))\n\t})\n}\n\nfunc TestSample(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := Sample(values(\"a\", \"b\", \"c\"))\n\tresult2 := Sample(values[string]())\n\n\tis.True(Contains(values(\"a\", \"b\", \"c\"), result1))\n\tis.Empty(result2)\n}\n\nfunc TestSampleBy(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := SampleBy(values(\"a\", \"b\", \"c\"), xrand.IntN)\n\tresult2 := SampleBy(values[string](), xrand.IntN)\n\n\tis.True(Contains(values(\"a\", \"b\", \"c\"), result1))\n\tis.Empty(result2)\n}\n\nfunc TestSamples(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := Samples(values(\"a\", \"b\", \"c\"), 3)\n\tresult2 := Samples(values[string](), 3)\n\n\tis.ElementsMatch(slices.Collect(result1), []string{\"a\", \"b\", \"c\"})\n\tis.Empty(slices.Collect(result2))\n\n\ttype myStrings iter.Seq[string]\n\tallStrings := myStrings(values(\"\", \"foo\", \"bar\"))\n\tnonempty := Samples(allStrings, 2)\n\tis.IsType(nonempty, allStrings, \"type preserved\")\n}\n\nfunc TestSamplesBy(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := SamplesBy(values(\"a\", \"b\", \"c\"), 3, xrand.IntN)\n\tresult2 := SamplesBy(values[string](), 3, xrand.IntN)\n\tresult3 := SamplesBy(values(\"a\", \"b\", \"c\"), 3, func(n int) int { return n - 1 })\n\tresult4 := SamplesBy(values(\"a\", \"b\", \"c\"), 3, func(int) int { return 0 })\n\tresult5 := SamplesBy(values(\"a\", \"b\", \"c\"), 0, func(int) int { return 1 })\n\tresult6 := SamplesBy(values(\"a\", \"b\", \"c\"), -1, nil)\n\n\t// index out of range [1] with length 1\n\tis.Panics(func() {\n\t\tSamplesBy(values(\"a\", \"b\", \"c\"), 3, func(int) int { return 1 })\n\t})\n\n\tis.ElementsMatch(slices.Collect(result1), []string{\"a\", \"b\", \"c\"})\n\tis.Empty(slices.Collect(result2))\n\tis.Equal([]string{\"c\", \"b\", \"a\"}, slices.Collect(result3))\n\tis.Equal([]string{\"a\", \"c\", \"b\"}, slices.Collect(result4))\n\tis.Empty(slices.Collect(result5))\n\tis.Empty(slices.Collect(result6))\n\n\ttype myStrings iter.Seq[string]\n\tallStrings := myStrings(values(\"\", \"foo\", \"bar\"))\n\tnonempty := SamplesBy(allStrings, 2, xrand.IntN)\n\tis.IsType(nonempty, allStrings, \"type preserved\")\n}\n"
  },
  {
    "path": "it/intersect.go",
    "content": "//go:build go1.23\n\npackage it\n\nimport (\n\t\"iter\"\n\n\t\"github.com/samber/lo\"\n)\n\n// Contains returns true if an element is present in a collection.\n// Will iterate through the entire sequence if element is not found.\n// Play: https://go.dev/play/p/1edj7hH3TS2\nfunc Contains[T comparable](collection iter.Seq[T], element T) bool {\n\treturn ContainsBy(collection, func(item T) bool { return item == element })\n}\n\n// ContainsBy returns true if predicate function return true.\n// Will iterate through the entire sequence if predicate never returns true.\nfunc ContainsBy[T any](collection iter.Seq[T], predicate func(item T) bool) bool {\n\tfor item := range collection {\n\t\tif predicate(item) {\n\t\t\treturn true\n\t\t}\n\t}\n\n\treturn false\n}\n\n// Every returns true if all elements of a subset are contained in a collection or if the subset is empty.\n// Will iterate through the entire sequence if subset elements always match.\n// Play: https://go.dev/play/p/rwM9Y353aIC\nfunc Every[T comparable](collection iter.Seq[T], subset ...T) bool {\n\tif len(subset) == 0 {\n\t\treturn true\n\t}\n\n\tset := lo.Keyify(subset)\n\tfor item := range collection {\n\t\tif _, ok := set[item]; ok {\n\t\t\tdelete(set, item)\n\t\t\tif len(set) == 0 {\n\t\t\t\treturn true\n\t\t\t}\n\t\t}\n\t}\n\n\treturn false\n}\n\n// EveryBy returns true if the predicate returns true for all elements in the collection or if the collection is empty.\n// Will iterate through the entire sequence if predicate never returns false.\nfunc EveryBy[T any](collection iter.Seq[T], predicate func(item T) bool) bool {\n\tfor item := range collection {\n\t\tif !predicate(item) {\n\t\t\treturn false\n\t\t}\n\t}\n\n\treturn true\n}\n\n// Some returns true if at least 1 element of a subset is contained in a collection.\n// If the subset is empty Some returns false.\n// Will iterate through the entire sequence if subset elements never match.\n// Play: https://go.dev/play/p/KmX-fXictQl\nfunc Some[T comparable](collection iter.Seq[T], subset ...T) bool {\n\tif len(subset) == 0 {\n\t\treturn false\n\t}\n\n\tseen := lo.Keyify(subset)\n\treturn SomeBy(collection, func(item T) bool {\n\t\t_, ok := seen[item]\n\t\treturn ok\n\t})\n}\n\n// SomeBy returns true if the predicate returns true for any of the elements in the collection.\n// If the collection is empty SomeBy returns false.\n// Will iterate through the entire sequence if predicate never returns true.\nfunc SomeBy[T any](collection iter.Seq[T], predicate func(item T) bool) bool {\n\tfor item := range collection {\n\t\tif predicate(item) {\n\t\t\treturn true\n\t\t}\n\t}\n\n\treturn false\n}\n\n// None returns true if no element of a subset is contained in a collection or if the subset is empty.\n// Will iterate through the entire sequence if subset elements never match.\n// Play: https://go.dev/play/p/L7mm5S4a8Yo\nfunc None[T comparable](collection iter.Seq[T], subset ...T) bool {\n\tif len(subset) == 0 {\n\t\treturn true\n\t}\n\n\tseen := lo.Keyify(subset)\n\treturn NoneBy(collection, func(item T) bool {\n\t\t_, ok := seen[item]\n\t\treturn ok\n\t})\n}\n\n// NoneBy returns true if the predicate returns true for none of the elements in the collection or if the collection is empty.\n// Will iterate through the entire sequence if predicate never returns true.\nfunc NoneBy[T any](collection iter.Seq[T], predicate func(item T) bool) bool {\n\tfor item := range collection {\n\t\tif predicate(item) {\n\t\t\treturn false\n\t\t}\n\t}\n\n\treturn true\n}\n\n// Intersect returns the intersection between given collections.\n// Will allocate a map large enough to hold all distinct elements.\n// Long heterogeneous input sequences can cause excessive memory usage.\n// Play: https://go.dev/play/p/kz3cGhGZZWF\nfunc Intersect[T comparable, I ~func(func(T) bool)](lists ...I) I {\n\tif len(lists) == 0 {\n\t\treturn I(Empty[T]())\n\t}\n\n\treturn func(yield func(T) bool) {\n\t\tlast := lists[len(lists)-1]\n\n\t\tseen := make(map[T]bool)\n\n\t\tfor item := range last {\n\t\t\tseen[item] = false\n\t\t}\n\n\t\tfor i := len(lists) - 2; i > 0 && len(seen) != 0; i-- {\n\t\t\tfor item := range lists[i] {\n\t\t\t\tif _, ok := seen[item]; ok {\n\t\t\t\t\tseen[item] = true\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor k, v := range seen {\n\t\t\t\tif v {\n\t\t\t\t\tseen[k] = false\n\t\t\t\t} else {\n\t\t\t\t\tdelete(seen, k)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfor item := range lists[0] {\n\t\t\tif _, ok := seen[item]; ok {\n\t\t\t\tif !yield(item) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tdelete(seen, item)\n\t\t\t}\n\t\t}\n\t}\n}\n\n// IntersectBy returns the intersection between given collections using a\n// custom key selector function.\n// Will allocate a map large enough to hold all distinct elements.\n// Long heterogeneous input sequences can cause excessive memory usage.\n// Play: https://go.dev/play/p/X2nEvHC-lE2\nfunc IntersectBy[T any, K comparable, I ~func(func(T) bool)](transform func(T) K, lists ...I) I {\n\tif len(lists) == 0 {\n\t\treturn I(Empty[T]())\n\t}\n\n\treturn func(yield func(T) bool) {\n\t\tlast := lists[len(lists)-1]\n\n\t\tseen := make(map[K]bool)\n\n\t\tfor item := range last {\n\t\t\tk := transform(item)\n\t\t\tseen[k] = false\n\t\t}\n\n\t\tfor i := len(lists) - 2; i > 0 && len(seen) != 0; i-- {\n\t\t\tfor item := range lists[i] {\n\t\t\t\tk := transform(item)\n\t\t\t\tif _, ok := seen[k]; ok {\n\t\t\t\t\tseen[k] = true\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor k, v := range seen {\n\t\t\t\tif v {\n\t\t\t\t\tseen[k] = false\n\t\t\t\t} else {\n\t\t\t\t\tdelete(seen, k)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfor item := range lists[0] {\n\t\t\tk := transform(item)\n\t\t\tif _, ok := seen[k]; ok {\n\t\t\t\tif !yield(item) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tdelete(seen, k)\n\t\t\t}\n\t\t}\n\t}\n}\n\n// Union returns all distinct elements from given collections.\n// Will allocate a map large enough to hold all distinct elements.\n// Long heterogeneous input sequences can cause excessive memory usage.\n// Play: https://go.dev/play/p/ImIoFNpSUUB\nfunc Union[T comparable, I ~func(func(T) bool)](lists ...I) I {\n\treturn func(yield func(T) bool) {\n\t\tseen := make(map[T]struct{})\n\n\t\tfor i := range lists {\n\t\t\tfor item := range lists[i] {\n\t\t\t\tif _, ok := seen[item]; !ok {\n\t\t\t\t\tif !yield(item) {\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\tseen[item] = struct{}{}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n// Without returns a sequence excluding all given values.\n// Will allocate a map large enough to hold all distinct excludes.\n// Play: https://go.dev/play/p/LbN55AVBZ7h\nfunc Without[T comparable, I ~func(func(T) bool)](collection I, exclude ...T) I {\n\treturn WithoutBy(collection, func(item T) T { return item }, exclude...)\n}\n\n// WithoutBy filters a sequence by excluding elements whose extracted keys match any in the exclude list.\n// Returns a sequence containing only the elements whose keys are not in the exclude list.\n// Will allocate a map large enough to hold all distinct excludes.\n// Play: https://go.dev/play/p/Hm734hnLnLI\nfunc WithoutBy[T any, K comparable, I ~func(func(T) bool)](collection I, transform func(item T) K, exclude ...K) I {\n\tset := lo.Keyify(exclude)\n\treturn Reject(collection, func(item T) bool { return lo.HasKey(set, transform(item)) })\n}\n\n// WithoutNth returns a sequence excluding the nth value.\n// Will allocate a map large enough to hold all distinct nths.\n// Play: https://go.dev/play/p/KGE7Lpsk18P\nfunc WithoutNth[T comparable, I ~func(func(T) bool)](collection I, nths ...int) I {\n\tset := lo.Keyify(nths)\n\treturn RejectI(collection, func(_ T, index int) bool { return lo.HasKey(set, index) })\n}\n\n// ElementsMatch returns true if lists contain the same set of elements (including empty set).\n// If there are duplicate elements, the number of occurrences in each list should match.\n// The order of elements is not checked.\n// Will iterate through each sequence before returning and allocate a map large enough to hold all distinct elements.\n// Long heterogeneous input sequences can cause excessive memory usage.\n// Play: https://go.dev/play/p/24SGQm1yMRe\nfunc ElementsMatch[T comparable](list1, list2 iter.Seq[T]) bool {\n\treturn ElementsMatchBy(list1, list2, func(item T) T { return item })\n}\n\n// ElementsMatchBy returns true if lists contain the same set of elements' keys (including empty set).\n// If there are duplicate keys, the number of occurrences in each list should match.\n// The order of elements is not checked.\n// Will iterate through each sequence before returning and allocate a map large enough to hold all distinct transformed elements.\n// Long heterogeneous input sequences can cause excessive memory usage.\n// Play: https://go.dev/play/p/I3vFrmQo43E\nfunc ElementsMatchBy[T any, K comparable](list1, list2 iter.Seq[T], transform func(item T) K) bool {\n\tcounters := make(map[K]int)\n\n\tfor item := range list1 {\n\t\tcounters[transform(item)]++\n\t}\n\n\tfor item := range list2 {\n\t\tcounters[transform(item)]--\n\t}\n\n\tfor _, count := range counters {\n\t\tif count != 0 {\n\t\t\treturn false\n\t\t}\n\t}\n\n\treturn true\n}\n"
  },
  {
    "path": "it/intersect_example_test.go",
    "content": "//go:build go1.23\n\npackage it\n\nimport (\n\t\"fmt\"\n\t\"slices\"\n)\n\nfunc ExampleWithoutBy() {\n\ttype User struct {\n\t\tID   int\n\t\tName string\n\t}\n\t// original users\n\tusers := values(\n\t\tUser{ID: 1, Name: \"Alice\"},\n\t\tUser{ID: 2, Name: \"Bob\"},\n\t\tUser{ID: 3, Name: \"Charlie\"},\n\t)\n\n\t// exclude users with IDs 2 and 3\n\texcludedIDs := []int{2, 3}\n\n\t// extract function to get the user ID\n\textractID := func(user User) int {\n\t\treturn user.ID\n\t}\n\n\t// filtering users\n\tfilteredUsers := WithoutBy(users, extractID, excludedIDs...)\n\n\t// output the filtered users\n\tfmt.Printf(\"%v\", slices.Collect(filteredUsers))\n\t// Output:\n\t// [{1 Alice}]\n}\n"
  },
  {
    "path": "it/intersect_test.go",
    "content": "//go:build go1.23\n\npackage it\n\nimport (\n\t\"iter\"\n\t\"slices\"\n\t\"strconv\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestContains(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := Contains(values(0, 1, 2, 3, 4, 5), 5)\n\tresult2 := Contains(values(0, 1, 2, 3, 4, 5), 6)\n\n\tis.True(result1)\n\tis.False(result2)\n}\n\nfunc TestContainsBy(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\ttype a struct {\n\t\tA int\n\t\tB string\n\t}\n\n\ta1 := values(a{A: 1, B: \"1\"}, a{A: 2, B: \"2\"}, a{A: 3, B: \"3\"})\n\tresult1 := ContainsBy(a1, func(t a) bool { return t.A == 1 && t.B == \"2\" })\n\tresult2 := ContainsBy(a1, func(t a) bool { return t.A == 2 && t.B == \"2\" })\n\n\ta2 := values(\"aaa\", \"bbb\", \"ccc\")\n\tresult3 := ContainsBy(a2, func(t string) bool { return t == \"ccc\" })\n\tresult4 := ContainsBy(a2, func(t string) bool { return t == \"ddd\" })\n\n\tis.False(result1)\n\tis.True(result2)\n\tis.True(result3)\n\tis.False(result4)\n}\n\nfunc TestEvery(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := Every(values(0, 1, 2, 3, 4, 5), 0, 2)\n\tresult2 := Every(values(0, 1, 2, 3, 4, 5), 0, 6)\n\tresult3 := Every(values(0, 1, 2, 3, 4, 5), -1, 6)\n\tresult4 := Every(values(0, 1, 2, 3, 4, 5))\n\n\tis.True(result1)\n\tis.False(result2)\n\tis.False(result3)\n\tis.True(result4)\n}\n\nfunc TestEveryBy(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := EveryBy(values(1, 2, 3, 4), func(x int) bool {\n\t\treturn x < 5\n\t})\n\n\tis.True(result1)\n\n\tresult2 := EveryBy(values(1, 2, 3, 4), func(x int) bool {\n\t\treturn x < 3\n\t})\n\n\tis.False(result2)\n\n\tresult3 := EveryBy(values(1, 2, 3, 4), func(x int) bool {\n\t\treturn x < 0\n\t})\n\n\tis.False(result3)\n\n\tresult4 := EveryBy(values[int](), func(x int) bool {\n\t\treturn x < 5\n\t})\n\n\tis.True(result4)\n}\n\nfunc TestSome(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := Some(values(0, 1, 2, 3, 4, 5), 0, 2)\n\tresult2 := Some(values(0, 1, 2, 3, 4, 5), 0, 6)\n\tresult3 := Some(values(0, 1, 2, 3, 4, 5), -1, 6)\n\tresult4 := Some(values(0, 1, 2, 3, 4, 5))\n\n\tis.True(result1)\n\tis.True(result2)\n\tis.False(result3)\n\tis.False(result4)\n}\n\nfunc TestSomeBy(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := SomeBy(values(1, 2, 3, 4), func(x int) bool {\n\t\treturn x < 5\n\t})\n\n\tis.True(result1)\n\n\tresult2 := SomeBy(values(1, 2, 3, 4), func(x int) bool {\n\t\treturn x < 3\n\t})\n\n\tis.True(result2)\n\n\tresult3 := SomeBy(values(1, 2, 3, 4), func(x int) bool {\n\t\treturn x < 0\n\t})\n\n\tis.False(result3)\n\n\tresult4 := SomeBy(values[int](), func(x int) bool {\n\t\treturn x < 5\n\t})\n\n\tis.False(result4)\n}\n\nfunc TestNone(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := None(values(0, 1, 2, 3, 4, 5), 0, 2)\n\tresult2 := None(values(0, 1, 2, 3, 4, 5), 0, 6)\n\tresult3 := None(values(0, 1, 2, 3, 4, 5), -1, 6)\n\tresult4 := None(values(0, 1, 2, 3, 4, 5))\n\n\tis.False(result1)\n\tis.False(result2)\n\tis.True(result3)\n\tis.True(result4)\n}\n\nfunc TestNoneBy(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := NoneBy(values(1, 2, 3, 4), func(x int) bool {\n\t\treturn x < 5\n\t})\n\n\tis.False(result1)\n\n\tresult2 := NoneBy(values(1, 2, 3, 4), func(x int) bool {\n\t\treturn x < 3\n\t})\n\n\tis.False(result2)\n\n\tresult3 := NoneBy(values(1, 2, 3, 4), func(x int) bool {\n\t\treturn x < 0\n\t})\n\n\tis.True(result3)\n\n\tresult4 := NoneBy(values[int](), func(x int) bool {\n\t\treturn x < 5\n\t})\n\n\tis.True(result4)\n}\n\nfunc TestIntersect(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := Intersect([]iter.Seq[int]{}...)\n\tresult2 := Intersect(values(0, 1, 2, 3, 4, 5))\n\tresult3 := Intersect(values(0, 1, 2, 3, 4, 5), values(0, 6))\n\tresult4 := Intersect(values(0, 1, 2, 3, 4, 5), values(-1, 6))\n\tresult5 := Intersect(values(0, 6, 0), values(0, 1, 2, 3, 4, 5))\n\tresult6 := Intersect(values(0, 1, 2, 3, 4, 5), values(0, 6, 0))\n\tresult7 := Intersect(values(0, 1, 2), values(1, 2, 3), values(2, 3, 4))\n\tresult8 := Intersect(values(0, 1, 2), values(1, 2, 3), values(2, 3, 4), values(3, 4, 5))\n\tresult9 := Intersect(values(0, 1, 2), values(0, 1, 2), values(1, 2, 3), values(2, 3, 4), values(3, 4, 5))\n\tresultA := Intersect(values(0, 1, 1))\n\n\tis.Empty(slices.Collect(result1))\n\tis.Equal([]int{0, 1, 2, 3, 4, 5}, slices.Collect(result2))\n\tis.Equal([]int{0}, slices.Collect(result3))\n\tis.Empty(slices.Collect(result4))\n\tis.Equal([]int{0}, slices.Collect(result5))\n\tis.Equal([]int{0}, slices.Collect(result6))\n\tis.Equal([]int{2}, slices.Collect(result7))\n\tis.Empty(slices.Collect(result8))\n\tis.Empty(slices.Collect(result9))\n\tis.Equal([]int{0, 1}, slices.Collect(resultA))\n\n\ttype myStrings iter.Seq[string]\n\tallStrings := myStrings(values(\"\", \"foo\", \"bar\"))\n\tnonempty := Intersect(allStrings, allStrings)\n\tis.IsType(nonempty, allStrings, \"type preserved\")\n}\n\nfunc TestIntersectBy(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\ttransform := strconv.Itoa\n\n\tresult1 := IntersectBy(transform, []iter.Seq[int]{}...)\n\tresult2 := IntersectBy(transform, values(0, 1, 2, 3, 4, 5))\n\tresult3 := IntersectBy(transform, values(0, 1, 2, 3, 4, 5), values(0, 6))\n\tresult4 := IntersectBy(transform, values(0, 1, 2, 3, 4, 5), values(-1, 6))\n\tresult5 := IntersectBy(transform, values(0, 6, 0), values(0, 1, 2, 3, 4, 5))\n\tresult6 := IntersectBy(transform, values(0, 1, 2, 3, 4, 5), values(0, 6, 0))\n\tresult7 := IntersectBy(transform, values(0, 1, 2), values(1, 2, 3), values(2, 3, 4))\n\tresult8 := IntersectBy(transform, values(0, 1, 2), values(1, 2, 3), values(2, 3, 4), values(3, 4, 5))\n\tresult9 := IntersectBy(transform, values(0, 1, 2), values(0, 1, 2), values(1, 2, 3), values(2, 3, 4), values(3, 4, 5))\n\tresultA := IntersectBy(transform, values(0, 1, 1))\n\n\tis.Empty(slices.Collect(result1))\n\tis.Equal([]int{0, 1, 2, 3, 4, 5}, slices.Collect(result2))\n\tis.Equal([]int{0}, slices.Collect(result3))\n\tis.Empty(slices.Collect(result4))\n\tis.Equal([]int{0}, slices.Collect(result5))\n\tis.Equal([]int{0}, slices.Collect(result6))\n\tis.Equal([]int{2}, slices.Collect(result7))\n\tis.Empty(slices.Collect(result8))\n\tis.Empty(slices.Collect(result9))\n\tis.Equal([]int{0, 1}, slices.Collect(resultA))\n\n\ttype myStrings iter.Seq[string]\n\tallStrings := myStrings(values(\"\", \"foo\", \"bar\"))\n\tnonempty := IntersectBy(func(s string) string { return s + s }, allStrings, allStrings)\n\tis.IsType(nonempty, allStrings, \"type preserved\")\n}\n\nfunc TestUnion(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := Union(values(0, 1, 2, 3, 4, 5), values(0, 2, 10))\n\tresult2 := Union(values(0, 1, 2, 3, 4, 5), values(6, 7))\n\tresult3 := Union(values(0, 1, 2, 3, 4, 5), values[int]())\n\tresult4 := Union(values(0, 1, 2), values(0, 1, 2, 3, 3))\n\tresult5 := Union(values(0, 1, 2), values(0, 1, 2))\n\tresult6 := Union(values[int](), values[int]())\n\tis.Equal([]int{0, 1, 2, 3, 4, 5, 10}, slices.Collect(result1))\n\tis.Equal([]int{0, 1, 2, 3, 4, 5, 6, 7}, slices.Collect(result2))\n\tis.Equal([]int{0, 1, 2, 3, 4, 5}, slices.Collect(result3))\n\tis.Equal([]int{0, 1, 2, 3}, slices.Collect(result4))\n\tis.Equal([]int{0, 1, 2}, slices.Collect(result5))\n\tis.Empty(slices.Collect(result6))\n\n\tresult11 := Union(values(0, 1, 2, 3, 4, 5), values(0, 2, 10), values(0, 1, 11))\n\tresult12 := Union(values(0, 1, 2, 3, 4, 5), values(6, 7), values(8, 9))\n\tresult13 := Union(values(0, 1, 2, 3, 4, 5), values[int](), values[int]())\n\tresult14 := Union(values(0, 1, 2), values(0, 1, 2), values(0, 1, 2))\n\tresult15 := Union(values[int](), values[int](), values[int]())\n\tis.Equal([]int{0, 1, 2, 3, 4, 5, 10, 11}, slices.Collect(result11))\n\tis.Equal([]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, slices.Collect(result12))\n\tis.Equal([]int{0, 1, 2, 3, 4, 5}, slices.Collect(result13))\n\tis.Equal([]int{0, 1, 2}, slices.Collect(result14))\n\tis.Empty(slices.Collect(result15))\n\n\ttype myStrings iter.Seq[string]\n\tallStrings := myStrings(values(\"\", \"foo\", \"bar\"))\n\tnonempty := Union(allStrings, allStrings)\n\tis.IsType(nonempty, allStrings, \"type preserved\")\n}\n\nfunc TestWithout(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := Without(values(0, 2, 10), 0, 1, 2, 3, 4, 5)\n\tresult2 := Without(values(0, 7), 0, 1, 2, 3, 4, 5)\n\tresult3 := Without(values[int](), 0, 1, 2, 3, 4, 5)\n\tresult4 := Without(values(0, 1, 2), 0, 1, 2)\n\tresult5 := Without(values[int]())\n\tis.Equal([]int{10}, slices.Collect(result1))\n\tis.Equal([]int{7}, slices.Collect(result2))\n\tis.Empty(slices.Collect(result3))\n\tis.Empty(slices.Collect(result4))\n\tis.Empty(slices.Collect(result5))\n\n\ttype myStrings iter.Seq[string]\n\tallStrings := myStrings(values(\"\", \"foo\", \"bar\"))\n\tnonempty := Without(allStrings, \"\")\n\tis.IsType(nonempty, allStrings, \"type preserved\")\n}\n\nfunc TestWithoutBy(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\ttype User struct {\n\t\tName string\n\t\tAge  int\n\t}\n\n\tresult1 := WithoutBy(values(User{Name: \"nick\"}, User{Name: \"peter\"}),\n\t\tfunc(item User) string {\n\t\t\treturn item.Name\n\t\t}, \"nick\", \"lily\")\n\tresult2 := WithoutBy(values[User](), func(item User) int { return item.Age }, 1, 2, 3)\n\tresult3 := WithoutBy(values[User](), func(item User) string { return item.Name })\n\tis.Equal([]User{{Name: \"peter\"}}, slices.Collect(result1))\n\tis.Empty(slices.Collect(result2))\n\tis.Empty(slices.Collect(result3))\n\n\ttype myStrings iter.Seq[string]\n\tallStrings := myStrings(values(\"\", \"foo\", \"bar\"))\n\tnonempty := WithoutBy(allStrings, func(string) string { return \"\" })\n\tis.IsType(nonempty, allStrings, \"type preserved\")\n}\n\nfunc TestWithoutNth(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := WithoutNth(values(5, 6, 7), 1, 0)\n\tis.Equal([]int{7}, slices.Collect(result1))\n\n\tresult2 := WithoutNth(values(1, 2))\n\tis.Equal([]int{1, 2}, slices.Collect(result2))\n\n\tresult3 := WithoutNth(values[int]())\n\tis.Empty(slices.Collect(result3))\n\n\tresult4 := WithoutNth(values(0, 1, 2, 3), -1, 4)\n\tis.Equal([]int{0, 1, 2, 3}, slices.Collect(result4))\n\n\ttype myStrings iter.Seq[string]\n\tallStrings := myStrings(values(\"\", \"foo\", \"bar\"))\n\tnonempty := WithoutNth(allStrings)\n\tis.IsType(nonempty, allStrings, \"type preserved\")\n}\n\nfunc TestElementsMatch(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tis.False(ElementsMatch(values[int](), values(1)))\n\tis.False(ElementsMatch(values(1), values(2)))\n\tis.False(ElementsMatch(values(1), values(1, 2)))\n\tis.False(ElementsMatch(values(1, 1, 2), values(2, 2, 1)))\n\n\tis.True(ElementsMatch(values(1), values(1)))\n\tis.True(ElementsMatch(values(1, 1), values(1, 1)))\n\tis.True(ElementsMatch(values(1, 2), values(2, 1)))\n\tis.True(ElementsMatch(values(1, 1, 2), values(1, 2, 1)))\n}\n\nfunc TestElementsMatchBy(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\ttype someType struct {\n\t\tkey string\n\t}\n\n\tis.True(ElementsMatchBy(\n\t\tvalues(someType{key: \"a\"}, someType{key: \"b\"}),\n\t\tvalues(someType{key: \"b\"}, someType{key: \"a\"}),\n\t\tfunc(item someType) string { return item.key },\n\t))\n}\n"
  },
  {
    "path": "it/lo_test.go",
    "content": "//go:build go1.23\n\npackage it\n\nimport (\n\t\"iter\"\n\t\"slices\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\n// assertSeqSupportBreak checks whether it is possible to break iteration over a [iter.Seq].\nfunc assertSeqSupportBreak[T any](t *testing.T, seq iter.Seq[T]) iter.Seq[T] {\n\tt.Helper()\n\tassert.NotPanics(t, func() {\n\t\tfor range seq {\n\t\t\tbreak\n\t\t}\n\n\t\tfor range seq {\n\t\t\treturn\n\t\t}\n\t})\n\n\treturn seq\n}\n\nfunc values[T any](v ...T) iter.Seq[T] { return slices.Values(v) }\n\ntype foo struct {\n\tbar string\n}\n\nfunc (f foo) Clone() foo {\n\treturn foo{f.bar}\n}\n"
  },
  {
    "path": "it/map.go",
    "content": "//go:build go1.23\n\npackage it\n\nimport (\n\t\"iter\"\n\t\"maps\"\n)\n\n// Keys creates a sequence of the map keys.\n// Play: https://go.dev/play/p/Fu7h-eW18QM\nfunc Keys[K comparable, V any](in ...map[K]V) iter.Seq[K] {\n\treturn func(yield func(K) bool) {\n\t\tfor i := range in {\n\t\t\tfor k := range in[i] {\n\t\t\t\tif !yield(k) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n// UniqKeys creates a sequence of unique keys in the map.\n// Will allocate a map large enough to hold all distinct input keys.\n// Long input sequences with heterogeneous keys can cause excessive memory usage.\n// Play: https://go.dev/play/p/_NicwfgAHbO\nfunc UniqKeys[K comparable, V any](in ...map[K]V) iter.Seq[K] {\n\treturn func(yield func(K) bool) {\n\t\tvar total int\n\t\tfor i := range in {\n\t\t\ttotal += len(in[i])\n\t\t}\n\t\tseen := make(map[K]struct{}, total)\n\n\t\tfor i := range in {\n\t\t\tfor k := range in[i] {\n\t\t\t\tif _, ok := seen[k]; !ok {\n\t\t\t\t\tif !yield(k) {\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\tseen[k] = struct{}{}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n// Values creates a sequence of the map values.\n// Play: https://go.dev/play/p/L9KcJ3h8E4f\nfunc Values[K comparable, V any](in ...map[K]V) iter.Seq[V] {\n\treturn func(yield func(V) bool) {\n\t\tfor i := range in {\n\t\t\tfor _, v := range in[i] {\n\t\t\t\tif !yield(v) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n// UniqValues creates a sequence of unique values in the map.\n// Will allocate a map large enough to hold all distinct input values.\n// Long input sequences with heterogeneous values can cause excessive memory usage.\n// Play: https://go.dev/play/p/QQv4zGrk-fF\nfunc UniqValues[K, V comparable](in ...map[K]V) iter.Seq[V] {\n\treturn func(yield func(V) bool) {\n\t\tvar total int\n\t\tfor i := range in {\n\t\t\ttotal += len(in[i])\n\t\t}\n\t\tseen := make(map[V]struct{}, total)\n\n\t\tfor i := range in {\n\t\t\tfor _, v := range in[i] {\n\t\t\t\tif _, ok := seen[v]; !ok {\n\t\t\t\t\tif !yield(v) {\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\tseen[v] = struct{}{}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n// Entries transforms a map into a sequence of key/value pairs.\n// Play: https://go.dev/play/p/ckLxqTE9KCz\nfunc Entries[K comparable, V any](in ...map[K]V) iter.Seq2[K, V] {\n\treturn func(yield func(K, V) bool) {\n\t\tfor _, m := range in {\n\t\t\tfor k, v := range m {\n\t\t\t\tif !yield(k, v) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n// ToPairs transforms a map into a sequence of key/value pairs.\n// Alias of Entries().\n// Play: https://go.dev/play/p/N8RbJ5t6H2k\nfunc ToPairs[K comparable, V any](in ...map[K]V) iter.Seq2[K, V] {\n\treturn Entries(in...)\n}\n\n// FromEntries transforms a sequence of key/value pairs into a map.\n// Play: https://go.dev/play/p/MgEF1J5-tuK\nfunc FromEntries[K comparable, V any](entries ...iter.Seq2[K, V]) map[K]V {\n\tm := make(map[K]V)\n\tfor _, e := range entries {\n\t\tmaps.Insert(m, e)\n\t}\n\treturn m\n}\n\n// FromPairs transforms a sequence of key/value pairs into a map.\n// Alias of FromEntries().\n// Play: https://go.dev/play/p/GqPl6isVR9W\nfunc FromPairs[K comparable, V any](entries ...iter.Seq2[K, V]) map[K]V {\n\treturn FromEntries(entries...)\n}\n\n// Invert creates a sequence composed of inverted keys and values.\n// Play: https://go.dev/play/p/Iph19Lgcsx-\nfunc Invert[K, V comparable](in iter.Seq2[K, V]) iter.Seq2[V, K] {\n\treturn func(yield func(V, K) bool) {\n\t\tfor k, v := range in {\n\t\t\tif !yield(v, k) {\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}\n}\n\n// Assign merges multiple sequences of maps from left to right.\n// Play: https://go.dev/play/p/lwngaIFkFAg\nfunc Assign[K comparable, V any, Map ~map[K]V](maps ...iter.Seq[Map]) Map {\n\tout := make(Map)\n\n\tfor i := range maps {\n\t\tfor item := range maps[i] {\n\t\t\tfor k, v := range item {\n\t\t\t\tout[k] = v //nolint:modernize\n\t\t\t}\n\t\t}\n\t}\n\n\treturn out\n}\n\n// ChunkEntries splits a map into a sequence of elements in groups of length equal to its size. If the map cannot be split evenly,\n// the final chunk will contain the remaining elements.\n// Play: https://go.dev/play/p/xtX-so65kDp\nfunc ChunkEntries[K comparable, V any](m map[K]V, size int) iter.Seq[map[K]V] {\n\tif size <= 0 {\n\t\tpanic(\"it.ChunkEntries: size must be greater than 0\")\n\t}\n\n\treturn func(yield func(map[K]V) bool) {\n\t\tvar result map[K]V\n\t\tfor k, v := range m {\n\t\t\tif result == nil {\n\t\t\t\tresult = make(map[K]V, size)\n\t\t\t}\n\t\t\tresult[k] = v\n\t\t\tif len(result) == size {\n\t\t\t\tif !yield(result) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tresult = nil\n\t\t\t}\n\t\t}\n\t\tif result != nil {\n\t\t\tyield(result)\n\t\t}\n\t}\n}\n\n// MapToSeq transforms a map into a sequence based on specified transform.\n// Play: https://go.dev/play/p/SEV4Vz5XFac\nfunc MapToSeq[K comparable, V, R any](in map[K]V, transform func(key K, value V) R) iter.Seq[R] {\n\treturn func(yield func(R) bool) {\n\t\tfor k, v := range in {\n\t\t\tif !yield(transform(k, v)) {\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}\n}\n\n// FilterMapToSeq transforms a map into a sequence based on specified transform.\n// The transform returns a value and a boolean. If the boolean is true, the value is added to the result sequence.\n// If the boolean is false, the value is not added to the result sequence.\n// The order of the keys in the input map is not specified and the order of the keys in the output sequence is not guaranteed.\n// Play: https://go.dev/play/p/HQgi01x8A4o\nfunc FilterMapToSeq[K comparable, V, R any](in map[K]V, transform func(key K, value V) (R, bool)) iter.Seq[R] {\n\treturn func(yield func(R) bool) {\n\t\tfor k, v := range in {\n\t\t\tif v, ok := transform(k, v); ok && !yield(v) {\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}\n}\n\n// FilterKeys transforms a map into a sequence based on predicate returns true for specific elements.\n// It is a mix of Filter and Keys.\n// Play: https://go.dev/play/p/ODxc6_IiWtO\nfunc FilterKeys[K comparable, V any](in map[K]V, predicate func(key K, value V) bool) iter.Seq[K] {\n\treturn func(yield func(K) bool) {\n\t\tfor k, v := range in {\n\t\t\tif predicate(k, v) && !yield(k) {\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}\n}\n\n// FilterValues transforms a map into a sequence based on predicate returns true for specific elements.\n// It is a mix of Filter and Values.\n// Play: https://go.dev/play/p/9SBiyOqgrl8\nfunc FilterValues[K comparable, V any](in map[K]V, predicate func(key K, value V) bool) iter.Seq[V] {\n\treturn func(yield func(V) bool) {\n\t\tfor k, v := range in {\n\t\t\tif predicate(k, v) && !yield(v) {\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}\n}\n\n// SeqToSeq2 converts a sequence into a sequence of key-value pairs keyed by index.\n// Play: https://go.dev/play/p/V5wL9xY8nQr\nfunc SeqToSeq2[T any](in iter.Seq[T]) iter.Seq2[int, T] {\n\treturn func(yield func(int, T) bool) {\n\t\tvar i int\n\t\tfor item := range in {\n\t\t\tif !yield(i, item) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\ti++\n\t\t}\n\t}\n}\n\n// Seq2KeyToSeq converts a sequence of key-value pairs into a sequence of keys.\n// Play: https://go.dev/play/p/W6xM7zZ9oSt\nfunc Seq2KeyToSeq[K, V any](in iter.Seq2[K, V]) iter.Seq[K] {\n\treturn func(yield func(K) bool) {\n\t\tfor k := range in {\n\t\t\tif !yield(k) {\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}\n}\n\n// Seq2ValueToSeq converts a sequence of key-value pairs into a sequence of values.\n// Play: https://go.dev/play/p/X7yN8aA1pUv\nfunc Seq2ValueToSeq[K, V any](in iter.Seq2[K, V]) iter.Seq[V] {\n\treturn func(yield func(V) bool) {\n\t\tfor _, v := range in {\n\t\t\tif !yield(v) {\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "it/map_example_test.go",
    "content": "//go:build go1.23\n\npackage it\n\nimport (\n\t\"fmt\"\n\t\"maps\"\n\t\"slices\"\n\t\"sort\"\n)\n\nfunc ExampleKeys() {\n\tkv := map[string]int{\"foo\": 1, \"bar\": 2}\n\tkv2 := map[string]int{\"baz\": 3}\n\n\tresult := slices.Collect(Keys(kv, kv2))\n\tsort.Strings(result)\n\tfmt.Printf(\"%v\", result)\n\t// Output: [bar baz foo]\n}\n\nfunc ExampleUniqKeys() {\n\tkv := map[string]int{\"foo\": 1, \"bar\": 2}\n\tkv2 := map[string]int{\"bar\": 3}\n\n\tresult := slices.Collect(UniqKeys(kv, kv2))\n\tsort.Strings(result)\n\tfmt.Printf(\"%v\", result)\n\t// Output: [bar foo]\n}\n\nfunc ExampleValues() {\n\tkv := map[string]int{\"foo\": 1, \"bar\": 2}\n\tkv2 := map[string]int{\"baz\": 3}\n\n\tresult := slices.Collect(Values(kv, kv2))\n\n\tsort.Ints(result)\n\tfmt.Printf(\"%v\", result)\n\t// Output: [1 2 3]\n}\n\nfunc ExampleUniqValues() {\n\tkv := map[string]int{\"foo\": 1, \"bar\": 2}\n\tkv2 := map[string]int{\"baz\": 2}\n\n\tresult := slices.Collect(UniqValues(kv, kv2))\n\n\tsort.Ints(result)\n\tfmt.Printf(\"%v\", result)\n\t// Output: [1 2]\n}\n\nfunc ExampleEntries() {\n\tkv := map[string]int{\"foo\": 1, \"bar\": 2, \"baz\": 3}\n\n\tresult := maps.Collect(Entries(kv))\n\n\tfmt.Printf(\"%v %v %v %v\", len(result), result[\"foo\"], result[\"bar\"], result[\"baz\"])\n\t// Output: 3 1 2 3\n}\n\nfunc ExampleFromEntries() {\n\tresult := FromEntries(maps.All(map[string]int{\n\t\t\"foo\": 1,\n\t\t\"bar\": 2,\n\t\t\"baz\": 3,\n\t}))\n\n\tfmt.Printf(\"%v %v %v %v\", len(result), result[\"foo\"], result[\"bar\"], result[\"baz\"])\n\t// Output: 3 1 2 3\n}\n\nfunc ExampleInvert() {\n\tkv := maps.All(map[string]int{\"foo\": 1, \"bar\": 2, \"baz\": 3})\n\n\tresult := maps.Collect(Invert(kv))\n\n\tfmt.Printf(\"%v %v %v %v\", len(result), result[1], result[2], result[3])\n\t// Output: 3 foo bar baz\n}\n\nfunc ExampleAssign() {\n\tresult := Assign(values(\n\t\tmap[string]int{\"a\": 1, \"b\": 2},\n\t\tmap[string]int{\"b\": 3, \"c\": 4},\n\t))\n\n\tfmt.Printf(\"%v %v %v %v\", len(result), result[\"a\"], result[\"b\"], result[\"c\"])\n\t// Output: 3 1 3 4\n}\n\nfunc ExampleChunkEntries() {\n\tresult := ChunkEntries(\n\t\tmap[string]int{\n\t\t\t\"a\": 1,\n\t\t\t\"b\": 2,\n\t\t\t\"c\": 3,\n\t\t\t\"d\": 4,\n\t\t\t\"e\": 5,\n\t\t},\n\t\t3,\n\t)\n\n\tfor r := range result {\n\t\tfmt.Printf(\"%d\\n\", len(r))\n\t}\n\t// Output:\n\t// 3\n\t// 2\n}\n\nfunc ExampleMapToSeq() {\n\tkv := map[int]int64{1: 1, 2: 2, 3: 3, 4: 4}\n\n\tresult := slices.Collect(MapToSeq(kv, func(k int, v int64) string {\n\t\treturn fmt.Sprintf(\"%d_%d\", k, v)\n\t}))\n\n\tsort.Strings(result)\n\tfmt.Printf(\"%v\", result)\n\t// Output: [1_1 2_2 3_3 4_4]\n}\n\nfunc ExampleFilterMapToSeq() {\n\tkv := map[int]int64{1: 1, 2: 2, 3: 3, 4: 4}\n\n\tresult := slices.Collect(FilterMapToSeq(kv, func(k int, v int64) (string, bool) {\n\t\treturn fmt.Sprintf(\"%d_%d\", k, v), k%2 == 0\n\t}))\n\n\tsort.Strings(result)\n\tfmt.Printf(\"%v\", result)\n\t// Output: [2_2 4_4]\n}\n\nfunc ExampleFilterKeys() {\n\tkv := map[int]string{1: \"foo\", 2: \"bar\", 3: \"baz\"}\n\n\tresult := slices.Collect(FilterKeys(kv, func(k int, v string) bool {\n\t\treturn v == \"foo\"\n\t}))\n\n\tfmt.Printf(\"%v\", result)\n\t// Output: [1]\n}\n\nfunc ExampleFilterValues() {\n\tkv := map[int]string{1: \"foo\", 2: \"bar\", 3: \"baz\"}\n\n\tresult := slices.Collect(FilterValues(kv, func(k int, v string) bool {\n\t\treturn v == \"foo\"\n\t}))\n\n\tfmt.Printf(\"%v\", result)\n\t// Output: [foo]\n}\n\nfunc ExampleSeqToSeq2() {\n\tresult := maps.Collect(SeqToSeq2(slices.Values([]string{\"foo\", \"bar\", \"baz\"})))\n\n\tfmt.Printf(\"%v %v %v %v\", len(result), result[0], result[1], result[2])\n\t// Output: 3 foo bar baz\n}\n\nfunc ExampleSeq2KeyToSeq() {\n\tresult := slices.Collect(Seq2KeyToSeq(maps.All(map[string]int{\n\t\t\"foo\": 1,\n\t\t\"bar\": 2,\n\t\t\"baz\": 3,\n\t})))\n\n\tsort.Strings(result)\n\tfmt.Printf(\"%v\", result)\n\t// Output: [bar baz foo]\n}\n\nfunc ExampleSeq2ValueToSeq() {\n\tresult := slices.Collect(Seq2ValueToSeq(maps.All(map[string]int{\n\t\t\"foo\": 1,\n\t\t\"bar\": 2,\n\t\t\"baz\": 3,\n\t})))\n\n\tsort.Ints(result)\n\tfmt.Printf(\"%v\", result)\n\t// Output: [1 2 3]\n}\n"
  },
  {
    "path": "it/map_test.go",
    "content": "//go:build go1.23\n\npackage it\n\nimport (\n\t\"fmt\"\n\t\"maps\"\n\t\"slices\"\n\t\"strconv\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestKeys(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tr1 := slices.Collect(Keys(map[string]int{\"foo\": 1, \"bar\": 2}))\n\tis.ElementsMatch(r1, []string{\"bar\", \"foo\"})\n\n\tr2 := slices.Collect(Keys(map[string]int{}))\n\tis.Empty(r2)\n\n\tr3 := slices.Collect(Keys(map[string]int{\"foo\": 1, \"bar\": 2}, map[string]int{\"baz\": 3}))\n\tis.ElementsMatch(r3, []string{\"bar\", \"baz\", \"foo\"})\n\n\tr4 := slices.Collect(Keys[string, int]())\n\tis.Empty(r4)\n\n\tr5 := slices.Collect(Keys(map[string]int{\"foo\": 1, \"bar\": 2}, map[string]int{\"bar\": 3}))\n\tis.ElementsMatch(r5, []string{\"bar\", \"bar\", \"foo\"})\n}\n\nfunc TestUniqKeys(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tr1 := slices.Collect(UniqKeys(map[string]int{\"foo\": 1, \"bar\": 2}))\n\tis.ElementsMatch(r1, []string{\"bar\", \"foo\"})\n\n\tr2 := slices.Collect(UniqKeys(map[string]int{}))\n\tis.Empty(r2)\n\n\tr3 := slices.Collect(UniqKeys(map[string]int{\"foo\": 1, \"bar\": 2}, map[string]int{\"baz\": 3}))\n\tis.ElementsMatch(r3, []string{\"bar\", \"baz\", \"foo\"})\n\n\tr4 := slices.Collect(UniqKeys[string, int]())\n\tis.Empty(r4)\n\n\tr5 := slices.Collect(UniqKeys(map[string]int{\"foo\": 1, \"bar\": 2}, map[string]int{\"foo\": 1, \"bar\": 3}))\n\tis.ElementsMatch(r5, []string{\"bar\", \"foo\"})\n\n\t// check order\n\tr6 := slices.Collect(UniqKeys(map[string]int{\"foo\": 1}, map[string]int{\"bar\": 3}))\n\tis.Equal([]string{\"foo\", \"bar\"}, r6)\n}\n\nfunc TestValues(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tr1 := slices.Collect(Values(map[string]int{\"foo\": 1, \"bar\": 2}))\n\tis.ElementsMatch(r1, []int{1, 2})\n\n\tr2 := slices.Collect(Values(map[string]int{}))\n\tis.Empty(r2)\n\n\tr3 := slices.Collect(Values(map[string]int{\"foo\": 1, \"bar\": 2}, map[string]int{\"baz\": 3}))\n\tis.ElementsMatch(r3, []int{1, 2, 3})\n\n\tr4 := slices.Collect(Values[string, int]())\n\tis.Empty(r4)\n\n\tr5 := slices.Collect(Values(map[string]int{\"foo\": 1, \"bar\": 2}, map[string]int{\"foo\": 1, \"bar\": 3}))\n\tis.ElementsMatch(r5, []int{1, 1, 2, 3})\n}\n\nfunc TestUniqValues(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tr1 := slices.Collect(UniqValues(map[string]int{\"foo\": 1, \"bar\": 2}))\n\tis.ElementsMatch(r1, []int{1, 2})\n\n\tr2 := slices.Collect(UniqValues(map[string]int{}))\n\tis.Empty(r2)\n\n\tr3 := slices.Collect(UniqValues(map[string]int{\"foo\": 1, \"bar\": 2}, map[string]int{\"baz\": 3}))\n\tis.ElementsMatch(r3, []int{1, 2, 3})\n\n\tr4 := slices.Collect(UniqValues[string, int]())\n\tis.Empty(r4)\n\n\tr5 := slices.Collect(UniqValues(map[string]int{\"foo\": 1, \"bar\": 2}, map[string]int{\"foo\": 1, \"bar\": 3}))\n\tis.ElementsMatch(r5, []int{1, 2, 3})\n\n\tr6 := slices.Collect(UniqValues(map[string]int{\"foo\": 1, \"bar\": 1}, map[string]int{\"foo\": 1, \"bar\": 3}))\n\tis.ElementsMatch(r6, []int{1, 3})\n\n\t// check order\n\tr7 := slices.Collect(UniqValues(map[string]int{\"foo\": 1}, map[string]int{\"bar\": 3}))\n\tis.Equal([]int{1, 3}, r7)\n}\n\nfunc TestEntries(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tr1 := maps.Collect(Entries(map[string]int{\"foo\": 1, \"bar\": 2}))\n\tis.Equal(map[string]int{\"foo\": 1, \"bar\": 2}, r1)\n}\n\nfunc TestToPairs(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tr1 := maps.Collect(ToPairs(map[string]int{\"foo\": 1, \"bar\": 2}))\n\tis.Equal(map[string]int{\"foo\": 1, \"bar\": 2}, r1)\n}\n\nfunc TestFromEntries(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tr1 := FromEntries(maps.All(map[string]int{\"foo\": 1, \"bar\": 2}))\n\n\tis.Len(r1, 2)\n\tis.Equal(1, r1[\"foo\"])\n\tis.Equal(2, r1[\"bar\"])\n}\n\nfunc TestFromPairs(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tr1 := FromPairs(maps.All(map[string]int{\"baz\": 3, \"qux\": 4}))\n\n\tis.Len(r1, 2)\n\tis.Equal(3, r1[\"baz\"])\n\tis.Equal(4, r1[\"qux\"])\n}\n\nfunc TestInvert(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tr1 := Invert(maps.All(map[string]int{\"a\": 1, \"b\": 2}))\n\tr2 := Invert(maps.All(map[string]int{\"a\": 1, \"b\": 2, \"c\": 1}))\n\n\tis.Equal(map[int]string{1: \"a\", 2: \"b\"}, maps.Collect(r1))\n\tis.Len(maps.Collect(r2), 2)\n}\n\nfunc TestAssign(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := Assign(values(map[string]int{\"a\": 1, \"b\": 2}, map[string]int{\"b\": 3, \"c\": 4}))\n\tis.Equal(map[string]int{\"a\": 1, \"b\": 3, \"c\": 4}, result1)\n\n\ttype myMap map[string]int\n\tbefore := myMap{\"\": 0, \"foobar\": 6, \"baz\": 3}\n\tafter := Assign(values(before, before))\n\tis.IsType(myMap{}, after, \"type preserved\")\n}\n\nfunc TestChunkEntries(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := ChunkEntries(map[string]int{\"a\": 1, \"b\": 2, \"c\": 3, \"d\": 4, \"e\": 5}, 2)\n\tresult2 := ChunkEntries(map[string]int{\"a\": 1, \"b\": 2, \"c\": 3, \"d\": 4, \"e\": 5}, 3)\n\tresult3 := ChunkEntries(map[string]int{}, 2)\n\tresult4 := ChunkEntries(map[string]int{\"a\": 1}, 2)\n\tresult5 := ChunkEntries(map[string]int{\"a\": 1, \"b\": 2}, 1)\n\n\tis.Len(slices.Collect(result1), 3)\n\tis.Len(slices.Collect(result2), 2)\n\tis.Empty(slices.Collect(result3))\n\tis.Len(slices.Collect(result4), 1)\n\tis.Len(slices.Collect(result5), 2)\n\n\tis.PanicsWithValue(\"it.ChunkEntries: size must be greater than 0\", func() {\n\t\tChunkEntries(map[string]int{\"a\": 1}, 0)\n\t})\n\tis.PanicsWithValue(\"it.ChunkEntries: size must be greater than 0\", func() {\n\t\tChunkEntries(map[string]int{\"a\": 1}, -1)\n\t})\n\n\ttype myStruct struct {\n\t\tName  string\n\t\tValue int\n\t}\n\n\tallStructs := []myStruct{{\"one\", 1}, {\"two\", 2}, {\"three\", 3}}\n\tnonempty := ChunkEntries(map[string]myStruct{\"a\": allStructs[0], \"b\": allStructs[1], \"c\": allStructs[2]}, 2)\n\tis.Len(slices.Collect(nonempty), 2)\n\n\toriginalMap := map[string]int{\"a\": 1, \"b\": 2, \"c\": 3, \"d\": 4, \"e\": 5}\n\tresult6 := slices.Collect(ChunkEntries(originalMap, 2))\n\tfor k := range result6[0] {\n\t\tresult6[0][k] = 10\n\t}\n\tis.Equal(map[string]int{\"a\": 1, \"b\": 2, \"c\": 3, \"d\": 4, \"e\": 5}, originalMap)\n}\n\nfunc TestMapToSeq(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := MapToSeq(map[int]int{1: 5, 2: 6, 3: 7, 4: 8}, func(k, v int) string {\n\t\treturn fmt.Sprintf(\"%d_%d\", k, v)\n\t})\n\tresult2 := MapToSeq(map[int]int{1: 5, 2: 6, 3: 7, 4: 8}, func(k, _ int) string {\n\t\treturn strconv.FormatInt(int64(k), 10)\n\t})\n\n\tis.ElementsMatch(slices.Collect(result1), []string{\"1_5\", \"2_6\", \"3_7\", \"4_8\"})\n\tis.ElementsMatch(slices.Collect(result2), []string{\"1\", \"2\", \"3\", \"4\"})\n}\n\nfunc TestFilterMapToSeq(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := FilterMapToSeq(map[int]int{1: 5, 2: 6, 3: 7, 4: 8}, func(k, v int) (string, bool) {\n\t\treturn fmt.Sprintf(\"%d_%d\", k, v), k%2 == 0\n\t})\n\tresult2 := FilterMapToSeq(map[int]int{1: 5, 2: 6, 3: 7, 4: 8}, func(k, _ int) (string, bool) {\n\t\treturn strconv.FormatInt(int64(k), 10), k%2 == 0\n\t})\n\n\tis.ElementsMatch(slices.Collect(result1), []string{\"2_6\", \"4_8\"})\n\tis.ElementsMatch(slices.Collect(result2), []string{\"2\", \"4\"})\n}\n\nfunc TestFilterKeys(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := FilterKeys(map[int]string{1: \"foo\", 2: \"bar\", 3: \"baz\"}, func(k int, v string) bool {\n\t\treturn v == \"foo\"\n\t})\n\tis.Equal([]int{1}, slices.Collect(result1))\n\n\tresult2 := FilterKeys(map[string]int{\"foo\": 1, \"bar\": 2, \"baz\": 3}, func(k string, v int) bool {\n\t\treturn false\n\t})\n\tis.Empty(slices.Collect(result2))\n}\n\nfunc TestFilterValues(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := FilterValues(map[int]string{1: \"foo\", 2: \"bar\", 3: \"baz\"}, func(k int, v string) bool {\n\t\treturn v == \"foo\"\n\t})\n\tis.Equal([]string{\"foo\"}, slices.Collect(result1))\n\n\tresult2 := FilterValues(map[string]int{\"foo\": 1, \"bar\": 2, \"baz\": 3}, func(k string, v int) bool {\n\t\treturn false\n\t})\n\tis.Empty(slices.Collect(result2))\n}\n\nfunc TestSeqToSeq2(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tr1 := maps.Collect(SeqToSeq2(values(\"foo\", \"bar\")))\n\tis.Equal(map[int]string{0: \"foo\", 1: \"bar\"}, r1)\n\n\tr2 := maps.Collect(SeqToSeq2(values[string]()))\n\tis.Empty(r2)\n}\n\nfunc TestSeq2KeyToSeq(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tr1 := slices.Collect(Seq2KeyToSeq(maps.All(map[string]int{\"foo\": 4, \"bar\": 5})))\n\tis.ElementsMatch([]string{\"foo\", \"bar\"}, r1)\n\n\tr2 := slices.Collect(Seq2KeyToSeq(maps.All(map[string]int{})))\n\tis.Empty(r2)\n}\n\nfunc TestSeq2ValueToSeq(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tr1 := slices.Collect(Seq2ValueToSeq(maps.All(map[string]int{\"foo\": 4, \"bar\": 5})))\n\tis.ElementsMatch([]int{4, 5}, r1)\n\n\tr2 := slices.Collect(Seq2ValueToSeq(maps.All(map[string]int{})))\n\tis.Empty(r2)\n}\n\nfunc BenchmarkAssign(b *testing.B) {\n\tcounts := []int{32768, 1024, 128, 32, 2}\n\n\tallDifferentMap := func(b *testing.B, n int) []map[string]int {\n\t\tb.Helper()\n\t\tdefer b.ResetTimer()\n\t\tm := make([]map[string]int, 0, n)\n\t\tfor i := range n {\n\t\t\tm = append(m, map[string]int{\n\t\t\t\tstrconv.Itoa(i): i,\n\t\t\t\tstrconv.Itoa(i): i,\n\t\t\t\tstrconv.Itoa(i): i,\n\t\t\t\tstrconv.Itoa(i): i,\n\t\t\t\tstrconv.Itoa(i): i,\n\t\t\t\tstrconv.Itoa(i): i,\n\t\t\t},\n\t\t\t)\n\t\t}\n\t\treturn m\n\t}\n\n\tallTheSameMap := func(b *testing.B, n int) []map[string]int {\n\t\tb.Helper()\n\t\tdefer b.ResetTimer()\n\t\tm := make([]map[string]int, 0, n)\n\t\tfor range n {\n\t\t\tm = append(m, map[string]int{\n\t\t\t\t\"a\": 1,\n\t\t\t\t\"b\": 2,\n\t\t\t\t\"c\": 3,\n\t\t\t\t\"d\": 4,\n\t\t\t\t\"e\": 5,\n\t\t\t\t\"f\": 6,\n\t\t\t},\n\t\t\t)\n\t\t}\n\t\treturn m\n\t}\n\n\tfor _, count := range counts {\n\t\tdifferentMap := allDifferentMap(b, count)\n\t\tsameMap := allTheSameMap(b, count)\n\n\t\tb.Run(strconv.Itoa(count), func(b *testing.B) {\n\t\t\ttestCases := []struct {\n\t\t\t\tname string\n\t\t\t\tin   []map[string]int\n\t\t\t}{\n\t\t\t\t{\"different\", differentMap},\n\t\t\t\t{\"same\", sameMap},\n\t\t\t}\n\n\t\t\tfor _, tc := range testCases {\n\t\t\t\tb.Run(tc.name, func(b *testing.B) {\n\t\t\t\t\tb.ResetTimer()\n\t\t\t\t\tfor range b.N {\n\t\t\t\t\t\tresult := Assign(values(tc.in...))\n\t\t\t\t\t\t_ = result\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "it/math.go",
    "content": "//go:build go1.23\n\npackage it\n\nimport (\n\t\"iter\"\n\n\t\"github.com/samber/lo\"\n\t\"github.com/samber/lo/internal/constraints\"\n)\n\n// Range creates a sequence of numbers (positive and/or negative) with given length.\n// Play: https://go.dev/play/p/79QUZBa8Ukn\nfunc Range(elementNum int) iter.Seq[int] {\n\tstep := lo.Ternary(elementNum < 0, -1, 1)\n\tlength := elementNum * step\n\treturn func(yield func(int) bool) {\n\t\tfor i, j := 0, 0; i < length; i, j = i+1, j+step {\n\t\t\tif !yield(j) {\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}\n}\n\n// RangeFrom creates a sequence of numbers from start with specified length.\n// Play: https://go.dev/play/p/WHP_NI5scj9\nfunc RangeFrom[T constraints.Integer | constraints.Float](start T, elementNum int) iter.Seq[T] {\n\tstep := lo.Ternary(elementNum < 0, -1, 1)\n\tlength := elementNum * step\n\treturn func(yield func(T) bool) {\n\t\tfor i, j := 0, start; i < length; i, j = i+1, j+T(step) {\n\t\t\tif !yield(j) {\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}\n}\n\n// RangeWithSteps creates a sequence of numbers (positive and/or negative) progressing from start up to, but not including end.\n// step set to zero will return an empty sequence.\n// Play: https://go.dev/play/p/qxm2YNLG0vT\nfunc RangeWithSteps[T constraints.Integer | constraints.Float](start, end, step T) iter.Seq[T] {\n\treturn func(yield func(T) bool) {\n\t\tif start == end || step == 0 {\n\t\t\treturn\n\t\t}\n\t\tif start < end {\n\t\t\tif step < 0 {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tfor i := start; i < end; i += step {\n\t\t\t\tif !yield(i) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif step > 0 {\n\t\t\treturn\n\t\t}\n\t\tfor i := start; i > end; i += step {\n\t\t\tif !yield(i) {\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}\n}\n\n// Sum sums the values in a collection. If collection is empty 0 is returned.\n// Will iterate through the entire sequence.\n// Play: https://go.dev/play/p/nHbGFOEIeTa\nfunc Sum[T constraints.Float | constraints.Integer | constraints.Complex](collection iter.Seq[T]) T {\n\treturn SumBy(collection, func(item T) T { return item })\n}\n\n// SumBy summarizes the values in a collection using the given return value from the iteration function. If collection is empty 0 is returned.\n// Will iterate through the entire sequence.\n// Play: https://go.dev/play/p/ZNiqXNMu5QP\nfunc SumBy[T any, R constraints.Float | constraints.Integer | constraints.Complex](collection iter.Seq[T], transform func(item T) R) R {\n\tvar sum R\n\tfor item := range collection {\n\t\tsum += transform(item)\n\t}\n\treturn sum\n}\n\n// Product gets the product of the values in a collection. If collection is empty 1 is returned.\n// Will iterate through the entire sequence.\n// Play: https://go.dev/play/p/AOMCD1Yl5Bc\nfunc Product[T constraints.Float | constraints.Integer | constraints.Complex](collection iter.Seq[T]) T {\n\treturn ProductBy(collection, func(item T) T { return item })\n}\n\n// ProductBy summarizes the values in a collection using the given return value from the iteration function. If collection is empty 1 is returned.\n// Will iterate through the entire sequence.\n// Play: https://go.dev/play/p/dgFCRJrlPHY\nfunc ProductBy[T any, R constraints.Float | constraints.Integer | constraints.Complex](collection iter.Seq[T], transform func(item T) R) R {\n\tvar product R = 1\n\tfor item := range collection {\n\t\tproduct *= transform(item)\n\t}\n\treturn product\n}\n\n// Mean calculates the mean of a collection of numbers.\n// Will iterate through the entire sequence.\n// Play: https://go.dev/play/p/Lez0CsvVRl_l\nfunc Mean[T constraints.Float | constraints.Integer](collection iter.Seq[T]) T {\n\treturn MeanBy(collection, func(item T) T { return item })\n}\n\n// MeanBy calculates the mean of a collection of numbers using the given return value from the iteration function.\n// Will iterate through the entire sequence.\n// Play: https://go.dev/play/p/Ked4rpztH5Y\nfunc MeanBy[T any, R constraints.Float | constraints.Integer](collection iter.Seq[T], transform func(item T) R) R {\n\tvar sum R\n\tvar length R\n\tfor item := range collection {\n\t\tsum += transform(item)\n\t\tlength++\n\t}\n\tif length == 0 {\n\t\treturn 0\n\t}\n\treturn sum / length\n}\n\n// Mode returns the mode (most frequent value) of a collection.\n// If multiple values have the same highest frequency, then multiple values are returned.\n// If the collection is empty, then the zero value of T is returned.\n// Will iterate through the entire sequence and allocate a map large enough to hold all distinct elements.\n// Long heterogeneous input sequences can cause excessive memory usage.\n// Play: https://go.dev/play/p/c_cmMMA5EhH\nfunc Mode[T constraints.Integer | constraints.Float](collection iter.Seq[T]) []T {\n\tmode := make([]T, 0)\n\tmaxFreq := 0\n\tfrequency := make(map[T]int)\n\n\tfor item := range collection {\n\t\tfrequency[item]++\n\t\tcount := frequency[item]\n\n\t\tif count > maxFreq {\n\t\t\tmaxFreq = count\n\t\t\tmode = append(mode[:0], item)\n\t\t} else if count == maxFreq {\n\t\t\tmode = append(mode, item)\n\t\t}\n\t}\n\n\treturn mode[:len(mode):len(mode)]\n}\n"
  },
  {
    "path": "it/math_example_test.go",
    "content": "//go:build go1.23\n\npackage it\n\nimport (\n\t\"fmt\"\n\t\"slices\"\n)\n\nfunc ExampleRange() {\n\tresult1 := Range(4)\n\tresult2 := Range(-4)\n\tresult3 := RangeFrom(1, 5)\n\tresult4 := RangeFrom(1.0, 5)\n\tresult5 := RangeWithSteps(0, 20, 5)\n\tresult6 := RangeWithSteps[float32](-1.0, -4.0, -1.0)\n\tresult7 := RangeWithSteps(1, 4, -1)\n\tresult8 := Range(0)\n\n\tfmt.Printf(\"%v\\n\", slices.Collect(result1))\n\tfmt.Printf(\"%v\\n\", slices.Collect(result2))\n\tfmt.Printf(\"%v\\n\", slices.Collect(result3))\n\tfmt.Printf(\"%v\\n\", slices.Collect(result4))\n\tfmt.Printf(\"%v\\n\", slices.Collect(result5))\n\tfmt.Printf(\"%v\\n\", slices.Collect(result6))\n\tfmt.Printf(\"%v\\n\", slices.Collect(result7))\n\tfmt.Printf(\"%v\\n\", slices.Collect(result8))\n\t// Output:\n\t// [0 1 2 3]\n\t// [0 -1 -2 -3]\n\t// [1 2 3 4 5]\n\t// [1 2 3 4 5]\n\t// [0 5 10 15]\n\t// [-1 -2 -3]\n\t// []\n\t// []\n}\n\nfunc ExampleSum() {\n\tints := slices.Values([]int{1, 2, 3, 4, 5})\n\n\tsum := Sum(ints)\n\n\tfmt.Printf(\"%v\", sum)\n\t// Output: 15\n}\n\nfunc ExampleSumBy() {\n\tints := slices.Values([]string{\"foo\", \"bar\"})\n\n\tresult := SumBy(ints, func(item string) int {\n\t\treturn len(item)\n\t})\n\n\tfmt.Printf(\"%v\", result)\n\t// Output: 6\n}\n\nfunc ExampleProduct() {\n\tints := slices.Values([]int{1, 2, 3, 4, 5})\n\n\tresult := Product(ints)\n\n\tfmt.Printf(\"%v\", result)\n\t// Output: 120\n}\n\nfunc ExampleProductBy() {\n\tstrs := slices.Values([]string{\"foo\", \"bar\"})\n\n\tresult := ProductBy(strs, func(item string) int {\n\t\treturn len(item)\n\t})\n\n\tfmt.Printf(\"%v\", result)\n\t// Output: 9\n}\n\nfunc ExampleMean() {\n\tints := slices.Values([]int{1, 2, 3, 4, 5})\n\n\tresult := Mean(ints)\n\n\tfmt.Printf(\"%v\", result)\n\t// Output: 3\n}\n\nfunc ExampleMeanBy() {\n\tstrs := slices.Values([]string{\"foo\", \"bar\"})\n\n\tresult := MeanBy(strs, func(item string) int {\n\t\treturn len(item)\n\t})\n\n\tfmt.Printf(\"%v\", result)\n\t// Output: 3\n}\n"
  },
  {
    "path": "it/math_test.go",
    "content": "//go:build go1.23\n\npackage it\n\nimport (\n\t\"slices\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestRange(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := Range(4)\n\tresult2 := Range(-4)\n\tresult3 := Range(0)\n\tis.Equal([]int{0, 1, 2, 3}, slices.Collect(result1))\n\tis.Equal([]int{0, -1, -2, -3}, slices.Collect(result2))\n\tis.Empty(slices.Collect(result3))\n}\n\nfunc TestRangeFrom(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := RangeFrom(1, 5)\n\tresult2 := RangeFrom(-1, -5)\n\tresult3 := RangeFrom(10, 0)\n\tresult4 := RangeFrom(2.0, 3)\n\tresult5 := RangeFrom(-2.0, -3)\n\tresult6 := RangeFrom(2.5, 3)\n\tresult7 := RangeFrom(-2.5, -3)\n\tis.Equal([]int{1, 2, 3, 4, 5}, slices.Collect(result1))\n\tis.Equal([]int{-1, -2, -3, -4, -5}, slices.Collect(result2))\n\tis.Empty(slices.Collect(result3))\n\tis.Equal([]float64{2.0, 3.0, 4.0}, slices.Collect(result4))\n\tis.Equal([]float64{-2.0, -3.0, -4.0}, slices.Collect(result5))\n\tis.Equal([]float64{2.5, 3.5, 4.5}, slices.Collect(result6))\n\tis.Equal([]float64{-2.5, -3.5, -4.5}, slices.Collect(result7))\n}\n\nfunc TestRangeWithSteps(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := RangeWithSteps(0, 20, 6)\n\tresult2 := RangeWithSteps(0, 3, -5)\n\tresult3 := RangeWithSteps(1, 1, 0)\n\tresult4 := RangeWithSteps(3, 2, 1)\n\tresult5 := RangeWithSteps(1.0, 4.0, 2.0)\n\tresult6 := RangeWithSteps[float32](-1.0, -4.0, -1.0)\n\tresult7 := RangeWithSteps(0.0, 0.5, 1.0)\n\tresult8 := RangeWithSteps(0.0, 0.3, 0.1)\n\tresult9 := RangeWithSteps(0.0, 5.5, 2.5)\n\n\ttype f64 float64\n\tresult10 := RangeWithSteps[f64](0.0, 0.3, 0.1)\n\n\tis.Equal([]int{0, 6, 12, 18}, slices.Collect(result1))\n\tis.Empty(slices.Collect(result2))\n\tis.Empty(slices.Collect(result3))\n\tis.Empty(slices.Collect(result4))\n\tis.Equal([]float64{1.0, 3.0}, slices.Collect(result5))\n\tis.Equal([]float32{-1.0, -2.0, -3.0}, slices.Collect(result6))\n\tis.Equal([]float64{0.0}, slices.Collect(result7))\n\tis.Equal([]float64{0.0, 0.1, 0.2}, slices.Collect(result8))\n\tis.Equal([]float64{0.0, 2.5, 5.0}, slices.Collect(result9))\n\tis.Equal([]f64{0.0, 0.1, 0.2}, slices.Collect(result10))\n}\n\nfunc TestSum(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := Sum(values[float32](2.3, 3.3, 4, 5.3))\n\tresult2 := Sum(values[int32](2, 3, 4, 5))\n\tresult3 := Sum(values[uint32](2, 3, 4, 5))\n\tresult4 := Sum(values[uint32]())\n\tresult5 := Sum(values[complex128](4_4, 2_2))\n\n\tis.InEpsilon(14.9, result1, 1e-7)\n\tis.Equal(int32(14), result2)\n\tis.Equal(uint32(14), result3)\n\tis.Equal(uint32(0), result4)\n\tis.Equal(complex128(6_6), result5)\n}\n\nfunc TestSumBy(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := SumBy(values[float32](2.3, 3.3, 4, 5.3), func(n float32) float32 { return n })\n\tresult2 := SumBy(values[int32](2, 3, 4, 5), func(n int32) int32 { return n })\n\tresult3 := SumBy(values[uint32](2, 3, 4, 5), func(n uint32) uint32 { return n })\n\tresult4 := SumBy(values[uint32](), func(n uint32) uint32 { return n })\n\tresult5 := SumBy(values[complex128](4_4, 2_2), func(n complex128) complex128 { return n })\n\n\tis.InEpsilon(14.9, result1, 1e-7)\n\tis.Equal(int32(14), result2)\n\tis.Equal(uint32(14), result3)\n\tis.Equal(uint32(0), result4)\n\tis.Equal(complex128(6_6), result5)\n}\n\nfunc TestProduct(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := Product(values[float32](2.3, 3.3, 4, 5.3))\n\tresult2 := Product(values[int32](2, 3, 4, 5))\n\tresult3 := Product(values[int32](7, 8, 9, 0))\n\tresult4 := Product(values[int32](7, -1, 9, 2))\n\tresult5 := Product(values[uint32](2, 3, 4, 5))\n\tresult6 := Product(values[uint32]())\n\tresult7 := Product(values[complex128](4_4, 2_2))\n\n\tis.InEpsilon(160.908, result1, 1e-7)\n\tis.Equal(int32(120), result2)\n\tis.Equal(int32(0), result3)\n\tis.Equal(int32(-126), result4)\n\tis.Equal(uint32(120), result5)\n\tis.Equal(uint32(1), result6)\n\tis.Equal(complex128(96_8), result7)\n}\n\nfunc TestProductBy(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := ProductBy(values[float32](2.3, 3.3, 4, 5.3), func(n float32) float32 { return n })\n\tresult2 := ProductBy(values[int32](2, 3, 4, 5), func(n int32) int32 { return n })\n\tresult3 := ProductBy(values[int32](7, 8, 9, 0), func(n int32) int32 { return n })\n\tresult4 := ProductBy(values[int32](7, -1, 9, 2), func(n int32) int32 { return n })\n\tresult5 := ProductBy(values[uint32](2, 3, 4, 5), func(n uint32) uint32 { return n })\n\tresult6 := ProductBy(values[uint32](), func(n uint32) uint32 { return n })\n\tresult7 := ProductBy(values[complex128](4_4, 2_2), func(n complex128) complex128 { return n })\n\n\tis.InEpsilon(160.908, result1, 1e-7)\n\tis.Equal(int32(120), result2)\n\tis.Equal(int32(0), result3)\n\tis.Equal(int32(-126), result4)\n\tis.Equal(uint32(120), result5)\n\tis.Equal(uint32(1), result6)\n\tis.Equal(complex128(96_8), result7)\n}\n\nfunc TestMean(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := Mean(values[float32](2.3, 3.3, 4, 5.3))\n\tresult2 := Mean(values[int32](2, 3, 4, 5))\n\tresult3 := Mean(values[uint32](2, 3, 4, 5))\n\tresult4 := Mean(values[uint32]())\n\n\tis.InEpsilon(3.725, result1, 1e-7)\n\tis.Equal(int32(3), result2)\n\tis.Equal(uint32(3), result3)\n\tis.Equal(uint32(0), result4)\n}\n\nfunc TestMeanBy(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := MeanBy(values[float32](2.3, 3.3, 4, 5.3), func(n float32) float32 { return n })\n\tresult2 := MeanBy(values[int32](2, 3, 4, 5), func(n int32) int32 { return n })\n\tresult3 := MeanBy(values[uint32](2, 3, 4, 5), func(n uint32) uint32 { return n })\n\tresult4 := MeanBy(values[uint32](), func(n uint32) uint32 { return n })\n\n\tis.InEpsilon(3.725, result1, 1e-7)\n\tis.Equal(int32(3), result2)\n\tis.Equal(uint32(3), result3)\n\tis.Equal(uint32(0), result4)\n}\n\nfunc TestMode(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := Mode(values[float32](2.3, 3.3, 3.3, 5.3))\n\tresult2 := Mode(values[int32](2, 2, 3, 4))\n\tresult3 := Mode(values[uint32](2, 2, 3, 3))\n\tresult4 := Mode(values[uint32]())\n\tresult5 := Mode(values(1, 2, 3, 4, 5, 6, 7, 8, 9))\n\n\tis.Equal([]float32{3.3}, result1)\n\tis.Equal([]int32{2}, result2)\n\tis.Equal([]uint32{2, 3}, result3)\n\tis.Empty(result4)\n\tis.Equal([]int{1, 2, 3, 4, 5, 6, 7, 8, 9}, result5)\n}\n\nfunc TestModeCapacityConsistency(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tarr := []int{1, 1, 2, 2, 3, 3, 3}\n\n\tresult := Mode(values(arr...))\n\n\tis.Equal([]int{3}, result, \"Mode should return correct mode value\")\n\tis.Equal(len(result), cap(result), \"Mode slice capacity should match its length\")\n}\n"
  },
  {
    "path": "it/seq.go",
    "content": "//go:build go1.23\n\npackage it\n\nimport (\n\t\"iter\"\n\t\"slices\"\n\n\t\"github.com/samber/lo\"\n\t\"github.com/samber/lo/internal/constraints\"\n\t\"github.com/samber/lo/mutable\"\n)\n\n// Length returns the length of collection.\n// Will iterate through the entire sequence.\nfunc Length[T any](collection iter.Seq[T]) int {\n\tvar count int\n\n\tfor range collection {\n\t\tcount++\n\t}\n\n\treturn count\n}\n\n// Drain consumes an entire sequence.\nfunc Drain[T any](collection iter.Seq[T]) {\n\tfor range collection { //nolint:revive\n\t}\n}\n\n// Filter iterates over elements of collection, returning a sequence of all elements predicate returns true for.\n// Play: https://go.dev/play/p/psenko2KKsX\nfunc Filter[T any, I ~func(func(T) bool)](collection I, predicate func(item T) bool) I {\n\treturn FilterI(collection, func(item T, _ int) bool { return predicate(item) })\n}\n\n// FilterI iterates over elements of collection, returning a sequence of all elements predicate returns true for.\n// Play: https://go.dev/play/p/5fpdlQvdL-q\nfunc FilterI[T any, I ~func(func(T) bool)](collection I, predicate func(item T, index int) bool) I {\n\treturn func(yield func(T) bool) {\n\t\tvar i int\n\t\tfor item := range collection {\n\t\t\tif predicate(item, i) && !yield(item) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\ti++\n\t\t}\n\t}\n}\n\n// Map manipulates a sequence and transforms it to a sequence of another type.\n// Play: https://go.dev/play/p/F_FkOP-9F9T\nfunc Map[T, R any](collection iter.Seq[T], transform func(item T) R) iter.Seq[R] {\n\treturn MapI(collection, func(item T, _ int) R { return transform(item) })\n}\n\n// MapI manipulates a sequence and transforms it to a sequence of another type.\n// Play: https://go.dev/play/p/6gqemRweL-r\nfunc MapI[T, R any](collection iter.Seq[T], transform func(item T, index int) R) iter.Seq[R] {\n\treturn func(yield func(R) bool) {\n\t\tvar i int\n\t\tfor item := range collection {\n\t\t\tif !yield(transform(item, i)) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\ti++\n\t\t}\n\t}\n}\n\n// UniqMap manipulates a sequence and transforms it to a sequence of another type with unique values.\n// Will allocate a map large enough to hold all distinct transformed elements.\n// Long heterogeneous input sequences can cause excessive memory usage.\n// Play: https://go.dev/play/p/7hrfnSxfL-s\nfunc UniqMap[T any, R comparable](collection iter.Seq[T], transform func(item T) R) iter.Seq[R] {\n\treturn Uniq(Map(collection, transform))\n}\n\n// UniqMapI manipulates a sequence and transforms it to a sequence of another type with unique values.\n// Will allocate a map large enough to hold all distinct transformed elements.\n// Long heterogeneous input sequences can cause excessive memory usage.\n// Play: https://go.dev/play/p/8isgTsyfL-t\nfunc UniqMapI[T any, R comparable](collection iter.Seq[T], transform func(item T, index int) R) iter.Seq[R] {\n\treturn Uniq(MapI(collection, transform))\n}\n\n// FilterMap returns a sequence obtained after both filtering and mapping using the given callback function.\n// The callback function should return two values:\n//   - the result of the mapping operation and\n//   - whether the result element should be included or not.\n//\n// Play: https://go.dev/play/p/Gxwu8j_TJuh\nfunc FilterMap[T, R any](collection iter.Seq[T], callback func(item T) (R, bool)) iter.Seq[R] {\n\treturn FilterMapI(collection, func(item T, _ int) (R, bool) { return callback(item) })\n}\n\n// FilterMapI returns a sequence obtained after both filtering and mapping using the given callback function.\n// The callback function should return two values:\n//   - the result of the mapping operation and\n//   - whether the result element should be included or not.\n//\n// Play: https://go.dev/play/p/0XrQKOk-vw\nfunc FilterMapI[T, R any](collection iter.Seq[T], callback func(item T, index int) (R, bool)) iter.Seq[R] {\n\treturn func(yield func(R) bool) {\n\t\tvar i int\n\t\tfor item := range collection {\n\t\t\tif r, ok := callback(item, i); ok && !yield(r) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\ti++\n\t\t}\n\t}\n}\n\n// FlatMap manipulates a sequence and transforms and flattens it to a sequence of another type.\n// The transform function can either return a sequence or a `nil`, and in the `nil` case\n// no value is yielded.\n// Play: https://go.dev/play/p/6toB9w2gpSy\nfunc FlatMap[T, R any](collection iter.Seq[T], transform func(item T) iter.Seq[R]) iter.Seq[R] {\n\treturn FlatMapI(collection, func(item T, _ int) iter.Seq[R] { return transform(item) })\n}\n\n// FlatMapI manipulates a sequence and transforms and flattens it to a sequence of another type.\n// The transform function can either return a sequence or a `nil`, and in the `nil` case\n// no value is yielded.\n// Play: https://go.dev/play/p/2ZtSMQm-xy\nfunc FlatMapI[T, R any](collection iter.Seq[T], transform func(item T, index int) iter.Seq[R]) iter.Seq[R] {\n\treturn func(yield func(R) bool) {\n\t\tvar i int\n\t\tfor item := range collection {\n\t\t\tfor r := range transform(item, i) {\n\t\t\t\tif !yield(r) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\t\t\ti++\n\t\t}\n\t}\n}\n\n// Reduce reduces collection to a value which is the accumulated result of running each element in collection\n// through accumulator, where each successive invocation is supplied the return value of the previous.\n// Will iterate through the entire sequence.\n// Play: https://go.dev/play/p/l5wWLATXclf\nfunc Reduce[T, R any](collection iter.Seq[T], accumulator func(agg R, item T) R, initial R) R {\n\treturn ReduceI(collection, func(agg R, item T, _ int) R { return accumulator(agg, item) }, initial)\n}\n\n// ReduceI reduces collection to a value which is the accumulated result of running each element in collection\n// through accumulator, where each successive invocation is supplied the return value of the previous.\n// Will iterate through the entire sequence.\n// Play: https://go.dev/play/p/3AuTNRn-yz\nfunc ReduceI[T, R any](collection iter.Seq[T], accumulator func(agg R, item T, index int) R, initial R) R {\n\tvar i int\n\tfor item := range collection {\n\t\tinitial = accumulator(initial, item, i)\n\t\ti++\n\t}\n\n\treturn initial\n}\n\n// ReduceLast is like Reduce except that it iterates over elements of collection in reverse.\n// Will iterate through the entire sequence and allocate a slice large enough to hold all elements.\n// Long input sequences can cause excessive memory usage.\n// Play: https://go.dev/play/p/D2ZGZ2pN270\nfunc ReduceLast[T, R any](collection iter.Seq[T], accumulator func(agg R, item T) R, initial R) R {\n\treturn Reduce(Reverse(collection), accumulator, initial)\n}\n\n// ReduceLastI is like Reduce except that it iterates over elements of collection in reverse.\n// Will iterate through the entire sequence and allocate a slice large enough to hold all elements.\n// Long input sequences can cause excessive memory usage.\n// Play: https://go.dev/play/p/5CwPTPz-zb\nfunc ReduceLastI[T, R any](collection iter.Seq[T], accumulator func(agg R, item T, index int) R, initial R) R {\n\treturn ReduceI(Reverse(collection), accumulator, initial)\n}\n\n// ForEach iterates over elements of collection and invokes callback for each element.\n// Will iterate through the entire sequence.\n// Play: https://go.dev/play/p/OvW9yNNYgsX\nfunc ForEach[T any](collection iter.Seq[T], callback func(item T)) {\n\tForEachI(collection, func(item T, _ int) { callback(item) })\n}\n\n// ForEachI iterates over elements of collection and invokes callback for each element.\n// Will iterate through the entire sequence.\n// Play: https://go.dev/play/p/6NhAE0-zm\nfunc ForEachI[T any](collection iter.Seq[T], callback func(item T, index int)) {\n\tvar i int\n\tfor item := range collection {\n\t\tcallback(item, i)\n\t\ti++\n\t}\n}\n\n// ForEachWhile iterates over elements of collection and invokes predicate for each element\n// collection return value decide to continue or break, like do while().\n// Will iterate through the entire sequence.\n// Play: https://go.dev/play/p/UsfPR_gmSs7\nfunc ForEachWhile[T any](collection iter.Seq[T], predicate func(item T) bool) {\n\tForEachWhileI(collection, func(item T, _ int) bool { return predicate(item) })\n}\n\n// ForEachWhileI iterates over elements of collection and invokes predicate for each element\n// collection return value decide to continue or break, like do while().\n// Will iterate through the entire sequence.\n// Play: https://go.dev/play/p/8PjCG2-zo\nfunc ForEachWhileI[T any](collection iter.Seq[T], predicate func(item T, index int) bool) {\n\tvar i int\n\tfor item := range collection {\n\t\tif !predicate(item, i) {\n\t\t\treturn\n\t\t}\n\t\ti++\n\t}\n}\n\n// Times invokes callback n times and returns a sequence of results.\n// The transform is invoked with index as argument.\n// Play: https://go.dev/play/p/0W4IRzQuCEc\nfunc Times[T any](count int, callback func(index int) T) iter.Seq[T] {\n\treturn func(yield func(T) bool) {\n\t\tfor i := range count {\n\t\t\tif !yield(callback(i)) {\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}\n}\n\n// Uniq returns a duplicate-free version of a sequence, in which only the first occurrence of each element is kept.\n// The order of result values is determined by the order they occur in the sequence.\n// Will allocate a map large enough to hold all distinct elements.\n// Long heterogeneous input sequences can cause excessive memory usage.\n// Play: https://go.dev/play/p/D-SenTW-ipj\nfunc Uniq[T comparable, I ~func(func(T) bool)](collection I) I {\n\treturn UniqBy(collection, func(item T) T { return item })\n}\n\n// UniqBy returns a duplicate-free version of a sequence, in which only the first occurrence of each element is kept.\n// The order of result values is determined by the order they occur in the sequence. A transform function is\n// invoked for each element in the sequence to generate the criterion by which uniqueness is computed.\n// Will allocate a map large enough to hold all distinct transformed elements.\n// Long heterogeneous input sequences can cause excessive memory usage.\n// Play: https://go.dev/play/p/HKrt3AvwMTR\nfunc UniqBy[T any, U comparable, I ~func(func(T) bool)](collection I, transform func(item T) U) I {\n\treturn func(yield func(T) bool) {\n\t\tseen := make(map[U]struct{})\n\n\t\tfor item := range collection {\n\t\t\tkey := transform(item)\n\n\t\t\tif _, ok := seen[key]; !ok {\n\t\t\t\tif !yield(item) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tseen[key] = struct{}{}\n\t\t\t}\n\t\t}\n\t}\n}\n\n// GroupBy returns an object composed of keys generated from the results of running each element of collection through transform.\n// Will iterate through the entire sequence.\n// Play: https://go.dev/play/p/oRIakS89OYy\nfunc GroupBy[T any, U comparable](collection iter.Seq[T], transform func(item T) U) map[U][]T {\n\treturn GroupByMap(collection, func(item T) (U, T) { return transform(item), item })\n}\n\n// GroupByMap returns an object composed of keys generated from the results of running each element of collection through transform.\n// Will iterate through the entire sequence.\n// Play: https://go.dev/play/p/3UoHL7-zt\nfunc GroupByMap[T any, K comparable, V any](collection iter.Seq[T], transform func(item T) (K, V)) map[K][]V {\n\tresult := make(map[K][]V)\n\n\tfor item := range collection {\n\t\tk, v := transform(item)\n\n\t\tresult[k] = append(result[k], v)\n\t}\n\n\treturn result\n}\n\n// Chunk returns a sequence of elements split into groups of length size. If the sequence can't be split evenly,\n// the final chunk will be the remaining elements.\n// Play: https://go.dev/play/p/qo8esZ_L60Q\nfunc Chunk[T any](collection iter.Seq[T], size int) iter.Seq[[]T] {\n\tif size <= 0 {\n\t\tpanic(\"it.Chunk: size must be greater than 0\")\n\t}\n\n\treturn func(yield func([]T) bool) {\n\t\tvar newSlice []T\n\t\tfor item := range collection {\n\t\t\tif newSlice == nil {\n\t\t\t\tnewSlice = make([]T, 0, size)\n\t\t\t}\n\t\t\tnewSlice = append(newSlice, item)\n\t\t\tif len(newSlice) == size {\n\t\t\t\tif !yield(newSlice) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tnewSlice = nil\n\t\t\t}\n\t\t}\n\t\tif newSlice != nil {\n\t\t\tyield(newSlice)\n\t\t}\n\t}\n}\n\n// Window creates a sequence of sliding windows of a given size.\n// Each window overlaps with the previous one by size-1 elements.\n// This is equivalent to Sliding(collection, size, 1).\n// Play: https://go.dev/play/p/_1BzQYtKBhi\nfunc Window[T any](collection iter.Seq[T], size int) iter.Seq[[]T] {\n\tif size <= 0 {\n\t\tpanic(\"it.Window: size must be greater than 0\")\n\t}\n\n\treturn Sliding(collection, size, 1)\n}\n\n// Sliding creates a sequence of sliding windows of a given size with a given step.\n// offset = step - size: offset == 0 means adjacent windows (no overlap/gap);\n// offset < 0 means overlapping windows; offset > 0 means gaps between windows.\n// Only full-size windows are yielded; a partial window at the end is not yielded.\n// Play: https://go.dev/play/p/mzhO4CZeiik\nfunc Sliding[T any](collection iter.Seq[T], size, step int) iter.Seq[[]T] {\n\tif size <= 0 {\n\t\tpanic(\"it.Sliding: size must be greater than 0\")\n\t}\n\tif step <= 0 {\n\t\tpanic(\"it.Sliding: step must be greater than 0\")\n\t}\n\n\treturn func(yield func([]T) bool) {\n\t\tbuffer := make([]T, size)\n\t\tcount := 0\n\t\toffset := step - size\n\n\t\tswitch {\n\t\tcase offset == 0:\n\t\t\t// Adjacent windows: no overlap, no gap.\n\t\t\tfor buffer[count] = range collection {\n\t\t\t\tif count++; count == size {\n\t\t\t\t\tif !yield(append(make([]T, 0, size), buffer...)) {\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\tcount = 0\n\t\t\t\t}\n\t\t\t}\n\n\t\tcase offset < 0:\n\t\t\t// Overlap: next window starts inside the current one; keep tail in buffer.\n\t\t\tfor buffer[count] = range collection {\n\t\t\t\tif count++; count == size {\n\t\t\t\t\tif !yield(append(make([]T, 0, size), buffer...)) {\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\tcount -= step\n\t\t\t\t\tcopy(buffer, buffer[step:])\n\t\t\t\t}\n\t\t\t}\n\n\t\tdefault: // offset > 0 (step > size)\n\t\t\t// Gap: skip elements between windows.\n\t\t\tskip := 0\n\t\t\tfor item := range collection {\n\t\t\t\tif skip > 0 {\n\t\t\t\t\tskip--\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tbuffer[count] = item\n\t\t\t\tif count++; count == size {\n\t\t\t\t\tif !yield(append(make([]T, 0, size), buffer...)) {\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\tcount = 0\n\t\t\t\t\tskip = offset\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n// PartitionBy returns a sequence of elements split into groups. The order of grouped values is\n// determined by the order they occur in collection. The grouping is generated from the results\n// of running each element of collection through transform.\n// Will allocate a map large enough to hold all distinct transformed elements.\n// Long heterogeneous input sequences can cause excessive memory usage.\n// Play: https://go.dev/play/p/VxTx8mva28z\nfunc PartitionBy[T any, K comparable](collection iter.Seq[T], transform func(item T) K) [][]T {\n\tvar result [][]T\n\tseen := map[K]int{}\n\n\tfor item := range collection {\n\t\tkey := transform(item)\n\n\t\tresultIndex, ok := seen[key]\n\t\tif ok {\n\t\t\tresult[resultIndex] = append(result[resultIndex], item)\n\t\t} else {\n\t\t\tseen[key] = len(result)\n\t\t\tresult = append(result, []T{item})\n\t\t}\n\t}\n\n\treturn result\n}\n\n// Flatten returns a sequence a single level deep.\n// Play: https://go.dev/play/p/CCklxuNk7Lm\nfunc Flatten[T any, I ~func(func(T) bool)](collection []I) I {\n\treturn func(yield func(T) bool) {\n\t\tfor _, item := range collection {\n\t\t\tfor item := range item {\n\t\t\t\tif !yield(item) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n// Concat returns a sequence of all the elements in iterators. Concat conserves the order of the elements.\n// Play: https://go.dev/play/p/Fa0u7xT2JOR\nfunc Concat[T any, I ~func(func(T) bool)](collection ...I) I {\n\treturn Flatten(collection)\n}\n\n// Interleave round-robin alternating input sequences and sequentially appending value at index into result.\n// Will allocate a slice the size of collections.\n// Play: https://go.dev/play/p/kNvnz4ClLgH\nfunc Interleave[T any](collections ...iter.Seq[T]) iter.Seq[T] {\n\treturn func(yield func(T) bool) {\n\t\tnext := make([]func() (T, bool), len(collections))\n\t\tfor i, c := range collections {\n\t\t\tvar stop func()\n\t\t\tnext[i], stop = iter.Pull(c)\n\t\t\tdefer stop()\n\t\t}\n\t\tvar done int\n\t\tfor done < len(next) {\n\t\t\tdone = 0\n\t\t\tfor i, n := range next {\n\t\t\t\tif n == nil {\n\t\t\t\t\tdone++\n\t\t\t\t} else if t, ok := n(); !ok {\n\t\t\t\t\tnext[i] = nil\n\t\t\t\t\tdone++\n\t\t\t\t} else if !yield(t) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n// Shuffle returns a sequence of shuffled values. Uses the Fisher-Yates shuffle algorithm.\n// Will iterate through the entire sequence and allocate a slice large enough to hold all elements.\n// Long input sequences can cause excessive memory usage.\n// Play: https://go.dev/play/p/8isgTsyfL-t\nfunc Shuffle[T any, I ~func(func(T) bool)](collection I) I {\n\tslice := slices.Collect(iter.Seq[T](collection))\n\tmutable.Shuffle(slice)\n\treturn I(slices.Values(slice))\n}\n\n// Reverse reverses a sequence so that the first element becomes the last, the second element becomes the second to last, and so on.\n// Will iterate through the entire sequence and allocate a slice large enough to hold all elements.\n// Long input sequences can cause excessive memory usage.\n// Play: https://go.dev/play/p/9jthUzgF-u\nfunc Reverse[T any, I ~func(func(T) bool)](collection I) I {\n\tslice := slices.Collect(iter.Seq[T](collection))\n\n\treturn I(func(yield func(T) bool) {\n\t\tfor i := len(slice) - 1; i >= 0; i-- {\n\t\t\tif !yield(slice[i]) {\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t})\n}\n\n// Fill replaces elements of a sequence with `initial` value.\n// Play: https://go.dev/play/p/mHShWq5ezMc\nfunc Fill[T lo.Clonable[T], I ~func(func(T) bool)](collection I, initial T) I {\n\treturn func(yield func(T) bool) {\n\t\tfor range collection {\n\t\t\tif !yield(initial.Clone()) {\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}\n}\n\n// Repeat builds a sequence with N copies of initial value.\n// Play: https://go.dev/play/p/xs-aq0p_uDP\nfunc Repeat[T lo.Clonable[T]](count int, initial T) iter.Seq[T] {\n\treturn RepeatBy(count, func(int) T { return initial.Clone() })\n}\n\n// RepeatBy builds a sequence with values returned by N calls of transform.\n// Play: https://go.dev/play/p/i7BuZQBcUzZ\nfunc RepeatBy[T any](count int, callback func(index int) T) iter.Seq[T] {\n\treturn func(yield func(T) bool) {\n\t\tfor i := range count {\n\t\t\tif !yield(callback(i)) {\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}\n}\n\n// KeyBy transforms a sequence to a map based on a pivot transform function.\n// Will iterate through the entire sequence.\n// Play: https://go.dev/play/p/MMaHpzTqY0a\nfunc KeyBy[K comparable, V any](collection iter.Seq[V], transform func(item V) K) map[K]V {\n\tresult := make(map[K]V)\n\n\tfor item := range collection {\n\t\tk := transform(item)\n\t\tresult[k] = item\n\t}\n\n\treturn result\n}\n\n// Associate returns a map containing key-value pairs provided by transform function applied to elements of the given sequence.\n// If any of two pairs have the same key the last one gets added to the map.\n// The order of keys in returned map is not specified and is not guaranteed to be the same from the original sequence.\n// Will iterate through the entire sequence.\n// Play: https://go.dev/play/p/ayCImLr_4im\nfunc Associate[T any, K comparable, V any](collection iter.Seq[T], transform func(item T) (K, V)) map[K]V {\n\treturn AssociateI(collection, func(item T, _ int) (K, V) { return transform(item) })\n}\n\n// AssociateI returns a map containing key-value pairs provided by transform function applied to elements of the given sequence.\n// If any of two pairs have the same key the last one gets added to the map.\n// The order of keys in returned map is not specified and is not guaranteed to be the same from the original sequence.\n// Will iterate through the entire sequence.\n// Play: https://go.dev/play/p/5CwPTPz-zb\nfunc AssociateI[T any, K comparable, V any](collection iter.Seq[T], transform func(item T, index int) (K, V)) map[K]V {\n\tresult := make(map[K]V)\n\n\tvar i int\n\tfor item := range collection {\n\t\tk, v := transform(item, i)\n\t\tresult[k] = v\n\t\ti++\n\t}\n\n\treturn result\n}\n\n// SeqToMap returns a map containing key-value pairs provided by transform function applied to elements of the given sequence.\n// If any of two pairs have the same key the last one gets added to the map.\n// The order of keys in returned map is not specified and is not guaranteed to be the same from the original sequence.\n// Alias of Associate().\n// Will iterate through the entire sequence.\n// Play: https://go.dev/play/p/6NhAE0-zm\nfunc SeqToMap[T any, K comparable, V any](collection iter.Seq[T], transform func(item T) (K, V)) map[K]V {\n\treturn Associate(collection, transform)\n}\n\n// SeqToMapI returns a map containing key-value pairs provided by transform function applied to elements of the given sequence.\n// If any of two pairs have the same key the last one gets added to the map.\n// The order of keys in returned map is not specified and is not guaranteed to be the same from the original sequence.\n// Alias of AssociateI().\n// Will iterate through the entire sequence.\n// Play: https://go.dev/play/p/7OiBF1-zn\nfunc SeqToMapI[T any, K comparable, V any](collection iter.Seq[T], transform func(item T, index int) (K, V)) map[K]V {\n\treturn AssociateI(collection, transform)\n}\n\n// FilterSeqToMap returns a map containing key-value pairs provided by transform function applied to elements of the given sequence.\n// If any of two pairs have the same key the last one gets added to the map.\n// The order of keys in returned map is not specified and is not guaranteed to be the same from the original sequence.\n// The third return value of the transform function is a boolean that indicates whether the key-value pair should be included in the map.\n// Will iterate through the entire sequence.\n// Play: https://go.dev/play/p/8PjCG2-zo\nfunc FilterSeqToMap[T any, K comparable, V any](collection iter.Seq[T], transform func(item T) (K, V, bool)) map[K]V {\n\treturn FilterSeqToMapI(collection, func(item T, _ int) (K, V, bool) {\n\t\treturn transform(item)\n\t})\n}\n\n// FilterSeqToMapI returns a map containing key-value pairs provided by transform function applied to elements of the given sequence.\n// If any of two pairs have the same key the last one gets added to the map.\n// The order of keys in returned map is not specified and is not guaranteed to be the same from the original sequence.\n// The third return value of the transform function is a boolean that indicates whether the key-value pair should be included in the map.\n// Will iterate through the entire sequence.\n// Play: https://go.dev/play/p/9QkDH3-zp\nfunc FilterSeqToMapI[T any, K comparable, V any](collection iter.Seq[T], transform func(item T, index int) (K, V, bool)) map[K]V {\n\tresult := make(map[K]V)\n\n\tvar i int\n\tfor item := range collection {\n\t\tif k, v, ok := transform(item, i); ok {\n\t\t\tresult[k] = v\n\t\t}\n\t\ti++\n\t}\n\n\treturn result\n}\n\n// Keyify returns a map with each unique element of the sequence as a key.\n// Will iterate through the entire sequence.\n// Play: https://go.dev/play/p/aHOD29_l-rF\nfunc Keyify[T comparable](collection iter.Seq[T]) map[T]struct{} {\n\tresult := make(map[T]struct{})\n\n\tfor item := range collection {\n\t\tresult[item] = struct{}{}\n\t}\n\n\treturn result\n}\n\n// Drop drops n elements from the beginning of a sequence.\n// Play: https://go.dev/play/p/O1J1-uWc3z9\nfunc Drop[T any, I ~func(func(T) bool)](collection I, n int) I {\n\tif n < 0 {\n\t\tpanic(\"it.Drop: n must not be negative\")\n\t}\n\n\tif n == 0 {\n\t\treturn collection\n\t}\n\n\treturn FilterI(collection, func(_ T, index int) bool { return index >= n })\n}\n\n// DropLast drops n elements from the end of a sequence.\n// Will allocate a slice of length n.\n// Play: https://go.dev/play/p/-NzU5Px5Tp4\nfunc DropLast[T any, I ~func(func(T) bool)](collection I, n int) I {\n\tif n < 0 {\n\t\tpanic(\"it.DropLast: n must not be negative\")\n\t}\n\n\tif n == 0 {\n\t\treturn collection\n\t}\n\n\treturn func(yield func(T) bool) {\n\t\tbuf := make([]T, n)\n\t\tvar count int\n\n\t\tfor item := range collection {\n\t\t\tidx := count % n\n\t\t\tcount++\n\n\t\t\tif count > n && !yield(buf[idx]) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tbuf[idx] = item\n\t\t}\n\t}\n}\n\n// DropWhile drops elements from the beginning of a sequence while the predicate returns true.\n// Play: https://go.dev/play/p/zSM8x08a9QD\nfunc DropWhile[T any, I ~func(func(T) bool)](collection I, predicate func(item T) bool) I {\n\treturn func(yield func(T) bool) {\n\t\tdropping := true\n\t\tfor item := range collection {\n\t\t\tdropping = dropping && predicate(item)\n\t\t\tif !dropping && !yield(item) {\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}\n}\n\n// DropLastWhile drops elements from the end of a sequence while the predicate returns true.\n// Will allocate a slice large enough to hold the longest sequence of matching elements.\n// Long input sequences of consecutive matches can cause excessive memory usage.\n// Play: https://go.dev/play/p/qZ81Cq7R-Yt\nfunc DropLastWhile[T any, I ~func(func(T) bool)](collection I, predicate func(item T) bool) I {\n\treturn func(yield func(T) bool) {\n\t\tvar buf []T\n\t\tfor item := range collection {\n\t\t\tif predicate(item) {\n\t\t\t\tbuf = append(buf, item)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif len(buf) > 0 {\n\t\t\t\tfor i := range buf {\n\t\t\t\t\tif !yield(buf[i]) {\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbuf = buf[:0]\n\t\t\t}\n\t\t\tif !yield(item) {\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}\n}\n\n// Take takes the first n elements from a sequence.\nfunc Take[T any, I ~func(func(T) bool)](collection I, n int) I {\n\tif n < 0 {\n\t\tpanic(\"it.Take: n must not be negative\")\n\t}\n\n\tif n == 0 {\n\t\treturn I(func(func(T) bool) {})\n\t}\n\n\treturn func(yield func(T) bool) {\n\t\tcount := 0\n\t\tfor item := range collection {\n\t\t\tcount++\n\t\t\tif !yield(item) || count >= n {\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}\n}\n\n// TakeWhile takes elements from the beginning of a sequence while the predicate returns true.\nfunc TakeWhile[T any, I ~func(func(T) bool)](collection I, predicate func(item T) bool) I {\n\treturn func(yield func(T) bool) {\n\t\tfor item := range collection {\n\t\t\tif !predicate(item) || !yield(item) {\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}\n}\n\n// DropByIndex drops elements from a sequence by the index.\n// Will allocate a map large enough to hold all distinct indexes.\n// Play: https://go.dev/play/p/vPbrZYgiU4q\nfunc DropByIndex[T any, I ~func(func(T) bool)](collection I, indexes ...int) I {\n\tset := lo.Keyify(indexes)\n\treturn RejectI(collection, func(_ T, index int) bool { return lo.HasKey(set, index) })\n}\n\n// TakeFilter filters elements and takes the first n elements that match the predicate.\n// Equivalent to calling Take(Filter(...)), but more efficient as it stops after finding n matches.\n// Play: https://go.dev/play/p/Db68Bhu4MCA\nfunc TakeFilter[T any, I ~func(func(T) bool)](collection I, n int, predicate func(item T) bool) I {\n\treturn TakeFilterI(collection, n, func(item T, _ int) bool { return predicate(item) })\n}\n\n// TakeFilterI filters elements and takes the first n elements that match the predicate.\n// Equivalent to calling Take(FilterI(...)), but more efficient as it stops after finding n matches.\nfunc TakeFilterI[T any, I ~func(func(T) bool)](collection I, n int, predicate func(item T, index int) bool) I {\n\tif n < 0 {\n\t\tpanic(\"it.TakeFilterI: n must not be negative\")\n\t}\n\n\tif n == 0 {\n\t\treturn I(func(func(T) bool) {})\n\t}\n\n\treturn func(yield func(T) bool) {\n\t\tvar count int\n\t\tvar index int\n\t\tfor item := range collection {\n\t\t\tif predicate(item, index) {\n\t\t\t\tcount++\n\t\t\t\tif !yield(item) || count >= n {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\t\t\tindex++\n\t\t}\n\t}\n}\n\n// Reject is the opposite of Filter, this method returns the elements of collection that predicate does not return true for.\n// Play: https://go.dev/play/p/IIQcknFhZnq\nfunc Reject[T any, I ~func(func(T) bool)](collection I, predicate func(item T) bool) I {\n\treturn RejectI(collection, func(item T, _ int) bool { return predicate(item) })\n}\n\n// RejectI is the opposite of Filter, this method returns the elements of collection that predicate does not return true for.\n// Play: https://go.dev/play/p/7YsLP1-zx\nfunc RejectI[T any, I ~func(func(T) bool)](collection I, predicate func(item T, index int) bool) I {\n\treturn func(yield func(T) bool) {\n\t\tvar i int\n\t\tfor item := range collection {\n\t\t\tif !predicate(item, i) && !yield(item) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\ti++\n\t\t}\n\t}\n}\n\n// RejectMap is the opposite of FilterMap, this method returns a sequence obtained after both filtering and mapping using the given callback function.\n// The callback function should return two values:\n//   - the result of the mapping operation and\n//   - whether the result element should be included or not.\n//\n// Play: https://go.dev/play/p/51jRHVYscgi\nfunc RejectMap[T, R any](collection iter.Seq[T], callback func(item T) (R, bool)) iter.Seq[R] {\n\treturn RejectMapI(collection, func(item T, _ int) (R, bool) { return callback(item) })\n}\n\n// RejectMapI is the opposite of FilterMap, this method returns a sequence obtained after both filtering and mapping using the given callback function.\n// The callback function should return two values:\n//   - the result of the mapping operation and\n//   - whether the result element should be included or not.\n//\n// Play: https://go.dev/play/p/9jthUzgF-u\nfunc RejectMapI[T, R any](collection iter.Seq[T], callback func(item T, index int) (R, bool)) iter.Seq[R] {\n\treturn func(yield func(R) bool) {\n\t\tvar i int\n\t\tfor item := range collection {\n\t\t\tif r, ok := callback(item, i); !ok && !yield(r) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\ti++\n\t\t}\n\t}\n}\n\n// Count counts the number of elements in the collection that equal value.\n// Will iterate through the entire sequence.\n// Play: https://go.dev/play/p/UcJ-6cANwfY\nfunc Count[T comparable](collection iter.Seq[T], value T) int {\n\treturn CountBy(collection, func(item T) bool { return item == value })\n}\n\n// CountBy counts the number of elements in the collection for which predicate is true.\n// Will iterate through the entire sequence.\n// Play: https://go.dev/play/p/m6G0o3huCOG\nfunc CountBy[T any](collection iter.Seq[T], predicate func(item T) bool) int {\n\tvar count int\n\n\tfor item := range collection {\n\t\tif predicate(item) {\n\t\t\tcount++\n\t\t}\n\t}\n\n\treturn count\n}\n\n// CountValues counts the number of each element in the collection.\n// Will iterate through the entire sequence.\n// Play: https://go.dev/play/p/PPBT4Fp-V3B\nfunc CountValues[T comparable](collection iter.Seq[T]) map[T]int {\n\treturn CountValuesBy(collection, func(item T) T { return item })\n}\n\n// CountValuesBy counts the number of each element returned from transform function.\n// Is equivalent to chaining Map and CountValues.\n// Will iterate through the entire sequence.\n// Play: https://go.dev/play/p/gnr_MPhYCHX\nfunc CountValuesBy[T any, U comparable](collection iter.Seq[T], transform func(item T) U) map[U]int {\n\tresult := make(map[U]int)\n\n\tfor item := range collection {\n\t\tresult[transform(item)]++\n\t}\n\n\treturn result\n}\n\n// Subset returns a subset of a sequence from `offset` up to `length` elements.\n// Will iterate at most offset+length times.\n// Play: https://go.dev/play/p/r-6FdqOL28Z\nfunc Subset[T any, I ~func(func(T) bool)](collection I, offset, length int) I {\n\tif offset < 0 {\n\t\tpanic(\"it.Subset: offset must not be negative\")\n\t}\n\tif length < 0 {\n\t\tpanic(\"it.Subset: length must not be negative\")\n\t}\n\n\treturn Slice(collection, offset, offset+length)\n}\n\n// Slice returns a subset of a sequence from `start` up to, but not including `end`.\n// Will iterate at most end times.\n// Play: https://go.dev/play/p/jKIu1oPf5hK\nfunc Slice[T any, I ~func(func(T) bool)](collection I, start, end int) I {\n\tif start < 0 {\n\t\tstart = 0\n\t}\n\tif end < 0 {\n\t\tend = 0\n\t}\n\n\treturn func(yield func(T) bool) {\n\t\tvar i int\n\t\tfor item := range collection {\n\t\t\tif i >= start && (i >= end || !yield(item)) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\ti++\n\t\t}\n\t}\n}\n\n// Replace returns a sequence with the first n non-overlapping instances of old replaced by new.\n// Play: https://go.dev/play/p/aFXjeyf0KqV\nfunc Replace[T comparable, I ~func(func(T) bool)](collection I, old, nEw T, n int) I {\n\treturn I(func(yield func(T) bool) {\n\t\tn := n\n\t\tMap(iter.Seq[T](collection), func(item T) T {\n\t\t\tif n != 0 && item == old {\n\t\t\t\tn--\n\t\t\t\treturn nEw\n\t\t\t}\n\t\t\treturn item\n\t\t})(yield)\n\t})\n}\n\n// ReplaceAll returns a sequence with all non-overlapping instances of old replaced by new.\n// Play: https://go.dev/play/p/sOckhMvvwjc\nfunc ReplaceAll[T comparable, I ~func(func(T) bool)](collection I, old, nEw T) I {\n\treturn Replace(collection, old, nEw, -1)\n}\n\n// Compact returns a sequence of all non-zero elements.\n// Play: https://go.dev/play/p/R_xT99w2QaU\nfunc Compact[T comparable, I ~func(func(T) bool)](collection I) I {\n\treturn Filter(collection, lo.IsNotEmpty)\n}\n\n// IsSorted checks if a sequence is sorted.\n// Will iterate through the entire sequence.\n// Play: https://go.dev/play/p/o-BD4UOn-0U\nfunc IsSorted[T constraints.Ordered](collection iter.Seq[T]) bool {\n\treturn IsSortedBy(collection, func(item T) T { return item })\n}\n\n// IsSortedBy checks if a sequence is sorted by transform.\n// Will iterate through the entire sequence.\n// Play: https://go.dev/play/p/AfYOiGWa78T\nfunc IsSortedBy[T any, K constraints.Ordered](collection iter.Seq[T], transform func(item T) K) bool {\n\tfirst := true\n\tvar prev K\n\tfor item := range collection {\n\t\tkey := transform(item)\n\t\tif first {\n\t\t\tfirst = false\n\t\t} else if prev > key {\n\t\t\treturn false\n\t\t}\n\t\tprev = key\n\t}\n\treturn true\n}\n\n// Splice inserts multiple elements at index i. The helper is protected against overflow errors.\n// Play: https://go.dev/play/p/TevQSvDKO_i\nfunc Splice[T any, I ~func(func(T) bool)](collection I, index int, elements ...T) I {\n\tif index < 0 {\n\t\tpanic(\"it.Splice: index must not be negative\")\n\t}\n\n\tif len(elements) == 0 {\n\t\treturn collection\n\t}\n\n\treturn func(yield func(T) bool) {\n\t\tvar i int\n\t\tfor item := range collection {\n\t\t\tif i == index {\n\t\t\t\tfor _, element := range elements {\n\t\t\t\t\tif !yield(element) {\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif !yield(item) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\ti++\n\t\t}\n\t\tif i <= index {\n\t\t\tfor _, element := range elements {\n\t\t\t\tif !yield(element) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n// CutPrefix returns collection without the provided leading prefix\n// and reports whether it found the prefix.\n// If collection doesn't start with prefix, CutPrefix returns collection, false.\n// If prefix is empty, CutPrefix returns collection, true.\n// Will iterate at most the size of separator before returning.\n// Play: https://go.dev/play/p/bPnV39zVnAV\nfunc CutPrefix[T comparable, I ~func(func(T) bool)](collection I, separator []T) (after I, found bool) { //nolint:gocyclo\n\tif len(separator) == 0 {\n\t\treturn collection, true\n\t}\n\n\tnext, stop := iter.Pull(iter.Seq[T](collection))\n\tfor i := range separator {\n\t\titem, ok := next()\n\t\tif !ok {\n\t\t\treturn func(yield func(T) bool) {\n\t\t\t\tdefer stop()\n\t\t\t\tfor j := range i {\n\t\t\t\t\tif !yield(separator[j]) {\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}, false\n\t\t}\n\n\t\tif item != separator[i] {\n\t\t\treturn func(yield func(T) bool) {\n\t\t\t\tdefer stop()\n\t\t\t\tfor j := range i {\n\t\t\t\t\tif !yield(separator[j]) {\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif ok && !yield(item) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tfor {\n\t\t\t\t\tif item, ok := next(); !ok || !yield(item) {\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}, false\n\t\t}\n\t}\n\n\treturn func(yield func(T) bool) {\n\t\tdefer stop()\n\t\tfor {\n\t\t\tif item, ok := next(); !ok || !yield(item) {\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}, true\n}\n\n// CutSuffix returns collection without the provided ending suffix and reports\n// whether it found the suffix. If collection doesn't end with suffix, CutSuffix returns collection, false.\n// If suffix is empty, CutSuffix returns collection, true.\n// Will iterate through the entire sequence and allocate a slice large enough to hold all elements.\n// Long input sequences can cause excessive memory usage.\n// Play: https://go.dev/play/p/CTRh9m1UHrZ\nfunc CutSuffix[T comparable, I ~func(func(T) bool)](collection I, separator []T) (before I, found bool) {\n\tslice := slices.Collect(iter.Seq[T](collection))\n\tresult, ok := lo.CutSuffix(slice, separator)\n\treturn I(slices.Values(result)), ok\n}\n\n// Trim removes all the leading and trailing cutset from the collection.\n// Will allocate a map large enough to hold all distinct cutset elements.\n// Play: https://go.dev/play/p/k0VCcilk4V1\nfunc Trim[T comparable, I ~func(func(T) bool)](collection I, cutset ...T) I {\n\tpredicate := lo.Partial(lo.HasKey, lo.Keyify(cutset))\n\treturn DropLastWhile(DropWhile(collection, predicate), predicate)\n}\n\n// TrimFirst removes all the leading cutset from the collection.\n// Will allocate a map large enough to hold all distinct cutset elements.\n// Play: https://go.dev/play/p/4D4Ke5C5MwH\nfunc TrimFirst[T comparable, I ~func(func(T) bool)](collection I, cutset ...T) I {\n\treturn DropWhile(collection, lo.Partial(lo.HasKey, lo.Keyify(cutset)))\n}\n\n// TrimPrefix removes all the leading prefix from the collection.\n// Play: https://go.dev/play/p/Pce4zSPnThY\nfunc TrimPrefix[T comparable, I ~func(func(T) bool)](collection I, prefix []T) I {\n\tn := len(prefix)\n\tif n == 0 {\n\t\treturn collection\n\t}\n\n\treturn func(yield func(T) bool) {\n\t\tvar i int\n\t\tfor item := range collection {\n\t\t\tif i >= 0 {\n\t\t\t\tif item == prefix[i] {\n\t\t\t\t\ti = (i + 1) % n\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\n\t\t\t\tfor j := range i {\n\t\t\t\t\tif !yield(prefix[j]) {\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\ti = -1\n\t\t\t}\n\n\t\t\tif !yield(item) {\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t\tfor j := range i {\n\t\t\tif !yield(prefix[j]) {\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}\n}\n\n// TrimLast removes all the trailing cutset from the collection.\n// Will allocate a map large enough to hold all distinct cutset elements.\n// Play: https://go.dev/play/p/GQLhnaeW0gd\nfunc TrimLast[T comparable, I ~func(func(T) bool)](collection I, cutset ...T) I {\n\treturn DropLastWhile(collection, lo.Partial(lo.HasKey, lo.Keyify(cutset)))\n}\n\n// TrimSuffix removes all the trailing suffix from the collection.\n// Play: https://go.dev/play/p/s9nwy9helEi\nfunc TrimSuffix[T comparable, I ~func(func(T) bool)](collection I, suffix []T) I {\n\tn := len(suffix)\n\tif n == 0 {\n\t\treturn collection\n\t}\n\n\treturn func(yield func(T) bool) {\n\t\tvar i int\n\t\tfor item := range collection {\n\t\t\tif item == suffix[i%n] {\n\t\t\t\ti++\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tfor j := range i {\n\t\t\t\tif !yield(suffix[j%n]) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\n\t\t\ti = 0\n\t\t\tif item == suffix[0] {\n\t\t\t\ti++\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif !yield(item) {\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t\tif i%n != 0 {\n\t\t\tfor j := range i {\n\t\t\t\tif !yield(suffix[j%n]) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n// Buffer returns a sequence of slices, each containing up to size items read from the channel.\n// The last slice may be smaller if the channel closes before filling the buffer.\n// Play: https://go.dev/play/p/zDZdcCA20ut\nfunc Buffer[T any](seq iter.Seq[T], size int) iter.Seq[[]T] {\n\treturn func(yield func([]T) bool) {\n\t\tbuffer := make([]T, 0, size)\n\n\t\tseq(func(v T) bool {\n\t\t\tbuffer = append(buffer, v)\n\t\t\tif len(buffer) < size {\n\t\t\t\treturn true // keep pulling\n\t\t\t}\n\t\t\t// Buffer full, yield it\n\t\t\tresult := buffer\n\t\t\tbuffer = make([]T, 0, size) // allocate new buffer\n\t\t\treturn yield(result)        // false = stop, true = continue\n\t\t})\n\n\t\t// Yield remaining partial buffer\n\t\tif len(buffer) > 0 {\n\t\t\tyield(buffer)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "it/seq_example_test.go",
    "content": "//go:build go1.23\n\npackage it\n\nimport (\n\t\"fmt\"\n\t\"iter\"\n\t\"math\"\n\t\"slices\"\n\t\"strconv\"\n)\n\nfunc ExampleLength() {\n\tlist := slices.Values([]int64{1, 2, 3, 4})\n\n\tresult := Length(list)\n\n\tfmt.Printf(\"%v\", result)\n\t// Output: 4\n}\n\nfunc ExampleDrain() {\n\tlist := slices.Values([]int64{1, 2, 3, 4})\n\n\tDrain(list)\n}\n\nfunc ExampleFilter() {\n\tlist := slices.Values([]int64{1, 2, 3, 4})\n\n\tresult := Filter(list, func(nbr int64) bool {\n\t\treturn nbr%2 == 0\n\t})\n\n\tfmt.Printf(\"%v\", slices.Collect(result))\n\t// Output: [2 4]\n}\n\nfunc ExampleMap() {\n\tlist := slices.Values([]int64{1, 2, 3, 4})\n\n\tresult := Map(list, func(nbr int64) string {\n\t\treturn strconv.FormatInt(nbr*2, 10)\n\t})\n\n\tfmt.Printf(\"%v\", slices.Collect(result))\n\t// Output: [2 4 6 8]\n}\n\nfunc ExampleUniqMap() {\n\ttype User struct {\n\t\tName string\n\t\tAge  int\n\t}\n\tusers := slices.Values([]User{{Name: \"Alex\", Age: 10}, {Name: \"Alex\", Age: 12}, {Name: \"Bob\", Age: 11}, {Name: \"Alice\", Age: 20}})\n\n\tresult := UniqMap(users, func(u User) string {\n\t\treturn u.Name\n\t})\n\n\tfmt.Printf(\"%v\", slices.Collect(result))\n\t// Output: [Alex Bob Alice]\n}\n\nfunc ExampleFilterMap() {\n\tlist := slices.Values([]int64{1, 2, 3, 4})\n\n\tresult := FilterMap(list, func(nbr int64) (string, bool) {\n\t\treturn strconv.FormatInt(nbr*2, 10), nbr%2 == 0\n\t})\n\n\tfmt.Printf(\"%v\", slices.Collect(result))\n\t// Output: [4 8]\n}\n\nfunc ExampleFlatMap() {\n\tlist := slices.Values([]int64{1, 2, 3, 4})\n\n\tresult := FlatMap(list, func(nbr int64) iter.Seq[string] {\n\t\treturn slices.Values([]string{\n\t\t\tstrconv.FormatInt(nbr, 10), // base 10\n\t\t\tstrconv.FormatInt(nbr, 2),  // base 2\n\t\t})\n\t})\n\n\tfmt.Printf(\"%v\", slices.Collect(result))\n\t// Output: [1 1 2 10 3 11 4 100]\n}\n\nfunc ExampleReduce() {\n\tlist := slices.Values([]int64{1, 2, 3, 4})\n\n\tresult := Reduce(list, func(agg, item int64) int64 {\n\t\treturn agg + item\n\t}, 0)\n\n\tfmt.Printf(\"%v\", result)\n\t// Output: 10\n}\n\nfunc ExampleReduceLast() {\n\tlist := slices.Values([][]int{{0, 1}, {2, 3}, {4, 5}})\n\n\tresult := ReduceLast(list, func(agg, item []int) []int {\n\t\treturn append(agg, item...)\n\t}, []int{})\n\n\tfmt.Printf(\"%v\", result)\n\t// Output: [4 5 2 3 0 1]\n}\n\nfunc ExampleForEach() {\n\tlist := slices.Values([]int64{1, 2, 3, 4})\n\n\tForEach(list, func(x int64) {\n\t\tfmt.Println(x)\n\t})\n\n\t// Output:\n\t// 1\n\t// 2\n\t// 3\n\t// 4\n}\n\nfunc ExampleForEachWhile() {\n\tlist := slices.Values([]int64{1, 2, -math.MaxInt, 4})\n\n\tForEachWhile(list, func(x int64) bool {\n\t\tif x < 0 {\n\t\t\treturn false\n\t\t}\n\t\tfmt.Println(x)\n\t\treturn true\n\t})\n\n\t// Output:\n\t// 1\n\t// 2\n}\n\nfunc ExampleTimes() {\n\tresult := Times(3, func(i int) string {\n\t\treturn strconv.FormatInt(int64(i), 10)\n\t})\n\n\tfmt.Printf(\"%v\", slices.Collect(result))\n\t// Output: [0 1 2]\n}\n\nfunc ExampleUniq() {\n\tlist := slices.Values([]int{1, 2, 2, 1})\n\n\tresult := Uniq(list)\n\n\tfmt.Printf(\"%v\", slices.Collect(result))\n\t// Output: [1 2]\n}\n\nfunc ExampleUniqBy() {\n\tlist := slices.Values([]int{0, 1, 2, 3, 4, 5})\n\n\tresult := UniqBy(list, func(i int) int {\n\t\treturn i % 3\n\t})\n\n\tfmt.Printf(\"%v\", slices.Collect(result))\n\t// Output: [0 1 2]\n}\n\nfunc ExampleGroupBy() {\n\tlist := slices.Values([]int{0, 1, 2, 3, 4, 5})\n\n\tresult := GroupBy(list, func(i int) int {\n\t\treturn i % 3\n\t})\n\n\tfmt.Printf(\"%v\\n\", result[0])\n\tfmt.Printf(\"%v\\n\", result[1])\n\tfmt.Printf(\"%v\\n\", result[2])\n\t// Output:\n\t// [0 3]\n\t// [1 4]\n\t// [2 5]\n}\n\nfunc ExampleGroupByMap() {\n\tlist := slices.Values([]int{0, 1, 2, 3, 4, 5})\n\n\tresult := GroupByMap(list, func(i int) (int, int) {\n\t\treturn i % 3, i * 2\n\t})\n\n\tfmt.Printf(\"%v\\n\", result[0])\n\tfmt.Printf(\"%v\\n\", result[1])\n\tfmt.Printf(\"%v\\n\", result[2])\n\t// Output:\n\t// [0 6]\n\t// [2 8]\n\t// [4 10]\n}\n\nfunc ExampleChunk() {\n\tlist := slices.Values([]int{0, 1, 2, 3, 4})\n\n\tresult := Chunk(list, 2)\n\n\tfor r := range result {\n\t\tfmt.Printf(\"%v\\n\", r)\n\t}\n\t// Output:\n\t// [0 1]\n\t// [2 3]\n\t// [4]\n}\n\nfunc ExampleWindow() {\n\tlist := slices.Values([]int{1, 2, 3, 4, 5})\n\n\tresult := Window(list, 3)\n\n\tfor r := range result {\n\t\tfmt.Printf(\"%v\\n\", r)\n\t}\n\t// Output:\n\t// [1 2 3]\n\t// [2 3 4]\n\t// [3 4 5]\n}\n\nfunc ExampleSliding() {\n\tlist := slices.Values([]int{1, 2, 3, 4, 5, 6, 7, 8})\n\n\tresult := Sliding(list, 2, 3)\n\n\tfor r := range result {\n\t\tfmt.Printf(\"%v\\n\", r)\n\t}\n\t// Output:\n\t// [1 2]\n\t// [4 5]\n\t// [7 8]\n}\n\nfunc ExamplePartitionBy() {\n\tlist := slices.Values([]int{-2, -1, 0, 1, 2, 3, 4})\n\n\tresult := PartitionBy(list, func(x int) string {\n\t\tif x < 0 {\n\t\t\treturn \"negative\"\n\t\t} else if x%2 == 0 {\n\t\t\treturn \"even\"\n\t\t}\n\t\treturn \"odd\"\n\t})\n\n\tfor _, v := range result {\n\t\tfmt.Printf(\"%v\\n\", v)\n\t}\n\t// Output:\n\t// [-2 -1]\n\t// [0 2 4]\n\t// [1 3]\n}\n\nfunc ExampleFlatten() {\n\tlist := []iter.Seq[int]{slices.Values([]int{0, 1, 2}), slices.Values([]int{3, 4, 5})}\n\n\tresult := Flatten(list)\n\n\tfmt.Printf(\"%v\", slices.Collect(result))\n\t// Output: [0 1 2 3 4 5]\n}\n\nfunc ExampleConcat() {\n\tlist1 := slices.Values([]int{0, 1, 2})\n\tlist2 := slices.Values([]int{3, 4, 5})\n\tlist3 := slices.Values([]int{6, 7, 8})\n\n\tresult := Concat(list1, list2, list3)\n\n\tfmt.Printf(\"%v\", slices.Collect(result))\n\t// Output: [0 1 2 3 4 5 6 7 8]\n}\n\nfunc ExampleInterleave() {\n\tlist1 := []iter.Seq[int]{slices.Values([]int{1, 4, 7}), slices.Values([]int{2, 5, 8}), slices.Values([]int{3, 6, 9})}\n\tlist2 := []iter.Seq[int]{slices.Values([]int{1}), slices.Values([]int{2, 5, 8}), slices.Values([]int{3, 6}), slices.Values([]int{4, 7, 9, 10})}\n\n\tresult1 := slices.Collect(Interleave(list1...))\n\tresult2 := slices.Collect(Interleave(list2...))\n\n\tfmt.Printf(\"%v\\n\", result1)\n\tfmt.Printf(\"%v\\n\", result2)\n\t// Output:\n\t// [1 2 3 4 5 6 7 8 9]\n\t// [1 2 3 4 5 6 7 8 9 10]\n}\n\nfunc ExampleShuffle() {\n\tlist := slices.Values([]int{0, 1, 2, 3, 4, 5})\n\n\tresult := slices.Collect(Shuffle(list))\n\n\tfmt.Printf(\"%v\", result)\n}\n\nfunc ExampleReverse() {\n\tlist := slices.Values([]int{0, 1, 2, 3, 4, 5})\n\n\tresult := slices.Collect(Reverse(list))\n\n\tfmt.Printf(\"%v\", result)\n\t// Output: [5 4 3 2 1 0]\n}\n\nfunc ExampleFill() {\n\tlist := slices.Values([]foo{{\"a\"}, {\"a\"}})\n\n\tresult := Fill(list, foo{\"b\"})\n\n\tfmt.Printf(\"%v\", slices.Collect(result))\n\t// Output: [{b} {b}]\n}\n\nfunc ExampleRepeat() {\n\tresult := Repeat(2, foo{\"a\"})\n\n\tfmt.Printf(\"%v\", slices.Collect(result))\n\t// Output: [{a} {a}]\n}\n\nfunc ExampleRepeatBy() {\n\tresult := RepeatBy(5, func(i int) string {\n\t\treturn strconv.FormatInt(int64(math.Pow(float64(i), 2)), 10)\n\t})\n\n\tfmt.Printf(\"%v\", slices.Collect(result))\n\t// Output: [0 1 4 9 16]\n}\n\nfunc ExampleKeyBy() {\n\tlist := slices.Values([]string{\"a\", \"aa\", \"aaa\"})\n\n\tresult := KeyBy(list, func(str string) int {\n\t\treturn len(str)\n\t})\n\n\tfmt.Printf(\"%v\", result)\n\t// Output: map[1:a 2:aa 3:aaa]\n}\n\nfunc ExampleSeqToMap() {\n\tlist := slices.Values([]string{\"a\", \"aa\", \"aaa\"})\n\n\tresult := SeqToMap(list, func(str string) (string, int) {\n\t\treturn str, len(str)\n\t})\n\n\tfmt.Printf(\"%v\", result)\n\t// Output: map[a:1 aa:2 aaa:3]\n}\n\nfunc ExampleFilterSeqToMap() {\n\tlist := slices.Values([]string{\"a\", \"aa\", \"aaa\"})\n\n\tresult := FilterSeqToMap(list, func(str string) (string, int, bool) {\n\t\treturn str, len(str), len(str) > 1\n\t})\n\n\tfmt.Printf(\"%v\", result)\n\t// Output: map[aa:2 aaa:3]\n}\n\nfunc ExampleKeyify() {\n\tlist := slices.Values([]string{\"a\", \"a\", \"b\", \"b\", \"d\"})\n\n\tset := Keyify(list)\n\t_, ok1 := set[\"a\"]\n\t_, ok2 := set[\"c\"]\n\tfmt.Printf(\"%v\\n\", ok1)\n\tfmt.Printf(\"%v\\n\", ok2)\n\tfmt.Printf(\"%v\\n\", set)\n\n\t// Output:\n\t// true\n\t// false\n\t// map[a:{} b:{} d:{}]\n}\n\nfunc ExampleDrop() {\n\tlist := slices.Values([]int{0, 1, 2, 3, 4, 5})\n\n\tresult := Drop(list, 2)\n\n\tfmt.Printf(\"%v\", slices.Collect(result))\n\t// Output: [2 3 4 5]\n}\n\nfunc ExampleTake() {\n\tlist := slices.Values([]int{0, 1, 2, 3, 4, 5})\n\n\tresult := Take(list, 3)\n\n\tfmt.Printf(\"%v\", slices.Collect(result))\n\t// Output: [0 1 2]\n}\n\nfunc ExampleDropWhile() {\n\tlist := slices.Values([]int{0, 1, 2, 3, 4, 5})\n\n\tresult := DropWhile(list, func(val int) bool {\n\t\treturn val < 2\n\t})\n\n\tfmt.Printf(\"%v\", slices.Collect(result))\n\t// Output: [2 3 4 5]\n}\n\nfunc ExampleTakeWhile() {\n\tlist := slices.Values([]int{0, 1, 2, 3, 4, 5})\n\n\tresult := TakeWhile(list, func(val int) bool {\n\t\treturn val < 3\n\t})\n\n\tfmt.Printf(\"%v\", slices.Collect(result))\n\t// Output: [0 1 2]\n}\n\nfunc ExampleDropByIndex() {\n\tlist := slices.Values([]int{0, 1, 2, 3, 4, 5})\n\n\tresult := DropByIndex(list, 2)\n\n\tfmt.Printf(\"%v\", slices.Collect(result))\n\t// Output: [0 1 3 4 5]\n}\n\nfunc ExampleTakeFilter() {\n\tlist := slices.Values([]int{1, 2, 3, 4, 5, 6})\n\n\tresult := TakeFilter(list, 2, func(val int) bool {\n\t\treturn val%2 == 0\n\t})\n\n\tfmt.Printf(\"%v\", slices.Collect(result))\n\t// Output: [2 4]\n}\n\nfunc ExampleTakeFilterI() {\n\tlist := slices.Values([]int{1, 2, 3, 4, 5, 6})\n\n\tresult := TakeFilterI(list, 2, func(val, index int) bool {\n\t\treturn val%2 == 0 && index < 4\n\t})\n\n\tfmt.Printf(\"%v\", slices.Collect(result))\n\t// Output: [2 4]\n}\n\nfunc ExampleReject() {\n\tlist := slices.Values([]int{0, 1, 2, 3, 4, 5})\n\n\tresult := Reject(list, func(x int) bool {\n\t\treturn x%2 == 0\n\t})\n\n\tfmt.Printf(\"%v\", slices.Collect(result))\n\t// Output: [1 3 5]\n}\n\nfunc ExampleCount() {\n\tlist := slices.Values([]int{0, 1, 2, 3, 4, 5, 0, 1, 2, 3})\n\n\tresult := Count(list, 2)\n\n\tfmt.Printf(\"%v\", result)\n\t// Output: 2\n}\n\nfunc ExampleCountBy() {\n\tlist := slices.Values([]int{0, 1, 2, 3, 4, 5, 0, 1, 2, 3})\n\n\tresult := CountBy(list, func(i int) bool {\n\t\treturn i < 4\n\t})\n\n\tfmt.Printf(\"%v\", result)\n\t// Output: 8\n}\n\nfunc ExampleCountValues() {\n\tresult1 := CountValues(slices.Values([]int{}))\n\tresult2 := CountValues(slices.Values([]int{1, 2}))\n\tresult3 := CountValues(slices.Values([]int{1, 2, 2}))\n\tresult4 := CountValues(slices.Values([]string{\"foo\", \"bar\", \"\"}))\n\tresult5 := CountValues(slices.Values([]string{\"foo\", \"bar\", \"bar\"}))\n\n\tfmt.Printf(\"%v\\n\", result1)\n\tfmt.Printf(\"%v\\n\", result2)\n\tfmt.Printf(\"%v\\n\", result3)\n\tfmt.Printf(\"%v\\n\", result4)\n\tfmt.Printf(\"%v\\n\", result5)\n\t// Output:\n\t// map[]\n\t// map[1:1 2:1]\n\t// map[1:1 2:2]\n\t// map[:1 bar:1 foo:1]\n\t// map[bar:2 foo:1]\n}\n\nfunc ExampleCountValuesBy() {\n\tisEven := func(v int) bool {\n\t\treturn v%2 == 0\n\t}\n\n\tresult1 := CountValuesBy(slices.Values([]int{}), isEven)\n\tresult2 := CountValuesBy(slices.Values([]int{1, 2}), isEven)\n\tresult3 := CountValuesBy(slices.Values([]int{1, 2, 2}), isEven)\n\n\tlength := func(v string) int {\n\t\treturn len(v)\n\t}\n\n\tresult4 := CountValuesBy(slices.Values([]string{\"foo\", \"bar\", \"\"}), length)\n\tresult5 := CountValuesBy(slices.Values([]string{\"foo\", \"bar\", \"bar\"}), length)\n\n\tfmt.Printf(\"%v\\n\", result1)\n\tfmt.Printf(\"%v\\n\", result2)\n\tfmt.Printf(\"%v\\n\", result3)\n\tfmt.Printf(\"%v\\n\", result4)\n\tfmt.Printf(\"%v\\n\", result5)\n\t// Output:\n\t// map[]\n\t// map[false:1 true:1]\n\t// map[false:1 true:2]\n\t// map[0:1 3:2]\n\t// map[3:3]\n}\n\nfunc ExampleSubset() {\n\tlist := slices.Values([]int{0, 1, 2, 3, 4, 5})\n\n\tresult := Subset(list, 2, 3)\n\n\tfmt.Printf(\"%v\", slices.Collect(result))\n\t// Output: [2 3 4]\n}\n\nfunc ExampleSlice() {\n\tlist := values(0, 1, 2, 3, 4, 5)\n\n\tresult := Slice(list, 1, 4)\n\tfmt.Printf(\"%v\\n\", slices.Collect(result))\n\n\tresult = Slice(list, 4, 1)\n\tfmt.Printf(\"%v\\n\", slices.Collect(result))\n\n\tresult = Slice(list, 4, 5)\n\tfmt.Printf(\"%v\\n\", slices.Collect(result))\n\n\t// Output:\n\t// [1 2 3]\n\t// []\n\t// [4]\n}\n\nfunc ExampleReplace() {\n\tlist := slices.Values([]int{0, 1, 0, 1, 2, 3, 0})\n\n\tresult := Replace(list, 0, 42, 1)\n\tfmt.Printf(\"%v\\n\", slices.Collect(result))\n\n\tresult = Replace(list, -1, 42, 1)\n\tfmt.Printf(\"%v\\n\", slices.Collect(result))\n\n\tresult = Replace(list, 0, 42, 2)\n\tfmt.Printf(\"%v\\n\", slices.Collect(result))\n\n\tresult = Replace(list, 0, 42, -1)\n\tfmt.Printf(\"%v\\n\", slices.Collect(result))\n\n\t// Output:\n\t// [42 1 0 1 2 3 0]\n\t// [0 1 0 1 2 3 0]\n\t// [42 1 42 1 2 3 0]\n\t// [42 1 42 1 2 3 42]\n}\n\nfunc ExampleCompact() {\n\tlist := slices.Values([]string{\"\", \"foo\", \"\", \"bar\", \"\"})\n\n\tresult := Compact(list)\n\n\tfmt.Printf(\"%v\", slices.Collect(result))\n\n\t// Output: [foo bar]\n}\n\nfunc ExampleIsSorted() {\n\tlist := slices.Values([]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9})\n\n\tresult := IsSorted(list)\n\n\tfmt.Printf(\"%v\", result)\n\n\t// Output: true\n}\n\nfunc ExampleIsSortedBy() {\n\tlist := slices.Values([]string{\"a\", \"bb\", \"ccc\"})\n\n\tresult := IsSortedBy(list, func(s string) int {\n\t\treturn len(s)\n\t})\n\n\tfmt.Printf(\"%v\", result)\n\n\t// Output: true\n}\n\nfunc ExampleCutPrefix() {\n\tcollection := slices.Values([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"})\n\n\t// Test with valid prefix\n\tafter, found := CutPrefix(collection, []string{\"a\", \"b\", \"c\"})\n\tfmt.Printf(\"After: %v, Found: %t\\n\", slices.Collect(after), found)\n\n\t// Test with prefix not found\n\tafter2, found2 := CutPrefix(collection, []string{\"b\"})\n\tfmt.Printf(\"After: %v, Found: %t\\n\", slices.Collect(after2), found2)\n\n\t// Test with empty prefix\n\tafter3, found3 := CutPrefix(collection, []string{})\n\tfmt.Printf(\"After: %v, Found: %t\\n\", slices.Collect(after3), found3)\n\n\t// Output:\n\t// After: [d e f g], Found: true\n\t// After: [a b c d e f g], Found: false\n\t// After: [a b c d e f g], Found: true\n}\n\nfunc ExampleCutSuffix() {\n\tcollection := slices.Values([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"})\n\n\t// Test with valid suffix\n\tbefore, found := CutSuffix(collection, []string{\"f\", \"g\"})\n\tfmt.Printf(\"Before: %v, Found: %t\\n\", slices.Collect(before), found)\n\n\t// Test with suffix not found\n\tbefore2, found2 := CutSuffix(collection, []string{\"b\"})\n\tfmt.Printf(\"Before: %v, Found: %t\\n\", slices.Collect(before2), found2)\n\n\t// Test with empty suffix\n\tbefore3, found3 := CutSuffix(collection, []string{})\n\tfmt.Printf(\"Before: %v, Found: %t\\n\", slices.Collect(before3), found3)\n\n\t// Output:\n\t// Before: [a b c d e], Found: true\n\t// Before: [a b c d e f g], Found: false\n\t// Before: [a b c d e f g], Found: true\n}\n\nfunc ExampleTrim() {\n\tcollection := slices.Values([]int{0, 1, 2, 0, 3, 0})\n\n\t// Test with valid cutset\n\tresult := Trim(collection, 0)\n\tfmt.Printf(\"Trim with cutset {0}: %v\\n\", slices.Collect(result))\n\n\t// Test with string collection\n\twords := slices.Values([]string{\"  hello  \", \"world\", \"  \"})\n\tresult2 := Trim(words, \" \")\n\tfmt.Printf(\"Trim with string cutset: %v\\n\", slices.Collect(result2))\n\n\t// Test with no cutset elements\n\tresult3 := Trim(collection, 5)\n\tfmt.Printf(\"Trim with cutset {5} (not present): %v\\n\", slices.Collect(result3))\n\n\t// Output:\n\t// Trim with cutset {0}: [1 2 0 3]\n\t// Trim with string cutset: [  hello   world   ]\n\t// Trim with cutset {5} (not present): [0 1 2 0 3 0]\n}\n\nfunc ExampleTrimFirst() {\n\tcollection := slices.Values([]int{0, 1, 2, 0, 3, 0})\n\n\t// Test with valid cutset\n\tresult := TrimFirst(collection, 0)\n\tfmt.Printf(\"TrimFirst with cutset {0}: %v\\n\", slices.Collect(result))\n\n\t// Test with string collection\n\twords := slices.Values([]string{\"  hello  \", \"world\", \"  \"})\n\tresult2 := TrimFirst(words, \" \")\n\tfmt.Printf(\"TrimFirst with string cutset: %v\\n\", slices.Collect(result2))\n\n\t// Test with no cutset elements\n\tresult3 := TrimFirst(collection, 5)\n\tfmt.Printf(\"TrimFirst with cutset {5} (not present): %v\\n\", slices.Collect(result3))\n\n\t// Output:\n\t// TrimFirst with cutset {0}: [1 2 0 3 0]\n\t// TrimFirst with string cutset: [  hello   world   ]\n\t// TrimFirst with cutset {5} (not present): [0 1 2 0 3 0]\n}\n\nfunc ExampleTrimPrefix() {\n\tcollection := slices.Values([]int{1, 2, 1, 2, 3})\n\n\t// Test with valid prefix\n\tresult := TrimPrefix(collection, []int{1, 2})\n\tfmt.Printf(\"TrimPrefix with prefix {1,2}: %v\\n\", slices.Collect(result))\n\n\t// Test with string collection\n\twords := slices.Values([]string{\"hello\", \"hello\", \"world\"})\n\tresult2 := TrimPrefix(words, []string{\"hello\"})\n\tfmt.Printf(\"TrimPrefix with string prefix: %v\\n\", slices.Collect(result2))\n\n\t// Test with prefix not present\n\tresult3 := TrimPrefix(collection, []int{5, 6})\n\tfmt.Printf(\"TrimPrefix with prefix {5,6} (not present): %v\\n\", slices.Collect(result3))\n\n\t// Output:\n\t// TrimPrefix with prefix {1,2}: [3]\n\t// TrimPrefix with string prefix: [world]\n\t// TrimPrefix with prefix {5,6} (not present): [1 2 1 2 3]\n}\n\nfunc ExampleTrimLast() {\n\tcollection := slices.Values([]int{0, 1, 2, 0, 3, 0})\n\n\t// Test with valid cutset\n\tresult := TrimLast(collection, 0)\n\tfmt.Printf(\"TrimLast with cutset {0}: %v\\n\", slices.Collect(result))\n\n\t// Test with string collection\n\twords := slices.Values([]string{\"  hello  \", \"world\", \"  \"})\n\tresult2 := TrimLast(words, \" \")\n\tfmt.Printf(\"TrimLast with string cutset: %v\\n\", slices.Collect(result2))\n\n\t// Test with no cutset elements\n\tresult3 := TrimLast(collection, 5)\n\tfmt.Printf(\"TrimLast with cutset {5} (not present): %v\\n\", slices.Collect(result3))\n\n\t// Output:\n\t// TrimLast with cutset {0}: [0 1 2 0 3]\n\t// TrimLast with string cutset: [  hello   world   ]\n\t// TrimLast with cutset {5} (not present): [0 1 2 0 3 0]\n}\n\nfunc ExampleTrimSuffix() {\n\tcollection := slices.Values([]int{1, 2, 1, 2, 3})\n\n\t// Test with valid suffix\n\tresult := TrimSuffix(collection, []int{1, 2})\n\tfmt.Printf(\"TrimSuffix with suffix {1,2}: %v\\n\", slices.Collect(result))\n\n\t// Test with string collection\n\twords := slices.Values([]string{\"hello\", \"world\", \"test\"})\n\tresult2 := TrimSuffix(words, []string{\"test\"})\n\tfmt.Printf(\"TrimSuffix with string suffix: %v\\n\", slices.Collect(result2))\n\n\t// Test with suffix not present\n\tresult3 := TrimSuffix(collection, []int{5, 6})\n\tfmt.Printf(\"TrimSuffix with suffix {5,6} (not present): %v\\n\", slices.Collect(result3))\n\n\t// Output:\n\t// TrimSuffix with suffix {1,2}: [1 2 1 2 3]\n\t// TrimSuffix with string suffix: [hello world]\n\t// TrimSuffix with suffix {5,6} (not present): [1 2 1 2 3]\n}\n"
  },
  {
    "path": "it/seq_test.go",
    "content": "//go:build go1.23\n\npackage it\n\nimport (\n\t\"fmt\"\n\t\"iter\"\n\t\"math\"\n\t\"slices\"\n\t\"strconv\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestLength(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tr1 := Length(values[int]())\n\tr2 := Length(values(1, 2, 3, 4))\n\n\tis.Zero(r1)\n\tis.Equal(4, r2)\n}\n\nfunc TestDrain(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tvar done bool\n\tlist := iter.Seq[int](func(yield func(int) bool) {\n\t\t_ = yield(1) && yield(2) && yield(3)\n\n\t\tdone = true\n\t})\n\n\tDrain(list)\n\n\tis.True(done)\n}\n\nfunc TestFilter(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tr1 := Filter(values(1, 2, 3, 4), func(x int) bool {\n\t\treturn x%2 == 0\n\t})\n\tis.Equal([]int{2, 4}, slices.Collect(r1))\n\n\tr2 := Filter(values(\"\", \"foo\", \"\", \"bar\", \"\"), func(x string) bool {\n\t\treturn len(x) > 0\n\t})\n\tis.Equal([]string{\"foo\", \"bar\"}, slices.Collect(r2))\n\n\ttype myStrings iter.Seq[string]\n\tallStrings := myStrings(values(\"\", \"foo\", \"bar\"))\n\tnonempty := Filter(allStrings, func(x string) bool {\n\t\treturn len(x) > 0\n\t})\n\tis.IsType(nonempty, allStrings, \"type preserved\")\n}\n\nfunc TestFilterI(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tr1 := FilterI(values(1, 2, 3, 4), func(x, _ int) bool {\n\t\treturn x%2 == 0\n\t})\n\tis.Equal([]int{2, 4}, slices.Collect(r1))\n\n\tr2 := FilterI(values(\"\", \"foo\", \"\", \"bar\", \"\"), func(x string, _ int) bool {\n\t\treturn len(x) > 0\n\t})\n\tis.Equal([]string{\"foo\", \"bar\"}, slices.Collect(r2))\n\n\ttype myStrings iter.Seq[string]\n\tallStrings := myStrings(values(\"\", \"foo\", \"bar\"))\n\tnonempty := FilterI(allStrings, func(x string, _ int) bool {\n\t\treturn len(x) > 0\n\t})\n\tis.IsType(nonempty, allStrings, \"type preserved\")\n}\n\nfunc TestMap(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := Map(values(1, 2, 3, 4), func(x int) string {\n\t\treturn \"Hello\"\n\t})\n\tresult2 := Map(values[int64](1, 2, 3, 4), func(x int64) string {\n\t\treturn strconv.FormatInt(x, 10)\n\t})\n\n\tis.Equal([]string{\"Hello\", \"Hello\", \"Hello\", \"Hello\"}, slices.Collect(result1))\n\tis.Equal([]string{\"1\", \"2\", \"3\", \"4\"}, slices.Collect(result2))\n}\n\nfunc TestMapI(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := MapI(values(1, 2, 3, 4), func(x, _ int) string {\n\t\treturn \"Hello\"\n\t})\n\tresult2 := MapI(values[int64](1, 2, 3, 4), func(x int64, _ int) string {\n\t\treturn strconv.FormatInt(x, 10)\n\t})\n\n\tis.Equal([]string{\"Hello\", \"Hello\", \"Hello\", \"Hello\"}, slices.Collect(result1))\n\tis.Equal([]string{\"1\", \"2\", \"3\", \"4\"}, slices.Collect(result2))\n}\n\nfunc TestUniqMap(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\ttype User struct {\n\t\tName string\n\t\tage  int\n\t}\n\n\tusers := values(User{Name: \"Alice\", age: 20}, User{Name: \"Alex\", age: 21}, User{Name: \"Alex\", age: 22})\n\tresult := UniqMap(users, func(item User) string {\n\t\treturn item.Name\n\t})\n\n\tis.Equal([]string{\"Alice\", \"Alex\"}, slices.Collect(result))\n}\n\nfunc TestUniqMapI(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\ttype User struct {\n\t\tName string\n\t\tage  int\n\t}\n\n\tusers := values(User{Name: \"Alice\", age: 20}, User{Name: \"Alex\", age: 21}, User{Name: \"Alex\", age: 22})\n\tresult := UniqMapI(users, func(item User, _ int) string {\n\t\treturn item.Name\n\t})\n\n\tis.Equal([]string{\"Alice\", \"Alex\"}, slices.Collect(result))\n}\n\nfunc TestFilterMap(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tr1 := FilterMap(values[int64](1, 2, 3, 4), func(x int64) (string, bool) {\n\t\tif x%2 == 0 {\n\t\t\treturn strconv.FormatInt(x, 10), true\n\t\t}\n\t\treturn \"\", false\n\t})\n\tr2 := FilterMap(values(\"cpu\", \"gpu\", \"mouse\", \"keyboard\"), func(x string) (string, bool) {\n\t\tif strings.HasSuffix(x, \"pu\") {\n\t\t\treturn \"xpu\", true\n\t\t}\n\t\treturn \"\", false\n\t})\n\n\tis.Equal([]string{\"2\", \"4\"}, slices.Collect(r1))\n\tis.Equal([]string{\"xpu\", \"xpu\"}, slices.Collect(r2))\n}\n\nfunc TestFilterMapI(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tr1 := FilterMapI(values[int64](1, 2, 3, 4), func(x int64, _ int) (string, bool) {\n\t\tif x%2 == 0 {\n\t\t\treturn strconv.FormatInt(x, 10), true\n\t\t}\n\t\treturn \"\", false\n\t})\n\tr2 := FilterMapI(values(\"cpu\", \"gpu\", \"mouse\", \"keyboard\"), func(x string, _ int) (string, bool) {\n\t\tif strings.HasSuffix(x, \"pu\") {\n\t\t\treturn \"xpu\", true\n\t\t}\n\t\treturn \"\", false\n\t})\n\n\tis.Equal([]string{\"2\", \"4\"}, slices.Collect(r1))\n\tis.Equal([]string{\"xpu\", \"xpu\"}, slices.Collect(r2))\n}\n\nfunc TestFlatMap(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := FlatMap(values(0, 1, 2, 3, 4), func(x int) iter.Seq[string] {\n\t\treturn values(\"Hello\")\n\t})\n\tresult2 := FlatMap(values[int64](0, 1, 2, 3, 4), func(x int64) iter.Seq[string] {\n\t\treturn func(yield func(string) bool) {\n\t\t\tfor range x {\n\t\t\t\tif !yield(strconv.FormatInt(x, 10)) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t})\n\n\tis.Equal([]string{\"Hello\", \"Hello\", \"Hello\", \"Hello\", \"Hello\"}, slices.Collect(result1))\n\tis.Equal([]string{\"1\", \"2\", \"2\", \"3\", \"3\", \"3\", \"4\", \"4\", \"4\", \"4\"}, slices.Collect(result2))\n}\n\nfunc TestFlatMapI(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := FlatMapI(values(0, 1, 2, 3, 4), func(x, _ int) iter.Seq[string] {\n\t\treturn values(\"Hello\")\n\t})\n\tresult2 := FlatMapI(values[int64](0, 1, 2, 3, 4), func(x int64, _ int) iter.Seq[string] {\n\t\treturn func(yield func(string) bool) {\n\t\t\tfor range x {\n\t\t\t\tif !yield(strconv.FormatInt(x, 10)) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t})\n\n\tis.Equal([]string{\"Hello\", \"Hello\", \"Hello\", \"Hello\", \"Hello\"}, slices.Collect(result1))\n\tis.Equal([]string{\"1\", \"2\", \"2\", \"3\", \"3\", \"3\", \"4\", \"4\", \"4\", \"4\"}, slices.Collect(result2))\n}\n\nfunc TestTimes(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := Times(3, func(i int) string {\n\t\treturn strconv.FormatInt(int64(i), 10)\n\t})\n\tis.Equal([]string{\"0\", \"1\", \"2\"}, slices.Collect(result1))\n}\n\nfunc TestReduce(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := Reduce(values(1, 2, 3, 4), func(agg, item int) int {\n\t\treturn agg + item\n\t}, 0)\n\tresult2 := Reduce(values(1, 2, 3, 4), func(agg, item int) int {\n\t\treturn agg + item\n\t}, 10)\n\n\tis.Equal(10, result1)\n\tis.Equal(20, result2)\n}\n\nfunc TestReduceI(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := ReduceI(values(1, 2, 3, 4), func(agg, item, _ int) int {\n\t\treturn agg + item\n\t}, 0)\n\tresult2 := ReduceI(values(1, 2, 3, 4), func(agg, item, _ int) int {\n\t\treturn agg + item\n\t}, 10)\n\n\tis.Equal(10, result1)\n\tis.Equal(20, result2)\n}\n\nfunc TestReduceLast(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := ReduceLast(values([]int{0, 1}, []int{2, 3}, []int{4, 5}), func(agg, item []int) []int {\n\t\treturn append(agg, item...)\n\t}, []int{})\n\tis.Equal([]int{4, 5, 2, 3, 0, 1}, result1)\n\n\tresult2 := ReduceLast(values(1, 2, 3, 4), func(agg, item int) int {\n\t\treturn agg + item\n\t}, 10)\n\tis.Equal(20, result2)\n}\n\nfunc TestReduceLastI(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := ReduceLastI(values([]int{0, 1}, []int{2, 3}, []int{4, 5}), func(agg, item []int, _ int) []int {\n\t\treturn append(agg, item...)\n\t}, []int{})\n\tis.Equal([]int{4, 5, 2, 3, 0, 1}, result1)\n\n\tresult2 := ReduceLastI(values(1, 2, 3, 4), func(agg, item, _ int) int {\n\t\treturn agg + item\n\t}, 10)\n\tis.Equal(20, result2)\n}\n\nfunc TestForEachI(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\t// check of callback is called for every element and in proper order\n\n\tcallParams1 := []string{}\n\tcallParams2 := []int{}\n\n\tForEachI(values(\"a\", \"b\", \"c\"), func(item string, i int) {\n\t\tcallParams1 = append(callParams1, item)\n\t\tcallParams2 = append(callParams2, i)\n\t})\n\n\tis.Equal([]string{\"a\", \"b\", \"c\"}, callParams1)\n\tis.Equal([]int{0, 1, 2}, callParams2)\n\tis.IsIncreasing(callParams2)\n}\n\nfunc TestForEachWhileI(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\t// check of callback is called for every element and in proper order\n\n\tvar callParams1 []string\n\tvar callParams2 []int\n\n\tForEachWhileI(values(\"a\", \"b\", \"c\"), func(item string, i int) bool {\n\t\tif item == \"c\" {\n\t\t\treturn false\n\t\t}\n\t\tcallParams1 = append(callParams1, item)\n\t\tcallParams2 = append(callParams2, i)\n\t\treturn true\n\t})\n\n\tis.Equal([]string{\"a\", \"b\"}, callParams1)\n\tis.Equal([]int{0, 1}, callParams2)\n\tis.IsIncreasing(callParams2)\n}\n\nfunc TestUniq(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := Uniq(values(1, 2, 2, 1))\n\tis.Equal([]int{1, 2}, slices.Collect(result1))\n\n\ttype myStrings iter.Seq[string]\n\tallStrings := myStrings(values(\"\", \"foo\", \"bar\"))\n\tnonempty := Uniq(allStrings)\n\tis.IsType(nonempty, allStrings, \"type preserved\")\n}\n\nfunc TestUniqBy(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := UniqBy(values(0, 1, 2, 3, 4, 5), func(i int) int {\n\t\treturn i % 3\n\t})\n\tis.Equal([]int{0, 1, 2}, slices.Collect(result1))\n\n\ttype myStrings iter.Seq[string]\n\tallStrings := myStrings(values(\"\", \"foo\", \"bar\"))\n\tnonempty := UniqBy(allStrings, func(i string) string {\n\t\treturn i\n\t})\n\tis.IsType(nonempty, allStrings, \"type preserved\")\n}\n\nfunc TestGroupBy(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := GroupBy(values(0, 1, 2, 3, 4, 5), func(i int) int {\n\t\treturn i % 3\n\t})\n\tis.Equal(map[int][]int{\n\t\t0: {0, 3},\n\t\t1: {1, 4},\n\t\t2: {2, 5},\n\t}, result1)\n}\n\nfunc TestGroupByMap(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := GroupByMap(values(0, 1, 2, 3, 4, 5), func(i int) (int, string) {\n\t\treturn i % 3, strconv.Itoa(i)\n\t})\n\tis.Equal(map[int][]string{\n\t\t0: {\"0\", \"3\"},\n\t\t1: {\"1\", \"4\"},\n\t\t2: {\"2\", \"5\"},\n\t}, result1)\n\n\ttype myInt int\n\tresult2 := GroupByMap(values[myInt](1, 0, 2, 3, 4, 5), func(i myInt) (int, string) {\n\t\treturn int(i % 3), strconv.Itoa(int(i))\n\t})\n\tis.Equal(map[int][]string{\n\t\t0: {\"0\", \"3\"},\n\t\t1: {\"1\", \"4\"},\n\t\t2: {\"2\", \"5\"},\n\t}, result2)\n\n\ttype product struct {\n\t\tID         int64\n\t\tCategoryID int64\n\t}\n\tproducts := values(\n\t\tproduct{ID: 1, CategoryID: 1},\n\t\tproduct{ID: 2, CategoryID: 1},\n\t\tproduct{ID: 3, CategoryID: 2},\n\t\tproduct{ID: 4, CategoryID: 3},\n\t\tproduct{ID: 5, CategoryID: 3},\n\t)\n\tresult3 := GroupByMap(products, func(item product) (int64, string) {\n\t\treturn item.CategoryID, \"Product \" + strconv.FormatInt(item.ID, 10)\n\t})\n\tis.Equal(map[int64][]string{\n\t\t1: {\"Product 1\", \"Product 2\"},\n\t\t2: {\"Product 3\"},\n\t\t3: {\"Product 4\", \"Product 5\"},\n\t}, result3)\n}\n\nfunc TestChunk(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := Chunk(values(0, 1, 2, 3, 4, 5), 2)\n\tresult2 := Chunk(values(0, 1, 2, 3, 4, 5, 6), 2)\n\tresult3 := Chunk(values[int](), 2)\n\tresult4 := Chunk(values(0), 2)\n\n\tis.Equal([][]int{{0, 1}, {2, 3}, {4, 5}}, slices.Collect(result1))\n\tis.Equal([][]int{{0, 1}, {2, 3}, {4, 5}, {6}}, slices.Collect(result2))\n\tis.Empty(slices.Collect(result3))\n\tis.Equal([][]int{{0}}, slices.Collect(result4))\n\tis.PanicsWithValue(\"it.Chunk: size must be greater than 0\", func() {\n\t\tChunk(values(0), 0)\n\t})\n}\n\nfunc TestWindow(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := Window(values(1, 2, 3, 4, 5), 3)\n\tresult2 := Window(values(1, 2, 3, 4, 5, 6), 3)\n\tresult3 := Window(values(1, 2), 3)\n\tresult4 := Window(values(1, 2, 3), 3)\n\tresult5 := Window(values(1, 2, 3, 4), 1)\n\n\tis.Equal([][]int{{1, 2, 3}, {2, 3, 4}, {3, 4, 5}}, slices.Collect(result1))\n\tis.Equal([][]int{{1, 2, 3}, {2, 3, 4}, {3, 4, 5}, {4, 5, 6}}, slices.Collect(result2))\n\tis.Empty(slices.Collect(result3))\n\tis.Equal([][]int{{1, 2, 3}}, slices.Collect(result4))\n\tis.Equal([][]int{{1}, {2}, {3}, {4}}, slices.Collect(result5))\n\n\tis.PanicsWithValue(\"it.Window: size must be greater than 0\", func() {\n\t\tWindow(values(1, 2, 3), 0)\n\t})\n\n\tis.PanicsWithValue(\"it.Window: size must be greater than 0\", func() {\n\t\tWindow(values(1, 2, 3), -1)\n\t})\n}\n\nfunc TestSliding(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := Sliding(values(1, 2, 3, 4, 5, 6), 3, 1)\n\tis.Equal([][]int{{1, 2, 3}, {2, 3, 4}, {3, 4, 5}, {4, 5, 6}}, slices.Collect(result1))\n\n\tresult2 := Sliding(values(1, 2, 3, 4, 5, 6), 3, 3)\n\tis.Equal([][]int{{1, 2, 3}, {4, 5, 6}}, slices.Collect(result2))\n\n\tresult3 := Sliding(values(1, 2, 3, 4, 5, 6, 7, 8), 2, 3)\n\tis.Equal([][]int{{1, 2}, {4, 5}, {7, 8}}, slices.Collect(result3))\n\n\tresult4 := Sliding(values(1, 2, 3, 4), 1, 1)\n\tis.Equal([][]int{{1}, {2}, {3}, {4}}, slices.Collect(result4))\n\n\tresult5 := Sliding(values(1, 2), 3, 1)\n\tis.Empty(slices.Collect(result5))\n\n\tresult6 := Sliding(values(1, 2, 3, 4, 5, 6), 2, 2)\n\tis.Equal([][]int{{1, 2}, {3, 4}, {5, 6}}, slices.Collect(result6))\n\n\tis.PanicsWithValue(\"it.Sliding: size must be greater than 0\", func() {\n\t\tSliding(values(1, 2, 3), 0, 1)\n\t})\n\n\tis.PanicsWithValue(\"it.Sliding: step must be greater than 0\", func() {\n\t\tSliding(values(1, 2, 3), 2, 0)\n\t})\n\n\tis.PanicsWithValue(\"it.Sliding: step must be greater than 0\", func() {\n\t\tSliding(values(1, 2, 3), 2, -1)\n\t})\n\n\t// Test overlapping windows (step < size)\n\tresult7 := Sliding(values(1, 2, 3, 4, 5), 3, 2)\n\tis.Equal([][]int{{1, 2, 3}, {3, 4, 5}}, slices.Collect(result7))\n\n\t// Test with step > size (non-overlapping with gaps)\n\tresult8 := Sliding(values(1, 2, 3, 4, 5, 6, 7, 8), 2, 4)\n\tis.Equal([][]int{{1, 2}, {5, 6}}, slices.Collect(result8))\n\n\t// Test empty collection\n\tresult9 := Sliding(values[int](), 2, 1)\n\tis.Empty(slices.Collect(result9))\n\n\t// Test collection exactly equal to size (one window)\n\tresult10 := Sliding(values(1, 2, 3), 3, 1)\n\tis.Equal([][]int{{1, 2, 3}}, slices.Collect(result10))\n\n\t// Test collection exactly equal to size with step=3\n\tresult11 := Sliding(values(1, 2, 3), 3, 3)\n\tis.Equal([][]int{{1, 2, 3}}, slices.Collect(result11))\n\n\t// Test collection just larger than size (two windows)\n\tresult12 := Sliding(values(1, 2, 3, 4), 3, 1)\n\tis.Equal([][]int{{1, 2, 3}, {2, 3, 4}}, slices.Collect(result12))\n\n\t// Test size=1 with different steps\n\tresult13 := Sliding(values(1, 2, 3, 4, 5), 1, 2)\n\tis.Equal([][]int{{1}, {3}, {5}}, slices.Collect(result13))\n\n\tresult14 := Sliding(values(1, 2, 3, 4, 5), 1, 3)\n\tis.Equal([][]int{{1}, {4}}, slices.Collect(result14))\n\n\t// Test very large step (only first window)\n\tresult15 := Sliding(values(1, 2, 3, 4, 5, 6, 7, 8, 9, 10), 2, 100)\n\tis.Equal([][]int{{1, 2}}, slices.Collect(result15))\n\n\t// Test step=1 with large size (maximum overlap)\n\tresult16 := Sliding(values(1, 2, 3, 4, 5), 4, 1)\n\tis.Equal([][]int{{1, 2, 3, 4}, {2, 3, 4, 5}}, slices.Collect(result16))\n\n\t// Test with strings\n\tresult17 := Sliding(values(\"a\", \"b\", \"c\", \"d\"), 2, 1)\n\tis.Equal([][]string{{\"a\", \"b\"}, {\"b\", \"c\"}, {\"c\", \"d\"}}, slices.Collect(result17))\n\n\t// Test with structs\n\ttype Person struct {\n\t\tName string\n\t\tAge  int\n\t}\n\tpeople := values(\n\t\tPerson{\"Alice\", 25},\n\t\tPerson{\"Bob\", 30},\n\t\tPerson{\"Charlie\", 35},\n\t\tPerson{\"Diana\", 40},\n\t)\n\tresult18 := Sliding(people, 2, 1)\n\tcollected := slices.Collect(result18)\n\tis.Len(collected, 3)\n\tis.Equal(Person{\"Alice\", 25}, collected[0][0])\n\tis.Equal(Person{\"Bob\", 30}, collected[0][1])\n\tis.Equal(Person{\"Bob\", 30}, collected[1][0])\n\tis.Equal(Person{\"Charlie\", 35}, collected[1][1])\n\n\t// Test size equals collection length with step > size (only one window)\n\tresult19 := Sliding(values(1, 2, 3), 3, 5)\n\tis.Equal([][]int{{1, 2, 3}}, slices.Collect(result19))\n\n\t// Test step=1 with size=2 on single element\n\tresult20 := Sliding(values(1), 2, 1)\n\tis.Empty(slices.Collect(result20))\n\n\t// Test large collection with small windows\n\tresult21 := Sliding(values(1, 2, 3, 4, 5, 6, 7, 8, 9, 10), 2, 2)\n\tis.Equal([][]int{{1, 2}, {3, 4}, {5, 6}, {7, 8}, {9, 10}}, slices.Collect(result21))\n\n\t// Test overlapping with step=2, size=4 (only full windows are returned)\n\tresult22 := Sliding(values(1, 2, 3, 4, 5, 6, 7), 4, 2)\n\tis.Equal([][]int{{1, 2, 3, 4}, {3, 4, 5, 6}}, slices.Collect(result22))\n\n\t// Test with float64\n\tresult23 := Sliding(values(1.1, 2.2, 3.3, 4.4), 2, 1)\n\tis.Equal([][]float64{{1.1, 2.2}, {2.2, 3.3}, {3.3, 4.4}}, slices.Collect(result23))\n\n\t// Test with bool\n\tresult24 := Sliding(values(true, false, true, false, true), 3, 2)\n\tis.Equal([][]bool{{true, false, true}, {true, false, true}}, slices.Collect(result24))\n\n\t// Test size=5, step=3 on collection of 7 elements (only full windows are returned)\n\tresult25 := Sliding(values(1, 2, 3, 4, 5, 6, 7), 5, 3)\n\tis.Equal([][]int{{1, 2, 3, 4, 5}}, slices.Collect(result25))\n\n\t// Test when collection size is exactly size + step - 1 (two windows with overlap)\n\tresult26 := Sliding(values(1, 2, 3, 4, 5), 3, 2)\n\tis.Equal([][]int{{1, 2, 3}, {3, 4, 5}}, slices.Collect(result26))\n\n\t// Test with negative size should panic\n\tis.PanicsWithValue(\"it.Sliding: size must be greater than 0\", func() {\n\t\tSliding(values(1, 2, 3), -1, 1)\n\t})\n\n\t// Test multiple early termination (stop yielding)\n\tresult27 := Sliding(values(1, 2, 3, 4, 5, 6), 2, 1)\n\tcount := 0\n\tfor window := range result27 {\n\t\tcount++\n\t\tif count == 2 {\n\t\t\tbreak\n\t\t}\n\t\t_ = window\n\t}\n\tis.Equal(2, count)\n\n\t// Test with large size, small step, large collection (only full windows are returned)\n\tresult28 := Sliding(values(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12), 5, 3)\n\tis.Equal([][]int{{1, 2, 3, 4, 5}, {4, 5, 6, 7, 8}, {7, 8, 9, 10, 11}}, slices.Collect(result28))\n\n\t// Test size equals step equals 1\n\tresult29 := Sliding(values(1, 2, 3, 4, 5), 1, 1)\n\tis.Equal([][]int{{1}, {2}, {3}, {4}, {5}}, slices.Collect(result29))\n\n\t// Test with zero elements in collection\n\tresult30 := Sliding(values[int](), 1, 1)\n\tis.Empty(slices.Collect(result30))\n\n\t// Test when last window is exactly size elements\n\tresult31 := Sliding(values(1, 2, 3, 4, 5, 6), 3, 3)\n\tis.Equal([][]int{{1, 2, 3}, {4, 5, 6}}, slices.Collect(result31))\n\n\t// Test with pointers\n\tx, y, z := 1, 2, 3\n\tresult32 := Sliding(values(&x, &y, &z), 2, 1)\n\tcollected32 := slices.Collect(result32)\n\tis.Len(collected32, 2)\n\tis.Equal(&x, collected32[0][0])\n\tis.Equal(&y, collected32[0][1])\n\tis.Equal(&y, collected32[1][0])\n\tis.Equal(&z, collected32[1][1])\n}\n\nfunc TestPartitionBy(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\toddEven := func(x int) string {\n\t\tif x < 0 {\n\t\t\treturn \"negative\"\n\t\t} else if x%2 == 0 {\n\t\t\treturn \"even\"\n\t\t}\n\t\treturn \"odd\"\n\t}\n\n\tresult1 := PartitionBy(values(-2, -1, 0, 1, 2, 3, 4, 5), oddEven)\n\tresult2 := PartitionBy(values[int](), oddEven)\n\n\tis.Equal([][]int{{-2, -1}, {0, 2, 4}, {1, 3, 5}}, result1)\n\tis.Empty(result2)\n}\n\nfunc TestFlatten(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := Flatten([]iter.Seq[int]{values(0, 1), values(2, 3, 4, 5)})\n\n\tis.Equal([]int{0, 1, 2, 3, 4, 5}, slices.Collect(result1))\n\n\ttype myStrings iter.Seq[string]\n\tallStrings := myStrings(values(\"\", \"foo\", \"bar\"))\n\tnonempty := Flatten([]myStrings{allStrings})\n\tis.IsType(nonempty, allStrings, \"type preserved\")\n}\n\nfunc TestConcat(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := Concat(values(0, 1), values(2, 3, 4, 5))\n\tis.Equal([]int{0, 1, 2, 3, 4, 5}, slices.Collect(result1))\n\n\ttype myStrings iter.Seq[string]\n\tallStrings := myStrings(values(\"\", \"foo\", \"bar\"))\n\tnonempty := Concat(allStrings, allStrings)\n\tis.IsType(nonempty, allStrings, \"type preserved\")\n}\n\nfunc TestInterleave(t *testing.T) {\n\tt.Parallel()\n\n\ttestCases := []struct {\n\t\tname string\n\t\tin   []iter.Seq[int]\n\t\twant []int\n\t}{\n\t\t{\n\t\t\t\"empty\",\n\t\t\t[]iter.Seq[int]{},\n\t\t\tnil,\n\t\t},\n\t\t{\n\t\t\t\"empties\",\n\t\t\t[]iter.Seq[int]{values[int](), values[int]()},\n\t\t\tnil,\n\t\t},\n\t\t{\n\t\t\t\"same length\",\n\t\t\t[]iter.Seq[int]{values(1, 3, 5), values(2, 4, 6)},\n\t\t\t[]int{1, 2, 3, 4, 5, 6},\n\t\t},\n\t\t{\n\t\t\t\"different length\",\n\t\t\t[]iter.Seq[int]{values(1, 3, 5, 6), values(2, 4)},\n\t\t\t[]int{1, 2, 3, 4, 5, 6},\n\t\t},\n\t\t{\n\t\t\t\"many sequences\",\n\t\t\t[]iter.Seq[int]{values(1), values(2, 5, 8), values(3, 6), values(4, 7, 9, 10)},\n\t\t\t[]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10},\n\t\t},\n\t}\n\tfor _, tc := range testCases {\n\t\ttc := tc //nolint:modernize\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\tassert.Equal(t, tc.want, slices.Collect(Interleave(tc.in...)))\n\t\t})\n\t}\n}\n\nfunc TestShuffle(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := Shuffle(values(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10))\n\tresult2 := Shuffle(values[int]())\n\n\tslice1 := slices.Collect(result1)\n\tis.NotEqual([]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, slice1)\n\tis.ElementsMatch([]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, slice1)\n\tis.Empty(slices.Collect(result2))\n\n\ttype myStrings iter.Seq[string]\n\tallStrings := myStrings(values(\"\", \"foo\", \"bar\"))\n\tnonempty := Shuffle(allStrings)\n\tis.IsType(nonempty, allStrings, \"type preserved\")\n}\n\nfunc TestReverse(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := Reverse(values(0, 1, 2, 3, 4, 5))\n\tresult2 := Reverse(values(0, 1, 2, 3, 4, 5, 6))\n\tresult3 := Reverse(values[int]())\n\n\tis.Equal([]int{5, 4, 3, 2, 1, 0}, slices.Collect(result1))\n\tis.Equal([]int{6, 5, 4, 3, 2, 1, 0}, slices.Collect(result2))\n\tis.Empty(slices.Collect(result3))\n\n\ttype myStrings iter.Seq[string]\n\tallStrings := myStrings(values(\"\", \"foo\", \"bar\"))\n\tnonempty := Reverse(allStrings)\n\tis.IsType(nonempty, allStrings, \"type preserved\")\n}\n\nfunc TestFill(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := Fill(values(foo{\"a\"}, foo{\"a\"}), foo{\"b\"})\n\tresult2 := Fill(values[foo](), foo{\"a\"})\n\n\tis.Equal([]foo{{\"b\"}, {\"b\"}}, slices.Collect(result1))\n\tis.Empty(slices.Collect(result2))\n}\n\nfunc TestRepeat(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := Repeat(2, foo{\"a\"})\n\tresult2 := Repeat(0, foo{\"a\"})\n\n\tis.Equal([]foo{{\"a\"}, {\"a\"}}, slices.Collect(result1))\n\tis.Empty(slices.Collect(result2))\n}\n\nfunc TestRepeatBy(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tcb := func(i int) int {\n\t\treturn int(math.Pow(float64(i), 2))\n\t}\n\n\tresult1 := RepeatBy(0, cb)\n\tresult2 := RepeatBy(2, cb)\n\tresult3 := RepeatBy(5, cb)\n\n\tis.Empty(slices.Collect(result1))\n\tis.Equal([]int{0, 1}, slices.Collect(result2))\n\tis.Equal([]int{0, 1, 4, 9, 16}, slices.Collect(result3))\n}\n\nfunc TestKeyBy(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := KeyBy(values(\"a\", \"aa\", \"aaa\"), func(str string) int {\n\t\treturn len(str)\n\t})\n\n\tis.Equal(map[int]string{1: \"a\", 2: \"aa\", 3: \"aaa\"}, result1)\n}\n\nfunc TestAssociate(t *testing.T) {\n\tt.Parallel()\n\n\ttype foo struct {\n\t\tbaz string\n\t\tbar int\n\t}\n\ttransform := func(f *foo) (string, int) {\n\t\treturn f.baz, f.bar\n\t}\n\ttestCases := []struct {\n\t\tin   []*foo\n\t\twant map[string]int\n\t}{\n\t\t{\n\t\t\tin:   []*foo{{baz: \"apple\", bar: 1}},\n\t\t\twant: map[string]int{\"apple\": 1},\n\t\t},\n\t\t{\n\t\t\tin:   []*foo{{baz: \"apple\", bar: 1}, {baz: \"banana\", bar: 2}},\n\t\t\twant: map[string]int{\"apple\": 1, \"banana\": 2},\n\t\t},\n\t\t{\n\t\t\tin:   []*foo{{baz: \"apple\", bar: 1}, {baz: \"apple\", bar: 2}},\n\t\t\twant: map[string]int{\"apple\": 2},\n\t\t},\n\t}\n\tfor i, tc := range testCases {\n\t\ttc := tc //nolint:modernize\n\t\tt.Run(fmt.Sprintf(\"test_%d\", i), func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\tassert.Equal(t, tc.want, Associate(slices.Values(tc.in), transform))\n\t\t})\n\t}\n}\n\nfunc TestAssociateI(t *testing.T) {\n\tt.Parallel()\n\n\ttransform := func(s string, i int) (int, string) {\n\t\treturn i % 2, s\n\t}\n\ttestCases := []struct {\n\t\tin   []string\n\t\twant map[int]string\n\t}{\n\t\t{\n\t\t\tin:   []string{\"zero\"},\n\t\t\twant: map[int]string{0: \"zero\"},\n\t\t},\n\t\t{\n\t\t\tin:   []string{\"zero\", \"one\"},\n\t\t\twant: map[int]string{0: \"zero\", 1: \"one\"},\n\t\t},\n\t\t{\n\t\t\tin:   []string{\"two\", \"one\", \"zero\"},\n\t\t\twant: map[int]string{0: \"zero\", 1: \"one\"},\n\t\t},\n\t}\n\tfor i, tc := range testCases {\n\t\ttc := tc //nolint:modernize\n\t\tt.Run(fmt.Sprintf(\"test_%d\", i), func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\tassert.Equal(t, tc.want, AssociateI(slices.Values(tc.in), transform))\n\t\t})\n\t}\n}\n\nfunc TestSeqToMap(t *testing.T) {\n\tt.Parallel()\n\n\ttype foo struct {\n\t\tbaz string\n\t\tbar int\n\t}\n\ttransform := func(f *foo) (string, int) {\n\t\treturn f.baz, f.bar\n\t}\n\ttestCases := []struct {\n\t\tin   []*foo\n\t\twant map[string]int\n\t}{\n\t\t{\n\t\t\tin:   []*foo{{baz: \"apple\", bar: 1}},\n\t\t\twant: map[string]int{\"apple\": 1},\n\t\t},\n\t\t{\n\t\t\tin:   []*foo{{baz: \"apple\", bar: 1}, {baz: \"banana\", bar: 2}},\n\t\t\twant: map[string]int{\"apple\": 1, \"banana\": 2},\n\t\t},\n\t\t{\n\t\t\tin:   []*foo{{baz: \"apple\", bar: 1}, {baz: \"apple\", bar: 2}},\n\t\t\twant: map[string]int{\"apple\": 2},\n\t\t},\n\t}\n\tfor i, tc := range testCases {\n\t\ttc := tc //nolint:modernize\n\t\tt.Run(fmt.Sprintf(\"test_%d\", i), func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\tassert.Equal(t, tc.want, SeqToMap(slices.Values(tc.in), transform))\n\t\t})\n\t}\n}\n\nfunc TestSeqToMapI(t *testing.T) {\n\tt.Parallel()\n\n\ttransform := func(s string, i int) (int, string) {\n\t\treturn i % 2, s\n\t}\n\ttestCases := []struct {\n\t\tin   []string\n\t\twant map[int]string\n\t}{\n\t\t{\n\t\t\tin:   []string{\"zero\"},\n\t\t\twant: map[int]string{0: \"zero\"},\n\t\t},\n\t\t{\n\t\t\tin:   []string{\"zero\", \"one\"},\n\t\t\twant: map[int]string{0: \"zero\", 1: \"one\"},\n\t\t},\n\t\t{\n\t\t\tin:   []string{\"two\", \"one\", \"zero\"},\n\t\t\twant: map[int]string{0: \"zero\", 1: \"one\"},\n\t\t},\n\t}\n\tfor i, tc := range testCases {\n\t\ttc := tc //nolint:modernize\n\t\tt.Run(fmt.Sprintf(\"test_%d\", i), func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\tassert.Equal(t, tc.want, SeqToMapI(slices.Values(tc.in), transform))\n\t\t})\n\t}\n}\n\nfunc TestFilterSeqToMap(t *testing.T) {\n\tt.Parallel()\n\n\ttype foo struct {\n\t\tbaz string\n\t\tbar int\n\t}\n\ttransform := func(f *foo) (string, int, bool) {\n\t\treturn f.baz, f.bar, f.bar > 1\n\t}\n\ttestCases := []struct {\n\t\tin   []*foo\n\t\twant map[string]int\n\t}{\n\t\t{\n\t\t\tin:   []*foo{{baz: \"apple\", bar: 1}},\n\t\t\twant: map[string]int{},\n\t\t},\n\t\t{\n\t\t\tin:   []*foo{{baz: \"apple\", bar: 1}, {baz: \"banana\", bar: 2}},\n\t\t\twant: map[string]int{\"banana\": 2},\n\t\t},\n\t\t{\n\t\t\tin:   []*foo{{baz: \"apple\", bar: 1}, {baz: \"apple\", bar: 2}},\n\t\t\twant: map[string]int{\"apple\": 2},\n\t\t},\n\t}\n\tfor i, tc := range testCases {\n\t\ttc := tc //nolint:modernize\n\t\tt.Run(fmt.Sprintf(\"test_%d\", i), func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\tassert.Equal(t, tc.want, FilterSeqToMap(slices.Values(tc.in), transform))\n\t\t})\n\t}\n}\n\nfunc TestFilterSeqToMapI(t *testing.T) {\n\tt.Parallel()\n\n\ttransform := func(s string, i int) (int, string, bool) {\n\t\treturn i % 5, s, i%2 == 0\n\t}\n\ttestCases := []struct {\n\t\tin   []string\n\t\twant map[int]string\n\t}{\n\t\t{\n\t\t\tin:   []string{\"zero\"},\n\t\t\twant: map[int]string{0: \"zero\"},\n\t\t},\n\t\t{\n\t\t\tin:   []string{\"zero\", \"one\", \"two\", \"three\", \"four\"},\n\t\t\twant: map[int]string{0: \"zero\", 2: \"two\", 4: \"four\"},\n\t\t},\n\t\t{\n\t\t\tin:   []string{\"zero\", \"one\", \"two\", \"three\", \"four\", \"five\", \"six\", \"seven\", \"eight\", \"nine\", \"ten\"},\n\t\t\twant: map[int]string{0: \"ten\", 1: \"six\", 2: \"two\", 3: \"eight\", 4: \"four\"},\n\t\t},\n\t}\n\tfor i, tc := range testCases {\n\t\ttc := tc //nolint:modernize\n\t\tt.Run(fmt.Sprintf(\"test_%d\", i), func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\tassert.Equal(t, tc.want, FilterSeqToMapI(slices.Values(tc.in), transform))\n\t\t})\n\t}\n}\n\nfunc TestKeyify(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := Keyify(values(1, 2, 3, 4))\n\tresult2 := Keyify(values(1, 1, 1, 2))\n\tresult3 := Keyify(values[int]())\n\tis.Equal(map[int]struct{}{1: {}, 2: {}, 3: {}, 4: {}}, result1)\n\tis.Equal(map[int]struct{}{1: {}, 2: {}}, result2)\n\tis.Empty(result3)\n}\n\nfunc TestDrop(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tis.Equal([]int{0, 1, 2, 3, 4}, slices.Collect(Drop(values(0, 1, 2, 3, 4), 0)))\n\tis.Equal([]int{1, 2, 3, 4}, slices.Collect(Drop(values(0, 1, 2, 3, 4), 1)))\n\tis.Equal([]int{2, 3, 4}, slices.Collect(Drop(values(0, 1, 2, 3, 4), 2)))\n\tis.Equal([]int{3, 4}, slices.Collect(Drop(values(0, 1, 2, 3, 4), 3)))\n\tis.Equal([]int{4}, slices.Collect(Drop(values(0, 1, 2, 3, 4), 4)))\n\tis.Empty(slices.Collect(Drop(values(0, 1, 2, 3, 4), 5)))\n\tis.Empty(slices.Collect(Drop(values(0, 1, 2, 3, 4), 6)))\n\n\tis.PanicsWithValue(\"it.Drop: n must not be negative\", func() {\n\t\tDrop(values(0, 1, 2, 3, 4), -1)\n\t})\n\n\ttype myStrings iter.Seq[string]\n\tallStrings := myStrings(values(\"\", \"foo\", \"bar\"))\n\tnonempty := Drop(allStrings, 2)\n\tis.IsType(nonempty, allStrings, \"type preserved\")\n}\n\nfunc TestDropLast(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tis.Equal([]int{0, 1, 2, 3, 4}, slices.Collect(DropLast(values(0, 1, 2, 3, 4), 0)))\n\tis.Equal([]int{0, 1, 2, 3}, slices.Collect(DropLast(values(0, 1, 2, 3, 4), 1)))\n\tis.Equal([]int{0, 1, 2}, slices.Collect(DropLast(values(0, 1, 2, 3, 4), 2)))\n\tis.Equal([]int{0, 1}, slices.Collect(DropLast(values(0, 1, 2, 3, 4), 3)))\n\tis.Equal([]int{0}, slices.Collect(DropLast(values(0, 1, 2, 3, 4), 4)))\n\tis.Empty(slices.Collect(DropLast(values(0, 1, 2, 3, 4), 5)))\n\tis.Empty(slices.Collect(DropLast(values(0, 1, 2, 3, 4), 6)))\n\n\tis.PanicsWithValue(\"it.DropLast: n must not be negative\", func() {\n\t\tDropLast(values(0, 1, 2, 3, 4), -1)\n\t})\n\n\ttype myStrings iter.Seq[string]\n\tallStrings := myStrings(values(\"\", \"foo\", \"bar\"))\n\tnonempty := DropLast(allStrings, 2)\n\tis.IsType(nonempty, allStrings, \"type preserved\")\n}\n\nfunc TestDropWhile(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tis.Equal([]int{4, 5, 6}, slices.Collect(DropWhile(values(0, 1, 2, 3, 4, 5, 6), func(t int) bool {\n\t\treturn t != 4\n\t})))\n\n\tis.Empty(slices.Collect(DropWhile(values(0, 1, 2, 3, 4, 5, 6), func(t int) bool {\n\t\treturn true\n\t})))\n\n\tis.Equal([]int{0, 1, 2, 3, 4, 5, 6}, slices.Collect(DropWhile(values(0, 1, 2, 3, 4, 5, 6), func(t int) bool {\n\t\treturn t == 10\n\t})))\n\n\ttype myStrings iter.Seq[string]\n\tallStrings := myStrings(values(\"\", \"foo\", \"bar\"))\n\tnonempty := DropWhile(allStrings, func(t string) bool {\n\t\treturn t != \"foo\"\n\t})\n\tis.IsType(nonempty, allStrings, \"type preserved\")\n}\n\nfunc TestDropLastWhile(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tis.Equal([]int{0, 1, 2, 3}, slices.Collect(DropLastWhile(values(0, 1, 2, 3, 4, 5, 6), func(t int) bool {\n\t\treturn t != 3\n\t})))\n\n\tis.Equal([]int{0, 1}, slices.Collect(DropLastWhile(values(0, 1, 2, 3, 4, 5, 6), func(t int) bool {\n\t\treturn t != 1\n\t})))\n\n\tis.Equal([]int{0, 1, 2, 3, 4, 5, 6}, slices.Collect(DropLastWhile(values(0, 1, 2, 3, 4, 5, 6), func(t int) bool {\n\t\treturn t == 10\n\t})))\n\n\tis.Empty(slices.Collect(DropLastWhile(values(0, 1, 2, 3, 4, 5, 6), func(t int) bool {\n\t\treturn t != 10\n\t})))\n\n\ttype myStrings iter.Seq[string]\n\tallStrings := myStrings(values(\"\", \"foo\", \"bar\"))\n\tnonempty := DropLastWhile(allStrings, func(t string) bool {\n\t\treturn t != \"foo\"\n\t})\n\tis.IsType(nonempty, allStrings, \"type preserved\")\n}\n\nfunc TestTake(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tis.Equal([]int{0, 1, 2}, slices.Collect(Take(values(0, 1, 2, 3, 4), 3)))\n\tis.Equal([]int{0, 1}, slices.Collect(Take(values(0, 1, 2, 3, 4), 2)))\n\tis.Equal([]int{0}, slices.Collect(Take(values(0, 1, 2, 3, 4), 1)))\n\tis.Empty(slices.Collect(Take(values(0, 1, 2, 3, 4), 0)))\n\tis.Equal([]int{0, 1, 2, 3, 4}, slices.Collect(Take(values(0, 1, 2, 3, 4), 5)))\n\tis.Equal([]int{0, 1, 2, 3, 4}, slices.Collect(Take(values(0, 1, 2, 3, 4), 10)))\n\n\tis.PanicsWithValue(\"it.Take: n must not be negative\", func() {\n\t\tTake(values(0, 1, 2, 3, 4), -1)\n\t})\n\n\ttype myStrings iter.Seq[string]\n\tallStrings := myStrings(values(\"\", \"foo\", \"bar\"))\n\tnonempty := Take(allStrings, 2)\n\tis.IsType(nonempty, allStrings, \"type preserved\")\n}\n\nfunc TestTakeWhile(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tis.Equal([]int{0, 1, 2, 3}, slices.Collect(TakeWhile(values(0, 1, 2, 3, 4, 5, 6), func(t int) bool {\n\t\treturn t != 4\n\t})))\n\n\tis.Equal([]int{0, 1, 2, 3, 4, 5, 6}, slices.Collect(TakeWhile(values(0, 1, 2, 3, 4, 5, 6), func(t int) bool {\n\t\treturn true\n\t})))\n\n\tis.Empty(slices.Collect(TakeWhile(values(0, 1, 2, 3, 4, 5, 6), func(t int) bool {\n\t\treturn false\n\t})))\n\n\tis.Equal([]int{0, 1, 2}, slices.Collect(TakeWhile(values(0, 1, 2, 3, 4, 5, 6), func(t int) bool {\n\t\treturn t < 3\n\t})))\n\n\ttype myStrings iter.Seq[string]\n\tallStrings := myStrings(values(\"\", \"foo\", \"bar\"))\n\tnonempty := TakeWhile(allStrings, func(t string) bool {\n\t\treturn t != \"bar\"\n\t})\n\tis.IsType(nonempty, allStrings, \"type preserved\")\n}\n\nfunc TestTakeFilter(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tis.Equal([]int{2, 4}, slices.Collect(TakeFilter(values(1, 2, 3, 4, 5, 6), 2, func(item int) bool {\n\t\treturn item%2 == 0\n\t})))\n\n\tis.Empty(slices.Collect(TakeFilter(values(1, 2, 3, 4, 5, 6), 0, func(item int) bool {\n\t\treturn item%2 == 0\n\t})))\n\n\tis.Empty(slices.Collect(TakeFilter(values(1, 3, 5), 2, func(item int) bool {\n\t\treturn item%2 == 0\n\t})))\n\n\tis.PanicsWithValue(\"it.TakeFilterI: n must not be negative\", func() {\n\t\tTakeFilter(values(1, 2, 3), -1, func(item int) bool { return true })\n\t})\n\n\ttype myStrings iter.Seq[string]\n\tallStrings := myStrings(values(\"\", \"foo\", \"bar\", \"baz\"))\n\tnonempty := TakeFilter(allStrings, 2, func(item string) bool {\n\t\treturn item != \"\"\n\t})\n\tis.IsType(nonempty, allStrings, \"type preserved\")\n}\n\nfunc TestTakeFilterI(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tis.Equal([]int{2, 4}, slices.Collect(TakeFilterI(values(1, 2, 3, 4, 5, 6), 2, func(item, index int) bool {\n\t\treturn item%2 == 0 && index < 4\n\t})))\n\n\tis.Equal([]int{2, 4, 6}, slices.Collect(TakeFilterI(values(1, 2, 3, 4, 5, 6), 10, func(item, _ int) bool {\n\t\treturn item%2 == 0\n\t})))\n\n\tis.Empty(slices.Collect(TakeFilterI(values(1, 2, 3, 4, 5, 6), 0, func(item, index int) bool {\n\t\treturn item%2 == 0 && index < 4\n\t})))\n\n\tis.Empty(slices.Collect(TakeFilterI(values(1, 3, 5), 2, func(item, _ int) bool {\n\t\treturn item%2 == 0\n\t})))\n\n\tis.Equal([]int{1}, slices.Collect(TakeFilterI(values(1, 2, 3, 4, 5), 1, func(item, _ int) bool {\n\t\treturn item%2 != 0\n\t})))\n\n\tis.PanicsWithValue(\"it.TakeFilterI: n must not be negative\", func() {\n\t\tTakeFilterI(values(1, 2, 3), -1, func(item, _ int) bool { return true })\n\t})\n}\n\nfunc TestDropByIndex(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tis.Equal([]int{1, 2, 3, 4}, slices.Collect(DropByIndex(values(0, 1, 2, 3, 4), 0)))\n\tis.Equal([]int{3, 4}, slices.Collect(DropByIndex(values(0, 1, 2, 3, 4), 0, 1, 2)))\n\tis.Equal([]int{2, 4}, slices.Collect(DropByIndex(values(0, 1, 2, 3, 4), 3, 1, 0)))\n\tis.Equal([]int{0, 1, 3, 4}, slices.Collect(DropByIndex(values(0, 1, 2, 3, 4), 2)))\n\tis.Equal([]int{0, 1, 2, 3}, slices.Collect(DropByIndex(values(0, 1, 2, 3, 4), 4)))\n\tis.Equal([]int{0, 1, 2, 3, 4}, slices.Collect(DropByIndex(values(0, 1, 2, 3, 4), 5)))\n\tis.Equal([]int{0, 1, 2, 3, 4}, slices.Collect(DropByIndex(values(0, 1, 2, 3, 4), 100)))\n\tis.Empty(slices.Collect(DropByIndex(values[int](), 0, 1)))\n\tis.Empty(slices.Collect(DropByIndex(values(42), 0, 1)))\n\tis.Empty(slices.Collect(DropByIndex(values(42), 1, 0)))\n\tis.Empty(slices.Collect(DropByIndex(values[int](), 1)))\n\tis.Empty(slices.Collect(DropByIndex(values(1), 0)))\n\n\ttype myStrings iter.Seq[string]\n\tallStrings := myStrings(values(\"\", \"foo\", \"bar\"))\n\tnonempty := DropByIndex(allStrings)\n\tis.IsType(nonempty, allStrings, \"type preserved\")\n}\n\nfunc TestReject(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tr1 := Reject(values(1, 2, 3, 4), func(x int) bool {\n\t\treturn x%2 == 0\n\t})\n\n\tis.Equal([]int{1, 3}, slices.Collect(r1))\n\n\tr2 := Reject(values(\"Smith\", \"foo\", \"Domin\", \"bar\", \"Olivia\"), func(x string) bool {\n\t\treturn len(x) > 3\n\t})\n\n\tis.Equal([]string{\"foo\", \"bar\"}, slices.Collect(r2))\n\n\ttype myStrings iter.Seq[string]\n\tallStrings := myStrings(values(\"\", \"foo\", \"bar\"))\n\tnonempty := Reject(allStrings, func(x string) bool {\n\t\treturn len(x) > 0\n\t})\n\tis.IsType(nonempty, allStrings, \"type preserved\")\n}\n\nfunc TestRejectI(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tr1 := RejectI(values(1, 2, 3, 4), func(x, _ int) bool {\n\t\treturn x%2 == 0\n\t})\n\n\tis.Equal([]int{1, 3}, slices.Collect(r1))\n\n\tr2 := RejectI(values(\"Smith\", \"foo\", \"Domin\", \"bar\", \"Olivia\"), func(x string, _ int) bool {\n\t\treturn len(x) > 3\n\t})\n\n\tis.Equal([]string{\"foo\", \"bar\"}, slices.Collect(r2))\n\n\ttype myStrings iter.Seq[string]\n\tallStrings := myStrings(values(\"\", \"foo\", \"bar\"))\n\tnonempty := RejectI(allStrings, func(x string, _ int) bool {\n\t\treturn len(x) > 0\n\t})\n\tis.IsType(nonempty, allStrings, \"type preserved\")\n}\n\nfunc TestRejectMap(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tr1 := RejectMap(values[int64](1, 2, 3, 4), func(x int64) (string, bool) {\n\t\tif x%2 == 0 {\n\t\t\treturn strconv.FormatInt(x, 10), false\n\t\t}\n\t\treturn \"\", true\n\t})\n\tr2 := RejectMap(values(\"cpu\", \"gpu\", \"mouse\", \"keyboard\"), func(x string) (string, bool) {\n\t\tif strings.HasSuffix(x, \"pu\") {\n\t\t\treturn \"xpu\", false\n\t\t}\n\t\treturn \"\", true\n\t})\n\n\tis.Equal([]string{\"2\", \"4\"}, slices.Collect(r1))\n\tis.Equal([]string{\"xpu\", \"xpu\"}, slices.Collect(r2))\n}\n\nfunc TestRejectMapI(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tr1 := RejectMapI(values[int64](1, 2, 3, 4), func(x int64, _ int) (string, bool) {\n\t\tif x%2 == 0 {\n\t\t\treturn strconv.FormatInt(x, 10), false\n\t\t}\n\t\treturn \"\", true\n\t})\n\tr2 := RejectMapI(values(\"cpu\", \"gpu\", \"mouse\", \"keyboard\"), func(x string, _ int) (string, bool) {\n\t\tif strings.HasSuffix(x, \"pu\") {\n\t\t\treturn \"xpu\", false\n\t\t}\n\t\treturn \"\", true\n\t})\n\n\tis.Equal([]string{\"2\", \"4\"}, slices.Collect(r1))\n\tis.Equal([]string{\"xpu\", \"xpu\"}, slices.Collect(r2))\n}\n\nfunc TestCount(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tcount1 := Count(values(1, 2, 1), 1)\n\tcount2 := Count(values(1, 2, 1), 3)\n\tcount3 := Count(values[int](), 1)\n\n\tis.Equal(2, count1)\n\tis.Zero(count2)\n\tis.Zero(count3)\n}\n\nfunc TestCountBy(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tcount1 := CountBy(values(1, 2, 1), func(i int) bool {\n\t\treturn i < 2\n\t})\n\tcount2 := CountBy(values(1, 2, 1), func(i int) bool {\n\t\treturn i > 2\n\t})\n\tcount3 := CountBy(values[int](), func(i int) bool {\n\t\treturn i <= 2\n\t})\n\n\tis.Equal(2, count1)\n\tis.Zero(count2)\n\tis.Zero(count3)\n}\n\nfunc TestCountValues(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tis.Empty(CountValues(values[int]()))\n\tis.Equal(map[int]int{1: 1, 2: 1}, CountValues(values(1, 2)))\n\tis.Equal(map[int]int{1: 1, 2: 2}, CountValues(values(1, 2, 2)))\n\tis.Equal(map[string]int{\"\": 1, \"foo\": 1, \"bar\": 1}, CountValues(values(\"foo\", \"bar\", \"\")))\n\tis.Equal(map[string]int{\"foo\": 1, \"bar\": 2}, CountValues(values(\"foo\", \"bar\", \"bar\")))\n}\n\nfunc TestCountValuesBy(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\toddEven := func(v int) bool {\n\t\treturn v%2 == 0\n\t}\n\tlength := func(v string) int {\n\t\treturn len(v)\n\t}\n\n\tresult1 := CountValuesBy(values[int](), oddEven)\n\tresult2 := CountValuesBy(values(1, 2), oddEven)\n\tresult3 := CountValuesBy(values(1, 2, 2), oddEven)\n\tresult4 := CountValuesBy(values(\"foo\", \"bar\", \"\"), length)\n\tresult5 := CountValuesBy(values(\"foo\", \"bar\", \"bar\"), length)\n\n\tis.Empty(result1)\n\tis.Equal(map[bool]int{true: 1, false: 1}, result2)\n\tis.Equal(map[bool]int{true: 2, false: 1}, result3)\n\tis.Equal(map[int]int{0: 1, 3: 2}, result4)\n\tis.Equal(map[int]int{3: 3}, result5)\n}\n\nfunc TestSubset(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tin := values(0, 1, 2, 3, 4)\n\n\tout1 := Subset(in, 0, 0)\n\tout2 := Subset(in, 10, 2)\n\tout4 := Subset(in, 0, 10)\n\tout5 := Subset(in, 0, 2)\n\tout6 := Subset(in, 2, 2)\n\tout7 := Subset(in, 2, 5)\n\tout8 := Subset(in, 2, 3)\n\tout9 := Subset(in, 2, 4)\n\n\tis.Empty(slices.Collect(out1))\n\tis.Empty(slices.Collect(out2))\n\tis.Equal([]int{0, 1, 2, 3, 4}, slices.Collect(out4))\n\tis.Equal([]int{0, 1}, slices.Collect(out5))\n\tis.Equal([]int{2, 3}, slices.Collect(out6))\n\tis.Equal([]int{2, 3, 4}, slices.Collect(out7))\n\tis.Equal([]int{2, 3, 4}, slices.Collect(out8))\n\tis.Equal([]int{2, 3, 4}, slices.Collect(out9))\n\n\ttype myStrings iter.Seq[string]\n\tallStrings := myStrings(values(\"\", \"foo\", \"bar\"))\n\tnonempty := Subset(allStrings, 0, 2)\n\tis.IsType(nonempty, allStrings, \"type preserved\")\n}\n\nfunc TestSlice(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tin := values(0, 1, 2, 3, 4)\n\n\tout1 := Slice(in, 0, 0)\n\tout2 := Slice(in, 0, 1)\n\tout3 := Slice(in, 0, 5)\n\tout4 := Slice(in, 0, 6)\n\tout5 := Slice(in, 1, 1)\n\tout6 := Slice(in, 1, 5)\n\tout7 := Slice(in, 1, 6)\n\tout8 := Slice(in, 4, 5)\n\tout9 := Slice(in, 5, 5)\n\tout10 := Slice(in, 6, 5)\n\tout11 := Slice(in, 6, 6)\n\tout12 := Slice(in, 1, 0)\n\tout13 := Slice(in, 5, 0)\n\tout14 := Slice(in, 6, 4)\n\tout15 := Slice(in, 6, 7)\n\n\tis.Empty(slices.Collect(out1))\n\tis.Equal([]int{0}, slices.Collect(out2))\n\tis.Equal([]int{0, 1, 2, 3, 4}, slices.Collect(out3))\n\tis.Equal([]int{0, 1, 2, 3, 4}, slices.Collect(out4))\n\tis.Empty(slices.Collect(out5))\n\tis.Equal([]int{1, 2, 3, 4}, slices.Collect(out6))\n\tis.Equal([]int{1, 2, 3, 4}, slices.Collect(out7))\n\tis.Equal([]int{4}, slices.Collect(out8))\n\tis.Empty(slices.Collect(out9))\n\tis.Empty(slices.Collect(out10))\n\tis.Empty(slices.Collect(out11))\n\tis.Empty(slices.Collect(out12))\n\tis.Empty(slices.Collect(out13))\n\tis.Empty(slices.Collect(out14))\n\tis.Empty(slices.Collect(out15))\n\n\ttype myStrings iter.Seq[string]\n\tallStrings := myStrings(values(\"\", \"foo\", \"bar\"))\n\tnonempty := Slice(allStrings, 0, 2)\n\tis.IsType(nonempty, allStrings, \"type preserved\")\n}\n\nfunc TestReplace(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tin := values(0, 1, 0, 1, 2, 3, 0)\n\n\tout1 := Replace(in, 0, 42, 2)\n\tout2 := Replace(in, 0, 42, 1)\n\tout3 := Replace(in, 0, 42, 0)\n\tout4 := Replace(in, 0, 42, -1)\n\tout5 := Replace(in, 0, 42, -1)\n\tout6 := Replace(in, -1, 42, 2)\n\tout7 := Replace(in, -1, 42, 1)\n\tout8 := Replace(in, -1, 42, 0)\n\tout9 := Replace(in, -1, 42, -1)\n\tout10 := Replace(in, -1, 42, -1)\n\n\tis.Equal([]int{42, 1, 42, 1, 2, 3, 0}, slices.Collect(out1))\n\tis.Equal([]int{42, 1, 42, 1, 2, 3, 0}, slices.Collect(out1)) // check no counter mutation\n\tis.Equal([]int{42, 1, 0, 1, 2, 3, 0}, slices.Collect(out2))\n\tis.Equal([]int{0, 1, 0, 1, 2, 3, 0}, slices.Collect(out3))\n\tis.Equal([]int{42, 1, 42, 1, 2, 3, 42}, slices.Collect(out4))\n\tis.Equal([]int{42, 1, 42, 1, 2, 3, 42}, slices.Collect(out5))\n\tis.Equal([]int{0, 1, 0, 1, 2, 3, 0}, slices.Collect(out6))\n\tis.Equal([]int{0, 1, 0, 1, 2, 3, 0}, slices.Collect(out7))\n\tis.Equal([]int{0, 1, 0, 1, 2, 3, 0}, slices.Collect(out8))\n\tis.Equal([]int{0, 1, 0, 1, 2, 3, 0}, slices.Collect(out9))\n\tis.Equal([]int{0, 1, 0, 1, 2, 3, 0}, slices.Collect(out10))\n\n\ttype myStrings iter.Seq[string]\n\tallStrings := myStrings(values(\"\", \"foo\", \"bar\"))\n\tnonempty := Replace(allStrings, \"0\", \"2\", 1)\n\tis.IsType(nonempty, allStrings, \"type preserved\")\n}\n\nfunc TestReplaceAll(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tin := values(0, 1, 0, 1, 2, 3, 0)\n\n\tout1 := ReplaceAll(in, 0, 42)\n\tout2 := ReplaceAll(in, -1, 42)\n\n\tis.Equal([]int{42, 1, 42, 1, 2, 3, 42}, slices.Collect(out1))\n\tis.Equal([]int{0, 1, 0, 1, 2, 3, 0}, slices.Collect(out2))\n\n\ttype myStrings iter.Seq[string]\n\tallStrings := myStrings(values(\"\", \"foo\", \"bar\"))\n\tnonempty := ReplaceAll(allStrings, \"0\", \"2\")\n\tis.IsType(nonempty, allStrings, \"type preserved\")\n}\n\nfunc TestCompact(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tr1 := Compact(values(2, 0, 4, 0))\n\n\tis.Equal([]int{2, 4}, slices.Collect(r1))\n\n\tr2 := Compact(values(\"\", \"foo\", \"\", \"bar\", \"\"))\n\n\tis.Equal([]string{\"foo\", \"bar\"}, slices.Collect(r2))\n\n\tr3 := Compact(values(true, false, true, false))\n\n\tis.Equal([]bool{true, true}, slices.Collect(r3))\n\n\ttype foo struct {\n\t\tbar int\n\t\tbaz string\n\t}\n\n\t// sequence of structs\n\t// If all fields of an element are zero values, Compact removes it.\n\n\tr4 := Compact(values(\n\t\tfoo{bar: 1, baz: \"a\"}, // all fields are non-zero values\n\t\tfoo{bar: 0, baz: \"\"},  // all fields are zero values\n\t\tfoo{bar: 2, baz: \"\"},  // bar is non-zero\n\t))\n\n\tis.Equal([]foo{{bar: 1, baz: \"a\"}, {bar: 2, baz: \"\"}}, slices.Collect(r4))\n\n\t// sequence of pointers to structs\n\t// If an element is nil, Compact removes it.\n\n\te1, e2, e3 := foo{bar: 1, baz: \"a\"}, foo{bar: 0, baz: \"\"}, foo{bar: 2, baz: \"\"}\n\t// NOTE: e2 is a zero value of foo, but its pointer &e2 is not a zero value of *foo.\n\tr5 := Compact(values(&e1, &e2, nil, &e3))\n\n\tis.Equal([]*foo{&e1, &e2, &e3}, slices.Collect(r5))\n\n\ttype myStrings iter.Seq[string]\n\tallStrings := myStrings(values(\"\", \"foo\", \"bar\"))\n\tnonempty := Compact(allStrings)\n\tis.IsType(nonempty, allStrings, \"type preserved\")\n}\n\nfunc TestIsSorted(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tis.True(IsSorted(values(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)))\n\tis.True(IsSorted(values(\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\", \"h\", \"i\", \"j\")))\n\n\tis.False(IsSorted(values(0, 1, 4, 3, 2, 5, 6, 7, 8, 9, 10)))\n\tis.False(IsSorted(values(\"a\", \"b\", \"d\", \"c\", \"e\", \"f\", \"g\", \"h\", \"i\", \"j\")))\n}\n\nfunc TestIsSortedBy(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tis.True(IsSortedBy(values(\"a\", \"bb\", \"ccc\"), func(s string) int {\n\t\treturn len(s)\n\t}))\n\n\tis.False(IsSortedBy(values(\"aa\", \"b\", \"ccc\"), func(s string) int {\n\t\treturn len(s)\n\t}))\n\n\tis.True(IsSortedBy(values(\"1\", \"2\", \"3\", \"11\"), func(s string) int {\n\t\tret, _ := strconv.Atoi(s)\n\t\treturn ret\n\t}))\n}\n\nfunc TestSplice(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tsample := values(\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\")\n\n\t// normal case\n\tresults := slices.Collect(Splice(sample, 1, \"1\", \"2\"))\n\tis.Equal([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, slices.Collect(sample))\n\tis.Equal([]string{\"a\", \"1\", \"2\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, results)\n\n\t// positive overflow\n\tresults = slices.Collect(Splice(sample, 42, \"1\", \"2\"))\n\tis.Equal([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, slices.Collect(sample))\n\tis.Equal([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\", \"1\", \"2\"}, results)\n\n\t// other\n\tis.Equal([]string{\"1\", \"2\"}, slices.Collect(Splice(values[string](), 0, \"1\", \"2\")))\n\tis.Equal([]string{\"1\", \"2\"}, slices.Collect(Splice(values[string](), 1, \"1\", \"2\")))\n\tis.Equal([]string{\"1\", \"2\", \"0\"}, slices.Collect(Splice(values(\"0\"), 0, \"1\", \"2\")))\n\tis.Equal([]string{\"0\", \"1\", \"2\"}, slices.Collect(Splice(values(\"0\"), 1, \"1\", \"2\")))\n\n\t// type preserved\n\ttype myStrings iter.Seq[string]\n\tallStrings := myStrings(values(\"\", \"foo\", \"bar\"))\n\tnonempty := Splice(allStrings, 1, \"1\", \"2\")\n\tis.IsType(nonempty, allStrings, \"type preserved\")\n}\n\nfunc TestCutPrefix(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tactual, result := CutPrefix(values(\"a\", \"a\", \"b\"), []string{\"a\"})\n\tis.True(result)\n\tis.Equal([]string{\"a\", \"b\"}, slices.Collect(actual))\n\n\tactual, result = CutPrefix(values(\"a\", \"a\", \"b\"), []string{\"a\"})\n\tis.True(result)\n\tis.Equal([]string{\"a\", \"b\"}, slices.Collect(actual))\n\n\tactual, result = CutPrefix(values(\"a\", \"a\", \"b\"), []string{\"b\"})\n\tis.False(result)\n\tis.Equal([]string{\"a\", \"a\", \"b\"}, slices.Collect(actual))\n\n\tactual, result = CutPrefix(values[string](), []string{\"b\"})\n\tis.False(result)\n\tis.Empty(slices.Collect(actual))\n\n\tactual, result = CutPrefix(values(\"a\", \"a\", \"b\"), []string{})\n\tis.True(result)\n\tis.Equal([]string{\"a\", \"a\", \"b\"}, slices.Collect(actual))\n\n\tactual, result = CutPrefix(values(\"a\", \"a\", \"b\"), []string{\"a\", \"a\", \"b\", \"b\"})\n\tis.False(result)\n\tis.Equal([]string{\"a\", \"a\", \"b\"}, slices.Collect(actual))\n\n\tactual, result = CutPrefix(values(\"a\", \"a\", \"b\"), []string{\"a\", \"b\"})\n\tis.False(result)\n\tis.Equal([]string{\"a\", \"a\", \"b\"}, slices.Collect(actual))\n}\n\nfunc TestCutSuffix(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tactual, result := CutSuffix(values(\"a\", \"a\", \"b\"), []string{\"c\"})\n\tis.False(result)\n\tis.Equal([]string{\"a\", \"a\", \"b\"}, slices.Collect(actual))\n\n\tactual, result = CutSuffix(values(\"a\", \"a\", \"b\"), []string{\"b\"})\n\tis.True(result)\n\tis.Equal([]string{\"a\", \"a\"}, slices.Collect(actual))\n\n\tactual, result = CutSuffix(values(\"a\", \"a\", \"b\"), []string{})\n\tis.True(result)\n\tis.Equal([]string{\"a\", \"a\", \"b\"}, slices.Collect(actual))\n\n\tactual, result = CutSuffix(values(\"a\", \"a\", \"b\"), []string{\"a\"})\n\tis.False(result)\n\tis.Equal([]string{\"a\", \"a\", \"b\"}, slices.Collect(actual))\n\n\tactual, result = CutSuffix(values(\"a\", \"a\", \"b\"), []string{})\n\tis.True(result)\n\tis.Equal([]string{\"a\", \"a\", \"b\"}, slices.Collect(actual))\n}\n\nfunc TestTrim(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tactual := Trim(values(\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"), \"a\", \"b\")\n\tis.Equal([]string{\"c\", \"d\", \"e\", \"f\", \"g\"}, slices.Collect(actual))\n\tactual = Trim(values(\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"), \"g\", \"f\")\n\tis.Equal([]string{\"a\", \"b\", \"c\", \"d\", \"e\"}, slices.Collect(actual))\n\tactual = Trim(values(\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"), \"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\")\n\tis.Empty(slices.Collect(actual))\n\tactual = Trim(values(\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"), \"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\", \"h\")\n\tis.Empty(slices.Collect(actual))\n\tactual = Trim(values(\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"))\n\tis.Equal([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, slices.Collect(actual))\n}\n\nfunc TestTrimFirst(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tactual := TrimFirst(values(\"a\", \"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"), \"a\", \"b\")\n\tis.Equal([]string{\"c\", \"d\", \"e\", \"f\", \"g\"}, slices.Collect(actual))\n\tactual = TrimFirst(values(\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"), \"b\", \"a\")\n\tis.Equal([]string{\"c\", \"d\", \"e\", \"f\", \"g\"}, slices.Collect(actual))\n\tactual = TrimFirst(values(\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"), \"g\", \"f\")\n\tis.Equal([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, slices.Collect(actual))\n\tactual = TrimFirst(values(\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"), \"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\")\n\tis.Empty(slices.Collect(actual))\n\tactual = TrimFirst(values(\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"), \"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\", \"h\")\n\tis.Empty(slices.Collect(actual))\n\tactual = TrimFirst(values(\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"))\n\tis.Equal([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, slices.Collect(actual))\n}\n\nfunc TestTrimPrefix(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tactual := TrimPrefix(values(\"a\", \"b\", \"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"), []string{\"a\", \"b\"})\n\tis.Equal([]string{\"c\", \"d\", \"e\", \"f\", \"g\"}, slices.Collect(actual))\n\tactual = TrimPrefix(values(\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"), []string{\"b\", \"a\"})\n\tis.Equal([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, slices.Collect(actual))\n\tactual = TrimPrefix(values(\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"), []string{\"g\", \"f\"})\n\tis.Equal([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, slices.Collect(actual))\n\tactual = TrimPrefix(values(\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"), []string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"})\n\tis.Empty(slices.Collect(actual))\n\tactual = TrimPrefix(values(\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"), []string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\", \"h\"})\n\tis.Equal([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, slices.Collect(actual))\n\tactual = TrimPrefix(values(\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"), []string{})\n\tis.Equal([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, slices.Collect(actual))\n}\n\nfunc TestTrimLast(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tactual := TrimLast(values(\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"), \"a\", \"b\")\n\tis.Equal([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, slices.Collect(actual))\n\tactual = TrimLast(values(\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\", \"g\"), \"g\", \"f\")\n\tis.Equal([]string{\"a\", \"b\", \"c\", \"d\", \"e\"}, slices.Collect(actual))\n\tactual = TrimLast(values(\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"), \"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\")\n\tis.Empty(slices.Collect(actual))\n\tactual = TrimLast(values(\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"), \"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\", \"h\")\n\tis.Empty(slices.Collect(actual))\n\tactual = TrimLast(values(\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"))\n\tis.Equal([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, slices.Collect(actual))\n}\n\nfunc TestTrimSuffix(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tactual := TrimSuffix(values(\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"), []string{\"a\", \"b\"})\n\tis.Equal([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, slices.Collect(actual))\n\tactual = TrimSuffix(values(\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\", \"f\", \"g\"), []string{\"f\", \"g\"})\n\tis.Equal([]string{\"a\", \"b\", \"c\", \"d\", \"e\"}, slices.Collect(actual))\n\tactual = TrimSuffix(values(\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\", \"f\", \"g\"), []string{\"g\", \"f\"})\n\tis.Equal([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\", \"f\", \"g\"}, slices.Collect(actual))\n\tactual = TrimSuffix(values(\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"f\", \"g\"), []string{\"f\", \"g\"})\n\tis.Equal([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\"}, slices.Collect(actual))\n\tactual = TrimSuffix(values(\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"), []string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"})\n\tis.Empty(slices.Collect(actual))\n\tactual = TrimSuffix(values(\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"), []string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\", \"h\"})\n\tis.Equal([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, slices.Collect(actual))\n\tactual = TrimSuffix(values(\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"), []string{})\n\tis.Equal([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, slices.Collect(actual))\n}\n\nfunc TestBuffer(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\t// full batches\n\tbatches := slices.Collect(Buffer(RangeFrom(1, 6), 2))\n\tis.Equal([][]int{{1, 2}, {3, 4}, {5, 6}}, batches)\n\n\t// partial last batch\n\tbatches2 := slices.Collect(Buffer(RangeFrom(1, 5), 2))\n\tis.Equal([][]int{{1, 2}, {3, 4}, {5}}, batches2)\n\n\t// empty channel\n\tbatches3 := slices.Collect(Buffer(RangeFrom(1, 0), 2))\n\tis.Empty(batches3)\n\n\t// stop after first batch (early termination)\n\tbatches4 := slices.Collect(Take(Buffer(RangeFrom(1, 6), 2), 1))\n\tis.Equal([][]int{{1, 2}}, batches4)\n}\n"
  },
  {
    "path": "it/string.go",
    "content": "//go:build go1.23\n\npackage it\n\nimport \"iter\"\n\n// ChunkString returns a sequence of strings split into groups of length size. If the string can't be split evenly,\n// the final chunk will be the remaining characters.\n// Play: https://go.dev/play/p/Bcc5ixTQQoQ\n//\n// Note: it.ChunkString and it.Chunk functions behave inconsistently for empty input: it.ChunkString(\"\", n) returns [\"\"] instead of [].\n// See https://github.com/samber/lo/issues/788\nfunc ChunkString[T ~string](str T, size int) iter.Seq[T] {\n\tif size <= 0 {\n\t\tpanic(\"it.ChunkString: size must be greater than 0\")\n\t}\n\n\treturn func(yield func(T) bool) {\n\t\tif len(str) == 0 || size >= len(str) {\n\t\t\tyield(str)\n\t\t\treturn\n\t\t}\n\n\t\tcurrentLen := 0\n\t\tcurrentStart := 0\n\t\tfor i := range str {\n\t\t\tif currentLen == size {\n\t\t\t\tif !yield(str[currentStart:i]) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tcurrentLen = 0\n\t\t\t\tcurrentStart = i\n\t\t\t}\n\t\t\tcurrentLen++\n\t\t}\n\t\tyield(str[currentStart:])\n\t}\n}\n"
  },
  {
    "path": "it/string_example_test.go",
    "content": "//go:build go1.23\n\npackage it\n\nimport (\n\t\"fmt\"\n\t\"slices\"\n)\n\nfunc ExampleChunkString() {\n\tresult1 := ChunkString(\"123456\", 2)\n\tresult2 := ChunkString(\"1234567\", 2)\n\tresult3 := ChunkString(\"\", 2)\n\tresult4 := ChunkString(\"1\", 2)\n\n\tfmt.Printf(\"%v\\n\", slices.Collect(result1))\n\tfmt.Printf(\"%v\\n\", slices.Collect(result2))\n\tfmt.Printf(\"%v\\n\", slices.Collect(result3))\n\tfmt.Printf(\"%v\\n\", slices.Collect(result4))\n\t// Output:\n\t// [12 34 56]\n\t// [12 34 56 7]\n\t// []\n\t// [1]\n}\n"
  },
  {
    "path": "it/string_test.go",
    "content": "//go:build go1.23\n\npackage it\n\nimport (\n\t\"slices\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestChunkString(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := ChunkString(\"12345\", 2)\n\tis.Equal([]string{\"12\", \"34\", \"5\"}, slices.Collect(result1))\n\n\tresult2 := ChunkString(\"123456\", 2)\n\tis.Equal([]string{\"12\", \"34\", \"56\"}, slices.Collect(result2))\n\n\tresult3 := ChunkString(\"123456\", 6)\n\tis.Equal([]string{\"123456\"}, slices.Collect(result3))\n\n\tresult4 := ChunkString(\"123456\", 10)\n\tis.Equal([]string{\"123456\"}, slices.Collect(result4))\n\n\tresult5 := ChunkString(\"\", 2)\n\tis.Equal([]string{\"\"}, slices.Collect(result5)) // @TODO: should be [] - see https://github.com/samber/lo/issues/788\n\n\tresult6 := ChunkString(\"明1好休2林森\", 2)\n\tis.Equal([]string{\"明1\", \"好休\", \"2林\", \"森\"}, slices.Collect(result6))\n\n\tis.PanicsWithValue(\"it.ChunkString: size must be greater than 0\", func() {\n\t\tChunkString(\"12345\", 0)\n\t})\n}\n"
  },
  {
    "path": "it/tuples.go",
    "content": "//go:build go1.23\n\npackage it\n\nimport (\n\t\"iter\"\n\n\t\"github.com/samber/lo\"\n)\n\n// Zip2 creates a sequence of grouped elements, the first of which contains the first elements\n// of the given sequences, the second of which contains the second elements of the given sequences, and so on.\n// When collections are different sizes, the Tuple attributes are filled with zero value.\n// Play: https://go.dev/play/p/U5nBWvR8eUZ\nfunc Zip2[A, B any](a iter.Seq[A], b iter.Seq[B]) iter.Seq[lo.Tuple2[A, B]] {\n\treturn func(yield func(lo.Tuple2[A, B]) bool) {\n\t\tnextA, stopA := iter.Pull(a)\n\t\tdefer stopA()\n\t\tnextB, stopB := iter.Pull(b)\n\t\tdefer stopB()\n\n\t\tfor {\n\t\t\tvar item lo.Tuple2[A, B]\n\t\t\tvar ok [2]bool\n\t\t\titem.A, ok[0] = nextA()\n\t\t\titem.B, ok[1] = nextB()\n\t\t\tif ok == [2]bool{} || !yield(item) {\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}\n}\n\n// Zip3 creates a sequence of grouped elements, the first of which contains the first elements\n// of the given sequences, the second of which contains the second elements of the given sequences, and so on.\n// When collections are different sizes, the Tuple attributes are filled with zero value.\n// Play: https://go.dev/play/p/V5wL9xY8nQr\nfunc Zip3[A, B, C any](a iter.Seq[A], b iter.Seq[B], c iter.Seq[C]) iter.Seq[lo.Tuple3[A, B, C]] {\n\treturn func(yield func(lo.Tuple3[A, B, C]) bool) {\n\t\tnextA, stopA := iter.Pull(a)\n\t\tdefer stopA()\n\t\tnextB, stopB := iter.Pull(b)\n\t\tdefer stopB()\n\t\tnextC, stopC := iter.Pull(c)\n\t\tdefer stopC()\n\n\t\tfor {\n\t\t\tvar item lo.Tuple3[A, B, C]\n\t\t\tvar ok [3]bool\n\t\t\titem.A, ok[0] = nextA()\n\t\t\titem.B, ok[1] = nextB()\n\t\t\titem.C, ok[2] = nextC()\n\t\t\tif ok == [3]bool{} || !yield(item) {\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}\n}\n\n// Zip4 creates a sequence of grouped elements, the first of which contains the first elements\n// of the given sequences, the second of which contains the second elements of the given sequences, and so on.\n// When collections are different sizes, the Tuple attributes are filled with zero value.\n// Play: https://go.dev/play/p/W6xM7zZ9oSt\nfunc Zip4[A, B, C, D any](a iter.Seq[A], b iter.Seq[B], c iter.Seq[C], d iter.Seq[D]) iter.Seq[lo.Tuple4[A, B, C, D]] {\n\treturn func(yield func(lo.Tuple4[A, B, C, D]) bool) {\n\t\tnextA, stopA := iter.Pull(a)\n\t\tdefer stopA()\n\t\tnextB, stopB := iter.Pull(b)\n\t\tdefer stopB()\n\t\tnextC, stopC := iter.Pull(c)\n\t\tdefer stopC()\n\t\tnextD, stopD := iter.Pull(d)\n\t\tdefer stopD()\n\n\t\tfor {\n\t\t\tvar item lo.Tuple4[A, B, C, D]\n\t\t\tvar ok [4]bool\n\t\t\titem.A, ok[0] = nextA()\n\t\t\titem.B, ok[1] = nextB()\n\t\t\titem.C, ok[2] = nextC()\n\t\t\titem.D, ok[3] = nextD()\n\t\t\tif ok == [4]bool{} || !yield(item) {\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}\n}\n\n// Zip5 creates a sequence of grouped elements, the first of which contains the first elements\n// of the given sequences, the second of which contains the second elements of the given sequences, and so on.\n// When collections are different sizes, the Tuple attributes are filled with zero value.\n// Play: https://go.dev/play/p/X7yN8aA1pUv\nfunc Zip5[A, B, C, D, E any](a iter.Seq[A], b iter.Seq[B], c iter.Seq[C], d iter.Seq[D], e iter.Seq[E]) iter.Seq[lo.Tuple5[A, B, C, D, E]] {\n\treturn func(yield func(lo.Tuple5[A, B, C, D, E]) bool) {\n\t\tnextA, stopA := iter.Pull(a)\n\t\tdefer stopA()\n\t\tnextB, stopB := iter.Pull(b)\n\t\tdefer stopB()\n\t\tnextC, stopC := iter.Pull(c)\n\t\tdefer stopC()\n\t\tnextD, stopD := iter.Pull(d)\n\t\tdefer stopD()\n\t\tnextE, stopE := iter.Pull(e)\n\t\tdefer stopE()\n\n\t\tfor {\n\t\t\tvar item lo.Tuple5[A, B, C, D, E]\n\t\t\tvar ok [5]bool\n\t\t\titem.A, ok[0] = nextA()\n\t\t\titem.B, ok[1] = nextB()\n\t\t\titem.C, ok[2] = nextC()\n\t\t\titem.D, ok[3] = nextD()\n\t\t\titem.E, ok[4] = nextE()\n\t\t\tif ok == [5]bool{} || !yield(item) {\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}\n}\n\n// Zip6 creates a sequence of grouped elements, the first of which contains the first elements\n// of the given sequences, the second of which contains the second elements of the given sequences, and so on.\n// When collections are different sizes, the Tuple attributes are filled with zero value.\n// Play: https://go.dev/play/p/Y4mN8bB2cXw\nfunc Zip6[A, B, C, D, E, F any](a iter.Seq[A], b iter.Seq[B], c iter.Seq[C], d iter.Seq[D], e iter.Seq[E], f iter.Seq[F]) iter.Seq[lo.Tuple6[A, B, C, D, E, F]] {\n\treturn func(yield func(lo.Tuple6[A, B, C, D, E, F]) bool) {\n\t\tnextA, stopA := iter.Pull(a)\n\t\tdefer stopA()\n\t\tnextB, stopB := iter.Pull(b)\n\t\tdefer stopB()\n\t\tnextC, stopC := iter.Pull(c)\n\t\tdefer stopC()\n\t\tnextD, stopD := iter.Pull(d)\n\t\tdefer stopD()\n\t\tnextE, stopE := iter.Pull(e)\n\t\tdefer stopE()\n\t\tnextF, stopF := iter.Pull(f)\n\t\tdefer stopF()\n\n\t\tfor {\n\t\t\tvar item lo.Tuple6[A, B, C, D, E, F]\n\t\t\tvar ok [6]bool\n\t\t\titem.A, ok[0] = nextA()\n\t\t\titem.B, ok[1] = nextB()\n\t\t\titem.C, ok[2] = nextC()\n\t\t\titem.D, ok[3] = nextD()\n\t\t\titem.E, ok[4] = nextE()\n\t\t\titem.F, ok[5] = nextF()\n\t\t\tif ok == [6]bool{} || !yield(item) {\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}\n}\n\n// Zip7 creates a sequence of grouped elements, the first of which contains the first elements\n// of the given sequences, the second of which contains the second elements of the given sequences, and so on.\n// When collections are different sizes, the Tuple attributes are filled with zero value.\n// Play: https://go.dev/play/p/Z9nA8cC3dXw\nfunc Zip7[A, B, C, D, E, F, G any](a iter.Seq[A], b iter.Seq[B], c iter.Seq[C], d iter.Seq[D], e iter.Seq[E], f iter.Seq[F], g iter.Seq[G]) iter.Seq[lo.Tuple7[A, B, C, D, E, F, G]] {\n\treturn func(yield func(lo.Tuple7[A, B, C, D, E, F, G]) bool) {\n\t\tnextA, stopA := iter.Pull(a)\n\t\tdefer stopA()\n\t\tnextB, stopB := iter.Pull(b)\n\t\tdefer stopB()\n\t\tnextC, stopC := iter.Pull(c)\n\t\tdefer stopC()\n\t\tnextD, stopD := iter.Pull(d)\n\t\tdefer stopD()\n\t\tnextE, stopE := iter.Pull(e)\n\t\tdefer stopE()\n\t\tnextF, stopF := iter.Pull(f)\n\t\tdefer stopF()\n\t\tnextG, stopG := iter.Pull(g)\n\t\tdefer stopG()\n\n\t\tfor {\n\t\t\tvar item lo.Tuple7[A, B, C, D, E, F, G]\n\t\t\tvar ok [7]bool\n\t\t\titem.A, ok[0] = nextA()\n\t\t\titem.B, ok[1] = nextB()\n\t\t\titem.C, ok[2] = nextC()\n\t\t\titem.D, ok[3] = nextD()\n\t\t\titem.E, ok[4] = nextE()\n\t\t\titem.F, ok[5] = nextF()\n\t\t\titem.G, ok[6] = nextG()\n\t\t\tif ok == [7]bool{} || !yield(item) {\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}\n}\n\n// Zip8 creates a sequence of grouped elements, the first of which contains the first elements\n// of the given sequences, the second of which contains the second elements of the given sequences, and so on.\n// When collections are different sizes, the Tuple attributes are filled with zero value.\n// Play: https://go.dev/play/p/0XrQKOk-vw\nfunc Zip8[A, B, C, D, E, F, G, H any](a iter.Seq[A], b iter.Seq[B], c iter.Seq[C], d iter.Seq[D], e iter.Seq[E], f iter.Seq[F], g iter.Seq[G], h iter.Seq[H]) iter.Seq[lo.Tuple8[A, B, C, D, E, F, G, H]] {\n\treturn func(yield func(lo.Tuple8[A, B, C, D, E, F, G, H]) bool) {\n\t\tnextA, stopA := iter.Pull(a)\n\t\tdefer stopA()\n\t\tnextB, stopB := iter.Pull(b)\n\t\tdefer stopB()\n\t\tnextC, stopC := iter.Pull(c)\n\t\tdefer stopC()\n\t\tnextD, stopD := iter.Pull(d)\n\t\tdefer stopD()\n\t\tnextE, stopE := iter.Pull(e)\n\t\tdefer stopE()\n\t\tnextF, stopF := iter.Pull(f)\n\t\tdefer stopF()\n\t\tnextG, stopG := iter.Pull(g)\n\t\tdefer stopG()\n\t\tnextH, stopH := iter.Pull(h)\n\t\tdefer stopH()\n\n\t\tfor {\n\t\t\tvar item lo.Tuple8[A, B, C, D, E, F, G, H]\n\t\t\tvar ok [8]bool\n\t\t\titem.A, ok[0] = nextA()\n\t\t\titem.B, ok[1] = nextB()\n\t\t\titem.C, ok[2] = nextC()\n\t\t\titem.D, ok[3] = nextD()\n\t\t\titem.E, ok[4] = nextE()\n\t\t\titem.F, ok[5] = nextF()\n\t\t\titem.G, ok[6] = nextG()\n\t\t\titem.H, ok[7] = nextH()\n\t\t\tif ok == [8]bool{} || !yield(item) {\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}\n}\n\n// Zip9 creates a sequence of grouped elements, the first of which contains the first elements\n// of the given sequences, the second of which contains the second elements of the given sequences, and so on.\n// When collections are different sizes, the Tuple attributes are filled with zero value.\n// Play: https://go.dev/play/p/1SmFJ5-zr\nfunc Zip9[A, B, C, D, E, F, G, H, I any](a iter.Seq[A], b iter.Seq[B], c iter.Seq[C], d iter.Seq[D], e iter.Seq[E], f iter.Seq[F], g iter.Seq[G], h iter.Seq[H], i iter.Seq[I]) iter.Seq[lo.Tuple9[A, B, C, D, E, F, G, H, I]] {\n\treturn func(yield func(lo.Tuple9[A, B, C, D, E, F, G, H, I]) bool) {\n\t\tnextA, stopA := iter.Pull(a)\n\t\tdefer stopA()\n\t\tnextB, stopB := iter.Pull(b)\n\t\tdefer stopB()\n\t\tnextC, stopC := iter.Pull(c)\n\t\tdefer stopC()\n\t\tnextD, stopD := iter.Pull(d)\n\t\tdefer stopD()\n\t\tnextE, stopE := iter.Pull(e)\n\t\tdefer stopE()\n\t\tnextF, stopF := iter.Pull(f)\n\t\tdefer stopF()\n\t\tnextG, stopG := iter.Pull(g)\n\t\tdefer stopG()\n\t\tnextH, stopH := iter.Pull(h)\n\t\tdefer stopH()\n\t\tnextI, stopI := iter.Pull(i)\n\t\tdefer stopI()\n\n\t\tfor {\n\t\t\tvar item lo.Tuple9[A, B, C, D, E, F, G, H, I]\n\t\t\tvar ok [9]bool\n\t\t\titem.A, ok[0] = nextA()\n\t\t\titem.B, ok[1] = nextB()\n\t\t\titem.C, ok[2] = nextC()\n\t\t\titem.D, ok[3] = nextD()\n\t\t\titem.E, ok[4] = nextE()\n\t\t\titem.F, ok[5] = nextF()\n\t\t\titem.G, ok[6] = nextG()\n\t\t\titem.H, ok[7] = nextH()\n\t\t\titem.I, ok[8] = nextI()\n\t\t\tif ok == [9]bool{} || !yield(item) {\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}\n}\n\n// ZipBy2 creates a sequence of transformed elements, the first of which contains the first elements\n// of the given sequences, the second of which contains the second elements of the given sequences, and so on.\n// When collections are different sizes, the Tuple attributes are filled with zero value.\n// Play: https://go.dev/play/p/y03uqMEAi1E\nfunc ZipBy2[A, B, Out any](a iter.Seq[A], b iter.Seq[B], transform func(a A, b B) Out) iter.Seq[Out] {\n\treturn Map(Zip2(a, b), func(item lo.Tuple2[A, B]) Out {\n\t\treturn transform(item.A, item.B)\n\t})\n}\n\n// ZipBy3 creates a sequence of transformed elements, the first of which contains the first elements\n// of the given sequences, the second of which contains the second elements of the given sequences, and so on.\n// When collections are different sizes, the Tuple attributes are filled with zero value.\n// Play: https://go.dev/play/p/3UoHL7-zt\nfunc ZipBy3[A, B, C, Out any](a iter.Seq[A], b iter.Seq[B], c iter.Seq[C], transform func(a A, b B, c C) Out) iter.Seq[Out] {\n\treturn Map(Zip3(a, b, c), func(item lo.Tuple3[A, B, C]) Out {\n\t\treturn transform(item.A, item.B, item.C)\n\t})\n}\n\n// ZipBy4 creates a sequence of transformed elements, the first of which contains the first elements\n// of the given sequences, the second of which contains the second elements of the given sequences, and so on.\n// When collections are different sizes, the Tuple attributes are filled with zero value.\n// Play: https://go.dev/play/p/4VpIM8-zu\nfunc ZipBy4[A, B, C, D, Out any](a iter.Seq[A], b iter.Seq[B], c iter.Seq[C], d iter.Seq[D], transform func(a A, b B, c C, d D) Out) iter.Seq[Out] {\n\treturn Map(Zip4(a, b, c, d), func(item lo.Tuple4[A, B, C, D]) Out {\n\t\treturn transform(item.A, item.B, item.C, item.D)\n\t})\n}\n\n// ZipBy5 creates a sequence of transformed elements, the first of which contains the first elements\n// of the given sequences, the second of which contains the second elements of the given sequences, and so on.\n// When collections are different sizes, the Tuple attributes are filled with zero value.\n// Play: https://go.dev/play/p/5WqJN9-zv\nfunc ZipBy5[A, B, C, D, E, Out any](a iter.Seq[A], b iter.Seq[B], c iter.Seq[C], d iter.Seq[D], e iter.Seq[E], transform func(a A, b B, c C, d D, e E) Out) iter.Seq[Out] {\n\treturn Map(Zip5(a, b, c, d, e), func(item lo.Tuple5[A, B, C, D, E]) Out {\n\t\treturn transform(item.A, item.B, item.C, item.D, item.E)\n\t})\n}\n\n// ZipBy6 creates a sequence of transformed elements, the first of which contains the first elements\n// of the given sequences, the second of which contains the second elements of the given sequences, and so on.\n// When collections are different sizes, the Tuple attributes are filled with zero value.\n// Play: https://go.dev/play/p/6XrKO0-zw\nfunc ZipBy6[A, B, C, D, E, F, Out any](a iter.Seq[A], b iter.Seq[B], c iter.Seq[C], d iter.Seq[D], e iter.Seq[E], f iter.Seq[F], transform func(a A, b B, c C, d D, e E, f F) Out) iter.Seq[Out] {\n\treturn Map(Zip6(a, b, c, d, e, f), func(item lo.Tuple6[A, B, C, D, E, F]) Out {\n\t\treturn transform(item.A, item.B, item.C, item.D, item.E, item.F)\n\t})\n}\n\n// ZipBy7 creates a sequence of transformed elements, the first of which contains the first elements\n// of the given sequences, the second of which contains the second elements of the given sequences, and so on.\n// When collections are different sizes, the Tuple attributes are filled with zero value.\n// Play: https://go.dev/play/p/7YsLP1-zx\nfunc ZipBy7[A, B, C, D, E, F, G, Out any](a iter.Seq[A], b iter.Seq[B], c iter.Seq[C], d iter.Seq[D], e iter.Seq[E], f iter.Seq[F], g iter.Seq[G], transform func(a A, b B, c C, d D, e E, f F, g G) Out) iter.Seq[Out] {\n\treturn Map(Zip7(a, b, c, d, e, f, g), func(item lo.Tuple7[A, B, C, D, E, F, G]) Out {\n\t\treturn transform(item.A, item.B, item.C, item.D, item.E, item.F, item.G)\n\t})\n}\n\n// ZipBy8 creates a sequence of transformed elements, the first of which contains the first elements\n// of the given sequences, the second of which contains the second elements of the given sequences, and so on.\n// When collections are different sizes, the Tuple attributes are filled with zero value.\n// Play: https://go.dev/play/p/8isgTsyfL-t\nfunc ZipBy8[A, B, C, D, E, F, G, H, Out any](a iter.Seq[A], b iter.Seq[B], c iter.Seq[C], d iter.Seq[D], e iter.Seq[E], f iter.Seq[F], g iter.Seq[G], h iter.Seq[H], transform func(a A, b B, c C, d D, e E, f F, g G, h H) Out) iter.Seq[Out] {\n\treturn Map(Zip8(a, b, c, d, e, f, g, h), func(item lo.Tuple8[A, B, C, D, E, F, G, H]) Out {\n\t\treturn transform(item.A, item.B, item.C, item.D, item.E, item.F, item.G, item.H)\n\t})\n}\n\n// ZipBy9 creates a sequence of transformed elements, the first of which contains the first elements\n// of the given sequences, the second of which contains the second elements of the given sequences, and so on.\n// When collections are different sizes, the Tuple attributes are filled with zero value.\n// Play: https://go.dev/play/p/9jthUzgF-u\nfunc ZipBy9[A, B, C, D, E, F, G, H, I, Out any](a iter.Seq[A], b iter.Seq[B], c iter.Seq[C], d iter.Seq[D], e iter.Seq[E], f iter.Seq[F], g iter.Seq[G], h iter.Seq[H], i iter.Seq[I], transform func(a A, b B, c C, d D, e E, f F, g G, h H, i I) Out) iter.Seq[Out] {\n\treturn Map(Zip9(a, b, c, d, e, f, g, h, i), func(item lo.Tuple9[A, B, C, D, E, F, G, H, I]) Out {\n\t\treturn transform(item.A, item.B, item.C, item.D, item.E, item.F, item.G, item.H, item.I)\n\t})\n}\n\n// CrossJoin2 combines every item from one list with every item from others.\n// It is the cartesian product of lists received as arguments.\n// Returns an empty list if a list is empty.\n// Play: https://go.dev/play/p/OFe8xjZFjWU\nfunc CrossJoin2[A, B any](listA iter.Seq[A], listB iter.Seq[B]) iter.Seq[lo.Tuple2[A, B]] {\n\treturn CrossJoinBy2(listA, listB, lo.T2[A, B])\n}\n\n// CrossJoin3 combines every item from one list with every item from others.\n// It is the cartesian product of lists received as arguments.\n// Returns an empty list if a list is empty.\n// Play: https://go.dev/play/p/0XrQKOk-vw\nfunc CrossJoin3[A, B, C any](listA iter.Seq[A], listB iter.Seq[B], listC iter.Seq[C]) iter.Seq[lo.Tuple3[A, B, C]] {\n\treturn CrossJoinBy3(listA, listB, listC, lo.T3[A, B, C])\n}\n\n// CrossJoin4 combines every item from one list with every item from others.\n// It is the cartesian product of lists received as arguments.\n// Returns an empty list if a list is empty.\n// Play: https://go.dev/play/p/1SmFJ5-zr\nfunc CrossJoin4[A, B, C, D any](listA iter.Seq[A], listB iter.Seq[B], listC iter.Seq[C], listD iter.Seq[D]) iter.Seq[lo.Tuple4[A, B, C, D]] {\n\treturn CrossJoinBy4(listA, listB, listC, listD, lo.T4[A, B, C, D])\n}\n\n// CrossJoin5 combines every item from one list with every item from others.\n// It is the cartesian product of lists received as arguments.\n// Returns an empty list if a list is empty.\n// Play: https://go.dev/play/p/2TnGK6-zs\nfunc CrossJoin5[A, B, C, D, E any](listA iter.Seq[A], listB iter.Seq[B], listC iter.Seq[C], listD iter.Seq[D], listE iter.Seq[E]) iter.Seq[lo.Tuple5[A, B, C, D, E]] {\n\treturn CrossJoinBy5(listA, listB, listC, listD, listE, lo.T5[A, B, C, D, E])\n}\n\n// CrossJoin6 combines every item from one list with every item from others.\n// It is the cartesian product of lists received as arguments.\n// Returns an empty list if a list is empty.\n// Play: https://go.dev/play/p/3UoHL7-zt\nfunc CrossJoin6[A, B, C, D, E, F any](listA iter.Seq[A], listB iter.Seq[B], listC iter.Seq[C], listD iter.Seq[D], listE iter.Seq[E], listF iter.Seq[F]) iter.Seq[lo.Tuple6[A, B, C, D, E, F]] {\n\treturn CrossJoinBy6(listA, listB, listC, listD, listE, listF, lo.T6[A, B, C, D, E, F])\n}\n\n// CrossJoin7 combines every item from one list with every item from others.\n// It is the cartesian product of lists received as arguments.\n// Returns an empty list if a list is empty.\n// Play: https://go.dev/play/p/4VpIM8-zu\nfunc CrossJoin7[A, B, C, D, E, F, G any](listA iter.Seq[A], listB iter.Seq[B], listC iter.Seq[C], listD iter.Seq[D], listE iter.Seq[E], listF iter.Seq[F], listG iter.Seq[G]) iter.Seq[lo.Tuple7[A, B, C, D, E, F, G]] {\n\treturn CrossJoinBy7(listA, listB, listC, listD, listE, listF, listG, lo.T7[A, B, C, D, E, F, G])\n}\n\n// CrossJoin8 combines every item from one list with every item from others.\n// It is the cartesian product of lists received as arguments.\n// Returns an empty list if a list is empty.\n// Play: https://go.dev/play/p/5WqJN9-zv\nfunc CrossJoin8[A, B, C, D, E, F, G, H any](listA iter.Seq[A], listB iter.Seq[B], listC iter.Seq[C], listD iter.Seq[D], listE iter.Seq[E], listF iter.Seq[F], listG iter.Seq[G], listH iter.Seq[H]) iter.Seq[lo.Tuple8[A, B, C, D, E, F, G, H]] {\n\treturn CrossJoinBy8(listA, listB, listC, listD, listE, listF, listG, listH, lo.T8[A, B, C, D, E, F, G, H])\n}\n\n// CrossJoin9 combines every item from one list with every item from others.\n// It is the cartesian product of lists received as arguments.\n// Returns an empty list if a list is empty.\n// Play: https://go.dev/play/p/6XrKO0-zw\nfunc CrossJoin9[A, B, C, D, E, F, G, H, I any](listA iter.Seq[A], listB iter.Seq[B], listC iter.Seq[C], listD iter.Seq[D], listE iter.Seq[E], listF iter.Seq[F], listG iter.Seq[G], listH iter.Seq[H], listI iter.Seq[I]) iter.Seq[lo.Tuple9[A, B, C, D, E, F, G, H, I]] {\n\treturn CrossJoinBy9(listA, listB, listC, listD, listE, listF, listG, listH, listI, lo.T9[A, B, C, D, E, F, G, H, I])\n}\n\n// CrossJoinBy2 combines every item from one list with every item from others.\n// It is the cartesian product of lists received as arguments. The transform function\n// is used to create the output values.\n// Returns an empty list if a list is empty.\n// Play: https://go.dev/play/p/6QGp3W-bQU1\nfunc CrossJoinBy2[A, B, Out any](listA iter.Seq[A], listB iter.Seq[B], transform func(a A, b B) Out) iter.Seq[Out] {\n\treturn func(yield func(Out) bool) {\n\t\tfor a := range listA {\n\t\t\tfor b := range listB {\n\t\t\t\tif !yield(transform(a, b)) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n// CrossJoinBy3 combines every item from one list with every item from others.\n// It is the cartesian product of lists received as arguments. The transform function\n// is used to create the output values.\n// Returns an empty list if a list is empty.\n// Play: https://go.dev/play/p/8isgTsyfL-t\nfunc CrossJoinBy3[A, B, C, Out any](listA iter.Seq[A], listB iter.Seq[B], listC iter.Seq[C], transform func(a A, b B, c C) Out) iter.Seq[Out] {\n\treturn func(yield func(Out) bool) {\n\t\tfor a := range listA {\n\t\t\tfor b := range listB {\n\t\t\t\tfor c := range listC {\n\t\t\t\t\tif !yield(transform(a, b, c)) {\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n// CrossJoinBy4 combines every item from one list with every item from others.\n// It is the cartesian product of lists received as arguments. The transform function\n// is used to create the output values.\n// Returns an empty list if a list is empty.\n// Play: https://go.dev/play/p/9jthUzgF-u\nfunc CrossJoinBy4[A, B, C, D, Out any](listA iter.Seq[A], listB iter.Seq[B], listC iter.Seq[C], listD iter.Seq[D], transform func(a A, b B, c C, d D) Out) iter.Seq[Out] {\n\treturn func(yield func(Out) bool) {\n\t\tfor a := range listA {\n\t\t\tfor b := range listB {\n\t\t\t\tfor c := range listC {\n\t\t\t\t\tfor d := range listD {\n\t\t\t\t\t\tif !yield(transform(a, b, c, d)) {\n\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n// CrossJoinBy5 combines every item from one list with every item from others.\n// It is the cartesian product of lists received as arguments. The transform function\n// is used to create the output values.\n// Returns an empty list if a list is empty.\n// Play: https://go.dev/play/p/0XrQKOk-vw\nfunc CrossJoinBy5[A, B, C, D, E, Out any](listA iter.Seq[A], listB iter.Seq[B], listC iter.Seq[C], listD iter.Seq[D], listE iter.Seq[E], transform func(a A, b B, c C, d D, e E) Out) iter.Seq[Out] {\n\treturn func(yield func(Out) bool) {\n\t\tfor a := range listA {\n\t\t\tfor b := range listB {\n\t\t\t\tfor c := range listC {\n\t\t\t\t\tfor d := range listD {\n\t\t\t\t\t\tfor e := range listE {\n\t\t\t\t\t\t\tif !yield(transform(a, b, c, d, e)) {\n\t\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n// CrossJoinBy6 combines every item from one list with every item from others.\n// It is the cartesian product of lists received as arguments. The transform function\n// is used to create the output values.\n// Returns an empty list if a list is empty.\n// Play: https://go.dev/play/p/1SmFJ5-zr\nfunc CrossJoinBy6[A, B, C, D, E, F, Out any](listA iter.Seq[A], listB iter.Seq[B], listC iter.Seq[C], listD iter.Seq[D], listE iter.Seq[E], listF iter.Seq[F], transform func(a A, b B, c C, d D, e E, f F) Out) iter.Seq[Out] {\n\treturn func(yield func(Out) bool) {\n\t\tfor a := range listA {\n\t\t\tfor b := range listB {\n\t\t\t\tfor c := range listC {\n\t\t\t\t\tfor d := range listD {\n\t\t\t\t\t\tfor e := range listE {\n\t\t\t\t\t\t\tfor f := range listF {\n\t\t\t\t\t\t\t\tif !yield(transform(a, b, c, d, e, f)) {\n\t\t\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n// CrossJoinBy7 combines every item from one list with every item from others.\n// It is the cartesian product of lists received as arguments. The transform function\n// is used to create the output values.\n// Returns an empty list if a list is empty.\n// Play: https://go.dev/play/p/2TnGK6-zs\nfunc CrossJoinBy7[A, B, C, D, E, F, G, Out any](listA iter.Seq[A], listB iter.Seq[B], listC iter.Seq[C], listD iter.Seq[D], listE iter.Seq[E], listF iter.Seq[F], listG iter.Seq[G], transform func(a A, b B, c C, d D, e E, f F, g G) Out) iter.Seq[Out] {\n\treturn func(yield func(Out) bool) {\n\t\tfor a := range listA {\n\t\t\tfor b := range listB {\n\t\t\t\tfor c := range listC {\n\t\t\t\t\tfor d := range listD {\n\t\t\t\t\t\tfor e := range listE {\n\t\t\t\t\t\t\tfor f := range listF {\n\t\t\t\t\t\t\t\tfor g := range listG {\n\t\t\t\t\t\t\t\t\tif !yield(transform(a, b, c, d, e, f, g)) {\n\t\t\t\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n// CrossJoinBy8 combines every item from one list with every item from others.\n// It is the cartesian product of lists received as arguments. The transform function\n// is used to create the output values.\n// Returns an empty list if a list is empty.\n// Play: https://go.dev/play/p/3UoHL7-zt\nfunc CrossJoinBy8[A, B, C, D, E, F, G, H, Out any](listA iter.Seq[A], listB iter.Seq[B], listC iter.Seq[C], listD iter.Seq[D], listE iter.Seq[E], listF iter.Seq[F], listG iter.Seq[G], listH iter.Seq[H], transform func(a A, b B, c C, d D, e E, f F, g G, h H) Out) iter.Seq[Out] {\n\treturn func(yield func(Out) bool) {\n\t\tfor a := range listA {\n\t\t\tfor b := range listB {\n\t\t\t\tfor c := range listC {\n\t\t\t\t\tfor d := range listD {\n\t\t\t\t\t\tfor e := range listE {\n\t\t\t\t\t\t\tfor f := range listF {\n\t\t\t\t\t\t\t\tfor g := range listG {\n\t\t\t\t\t\t\t\t\tfor h := range listH {\n\t\t\t\t\t\t\t\t\t\tif !yield(transform(a, b, c, d, e, f, g, h)) {\n\t\t\t\t\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n// CrossJoinBy9 combines every item from one list with every item from others.\n// It is the cartesian product of lists received as arguments. The transform function\n// is used to create the output values.\n// Returns an empty list if a list is empty.\n// Play: https://go.dev/play/p/4VpIM8-zu\nfunc CrossJoinBy9[A, B, C, D, E, F, G, H, I, Out any](listA iter.Seq[A], listB iter.Seq[B], listC iter.Seq[C], listD iter.Seq[D], listE iter.Seq[E], listF iter.Seq[F], listG iter.Seq[G], listH iter.Seq[H], listI iter.Seq[I], transform func(a A, b B, c C, d D, e E, f F, g G, h H, i I) Out) iter.Seq[Out] {\n\treturn func(yield func(Out) bool) {\n\t\tfor a := range listA {\n\t\t\tfor b := range listB {\n\t\t\t\tfor c := range listC {\n\t\t\t\t\tfor d := range listD {\n\t\t\t\t\t\tfor e := range listE {\n\t\t\t\t\t\t\tfor f := range listF {\n\t\t\t\t\t\t\t\tfor g := range listG {\n\t\t\t\t\t\t\t\t\tfor h := range listH {\n\t\t\t\t\t\t\t\t\t\tfor i := range listI {\n\t\t\t\t\t\t\t\t\t\t\tif !yield(transform(a, b, c, d, e, f, g, h, i)) {\n\t\t\t\t\t\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "it/tuples_example_test.go",
    "content": "//go:build go1.23\n\npackage it\n\nimport (\n\t\"fmt\"\n\t\"slices\"\n)\n\nfunc ExampleZip2() {\n\tresult := Zip2(values(\"hello\"), values(2))\n\tfmt.Printf(\"%v\", slices.Collect(result))\n\t// Output: [{hello 2}]\n}\n\nfunc ExampleZip3() {\n\tresult := Zip3(values(\"hello\"), values(2), values(true))\n\tfmt.Printf(\"%v\", slices.Collect(result))\n\t// Output: [{hello 2 true}]\n}\n\nfunc ExampleZip4() {\n\tresult := Zip4(values(\"hello\"), values(2), values(true), values(foo{bar: \"bar\"}))\n\tfmt.Printf(\"%v\", slices.Collect(result))\n\t// Output: [{hello 2 true {bar}}]\n}\n\nfunc ExampleZip5() {\n\tresult := Zip5(values(\"hello\"), values(2), values(true), values(foo{bar: \"bar\"}), values(4.2))\n\tfmt.Printf(\"%v\", slices.Collect(result))\n\t// Output: [{hello 2 true {bar} 4.2}]\n}\n\nfunc ExampleZip6() {\n\tresult := Zip6(values(\"hello\"), values(2), values(true), values(foo{bar: \"bar\"}), values(4.2), values(\"plop\"))\n\tfmt.Printf(\"%v\", slices.Collect(result))\n\t// Output: [{hello 2 true {bar} 4.2 plop}]\n}\n\nfunc ExampleZip7() {\n\tresult := Zip7(values(\"hello\"), values(2), values(true), values(foo{bar: \"bar\"}), values(4.2), values(\"plop\"), values(false))\n\tfmt.Printf(\"%v\", slices.Collect(result))\n\t// Output: [{hello 2 true {bar} 4.2 plop false}]\n}\n\nfunc ExampleZip8() {\n\tresult := Zip8(values(\"hello\"), values(2), values(true), values(foo{bar: \"bar\"}), values(4.2), values(\"plop\"), values(false), values(42))\n\tfmt.Printf(\"%v\", slices.Collect(result))\n\t// Output: [{hello 2 true {bar} 4.2 plop false 42}]\n}\n\nfunc ExampleZip9() {\n\tresult := Zip9(values(\"hello\"), values(2), values(true), values(foo{bar: \"bar\"}), values(4.2), values(\"plop\"), values(false), values(42), values(\"hello world\"))\n\tfmt.Printf(\"%v\", slices.Collect(result))\n\t// Output: [{hello 2 true {bar} 4.2 plop false 42 hello world}]\n}\n\nfunc ExampleCrossJoin2() {\n\tresult := CrossJoin2(values(\"a\", \"b\"), values(1, 2, 3, 4))\n\tfor r := range result {\n\t\tfmt.Printf(\"%v\\n\", r)\n\t}\n\t// Output:\n\t// {a 1}\n\t// {a 2}\n\t// {a 3}\n\t// {a 4}\n\t// {b 1}\n\t// {b 2}\n\t// {b 3}\n\t// {b 4}\n}\n\nfunc ExampleCrossJoin3() {\n\tresult := CrossJoin3(values(\"a\", \"b\"), values(1, 2, 3, 4), values(true, false))\n\tfor r := range result {\n\t\tfmt.Printf(\"%v\\n\", r)\n\t}\n\t// Output:\n\t// {a 1 true}\n\t// {a 1 false}\n\t// {a 2 true}\n\t// {a 2 false}\n\t// {a 3 true}\n\t// {a 3 false}\n\t// {a 4 true}\n\t// {a 4 false}\n\t// {b 1 true}\n\t// {b 1 false}\n\t// {b 2 true}\n\t// {b 2 false}\n\t// {b 3 true}\n\t// {b 3 false}\n\t// {b 4 true}\n\t// {b 4 false}\n}\n\nfunc ExampleCrossJoin4() {\n\tresult := CrossJoin4(values(\"a\", \"b\"), values(1, 2, 3, 4), values(true, false), values(foo{bar: \"bar\"}))\n\tfor r := range result {\n\t\tfmt.Printf(\"%v\\n\", r)\n\t}\n\t// Output:\n\t// {a 1 true {bar}}\n\t// {a 1 false {bar}}\n\t// {a 2 true {bar}}\n\t// {a 2 false {bar}}\n\t// {a 3 true {bar}}\n\t// {a 3 false {bar}}\n\t// {a 4 true {bar}}\n\t// {a 4 false {bar}}\n\t// {b 1 true {bar}}\n\t// {b 1 false {bar}}\n\t// {b 2 true {bar}}\n\t// {b 2 false {bar}}\n\t// {b 3 true {bar}}\n\t// {b 3 false {bar}}\n\t// {b 4 true {bar}}\n\t// {b 4 false {bar}}\n}\n\nfunc ExampleCrossJoin5() {\n\tresult := CrossJoin5(values(\"a\", \"b\"), values(1, 2, 3, 4), values(true, false), values(foo{bar: \"bar\"}), values(4.2))\n\tfor r := range result {\n\t\tfmt.Printf(\"%v\\n\", r)\n\t}\n\t// Output:\n\t// {a 1 true {bar} 4.2}\n\t// {a 1 false {bar} 4.2}\n\t// {a 2 true {bar} 4.2}\n\t// {a 2 false {bar} 4.2}\n\t// {a 3 true {bar} 4.2}\n\t// {a 3 false {bar} 4.2}\n\t// {a 4 true {bar} 4.2}\n\t// {a 4 false {bar} 4.2}\n\t// {b 1 true {bar} 4.2}\n\t// {b 1 false {bar} 4.2}\n\t// {b 2 true {bar} 4.2}\n\t// {b 2 false {bar} 4.2}\n\t// {b 3 true {bar} 4.2}\n\t// {b 3 false {bar} 4.2}\n\t// {b 4 true {bar} 4.2}\n\t// {b 4 false {bar} 4.2}\n}\n\nfunc ExampleCrossJoin6() {\n\tresult := CrossJoin6(values(\"a\", \"b\"), values(1, 2, 3, 4), values(true, false), values(foo{bar: \"bar\"}), values(4.2), values(\"plop\"))\n\tfor r := range result {\n\t\tfmt.Printf(\"%v\\n\", r)\n\t}\n\t// Output:\n\t// {a 1 true {bar} 4.2 plop}\n\t// {a 1 false {bar} 4.2 plop}\n\t// {a 2 true {bar} 4.2 plop}\n\t// {a 2 false {bar} 4.2 plop}\n\t// {a 3 true {bar} 4.2 plop}\n\t// {a 3 false {bar} 4.2 plop}\n\t// {a 4 true {bar} 4.2 plop}\n\t// {a 4 false {bar} 4.2 plop}\n\t// {b 1 true {bar} 4.2 plop}\n\t// {b 1 false {bar} 4.2 plop}\n\t// {b 2 true {bar} 4.2 plop}\n\t// {b 2 false {bar} 4.2 plop}\n\t// {b 3 true {bar} 4.2 plop}\n\t// {b 3 false {bar} 4.2 plop}\n\t// {b 4 true {bar} 4.2 plop}\n\t// {b 4 false {bar} 4.2 plop}\n}\n\nfunc ExampleCrossJoin7() {\n\tresult := CrossJoin7(values(\"a\", \"b\"), values(1, 2, 3, 4), values(true, false), values(foo{bar: \"bar\"}), values(4.2), values(\"plop\"), values(false))\n\tfor r := range result {\n\t\tfmt.Printf(\"%v\\n\", r)\n\t}\n\t// Output:\n\t// {a 1 true {bar} 4.2 plop false}\n\t// {a 1 false {bar} 4.2 plop false}\n\t// {a 2 true {bar} 4.2 plop false}\n\t// {a 2 false {bar} 4.2 plop false}\n\t// {a 3 true {bar} 4.2 plop false}\n\t// {a 3 false {bar} 4.2 plop false}\n\t// {a 4 true {bar} 4.2 plop false}\n\t// {a 4 false {bar} 4.2 plop false}\n\t// {b 1 true {bar} 4.2 plop false}\n\t// {b 1 false {bar} 4.2 plop false}\n\t// {b 2 true {bar} 4.2 plop false}\n\t// {b 2 false {bar} 4.2 plop false}\n\t// {b 3 true {bar} 4.2 plop false}\n\t// {b 3 false {bar} 4.2 plop false}\n\t// {b 4 true {bar} 4.2 plop false}\n\t// {b 4 false {bar} 4.2 plop false}\n}\n\nfunc ExampleCrossJoin8() {\n\tresult := CrossJoin8(values(\"a\", \"b\"), values(1, 2, 3, 4), values(true, false), values(foo{bar: \"bar\"}), values(4.2), values(\"plop\"), values(false), values(42))\n\tfor r := range result {\n\t\tfmt.Printf(\"%v\\n\", r)\n\t}\n\t// Output:\n\t// {a 1 true {bar} 4.2 plop false 42}\n\t// {a 1 false {bar} 4.2 plop false 42}\n\t// {a 2 true {bar} 4.2 plop false 42}\n\t// {a 2 false {bar} 4.2 plop false 42}\n\t// {a 3 true {bar} 4.2 plop false 42}\n\t// {a 3 false {bar} 4.2 plop false 42}\n\t// {a 4 true {bar} 4.2 plop false 42}\n\t// {a 4 false {bar} 4.2 plop false 42}\n\t// {b 1 true {bar} 4.2 plop false 42}\n\t// {b 1 false {bar} 4.2 plop false 42}\n\t// {b 2 true {bar} 4.2 plop false 42}\n\t// {b 2 false {bar} 4.2 plop false 42}\n\t// {b 3 true {bar} 4.2 plop false 42}\n\t// {b 3 false {bar} 4.2 plop false 42}\n\t// {b 4 true {bar} 4.2 plop false 42}\n\t// {b 4 false {bar} 4.2 plop false 42}\n}\n\nfunc ExampleCrossJoin9() {\n\tresult := CrossJoin9(values(\"a\", \"b\"), values(1, 2, 3, 4), values(true, false), values(foo{bar: \"bar\"}), values(4.2), values(\"plop\"), values(false), values(42), values(\"hello world\"))\n\tfor r := range result {\n\t\tfmt.Printf(\"%v\\n\", r)\n\t}\n\t// Output:\n\t// {a 1 true {bar} 4.2 plop false 42 hello world}\n\t// {a 1 false {bar} 4.2 plop false 42 hello world}\n\t// {a 2 true {bar} 4.2 plop false 42 hello world}\n\t// {a 2 false {bar} 4.2 plop false 42 hello world}\n\t// {a 3 true {bar} 4.2 plop false 42 hello world}\n\t// {a 3 false {bar} 4.2 plop false 42 hello world}\n\t// {a 4 true {bar} 4.2 plop false 42 hello world}\n\t// {a 4 false {bar} 4.2 plop false 42 hello world}\n\t// {b 1 true {bar} 4.2 plop false 42 hello world}\n\t// {b 1 false {bar} 4.2 plop false 42 hello world}\n\t// {b 2 true {bar} 4.2 plop false 42 hello world}\n\t// {b 2 false {bar} 4.2 plop false 42 hello world}\n\t// {b 3 true {bar} 4.2 plop false 42 hello world}\n\t// {b 3 false {bar} 4.2 plop false 42 hello world}\n\t// {b 4 true {bar} 4.2 plop false 42 hello world}\n\t// {b 4 false {bar} 4.2 plop false 42 hello world}\n}\n\nfunc ExampleCrossJoinBy2() {\n\tresult := CrossJoinBy2(values(\"a\", \"b\"), values(1, 2, 3, 4), func(a string, b int) string {\n\t\treturn fmt.Sprintf(\"%v-%v\", a, b)\n\t})\n\tfor r := range result {\n\t\tfmt.Printf(\"%v\\n\", r)\n\t}\n\t// Output:\n\t// a-1\n\t// a-2\n\t// a-3\n\t// a-4\n\t// b-1\n\t// b-2\n\t// b-3\n\t// b-4\n}\n\nfunc ExampleCrossJoinBy3() {\n\tresult := CrossJoinBy3(values(\"a\", \"b\"), values(1, 2, 3, 4), values(true, false), func(a string, b int, c bool) string {\n\t\treturn fmt.Sprintf(\"%v-%v-%v\", a, b, c)\n\t})\n\tfor r := range result {\n\t\tfmt.Printf(\"%v\\n\", r)\n\t}\n\t// Output:\n\t// a-1-true\n\t// a-1-false\n\t// a-2-true\n\t// a-2-false\n\t// a-3-true\n\t// a-3-false\n\t// a-4-true\n\t// a-4-false\n\t// b-1-true\n\t// b-1-false\n\t// b-2-true\n\t// b-2-false\n\t// b-3-true\n\t// b-3-false\n\t// b-4-true\n\t// b-4-false\n}\n\nfunc ExampleCrossJoinBy4() {\n\tresult := CrossJoinBy4(values(\"a\", \"b\"), values(1, 2, 3, 4), values(true, false), values(foo{bar: \"bar\"}), func(a string, b int, c bool, d foo) string {\n\t\treturn fmt.Sprintf(\"%v-%v-%v-%v\", a, b, c, d)\n\t})\n\tfor r := range result {\n\t\tfmt.Printf(\"%v\\n\", r)\n\t}\n\t// Output:\n\t// a-1-true-{bar}\n\t// a-1-false-{bar}\n\t// a-2-true-{bar}\n\t// a-2-false-{bar}\n\t// a-3-true-{bar}\n\t// a-3-false-{bar}\n\t// a-4-true-{bar}\n\t// a-4-false-{bar}\n\t// b-1-true-{bar}\n\t// b-1-false-{bar}\n\t// b-2-true-{bar}\n\t// b-2-false-{bar}\n\t// b-3-true-{bar}\n\t// b-3-false-{bar}\n\t// b-4-true-{bar}\n\t// b-4-false-{bar}\n}\n\nfunc ExampleCrossJoinBy5() {\n\tresult := CrossJoinBy5(values(\"a\", \"b\"), values(1, 2, 3, 4), values(true, false), values(foo{bar: \"bar\"}), values(4.2), func(a string, b int, c bool, d foo, e float64) string {\n\t\treturn fmt.Sprintf(\"%v-%v-%v-%v-%v\", a, b, c, d, e)\n\t})\n\tfor r := range result {\n\t\tfmt.Printf(\"%v\\n\", r)\n\t}\n\t// Output:\n\t// a-1-true-{bar}-4.2\n\t// a-1-false-{bar}-4.2\n\t// a-2-true-{bar}-4.2\n\t// a-2-false-{bar}-4.2\n\t// a-3-true-{bar}-4.2\n\t// a-3-false-{bar}-4.2\n\t// a-4-true-{bar}-4.2\n\t// a-4-false-{bar}-4.2\n\t// b-1-true-{bar}-4.2\n\t// b-1-false-{bar}-4.2\n\t// b-2-true-{bar}-4.2\n\t// b-2-false-{bar}-4.2\n\t// b-3-true-{bar}-4.2\n\t// b-3-false-{bar}-4.2\n\t// b-4-true-{bar}-4.2\n\t// b-4-false-{bar}-4.2\n}\n\nfunc ExampleCrossJoinBy6() {\n\tresult := CrossJoinBy6(values(\"a\", \"b\"), values(1, 2, 3, 4), values(true, false), values(foo{bar: \"bar\"}), values(4.2), values(\"plop\"), func(a string, b int, c bool, d foo, e float64, f string) string {\n\t\treturn fmt.Sprintf(\"%v-%v-%v-%v-%v-%v\", a, b, c, d, e, f)\n\t})\n\tfor r := range result {\n\t\tfmt.Printf(\"%v\\n\", r)\n\t}\n\t// Output:\n\t// a-1-true-{bar}-4.2-plop\n\t// a-1-false-{bar}-4.2-plop\n\t// a-2-true-{bar}-4.2-plop\n\t// a-2-false-{bar}-4.2-plop\n\t// a-3-true-{bar}-4.2-plop\n\t// a-3-false-{bar}-4.2-plop\n\t// a-4-true-{bar}-4.2-plop\n\t// a-4-false-{bar}-4.2-plop\n\t// b-1-true-{bar}-4.2-plop\n\t// b-1-false-{bar}-4.2-plop\n\t// b-2-true-{bar}-4.2-plop\n\t// b-2-false-{bar}-4.2-plop\n\t// b-3-true-{bar}-4.2-plop\n\t// b-3-false-{bar}-4.2-plop\n\t// b-4-true-{bar}-4.2-plop\n\t// b-4-false-{bar}-4.2-plop\n}\n\nfunc ExampleCrossJoinBy7() {\n\tresult := CrossJoinBy7(values(\"a\", \"b\"), values(1, 2, 3, 4), values(true, false), values(foo{bar: \"bar\"}), values(4.2), values(\"plop\"), values(false), func(a string, b int, c bool, d foo, e float64, f string, g bool) string {\n\t\treturn fmt.Sprintf(\"%v-%v-%v-%v-%v-%v-%v\", a, b, c, d, e, f, g)\n\t})\n\tfor r := range result {\n\t\tfmt.Printf(\"%v\\n\", r)\n\t}\n\t// Output:\n\t// a-1-true-{bar}-4.2-plop-false\n\t// a-1-false-{bar}-4.2-plop-false\n\t// a-2-true-{bar}-4.2-plop-false\n\t// a-2-false-{bar}-4.2-plop-false\n\t// a-3-true-{bar}-4.2-plop-false\n\t// a-3-false-{bar}-4.2-plop-false\n\t// a-4-true-{bar}-4.2-plop-false\n\t// a-4-false-{bar}-4.2-plop-false\n\t// b-1-true-{bar}-4.2-plop-false\n\t// b-1-false-{bar}-4.2-plop-false\n\t// b-2-true-{bar}-4.2-plop-false\n\t// b-2-false-{bar}-4.2-plop-false\n\t// b-3-true-{bar}-4.2-plop-false\n\t// b-3-false-{bar}-4.2-plop-false\n\t// b-4-true-{bar}-4.2-plop-false\n\t// b-4-false-{bar}-4.2-plop-false\n}\n\nfunc ExampleCrossJoinBy8() {\n\tresult := CrossJoinBy8(values(\"a\", \"b\"), values(1, 2, 3, 4), values(true, false), values(foo{bar: \"bar\"}), values(4.2), values(\"plop\"), values(false), values(42), func(a string, b int, c bool, d foo, e float64, f string, g bool, h int) string {\n\t\treturn fmt.Sprintf(\"%v-%v-%v-%v-%v-%v-%v-%v\", a, b, c, d, e, f, g, h)\n\t})\n\tfor r := range result {\n\t\tfmt.Printf(\"%v\\n\", r)\n\t}\n\t// Output:\n\t// a-1-true-{bar}-4.2-plop-false-42\n\t// a-1-false-{bar}-4.2-plop-false-42\n\t// a-2-true-{bar}-4.2-plop-false-42\n\t// a-2-false-{bar}-4.2-plop-false-42\n\t// a-3-true-{bar}-4.2-plop-false-42\n\t// a-3-false-{bar}-4.2-plop-false-42\n\t// a-4-true-{bar}-4.2-plop-false-42\n\t// a-4-false-{bar}-4.2-plop-false-42\n\t// b-1-true-{bar}-4.2-plop-false-42\n\t// b-1-false-{bar}-4.2-plop-false-42\n\t// b-2-true-{bar}-4.2-plop-false-42\n\t// b-2-false-{bar}-4.2-plop-false-42\n\t// b-3-true-{bar}-4.2-plop-false-42\n\t// b-3-false-{bar}-4.2-plop-false-42\n\t// b-4-true-{bar}-4.2-plop-false-42\n\t// b-4-false-{bar}-4.2-plop-false-42\n}\n\nfunc ExampleCrossJoinBy9() {\n\tresult := CrossJoinBy9(values(\"a\", \"b\"), values(1, 2, 3, 4), values(true, false), values(foo{bar: \"bar\"}), values(4.2), values(\"plop\"), values(false), values(42), values(\"hello world\"), func(a string, b int, c bool, d foo, e float64, f string, g bool, h int, i string) string {\n\t\treturn fmt.Sprintf(\"%v-%v-%v-%v-%v-%v-%v-%v-%v\", a, b, c, d, e, f, g, h, i)\n\t})\n\tfor r := range result {\n\t\tfmt.Printf(\"%v\\n\", r)\n\t}\n\t// Output:\n\t// a-1-true-{bar}-4.2-plop-false-42-hello world\n\t// a-1-false-{bar}-4.2-plop-false-42-hello world\n\t// a-2-true-{bar}-4.2-plop-false-42-hello world\n\t// a-2-false-{bar}-4.2-plop-false-42-hello world\n\t// a-3-true-{bar}-4.2-plop-false-42-hello world\n\t// a-3-false-{bar}-4.2-plop-false-42-hello world\n\t// a-4-true-{bar}-4.2-plop-false-42-hello world\n\t// a-4-false-{bar}-4.2-plop-false-42-hello world\n\t// b-1-true-{bar}-4.2-plop-false-42-hello world\n\t// b-1-false-{bar}-4.2-plop-false-42-hello world\n\t// b-2-true-{bar}-4.2-plop-false-42-hello world\n\t// b-2-false-{bar}-4.2-plop-false-42-hello world\n\t// b-3-true-{bar}-4.2-plop-false-42-hello world\n\t// b-3-false-{bar}-4.2-plop-false-42-hello world\n\t// b-4-true-{bar}-4.2-plop-false-42-hello world\n\t// b-4-false-{bar}-4.2-plop-false-42-hello world\n}\n"
  },
  {
    "path": "it/tuples_test.go",
    "content": "//go:build go1.23\n\npackage it\n\nimport (\n\t\"slices\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\n\t\"github.com/samber/lo\"\n)\n\nfunc TestZip(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tr1 := Zip2(\n\t\tvalues(\"a\", \"b\"),\n\t\tvalues(1, 2),\n\t)\n\n\tr2 := Zip3(\n\t\tvalues(\"a\", \"b\", \"c\"),\n\t\tvalues(1, 2, 3),\n\t\tvalues(4, 5, 6),\n\t)\n\n\tr3 := Zip4(\n\t\tvalues(\"a\", \"b\", \"c\", \"d\"),\n\t\tvalues(1, 2, 3, 4),\n\t\tvalues(5, 6, 7, 8),\n\t\tvalues(true, true, true, true),\n\t)\n\n\tr4 := Zip5(\n\t\tvalues(\"a\", \"b\", \"c\", \"d\", \"e\"),\n\t\tvalues(1, 2, 3, 4, 5),\n\t\tvalues(6, 7, 8, 9, 10),\n\t\tvalues(true, true, true, true, true),\n\t\tvalues[float32](0.1, 0.2, 0.3, 0.4, 0.5),\n\t)\n\n\tr5 := Zip6(\n\t\tvalues(\"a\", \"b\", \"c\", \"d\", \"e\", \"f\"),\n\t\tvalues(1, 2, 3, 4, 5, 6),\n\t\tvalues(7, 8, 9, 10, 11, 12),\n\t\tvalues(true, true, true, true, true, true),\n\t\tvalues[float32](0.1, 0.2, 0.3, 0.4, 0.5, 0.6),\n\t\tvalues(0.01, 0.02, 0.03, 0.04, 0.05, 0.06),\n\t)\n\n\tr6 := Zip7(\n\t\tvalues(\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"),\n\t\tvalues(1, 2, 3, 4, 5, 6, 7),\n\t\tvalues(8, 9, 10, 11, 12, 13, 14),\n\t\tvalues(true, true, true, true, true, true, true),\n\t\tvalues[float32](0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7),\n\t\tvalues(0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07),\n\t\tvalues[int8](1, 2, 3, 4, 5, 6, 7),\n\t)\n\n\tr7 := Zip8(\n\t\tvalues(\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\", \"h\"),\n\t\tvalues(1, 2, 3, 4, 5, 6, 7, 8),\n\t\tvalues(9, 10, 11, 12, 13, 14, 15, 16),\n\t\tvalues(true, true, true, true, true, true, true, true),\n\t\tvalues[float32](0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8),\n\t\tvalues(0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08),\n\t\tvalues[int8](1, 2, 3, 4, 5, 6, 7, 8),\n\t\tvalues[int16](1, 2, 3, 4, 5, 6, 7, 8),\n\t)\n\n\tr8 := Zip9(\n\t\tvalues(\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\", \"h\", \"i\"),\n\t\tvalues(1, 2, 3, 4, 5, 6, 7, 8, 9),\n\t\tvalues(10, 11, 12, 13, 14, 15, 16, 17, 18),\n\t\tvalues(true, true, true, true, true, true, true, true, true),\n\t\tvalues[float32](0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9),\n\t\tvalues(0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09),\n\t\tvalues[int8](1, 2, 3, 4, 5, 6, 7, 8, 9),\n\t\tvalues[int16](1, 2, 3, 4, 5, 6, 7, 8, 9),\n\t\tvalues[int32](1, 2, 3, 4, 5, 6, 7, 8, 9),\n\t)\n\n\tassertSeqSupportBreak(t, r1)\n\tassertSeqSupportBreak(t, r2)\n\tassertSeqSupportBreak(t, r3)\n\tassertSeqSupportBreak(t, r4)\n\tassertSeqSupportBreak(t, r5)\n\tassertSeqSupportBreak(t, r6)\n\tassertSeqSupportBreak(t, r7)\n\tassertSeqSupportBreak(t, r8)\n\n\tis.Equal([]lo.Tuple2[string, int]{\n\t\t{A: \"a\", B: 1},\n\t\t{A: \"b\", B: 2},\n\t}, slices.Collect(r1))\n\n\tis.Equal([]lo.Tuple3[string, int, int]{\n\t\t{A: \"a\", B: 1, C: 4},\n\t\t{A: \"b\", B: 2, C: 5},\n\t\t{A: \"c\", B: 3, C: 6},\n\t}, slices.Collect(r2))\n\n\tis.Equal([]lo.Tuple4[string, int, int, bool]{\n\t\t{A: \"a\", B: 1, C: 5, D: true},\n\t\t{A: \"b\", B: 2, C: 6, D: true},\n\t\t{A: \"c\", B: 3, C: 7, D: true},\n\t\t{A: \"d\", B: 4, C: 8, D: true},\n\t}, slices.Collect(r3))\n\n\tis.Equal([]lo.Tuple5[string, int, int, bool, float32]{\n\t\t{A: \"a\", B: 1, C: 6, D: true, E: 0.1},\n\t\t{A: \"b\", B: 2, C: 7, D: true, E: 0.2},\n\t\t{A: \"c\", B: 3, C: 8, D: true, E: 0.3},\n\t\t{A: \"d\", B: 4, C: 9, D: true, E: 0.4},\n\t\t{A: \"e\", B: 5, C: 10, D: true, E: 0.5},\n\t}, slices.Collect(r4))\n\n\tis.Equal([]lo.Tuple6[string, int, int, bool, float32, float64]{\n\t\t{A: \"a\", B: 1, C: 7, D: true, E: 0.1, F: 0.01},\n\t\t{A: \"b\", B: 2, C: 8, D: true, E: 0.2, F: 0.02},\n\t\t{A: \"c\", B: 3, C: 9, D: true, E: 0.3, F: 0.03},\n\t\t{A: \"d\", B: 4, C: 10, D: true, E: 0.4, F: 0.04},\n\t\t{A: \"e\", B: 5, C: 11, D: true, E: 0.5, F: 0.05},\n\t\t{A: \"f\", B: 6, C: 12, D: true, E: 0.6, F: 0.06},\n\t}, slices.Collect(r5))\n\n\tis.Equal([]lo.Tuple7[string, int, int, bool, float32, float64, int8]{\n\t\t{A: \"a\", B: 1, C: 8, D: true, E: 0.1, F: 0.01, G: 1},\n\t\t{A: \"b\", B: 2, C: 9, D: true, E: 0.2, F: 0.02, G: 2},\n\t\t{A: \"c\", B: 3, C: 10, D: true, E: 0.3, F: 0.03, G: 3},\n\t\t{A: \"d\", B: 4, C: 11, D: true, E: 0.4, F: 0.04, G: 4},\n\t\t{A: \"e\", B: 5, C: 12, D: true, E: 0.5, F: 0.05, G: 5},\n\t\t{A: \"f\", B: 6, C: 13, D: true, E: 0.6, F: 0.06, G: 6},\n\t\t{A: \"g\", B: 7, C: 14, D: true, E: 0.7, F: 0.07, G: 7},\n\t}, slices.Collect(r6))\n\n\tis.Equal([]lo.Tuple8[string, int, int, bool, float32, float64, int8, int16]{\n\t\t{A: \"a\", B: 1, C: 9, D: true, E: 0.1, F: 0.01, G: 1, H: 1},\n\t\t{A: \"b\", B: 2, C: 10, D: true, E: 0.2, F: 0.02, G: 2, H: 2},\n\t\t{A: \"c\", B: 3, C: 11, D: true, E: 0.3, F: 0.03, G: 3, H: 3},\n\t\t{A: \"d\", B: 4, C: 12, D: true, E: 0.4, F: 0.04, G: 4, H: 4},\n\t\t{A: \"e\", B: 5, C: 13, D: true, E: 0.5, F: 0.05, G: 5, H: 5},\n\t\t{A: \"f\", B: 6, C: 14, D: true, E: 0.6, F: 0.06, G: 6, H: 6},\n\t\t{A: \"g\", B: 7, C: 15, D: true, E: 0.7, F: 0.07, G: 7, H: 7},\n\t\t{A: \"h\", B: 8, C: 16, D: true, E: 0.8, F: 0.08, G: 8, H: 8},\n\t}, slices.Collect(r7))\n\n\tis.Equal([]lo.Tuple9[string, int, int, bool, float32, float64, int8, int16, int32]{\n\t\t{A: \"a\", B: 1, C: 10, D: true, E: 0.1, F: 0.01, G: 1, H: 1, I: 1},\n\t\t{A: \"b\", B: 2, C: 11, D: true, E: 0.2, F: 0.02, G: 2, H: 2, I: 2},\n\t\t{A: \"c\", B: 3, C: 12, D: true, E: 0.3, F: 0.03, G: 3, H: 3, I: 3},\n\t\t{A: \"d\", B: 4, C: 13, D: true, E: 0.4, F: 0.04, G: 4, H: 4, I: 4},\n\t\t{A: \"e\", B: 5, C: 14, D: true, E: 0.5, F: 0.05, G: 5, H: 5, I: 5},\n\t\t{A: \"f\", B: 6, C: 15, D: true, E: 0.6, F: 0.06, G: 6, H: 6, I: 6},\n\t\t{A: \"g\", B: 7, C: 16, D: true, E: 0.7, F: 0.07, G: 7, H: 7, I: 7},\n\t\t{A: \"h\", B: 8, C: 17, D: true, E: 0.8, F: 0.08, G: 8, H: 8, I: 8},\n\t\t{A: \"i\", B: 9, C: 18, D: true, E: 0.9, F: 0.09, G: 9, H: 9, I: 9},\n\t}, slices.Collect(r8))\n}\n\nfunc TestZipBy(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tr1 := ZipBy2(\n\t\tvalues(\"a\", \"b\"),\n\t\tvalues(1, 2),\n\t\tlo.T2[string, int],\n\t)\n\n\tr2 := ZipBy3(\n\t\tvalues(\"a\", \"b\", \"c\"),\n\t\tvalues(1, 2, 3),\n\t\tvalues(4, 5, 6),\n\t\tlo.T3[string, int, int],\n\t)\n\n\tr3 := ZipBy4(\n\t\tvalues(\"a\", \"b\", \"c\", \"d\"),\n\t\tvalues(1, 2, 3, 4),\n\t\tvalues(5, 6, 7, 8),\n\t\tvalues(true, true, true, true),\n\t\tlo.T4[string, int, int, bool],\n\t)\n\n\tr4 := ZipBy5(\n\t\tvalues(\"a\", \"b\", \"c\", \"d\", \"e\"),\n\t\tvalues(1, 2, 3, 4, 5),\n\t\tvalues(6, 7, 8, 9, 10),\n\t\tvalues(true, true, true, true, true),\n\t\tvalues[float32](0.1, 0.2, 0.3, 0.4, 0.5),\n\t\tlo.T5[string, int, int, bool, float32],\n\t)\n\n\tr5 := ZipBy6(\n\t\tvalues(\"a\", \"b\", \"c\", \"d\", \"e\", \"f\"),\n\t\tvalues(1, 2, 3, 4, 5, 6),\n\t\tvalues(7, 8, 9, 10, 11, 12),\n\t\tvalues(true, true, true, true, true, true),\n\t\tvalues[float32](0.1, 0.2, 0.3, 0.4, 0.5, 0.6),\n\t\tvalues(0.01, 0.02, 0.03, 0.04, 0.05, 0.06),\n\t\tlo.T6[string, int, int, bool, float32, float64],\n\t)\n\n\tr6 := ZipBy7(\n\t\tvalues(\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"),\n\t\tvalues(1, 2, 3, 4, 5, 6, 7),\n\t\tvalues(8, 9, 10, 11, 12, 13, 14),\n\t\tvalues(true, true, true, true, true, true, true),\n\t\tvalues[float32](0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7),\n\t\tvalues(0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07),\n\t\tvalues[int8](1, 2, 3, 4, 5, 6, 7),\n\t\tlo.T7[string, int, int, bool, float32, float64, int8],\n\t)\n\n\tr7 := ZipBy8(\n\t\tvalues(\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\", \"h\"),\n\t\tvalues(1, 2, 3, 4, 5, 6, 7, 8),\n\t\tvalues(9, 10, 11, 12, 13, 14, 15, 16),\n\t\tvalues(true, true, true, true, true, true, true, true),\n\t\tvalues[float32](0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8),\n\t\tvalues(0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08),\n\t\tvalues[int8](1, 2, 3, 4, 5, 6, 7, 8),\n\t\tvalues[int16](1, 2, 3, 4, 5, 6, 7, 8),\n\t\tlo.T8[string, int, int, bool, float32, float64, int8, int16],\n\t)\n\n\tr8 := ZipBy9(\n\t\tvalues(\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\", \"h\", \"i\"),\n\t\tvalues(1, 2, 3, 4, 5, 6, 7, 8, 9),\n\t\tvalues(10, 11, 12, 13, 14, 15, 16, 17, 18),\n\t\tvalues(true, true, true, true, true, true, true, true, true),\n\t\tvalues[float32](0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9),\n\t\tvalues(0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09),\n\t\tvalues[int8](1, 2, 3, 4, 5, 6, 7, 8, 9),\n\t\tvalues[int16](1, 2, 3, 4, 5, 6, 7, 8, 9),\n\t\tvalues[int32](1, 2, 3, 4, 5, 6, 7, 8, 9),\n\t\tlo.T9[string, int, int, bool, float32, float64, int8, int16, int32],\n\t)\n\n\tassertSeqSupportBreak(t, r1)\n\tassertSeqSupportBreak(t, r2)\n\tassertSeqSupportBreak(t, r3)\n\tassertSeqSupportBreak(t, r4)\n\tassertSeqSupportBreak(t, r5)\n\tassertSeqSupportBreak(t, r6)\n\tassertSeqSupportBreak(t, r7)\n\tassertSeqSupportBreak(t, r8)\n\n\tis.Equal([]lo.Tuple2[string, int]{\n\t\t{A: \"a\", B: 1},\n\t\t{A: \"b\", B: 2},\n\t}, slices.Collect(r1))\n\n\tis.Equal([]lo.Tuple3[string, int, int]{\n\t\t{A: \"a\", B: 1, C: 4},\n\t\t{A: \"b\", B: 2, C: 5},\n\t\t{A: \"c\", B: 3, C: 6},\n\t}, slices.Collect(r2))\n\n\tis.Equal([]lo.Tuple4[string, int, int, bool]{\n\t\t{A: \"a\", B: 1, C: 5, D: true},\n\t\t{A: \"b\", B: 2, C: 6, D: true},\n\t\t{A: \"c\", B: 3, C: 7, D: true},\n\t\t{A: \"d\", B: 4, C: 8, D: true},\n\t}, slices.Collect(r3))\n\n\tis.Equal([]lo.Tuple5[string, int, int, bool, float32]{\n\t\t{A: \"a\", B: 1, C: 6, D: true, E: 0.1},\n\t\t{A: \"b\", B: 2, C: 7, D: true, E: 0.2},\n\t\t{A: \"c\", B: 3, C: 8, D: true, E: 0.3},\n\t\t{A: \"d\", B: 4, C: 9, D: true, E: 0.4},\n\t\t{A: \"e\", B: 5, C: 10, D: true, E: 0.5},\n\t}, slices.Collect(r4))\n\n\tis.Equal([]lo.Tuple6[string, int, int, bool, float32, float64]{\n\t\t{A: \"a\", B: 1, C: 7, D: true, E: 0.1, F: 0.01},\n\t\t{A: \"b\", B: 2, C: 8, D: true, E: 0.2, F: 0.02},\n\t\t{A: \"c\", B: 3, C: 9, D: true, E: 0.3, F: 0.03},\n\t\t{A: \"d\", B: 4, C: 10, D: true, E: 0.4, F: 0.04},\n\t\t{A: \"e\", B: 5, C: 11, D: true, E: 0.5, F: 0.05},\n\t\t{A: \"f\", B: 6, C: 12, D: true, E: 0.6, F: 0.06},\n\t}, slices.Collect(r5))\n\n\tis.Equal([]lo.Tuple7[string, int, int, bool, float32, float64, int8]{\n\t\t{A: \"a\", B: 1, C: 8, D: true, E: 0.1, F: 0.01, G: 1},\n\t\t{A: \"b\", B: 2, C: 9, D: true, E: 0.2, F: 0.02, G: 2},\n\t\t{A: \"c\", B: 3, C: 10, D: true, E: 0.3, F: 0.03, G: 3},\n\t\t{A: \"d\", B: 4, C: 11, D: true, E: 0.4, F: 0.04, G: 4},\n\t\t{A: \"e\", B: 5, C: 12, D: true, E: 0.5, F: 0.05, G: 5},\n\t\t{A: \"f\", B: 6, C: 13, D: true, E: 0.6, F: 0.06, G: 6},\n\t\t{A: \"g\", B: 7, C: 14, D: true, E: 0.7, F: 0.07, G: 7},\n\t}, slices.Collect(r6))\n\n\tis.Equal([]lo.Tuple8[string, int, int, bool, float32, float64, int8, int16]{\n\t\t{A: \"a\", B: 1, C: 9, D: true, E: 0.1, F: 0.01, G: 1, H: 1},\n\t\t{A: \"b\", B: 2, C: 10, D: true, E: 0.2, F: 0.02, G: 2, H: 2},\n\t\t{A: \"c\", B: 3, C: 11, D: true, E: 0.3, F: 0.03, G: 3, H: 3},\n\t\t{A: \"d\", B: 4, C: 12, D: true, E: 0.4, F: 0.04, G: 4, H: 4},\n\t\t{A: \"e\", B: 5, C: 13, D: true, E: 0.5, F: 0.05, G: 5, H: 5},\n\t\t{A: \"f\", B: 6, C: 14, D: true, E: 0.6, F: 0.06, G: 6, H: 6},\n\t\t{A: \"g\", B: 7, C: 15, D: true, E: 0.7, F: 0.07, G: 7, H: 7},\n\t\t{A: \"h\", B: 8, C: 16, D: true, E: 0.8, F: 0.08, G: 8, H: 8},\n\t}, slices.Collect(r7))\n\n\tis.Equal([]lo.Tuple9[string, int, int, bool, float32, float64, int8, int16, int32]{\n\t\t{A: \"a\", B: 1, C: 10, D: true, E: 0.1, F: 0.01, G: 1, H: 1, I: 1},\n\t\t{A: \"b\", B: 2, C: 11, D: true, E: 0.2, F: 0.02, G: 2, H: 2, I: 2},\n\t\t{A: \"c\", B: 3, C: 12, D: true, E: 0.3, F: 0.03, G: 3, H: 3, I: 3},\n\t\t{A: \"d\", B: 4, C: 13, D: true, E: 0.4, F: 0.04, G: 4, H: 4, I: 4},\n\t\t{A: \"e\", B: 5, C: 14, D: true, E: 0.5, F: 0.05, G: 5, H: 5, I: 5},\n\t\t{A: \"f\", B: 6, C: 15, D: true, E: 0.6, F: 0.06, G: 6, H: 6, I: 6},\n\t\t{A: \"g\", B: 7, C: 16, D: true, E: 0.7, F: 0.07, G: 7, H: 7, I: 7},\n\t\t{A: \"h\", B: 8, C: 17, D: true, E: 0.8, F: 0.08, G: 8, H: 8, I: 8},\n\t\t{A: \"i\", B: 9, C: 18, D: true, E: 0.9, F: 0.09, G: 9, H: 9, I: 9},\n\t}, slices.Collect(r8))\n}\n\nfunc TestCrossJoin(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tlistOne := values(\"a\", \"b\", \"c\")\n\tlistTwo := values(1, 2, 3)\n\temptyList := values[any]()\n\tmixedList := values[any](9.6, 4, \"foobar\")\n\n\tresults1 := CrossJoin2(emptyList, listTwo)\n\tis.Empty(slices.Collect(results1))\n\n\tresults2 := CrossJoin2(listOne, emptyList)\n\tis.Empty(slices.Collect(results2))\n\n\tresults3 := CrossJoin2(emptyList, emptyList)\n\tis.Empty(slices.Collect(results3))\n\n\tresults4 := CrossJoin2(values(\"a\"), listTwo)\n\tis.Equal([]lo.Tuple2[string, int]{lo.T2(\"a\", 1), lo.T2(\"a\", 2), lo.T2(\"a\", 3)}, slices.Collect(results4))\n\n\tresults5 := CrossJoin2(listOne, values(1))\n\tis.Equal([]lo.Tuple2[string, int]{lo.T2(\"a\", 1), lo.T2(\"b\", 1), lo.T2(\"c\", 1)}, slices.Collect(results5))\n\n\tresults6 := CrossJoin2(listOne, listTwo)\n\tis.Equal([]lo.Tuple2[string, int]{lo.T2(\"a\", 1), lo.T2(\"a\", 2), lo.T2(\"a\", 3), lo.T2(\"b\", 1), lo.T2(\"b\", 2), lo.T2(\"b\", 3), lo.T2(\"c\", 1), lo.T2(\"c\", 2), lo.T2(\"c\", 3)}, slices.Collect(results6))\n\n\tresults7 := CrossJoin2(listOne, mixedList)\n\tis.Equal([]lo.Tuple2[string, any]{lo.T2[string, any](\"a\", 9.6), lo.T2[string, any](\"a\", 4), lo.T2[string, any](\"a\", \"foobar\"), lo.T2[string, any](\"b\", 9.6), lo.T2[string, any](\"b\", 4), lo.T2[string, any](\"b\", \"foobar\"), lo.T2[string, any](\"c\", 9.6), lo.T2[string, any](\"c\", 4), lo.T2[string, any](\"c\", \"foobar\")}, slices.Collect(results7))\n}\n\nfunc TestCrossJoinBy(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tlistOne := values(\"a\", \"b\", \"c\")\n\tlistTwo := values(1, 2, 3)\n\temptyList := values[any]()\n\tmixedList := values[any](9.6, 4, \"foobar\")\n\n\tresults1 := CrossJoinBy2(emptyList, listTwo, lo.T2[any, int])\n\tis.Empty(slices.Collect(results1))\n\n\tresults2 := CrossJoinBy2(listOne, emptyList, lo.T2[string, any])\n\tis.Empty(slices.Collect(results2))\n\n\tresults3 := CrossJoinBy2(emptyList, emptyList, lo.T2[any, any])\n\tis.Empty(slices.Collect(results3))\n\n\tresults4 := CrossJoinBy2(values(\"a\"), listTwo, lo.T2[string, int])\n\tis.Equal([]lo.Tuple2[string, int]{lo.T2(\"a\", 1), lo.T2(\"a\", 2), lo.T2(\"a\", 3)}, slices.Collect(results4))\n\n\tresults5 := CrossJoinBy2(listOne, values(1), lo.T2[string, int])\n\tis.Equal([]lo.Tuple2[string, int]{lo.T2(\"a\", 1), lo.T2(\"b\", 1), lo.T2(\"c\", 1)}, slices.Collect(results5))\n\n\tresults6 := CrossJoinBy2(listOne, listTwo, lo.T2[string, int])\n\tis.Equal([]lo.Tuple2[string, int]{lo.T2(\"a\", 1), lo.T2(\"a\", 2), lo.T2(\"a\", 3), lo.T2(\"b\", 1), lo.T2(\"b\", 2), lo.T2(\"b\", 3), lo.T2(\"c\", 1), lo.T2(\"c\", 2), lo.T2(\"c\", 3)}, slices.Collect(results6))\n\n\tresults7 := CrossJoinBy2(listOne, mixedList, lo.T2[string, any])\n\tis.Equal([]lo.Tuple2[string, any]{lo.T2[string, any](\"a\", 9.6), lo.T2[string, any](\"a\", 4), lo.T2[string, any](\"a\", \"foobar\"), lo.T2[string, any](\"b\", 9.6), lo.T2[string, any](\"b\", 4), lo.T2[string, any](\"b\", \"foobar\"), lo.T2[string, any](\"c\", 9.6), lo.T2[string, any](\"c\", 4), lo.T2[string, any](\"c\", \"foobar\")}, slices.Collect(results7))\n}\n"
  },
  {
    "path": "it/type_manipulation.go",
    "content": "//go:build go1.23\n\npackage it\n\nimport (\n\t\"iter\"\n\n\t\"github.com/samber/lo\"\n)\n\n// ToSeqPtr returns a sequence of pointers to each value.\n// Play: https://go.dev/play/p/70BcKpDcOKm\nfunc ToSeqPtr[T any](collection iter.Seq[T]) iter.Seq[*T] {\n\treturn Map(collection, lo.ToPtr)\n}\n\n// FromSeqPtr returns a sequence with the pointer values.\n// Returns a zero value in case of a nil pointer element.\n// Play: https://go.dev/play/p/_eO6scpLcBF\nfunc FromSeqPtr[T any](collection iter.Seq[*T]) iter.Seq[T] {\n\treturn Map(collection, lo.FromPtr)\n}\n\n// FromSeqPtrOr returns a sequence with the pointer values or the fallback value.\n// Play: https://go.dev/play/p/LJ17S4pvOjo\nfunc FromSeqPtrOr[T any](collection iter.Seq[*T], fallback T) iter.Seq[T] {\n\treturn Map(collection, func(x *T) T { return lo.FromPtrOr(x, fallback) })\n}\n\n// ToAnySeq returns a sequence with all elements mapped to `any` type.\n// Play: https://go.dev/play/p/ktE4IMXDMxv\nfunc ToAnySeq[T any](collection iter.Seq[T]) iter.Seq[any] {\n\treturn Map(collection, func(x T) any { return x })\n}\n\n// FromAnySeq returns a sequence with all elements mapped to a type.\n// Panics on type conversion failure.\n// Play: https://go.dev/play/p/wnOma1j5Uzu\nfunc FromAnySeq[T any](collection iter.Seq[any]) iter.Seq[T] {\n\treturn Map(collection, func(item any) T {\n\t\tif t, ok := item.(T); ok {\n\t\t\treturn t\n\t\t}\n\t\tpanic(\"it.FromAnySeq: type conversion failed\")\n\t})\n}\n\n// Empty returns an empty sequence.\n// Play: https://go.dev/play/p/Y9yplM3vGFe\nfunc Empty[T any]() iter.Seq[T] {\n\treturn func(yield func(T) bool) {}\n}\n\n// IsEmpty returns true if the sequence is empty.\n// Will iterate at most once.\n// Play: https://go.dev/play/p/krZ-laaVi2C\nfunc IsEmpty[T any](collection iter.Seq[T]) bool {\n\tfor range collection {\n\t\treturn false\n\t}\n\treturn true\n}\n\n// IsNotEmpty returns true if the sequence is not empty.\n// Will iterate at most once.\n// Play: https://go.dev/play/p/jMAjbDvrdPu\nfunc IsNotEmpty[T any](collection iter.Seq[T]) bool {\n\treturn !IsEmpty(collection)\n}\n\n// CoalesceSeq returns the first non-empty sequence.\n// Will iterate through each sub-sequence at most once.\n// Play: https://go.dev/play/p/wep4z2KJLCO\nfunc CoalesceSeq[T any](v ...iter.Seq[T]) (iter.Seq[T], bool) {\n\tfor i := range v {\n\t\tfor range v[i] {\n\t\t\treturn v[i], true\n\t\t}\n\t}\n\treturn Empty[T](), false\n}\n\n// CoalesceSeqOrEmpty returns the first non-empty sequence.\n// Will iterate through each sub-sequence at most once.\n// Play: https://go.dev/play/p/3KZPAFRQr8B\nfunc CoalesceSeqOrEmpty[T any](v ...iter.Seq[T]) iter.Seq[T] {\n\tresult, _ := CoalesceSeq(v...)\n\treturn result\n}\n"
  },
  {
    "path": "it/type_manipulation_test.go",
    "content": "//go:build go1.23\n\npackage it\n\nimport (\n\t\"slices\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestToSeqPtr(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tstr1 := \"foo\"\n\tstr2 := \"bar\"\n\tresult1 := ToSeqPtr(values(str1, str2))\n\n\tis.Equal([]*string{&str1, &str2}, slices.Collect(result1))\n}\n\nfunc TestFromSeqPtr(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tstr1 := \"foo\"\n\tstr2 := \"bar\"\n\tresult1 := FromSeqPtr(values(&str1, &str2, nil))\n\n\tis.Equal([]string{str1, str2, \"\"}, slices.Collect(result1))\n}\n\nfunc TestFromSeqPtrOr(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tstr1 := \"foo\"\n\tstr2 := \"bar\"\n\tresult1 := FromSeqPtrOr(values(&str1, &str2, nil), \"fallback\")\n\n\tis.Equal([]string{str1, str2, \"fallback\"}, slices.Collect(result1))\n}\n\nfunc TestToAnySeq(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tin1 := values(0, 1, 2, 3)\n\tin2 := values[int]()\n\tout1 := ToAnySeq(in1)\n\tout2 := ToAnySeq(in2)\n\n\tis.Equal([]any{0, 1, 2, 3}, slices.Collect(out1))\n\tis.Empty(slices.Collect(out2))\n}\n\nfunc TestFromAnySeq(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tout1 := FromAnySeq[string](values[any](\"foobar\", 42))\n\tout2 := FromAnySeq[string](values[any](\"foobar\", \"42\"))\n\n\tis.PanicsWithValue(\"it.FromAnySeq: type conversion failed\", func() { _ = slices.Collect(out1) })\n\tis.Equal([]string{\"foobar\", \"42\"}, slices.Collect(out2))\n}\n\nfunc TestEmpty(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tis.Empty(slices.Collect(Empty[string]()))\n}\n\nfunc TestIsEmpty(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tis.True(IsEmpty(values[string]()))\n\tis.False(IsEmpty(values(\"foo\")))\n}\n\nfunc TestIsNotEmpty(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tis.False(IsNotEmpty(values[string]()))\n\tis.True(IsNotEmpty(values(\"foo\")))\n}\n\nfunc TestCoalesceSeq(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tseq0 := values[int]()\n\tseq1 := values(1)\n\tseq2 := values(1, 2)\n\n\tresult1, ok1 := CoalesceSeq[int]()\n\tresult4, ok4 := CoalesceSeq(seq0)\n\tresult6, ok6 := CoalesceSeq(seq2)\n\tresult7, ok7 := CoalesceSeq(seq1)\n\tresult8, ok8 := CoalesceSeq(seq1, seq2)\n\tresult9, ok9 := CoalesceSeq(seq2, seq1)\n\tresult10, ok10 := CoalesceSeq(seq0, seq1, seq2)\n\n\tis.NotNil(result1)\n\tis.Empty(slices.Collect(result1))\n\tis.False(ok1)\n\n\tis.NotNil(result4)\n\tis.Empty(slices.Collect(result4))\n\tis.False(ok4)\n\n\tis.NotNil(result6)\n\tis.Equal(slices.Collect(seq2), slices.Collect(result6))\n\tis.True(ok6)\n\n\tis.NotNil(result7)\n\tis.Equal(slices.Collect(seq1), slices.Collect(result7))\n\tis.True(ok7)\n\n\tis.NotNil(result8)\n\tis.Equal(slices.Collect(seq1), slices.Collect(result8))\n\tis.True(ok8)\n\n\tis.NotNil(result9)\n\tis.Equal(slices.Collect(seq2), slices.Collect(result9))\n\tis.True(ok9)\n\n\tis.NotNil(result10)\n\tis.Equal(slices.Collect(seq1), slices.Collect(result10))\n\tis.True(ok10)\n}\n\nfunc TestCoalesceSeqOrEmpty(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tseq0 := values[int]()\n\tseq1 := values(1)\n\tseq2 := values(1, 2)\n\n\tresult1 := CoalesceSeqOrEmpty[int]()\n\tresult4 := CoalesceSeqOrEmpty(seq0)\n\tresult6 := CoalesceSeqOrEmpty(seq2)\n\tresult7 := CoalesceSeqOrEmpty(seq1)\n\tresult8 := CoalesceSeqOrEmpty(seq1, seq2)\n\tresult9 := CoalesceSeqOrEmpty(seq2, seq1)\n\tresult10 := CoalesceSeqOrEmpty(seq0, seq1, seq2)\n\n\tis.NotNil(result1)\n\tis.Empty(slices.Collect(result1))\n\tis.NotNil(result4)\n\tis.Empty(slices.Collect(result4))\n\tis.NotNil(result6)\n\tis.Equal(slices.Collect(seq2), slices.Collect(result6))\n\tis.NotNil(result7)\n\tis.Equal(slices.Collect(seq1), slices.Collect(result7))\n\tis.NotNil(result8)\n\tis.Equal(slices.Collect(seq1), slices.Collect(result8))\n\tis.NotNil(result9)\n\tis.Equal(slices.Collect(seq2), slices.Collect(result9))\n\tis.NotNil(result10)\n\tis.Equal(slices.Collect(seq1), slices.Collect(result10))\n}\n"
  },
  {
    "path": "lo_example_test.go",
    "content": "package lo\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"math\"\n\t\"sort\"\n\t\"strconv\"\n\t\"strings\"\n\t\"time\"\n)\n\nfunc ExampleTernary() {\n\tresult := Ternary(true, \"a\", \"b\")\n\n\tfmt.Printf(\"%v\", result)\n\t// Output: a\n}\n\nfunc ExampleTernaryF() {\n\tresult := TernaryF(true, func() string { return \"a\" }, func() string { return \"b\" })\n\n\tfmt.Printf(\"%v\", result)\n\t// Output: a\n}\n\nfunc ExampleIf() {\n\tresult1 := If(true, 1).\n\t\tElseIf(false, 2).\n\t\tElse(3)\n\n\tresult2 := If(false, 1).\n\t\tElseIf(true, 2).\n\t\tElse(3)\n\n\tresult3 := If(false, 1).\n\t\tElseIf(false, 2).\n\t\tElse(3)\n\n\tresult4 := IfF(true, func() int { return 1 }).\n\t\tElseIfF(false, func() int { return 2 }).\n\t\tElseF(func() int { return 3 })\n\n\tresult5 := IfF(false, func() int { return 1 }).\n\t\tElseIfF(true, func() int { return 2 }).\n\t\tElseF(func() int { return 3 })\n\n\tresult6 := IfF(false, func() int { return 1 }).\n\t\tElseIfF(false, func() int { return 2 }).\n\t\tElseF(func() int { return 3 })\n\n\tfmt.Printf(\"%v\\n\", result1)\n\tfmt.Printf(\"%v\\n\", result2)\n\tfmt.Printf(\"%v\\n\", result3)\n\tfmt.Printf(\"%v\\n\", result4)\n\tfmt.Printf(\"%v\\n\", result5)\n\tfmt.Printf(\"%v\\n\", result6)\n\t// Output:\n\t// 1\n\t// 2\n\t// 3\n\t// 1\n\t// 2\n\t// 3\n}\n\nfunc ExampleIfF() {\n\tresult1 := If(true, 1).\n\t\tElseIf(false, 2).\n\t\tElse(3)\n\n\tresult2 := If(false, 1).\n\t\tElseIf(true, 2).\n\t\tElse(3)\n\n\tresult3 := If(false, 1).\n\t\tElseIf(false, 2).\n\t\tElse(3)\n\n\tresult4 := IfF(true, func() int { return 1 }).\n\t\tElseIfF(false, func() int { return 2 }).\n\t\tElseF(func() int { return 3 })\n\n\tresult5 := IfF(false, func() int { return 1 }).\n\t\tElseIfF(true, func() int { return 2 }).\n\t\tElseF(func() int { return 3 })\n\n\tresult6 := IfF(false, func() int { return 1 }).\n\t\tElseIfF(false, func() int { return 2 }).\n\t\tElseF(func() int { return 3 })\n\n\tfmt.Printf(\"%v\\n\", result1)\n\tfmt.Printf(\"%v\\n\", result2)\n\tfmt.Printf(\"%v\\n\", result3)\n\tfmt.Printf(\"%v\\n\", result4)\n\tfmt.Printf(\"%v\\n\", result5)\n\tfmt.Printf(\"%v\\n\", result6)\n\t// Output:\n\t// 1\n\t// 2\n\t// 3\n\t// 1\n\t// 2\n\t// 3\n}\n\nfunc Example_ifElse_ElseIf() {\n\tresult1 := If(true, 1).\n\t\tElseIf(false, 2).\n\t\tElse(3)\n\n\tresult2 := If(false, 1).\n\t\tElseIf(true, 2).\n\t\tElse(3)\n\n\tresult3 := If(false, 1).\n\t\tElseIf(false, 2).\n\t\tElse(3)\n\n\tresult4 := IfF(true, func() int { return 1 }).\n\t\tElseIfF(false, func() int { return 2 }).\n\t\tElseF(func() int { return 3 })\n\n\tresult5 := IfF(false, func() int { return 1 }).\n\t\tElseIfF(true, func() int { return 2 }).\n\t\tElseF(func() int { return 3 })\n\n\tresult6 := IfF(false, func() int { return 1 }).\n\t\tElseIfF(false, func() int { return 2 }).\n\t\tElseF(func() int { return 3 })\n\n\tfmt.Printf(\"%v\\n\", result1)\n\tfmt.Printf(\"%v\\n\", result2)\n\tfmt.Printf(\"%v\\n\", result3)\n\tfmt.Printf(\"%v\\n\", result4)\n\tfmt.Printf(\"%v\\n\", result5)\n\tfmt.Printf(\"%v\\n\", result6)\n\t// Output:\n\t// 1\n\t// 2\n\t// 3\n\t// 1\n\t// 2\n\t// 3\n}\n\nfunc Example_ifElse_ElseIfF() {\n\tresult1 := If(true, 1).\n\t\tElseIf(false, 2).\n\t\tElse(3)\n\n\tresult2 := If(false, 1).\n\t\tElseIf(true, 2).\n\t\tElse(3)\n\n\tresult3 := If(false, 1).\n\t\tElseIf(false, 2).\n\t\tElse(3)\n\n\tresult4 := IfF(true, func() int { return 1 }).\n\t\tElseIfF(false, func() int { return 2 }).\n\t\tElseF(func() int { return 3 })\n\n\tresult5 := IfF(false, func() int { return 1 }).\n\t\tElseIfF(true, func() int { return 2 }).\n\t\tElseF(func() int { return 3 })\n\n\tresult6 := IfF(false, func() int { return 1 }).\n\t\tElseIfF(false, func() int { return 2 }).\n\t\tElseF(func() int { return 3 })\n\n\tfmt.Printf(\"%v\\n\", result1)\n\tfmt.Printf(\"%v\\n\", result2)\n\tfmt.Printf(\"%v\\n\", result3)\n\tfmt.Printf(\"%v\\n\", result4)\n\tfmt.Printf(\"%v\\n\", result5)\n\tfmt.Printf(\"%v\\n\", result6)\n\t// Output:\n\t// 1\n\t// 2\n\t// 3\n\t// 1\n\t// 2\n\t// 3\n}\n\nfunc Example_ifElse_Else() {\n\tresult1 := If(true, 1).\n\t\tElseIf(false, 2).\n\t\tElse(3)\n\n\tresult2 := If(false, 1).\n\t\tElseIf(true, 2).\n\t\tElse(3)\n\n\tresult3 := If(false, 1).\n\t\tElseIf(false, 2).\n\t\tElse(3)\n\n\tresult4 := IfF(true, func() int { return 1 }).\n\t\tElseIfF(false, func() int { return 2 }).\n\t\tElseF(func() int { return 3 })\n\n\tresult5 := IfF(false, func() int { return 1 }).\n\t\tElseIfF(true, func() int { return 2 }).\n\t\tElseF(func() int { return 3 })\n\n\tresult6 := IfF(false, func() int { return 1 }).\n\t\tElseIfF(false, func() int { return 2 }).\n\t\tElseF(func() int { return 3 })\n\n\tfmt.Printf(\"%v\\n\", result1)\n\tfmt.Printf(\"%v\\n\", result2)\n\tfmt.Printf(\"%v\\n\", result3)\n\tfmt.Printf(\"%v\\n\", result4)\n\tfmt.Printf(\"%v\\n\", result5)\n\tfmt.Printf(\"%v\\n\", result6)\n\t// Output:\n\t// 1\n\t// 2\n\t// 3\n\t// 1\n\t// 2\n\t// 3\n}\n\nfunc Example_ifElse_ElseF() {\n\tresult1 := If(true, 1).\n\t\tElseIf(false, 2).\n\t\tElse(3)\n\n\tresult2 := If(false, 1).\n\t\tElseIf(true, 2).\n\t\tElse(3)\n\n\tresult3 := If(false, 1).\n\t\tElseIf(false, 2).\n\t\tElse(3)\n\n\tresult4 := IfF(true, func() int { return 1 }).\n\t\tElseIfF(false, func() int { return 2 }).\n\t\tElseF(func() int { return 3 })\n\n\tresult5 := IfF(false, func() int { return 1 }).\n\t\tElseIfF(true, func() int { return 2 }).\n\t\tElseF(func() int { return 3 })\n\n\tresult6 := IfF(false, func() int { return 1 }).\n\t\tElseIfF(false, func() int { return 2 }).\n\t\tElseF(func() int { return 3 })\n\n\tfmt.Printf(\"%v\\n\", result1)\n\tfmt.Printf(\"%v\\n\", result2)\n\tfmt.Printf(\"%v\\n\", result3)\n\tfmt.Printf(\"%v\\n\", result4)\n\tfmt.Printf(\"%v\\n\", result5)\n\tfmt.Printf(\"%v\\n\", result6)\n\t// Output:\n\t// 1\n\t// 2\n\t// 3\n\t// 1\n\t// 2\n\t// 3\n}\n\nfunc ExampleSwitch() {\n\tresult1 := Switch[int, string](1).\n\t\tCase(1, \"1\").\n\t\tCase(2, \"2\").\n\t\tDefault(\"3\")\n\n\tresult2 := Switch[int, string](2).\n\t\tCase(1, \"1\").\n\t\tCase(2, \"2\").\n\t\tDefault(\"3\")\n\n\tresult3 := Switch[int, string](42).\n\t\tCase(1, \"1\").\n\t\tCase(2, \"2\").\n\t\tDefault(\"3\")\n\n\tresult4 := Switch[int, string](1).\n\t\tCaseF(1, func() string { return \"1\" }).\n\t\tCaseF(2, func() string { return \"2\" }).\n\t\tDefaultF(func() string { return \"3\" })\n\n\tresult5 := Switch[int, string](2).\n\t\tCaseF(1, func() string { return \"1\" }).\n\t\tCaseF(2, func() string { return \"2\" }).\n\t\tDefaultF(func() string { return \"3\" })\n\n\tresult6 := Switch[int, string](42).\n\t\tCaseF(1, func() string { return \"1\" }).\n\t\tCaseF(2, func() string { return \"2\" }).\n\t\tDefaultF(func() string { return \"3\" })\n\n\tfmt.Printf(\"%v\\n\", result1)\n\tfmt.Printf(\"%v\\n\", result2)\n\tfmt.Printf(\"%v\\n\", result3)\n\tfmt.Printf(\"%v\\n\", result4)\n\tfmt.Printf(\"%v\\n\", result5)\n\tfmt.Printf(\"%v\\n\", result6)\n\t// Output:\n\t// 1\n\t// 2\n\t// 3\n\t// 1\n\t// 2\n\t// 3\n}\n\nfunc Example_switchCase_Case() {\n\tresult1 := Switch[int, string](1).\n\t\tCase(1, \"1\").\n\t\tCase(2, \"2\").\n\t\tDefault(\"3\")\n\n\tresult2 := Switch[int, string](2).\n\t\tCase(1, \"1\").\n\t\tCase(2, \"2\").\n\t\tDefault(\"3\")\n\n\tresult3 := Switch[int, string](42).\n\t\tCase(1, \"1\").\n\t\tCase(2, \"2\").\n\t\tDefault(\"3\")\n\n\tresult4 := Switch[int, string](1).\n\t\tCaseF(1, func() string { return \"1\" }).\n\t\tCaseF(2, func() string { return \"2\" }).\n\t\tDefaultF(func() string { return \"3\" })\n\n\tresult5 := Switch[int, string](2).\n\t\tCaseF(1, func() string { return \"1\" }).\n\t\tCaseF(2, func() string { return \"2\" }).\n\t\tDefaultF(func() string { return \"3\" })\n\n\tresult6 := Switch[int, string](42).\n\t\tCaseF(1, func() string { return \"1\" }).\n\t\tCaseF(2, func() string { return \"2\" }).\n\t\tDefaultF(func() string { return \"3\" })\n\n\tfmt.Printf(\"%v\\n\", result1)\n\tfmt.Printf(\"%v\\n\", result2)\n\tfmt.Printf(\"%v\\n\", result3)\n\tfmt.Printf(\"%v\\n\", result4)\n\tfmt.Printf(\"%v\\n\", result5)\n\tfmt.Printf(\"%v\\n\", result6)\n\t// Output:\n\t// 1\n\t// 2\n\t// 3\n\t// 1\n\t// 2\n\t// 3\n}\n\nfunc Example_switchCase_CaseF() {\n\tresult1 := Switch[int, string](1).\n\t\tCase(1, \"1\").\n\t\tCase(2, \"2\").\n\t\tDefault(\"3\")\n\n\tresult2 := Switch[int, string](2).\n\t\tCase(1, \"1\").\n\t\tCase(2, \"2\").\n\t\tDefault(\"3\")\n\n\tresult3 := Switch[int, string](42).\n\t\tCase(1, \"1\").\n\t\tCase(2, \"2\").\n\t\tDefault(\"3\")\n\n\tresult4 := Switch[int, string](1).\n\t\tCaseF(1, func() string { return \"1\" }).\n\t\tCaseF(2, func() string { return \"2\" }).\n\t\tDefaultF(func() string { return \"3\" })\n\n\tresult5 := Switch[int, string](2).\n\t\tCaseF(1, func() string { return \"1\" }).\n\t\tCaseF(2, func() string { return \"2\" }).\n\t\tDefaultF(func() string { return \"3\" })\n\n\tresult6 := Switch[int, string](42).\n\t\tCaseF(1, func() string { return \"1\" }).\n\t\tCaseF(2, func() string { return \"2\" }).\n\t\tDefaultF(func() string { return \"3\" })\n\n\tfmt.Printf(\"%v\\n\", result1)\n\tfmt.Printf(\"%v\\n\", result2)\n\tfmt.Printf(\"%v\\n\", result3)\n\tfmt.Printf(\"%v\\n\", result4)\n\tfmt.Printf(\"%v\\n\", result5)\n\tfmt.Printf(\"%v\\n\", result6)\n\t// Output:\n\t// 1\n\t// 2\n\t// 3\n\t// 1\n\t// 2\n\t// 3\n}\n\nfunc Example_switchCase_Default() {\n\tresult1 := Switch[int, string](1).\n\t\tCase(1, \"1\").\n\t\tCase(2, \"2\").\n\t\tDefault(\"3\")\n\n\tresult2 := Switch[int, string](2).\n\t\tCase(1, \"1\").\n\t\tCase(2, \"2\").\n\t\tDefault(\"3\")\n\n\tresult3 := Switch[int, string](42).\n\t\tCase(1, \"1\").\n\t\tCase(2, \"2\").\n\t\tDefault(\"3\")\n\n\tresult4 := Switch[int, string](1).\n\t\tCaseF(1, func() string { return \"1\" }).\n\t\tCaseF(2, func() string { return \"2\" }).\n\t\tDefaultF(func() string { return \"3\" })\n\n\tresult5 := Switch[int, string](2).\n\t\tCaseF(1, func() string { return \"1\" }).\n\t\tCaseF(2, func() string { return \"2\" }).\n\t\tDefaultF(func() string { return \"3\" })\n\n\tresult6 := Switch[int, string](42).\n\t\tCaseF(1, func() string { return \"1\" }).\n\t\tCaseF(2, func() string { return \"2\" }).\n\t\tDefaultF(func() string { return \"3\" })\n\n\tfmt.Printf(\"%v\\n\", result1)\n\tfmt.Printf(\"%v\\n\", result2)\n\tfmt.Printf(\"%v\\n\", result3)\n\tfmt.Printf(\"%v\\n\", result4)\n\tfmt.Printf(\"%v\\n\", result5)\n\tfmt.Printf(\"%v\\n\", result6)\n\t// Output:\n\t// 1\n\t// 2\n\t// 3\n\t// 1\n\t// 2\n\t// 3\n}\n\nfunc Example_switchCase_DefaultF() {\n\tresult1 := Switch[int, string](1).\n\t\tCase(1, \"1\").\n\t\tCase(2, \"2\").\n\t\tDefault(\"3\")\n\n\tresult2 := Switch[int, string](2).\n\t\tCase(1, \"1\").\n\t\tCase(2, \"2\").\n\t\tDefault(\"3\")\n\n\tresult3 := Switch[int, string](42).\n\t\tCase(1, \"1\").\n\t\tCase(2, \"2\").\n\t\tDefault(\"3\")\n\n\tresult4 := Switch[int, string](1).\n\t\tCaseF(1, func() string { return \"1\" }).\n\t\tCaseF(2, func() string { return \"2\" }).\n\t\tDefaultF(func() string { return \"3\" })\n\n\tresult5 := Switch[int, string](2).\n\t\tCaseF(1, func() string { return \"1\" }).\n\t\tCaseF(2, func() string { return \"2\" }).\n\t\tDefaultF(func() string { return \"3\" })\n\n\tresult6 := Switch[int, string](42).\n\t\tCaseF(1, func() string { return \"1\" }).\n\t\tCaseF(2, func() string { return \"2\" }).\n\t\tDefaultF(func() string { return \"3\" })\n\n\tfmt.Printf(\"%v\\n\", result1)\n\tfmt.Printf(\"%v\\n\", result2)\n\tfmt.Printf(\"%v\\n\", result3)\n\tfmt.Printf(\"%v\\n\", result4)\n\tfmt.Printf(\"%v\\n\", result5)\n\tfmt.Printf(\"%v\\n\", result6)\n\t// Output:\n\t// 1\n\t// 2\n\t// 3\n\t// 1\n\t// 2\n\t// 3\n}\n\nfunc ExampleValidate() {\n\ti := 42\n\n\terr1 := Validate(i < 0, \"expected %d < 0\", i)\n\terr2 := Validate(i > 0, \"expected %d > 0\", i)\n\n\tfmt.Printf(\"%v\\n%v\", err1, err2)\n\t// Output:\n\t// expected 42 < 0\n\t// <nil>\n}\n\nfunc ExampleMust() {\n\tdefer func() {\n\t\t_ = recover()\n\t}()\n\n\t// won't panic\n\tMust(42, nil)\n\n\t// won't panic\n\tcb := func() (int, error) {\n\t\treturn 42, nil\n\t}\n\tMust(cb())\n\n\t// will panic\n\tMust(42, errors.New(\"my error\"))\n\n\t// will panic with error message\n\tMust(42, errors.New(\"world\"), \"hello\")\n}\n\nfunc ExampleMust0() {\n\tdefer func() {\n\t\t_ = recover()\n\t}()\n\n\t// won't panic\n\tMust0(nil)\n\n\t// will panic\n\tMust0(errors.New(\"my error\"))\n\n\t// will panic with error message\n\tMust0(errors.New(\"world\"), \"hello\")\n}\n\nfunc ExampleMust1() {\n\tdefer func() {\n\t\t_ = recover()\n\t}()\n\n\t// won't panic\n\tMust1(42, nil)\n\n\t// won't panic\n\tcb := func() (int, error) {\n\t\treturn 42, nil\n\t}\n\tMust1(cb())\n\n\t// will panic\n\tMust1(42, errors.New(\"my error\"))\n\n\t// will panic with error message\n\tMust1(42, errors.New(\"world\"), \"hello\")\n}\n\nfunc ExampleMust2() {\n\tdefer func() {\n\t\t_ = recover()\n\t}()\n\n\t// won't panic\n\tMust2(42, \"hello\", nil)\n\n\t// will panic\n\tMust2(42, \"hello\", errors.New(\"my error\"))\n\n\t// will panic with error message\n\tMust2(42, \"hello\", errors.New(\"world\"), \"hello\")\n}\n\nfunc ExampleMust3() {\n\tdefer func() {\n\t\t_ = recover()\n\t}()\n\n\t// won't panic\n\tMust3(42, \"hello\", 4.2, nil)\n\n\t// will panic\n\tMust3(42, \"hello\", 4.2, errors.New(\"my error\"))\n\n\t// will panic with error message\n\tMust3(42, \"hello\", 4.2, errors.New(\"world\"), \"hello\")\n}\n\nfunc ExampleMust4() {\n\tdefer func() {\n\t\t_ = recover()\n\t}()\n\n\t// won't panic\n\tMust4(42, \"hello\", 4.2, true, nil)\n\n\t// will panic\n\tMust4(42, \"hello\", 4.2, true, errors.New(\"my error\"))\n\n\t// will panic with error message\n\tMust4(42, \"hello\", 4.2, true, errors.New(\"world\"), \"hello\")\n}\n\nfunc ExampleMust5() {\n\tdefer func() {\n\t\t_ = recover()\n\t}()\n\n\t// won't panic\n\tMust5(42, \"hello\", 4.2, true, foo{}, nil)\n\n\t// will panic\n\tMust5(42, \"hello\", 4.2, true, foo{}, errors.New(\"my error\"))\n\n\t// will panic with error message\n\tMust5(42, \"hello\", 4.2, true, foo{}, errors.New(\"world\"), \"hello\")\n}\n\nfunc ExampleMust6() {\n\tdefer func() {\n\t\t_ = recover()\n\t}()\n\n\t// won't panic\n\tMust5(42, \"hello\", 4.2, true, foo{}, \"foobar\", nil)\n\n\t// will panic\n\tMust5(42, \"hello\", 4.2, true, foo{}, \"foobar\", errors.New(\"my error\"))\n\n\t// will panic with error message\n\tMust5(42, \"hello\", 4.2, true, foo{}, \"foobar\", errors.New(\"world\"), \"hello\")\n}\n\nfunc ExampleTry() {\n\tok1 := Try(func() error {\n\t\treturn nil\n\t})\n\tok2 := Try(func() error {\n\t\treturn errors.New(\"my error\")\n\t})\n\tok3 := Try(func() error {\n\t\tpanic(\"my error\")\n\t})\n\n\tfmt.Printf(\"%v\\n\", ok1)\n\tfmt.Printf(\"%v\\n\", ok2)\n\tfmt.Printf(\"%v\\n\", ok3)\n\t// Output:\n\t// true\n\t// false\n\t// false\n}\n\nfunc ExampleTry1() {\n\tok1 := Try1(func() error {\n\t\treturn nil\n\t})\n\tok2 := Try1(func() error {\n\t\treturn errors.New(\"my error\")\n\t})\n\tok3 := Try1(func() error {\n\t\tpanic(\"my error\")\n\t})\n\n\tfmt.Printf(\"%v\\n\", ok1)\n\tfmt.Printf(\"%v\\n\", ok2)\n\tfmt.Printf(\"%v\\n\", ok3)\n\t// Output:\n\t// true\n\t// false\n\t// false\n}\n\nfunc ExampleTry2() {\n\tok1 := Try2(func() (int, error) {\n\t\treturn 42, nil\n\t})\n\tok2 := Try2(func() (int, error) {\n\t\treturn 42, errors.New(\"my error\")\n\t})\n\tok3 := Try2(func() (int, error) {\n\t\tpanic(\"my error\")\n\t})\n\n\tfmt.Printf(\"%v\\n\", ok1)\n\tfmt.Printf(\"%v\\n\", ok2)\n\tfmt.Printf(\"%v\\n\", ok3)\n\t// Output:\n\t// true\n\t// false\n\t// false\n}\n\nfunc ExampleTry3() {\n\tok1 := Try3(func() (int, string, error) {\n\t\treturn 42, \"foobar\", nil\n\t})\n\tok2 := Try3(func() (int, string, error) {\n\t\treturn 42, \"foobar\", errors.New(\"my error\")\n\t})\n\tok3 := Try3(func() (int, string, error) {\n\t\tpanic(\"my error\")\n\t})\n\n\tfmt.Printf(\"%v\\n\", ok1)\n\tfmt.Printf(\"%v\\n\", ok2)\n\tfmt.Printf(\"%v\\n\", ok3)\n\t// Output:\n\t// true\n\t// false\n\t// false\n}\n\nfunc ExampleTry4() {\n\tok1 := Try4(func() (int, string, float64, error) {\n\t\treturn 42, \"foobar\", 4.2, nil\n\t})\n\tok2 := Try4(func() (int, string, float64, error) {\n\t\treturn 42, \"foobar\", 4.2, errors.New(\"my error\")\n\t})\n\tok3 := Try4(func() (int, string, float64, error) {\n\t\tpanic(\"my error\")\n\t})\n\n\tfmt.Printf(\"%v\\n\", ok1)\n\tfmt.Printf(\"%v\\n\", ok2)\n\tfmt.Printf(\"%v\\n\", ok3)\n\t// Output:\n\t// true\n\t// false\n\t// false\n}\n\nfunc ExampleTry5() {\n\tok1 := Try5(func() (int, string, float64, bool, error) {\n\t\treturn 42, \"foobar\", 4.2, true, nil\n\t})\n\tok2 := Try5(func() (int, string, float64, bool, error) {\n\t\treturn 42, \"foobar\", 4.2, true, errors.New(\"my error\")\n\t})\n\tok3 := Try5(func() (int, string, float64, bool, error) {\n\t\tpanic(\"my error\")\n\t})\n\n\tfmt.Printf(\"%v\\n\", ok1)\n\tfmt.Printf(\"%v\\n\", ok2)\n\tfmt.Printf(\"%v\\n\", ok3)\n\t// Output:\n\t// true\n\t// false\n\t// false\n}\n\nfunc ExampleTry6() {\n\tok1 := Try6(func() (int, string, float64, bool, foo, error) {\n\t\treturn 42, \"foobar\", 4.2, true, foo{}, nil\n\t})\n\tok2 := Try6(func() (int, string, float64, bool, foo, error) {\n\t\treturn 42, \"foobar\", 4.2, true, foo{}, errors.New(\"my error\")\n\t})\n\tok3 := Try6(func() (int, string, float64, bool, foo, error) {\n\t\tpanic(\"my error\")\n\t})\n\n\tfmt.Printf(\"%v\\n\", ok1)\n\tfmt.Printf(\"%v\\n\", ok2)\n\tfmt.Printf(\"%v\\n\", ok3)\n\t// Output:\n\t// true\n\t// false\n\t// false\n}\n\nfunc ExampleTryOr() {\n\tvalue1, ok1 := TryOr(func() (int, error) {\n\t\treturn 42, nil\n\t}, 21)\n\tvalue2, ok2 := TryOr(func() (int, error) {\n\t\treturn 42, errors.New(\"my error\")\n\t}, 21)\n\tvalue3, ok3 := TryOr(func() (int, error) {\n\t\tpanic(\"my error\")\n\t}, 21)\n\n\tfmt.Printf(\"%v %v\\n\", value1, ok1)\n\tfmt.Printf(\"%v %v\\n\", value2, ok2)\n\tfmt.Printf(\"%v %v\\n\", value3, ok3)\n\t// Output:\n\t// 42 true\n\t// 21 false\n\t// 21 false\n}\n\nfunc ExampleTryOr1() {\n\tvalue1, ok1 := TryOr1(func() (int, error) {\n\t\treturn 42, nil\n\t}, 21)\n\tvalue2, ok2 := TryOr1(func() (int, error) {\n\t\treturn 42, errors.New(\"my error\")\n\t}, 21)\n\tvalue3, ok3 := TryOr1(func() (int, error) {\n\t\tpanic(\"my error\")\n\t}, 21)\n\n\tfmt.Printf(\"%v %v\\n\", value1, ok1)\n\tfmt.Printf(\"%v %v\\n\", value2, ok2)\n\tfmt.Printf(\"%v %v\\n\", value3, ok3)\n\t// Output:\n\t// 42 true\n\t// 21 false\n\t// 21 false\n}\n\nfunc ExampleTryOr2() {\n\tvalue1, value2, ok3 := TryOr2(func() (int, string, error) {\n\t\tpanic(\"my error\")\n\t}, 21, \"hello\")\n\n\tfmt.Printf(\"%v %v %v\\n\", value1, value2, ok3)\n\t// Output: 21 hello false\n}\n\nfunc ExampleTryOr3() {\n\tvalue1, value2, value3, ok3 := TryOr3(func() (int, string, bool, error) {\n\t\tpanic(\"my error\")\n\t}, 21, \"hello\", false)\n\n\tfmt.Printf(\"%v %v %v %v\\n\", value1, value2, value3, ok3)\n\t// Output: 21 hello false false\n}\n\nfunc ExampleTryOr4() {\n\tvalue1, value2, value3, value4, ok3 := TryOr4(func() (int, string, bool, foo, error) {\n\t\tpanic(\"my error\")\n\t}, 21, \"hello\", false, foo{bar: \"bar\"})\n\n\tfmt.Printf(\"%v %v %v %v %v\\n\", value1, value2, value3, value4, ok3)\n\t// Output: 21 hello false {bar} false\n}\n\nfunc ExampleTryOr5() {\n\tvalue1, value2, value3, value4, value5, ok3 := TryOr5(func() (int, string, bool, foo, float64, error) {\n\t\tpanic(\"my error\")\n\t}, 21, \"hello\", false, foo{bar: \"bar\"}, 4.2)\n\n\tfmt.Printf(\"%v %v %v %v %v %v\\n\", value1, value2, value3, value4, value5, ok3)\n\t// Output: 21 hello false {bar} 4.2 false\n}\n\nfunc ExampleTryOr6() {\n\tvalue1, value2, value3, value4, value5, value6, ok3 := TryOr6(func() (int, string, bool, foo, float64, string, error) {\n\t\tpanic(\"my error\")\n\t}, 21, \"hello\", false, foo{bar: \"bar\"}, 4.2, \"world\")\n\n\tfmt.Printf(\"%v %v %v %v %v %v %v\\n\", value1, value2, value3, value4, value5, value6, ok3)\n\t// Output: 21 hello false {bar} 4.2 world false\n}\n\nfunc ExampleTryWithErrorValue() {\n\terr1, ok1 := TryWithErrorValue(func() error {\n\t\treturn nil\n\t})\n\terr2, ok2 := TryWithErrorValue(func() error {\n\t\treturn errors.New(\"my error\")\n\t})\n\terr3, ok3 := TryWithErrorValue(func() error {\n\t\tpanic(\"my error\")\n\t})\n\n\tfmt.Printf(\"%v %v\\n\", err1, ok1)\n\tfmt.Printf(\"%v %v\\n\", err2, ok2)\n\tfmt.Printf(\"%v %v\\n\", err3, ok3)\n\t// Output:\n\t// <nil> true\n\t// my error false\n\t// my error false\n}\n\nfunc ExampleTryCatchWithErrorValue() {\n\tTryCatchWithErrorValue(\n\t\tfunc() error {\n\t\t\tpanic(\"trigger an error\")\n\t\t},\n\t\tfunc(err any) {\n\t\t\tfmt.Printf(\"catch: %s\", err)\n\t\t},\n\t)\n\n\t// Output: catch: trigger an error\n}\n\ntype myError struct{}\n\nfunc (e myError) Error() string {\n\treturn \"my error\"\n}\n\nfunc ExampleErrorsAs() {\n\tdoSomething := func() error {\n\t\treturn &myError{}\n\t}\n\n\terr := doSomething()\n\n\tif rateLimitErr, ok := ErrorsAs[*myError](err); ok {\n\t\tfmt.Printf(\"is type myError, err: %s\", rateLimitErr.Error())\n\t} else {\n\t\tfmt.Printf(\"is not type myError\")\n\t}\n\n\t// Output: is type myError, err: my error\n}\n\nfunc ExampleAssert() {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tfmt.Println(r)\n\t\t}\n\t}()\n\n\tage := 20\n\n\t// won't panic\n\tAssert(age >= 18)\n\n\t// won't panic\n\tAssert(age >= 18, \"age must be at least 18\")\n\n\t// will panic\n\tAssert(age < 18)\n\n\t// will panic\n\tAssert(age < 18, \"age must be less than 18\")\n\n\t// Output: assertion failed\n}\n\nfunc ExampleAssertf() {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tfmt.Println(r)\n\t\t}\n\t}()\n\n\tage := 20\n\n\t// won't panic\n\tAssertf(age >= 18, \"age must be at least 18, got %d\", age)\n\n\t// will panic\n\tAssertf(age < 18, \"age must be less than 18, got %d\", age)\n\n\t// Output: assertion failed: age must be less than 18, got 20\n}\n\nfunc ExampleIndexOf() {\n\tlist := []string{\"foo\", \"bar\", \"baz\"}\n\n\tresult := IndexOf(list, \"bar\")\n\n\tfmt.Printf(\"%d\", result)\n\t// Output: 1\n}\n\nfunc ExampleIndexOf_notFound() {\n\tlist := []string{\"foo\", \"bar\", \"baz\"}\n\n\tresult := IndexOf(list, \"qux\")\n\n\tfmt.Printf(\"%d\", result)\n\t// Output: -1\n}\n\nfunc ExampleLastIndexOf() {\n\tlist := []string{\"foo\", \"bar\", \"baz\", \"bar\"}\n\n\tresult := LastIndexOf(list, \"bar\")\n\n\tfmt.Printf(\"%d\", result)\n\t// Output: 3\n}\n\nfunc ExampleLastIndexOf_notFound() {\n\tlist := []string{\"foo\", \"bar\", \"baz\"}\n\n\tresult := LastIndexOf(list, \"qux\")\n\n\tfmt.Printf(\"%d\", result)\n\t// Output: -1\n}\n\nfunc ExampleFind() {\n\ttype User struct {\n\t\tName string\n\t\tAge  int\n\t}\n\n\tusers := []User{\n\t\t{Name: \"Alice\", Age: 25},\n\t\t{Name: \"Bob\", Age: 30},\n\t\t{Name: \"Charlie\", Age: 35},\n\t}\n\n\tresult, found := Find(users, func(user User) bool {\n\t\treturn user.Age > 30\n\t})\n\n\tfmt.Printf(\"%s %t\", result.Name, found)\n\t// Output: Charlie true\n}\n\nfunc ExampleFind_notFound() {\n\tlist := []int{1, 2, 3, 4, 5}\n\n\tresult, found := Find(list, func(n int) bool {\n\t\treturn n > 10\n\t})\n\n\tfmt.Printf(\"%d %t\", result, found)\n\t// Output: 0 false\n}\n\nfunc ExampleFindErr() {\n\tresult, err := FindErr([]string{\"a\", \"b\", \"c\", \"d\"}, func(i string) (bool, error) {\n\t\treturn i == \"b\", nil\n\t})\n\tfmt.Printf(\"%v %v\\n\", result, err)\n\n\tresult, err = FindErr([]string{\"foobar\"}, func(i string) (bool, error) {\n\t\treturn i == \"b\", nil\n\t})\n\tfmt.Printf(\"%v %v\\n\", result, err)\n\n\tresult, err = FindErr([]string{\"a\", \"b\", \"c\"}, func(i string) (bool, error) {\n\t\tif i == \"b\" {\n\t\t\treturn false, errors.New(\"b is not allowed\")\n\t\t}\n\t\treturn i == \"b\", nil\n\t})\n\tfmt.Printf(\"%v %v\", result, err)\n\t// Output:\n\t// b <nil>\n\t//  <nil>\n\t//  b is not allowed\n}\n\nfunc ExampleFindIndexOf() {\n\tlist := []int{1, 2, 3, 4, 5}\n\n\tresult, index, found := FindIndexOf(list, func(n int) bool {\n\t\treturn n > 2\n\t})\n\n\tfmt.Printf(\"%d %d %t\", result, index, found)\n\t// Output: 3 2 true\n}\n\nfunc ExampleFindIndexOf_notFound() {\n\tlist := []int{1, 2, 3, 4, 5}\n\n\tresult, index, found := FindIndexOf(list, func(n int) bool {\n\t\treturn n > 10\n\t})\n\n\tfmt.Printf(\"%d %d %t\", result, index, found)\n\t// Output: 0 -1 false\n}\n\nfunc ExampleFindLastIndexOf() {\n\tlist := []int{1, 2, 3, 4, 3, 5}\n\n\tresult, index, found := FindLastIndexOf(list, func(n int) bool {\n\t\treturn n == 3\n\t})\n\n\tfmt.Printf(\"%d %d %t\", result, index, found)\n\t// Output: 3 4 true\n}\n\nfunc ExampleFindLastIndexOf_notFound() {\n\tlist := []int{1, 2, 3, 4, 5}\n\n\tresult, index, found := FindLastIndexOf(list, func(n int) bool {\n\t\treturn n > 10\n\t})\n\n\tfmt.Printf(\"%d %d %t\", result, index, found)\n\t// Output: 0 -1 false\n}\n\nfunc ExampleFindOrElse() {\n\tlist := []int{1, 2, 3, 4, 5}\n\n\tresult := FindOrElse(list, -1, func(n int) bool {\n\t\treturn n > 10\n\t})\n\n\tfmt.Printf(\"%d\", result)\n\t// Output: -1\n}\n\nfunc ExampleFindOrElse_found() {\n\tlist := []int{1, 2, 3, 4, 5}\n\n\tresult := FindOrElse(list, -1, func(n int) bool {\n\t\treturn n > 3\n\t})\n\n\tfmt.Printf(\"%d\", result)\n\t// Output: 4\n}\n\nfunc ExampleFindKey() {\n\tusers := map[string]int{\n\t\t\"Alice\":   25,\n\t\t\"Bob\":     30,\n\t\t\"Charlie\": 35,\n\t}\n\n\tkey, found := FindKey(users, 30)\n\n\tfmt.Printf(\"%s %t\", key, found)\n\t// Output: Bob true\n}\n\nfunc ExampleFindKey_notFound() {\n\tusers := map[string]int{\n\t\t\"Alice\":   25,\n\t\t\"Bob\":     30,\n\t\t\"Charlie\": 35,\n\t}\n\n\tkey, found := FindKey(users, 40)\n\n\tfmt.Printf(\"%s %t\", key, found)\n\t// Output:  false\n}\n\nfunc ExampleFindKeyBy() {\n\tusers := map[string]int{\n\t\t\"Alice\":   25,\n\t\t\"Bob\":     30,\n\t\t\"Charlie\": 35,\n\t}\n\n\tkey, found := FindKeyBy(users, func(name string, age int) bool {\n\t\treturn age > 30\n\t})\n\n\tfmt.Printf(\"%s %t\", key, found)\n\t// Output: Charlie true\n}\n\nfunc ExampleFindKeyBy_notFound() {\n\tusers := map[string]int{\n\t\t\"Alice\":   25,\n\t\t\"Bob\":     30,\n\t\t\"Charlie\": 35,\n\t}\n\n\tkey, found := FindKeyBy(users, func(name string, age int) bool {\n\t\treturn age > 40\n\t})\n\n\tfmt.Printf(\"%s %t\", key, found)\n\t// Output:  false\n}\n\nfunc ExampleFindUniques() {\n\tlist := []int{1, 2, 2, 3, 3, 3, 4, 5}\n\n\tresult := FindUniques(list)\n\n\tfmt.Printf(\"%v\", result)\n\t// Output: [1 4 5]\n}\n\nfunc ExampleFindUniquesBy() {\n\ttype User struct {\n\t\tName string\n\t\tAge  int\n\t}\n\n\tusers := []User{\n\t\t{Name: \"Alice\", Age: 25},\n\t\t{Name: \"Bob\", Age: 30},\n\t\t{Name: \"Charlie\", Age: 25},\n\t\t{Name: \"David\", Age: 30},\n\t\t{Name: \"Eve\", Age: 35},\n\t}\n\n\tresult := FindUniquesBy(users, func(user User) int {\n\t\treturn user.Age\n\t})\n\n\tfmt.Printf(\"%d\", len(result))\n\t// Output: 1\n}\n\nfunc ExampleFindDuplicates() {\n\tlist := []int{1, 2, 2, 3, 3, 3, 4, 5}\n\n\tresult := FindDuplicates(list)\n\n\tfmt.Printf(\"%v\", result)\n\t// Output: [2 3]\n}\n\nfunc ExampleFindDuplicatesBy() {\n\ttype User struct {\n\t\tName string\n\t\tAge  int\n\t}\n\n\tusers := []User{\n\t\t{Name: \"Alice\", Age: 25},\n\t\t{Name: \"Bob\", Age: 30},\n\t\t{Name: \"Charlie\", Age: 25},\n\t\t{Name: \"David\", Age: 30},\n\t\t{Name: \"Eve\", Age: 35},\n\t}\n\n\tresult := FindDuplicatesBy(users, func(user User) int {\n\t\treturn user.Age\n\t})\n\n\tfmt.Printf(\"%d\", len(result))\n\t// Output: 2\n}\n\nfunc ExampleFindDuplicatesByErr() {\n\ttype User struct {\n\t\tName string\n\t\tAge  int\n\t}\n\n\tusers := []User{\n\t\t{Name: \"Alice\", Age: 25},\n\t\t{Name: \"Bob\", Age: 30},\n\t\t{Name: \"Charlie\", Age: 25},\n\t\t{Name: \"David\", Age: 30},\n\t\t{Name: \"Eve\", Age: 35},\n\t}\n\n\tresult, err := FindDuplicatesByErr(users, func(user User) (int, error) {\n\t\tif user.Name == \"Charlie\" {\n\t\t\treturn 0, errors.New(\"charlie is not allowed\")\n\t\t}\n\t\treturn user.Age, nil\n\t})\n\n\tfmt.Printf(\"%d %v\", len(result), err)\n\t// Output: 0 charlie is not allowed\n}\n\nfunc ExampleMin() {\n\tlist := []int{3, 1, 4, 1, 5, 9, 2, 6}\n\n\tresult := Min(list)\n\n\tfmt.Printf(\"%d\", result)\n\t// Output: 1\n}\n\nfunc ExampleMin_empty() {\n\tlist := []int{}\n\n\tresult := Min(list)\n\n\tfmt.Printf(\"%d\", result)\n\t// Output: 0\n}\n\nfunc ExampleMinIndex() {\n\tlist := []int{3, 1, 4, 1, 5, 9, 2, 6}\n\n\tresult, index := MinIndex(list)\n\n\tfmt.Printf(\"%d %d\", result, index)\n\t// Output: 1 1\n}\n\nfunc ExampleMinIndex_empty() {\n\tlist := []int{}\n\n\tresult, index := MinIndex(list)\n\n\tfmt.Printf(\"%d %d\", result, index)\n\t// Output: 0 -1\n}\n\nfunc ExampleMinBy() {\n\ttype User struct {\n\t\tName string\n\t\tAge  int\n\t}\n\n\tusers := []User{\n\t\t{Name: \"Alice\", Age: 25},\n\t\t{Name: \"Bob\", Age: 30},\n\t\t{Name: \"Charlie\", Age: 35},\n\t}\n\n\tresult := MinBy(users, func(a, b User) bool {\n\t\treturn a.Age < b.Age\n\t})\n\n\tfmt.Printf(\"%s\", result.Name)\n\t// Output: Alice\n}\n\nfunc ExampleMinByErr() {\n\ttype User struct {\n\t\tName string\n\t\tAge  int\n\t}\n\n\tusers := []User{\n\t\t{Name: \"Alice\", Age: 25},\n\t\t{Name: \"Bob\", Age: 30},\n\t\t{Name: \"Charlie\", Age: 35},\n\t}\n\n\tresult, err := MinByErr(users, func(a, b User) (bool, error) {\n\t\tif a.Name == \"Bob\" {\n\t\t\treturn false, errors.New(\"bob is not allowed\")\n\t\t}\n\t\treturn a.Age < b.Age, nil\n\t})\n\n\tfmt.Printf(\"%v %v\", result.Name, err)\n\t// Output:  bob is not allowed\n}\n\nfunc ExampleMinIndexBy() {\n\ttype User struct {\n\t\tName string\n\t\tAge  int\n\t}\n\n\tusers := []User{\n\t\t{Name: \"Alice\", Age: 25},\n\t\t{Name: \"Bob\", Age: 30},\n\t\t{Name: \"Charlie\", Age: 35},\n\t}\n\n\tresult, index := MinIndexBy(users, func(a, b User) bool {\n\t\treturn a.Age < b.Age\n\t})\n\n\tfmt.Printf(\"%s %d\", result.Name, index)\n\t// Output: Alice 0\n}\n\nfunc ExampleMinIndexByErr() {\n\ttype User struct {\n\t\tName string\n\t\tAge  int\n\t}\n\n\tusers := []User{\n\t\t{Name: \"Alice\", Age: 25},\n\t\t{Name: \"Bob\", Age: 30},\n\t\t{Name: \"Charlie\", Age: 35},\n\t}\n\n\tresult, _, err := MinIndexByErr(users, func(a, b User) (bool, error) {\n\t\tif a.Name == \"Bob\" {\n\t\t\treturn false, errors.New(\"bob is not allowed\")\n\t\t}\n\t\treturn a.Age < b.Age, nil\n\t})\n\n\tfmt.Printf(\"%v %v\", result.Name, err)\n\t// Output:  bob is not allowed\n}\n\nfunc ExampleEarliest() {\n\tnow := time.Now()\n\tpast := now.Add(-time.Hour)\n\tfuture := now.Add(time.Hour)\n\n\tresult := Earliest(future, now, past)\n\n\tfmt.Printf(\"%t\", result.Equal(past))\n\t// Output: true\n}\n\nfunc ExampleEarliestBy() {\n\ttype Event struct {\n\t\tName string\n\t\tTime time.Time\n\t}\n\n\tnow := time.Now()\n\tevents := []Event{\n\t\t{Name: \"Event A\", Time: now.Add(time.Hour)},\n\t\t{Name: \"Event B\", Time: now},\n\t\t{Name: \"Event C\", Time: now.Add(-time.Hour)},\n\t}\n\n\tresult := EarliestBy(events, func(event Event) time.Time {\n\t\treturn event.Time\n\t})\n\n\tfmt.Printf(\"%s\", result.Name)\n\t// Output: Event C\n}\n\nfunc ExampleEarliestByErr() {\n\ttype Event struct {\n\t\tName string\n\t\tTime time.Time\n\t}\n\n\tnow := time.Now()\n\tevents := []Event{\n\t\t{Name: \"Event A\", Time: now.Add(time.Hour)},\n\t\t{Name: \"Event B\", Time: now},\n\t\t{Name: \"Event C\", Time: now.Add(-time.Hour)},\n\t}\n\n\t_, err := EarliestByErr(events, func(event Event) (time.Time, error) {\n\t\tif event.Name == \"Event B\" {\n\t\t\treturn time.Time{}, errors.New(\"event b is not allowed\")\n\t\t}\n\t\treturn event.Time, nil\n\t})\n\n\tfmt.Printf(\"%v\", err)\n\t// Output: event b is not allowed\n}\n\nfunc ExampleMax() {\n\tlist := []int{3, 1, 4, 1, 5, 9, 2, 6}\n\n\tresult := Max(list)\n\n\tfmt.Printf(\"%d\", result)\n\t// Output: 9\n}\n\nfunc ExampleMax_empty() {\n\tlist := []int{}\n\n\tresult := Max(list)\n\n\tfmt.Printf(\"%d\", result)\n\t// Output: 0\n}\n\nfunc ExampleMaxIndex() {\n\tlist := []int{3, 1, 4, 1, 5, 9, 2, 6}\n\n\tresult, index := MaxIndex(list)\n\n\tfmt.Printf(\"%d %d\", result, index)\n\t// Output: 9 5\n}\n\nfunc ExampleMaxIndex_empty() {\n\tlist := []int{}\n\n\tresult, index := MaxIndex(list)\n\n\tfmt.Printf(\"%d %d\", result, index)\n\t// Output: 0 -1\n}\n\nfunc ExampleMaxBy() {\n\ttype User struct {\n\t\tName string\n\t\tAge  int\n\t}\n\n\tusers := []User{\n\t\t{Name: \"Alice\", Age: 25},\n\t\t{Name: \"Bob\", Age: 30},\n\t\t{Name: \"Charlie\", Age: 35},\n\t}\n\n\tresult := MaxBy(users, func(a, b User) bool {\n\t\treturn a.Age > b.Age\n\t})\n\n\tfmt.Printf(\"%s\", result.Name)\n\t// Output: Charlie\n}\n\nfunc ExampleMaxByErr() {\n\ttype User struct {\n\t\tName string\n\t\tAge  int\n\t}\n\n\tusers := []User{\n\t\t{Name: \"Alice\", Age: 25},\n\t\t{Name: \"Bob\", Age: 30},\n\t\t{Name: \"Charlie\", Age: 35},\n\t}\n\n\t_, err := MaxByErr(users, func(a, b User) (bool, error) {\n\t\tif b.Name == \"Bob\" {\n\t\t\treturn false, errors.New(\"bob is not allowed\")\n\t\t}\n\t\treturn a.Age > b.Age, nil\n\t})\n\n\tfmt.Printf(\"%v\", err)\n\t// Output: bob is not allowed\n}\n\nfunc ExampleMaxIndexBy() {\n\ttype User struct {\n\t\tName string\n\t\tAge  int\n\t}\n\n\tusers := []User{\n\t\t{Name: \"Alice\", Age: 25},\n\t\t{Name: \"Bob\", Age: 30},\n\t\t{Name: \"Charlie\", Age: 35},\n\t}\n\n\tresult, index := MaxIndexBy(users, func(a, b User) bool {\n\t\treturn a.Age > b.Age\n\t})\n\n\tfmt.Printf(\"%s %d\", result.Name, index)\n\t// Output: Charlie 2\n}\n\nfunc ExampleMaxIndexByErr() {\n\ttype User struct {\n\t\tName string\n\t\tAge  int\n\t}\n\n\tusers := []User{\n\t\t{Name: \"Alice\", Age: 25},\n\t\t{Name: \"Bob\", Age: 30},\n\t\t{Name: \"Charlie\", Age: 35},\n\t}\n\n\t_, _, err := MaxIndexByErr(users, func(a, b User) (bool, error) {\n\t\tif b.Name == \"Bob\" {\n\t\t\treturn false, errors.New(\"bob is not allowed\")\n\t\t}\n\t\treturn a.Age > b.Age, nil\n\t})\n\n\tfmt.Printf(\"%v\", err)\n\t// Output: bob is not allowed\n}\n\nfunc ExampleLatest() {\n\tnow := time.Now()\n\tpast := now.Add(-time.Hour)\n\tfuture := now.Add(time.Hour)\n\n\tresult := Latest(future, now, past)\n\n\tfmt.Printf(\"%t\", result.Equal(future))\n\t// Output: true\n}\n\nfunc ExampleLatestBy() {\n\ttype Event struct {\n\t\tName string\n\t\tTime time.Time\n\t}\n\n\tnow := time.Now()\n\tevents := []Event{\n\t\t{Name: \"Event A\", Time: now.Add(time.Hour)},\n\t\t{Name: \"Event B\", Time: now},\n\t\t{Name: \"Event C\", Time: now.Add(-time.Hour)},\n\t}\n\n\tresult := LatestBy(events, func(event Event) time.Time {\n\t\treturn event.Time\n\t})\n\n\tfmt.Printf(\"%s\", result.Name)\n\t// Output: Event A\n}\n\nfunc ExampleLatestByErr() {\n\ttype Event struct {\n\t\tName string\n\t\tTime time.Time\n\t\tErr  error // Simulates error condition\n\t}\n\n\tnow := time.Now()\n\tevents := []Event{\n\t\t{Name: \"Event A\", Time: now.Add(time.Hour), Err: nil},\n\t\t{Name: \"Event B\", Time: now, Err: errors.New(\"event b error\")},\n\t\t{Name: \"Event C\", Time: now.Add(-time.Hour), Err: nil},\n\t}\n\n\t_, err := LatestByErr(events, func(event Event) (time.Time, error) {\n\t\tif event.Err != nil {\n\t\t\treturn time.Time{}, event.Err\n\t\t}\n\t\treturn event.Time, nil\n\t})\n\n\tfmt.Printf(\"%v\", err)\n\t// Output: event b error\n}\n\nfunc ExampleFirst() {\n\tlist := []int{1, 2, 3, 4, 5}\n\n\tresult, found := First(list)\n\n\tfmt.Printf(\"%d %t\", result, found)\n\t// Output: 1 true\n}\n\nfunc ExampleFirst_empty() {\n\tlist := []int{}\n\n\tresult, found := First(list)\n\n\tfmt.Printf(\"%d %t\", result, found)\n\t// Output: 0 false\n}\n\nfunc ExampleFirstOrEmpty() {\n\tlist := []int{1, 2, 3, 4, 5}\n\n\tresult := FirstOrEmpty(list)\n\n\tfmt.Printf(\"%d\", result)\n\t// Output: 1\n}\n\nfunc ExampleFirstOrEmpty_empty() {\n\tlist := []int{}\n\n\tresult := FirstOrEmpty(list)\n\n\tfmt.Printf(\"%d\", result)\n\t// Output: 0\n}\n\nfunc ExampleFirstOr() {\n\tlist := []int{1, 2, 3, 4, 5}\n\n\tresult := FirstOr(list, -1)\n\n\tfmt.Printf(\"%d\", result)\n\t// Output: 1\n}\n\nfunc ExampleFirstOr_empty() {\n\tlist := []int{}\n\n\tresult := FirstOr(list, -1)\n\n\tfmt.Printf(\"%d\", result)\n\t// Output: -1\n}\n\nfunc ExampleLast() {\n\tlist := []int{1, 2, 3, 4, 5}\n\n\tresult, found := Last(list)\n\n\tfmt.Printf(\"%d %t\", result, found)\n\t// Output: 5 true\n}\n\nfunc ExampleLast_empty() {\n\tlist := []int{}\n\n\tresult, found := Last(list)\n\n\tfmt.Printf(\"%d %t\", result, found)\n\t// Output: 0 false\n}\n\nfunc ExampleLastOrEmpty() {\n\tlist := []int{1, 2, 3, 4, 5}\n\n\tresult := LastOrEmpty(list)\n\n\tfmt.Printf(\"%d\", result)\n\t// Output: 5\n}\n\nfunc ExampleLastOrEmpty_empty() {\n\tlist := []int{}\n\n\tresult := LastOrEmpty(list)\n\n\tfmt.Printf(\"%d\", result)\n\t// Output: 0\n}\n\nfunc ExampleLastOr() {\n\tlist := []int{1, 2, 3, 4, 5}\n\n\tresult := LastOr(list, -1)\n\n\tfmt.Printf(\"%d\", result)\n\t// Output: 5\n}\n\nfunc ExampleLastOr_empty() {\n\tlist := []int{}\n\n\tresult := LastOr(list, -1)\n\n\tfmt.Printf(\"%d\", result)\n\t// Output: -1\n}\n\nfunc ExampleNth() {\n\tlist := []int{1, 2, 3, 4, 5}\n\n\tresult, err := Nth(list, 2)\n\n\tfmt.Printf(\"%d %v\", result, err)\n\t// Output: 3 <nil>\n}\n\nfunc ExampleNth_negative() {\n\tlist := []int{1, 2, 3, 4, 5}\n\n\tresult, err := Nth(list, -2)\n\n\tfmt.Printf(\"%d %v\", result, err)\n\t// Output: 4 <nil>\n}\n\nfunc ExampleNth_outOfBounds() {\n\tlist := []int{1, 2, 3, 4, 5}\n\n\tresult, err := Nth(list, 10)\n\n\tfmt.Printf(\"%d %v\", result, err)\n\t// Output: 0 nth: 10 out of slice bounds\n}\n\nfunc ExampleNthOr() {\n\tlist := []int{1, 2, 3, 4, 5}\n\n\tresult := NthOr(list, 2, -1)\n\n\tfmt.Printf(\"%d\", result)\n\t// Output: 3\n}\n\nfunc ExampleNthOr_outOfBounds() {\n\tlist := []int{1, 2, 3, 4, 5}\n\n\tresult := NthOr(list, 10, -1)\n\n\tfmt.Printf(\"%d\", result)\n\t// Output: -1\n}\n\nfunc ExampleNthOrEmpty() {\n\tlist := []int{1, 2, 3, 4, 5}\n\n\tresult := NthOrEmpty(list, 2)\n\n\tfmt.Printf(\"%d\", result)\n\t// Output: 3\n}\n\nfunc ExampleNthOrEmpty_outOfBounds() {\n\tlist := []int{1, 2, 3, 4, 5}\n\n\tresult := NthOrEmpty(list, 10)\n\n\tfmt.Printf(\"%d\", result)\n\t// Output: 0\n}\n\nfunc ExampleWithoutBy() {\n\ttype User struct {\n\t\tID   int\n\t\tName string\n\t}\n\t// original users\n\tusers := []User{\n\t\t{ID: 1, Name: \"Alice\"},\n\t\t{ID: 2, Name: \"Bob\"},\n\t\t{ID: 3, Name: \"Charlie\"},\n\t}\n\n\t// exclude users with IDs 2 and 3\n\texcludedIDs := []int{2, 3}\n\n\t// extract function to get the user ID\n\textractID := func(user User) int {\n\t\treturn user.ID\n\t}\n\n\t// filtering users\n\tfilteredUsers := WithoutBy(users, extractID, excludedIDs...)\n\n\t// output the filtered users\n\tfmt.Printf(\"%v\", filteredUsers)\n\t// Output:\n\t// [{1 Alice}]\n}\n\nfunc ExampleWithoutByErr() {\n\ttype User struct {\n\t\tID   int\n\t\tName string\n\t}\n\t// original users\n\tusers := []User{\n\t\t{ID: 1, Name: \"Alice\"},\n\t\t{ID: 2, Name: \"Bob\"},\n\t\t{ID: 3, Name: \"Charlie\"},\n\t}\n\n\t// exclude users with IDs 2 and 3\n\texcludedIDs := []int{2, 3}\n\n\t// extract function to get the user ID\n\textractID := func(user User) (int, error) {\n\t\tif user.ID == 2 {\n\t\t\treturn 0, errors.New(\"user 2 extraction failed\")\n\t\t}\n\t\treturn user.ID, nil\n\t}\n\n\t// filtering users\n\tfilteredUsers, err := WithoutByErr(users, extractID, excludedIDs...)\n\n\t// output the filtered users\n\tfmt.Printf(\"%v %v\", filteredUsers, err)\n\t// Output:\n\t// [] user 2 extraction failed\n}\n\nfunc ExampleKeys() {\n\tkv := map[string]int{\"foo\": 1, \"bar\": 2}\n\tkv2 := map[string]int{\"baz\": 3}\n\n\tresult := Keys(kv, kv2)\n\tsort.Strings(result)\n\tfmt.Printf(\"%v\", result)\n\t// Output: [bar baz foo]\n}\n\nfunc ExampleUniqKeys() {\n\tkv := map[string]int{\"foo\": 1, \"bar\": 2}\n\tkv2 := map[string]int{\"bar\": 3}\n\n\tresult := UniqKeys(kv, kv2)\n\tsort.Strings(result)\n\tfmt.Printf(\"%v\", result)\n\t// Output: [bar foo]\n}\n\nfunc ExampleValues() {\n\tkv := map[string]int{\"foo\": 1, \"bar\": 2}\n\tkv2 := map[string]int{\"baz\": 3}\n\n\tresult := Values(kv, kv2)\n\n\tsort.Ints(result)\n\tfmt.Printf(\"%v\", result)\n\t// Output: [1 2 3]\n}\n\nfunc ExampleUniqValues() {\n\tkv := map[string]int{\"foo\": 1, \"bar\": 2}\n\tkv2 := map[string]int{\"baz\": 2}\n\n\tresult := UniqValues(kv, kv2)\n\n\tsort.Ints(result)\n\tfmt.Printf(\"%v\", result)\n\t// Output: [1 2]\n}\n\nfunc ExampleValueOr() {\n\tkv := map[string]int{\"foo\": 1, \"bar\": 2}\n\n\tresult1 := ValueOr(kv, \"foo\", 42)\n\tresult2 := ValueOr(kv, \"baz\", 42)\n\n\tfmt.Printf(\"%v %v\", result1, result2)\n\t// Output: 1 42\n}\n\nfunc ExamplePickBy() {\n\tkv := map[string]int{\"foo\": 1, \"bar\": 2, \"baz\": 3}\n\n\tresult := PickBy(kv, func(key string, value int) bool {\n\t\treturn value%2 == 1\n\t})\n\n\tfmt.Printf(\"%v %v %v\", len(result), result[\"foo\"], result[\"baz\"])\n\t// Output: 2 1 3\n}\n\nfunc ExamplePickByErr() {\n\tkv := map[string]int{\"foo\": 1, \"bar\": 2, \"baz\": 3}\n\n\t_, err := PickByErr(kv, func(key string, value int) (bool, error) {\n\t\tif key == \"bar\" {\n\t\t\treturn false, errors.New(\"key bar is not allowed\")\n\t\t}\n\t\treturn value%2 == 1, nil\n\t})\n\n\tfmt.Printf(\"%v\", err)\n\t// Output: key bar is not allowed\n}\n\nfunc ExamplePickByKeys() {\n\tkv := map[string]int{\"foo\": 1, \"bar\": 2, \"baz\": 3}\n\n\tresult := PickByKeys(kv, []string{\"foo\", \"baz\"})\n\n\tfmt.Printf(\"%v %v %v\", len(result), result[\"foo\"], result[\"baz\"])\n\t// Output: 2 1 3\n}\n\nfunc ExamplePickByValues() {\n\tkv := map[string]int{\"foo\": 1, \"bar\": 2, \"baz\": 3}\n\n\tresult := PickByValues(kv, []int{1, 3})\n\n\tfmt.Printf(\"%v %v %v\", len(result), result[\"foo\"], result[\"baz\"])\n\t// Output: 2 1 3\n}\n\nfunc ExampleOmitBy() {\n\tkv := map[string]int{\"foo\": 1, \"bar\": 2, \"baz\": 3}\n\n\tresult := OmitBy(kv, func(key string, value int) bool {\n\t\treturn value%2 == 1\n\t})\n\n\tfmt.Printf(\"%v\", result)\n\t// Output: map[bar:2]\n}\n\nfunc ExampleOmitByErr() {\n\tkv := map[string]int{\"foo\": 1, \"bar\": 2, \"baz\": 3}\n\n\t_, err := OmitByErr(kv, func(key string, value int) (bool, error) {\n\t\tif key == \"bar\" {\n\t\t\treturn false, errors.New(\"key bar is not allowed\")\n\t\t}\n\t\treturn value%2 == 1, nil\n\t})\n\n\tfmt.Printf(\"%v\", err)\n\t// Output: key bar is not allowed\n}\n\nfunc ExampleOmitByKeys() {\n\tkv := map[string]int{\"foo\": 1, \"bar\": 2, \"baz\": 3}\n\n\tresult := OmitByKeys(kv, []string{\"foo\", \"baz\"})\n\n\tfmt.Printf(\"%v\", result)\n\t// Output: map[bar:2]\n}\n\nfunc ExampleOmitByValues() {\n\tkv := map[string]int{\"foo\": 1, \"bar\": 2, \"baz\": 3}\n\n\tresult := OmitByValues(kv, []int{1, 3})\n\n\tfmt.Printf(\"%v\", result)\n\t// Output: map[bar:2]\n}\n\nfunc ExampleEntries() {\n\tkv := map[string]int{\"foo\": 1, \"bar\": 2, \"baz\": 3}\n\n\tresult := Entries(kv)\n\n\tsort.Slice(result, func(i, j int) bool {\n\t\treturn strings.Compare(result[i].Key, result[j].Key) < 0\n\t})\n\tfmt.Printf(\"%v\", result)\n\t// Output: [{bar 2} {baz 3} {foo 1}]\n}\n\nfunc ExampleFromEntries() {\n\tresult := FromEntries([]Entry[string, int]{\n\t\t{\n\t\t\tKey:   \"foo\",\n\t\t\tValue: 1,\n\t\t},\n\t\t{\n\t\t\tKey:   \"bar\",\n\t\t\tValue: 2,\n\t\t},\n\t\t{\n\t\t\tKey:   \"baz\",\n\t\t\tValue: 3,\n\t\t},\n\t})\n\n\tfmt.Printf(\"%v %v %v %v\", len(result), result[\"foo\"], result[\"bar\"], result[\"baz\"])\n\t// Output: 3 1 2 3\n}\n\nfunc ExampleInvert() {\n\tkv := map[string]int{\"foo\": 1, \"bar\": 2, \"baz\": 3}\n\n\tresult := Invert(kv)\n\n\tfmt.Printf(\"%v %v %v %v\", len(result), result[1], result[2], result[3])\n\t// Output: 3 foo bar baz\n}\n\nfunc ExampleAssign() {\n\tresult := Assign(\n\t\tmap[string]int{\"a\": 1, \"b\": 2},\n\t\tmap[string]int{\"b\": 3, \"c\": 4},\n\t)\n\n\tfmt.Printf(\"%v %v %v %v\", len(result), result[\"a\"], result[\"b\"], result[\"c\"])\n\t// Output: 3 1 3 4\n}\n\nfunc ExampleChunkEntries() {\n\tresult := ChunkEntries(\n\t\tmap[string]int{\n\t\t\t\"a\": 1,\n\t\t\t\"b\": 2,\n\t\t\t\"c\": 3,\n\t\t\t\"d\": 4,\n\t\t\t\"e\": 5,\n\t\t},\n\t\t3,\n\t)\n\n\tfor i := range result {\n\t\tfmt.Printf(\"%d\\n\", len(result[i]))\n\t}\n\t// Output:\n\t// 3\n\t// 2\n}\n\nfunc ExampleMapKeys() {\n\tkv := map[int]int{1: 1, 2: 2, 3: 3, 4: 4}\n\n\tresult := MapKeys(kv, func(_, k int) string {\n\t\treturn strconv.FormatInt(int64(k), 10)\n\t})\n\n\tfmt.Printf(\"%v %v %v %v %v\", len(result), result[\"1\"], result[\"2\"], result[\"3\"], result[\"4\"])\n\t// Output: 4 1 2 3 4\n}\n\nfunc ExampleMapKeysErr() {\n\tkv := map[int]int{1: 1, 2: 2, 3: 3, 4: 4}\n\n\t_, err := MapKeysErr(kv, func(_, k int) (string, error) {\n\t\tif k == 3 {\n\t\t\treturn \"\", errors.New(\"key 3 is not allowed\")\n\t\t}\n\t\treturn strconv.FormatInt(int64(k), 10), nil\n\t})\n\n\tfmt.Printf(\"%v\", err)\n\t// Output: key 3 is not allowed\n}\n\nfunc ExampleMapValues() {\n\tkv := map[int]int{1: 1, 2: 2, 3: 3, 4: 4}\n\n\tresult := MapValues(kv, func(v, _ int) string {\n\t\treturn strconv.FormatInt(int64(v), 10)\n\t})\n\n\tfmt.Printf(\"%v %q %q %q %q\", len(result), result[1], result[2], result[3], result[4])\n\t// Output: 4 \"1\" \"2\" \"3\" \"4\"\n}\n\nfunc ExampleMapValuesErr() {\n\tkv := map[int]int{1: 1, 2: 2, 3: 3, 4: 4}\n\n\t_, err := MapValuesErr(kv, func(v, _ int) (string, error) {\n\t\tif v == 3 {\n\t\t\treturn \"\", errors.New(\"value 3 is not allowed\")\n\t\t}\n\t\treturn strconv.FormatInt(int64(v), 10), nil\n\t})\n\n\tfmt.Printf(\"%v\", err)\n\t// Output: value 3 is not allowed\n}\n\nfunc ExampleMapEntries() {\n\tkv := map[string]int{\"foo\": 1, \"bar\": 2}\n\n\tresult := MapEntries(kv, func(k string, v int) (int, string) {\n\t\treturn v, k\n\t})\n\n\tfmt.Printf(\"%v\", result)\n\t// Output: map[1:foo 2:bar]\n}\n\nfunc ExampleMapEntriesErr() {\n\tkv := map[string]int{\"foo\": 1, \"bar\": 2}\n\n\t_, err := MapEntriesErr(kv, func(k string, v int) (int, string, error) {\n\t\tif k == \"foo\" {\n\t\t\treturn 0, \"\", errors.New(\"entry foo is not allowed\")\n\t\t}\n\t\treturn v, k, nil\n\t})\n\n\tfmt.Printf(\"%v\", err)\n\t// Output: entry foo is not allowed\n}\n\nfunc ExampleMapToSlice() {\n\tkv := map[int]int64{1: 1, 2: 2, 3: 3, 4: 4}\n\n\tresult := MapToSlice(kv, func(k int, v int64) string {\n\t\treturn fmt.Sprintf(\"%d_%d\", k, v)\n\t})\n\n\tsort.Strings(result)\n\tfmt.Printf(\"%v\", result)\n\t// Output: [1_1 2_2 3_3 4_4]\n}\n\nfunc ExampleMapToSliceErr() {\n\tkv := map[int]int64{1: 1, 2: 2, 3: 3, 4: 4}\n\n\t_, err := MapToSliceErr(kv, func(k int, v int64) (string, error) {\n\t\tif k == 3 {\n\t\t\treturn \"\", errors.New(\"key 3 is not allowed\")\n\t\t}\n\t\treturn fmt.Sprintf(\"%d_%d\", k, v), nil\n\t})\n\n\tfmt.Printf(\"%v\", err)\n\t// Output: key 3 is not allowed\n}\n\nfunc ExampleFilterMapToSlice() {\n\tkv := map[int]int64{1: 1, 2: 2, 3: 3, 4: 4}\n\n\tresult := FilterMapToSlice(kv, func(k int, v int64) (string, bool) {\n\t\treturn fmt.Sprintf(\"%d_%d\", k, v), k%2 == 0\n\t})\n\n\tsort.Strings(result)\n\tfmt.Printf(\"%v\", result)\n\t// Output: [2_2 4_4]\n}\n\nfunc ExampleFilterMapToSliceErr() {\n\tkv := map[int]int64{1: 1, 2: 2, 3: 3, 4: 4}\n\n\t_, err := FilterMapToSliceErr(kv, func(k int, v int64) (string, bool, error) {\n\t\tif k == 3 {\n\t\t\treturn \"\", false, errors.New(\"key 3 is not allowed\")\n\t\t}\n\t\treturn fmt.Sprintf(\"%d_%d\", k, v), k%2 == 0, nil\n\t})\n\n\tfmt.Printf(\"%v\", err)\n\t// Output: key 3 is not allowed\n}\n\nfunc ExampleFilterKeys() {\n\tkv := map[int]string{1: \"foo\", 2: \"bar\", 3: \"baz\"}\n\n\tresult := FilterKeys(kv, func(k int, v string) bool {\n\t\treturn v == \"foo\"\n\t})\n\n\tfmt.Printf(\"%v\", result)\n\t// Output: [1]\n}\n\nfunc ExampleFilterValues() {\n\tkv := map[int]string{1: \"foo\", 2: \"bar\", 3: \"baz\"}\n\n\tresult := FilterValues(kv, func(k int, v string) bool {\n\t\treturn v == \"foo\"\n\t})\n\n\tfmt.Printf(\"%v\", result)\n\t// Output: [foo]\n}\n\nfunc ExampleFilterKeysErr() {\n\tkv := map[int]string{1: \"foo\", 2: \"bar\", 3: \"baz\"}\n\n\tresult, err := FilterKeysErr(kv, func(k int, v string) (bool, error) {\n\t\tif k == 3 {\n\t\t\treturn false, errors.New(\"key 3 not allowed\")\n\t\t}\n\t\treturn v == \"foo\", nil\n\t})\n\tfmt.Printf(\"%v, %v\\n\", result, err)\n\n\tresult, err = FilterKeysErr(kv, func(k int, v string) (bool, error) {\n\t\treturn v == \"bar\", nil\n\t})\n\tfmt.Printf(\"%v, %v\\n\", result, err)\n\t// Output:\n\t// [], key 3 not allowed\n\t// [2], <nil>\n}\n\nfunc ExampleFilterValuesErr() {\n\tkv := map[int]string{1: \"foo\", 2: \"bar\", 3: \"baz\"}\n\n\tresult, err := FilterValuesErr(kv, func(k int, v string) (bool, error) {\n\t\tif k == 3 {\n\t\t\treturn false, errors.New(\"key 3 not allowed\")\n\t\t}\n\t\treturn v == \"foo\", nil\n\t})\n\tfmt.Printf(\"%v, %v\\n\", result, err)\n\n\tresult, err = FilterValuesErr(kv, func(k int, v string) (bool, error) {\n\t\treturn v == \"bar\", nil\n\t})\n\tfmt.Printf(\"%v, %v\\n\", result, err)\n\t// Output:\n\t// [], key 3 not allowed\n\t// [bar], <nil>\n}\n\nfunc ExampleRange() {\n\tresult1 := Range(4)\n\tresult2 := Range(-4)\n\tresult3 := RangeFrom(1, 5)\n\tresult4 := RangeFrom(1.0, 5)\n\tresult5 := RangeWithSteps(0, 20, 5)\n\tresult6 := RangeWithSteps[float32](-1.0, -4.0, -1.0)\n\tresult7 := RangeWithSteps(1, 4, -1)\n\tresult8 := Range(0)\n\n\tfmt.Printf(\"%v\\n\", result1)\n\tfmt.Printf(\"%v\\n\", result2)\n\tfmt.Printf(\"%v\\n\", result3)\n\tfmt.Printf(\"%v\\n\", result4)\n\tfmt.Printf(\"%v\\n\", result5)\n\tfmt.Printf(\"%v\\n\", result6)\n\tfmt.Printf(\"%v\\n\", result7)\n\tfmt.Printf(\"%v\\n\", result8)\n\t// Output:\n\t// [0 1 2 3]\n\t// [0 -1 -2 -3]\n\t// [1 2 3 4 5]\n\t// [1 2 3 4 5]\n\t// [0 5 10 15]\n\t// [-1 -2 -3]\n\t// []\n\t// []\n}\n\nfunc ExampleClamp() {\n\tresult1 := Clamp(0, -10, 10)\n\tresult2 := Clamp(-42, -10, 10)\n\tresult3 := Clamp(42, -10, 10)\n\n\tfmt.Printf(\"%v\\n\", result1)\n\tfmt.Printf(\"%v\\n\", result2)\n\tfmt.Printf(\"%v\\n\", result3)\n\t// Output:\n\t// 0\n\t// -10\n\t// 10\n}\n\nfunc ExampleSum() {\n\tlist := []int{1, 2, 3, 4, 5}\n\n\tsum := Sum(list)\n\n\tfmt.Printf(\"%v\", sum)\n\t// Output: 15\n}\n\nfunc ExampleSumBy() {\n\tlist := []string{\"foo\", \"bar\"}\n\n\tresult := SumBy(list, func(item string) int {\n\t\treturn len(item)\n\t})\n\n\tfmt.Printf(\"%v\", result)\n\t// Output: 6\n}\n\nfunc ExampleSumByErr() {\n\tlist := []string{\"foo\", \"bar\", \"baz\"}\n\n\t_, err := SumByErr(list, func(item string) (int, error) {\n\t\tif item == \"bar\" {\n\t\t\treturn 0, errors.New(\"bar is not allowed\")\n\t\t}\n\t\treturn len(item), nil\n\t})\n\n\tfmt.Printf(\"%v\", err)\n\t// Output: bar is not allowed\n}\n\nfunc ExampleProduct() {\n\tlist := []int{1, 2, 3, 4, 5}\n\n\tresult := Product(list)\n\n\tfmt.Printf(\"%v\", result)\n\t// Output: 120\n}\n\nfunc ExampleProductBy() {\n\tlist := []string{\"foo\", \"bar\"}\n\n\tresult := ProductBy(list, func(item string) int {\n\t\treturn len(item)\n\t})\n\n\tfmt.Printf(\"%v\", result)\n\t// Output: 9\n}\n\nfunc ExampleProductByErr() {\n\tlist := []string{\"foo\", \"bar\", \"baz\"}\n\n\t_, err := ProductByErr(list, func(item string) (int, error) {\n\t\tif item == \"bar\" {\n\t\t\treturn 0, errors.New(\"bar is not allowed\")\n\t\t}\n\t\treturn len(item), nil\n\t})\n\n\tfmt.Printf(\"%v\", err)\n\t// Output: bar is not allowed\n}\n\nfunc ExampleMean() {\n\tlist := []int{1, 2, 3, 4, 5}\n\n\tresult := Mean(list)\n\n\tfmt.Printf(\"%v\", result)\n\t// Output: 3\n}\n\nfunc ExampleMeanBy() {\n\tlist := []string{\"foo\", \"bar\"}\n\n\tresult := MeanBy(list, func(item string) int {\n\t\treturn len(item)\n\t})\n\n\tfmt.Printf(\"%v\", result)\n\t// Output: 3\n}\n\nfunc ExampleMeanByErr() {\n\tlist := []string{\"foo\", \"bar\", \"baz\"}\n\n\t_, err := MeanByErr(list, func(item string) (int, error) {\n\t\tif item == \"bar\" {\n\t\t\treturn 0, errors.New(\"bar is not allowed\")\n\t\t}\n\t\treturn len(item), nil\n\t})\n\n\tfmt.Printf(\"%v\", err)\n\t// Output: bar is not allowed\n}\n\nfunc ExampleFilter() {\n\tlist := []int64{1, 2, 3, 4}\n\n\tresult := Filter(list, func(nbr int64, index int) bool {\n\t\treturn nbr%2 == 0\n\t})\n\n\tfmt.Printf(\"%v\", result)\n\t// Output: [2 4]\n}\n\nfunc ExampleFilterErr() {\n\tlist := []int64{1, 2, 3, 4}\n\n\tresult, err := FilterErr(list, func(nbr int64, index int) (bool, error) {\n\t\tif nbr == 3 {\n\t\t\treturn false, errors.New(\"number 3 is not allowed\")\n\t\t}\n\t\treturn nbr%2 == 0, nil\n\t})\n\tfmt.Printf(\"%v, %v\\n\", result, err)\n\n\tresult, err = FilterErr([]int64{1, 2, 4, 6}, func(nbr int64, index int) (bool, error) {\n\t\treturn nbr%2 == 0, nil\n\t})\n\tfmt.Printf(\"%v, %v\\n\", result, err)\n\t// Output:\n\t// [], number 3 is not allowed\n\t// [2 4 6], <nil>\n}\n\nfunc ExampleMap() {\n\tlist := []int64{1, 2, 3, 4}\n\n\tresult := Map(list, func(nbr int64, index int) string {\n\t\treturn strconv.FormatInt(nbr*2, 10)\n\t})\n\n\tfmt.Printf(\"%v\", result)\n\t// Output: [2 4 6 8]\n}\n\nfunc ExampleMapErr() {\n\tlist := []int64{1, 2, 3, 4}\n\n\t_, err := MapErr(list, func(nbr int64, index int) (string, error) {\n\t\tif nbr == 3 {\n\t\t\treturn \"\", errors.New(\"number 3 is not allowed\")\n\t\t}\n\t\treturn strconv.FormatInt(nbr*2, 10), nil\n\t})\n\n\tfmt.Printf(\"%v\", err)\n\t// Output: number 3 is not allowed\n}\n\nfunc ExampleUniqMap() {\n\ttype User struct {\n\t\tName string\n\t\tAge  int\n\t}\n\tusers := []User{{Name: \"Alex\", Age: 10}, {Name: \"Alex\", Age: 12}, {Name: \"Bob\", Age: 11}, {Name: \"Alice\", Age: 20}}\n\n\tresult := UniqMap(users, func(u User, index int) string {\n\t\treturn u.Name\n\t})\n\n\tsort.Strings(result)\n\n\tfmt.Printf(\"%v\", result)\n\t// Output: [Alex Alice Bob]\n}\n\nfunc ExampleFilterMap() {\n\tlist := []int64{1, 2, 3, 4}\n\n\tresult := FilterMap(list, func(nbr int64, index int) (string, bool) {\n\t\treturn strconv.FormatInt(nbr*2, 10), nbr%2 == 0\n\t})\n\n\tfmt.Printf(\"%v\", result)\n\t// Output: [4 8]\n}\n\nfunc ExampleFlatMap() {\n\tlist := []int64{1, 2, 3, 4}\n\n\tresult := FlatMap(list, func(nbr int64, index int) []string {\n\t\treturn []string{\n\t\t\tstrconv.FormatInt(nbr, 10), // base 10\n\t\t\tstrconv.FormatInt(nbr, 2),  // base 2\n\t\t}\n\t})\n\n\tfmt.Printf(\"%v\", result)\n\t// Output: [1 1 2 10 3 11 4 100]\n}\n\nfunc ExampleFlatMapErr() {\n\tlist := []int64{1, 2, 3, 4}\n\n\t_, err := FlatMapErr(list, func(nbr int64, index int) ([]string, error) {\n\t\tif nbr == 3 {\n\t\t\treturn nil, errors.New(\"number 3 is not allowed\")\n\t\t}\n\t\treturn []string{\n\t\t\tstrconv.FormatInt(nbr, 10), // base 10\n\t\t\tstrconv.FormatInt(nbr, 2),  // base 2\n\t\t}, nil\n\t})\n\n\tfmt.Printf(\"%v\", err)\n\t// Output: number 3 is not allowed\n}\n\nfunc ExampleReduce() {\n\tlist := []int64{1, 2, 3, 4}\n\n\tresult := Reduce(list, func(agg, item int64, index int) int64 {\n\t\treturn agg + item\n\t}, 0)\n\n\tfmt.Printf(\"%v\", result)\n\t// Output: 10\n}\n\nfunc ExampleReduceErr() {\n\tlist := []int64{1, 2, 3, 4}\n\n\t_, err := ReduceErr(list, func(agg, item int64, index int) (int64, error) {\n\t\tif item == 3 {\n\t\t\treturn 0, errors.New(\"number 3 is not allowed\")\n\t\t}\n\t\treturn agg + item, nil\n\t}, 0)\n\n\tfmt.Printf(\"%v\", err)\n\t// Output: number 3 is not allowed\n}\n\nfunc ExampleReduceRight() {\n\tlist := [][]int{{0, 1}, {2, 3}, {4, 5}}\n\n\tresult := ReduceRight(list, func(agg, item []int, index int) []int {\n\t\treturn append(agg, item...)\n\t}, []int{})\n\n\tfmt.Printf(\"%v\", result)\n\t// Output: [4 5 2 3 0 1]\n}\n\nfunc ExampleReduceRightErr() {\n\tlist := [][]int{{0, 1}, {2, 3}, {4, 5}}\n\n\t_, err := ReduceRightErr(list, func(agg, item []int, index int) ([]int, error) {\n\t\tif index == 0 {\n\t\t\treturn nil, errors.New(\"index 0 is not allowed\")\n\t\t}\n\t\treturn append(agg, item...), nil\n\t}, []int{})\n\n\tfmt.Printf(\"%v\", err)\n\t// Output: index 0 is not allowed\n}\n\nfunc ExampleForEach() {\n\tlist := []int64{1, 2, 3, 4}\n\n\tForEach(list, func(x int64, _ int) {\n\t\tfmt.Println(x)\n\t})\n\n\t// Output:\n\t// 1\n\t// 2\n\t// 3\n\t// 4\n}\n\nfunc ExampleForEachWhile() {\n\tlist := []int64{1, 2, -math.MaxInt, 4}\n\n\tForEachWhile(list, func(x int64, _ int) bool {\n\t\tif x < 0 {\n\t\t\treturn false\n\t\t}\n\t\tfmt.Println(x)\n\t\treturn true\n\t})\n\n\t// Output:\n\t// 1\n\t// 2\n}\n\nfunc ExampleTimes() {\n\tresult := Times(3, func(i int) string {\n\t\treturn strconv.FormatInt(int64(i), 10)\n\t})\n\n\tfmt.Printf(\"%v\", result)\n\t// Output: [0 1 2]\n}\n\nfunc ExampleUniq() {\n\tlist := []int{1, 2, 2, 1}\n\n\tresult := Uniq(list)\n\n\tfmt.Printf(\"%v\", result)\n\t// Output: [1 2]\n}\n\nfunc ExampleUniqBy() {\n\tlist := []int{0, 1, 2, 3, 4, 5}\n\n\tresult := UniqBy(list, func(i int) int {\n\t\treturn i % 3\n\t})\n\n\tfmt.Printf(\"%v\", result)\n\t// Output: [0 1 2]\n}\n\nfunc ExampleUniqByErr() {\n\tlist := []int{0, 1, 2, 3, 4, 5}\n\n\t_, err := UniqByErr(list, func(i int) (int, error) {\n\t\tif i == 3 {\n\t\t\treturn 0, errors.New(\"number 3 is not allowed\")\n\t\t}\n\t\treturn i % 3, nil\n\t})\n\n\tfmt.Printf(\"%v\", err)\n\t// Output: number 3 is not allowed\n}\n\nfunc ExampleGroupBy() {\n\tlist := []int{0, 1, 2, 3, 4, 5}\n\n\tresult := GroupBy(list, func(i int) int {\n\t\treturn i % 3\n\t})\n\n\tfmt.Printf(\"%v\\n\", result[0])\n\tfmt.Printf(\"%v\\n\", result[1])\n\tfmt.Printf(\"%v\\n\", result[2])\n\t// Output:\n\t// [0 3]\n\t// [1 4]\n\t// [2 5]\n}\n\nfunc ExampleGroupByErr() {\n\tlist := []int{0, 1, 2, 3, 4, 5}\n\n\t_, err := GroupByErr(list, func(i int) (int, error) {\n\t\tif i == 3 {\n\t\t\treturn 0, errors.New(\"number 3 is not allowed\")\n\t\t}\n\t\treturn i % 3, nil\n\t})\n\n\tfmt.Printf(\"%v\", err)\n\t// Output: number 3 is not allowed\n}\n\nfunc ExampleGroupByMap() {\n\tlist := []int{0, 1, 2, 3, 4, 5}\n\n\tresult := GroupByMap(list, func(i int) (int, int) {\n\t\treturn i % 3, i * 2\n\t})\n\n\tfmt.Printf(\"%v\\n\", result[0])\n\tfmt.Printf(\"%v\\n\", result[1])\n\tfmt.Printf(\"%v\\n\", result[2])\n\t// Output:\n\t// [0 6]\n\t// [2 8]\n\t// [4 10]\n}\n\nfunc ExampleGroupByMapErr() {\n\tlist := []int{0, 1, 2, 3, 4, 5}\n\n\t_, err := GroupByMapErr(list, func(i int) (int, int, error) {\n\t\tif i == 3 {\n\t\t\treturn 0, 0, errors.New(\"number 3 is not allowed\")\n\t\t}\n\t\treturn i % 3, i * 2, nil\n\t})\n\n\tfmt.Printf(\"%v\", err)\n\t// Output: number 3 is not allowed\n}\n\nfunc ExampleChunk() {\n\tlist := []int{0, 1, 2, 3, 4}\n\n\tresult := Chunk(list, 2)\n\n\tfor _, item := range result {\n\t\tfmt.Printf(\"%v\\n\", item)\n\t}\n\t// Output:\n\t// [0 1]\n\t// [2 3]\n\t// [4]\n}\n\nfunc ExampleWindow() {\n\tlist := []int{1, 2, 3, 4, 5}\n\n\tresult := Window(list, 3)\n\n\tfor _, item := range result {\n\t\tfmt.Printf(\"%v\\n\", item)\n\t}\n\t// Output:\n\t// [1 2 3]\n\t// [2 3 4]\n\t// [3 4 5]\n}\n\nfunc ExampleSliding() {\n\tlist := []int{1, 2, 3, 4, 5, 6, 7, 8}\n\n\t// Overlapping windows (step < size)\n\tresult1 := Sliding(list, 3, 1)\n\tfmt.Printf(\"Overlapping: %v\\n\", result1)\n\n\t// Non-overlapping windows (step == size, like Chunk)\n\tresult2 := Sliding(list, 3, 3)\n\tfmt.Printf(\"Non-overlapping: %v\\n\", result2)\n\n\t// Step > size (skipping elements)\n\tresult3 := Sliding(list, 2, 3)\n\tfmt.Printf(\"With step: %v\\n\", result3)\n\n\t// Output:\n\t// Overlapping: [[1 2 3] [2 3 4] [3 4 5] [4 5 6] [5 6 7] [6 7 8]]\n\t// Non-overlapping: [[1 2 3] [4 5 6]]\n\t// With step: [[1 2] [4 5] [7 8]]\n}\n\nfunc ExamplePartitionBy() {\n\tlist := []int{-2, -1, 0, 1, 2, 3, 4}\n\n\tresult := PartitionBy(list, func(x int) string {\n\t\tif x < 0 {\n\t\t\treturn \"negative\"\n\t\t} else if x%2 == 0 {\n\t\t\treturn \"even\"\n\t\t}\n\t\treturn \"odd\"\n\t})\n\n\tfor _, item := range result {\n\t\tfmt.Printf(\"%v\\n\", item)\n\t}\n\t// Output:\n\t// [-2 -1]\n\t// [0 2 4]\n\t// [1 3]\n}\n\nfunc ExamplePartitionByErr() {\n\tlist := []int{-2, -1, 0, 1, 2, 3, 4}\n\n\t_, err := PartitionByErr(list, func(x int) (string, error) {\n\t\tif x == 0 {\n\t\t\treturn \"\", errors.New(\"zero is not allowed\")\n\t\t}\n\t\tif x < 0 {\n\t\t\treturn \"negative\", nil\n\t\t} else if x%2 == 0 {\n\t\t\treturn \"even\", nil\n\t\t}\n\t\treturn \"odd\", nil\n\t})\n\n\tfmt.Printf(\"%v\", err)\n\t// Output: zero is not allowed\n}\n\nfunc ExampleFlatten() {\n\tlist := [][]int{{0, 1, 2}, {3, 4, 5}}\n\n\tresult := Flatten(list)\n\n\tfmt.Printf(\"%v\", result)\n\t// Output: [0 1 2 3 4 5]\n}\n\nfunc ExampleConcat() {\n\tlist := []int{0, 1, 2, 3, 4, 5}\n\n\tresult := Concat(list, list)\n\n\tfmt.Printf(\"%v\", result)\n\t// Output: [0 1 2 3 4 5 0 1 2 3 4 5]\n}\n\nfunc ExampleInterleave() {\n\tlist1 := [][]int{{1, 4, 7}, {2, 5, 8}, {3, 6, 9}}\n\tlist2 := [][]int{{1}, {2, 5, 8}, {3, 6}, {4, 7, 9, 10}}\n\n\tresult1 := Interleave(list1...)\n\tresult2 := Interleave(list2...)\n\n\tfmt.Printf(\"%v\\n\", result1)\n\tfmt.Printf(\"%v\\n\", result2)\n\t// Output:\n\t// [1 2 3 4 5 6 7 8 9]\n\t// [1 2 3 4 5 6 7 8 9 10]\n}\n\nfunc ExampleShuffle() {\n\tlist := []int{0, 1, 2, 3, 4, 5}\n\n\tresult := Shuffle(list)\n\n\tfmt.Printf(\"%v\", result)\n}\n\nfunc ExampleReverse() {\n\tlist := []int{0, 1, 2, 3, 4, 5}\n\n\tresult := Reverse(list)\n\n\tfmt.Printf(\"%v\", result)\n\t// Output: [5 4 3 2 1 0]\n}\n\nfunc ExampleFill() {\n\tlist := []foo{{\"a\"}, {\"a\"}}\n\n\tresult := Fill(list, foo{\"b\"})\n\n\tfmt.Printf(\"%v\", result)\n\t// Output: [{b} {b}]\n}\n\nfunc ExampleRepeat() {\n\tresult := Repeat(2, foo{\"a\"})\n\n\tfmt.Printf(\"%v\", result)\n\t// Output: [{a} {a}]\n}\n\nfunc ExampleRepeatBy() {\n\tresult := RepeatBy(5, func(i int) string {\n\t\treturn strconv.FormatInt(int64(math.Pow(float64(i), 2)), 10)\n\t})\n\n\tfmt.Printf(\"%v\", result)\n\t// Output: [0 1 4 9 16]\n}\n\nfunc ExampleRepeatByErr() {\n\tresult, err := RepeatByErr(5, func(i int) (string, error) {\n\t\tif i == 3 {\n\t\t\treturn \"\", errors.New(\"index 3 is not allowed\")\n\t\t}\n\t\treturn fmt.Sprintf(\"item-%d\", i), nil\n\t})\n\n\tfmt.Printf(\"%d %v\", len(result), err)\n\t// Output: 0 index 3 is not allowed\n}\n\nfunc ExampleKeyBy() {\n\tlist := []string{\"a\", \"aa\", \"aaa\"}\n\n\tresult := KeyBy(list, func(str string) int {\n\t\treturn len(str)\n\t})\n\n\tfmt.Printf(\"%v\", result)\n\t// Output: map[1:a 2:aa 3:aaa]\n}\n\nfunc ExampleKeyByErr() {\n\tlist := []string{\"a\", \"aa\", \"aaa\"}\n\n\t_, err := KeyByErr(list, func(str string) (int, error) {\n\t\tif str == \"aa\" {\n\t\t\treturn 0, errors.New(\"aa is not allowed\")\n\t\t}\n\t\treturn len(str), nil\n\t})\n\n\tfmt.Printf(\"%v\", err)\n\t// Output: aa is not allowed\n}\n\nfunc ExampleSliceToMap() {\n\tlist := []string{\"a\", \"aa\", \"aaa\"}\n\n\tresult := SliceToMap(list, func(str string) (string, int) {\n\t\treturn str, len(str)\n\t})\n\n\tfmt.Printf(\"%v\", result)\n\t// Output: map[a:1 aa:2 aaa:3]\n}\n\nfunc ExampleFilterSliceToMap() {\n\tlist := []string{\"a\", \"aa\", \"aaa\"}\n\n\tresult := FilterSliceToMap(list, func(str string) (string, int, bool) {\n\t\treturn str, len(str), len(str) > 1\n\t})\n\n\tfmt.Printf(\"%v\", result)\n\t// Output: map[aa:2 aaa:3]\n}\n\nfunc ExampleKeyify() {\n\tlist := []string{\"a\", \"a\", \"b\", \"b\", \"d\"}\n\n\tset := Keyify(list)\n\t_, ok1 := set[\"a\"]\n\t_, ok2 := set[\"c\"]\n\tfmt.Printf(\"%v\\n\", ok1)\n\tfmt.Printf(\"%v\\n\", ok2)\n\tfmt.Printf(\"%v\\n\", set)\n\n\t// Output:\n\t// true\n\t// false\n\t// map[a:{} b:{} d:{}]\n}\n\nfunc ExampleDrop() {\n\tlist := []int{0, 1, 2, 3, 4, 5}\n\n\tresult := Drop(list, 2)\n\n\tfmt.Printf(\"%v\", result)\n\t// Output: [2 3 4 5]\n}\n\nfunc ExampleDropRight() {\n\tlist := []int{0, 1, 2, 3, 4, 5}\n\n\tresult := DropRight(list, 2)\n\n\tfmt.Printf(\"%v\", result)\n\t// Output: [0 1 2 3]\n}\n\nfunc ExampleDropWhile() {\n\tlist := []int{0, 1, 2, 3, 4, 5}\n\n\tresult := DropWhile(list, func(val int) bool {\n\t\treturn val < 2\n\t})\n\n\tfmt.Printf(\"%v\", result)\n\t// Output: [2 3 4 5]\n}\n\nfunc ExampleDropRightWhile() {\n\tlist := []int{0, 1, 2, 3, 4, 5}\n\n\tresult := DropRightWhile(list, func(val int) bool {\n\t\treturn val > 2\n\t})\n\n\tfmt.Printf(\"%v\", result)\n\t// Output: [0 1 2]\n}\n\nfunc ExampleTake() {\n\tlist := []int{0, 1, 2, 3, 4, 5}\n\n\tresult := Take(list, 3)\n\n\tfmt.Printf(\"%v\", result)\n\t// Output: [0 1 2]\n}\n\nfunc ExampleTakeWhile() {\n\tlist := []int{0, 1, 2, 3, 4, 5}\n\n\tresult := TakeWhile(list, func(val int) bool {\n\t\treturn val < 3\n\t})\n\n\tfmt.Printf(\"%v\", result)\n\t// Output: [0 1 2]\n}\n\nfunc ExampleTakeFilter() {\n\tlist := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}\n\n\tresult := TakeFilter(\n\t\tlist, 3, func(val, index int) bool {\n\t\t\treturn val%2 == 0\n\t\t},\n\t)\n\n\tfmt.Printf(\"%v\", result)\n\t// Output: [2 4 6]\n}\n\nfunc ExampleDropByIndex() {\n\tlist := []int{0, 1, 2, 3, 4, 5}\n\n\tresult := DropByIndex(list, 2)\n\n\tfmt.Printf(\"%v\", result)\n\t// Output: [0 1 3 4 5]\n}\n\nfunc ExampleReject() {\n\tlist := []int{0, 1, 2, 3, 4, 5}\n\n\tresult := Reject(list, func(x, _ int) bool {\n\t\treturn x%2 == 0\n\t})\n\n\tfmt.Printf(\"%v\", result)\n\t// Output: [1 3 5]\n}\n\nfunc ExampleRejectErr() {\n\tlist := []int64{0, 1, 2, 3, 4, 5}\n\n\tresult, err := RejectErr(list, func(x int64, index int) (bool, error) {\n\t\tif x == 3 {\n\t\t\treturn false, errors.New(\"number 3 is not allowed\")\n\t\t}\n\t\treturn x%2 == 0, nil\n\t})\n\tfmt.Printf(\"%v, %v\\n\", result, err)\n\n\tresult, err = RejectErr([]int64{0, 1, 2, 4, 6}, func(x int64, index int) (bool, error) {\n\t\treturn x%2 == 0, nil\n\t})\n\tfmt.Printf(\"%v, %v\\n\", result, err)\n\t// Output:\n\t// [], number 3 is not allowed\n\t// [1], <nil>\n}\n\nfunc ExampleCount() {\n\tlist := []int{0, 1, 2, 3, 4, 5, 0, 1, 2, 3}\n\n\tresult := Count(list, 2)\n\n\tfmt.Printf(\"%v\", result)\n\t// Output: 2\n}\n\nfunc ExampleCountBy() {\n\tlist := []int{0, 1, 2, 3, 4, 5, 0, 1, 2, 3}\n\n\tresult := CountBy(list, func(i int) bool {\n\t\treturn i < 4\n\t})\n\n\tfmt.Printf(\"%v\", result)\n\t// Output: 8\n}\n\nfunc ExampleCountByErr() {\n\tlist := []int{0, 1, 2, 3, 4, 5, 0, 1, 2, 3}\n\n\t_, err := CountByErr(list, func(i int) (bool, error) {\n\t\tif i == 3 {\n\t\t\treturn false, errors.New(\"number 3 is not allowed\")\n\t\t}\n\t\treturn i < 4, nil\n\t})\n\n\tfmt.Printf(\"%v\", err)\n\t// Output: number 3 is not allowed\n}\n\nfunc ExampleCountValues() {\n\tresult1 := CountValues([]int{})\n\tresult2 := CountValues([]int{1, 2})\n\tresult3 := CountValues([]int{1, 2, 2})\n\tresult4 := CountValues([]string{\"foo\", \"bar\", \"\"})\n\tresult5 := CountValues([]string{\"foo\", \"bar\", \"bar\"})\n\n\tfmt.Printf(\"%v\\n\", result1)\n\tfmt.Printf(\"%v\\n\", result2)\n\tfmt.Printf(\"%v\\n\", result3)\n\tfmt.Printf(\"%v\\n\", result4)\n\tfmt.Printf(\"%v\\n\", result5)\n\t// Output:\n\t// map[]\n\t// map[1:1 2:1]\n\t// map[1:1 2:2]\n\t// map[:1 bar:1 foo:1]\n\t// map[bar:2 foo:1]\n}\n\nfunc ExampleCountValuesBy() {\n\tisEven := func(v int) bool {\n\t\treturn v%2 == 0\n\t}\n\n\tresult1 := CountValuesBy([]int{}, isEven)\n\tresult2 := CountValuesBy([]int{1, 2}, isEven)\n\tresult3 := CountValuesBy([]int{1, 2, 2}, isEven)\n\n\tlength := func(v string) int {\n\t\treturn len(v)\n\t}\n\n\tresult4 := CountValuesBy([]string{\"foo\", \"bar\", \"\"}, length)\n\tresult5 := CountValuesBy([]string{\"foo\", \"bar\", \"bar\"}, length)\n\n\tfmt.Printf(\"%v\\n\", result1)\n\tfmt.Printf(\"%v\\n\", result2)\n\tfmt.Printf(\"%v\\n\", result3)\n\tfmt.Printf(\"%v\\n\", result4)\n\tfmt.Printf(\"%v\\n\", result5)\n\t// Output:\n\t// map[]\n\t// map[false:1 true:1]\n\t// map[false:1 true:2]\n\t// map[0:1 3:2]\n\t// map[3:3]\n}\n\nfunc ExampleSubset() {\n\tlist := []int{0, 1, 2, 3, 4, 5}\n\n\tresult := Subset(list, 2, 3)\n\n\tfmt.Printf(\"%v\", result)\n\t// Output: [2 3 4]\n}\n\nfunc ExampleSlice() {\n\tlist := []int{0, 1, 2, 3, 4, 5}\n\n\tresult := Slice(list, 1, 4)\n\tfmt.Printf(\"%v\\n\", result)\n\n\tresult = Slice(list, 4, 1)\n\tfmt.Printf(\"%v\\n\", result)\n\n\tresult = Slice(list, 4, 5)\n\tfmt.Printf(\"%v\\n\", result)\n\n\t// Output:\n\t// [1 2 3]\n\t// []\n\t// [4]\n}\n\nfunc ExampleReplace() {\n\tlist := []int{0, 1, 0, 1, 2, 3, 0}\n\n\tresult := Replace(list, 0, 42, 1)\n\tfmt.Printf(\"%v\\n\", result)\n\n\tresult = Replace(list, -1, 42, 1)\n\tfmt.Printf(\"%v\\n\", result)\n\n\tresult = Replace(list, 0, 42, 2)\n\tfmt.Printf(\"%v\\n\", result)\n\n\tresult = Replace(list, 0, 42, -1)\n\tfmt.Printf(\"%v\\n\", result)\n\n\t// Output:\n\t// [42 1 0 1 2 3 0]\n\t// [0 1 0 1 2 3 0]\n\t// [42 1 42 1 2 3 0]\n\t// [42 1 42 1 2 3 42]\n}\n\nfunc ExampleClone() {\n\tinput := []int{1, 2, 3, 4, 5}\n\n\toutput := Clone(input)\n\tinput[0] = 42\n\n\tfmt.Printf(\"%v\", output)\n\t// Output: [1 2 3 4 5]\n}\n\nfunc ExampleCompact() {\n\tlist := []string{\"\", \"foo\", \"\", \"bar\", \"\"}\n\n\tresult := Compact(list)\n\n\tfmt.Printf(\"%v\", result)\n\n\t// Output: [foo bar]\n}\n\nfunc ExampleIsSorted() {\n\tlist := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}\n\n\tresult := IsSorted(list)\n\n\tfmt.Printf(\"%v\", result)\n\n\t// Output: true\n}\n\nfunc ExampleIsSortedBy() {\n\tlist := []string{\"a\", \"bb\", \"ccc\"}\n\n\tresult := IsSortedBy(list, func(s string) int {\n\t\treturn len(s)\n\t})\n\n\tfmt.Printf(\"%v\", result)\n\n\t// Output: true\n}\n\nfunc ExampleCut() {\n\tcollection := []string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}\n\n\t// Test with valid separator\n\tbefore, after, found := Cut(collection, []string{\"b\", \"c\", \"d\"})\n\tfmt.Printf(\"Before: %v, After: %v, Found: %t\\n\", before, after, found)\n\n\t// Test with separator not found\n\tbefore2, after2, found2 := Cut(collection, []string{\"z\"})\n\tfmt.Printf(\"Before: %v, After: %v, Found: %t\\n\", before2, after2, found2)\n\n\t// Test with separator at beginning\n\tbefore3, after3, found3 := Cut(collection, []string{\"a\", \"b\"})\n\tfmt.Printf(\"Before: %v, After: %v, Found: %t\\n\", before3, after3, found3)\n\n\t// Output:\n\t// Before: [a], After: [e f g], Found: true\n\t// Before: [a b c d e f g], After: [], Found: false\n\t// Before: [], After: [c d e f g], Found: true\n}\n\nfunc ExampleCutPrefix() {\n\tcollection := []string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}\n\n\t// Test with valid prefix\n\tafter, found := CutPrefix(collection, []string{\"a\", \"b\", \"c\"})\n\tfmt.Printf(\"After: %v, Found: %t\\n\", after, found)\n\n\t// Test with prefix not found\n\tafter2, found2 := CutPrefix(collection, []string{\"b\"})\n\tfmt.Printf(\"After: %v, Found: %t\\n\", after2, found2)\n\n\t// Test with empty prefix\n\tafter3, found3 := CutPrefix(collection, []string{})\n\tfmt.Printf(\"After: %v, Found: %t\\n\", after3, found3)\n\n\t// Output:\n\t// After: [d e f g], Found: true\n\t// After: [a b c d e f g], Found: false\n\t// After: [a b c d e f g], Found: true\n}\n\nfunc ExampleCutSuffix() {\n\tcollection := []string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}\n\n\t// Test with valid suffix\n\tbefore, found := CutSuffix(collection, []string{\"f\", \"g\"})\n\tfmt.Printf(\"Before: %v, Found: %t\\n\", before, found)\n\n\t// Test with suffix not found\n\tbefore2, found2 := CutSuffix(collection, []string{\"b\"})\n\tfmt.Printf(\"Before: %v, Found: %t\\n\", before2, found2)\n\n\t// Test with empty suffix\n\tbefore3, found3 := CutSuffix(collection, []string{})\n\tfmt.Printf(\"Before: %v, Found: %t\\n\", before3, found3)\n\n\t// Output:\n\t// Before: [a b c d e], Found: true\n\t// Before: [a b c d e f g], Found: false\n\t// Before: [a b c d e f g], Found: true\n}\n\nfunc ExampleTrim() {\n\tcollection := []int{0, 1, 2, 0, 3, 0}\n\n\t// Test with valid cutset\n\tresult := Trim(collection, []int{0})\n\tfmt.Printf(\"Trim with cutset {0}: %v\\n\", result)\n\n\t// Test with string collection\n\twords := []string{\"  hello  \", \"world\", \"  \"}\n\tresult2 := Trim(words, []string{\" \"})\n\tfmt.Printf(\"Trim with string cutset: %v\\n\", result2)\n\n\t// Test with no cutset elements\n\tresult3 := Trim(collection, []int{5})\n\tfmt.Printf(\"Trim with cutset {5} (not present): %v\\n\", result3)\n\n\t// Output:\n\t// Trim with cutset {0}: [1 2 0 3]\n\t// Trim with string cutset: [  hello   world   ]\n\t// Trim with cutset {5} (not present): [0 1 2 0 3 0]\n}\n\nfunc ExampleTrimLeft() {\n\tcollection := []int{0, 1, 2, 0, 3, 0}\n\n\t// Test with valid cutset\n\tresult := TrimLeft(collection, []int{0})\n\tfmt.Printf(\"TrimLeft with cutset {0}: %v\\n\", result)\n\n\t// Test with string collection\n\twords := []string{\"  hello  \", \"world\", \"  \"}\n\tresult2 := TrimLeft(words, []string{\" \"})\n\tfmt.Printf(\"TrimLeft with string cutset: %v\\n\", result2)\n\n\t// Test with no cutset elements\n\tresult3 := TrimLeft(collection, []int{5})\n\tfmt.Printf(\"TrimLeft with cutset {5} (not present): %v\\n\", result3)\n\n\t// Output:\n\t// TrimLeft with cutset {0}: [1 2 0 3 0]\n\t// TrimLeft with string cutset: [  hello   world   ]\n\t// TrimLeft with cutset {5} (not present): [0 1 2 0 3 0]\n}\n\nfunc ExampleTrimPrefix() {\n\tcollection := []int{1, 2, 1, 2, 3}\n\n\t// Test with valid prefix\n\tresult := TrimPrefix(collection, []int{1, 2})\n\tfmt.Printf(\"TrimPrefix with prefix {1,2}: %v\\n\", result)\n\n\t// Test with string collection\n\twords := []string{\"hello\", \"hello\", \"world\"}\n\tresult2 := TrimPrefix(words, []string{\"hello\"})\n\tfmt.Printf(\"TrimPrefix with string prefix: %v\\n\", result2)\n\n\t// Test with prefix not present\n\tresult3 := TrimPrefix(collection, []int{5, 6})\n\tfmt.Printf(\"TrimPrefix with prefix {5,6} (not present): %v\\n\", result3)\n\n\t// Output:\n\t// TrimPrefix with prefix {1,2}: [3]\n\t// TrimPrefix with string prefix: [world]\n\t// TrimPrefix with prefix {5,6} (not present): [1 2 1 2 3]\n}\n\nfunc ExampleTrimRight() {\n\tcollection := []int{0, 1, 2, 0, 3, 0}\n\n\t// Test with valid cutset\n\tresult := TrimRight(collection, []int{0})\n\tfmt.Printf(\"TrimRight with cutset {0}: %v\\n\", result)\n\n\t// Test with string collection\n\twords := []string{\"  hello  \", \"world\", \"  \"}\n\tresult2 := TrimRight(words, []string{\" \"})\n\tfmt.Printf(\"TrimRight with string cutset: %v\\n\", result2)\n\n\t// Test with no cutset elements\n\tresult3 := TrimRight(collection, []int{5})\n\tfmt.Printf(\"TrimRight with cutset {5} (not present): %v\\n\", result3)\n\n\t// Output:\n\t// TrimRight with cutset {0}: [0 1 2 0 3]\n\t// TrimRight with string cutset: [  hello   world   ]\n\t// TrimRight with cutset {5} (not present): [0 1 2 0 3 0]\n}\n\nfunc ExampleTrimSuffix() {\n\tcollection := []int{1, 2, 1, 2, 3}\n\n\t// Test with valid suffix\n\tresult := TrimSuffix(collection, []int{1, 2})\n\tfmt.Printf(\"TrimSuffix with suffix {1,2}: %v\\n\", result)\n\n\t// Test with string collection\n\twords := []string{\"hello\", \"world\", \"test\"}\n\tresult2 := TrimSuffix(words, []string{\"test\"})\n\tfmt.Printf(\"TrimSuffix with string suffix: %v\\n\", result2)\n\n\t// Test with suffix not present\n\tresult3 := TrimSuffix(collection, []int{5, 6})\n\tfmt.Printf(\"TrimSuffix with suffix {5,6} (not present): %v\\n\", result3)\n\n\t// Output:\n\t// TrimSuffix with suffix {1,2}: [1 2 1 2 3]\n\t// TrimSuffix with string suffix: [hello world]\n\t// TrimSuffix with suffix {5,6} (not present): [1 2 1 2 3]\n}\n\nfunc ExampleSubstring() {\n\tresult1 := Substring(\"hello\", 2, 3)\n\tresult2 := Substring(\"hello\", -4, 3)\n\tresult3 := Substring(\"hello\", -2, math.MaxUint)\n\tresult4 := Substring(\"🏠🐶🐱\", 0, 2)\n\tresult5 := Substring(\"你好，世界\", 0, 3)\n\n\tfmt.Printf(\"%v\\n\", result1)\n\tfmt.Printf(\"%v\\n\", result2)\n\tfmt.Printf(\"%v\\n\", result3)\n\tfmt.Printf(\"%v\\n\", result4)\n\tfmt.Printf(\"%v\\n\", result5)\n\t// Output:\n\t// llo\n\t// ell\n\t// lo\n\t// 🏠🐶\n\t// 你好，\n}\n\nfunc ExampleChunkString() {\n\tresult1 := ChunkString(\"123456\", 2)\n\tresult2 := ChunkString(\"1234567\", 2)\n\tresult3 := ChunkString(\"\", 2)\n\tresult4 := ChunkString(\"1\", 2)\n\n\tfmt.Printf(\"%v\\n\", result1)\n\tfmt.Printf(\"%v\\n\", result2)\n\tfmt.Printf(\"%v\\n\", result3)\n\tfmt.Printf(\"%v\\n\", result4)\n\t// Output:\n\t// [12 34 56]\n\t// [12 34 56 7]\n\t// []\n\t// [1]\n}\n\nfunc ExampleRuneLength() {\n\tresult1, chars1 := RuneLength(\"hellô\"), len(\"hellô\")\n\tresult2, chars2 := RuneLength(\"🤘\"), len(\"🤘\")\n\n\tfmt.Printf(\"%v %v\\n\", result1, chars1)\n\tfmt.Printf(\"%v %v\\n\", result2, chars2)\n\t// Output:\n\t// 5 6\n\t// 1 4\n}\n\nfunc ExampleT2() {\n\tresult := T2(\"hello\", 2)\n\tfmt.Printf(\"%v %v\", result.A, result.B)\n\t// Output: hello 2\n}\n\nfunc ExampleT3() {\n\tresult := T3(\"hello\", 2, true)\n\tfmt.Printf(\"%v %v %v\", result.A, result.B, result.C)\n\t// Output: hello 2 true\n}\n\nfunc ExampleT4() {\n\tresult := T4(\"hello\", 2, true, foo{bar: \"bar\"})\n\tfmt.Printf(\"%v %v %v %v\", result.A, result.B, result.C, result.D)\n\t// Output: hello 2 true {bar}\n}\n\nfunc ExampleT5() {\n\tresult := T5(\"hello\", 2, true, foo{bar: \"bar\"}, 4.2)\n\tfmt.Printf(\"%v %v %v %v %v\", result.A, result.B, result.C, result.D, result.E)\n\t// Output: hello 2 true {bar} 4.2\n}\n\nfunc ExampleT6() {\n\tresult := T6(\"hello\", 2, true, foo{bar: \"bar\"}, 4.2, \"plop\")\n\tfmt.Printf(\"%v %v %v %v %v %v\", result.A, result.B, result.C, result.D, result.E, result.F)\n\t// Output: hello 2 true {bar} 4.2 plop\n}\n\nfunc ExampleT7() {\n\tresult := T7(\"hello\", 2, true, foo{bar: \"bar\"}, 4.2, \"plop\", false)\n\tfmt.Printf(\"%v %v %v %v %v %v %v\", result.A, result.B, result.C, result.D, result.E, result.F, result.G)\n\t// Output: hello 2 true {bar} 4.2 plop false\n}\n\nfunc ExampleT8() {\n\tresult := T8(\"hello\", 2, true, foo{bar: \"bar\"}, 4.2, \"plop\", false, 42)\n\tfmt.Printf(\"%v %v %v %v %v %v %v %v\", result.A, result.B, result.C, result.D, result.E, result.F, result.G, result.H)\n\t// Output: hello 2 true {bar} 4.2 plop false 42\n}\n\nfunc ExampleT9() {\n\tresult := T9(\"hello\", 2, true, foo{bar: \"bar\"}, 4.2, \"plop\", false, 42, \"hello world\")\n\tfmt.Printf(\"%v %v %v %v %v %v %v %v %v\", result.A, result.B, result.C, result.D, result.E, result.F, result.G, result.H, result.I)\n\t// Output: hello 2 true {bar} 4.2 plop false 42 hello world\n}\n\nfunc ExampleUnpack2() {\n\ta, b := Unpack2(T2(\"hello\", 2))\n\tfmt.Printf(\"%v %v\", a, b)\n\t// Output: hello 2\n}\n\nfunc ExampleUnpack3() {\n\ta, b, c := Unpack3(T3(\"hello\", 2, true))\n\tfmt.Printf(\"%v %v %v\", a, b, c)\n\t// Output: hello 2 true\n}\n\nfunc ExampleUnpack4() {\n\ta, b, c, d := Unpack4(T4(\"hello\", 2, true, foo{bar: \"bar\"}))\n\tfmt.Printf(\"%v %v %v %v\", a, b, c, d)\n\t// Output: hello 2 true {bar}\n}\n\nfunc ExampleUnpack5() {\n\ta, b, c, d, e := Unpack5(T5(\"hello\", 2, true, foo{bar: \"bar\"}, 4.2))\n\tfmt.Printf(\"%v %v %v %v %v\", a, b, c, d, e)\n\t// Output: hello 2 true {bar} 4.2\n}\n\nfunc ExampleUnpack6() {\n\ta, b, c, d, e, f := Unpack6(T6(\"hello\", 2, true, foo{bar: \"bar\"}, 4.2, \"plop\"))\n\tfmt.Printf(\"%v %v %v %v %v %v\", a, b, c, d, e, f)\n\t// Output: hello 2 true {bar} 4.2 plop\n}\n\nfunc ExampleUnpack7() {\n\ta, b, c, d, e, f, g := Unpack7(T7(\"hello\", 2, true, foo{bar: \"bar\"}, 4.2, \"plop\", false))\n\tfmt.Printf(\"%v %v %v %v %v %v %v\", a, b, c, d, e, f, g)\n\t// Output: hello 2 true {bar} 4.2 plop false\n}\n\nfunc ExampleUnpack8() {\n\ta, b, c, d, e, f, g, h := Unpack8(T8(\"hello\", 2, true, foo{bar: \"bar\"}, 4.2, \"plop\", false, 42))\n\tfmt.Printf(\"%v %v %v %v %v %v %v %v\", a, b, c, d, e, f, g, h)\n\t// Output: hello 2 true {bar} 4.2 plop false 42\n}\n\nfunc ExampleUnpack9() {\n\ta, b, c, d, e, f, g, h, i := Unpack9(T9(\"hello\", 2, true, foo{bar: \"bar\"}, 4.2, \"plop\", false, 42, \"hello world\"))\n\tfmt.Printf(\"%v %v %v %v %v %v %v %v %v\", a, b, c, d, e, f, g, h, i)\n\t// Output: hello 2 true {bar} 4.2 plop false 42 hello world\n}\n\nfunc ExampleZip2() {\n\tresult := Zip2([]string{\"hello\"}, []int{2})\n\tfmt.Printf(\"%v\", result)\n\t// Output: [{hello 2}]\n}\n\nfunc ExampleZip3() {\n\tresult := Zip3([]string{\"hello\"}, []int{2}, []bool{true})\n\tfmt.Printf(\"%v\", result)\n\t// Output: [{hello 2 true}]\n}\n\nfunc ExampleZip4() {\n\tresult := Zip4([]string{\"hello\"}, []int{2}, []bool{true}, []foo{{bar: \"bar\"}})\n\tfmt.Printf(\"%v\", result)\n\t// Output: [{hello 2 true {bar}}]\n}\n\nfunc ExampleZip5() {\n\tresult := Zip5([]string{\"hello\"}, []int{2}, []bool{true}, []foo{{bar: \"bar\"}}, []float64{4.2})\n\tfmt.Printf(\"%v\", result)\n\t// Output: [{hello 2 true {bar} 4.2}]\n}\n\nfunc ExampleZip6() {\n\tresult := Zip6([]string{\"hello\"}, []int{2}, []bool{true}, []foo{{bar: \"bar\"}}, []float64{4.2}, []string{\"plop\"})\n\tfmt.Printf(\"%v\", result)\n\t// Output: [{hello 2 true {bar} 4.2 plop}]\n}\n\nfunc ExampleZip7() {\n\tresult := Zip7([]string{\"hello\"}, []int{2}, []bool{true}, []foo{{bar: \"bar\"}}, []float64{4.2}, []string{\"plop\"}, []bool{false})\n\tfmt.Printf(\"%v\", result)\n\t// Output: [{hello 2 true {bar} 4.2 plop false}]\n}\n\nfunc ExampleZip8() {\n\tresult := Zip8([]string{\"hello\"}, []int{2}, []bool{true}, []foo{{bar: \"bar\"}}, []float64{4.2}, []string{\"plop\"}, []bool{false}, []int{42})\n\tfmt.Printf(\"%v\", result)\n\t// Output: [{hello 2 true {bar} 4.2 plop false 42}]\n}\n\nfunc ExampleZip9() {\n\tresult := Zip9([]string{\"hello\"}, []int{2}, []bool{true}, []foo{{bar: \"bar\"}}, []float64{4.2}, []string{\"plop\"}, []bool{false}, []int{42}, []string{\"hello world\"})\n\tfmt.Printf(\"%v\", result)\n\t// Output: [{hello 2 true {bar} 4.2 plop false 42 hello world}]\n}\n\nfunc ExampleUnzip2() {\n\ta, b := Unzip2([]Tuple2[string, int]{T2(\"hello\", 2)})\n\tfmt.Printf(\"%v %v\", a, b)\n\t// Output: [hello] [2]\n}\n\nfunc ExampleUnzip3() {\n\ta, b, c := Unzip3([]Tuple3[string, int, bool]{T3(\"hello\", 2, true)})\n\tfmt.Printf(\"%v %v %v\", a, b, c)\n\t// Output: [hello] [2] [true]\n}\n\nfunc ExampleUnzip4() {\n\ta, b, c, d := Unzip4([]Tuple4[string, int, bool, foo]{T4(\"hello\", 2, true, foo{bar: \"bar\"})})\n\tfmt.Printf(\"%v %v %v %v\", a, b, c, d)\n\t// Output: [hello] [2] [true] [{bar}]\n}\n\nfunc ExampleUnzip5() {\n\ta, b, c, d, e := Unzip5([]Tuple5[string, int, bool, foo, float64]{T5(\"hello\", 2, true, foo{bar: \"bar\"}, 4.2)})\n\tfmt.Printf(\"%v %v %v %v %v\", a, b, c, d, e)\n\t// Output: [hello] [2] [true] [{bar}] [4.2]\n}\n\nfunc ExampleUnzip6() {\n\ta, b, c, d, e, f := Unzip6([]Tuple6[string, int, bool, foo, float64, string]{T6(\"hello\", 2, true, foo{bar: \"bar\"}, 4.2, \"plop\")})\n\tfmt.Printf(\"%v %v %v %v %v %v\", a, b, c, d, e, f)\n\t// Output: [hello] [2] [true] [{bar}] [4.2] [plop]\n}\n\nfunc ExampleUnzip7() {\n\ta, b, c, d, e, f, g := Unzip7([]Tuple7[string, int, bool, foo, float64, string, bool]{T7(\"hello\", 2, true, foo{bar: \"bar\"}, 4.2, \"plop\", false)})\n\tfmt.Printf(\"%v %v %v %v %v %v %v\", a, b, c, d, e, f, g)\n\t// Output: [hello] [2] [true] [{bar}] [4.2] [plop] [false]\n}\n\nfunc ExampleUnzip8() {\n\ta, b, c, d, e, f, g, h := Unzip8([]Tuple8[string, int, bool, foo, float64, string, bool, int]{T8(\"hello\", 2, true, foo{bar: \"bar\"}, 4.2, \"plop\", false, 42)})\n\tfmt.Printf(\"%v %v %v %v %v %v %v %v\", a, b, c, d, e, f, g, h)\n\t// Output: [hello] [2] [true] [{bar}] [4.2] [plop] [false] [42]\n}\n\nfunc ExampleUnzip9() {\n\ta, b, c, d, e, f, g, h, i := Unzip9([]Tuple9[string, int, bool, foo, float64, string, bool, int, string]{T9(\"hello\", 2, true, foo{bar: \"bar\"}, 4.2, \"plop\", false, 42, \"hello world\")})\n\tfmt.Printf(\"%v %v %v %v %v %v %v %v %v\", a, b, c, d, e, f, g, h, i)\n\t// Output: [hello] [2] [true] [{bar}] [4.2] [plop] [false] [42] [hello world]\n}\n\nfunc ExampleUnzipByErr2() {\n\ta, b, err := UnzipByErr2([]string{\"hello\", \"error\", \"world\"}, func(str string) (string, int, error) {\n\t\tif str == \"error\" {\n\t\t\treturn \"\", 0, errors.New(\"error string not allowed\")\n\t\t}\n\t\treturn str, len(str), nil\n\t})\n\tfmt.Printf(\"%v %v %v\", len(a), len(b), err)\n\t// Output: 0 0 error string not allowed\n}\n\nfunc ExampleUnzipByErr3() {\n\ta, b, c, err := UnzipByErr3([]string{\"hello\", \"error\", \"world\"}, func(str string) (string, int, bool, error) {\n\t\tif str == \"error\" {\n\t\t\treturn \"\", 0, false, errors.New(\"error string not allowed\")\n\t\t}\n\t\treturn str, len(str), len(str) > 4, nil\n\t})\n\tfmt.Printf(\"%v %v %v %v\", len(a), len(b), len(c), err)\n\t// Output: 0 0 0 error string not allowed\n}\n\nfunc ExampleUnzipByErr4() {\n\ta, b, c, d, err := UnzipByErr4([]string{\"hello\", \"error\", \"world\"}, func(str string) (string, int, bool, float32, error) {\n\t\tif str == \"error\" {\n\t\t\treturn \"\", 0, false, 0, errors.New(\"error string not allowed\")\n\t\t}\n\t\treturn str, len(str), len(str) > 4, float32(len(str)), nil\n\t})\n\tfmt.Printf(\"%v %v %v %v %v\", len(a), len(b), len(c), len(d), err)\n\t// Output: 0 0 0 0 error string not allowed\n}\n\nfunc ExampleUnzipByErr5() {\n\ta, b, c, d, e, err := UnzipByErr5([]string{\"hello\", \"error\", \"world\"}, func(str string) (string, int, bool, float32, float64, error) {\n\t\tif str == \"error\" {\n\t\t\treturn \"\", 0, false, 0, 0, errors.New(\"error string not allowed\")\n\t\t}\n\t\treturn str, len(str), len(str) > 4, float32(len(str)), float64(len(str)), nil\n\t})\n\tfmt.Printf(\"%v %v %v %v %v %v\", len(a), len(b), len(c), len(d), len(e), err)\n\t// Output: 0 0 0 0 0 error string not allowed\n}\n\nfunc ExampleUnzipByErr6() {\n\ta, b, c, d, e, f, err := UnzipByErr6([]string{\"hello\", \"error\", \"world\"}, func(str string) (string, int, bool, float32, float64, int8, error) {\n\t\tif str == \"error\" {\n\t\t\treturn \"\", 0, false, 0, 0, 0, errors.New(\"error string not allowed\")\n\t\t}\n\t\treturn str, len(str), len(str) > 4, float32(len(str)), float64(len(str)), int8(len(str)), nil\n\t})\n\tfmt.Printf(\"%v %v %v %v %v %v %v\", len(a), len(b), len(c), len(d), len(e), len(f), err)\n\t// Output: 0 0 0 0 0 0 error string not allowed\n}\n\nfunc ExampleUnzipByErr7() {\n\ta, b, c, d, e, f, g, err := UnzipByErr7([]string{\"hello\", \"error\", \"world\"}, func(str string) (string, int, bool, float32, float64, int8, int16, error) {\n\t\tif str == \"error\" {\n\t\t\treturn \"\", 0, false, 0, 0, 0, 0, errors.New(\"error string not allowed\")\n\t\t}\n\t\treturn str, len(str), len(str) > 4, float32(len(str)), float64(len(str)), int8(len(str)), int16(len(str)), nil\n\t})\n\tfmt.Printf(\"%v %v %v %v %v %v %v %v\", len(a), len(b), len(c), len(d), len(e), len(f), len(g), err)\n\t// Output: 0 0 0 0 0 0 0 error string not allowed\n}\n\nfunc ExampleUnzipByErr8() {\n\ta, b, c, d, e, f, g, h, err := UnzipByErr8([]string{\"hello\", \"error\", \"world\"}, func(str string) (string, int, bool, float32, float64, int8, int16, int32, error) {\n\t\tif str == \"error\" {\n\t\t\treturn \"\", 0, false, 0, 0, 0, 0, 0, errors.New(\"error string not allowed\")\n\t\t}\n\t\treturn str, len(str), len(str) > 4, float32(len(str)), float64(len(str)), int8(len(str)), int16(len(str)), int32(len(str)), nil\n\t})\n\tfmt.Printf(\"%v %v %v %v %v %v %v %v %v\", len(a), len(b), len(c), len(d), len(e), len(f), len(g), len(h), err)\n\t// Output: 0 0 0 0 0 0 0 0 error string not allowed\n}\n\nfunc ExampleUnzipByErr9() {\n\ta, b, c, d, e, f, g, h, i, err := UnzipByErr9([]string{\"hello\", \"error\", \"world\"}, func(str string) (string, int, bool, float32, float64, int8, int16, int32, int64, error) {\n\t\tif str == \"error\" {\n\t\t\treturn \"\", 0, false, 0, 0, 0, 0, 0, 0, errors.New(\"error string not allowed\")\n\t\t}\n\t\treturn str, len(str), len(str) > 4, float32(len(str)), float64(len(str)), int8(len(str)), int16(len(str)), int32(len(str)), int64(len(str)), nil\n\t})\n\tfmt.Printf(\"%v %v %v %v %v %v %v %v %v %v\", len(a), len(b), len(c), len(d), len(e), len(f), len(g), len(h), len(i), err)\n\t// Output: 0 0 0 0 0 0 0 0 0 error string not allowed\n}\n\nfunc ExampleCrossJoin2() {\n\tresult := CrossJoin2([]string{\"a\", \"b\"}, []int{1, 2, 3, 4})\n\tfor _, r := range result {\n\t\tfmt.Printf(\"%v\\n\", r)\n\t}\n\t// Output:\n\t// {a 1}\n\t// {a 2}\n\t// {a 3}\n\t// {a 4}\n\t// {b 1}\n\t// {b 2}\n\t// {b 3}\n\t// {b 4}\n}\n\nfunc ExampleCrossJoin3() {\n\tresult := CrossJoin3([]string{\"a\", \"b\"}, []int{1, 2, 3, 4}, []bool{true, false})\n\tfor _, r := range result {\n\t\tfmt.Printf(\"%v\\n\", r)\n\t}\n\t// Output:\n\t// {a 1 true}\n\t// {a 1 false}\n\t// {a 2 true}\n\t// {a 2 false}\n\t// {a 3 true}\n\t// {a 3 false}\n\t// {a 4 true}\n\t// {a 4 false}\n\t// {b 1 true}\n\t// {b 1 false}\n\t// {b 2 true}\n\t// {b 2 false}\n\t// {b 3 true}\n\t// {b 3 false}\n\t// {b 4 true}\n\t// {b 4 false}\n}\n\nfunc ExampleCrossJoin4() {\n\tresult := CrossJoin4([]string{\"a\", \"b\"}, []int{1, 2, 3, 4}, []bool{true, false}, []foo{{bar: \"bar\"}})\n\tfor _, r := range result {\n\t\tfmt.Printf(\"%v\\n\", r)\n\t}\n\t// Output:\n\t// {a 1 true {bar}}\n\t// {a 1 false {bar}}\n\t// {a 2 true {bar}}\n\t// {a 2 false {bar}}\n\t// {a 3 true {bar}}\n\t// {a 3 false {bar}}\n\t// {a 4 true {bar}}\n\t// {a 4 false {bar}}\n\t// {b 1 true {bar}}\n\t// {b 1 false {bar}}\n\t// {b 2 true {bar}}\n\t// {b 2 false {bar}}\n\t// {b 3 true {bar}}\n\t// {b 3 false {bar}}\n\t// {b 4 true {bar}}\n\t// {b 4 false {bar}}\n}\n\nfunc ExampleCrossJoin5() {\n\tresult := CrossJoin5([]string{\"a\", \"b\"}, []int{1, 2, 3, 4}, []bool{true, false}, []foo{{bar: \"bar\"}}, []float64{4.2})\n\tfor _, r := range result {\n\t\tfmt.Printf(\"%v\\n\", r)\n\t}\n\t// Output:\n\t// {a 1 true {bar} 4.2}\n\t// {a 1 false {bar} 4.2}\n\t// {a 2 true {bar} 4.2}\n\t// {a 2 false {bar} 4.2}\n\t// {a 3 true {bar} 4.2}\n\t// {a 3 false {bar} 4.2}\n\t// {a 4 true {bar} 4.2}\n\t// {a 4 false {bar} 4.2}\n\t// {b 1 true {bar} 4.2}\n\t// {b 1 false {bar} 4.2}\n\t// {b 2 true {bar} 4.2}\n\t// {b 2 false {bar} 4.2}\n\t// {b 3 true {bar} 4.2}\n\t// {b 3 false {bar} 4.2}\n\t// {b 4 true {bar} 4.2}\n\t// {b 4 false {bar} 4.2}\n}\n\nfunc ExampleCrossJoin6() {\n\tresult := CrossJoin6([]string{\"a\", \"b\"}, []int{1, 2, 3, 4}, []bool{true, false}, []foo{{bar: \"bar\"}}, []float64{4.2}, []string{\"plop\"})\n\tfor _, r := range result {\n\t\tfmt.Printf(\"%v\\n\", r)\n\t}\n\t// Output:\n\t// {a 1 true {bar} 4.2 plop}\n\t// {a 1 false {bar} 4.2 plop}\n\t// {a 2 true {bar} 4.2 plop}\n\t// {a 2 false {bar} 4.2 plop}\n\t// {a 3 true {bar} 4.2 plop}\n\t// {a 3 false {bar} 4.2 plop}\n\t// {a 4 true {bar} 4.2 plop}\n\t// {a 4 false {bar} 4.2 plop}\n\t// {b 1 true {bar} 4.2 plop}\n\t// {b 1 false {bar} 4.2 plop}\n\t// {b 2 true {bar} 4.2 plop}\n\t// {b 2 false {bar} 4.2 plop}\n\t// {b 3 true {bar} 4.2 plop}\n\t// {b 3 false {bar} 4.2 plop}\n\t// {b 4 true {bar} 4.2 plop}\n\t// {b 4 false {bar} 4.2 plop}\n}\n\nfunc ExampleCrossJoin7() {\n\tresult := CrossJoin7([]string{\"a\", \"b\"}, []int{1, 2, 3, 4}, []bool{true, false}, []foo{{bar: \"bar\"}}, []float64{4.2}, []string{\"plop\"}, []bool{false})\n\tfor _, r := range result {\n\t\tfmt.Printf(\"%v\\n\", r)\n\t}\n\t// Output:\n\t// {a 1 true {bar} 4.2 plop false}\n\t// {a 1 false {bar} 4.2 plop false}\n\t// {a 2 true {bar} 4.2 plop false}\n\t// {a 2 false {bar} 4.2 plop false}\n\t// {a 3 true {bar} 4.2 plop false}\n\t// {a 3 false {bar} 4.2 plop false}\n\t// {a 4 true {bar} 4.2 plop false}\n\t// {a 4 false {bar} 4.2 plop false}\n\t// {b 1 true {bar} 4.2 plop false}\n\t// {b 1 false {bar} 4.2 plop false}\n\t// {b 2 true {bar} 4.2 plop false}\n\t// {b 2 false {bar} 4.2 plop false}\n\t// {b 3 true {bar} 4.2 plop false}\n\t// {b 3 false {bar} 4.2 plop false}\n\t// {b 4 true {bar} 4.2 plop false}\n\t// {b 4 false {bar} 4.2 plop false}\n}\n\nfunc ExampleCrossJoin8() {\n\tresult := CrossJoin8([]string{\"a\", \"b\"}, []int{1, 2, 3, 4}, []bool{true, false}, []foo{{bar: \"bar\"}}, []float64{4.2}, []string{\"plop\"}, []bool{false}, []int{42})\n\tfor _, r := range result {\n\t\tfmt.Printf(\"%v\\n\", r)\n\t}\n\t// Output:\n\t// {a 1 true {bar} 4.2 plop false 42}\n\t// {a 1 false {bar} 4.2 plop false 42}\n\t// {a 2 true {bar} 4.2 plop false 42}\n\t// {a 2 false {bar} 4.2 plop false 42}\n\t// {a 3 true {bar} 4.2 plop false 42}\n\t// {a 3 false {bar} 4.2 plop false 42}\n\t// {a 4 true {bar} 4.2 plop false 42}\n\t// {a 4 false {bar} 4.2 plop false 42}\n\t// {b 1 true {bar} 4.2 plop false 42}\n\t// {b 1 false {bar} 4.2 plop false 42}\n\t// {b 2 true {bar} 4.2 plop false 42}\n\t// {b 2 false {bar} 4.2 plop false 42}\n\t// {b 3 true {bar} 4.2 plop false 42}\n\t// {b 3 false {bar} 4.2 plop false 42}\n\t// {b 4 true {bar} 4.2 plop false 42}\n\t// {b 4 false {bar} 4.2 plop false 42}\n}\n\nfunc ExampleCrossJoin9() {\n\tresult := CrossJoin9([]string{\"a\", \"b\"}, []int{1, 2, 3, 4}, []bool{true, false}, []foo{{bar: \"bar\"}}, []float64{4.2}, []string{\"plop\"}, []bool{false}, []int{42}, []string{\"hello world\"})\n\tfor _, r := range result {\n\t\tfmt.Printf(\"%v\\n\", r)\n\t}\n\t// Output:\n\t// {a 1 true {bar} 4.2 plop false 42 hello world}\n\t// {a 1 false {bar} 4.2 plop false 42 hello world}\n\t// {a 2 true {bar} 4.2 plop false 42 hello world}\n\t// {a 2 false {bar} 4.2 plop false 42 hello world}\n\t// {a 3 true {bar} 4.2 plop false 42 hello world}\n\t// {a 3 false {bar} 4.2 plop false 42 hello world}\n\t// {a 4 true {bar} 4.2 plop false 42 hello world}\n\t// {a 4 false {bar} 4.2 plop false 42 hello world}\n\t// {b 1 true {bar} 4.2 plop false 42 hello world}\n\t// {b 1 false {bar} 4.2 plop false 42 hello world}\n\t// {b 2 true {bar} 4.2 plop false 42 hello world}\n\t// {b 2 false {bar} 4.2 plop false 42 hello world}\n\t// {b 3 true {bar} 4.2 plop false 42 hello world}\n\t// {b 3 false {bar} 4.2 plop false 42 hello world}\n\t// {b 4 true {bar} 4.2 plop false 42 hello world}\n\t// {b 4 false {bar} 4.2 plop false 42 hello world}\n}\n\nfunc ExampleCrossJoinBy2() {\n\tresult := CrossJoinBy2([]string{\"a\", \"b\"}, []int{1, 2, 3, 4}, func(a string, b int) string {\n\t\treturn fmt.Sprintf(\"%v-%v\", a, b)\n\t})\n\tfor _, r := range result {\n\t\tfmt.Printf(\"%v\\n\", r)\n\t}\n\t// Output:\n\t// a-1\n\t// a-2\n\t// a-3\n\t// a-4\n\t// b-1\n\t// b-2\n\t// b-3\n\t// b-4\n}\n\nfunc ExampleCrossJoinBy3() {\n\tresult := CrossJoinBy3([]string{\"a\", \"b\"}, []int{1, 2, 3, 4}, []bool{true, false}, func(a string, b int, c bool) string {\n\t\treturn fmt.Sprintf(\"%v-%v-%v\", a, b, c)\n\t})\n\tfor _, r := range result {\n\t\tfmt.Printf(\"%v\\n\", r)\n\t}\n\t// Output:\n\t// a-1-true\n\t// a-1-false\n\t// a-2-true\n\t// a-2-false\n\t// a-3-true\n\t// a-3-false\n\t// a-4-true\n\t// a-4-false\n\t// b-1-true\n\t// b-1-false\n\t// b-2-true\n\t// b-2-false\n\t// b-3-true\n\t// b-3-false\n\t// b-4-true\n\t// b-4-false\n}\n\nfunc ExampleCrossJoinBy4() {\n\tresult := CrossJoinBy4([]string{\"a\", \"b\"}, []int{1, 2, 3, 4}, []bool{true, false}, []foo{{bar: \"bar\"}}, func(a string, b int, c bool, d foo) string {\n\t\treturn fmt.Sprintf(\"%v-%v-%v-%v\", a, b, c, d)\n\t})\n\tfor _, r := range result {\n\t\tfmt.Printf(\"%v\\n\", r)\n\t}\n\t// Output:\n\t// a-1-true-{bar}\n\t// a-1-false-{bar}\n\t// a-2-true-{bar}\n\t// a-2-false-{bar}\n\t// a-3-true-{bar}\n\t// a-3-false-{bar}\n\t// a-4-true-{bar}\n\t// a-4-false-{bar}\n\t// b-1-true-{bar}\n\t// b-1-false-{bar}\n\t// b-2-true-{bar}\n\t// b-2-false-{bar}\n\t// b-3-true-{bar}\n\t// b-3-false-{bar}\n\t// b-4-true-{bar}\n\t// b-4-false-{bar}\n}\n\nfunc ExampleCrossJoinBy5() {\n\tresult := CrossJoinBy5([]string{\"a\", \"b\"}, []int{1, 2, 3, 4}, []bool{true, false}, []foo{{bar: \"bar\"}}, []float64{4.2}, func(a string, b int, c bool, d foo, e float64) string {\n\t\treturn fmt.Sprintf(\"%v-%v-%v-%v-%v\", a, b, c, d, e)\n\t})\n\tfor _, r := range result {\n\t\tfmt.Printf(\"%v\\n\", r)\n\t}\n\t// Output:\n\t// a-1-true-{bar}-4.2\n\t// a-1-false-{bar}-4.2\n\t// a-2-true-{bar}-4.2\n\t// a-2-false-{bar}-4.2\n\t// a-3-true-{bar}-4.2\n\t// a-3-false-{bar}-4.2\n\t// a-4-true-{bar}-4.2\n\t// a-4-false-{bar}-4.2\n\t// b-1-true-{bar}-4.2\n\t// b-1-false-{bar}-4.2\n\t// b-2-true-{bar}-4.2\n\t// b-2-false-{bar}-4.2\n\t// b-3-true-{bar}-4.2\n\t// b-3-false-{bar}-4.2\n\t// b-4-true-{bar}-4.2\n\t// b-4-false-{bar}-4.2\n}\n\nfunc ExampleCrossJoinBy6() {\n\tresult := CrossJoinBy6([]string{\"a\", \"b\"}, []int{1, 2, 3, 4}, []bool{true, false}, []foo{{bar: \"bar\"}}, []float64{4.2}, []string{\"plop\"}, func(a string, b int, c bool, d foo, e float64, f string) string {\n\t\treturn fmt.Sprintf(\"%v-%v-%v-%v-%v-%v\", a, b, c, d, e, f)\n\t})\n\tfor _, r := range result {\n\t\tfmt.Printf(\"%v\\n\", r)\n\t}\n\t// Output:\n\t// a-1-true-{bar}-4.2-plop\n\t// a-1-false-{bar}-4.2-plop\n\t// a-2-true-{bar}-4.2-plop\n\t// a-2-false-{bar}-4.2-plop\n\t// a-3-true-{bar}-4.2-plop\n\t// a-3-false-{bar}-4.2-plop\n\t// a-4-true-{bar}-4.2-plop\n\t// a-4-false-{bar}-4.2-plop\n\t// b-1-true-{bar}-4.2-plop\n\t// b-1-false-{bar}-4.2-plop\n\t// b-2-true-{bar}-4.2-plop\n\t// b-2-false-{bar}-4.2-plop\n\t// b-3-true-{bar}-4.2-plop\n\t// b-3-false-{bar}-4.2-plop\n\t// b-4-true-{bar}-4.2-plop\n\t// b-4-false-{bar}-4.2-plop\n}\n\nfunc ExampleCrossJoinBy7() {\n\tresult := CrossJoinBy7([]string{\"a\", \"b\"}, []int{1, 2, 3, 4}, []bool{true, false}, []foo{{bar: \"bar\"}}, []float64{4.2}, []string{\"plop\"}, []bool{false}, func(a string, b int, c bool, d foo, e float64, f string, g bool) string {\n\t\treturn fmt.Sprintf(\"%v-%v-%v-%v-%v-%v-%v\", a, b, c, d, e, f, g)\n\t})\n\tfor _, r := range result {\n\t\tfmt.Printf(\"%v\\n\", r)\n\t}\n\t// Output:\n\t// a-1-true-{bar}-4.2-plop-false\n\t// a-1-false-{bar}-4.2-plop-false\n\t// a-2-true-{bar}-4.2-plop-false\n\t// a-2-false-{bar}-4.2-plop-false\n\t// a-3-true-{bar}-4.2-plop-false\n\t// a-3-false-{bar}-4.2-plop-false\n\t// a-4-true-{bar}-4.2-plop-false\n\t// a-4-false-{bar}-4.2-plop-false\n\t// b-1-true-{bar}-4.2-plop-false\n\t// b-1-false-{bar}-4.2-plop-false\n\t// b-2-true-{bar}-4.2-plop-false\n\t// b-2-false-{bar}-4.2-plop-false\n\t// b-3-true-{bar}-4.2-plop-false\n\t// b-3-false-{bar}-4.2-plop-false\n\t// b-4-true-{bar}-4.2-plop-false\n\t// b-4-false-{bar}-4.2-plop-false\n}\n\nfunc ExampleCrossJoinBy8() {\n\tresult := CrossJoinBy8([]string{\"a\", \"b\"}, []int{1, 2, 3, 4}, []bool{true, false}, []foo{{bar: \"bar\"}}, []float64{4.2}, []string{\"plop\"}, []bool{false}, []int{42}, func(a string, b int, c bool, d foo, e float64, f string, g bool, h int) string {\n\t\treturn fmt.Sprintf(\"%v-%v-%v-%v-%v-%v-%v-%v\", a, b, c, d, e, f, g, h)\n\t})\n\tfor _, r := range result {\n\t\tfmt.Printf(\"%v\\n\", r)\n\t}\n\t// Output:\n\t// a-1-true-{bar}-4.2-plop-false-42\n\t// a-1-false-{bar}-4.2-plop-false-42\n\t// a-2-true-{bar}-4.2-plop-false-42\n\t// a-2-false-{bar}-4.2-plop-false-42\n\t// a-3-true-{bar}-4.2-plop-false-42\n\t// a-3-false-{bar}-4.2-plop-false-42\n\t// a-4-true-{bar}-4.2-plop-false-42\n\t// a-4-false-{bar}-4.2-plop-false-42\n\t// b-1-true-{bar}-4.2-plop-false-42\n\t// b-1-false-{bar}-4.2-plop-false-42\n\t// b-2-true-{bar}-4.2-plop-false-42\n\t// b-2-false-{bar}-4.2-plop-false-42\n\t// b-3-true-{bar}-4.2-plop-false-42\n\t// b-3-false-{bar}-4.2-plop-false-42\n\t// b-4-true-{bar}-4.2-plop-false-42\n\t// b-4-false-{bar}-4.2-plop-false-42\n}\n\nfunc ExampleCrossJoinBy9() {\n\tresult := CrossJoinBy9([]string{\"a\", \"b\"}, []int{1, 2, 3, 4}, []bool{true, false}, []foo{{bar: \"bar\"}}, []float64{4.2}, []string{\"plop\"}, []bool{false}, []int{42}, []string{\"hello world\"}, func(a string, b int, c bool, d foo, e float64, f string, g bool, h int, i string) string {\n\t\treturn fmt.Sprintf(\"%v-%v-%v-%v-%v-%v-%v-%v-%v\", a, b, c, d, e, f, g, h, i)\n\t})\n\tfor _, r := range result {\n\t\tfmt.Printf(\"%v\\n\", r)\n\t}\n\t// Output:\n\t// a-1-true-{bar}-4.2-plop-false-42-hello world\n\t// a-1-false-{bar}-4.2-plop-false-42-hello world\n\t// a-2-true-{bar}-4.2-plop-false-42-hello world\n\t// a-2-false-{bar}-4.2-plop-false-42-hello world\n\t// a-3-true-{bar}-4.2-plop-false-42-hello world\n\t// a-3-false-{bar}-4.2-plop-false-42-hello world\n\t// a-4-true-{bar}-4.2-plop-false-42-hello world\n\t// a-4-false-{bar}-4.2-plop-false-42-hello world\n\t// b-1-true-{bar}-4.2-plop-false-42-hello world\n\t// b-1-false-{bar}-4.2-plop-false-42-hello world\n\t// b-2-true-{bar}-4.2-plop-false-42-hello world\n\t// b-2-false-{bar}-4.2-plop-false-42-hello world\n\t// b-3-true-{bar}-4.2-plop-false-42-hello world\n\t// b-3-false-{bar}-4.2-plop-false-42-hello world\n\t// b-4-true-{bar}-4.2-plop-false-42-hello world\n\t// b-4-false-{bar}-4.2-plop-false-42-hello world\n}\n\nfunc ExampleCrossJoinByErr2() {\n\tresult, err := CrossJoinByErr2([]string{\"a\", \"b\"}, []int{1, 2}, func(a string, b int) (string, error) {\n\t\tif a == \"b\" {\n\t\t\treturn \"\", errors.New(\"b not allowed\")\n\t\t}\n\t\treturn fmt.Sprintf(\"%v-%v\", a, b), nil\n\t})\n\tif err != nil {\n\t\tfmt.Printf(\"error: %v\\n\", err)\n\t\treturn\n\t}\n\tfor _, r := range result {\n\t\tfmt.Printf(\"%v\\n\", r)\n\t}\n\t// Output:\n\t// error: b not allowed\n}\n\nfunc ExampleZipByErr2() {\n\tresult, err := ZipByErr2([]string{\"a\", \"b\", \"c\"}, []int{1, 2, 3}, func(a string, b int) (string, error) {\n\t\tif a == \"b\" {\n\t\t\treturn \"\", errors.New(\"b is not allowed\")\n\t\t}\n\t\treturn fmt.Sprintf(\"%v-%v\", a, b), nil\n\t})\n\tif err != nil {\n\t\tfmt.Printf(\"error: %v\\n\", err)\n\t\treturn\n\t}\n\tfor _, r := range result {\n\t\tfmt.Printf(\"%v\\n\", r)\n\t}\n\t// Output:\n\t// error: b is not allowed\n}\n\nfunc ExampleIntersect() {\n\tresult := Intersect([]int{0, 3, 5, 7}, []int{3, 5}, []int{0, 1, 2, 0, 3, 0})\n\tfmt.Printf(\"%v\", result)\n\t// Output:\n\t// [3]\n}\n\nfunc ExampleIntersectBy() {\n\tresult := IntersectBy(strconv.Itoa, []int{0, 6, 0, 3}, []int{0, 1, 2, 3, 4, 5}, []int{0, 6})\n\tfmt.Printf(\"%v\", result)\n\t// Output:\n\t// [0]\n}\n"
  },
  {
    "path": "lo_test.go",
    "content": "package lo\n\nimport (\n\t\"fmt\"\n\t\"runtime\"\n\t\"strconv\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/samber/lo/internal/xtime\"\n\t\"go.uber.org/goleak\"\n)\n\nfunc TestMain(m *testing.M) {\n\txtime.SetClock(xtime.NewFakeClock())\n\tgoleak.VerifyTestMain(m)\n}\n\n// https://github.com/stretchr/testify/issues/1101\nfunc testWithTimeout(t *testing.T, timeout time.Duration) {\n\tt.Helper()\n\n\ttestFinished := make(chan struct{})\n\n\tt.Cleanup(func() {\n\t\tclose(testFinished)\n\t})\n\n\tline := \"\"\n\tfuncName := \"\"\n\n\tvar pc [1]uintptr\n\tn := runtime.Callers(2, pc[:])\n\tif n > 0 {\n\t\tframes := runtime.CallersFrames(pc[:])\n\t\tframe, _ := frames.Next()\n\t\tline = frame.File + \":\" + strconv.Itoa(frame.Line)\n\t\tfuncName = frame.Function\n\t}\n\n\tgo func() {\n\t\tselect {\n\t\tcase <-testFinished:\n\t\tcase <-time.After(timeout):\n\t\t\tif line == \"\" || funcName == \"\" {\n\t\t\t\tpanic(fmt.Sprintf(\"Test timed out after: %v\", timeout))\n\t\t\t}\n\t\t\tpanic(fmt.Sprintf(\"%s: Test timed out after: %v\\n%s\", funcName, timeout, line))\n\n\t\t\t// t.Errorf(\"Test timed out after: %v\", timeout)\n\t\t\t// os.Exit(1)\n\t\t}\n\t}()\n}\n\ntype foo struct {\n\tbar string\n}\n\nfunc (f foo) Clone() foo {\n\treturn foo{f.bar}\n}\n"
  },
  {
    "path": "map.go",
    "content": "package lo\n\n// Keys creates a slice of the map keys.\n// Play: https://go.dev/play/p/Uu11fHASqrU\nfunc Keys[K comparable, V any](in ...map[K]V) []K {\n\tsize := 0\n\tfor i := range in {\n\t\tsize += len(in[i])\n\t}\n\tresult := make([]K, 0, size)\n\n\tfor i := range in {\n\t\tfor k := range in[i] {\n\t\t\tresult = append(result, k)\n\t\t}\n\t}\n\n\treturn result\n}\n\n// UniqKeys creates a slice of unique keys in the map.\n// Play: https://go.dev/play/p/TPKAb6ILdHk\nfunc UniqKeys[K comparable, V any](in ...map[K]V) []K {\n\tsize := 0\n\tfor i := range in {\n\t\tsize += len(in[i])\n\t}\n\n\tseen := make(map[K]struct{}, size)\n\tresult := make([]K, 0, size)\n\n\tfor i := range in {\n\t\tfor k := range in[i] {\n\t\t\tif _, exists := seen[k]; exists {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tseen[k] = struct{}{}\n\t\t\tresult = append(result, k)\n\t\t}\n\t}\n\n\treturn result\n}\n\n// HasKey returns whether the given key exists.\n// Play: https://go.dev/play/p/aVwubIvECqS\nfunc HasKey[K comparable, V any](in map[K]V, key K) bool {\n\t_, ok := in[key]\n\treturn ok\n}\n\n// Values creates a slice of the map values.\n// Play: https://go.dev/play/p/nnRTQkzQfF6\nfunc Values[K comparable, V any](in ...map[K]V) []V {\n\tsize := 0\n\tfor i := range in {\n\t\tsize += len(in[i])\n\t}\n\tresult := make([]V, 0, size)\n\n\tfor i := range in {\n\t\tfor _, v := range in[i] {\n\t\t\tresult = append(result, v)\n\t\t}\n\t}\n\n\treturn result\n}\n\n// UniqValues creates a slice of unique values in the map.\n// Play: https://go.dev/play/p/nf6bXMh7rM3\nfunc UniqValues[K, V comparable](in ...map[K]V) []V {\n\tsize := 0\n\tfor i := range in {\n\t\tsize += len(in[i])\n\t}\n\n\tseen := make(map[V]struct{}, size)\n\tresult := make([]V, 0, size)\n\n\tfor i := range in {\n\t\tfor _, v := range in[i] {\n\t\t\tif _, exists := seen[v]; exists {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tseen[v] = struct{}{}\n\t\t\tresult = append(result, v)\n\t\t}\n\t}\n\n\treturn result\n}\n\n// ValueOr returns the value of the given key or the fallback value if the key is not present.\n// Play: https://go.dev/play/p/bAq9mHErB4V\nfunc ValueOr[K comparable, V any](in map[K]V, key K, fallback V) V {\n\tif v, ok := in[key]; ok {\n\t\treturn v\n\t}\n\treturn fallback\n}\n\n// PickBy returns same map type filtered by given predicate.\n// Play: https://go.dev/play/p/kdg8GR_QMmf\nfunc PickBy[K comparable, V any, Map ~map[K]V](in Map, predicate func(key K, value V) bool) Map {\n\tr := make(Map, len(in))\n\tfor k, v := range in {\n\t\tif predicate(k, v) {\n\t\t\tr[k] = v\n\t\t}\n\t}\n\treturn r\n}\n\n// PickByErr returns same map type filtered by given predicate.\n// It returns the first error returned by the predicate.\nfunc PickByErr[K comparable, V any, Map ~map[K]V](in Map, predicate func(key K, value V) (bool, error)) (Map, error) {\n\tr := make(Map, len(in))\n\tfor k, v := range in {\n\t\tok, err := predicate(k, v)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tif ok {\n\t\t\tr[k] = v\n\t\t}\n\t}\n\treturn r, nil\n}\n\n// PickByKeys returns same map type filtered by given keys.\n// Play: https://go.dev/play/p/R1imbuci9qU\nfunc PickByKeys[K comparable, V any, Map ~map[K]V](in Map, keys []K) Map {\n\tr := make(Map, len(keys))\n\tfor i := range keys {\n\t\tif v, ok := in[keys[i]]; ok {\n\t\t\tr[keys[i]] = v\n\t\t}\n\t}\n\treturn r\n}\n\n// PickByValues returns same map type filtered by given values.\n// Play: https://go.dev/play/p/-_PPkSbO1Kc\nfunc PickByValues[K, V comparable, Map ~map[K]V](in Map, values []V) Map {\n\tr := make(Map, len(values))\n\n\tseen := Keyify(values)\n\tfor k, v := range in {\n\t\tif _, ok := seen[v]; ok {\n\t\t\tr[k] = v\n\t\t}\n\t}\n\treturn r\n}\n\n// OmitBy returns same map type filtered by given predicate.\n// Play: https://go.dev/play/p/EtBsR43bdsd\nfunc OmitBy[K comparable, V any, Map ~map[K]V](in Map, predicate func(key K, value V) bool) Map {\n\tr := make(Map, len(in))\n\tfor k, v := range in {\n\t\tif !predicate(k, v) {\n\t\t\tr[k] = v\n\t\t}\n\t}\n\treturn r\n}\n\n// OmitByErr returns same map type filtered by given predicate.\n// It returns the first error returned by the predicate.\nfunc OmitByErr[K comparable, V any, Map ~map[K]V](in Map, predicate func(key K, value V) (bool, error)) (Map, error) {\n\tr := make(Map, len(in))\n\tfor k, v := range in {\n\t\tok, err := predicate(k, v)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tif !ok {\n\t\t\tr[k] = v\n\t\t}\n\t}\n\treturn r, nil\n}\n\n// OmitByKeys returns same map type filtered by given keys.\n// Play: https://go.dev/play/p/t1QjCrs-ysk\nfunc OmitByKeys[K comparable, V any, Map ~map[K]V](in Map, keys []K) Map {\n\tr := make(Map, len(in))\n\tfor k, v := range in {\n\t\tr[k] = v\n\t}\n\tfor i := range keys {\n\t\tdelete(r, keys[i])\n\t}\n\treturn r\n}\n\n// OmitByValues returns same map type filtered by given values.\n// Play: https://go.dev/play/p/9UYZi-hrs8j\nfunc OmitByValues[K, V comparable, Map ~map[K]V](in Map, values []V) Map {\n\tr := make(Map, len(in))\n\n\tseen := Keyify(values)\n\tfor k, v := range in {\n\t\tif _, ok := seen[v]; !ok {\n\t\t\tr[k] = v\n\t\t}\n\t}\n\n\treturn r\n}\n\n// Entries transforms a map into a slice of key/value pairs.\n// Play: https://go.dev/play/p/_t4Xe34-Nl5\nfunc Entries[K comparable, V any](in map[K]V) []Entry[K, V] {\n\tentries := make([]Entry[K, V], 0, len(in))\n\n\tfor k, v := range in {\n\t\tentries = append(entries, Entry[K, V]{\n\t\t\tKey:   k,\n\t\t\tValue: v,\n\t\t})\n\t}\n\n\treturn entries\n}\n\n// ToPairs transforms a map into a slice of key/value pairs.\n// Alias of Entries().\n// Play: https://go.dev/play/p/3Dhgx46gawJ\nfunc ToPairs[K comparable, V any](in map[K]V) []Entry[K, V] {\n\treturn Entries(in)\n}\n\n// FromEntries transforms a slice of key/value pairs into a map.\n// Play: https://go.dev/play/p/oIr5KHFGCEN\nfunc FromEntries[K comparable, V any](entries []Entry[K, V]) map[K]V {\n\tout := make(map[K]V, len(entries))\n\n\tfor i := range entries {\n\t\tout[entries[i].Key] = entries[i].Value\n\t}\n\n\treturn out\n}\n\n// FromPairs transforms a slice of key/value pairs into a map.\n// Alias of FromEntries().\n// Play: https://go.dev/play/p/oIr5KHFGCEN\nfunc FromPairs[K comparable, V any](entries []Entry[K, V]) map[K]V {\n\treturn FromEntries(entries)\n}\n\n// Invert creates a map composed of the inverted keys and values. If map\n// contains duplicate values, subsequent values overwrite property assignments\n// of previous values.\n// Play: https://go.dev/play/p/rFQ4rak6iA1\nfunc Invert[K, V comparable](in map[K]V) map[V]K {\n\tout := make(map[V]K, len(in))\n\n\tfor k, v := range in {\n\t\tout[v] = k\n\t}\n\n\treturn out\n}\n\n// Assign merges multiple maps from left to right.\n// Play: https://go.dev/play/p/VhwfJOyxf5o\nfunc Assign[K comparable, V any, Map ~map[K]V](maps ...Map) Map {\n\tcount := 0\n\tfor i := range maps {\n\t\tcount += len(maps[i])\n\t}\n\n\tout := make(Map, count)\n\tfor i := range maps {\n\t\tfor k, v := range maps[i] {\n\t\t\tout[k] = v\n\t\t}\n\t}\n\n\treturn out\n}\n\n// ChunkEntries splits a map into a slice of elements in groups of length equal to its size. If the map cannot be split evenly,\n// the final chunk will contain the remaining elements.\n// Play: https://go.dev/play/p/X_YQL6mmoD-\nfunc ChunkEntries[K comparable, V any](m map[K]V, size int) []map[K]V {\n\tif size <= 0 {\n\t\tpanic(\"lo.ChunkEntries: size must be greater than 0\")\n\t}\n\n\tcount := len(m)\n\tif count == 0 {\n\t\treturn []map[K]V{}\n\t}\n\n\tresult := make([]map[K]V, 0, ((count-1)/size)+1)\n\n\tfor k, v := range m {\n\t\tif len(result) == 0 || len(result[len(result)-1]) == size {\n\t\t\tresult = append(result, make(map[K]V, size))\n\t\t}\n\n\t\tresult[len(result)-1][k] = v\n\t}\n\n\treturn result\n}\n\n// MapKeys manipulates map keys and transforms it to a map of another type.\n// Play: https://go.dev/play/p/9_4WPIqOetJ\nfunc MapKeys[K comparable, V any, R comparable](in map[K]V, iteratee func(value V, key K) R) map[R]V {\n\tresult := make(map[R]V, len(in))\n\n\tfor k, v := range in {\n\t\tresult[iteratee(v, k)] = v\n\t}\n\n\treturn result\n}\n\n// MapKeysErr manipulates map keys and transforms it to a map of another type.\n// It returns the first error returned by the iteratee.\nfunc MapKeysErr[K comparable, V any, R comparable](in map[K]V, iteratee func(value V, key K) (R, error)) (map[R]V, error) {\n\tresult := make(map[R]V, len(in))\n\n\tfor k, v := range in {\n\t\tr, err := iteratee(v, k)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tresult[r] = v\n\t}\n\n\treturn result, nil\n}\n\n// MapValues manipulates map values and transforms it to a map of another type.\n// Play: https://go.dev/play/p/T_8xAfvcf0W\nfunc MapValues[K comparable, V, R any](in map[K]V, iteratee func(value V, key K) R) map[K]R {\n\tresult := make(map[K]R, len(in))\n\n\tfor k, v := range in {\n\t\tresult[k] = iteratee(v, k)\n\t}\n\n\treturn result\n}\n\n// MapValuesErr manipulates map values and transforms it to a map of another type.\n// It returns the first error returned by the iteratee.\nfunc MapValuesErr[K comparable, V, R any](in map[K]V, iteratee func(value V, key K) (R, error)) (map[K]R, error) {\n\tresult := make(map[K]R, len(in))\n\n\tfor k, v := range in {\n\t\tr, err := iteratee(v, k)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tresult[k] = r\n\t}\n\n\treturn result, nil\n}\n\n// MapEntries manipulates map entries and transforms it to a map of another type.\n// Play: https://go.dev/play/p/VuvNQzxKimT\nfunc MapEntries[K1 comparable, V1 any, K2 comparable, V2 any](in map[K1]V1, iteratee func(key K1, value V1) (K2, V2)) map[K2]V2 {\n\tresult := make(map[K2]V2, len(in))\n\n\tfor k1 := range in {\n\t\tk2, v2 := iteratee(k1, in[k1])\n\t\tresult[k2] = v2\n\t}\n\n\treturn result\n}\n\n// MapEntriesErr manipulates map entries and transforms it to a map of another type.\n// It returns the first error returned by the iteratee.\nfunc MapEntriesErr[K1 comparable, V1 any, K2 comparable, V2 any](in map[K1]V1, iteratee func(key K1, value V1) (K2, V2, error)) (map[K2]V2, error) {\n\tresult := make(map[K2]V2, len(in))\n\n\tfor k1 := range in {\n\t\tk2, v2, err := iteratee(k1, in[k1])\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tresult[k2] = v2\n\t}\n\n\treturn result, nil\n}\n\n// MapToSlice transforms a map into a slice based on specified iteratee.\n// Play: https://go.dev/play/p/4f5hbHyMf5h\nfunc MapToSlice[K comparable, V, R any](in map[K]V, iteratee func(key K, value V) R) []R {\n\tresult := make([]R, 0, len(in))\n\n\tfor k, v := range in {\n\t\tresult = append(result, iteratee(k, v))\n\t}\n\n\treturn result\n}\n\n// MapToSliceErr transforms a map into a slice based on specified iteratee.\n// It returns the first error returned by the iteratee.\nfunc MapToSliceErr[K comparable, V, R any](in map[K]V, iteratee func(key K, value V) (R, error)) ([]R, error) {\n\tresult := make([]R, 0, len(in))\n\n\tfor k, v := range in {\n\t\tr, err := iteratee(k, v)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tresult = append(result, r)\n\t}\n\n\treturn result, nil\n}\n\n// FilterMapToSlice transforms a map into a slice based on specified iteratee.\n// The iteratee returns a value and a boolean. If the boolean is true, the value is added to the result slice.\n// If the boolean is false, the value is not added to the result slice.\n// The order of the keys in the input map is not specified and the order of the keys in the output slice is not guaranteed.\n// Play: https://go.dev/play/p/jgsD_Kil9pV\nfunc FilterMapToSlice[K comparable, V, R any](in map[K]V, iteratee func(key K, value V) (R, bool)) []R {\n\tresult := make([]R, 0, len(in))\n\n\tfor k, v := range in {\n\t\tif v, ok := iteratee(k, v); ok {\n\t\t\tresult = append(result, v)\n\t\t}\n\t}\n\n\treturn result\n}\n\n// FilterMapToSliceErr transforms a map into a slice based on specified iteratee.\n// The iteratee returns a value, a boolean, and an error. If the boolean is true, the value is added to the result slice.\n// If the boolean is false, the value is not added to the result slice.\n// If an error is returned, iteration stops immediately and returns the error.\n// The order of the keys in the input map is not specified and the order of the keys in the output slice is not guaranteed.\n// Play: https://go.dev/play/p/YjFEORLBWvk\nfunc FilterMapToSliceErr[K comparable, V, R any](in map[K]V, iteratee func(key K, value V) (R, bool, error)) ([]R, error) {\n\tresult := make([]R, 0, len(in))\n\n\tfor k, v := range in {\n\t\tr, ok, err := iteratee(k, v)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tif ok {\n\t\t\tresult = append(result, r)\n\t\t}\n\t}\n\n\treturn result, nil\n}\n\n// FilterKeys transforms a map into a slice based on predicate returns true for specific elements.\n// It is a mix of lo.Filter() and lo.Keys().\n// Play: https://go.dev/play/p/OFlKXlPrBAe\nfunc FilterKeys[K comparable, V any](in map[K]V, predicate func(key K, value V) bool) []K {\n\tresult := make([]K, 0, len(in))\n\n\tfor k, v := range in {\n\t\tif predicate(k, v) {\n\t\t\tresult = append(result, k)\n\t\t}\n\t}\n\n\treturn result\n}\n\n// FilterValues transforms a map into a slice based on predicate returns true for specific elements.\n// It is a mix of lo.Filter() and lo.Values().\n// Play: https://go.dev/play/p/YVD5r_h-LX-\nfunc FilterValues[K comparable, V any](in map[K]V, predicate func(key K, value V) bool) []V {\n\tresult := make([]V, 0, len(in))\n\n\tfor k, v := range in {\n\t\tif predicate(k, v) {\n\t\t\tresult = append(result, v)\n\t\t}\n\t}\n\n\treturn result\n}\n\n// FilterKeysErr transforms a map into a slice of keys based on predicate that can return an error.\n// It is a mix of lo.Filter() and lo.Keys() with error handling.\n// If the predicate returns true, the key is added to the result slice.\n// If the predicate returns an error, iteration stops immediately and returns the error.\n// The order of the keys in the input map is not specified.\n// Play: https://go.dev/play/p/j2gUQzCTu4t\nfunc FilterKeysErr[K comparable, V any](in map[K]V, predicate func(key K, value V) (bool, error)) ([]K, error) {\n\tresult := make([]K, 0, len(in))\n\n\tfor k, v := range in {\n\t\tok, err := predicate(k, v)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tif ok {\n\t\t\tresult = append(result, k)\n\t\t}\n\t}\n\n\treturn result, nil\n}\n\n// FilterValuesErr transforms a map into a slice of values based on predicate that can return an error.\n// It is a mix of lo.Filter() and lo.Values() with error handling.\n// If the predicate returns true, the value is added to the result slice.\n// If the predicate returns an error, iteration stops immediately and returns the error.\n// The order of the keys in the input map is not specified.\n// Play: https://go.dev/play/p/hKvHlqLzbdE\nfunc FilterValuesErr[K comparable, V any](in map[K]V, predicate func(key K, value V) (bool, error)) ([]V, error) {\n\tresult := make([]V, 0, len(in))\n\n\tfor k, v := range in {\n\t\tok, err := predicate(k, v)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tif ok {\n\t\t\tresult = append(result, v)\n\t\t}\n\t}\n\n\treturn result, nil\n}\n"
  },
  {
    "path": "map_test.go",
    "content": "package lo\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"strconv\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestKeys(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tr1 := Keys(map[string]int{\"foo\": 1, \"bar\": 2})\n\tis.ElementsMatch(r1, []string{\"bar\", \"foo\"})\n\n\tr2 := Keys(map[string]int{})\n\tis.Empty(r2)\n\n\tr3 := Keys(map[string]int{\"foo\": 1, \"bar\": 2}, map[string]int{\"baz\": 3})\n\tis.ElementsMatch(r3, []string{\"bar\", \"baz\", \"foo\"})\n\n\tr4 := Keys[string, int]()\n\tis.Empty(r4)\n\n\tr5 := Keys(map[string]int{\"foo\": 1, \"bar\": 2}, map[string]int{\"bar\": 3})\n\tis.ElementsMatch(r5, []string{\"bar\", \"bar\", \"foo\"})\n}\n\nfunc TestUniqKeys(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tr1 := UniqKeys(map[string]int{\"foo\": 1, \"bar\": 2})\n\tis.ElementsMatch(r1, []string{\"bar\", \"foo\"})\n\n\tr2 := UniqKeys(map[string]int{})\n\tis.Empty(r2)\n\n\tr3 := UniqKeys(map[string]int{\"foo\": 1, \"bar\": 2}, map[string]int{\"baz\": 3})\n\tis.ElementsMatch(r3, []string{\"bar\", \"baz\", \"foo\"})\n\n\tr4 := UniqKeys[string, int]()\n\tis.Empty(r4)\n\n\tr5 := UniqKeys(map[string]int{\"foo\": 1, \"bar\": 2}, map[string]int{\"foo\": 1, \"bar\": 3})\n\tis.ElementsMatch(r5, []string{\"bar\", \"foo\"})\n\n\t// check order\n\tr6 := UniqKeys(map[string]int{\"foo\": 1}, map[string]int{\"bar\": 3})\n\tis.Equal([]string{\"foo\", \"bar\"}, r6)\n}\n\nfunc TestHasKey(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tr1 := HasKey(map[string]int{\"foo\": 1}, \"bar\")\n\tis.False(r1)\n\n\tr2 := HasKey(map[string]int{\"foo\": 1}, \"foo\")\n\tis.True(r2)\n}\n\nfunc TestValues(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tr1 := Values(map[string]int{\"foo\": 1, \"bar\": 2})\n\tis.ElementsMatch(r1, []int{1, 2})\n\n\tr2 := Values(map[string]int{})\n\tis.Empty(r2)\n\n\tr3 := Values(map[string]int{\"foo\": 1, \"bar\": 2}, map[string]int{\"baz\": 3})\n\tis.ElementsMatch(r3, []int{1, 2, 3})\n\n\tr4 := Values[string, int]()\n\tis.Empty(r4)\n\n\tr5 := Values(map[string]int{\"foo\": 1, \"bar\": 2}, map[string]int{\"foo\": 1, \"bar\": 3})\n\tis.ElementsMatch(r5, []int{1, 1, 2, 3})\n}\n\nfunc TestUniqValues(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tr1 := UniqValues(map[string]int{\"foo\": 1, \"bar\": 2})\n\tis.ElementsMatch(r1, []int{1, 2})\n\n\tr2 := UniqValues(map[string]int{})\n\tis.Empty(r2)\n\n\tr3 := UniqValues(map[string]int{\"foo\": 1, \"bar\": 2}, map[string]int{\"baz\": 3})\n\tis.ElementsMatch(r3, []int{1, 2, 3})\n\n\tr4 := UniqValues[string, int]()\n\tis.Empty(r4)\n\n\tr5 := UniqValues(map[string]int{\"foo\": 1, \"bar\": 2}, map[string]int{\"foo\": 1, \"bar\": 3})\n\tis.ElementsMatch(r5, []int{1, 2, 3})\n\n\tr6 := UniqValues(map[string]int{\"foo\": 1, \"bar\": 1}, map[string]int{\"foo\": 1, \"bar\": 3})\n\tis.ElementsMatch(r6, []int{1, 3})\n\n\t// check order\n\tr7 := UniqValues(map[string]int{\"foo\": 1}, map[string]int{\"bar\": 3})\n\tis.Equal([]int{1, 3}, r7)\n}\n\nfunc TestValueOr(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tr1 := ValueOr(map[string]int{\"foo\": 1}, \"bar\", 2)\n\tis.Equal(2, r1)\n\n\tr2 := ValueOr(map[string]int{\"foo\": 1}, \"foo\", 2)\n\tis.Equal(1, r2)\n}\n\nfunc TestPickBy(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tr1 := PickBy(map[string]int{\"foo\": 1, \"bar\": 2, \"baz\": 3}, func(key string, value int) bool {\n\t\treturn value%2 == 1\n\t})\n\n\tis.Equal(map[string]int{\"foo\": 1, \"baz\": 3}, r1)\n\n\ttype myMap map[string]int\n\tbefore := myMap{\"\": 0, \"foobar\": 6, \"baz\": 3}\n\tafter := PickBy(before, func(key string, value int) bool { return true })\n\tis.IsType(after, before, \"type preserved\")\n}\n\nfunc TestPickByErr(t *testing.T) {\n\tt.Parallel()\n\n\ttests := []struct {\n\t\tname          string\n\t\tinput         map[string]int\n\t\tpredicate     func(string, int) (bool, error)\n\t\twant          map[string]int\n\t\twantErr       string\n\t\twantCallCount int // 0 means don't check (maps have no order)\n\t}{\n\t\t{\n\t\t\tname:  \"filter odd values\",\n\t\t\tinput: map[string]int{\"foo\": 1, \"bar\": 2, \"baz\": 3},\n\t\t\tpredicate: func(key string, value int) (bool, error) {\n\t\t\t\treturn value%2 == 1, nil\n\t\t\t},\n\t\t\twant:          map[string]int{\"foo\": 1, \"baz\": 3},\n\t\t\twantErr:       \"\",\n\t\t\twantCallCount: 0, // map iteration order is not deterministic\n\t\t},\n\t\t{\n\t\t\tname:  \"empty map\",\n\t\t\tinput: map[string]int{},\n\t\t\tpredicate: func(key string, value int) (bool, error) {\n\t\t\t\treturn true, nil\n\t\t\t},\n\t\t\twant:          map[string]int{},\n\t\t\twantErr:       \"\",\n\t\t\twantCallCount: 0,\n\t\t},\n\t\t{\n\t\t\tname:  \"error on specific key\",\n\t\t\tinput: map[string]int{\"foo\": 1, \"bar\": 2, \"baz\": 3},\n\t\t\tpredicate: func(key string, value int) (bool, error) {\n\t\t\t\tif key == \"bar\" {\n\t\t\t\t\treturn false, errors.New(\"bar not allowed\")\n\t\t\t\t}\n\t\t\t\treturn true, nil\n\t\t\t},\n\t\t\twant:          nil,\n\t\t\twantErr:       \"bar not allowed\",\n\t\t\twantCallCount: 0, // map iteration order is not deterministic\n\t\t},\n\t\t{\n\t\t\tname:  \"filter all out\",\n\t\t\tinput: map[string]int{\"foo\": 2, \"bar\": 4, \"baz\": 6},\n\t\t\tpredicate: func(key string, value int) (bool, error) {\n\t\t\t\treturn value%2 == 1, nil\n\t\t\t},\n\t\t\twant:          map[string]int{},\n\t\t\twantErr:       \"\",\n\t\t\twantCallCount: 0,\n\t\t},\n\t\t{\n\t\t\tname:  \"filter all in\",\n\t\t\tinput: map[string]int{\"foo\": 1, \"bar\": 3, \"baz\": 5},\n\t\t\tpredicate: func(key string, value int) (bool, error) {\n\t\t\t\treturn value%2 == 1, nil\n\t\t\t},\n\t\t\twant:          map[string]int{\"foo\": 1, \"bar\": 3, \"baz\": 5},\n\t\t\twantErr:       \"\",\n\t\t\twantCallCount: 0,\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\ttt := tt // capture range variable\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\tis := assert.New(t)\n\n\t\t\tgot, err := PickByErr(tt.input, tt.predicate)\n\n\t\t\tif tt.wantErr != \"\" {\n\t\t\t\tis.Error(err)\n\t\t\t\tis.Equal(tt.wantErr, err.Error())\n\t\t\t\tis.Nil(got)\n\t\t\t} else {\n\t\t\t\tis.NoError(err)\n\t\t\t\tis.Equal(tt.want, got)\n\t\t\t}\n\t\t})\n\t}\n\n\tt.Run(\"type preserved\", func(t *testing.T) {\n\t\tt.Parallel()\n\t\tis := assert.New(t)\n\n\t\ttype myMap map[string]int\n\t\tbefore := myMap{\"\": 0, \"foobar\": 6, \"baz\": 3}\n\t\tafter, err := PickByErr(before, func(key string, value int) (bool, error) {\n\t\t\treturn true, nil\n\t\t})\n\n\t\tis.NoError(err)\n\t\tis.IsType(after, before, \"type preserved\")\n\t})\n}\n\nfunc TestPickByKeys(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tr1 := PickByKeys(map[string]int{\"foo\": 1, \"bar\": 2, \"baz\": 3}, []string{\"foo\", \"baz\", \"qux\"})\n\n\tis.Equal(map[string]int{\"foo\": 1, \"baz\": 3}, r1)\n\n\ttype myMap map[string]int\n\tbefore := myMap{\"\": 0, \"foobar\": 6, \"baz\": 3}\n\tafter := PickByKeys(before, []string{\"foobar\", \"baz\"})\n\tis.IsType(after, before, \"type preserved\")\n}\n\nfunc TestPickByValues(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tr1 := PickByValues(map[string]int{\"foo\": 1, \"bar\": 2, \"baz\": 3}, []int{1, 3})\n\n\tis.Equal(map[string]int{\"foo\": 1, \"baz\": 3}, r1)\n\n\ttype myMap map[string]int\n\tbefore := myMap{\"\": 0, \"foobar\": 6, \"baz\": 3}\n\tafter := PickByValues(before, []int{0, 3})\n\tis.IsType(after, before, \"type preserved\")\n}\n\nfunc TestOmitBy(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tr1 := OmitBy(map[string]int{\"foo\": 1, \"bar\": 2, \"baz\": 3}, func(key string, value int) bool {\n\t\treturn value%2 == 1\n\t})\n\n\tis.Equal(map[string]int{\"bar\": 2}, r1)\n\n\ttype myMap map[string]int\n\tbefore := myMap{\"\": 0, \"foobar\": 6, \"baz\": 3}\n\tafter := PickBy(before, func(key string, value int) bool { return true })\n\tis.IsType(after, before, \"type preserved\")\n}\n\nfunc TestOmitByErr(t *testing.T) {\n\tt.Parallel()\n\n\ttests := []struct {\n\t\tname          string\n\t\tinput         map[string]int\n\t\tpredicate     func(string, int) (bool, error)\n\t\twant          map[string]int\n\t\twantErr       string\n\t\twantCallCount int // 0 means don't check (maps have no order)\n\t}{\n\t\t{\n\t\t\tname:  \"omit odd values\",\n\t\t\tinput: map[string]int{\"foo\": 1, \"bar\": 2, \"baz\": 3},\n\t\t\tpredicate: func(key string, value int) (bool, error) {\n\t\t\t\treturn value%2 == 1, nil\n\t\t\t},\n\t\t\twant:          map[string]int{\"bar\": 2},\n\t\t\twantErr:       \"\",\n\t\t\twantCallCount: 0, // map iteration order is not deterministic\n\t\t},\n\t\t{\n\t\t\tname:  \"empty map\",\n\t\t\tinput: map[string]int{},\n\t\t\tpredicate: func(key string, value int) (bool, error) {\n\t\t\t\treturn true, nil\n\t\t\t},\n\t\t\twant:          map[string]int{},\n\t\t\twantErr:       \"\",\n\t\t\twantCallCount: 0,\n\t\t},\n\t\t{\n\t\t\tname:  \"error on specific key\",\n\t\t\tinput: map[string]int{\"foo\": 1, \"bar\": 2, \"baz\": 3},\n\t\t\tpredicate: func(key string, value int) (bool, error) {\n\t\t\t\tif key == \"bar\" {\n\t\t\t\t\treturn false, errors.New(\"bar not allowed\")\n\t\t\t\t}\n\t\t\t\treturn true, nil\n\t\t\t},\n\t\t\twant:          nil,\n\t\t\twantErr:       \"bar not allowed\",\n\t\t\twantCallCount: 0, // map iteration order is not deterministic\n\t\t},\n\t\t{\n\t\t\tname:  \"omit all\",\n\t\t\tinput: map[string]int{\"foo\": 1, \"bar\": 3, \"baz\": 5},\n\t\t\tpredicate: func(key string, value int) (bool, error) {\n\t\t\t\treturn value%2 == 1, nil\n\t\t\t},\n\t\t\twant:          map[string]int{},\n\t\t\twantErr:       \"\",\n\t\t\twantCallCount: 0,\n\t\t},\n\t\t{\n\t\t\tname:  \"omit none\",\n\t\t\tinput: map[string]int{\"foo\": 2, \"bar\": 4, \"baz\": 6},\n\t\t\tpredicate: func(key string, value int) (bool, error) {\n\t\t\t\treturn value%2 == 1, nil\n\t\t\t},\n\t\t\twant:          map[string]int{\"foo\": 2, \"bar\": 4, \"baz\": 6},\n\t\t\twantErr:       \"\",\n\t\t\twantCallCount: 0,\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\ttt := tt // capture range variable\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\tis := assert.New(t)\n\n\t\t\tgot, err := OmitByErr(tt.input, tt.predicate)\n\n\t\t\tif tt.wantErr != \"\" {\n\t\t\t\tis.Error(err)\n\t\t\t\tis.Equal(tt.wantErr, err.Error())\n\t\t\t\tis.Nil(got)\n\t\t\t} else {\n\t\t\t\tis.NoError(err)\n\t\t\t\tis.Equal(tt.want, got)\n\t\t\t}\n\t\t})\n\t}\n\n\tt.Run(\"type preserved\", func(t *testing.T) {\n\t\tt.Parallel()\n\t\tis := assert.New(t)\n\n\t\ttype myMap map[string]int\n\t\tbefore := myMap{\"\": 0, \"foobar\": 6, \"baz\": 3}\n\t\tafter, err := OmitByErr(before, func(key string, value int) (bool, error) {\n\t\t\treturn false, nil\n\t\t})\n\n\t\tis.NoError(err)\n\t\tis.IsType(after, before, \"type preserved\")\n\t})\n}\n\nfunc TestOmitByKeys(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tr1 := OmitByKeys(map[string]int{\"foo\": 1, \"bar\": 2, \"baz\": 3}, []string{\"foo\", \"baz\", \"qux\"})\n\n\tis.Equal(map[string]int{\"bar\": 2}, r1)\n\n\ttype myMap map[string]int\n\tbefore := myMap{\"\": 0, \"foobar\": 6, \"baz\": 3}\n\tafter := OmitByKeys(before, []string{\"foobar\", \"baz\"})\n\tis.IsType(after, before, \"type preserved\")\n}\n\nfunc TestOmitByValues(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tr1 := OmitByValues(map[string]int{\"foo\": 1, \"bar\": 2, \"baz\": 3}, []int{1, 3})\n\n\tis.Equal(map[string]int{\"bar\": 2}, r1)\n\n\ttype myMap map[string]int\n\tbefore := myMap{\"\": 0, \"foobar\": 6, \"baz\": 3}\n\tafter := OmitByValues(before, []int{0, 3})\n\tis.IsType(after, before, \"type preserved\")\n}\n\nfunc TestEntries(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tr1 := Entries(map[string]int{\"foo\": 1, \"bar\": 2})\n\tis.ElementsMatch(r1, []Entry[string, int]{\n\t\t{\n\t\t\tKey:   \"foo\",\n\t\t\tValue: 1,\n\t\t},\n\t\t{\n\t\t\tKey:   \"bar\",\n\t\t\tValue: 2,\n\t\t},\n\t})\n}\n\nfunc TestToPairs(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tr1 := ToPairs(map[string]int{\"baz\": 3, \"qux\": 4})\n\tis.ElementsMatch(r1, []Entry[string, int]{\n\t\t{\n\t\t\tKey:   \"baz\",\n\t\t\tValue: 3,\n\t\t},\n\t\t{\n\t\t\tKey:   \"qux\",\n\t\t\tValue: 4,\n\t\t},\n\t})\n}\n\nfunc TestFromEntries(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tr1 := FromEntries([]Entry[string, int]{\n\t\t{\n\t\t\tKey:   \"foo\",\n\t\t\tValue: 1,\n\t\t},\n\t\t{\n\t\t\tKey:   \"bar\",\n\t\t\tValue: 2,\n\t\t},\n\t})\n\n\tis.Len(r1, 2)\n\tis.Equal(1, r1[\"foo\"])\n\tis.Equal(2, r1[\"bar\"])\n}\n\nfunc TestFromPairs(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tr1 := FromPairs([]Entry[string, int]{\n\t\t{\n\t\t\tKey:   \"baz\",\n\t\t\tValue: 3,\n\t\t},\n\t\t{\n\t\t\tKey:   \"qux\",\n\t\t\tValue: 4,\n\t\t},\n\t})\n\n\tis.Len(r1, 2)\n\tis.Equal(3, r1[\"baz\"])\n\tis.Equal(4, r1[\"qux\"])\n}\n\nfunc TestInvert(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tr1 := Invert(map[string]int{\"a\": 1, \"b\": 2})\n\tr2 := Invert(map[string]int{\"a\": 1, \"b\": 2, \"c\": 1})\n\n\tis.Equal(map[int]string{1: \"a\", 2: \"b\"}, r1)\n\tis.Len(r2, 2)\n}\n\nfunc TestAssign(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := Assign(map[string]int{\"a\": 1, \"b\": 2}, map[string]int{\"b\": 3, \"c\": 4})\n\tis.Equal(map[string]int{\"a\": 1, \"b\": 3, \"c\": 4}, result1)\n\n\ttype myMap map[string]int\n\tbefore := myMap{\"\": 0, \"foobar\": 6, \"baz\": 3}\n\tafter := Assign(before, before)\n\tis.IsType(after, before, \"type preserved\")\n}\n\nfunc TestChunkEntries(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := ChunkEntries(map[string]int{\"a\": 1, \"b\": 2, \"c\": 3, \"d\": 4, \"e\": 5}, 2)\n\tresult2 := ChunkEntries(map[string]int{\"a\": 1, \"b\": 2, \"c\": 3, \"d\": 4, \"e\": 5}, 3)\n\tresult3 := ChunkEntries(map[string]int{}, 2)\n\tresult4 := ChunkEntries(map[string]int{\"a\": 1}, 2)\n\tresult5 := ChunkEntries(map[string]int{\"a\": 1, \"b\": 2}, 1)\n\n\tis.Len(result1, 3)\n\tis.Len(result2, 2)\n\tis.Empty(result3)\n\tis.Len(result4, 1)\n\tis.Len(result5, 2)\n\n\tis.PanicsWithValue(\"lo.ChunkEntries: size must be greater than 0\", func() {\n\t\tChunkEntries(map[string]int{\"a\": 1}, 0)\n\t})\n\tis.PanicsWithValue(\"lo.ChunkEntries: size must be greater than 0\", func() {\n\t\tChunkEntries(map[string]int{\"a\": 1}, -1)\n\t})\n\n\ttype myStruct struct {\n\t\tName  string\n\t\tValue int\n\t}\n\n\tallStructs := []myStruct{{\"one\", 1}, {\"two\", 2}, {\"three\", 3}}\n\tnonempty := ChunkEntries(map[string]myStruct{\"a\": allStructs[0], \"b\": allStructs[1], \"c\": allStructs[2]}, 2)\n\tis.Len(nonempty, 2)\n\n\toriginalMap := map[string]int{\"a\": 1, \"b\": 2, \"c\": 3, \"d\": 4, \"e\": 5}\n\tresult6 := ChunkEntries(originalMap, 2)\n\tfor k := range result6[0] {\n\t\tresult6[0][k] = 10\n\t}\n\tis.Equal(map[string]int{\"a\": 1, \"b\": 2, \"c\": 3, \"d\": 4, \"e\": 5}, originalMap)\n}\n\nfunc TestMapKeys(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := MapKeys(map[int]int{1: 1, 2: 2, 3: 3, 4: 4}, func(x, _ int) string {\n\t\treturn \"Hello\"\n\t})\n\tresult2 := MapKeys(map[int]int{1: 1, 2: 2, 3: 3, 4: 4}, func(_, v int) string {\n\t\treturn strconv.FormatInt(int64(v), 10)\n\t})\n\n\tis.Len(result1, 1)\n\tis.Equal(map[string]int{\"1\": 1, \"2\": 2, \"3\": 3, \"4\": 4}, result2)\n}\n\nfunc TestMapKeysErr(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\t// Test successful case\n\tresult1, err := MapKeysErr(map[int]int{1: 1, 2: 2, 3: 3, 4: 4}, func(x, _ int) (string, error) {\n\t\treturn \"Hello\", nil\n\t})\n\tis.NoError(err)\n\tis.Len(result1, 1)\n\n\tresult2, err := MapKeysErr(map[int]int{1: 1, 2: 2, 3: 3, 4: 4}, func(_, v int) (string, error) {\n\t\treturn strconv.FormatInt(int64(v), 10), nil\n\t})\n\tis.NoError(err)\n\tis.Equal(map[string]int{\"1\": 1, \"2\": 2, \"3\": 3, \"4\": 4}, result2)\n\n\t// Test error case - returns first error\n\t_, err = MapKeysErr(map[int]int{1: 1, 2: 2, 3: 3, 4: 4}, func(v, _ int) (string, error) {\n\t\tif v == 3 {\n\t\t\treturn \"\", fmt.Errorf(\"error at %d\", v)\n\t\t}\n\t\treturn strconv.FormatInt(int64(v), 10), nil\n\t})\n\tis.Error(err)\n\tis.Equal(\"error at 3\", err.Error())\n\n\t// Test empty map\n\tresult3, err := MapKeysErr(map[int]int{}, func(v, _ int) (string, error) {\n\t\treturn strconv.FormatInt(int64(v), 10), nil\n\t})\n\tis.NoError(err)\n\tis.Empty(result3)\n\n\t// Test all keys collide - iteration order is non-deterministic, so check that value is one of expected values\n\tresult4, err := MapKeysErr(map[int]int{1: 1, 2: 2, 3: 3}, func(_, _ int) (string, error) {\n\t\treturn \"same\", nil\n\t})\n\tis.NoError(err)\n\tis.Len(result4, 1)\n\tis.Contains(result4, \"same\")\n\tis.Contains([]int{1, 2, 3}, result4[\"same\"])\n}\n\nfunc TestMapValues(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := MapValues(map[int]int{1: 1, 2: 2, 3: 3, 4: 4}, func(x, _ int) string {\n\t\treturn \"Hello\"\n\t})\n\tresult2 := MapValues(map[int]int{1: 1, 2: 2, 3: 3, 4: 4}, func(x, _ int) string {\n\t\treturn strconv.FormatInt(int64(x), 10)\n\t})\n\n\tis.Equal(map[int]string{1: \"Hello\", 2: \"Hello\", 3: \"Hello\", 4: \"Hello\"}, result1)\n\tis.Equal(map[int]string{1: \"1\", 2: \"2\", 3: \"3\", 4: \"4\"}, result2)\n}\n\nfunc TestMapValuesErr(t *testing.T) {\n\tt.Parallel()\n\n\ttests := []struct {\n\t\tname     string\n\t\tinput    map[int]int\n\t\titeratee func(int, int) (string, error)\n\t\twant     map[int]string\n\t\twantErr  string\n\t}{\n\t\t{\n\t\t\tname:  \"successful transformation\",\n\t\t\tinput: map[int]int{1: 1, 2: 2, 3: 3},\n\t\t\titeratee: func(x, _ int) (string, error) {\n\t\t\t\treturn strconv.FormatInt(int64(x), 10), nil\n\t\t\t},\n\t\t\twant:    map[int]string{1: \"1\", 2: \"2\", 3: \"3\"},\n\t\t\twantErr: \"\",\n\t\t},\n\t\t{\n\t\t\tname:  \"constant value transformation\",\n\t\t\tinput: map[int]int{1: 1, 2: 2, 3: 3},\n\t\t\titeratee: func(_, _ int) (string, error) {\n\t\t\t\treturn \"Hello\", nil\n\t\t\t},\n\t\t\twant:    map[int]string{1: \"Hello\", 2: \"Hello\", 3: \"Hello\"},\n\t\t\twantErr: \"\",\n\t\t},\n\t\t{\n\t\t\tname:  \"error on specific value\",\n\t\t\tinput: map[int]int{1: 1, 2: 2, 3: 3, 4: 4},\n\t\t\titeratee: func(x, _ int) (string, error) {\n\t\t\t\tif x == 3 {\n\t\t\t\t\treturn \"\", fmt.Errorf(\"error at %d\", x)\n\t\t\t\t}\n\t\t\t\treturn strconv.FormatInt(int64(x), 10), nil\n\t\t\t},\n\t\t\twant:    nil,\n\t\t\twantErr: \"error at 3\",\n\t\t},\n\t\t{\n\t\t\tname:  \"error on first value\",\n\t\t\tinput: map[int]int{1: 1, 2: 2},\n\t\t\titeratee: func(x, _ int) (string, error) {\n\t\t\t\tif x == 1 {\n\t\t\t\t\treturn \"\", errors.New(\"cannot process 1\")\n\t\t\t\t}\n\t\t\t\treturn strconv.FormatInt(int64(x), 10), nil\n\t\t\t},\n\t\t\twant:    nil,\n\t\t\twantErr: \"cannot process 1\",\n\t\t},\n\t\t{\n\t\t\tname:     \"empty map\",\n\t\t\tinput:    map[int]int{},\n\t\t\titeratee: func(x, _ int) (string, error) { return strconv.FormatInt(int64(x), 10), nil },\n\t\t\twant:     map[int]string{},\n\t\t\twantErr:  \"\",\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\ttt := tt // capture range variable\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\tis := assert.New(t)\n\n\t\t\tgot, err := MapValuesErr(tt.input, tt.iteratee)\n\n\t\t\tif tt.wantErr != \"\" {\n\t\t\t\tis.Error(err)\n\t\t\t\tis.Equal(tt.wantErr, err.Error())\n\t\t\t\tis.Nil(got)\n\t\t\t} else {\n\t\t\t\tis.NoError(err)\n\t\t\t\tis.Equal(tt.want, got)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMapEntries(t *testing.T) {\n\tt.Parallel()\n\n\tt.Run(\"Normal\", func(t *testing.T) {\n\t\tt.Parallel()\n\t\tis := assert.New(t)\n\n\t\tr1 := MapEntries(map[string]int{\"foo\": 1, \"bar\": 2},\n\t\t\tfunc(k string, v int) (string, int) {\n\t\t\t\treturn k, v + 1\n\t\t\t})\n\t\tis.Equal(map[string]int{\"foo\": 2, \"bar\": 3}, r1)\n\n\t\tr2 := MapEntries(map[string]int{\"foo\": 1, \"bar\": 2},\n\t\t\tfunc(k string, v int) (string, string) {\n\t\t\t\treturn k, k + strconv.Itoa(v)\n\t\t\t})\n\t\tis.Equal(map[string]string{\"foo\": \"foo1\", \"bar\": \"bar2\"}, r2)\n\n\t\tr3 := MapEntries(map[string]int{\"foo\": 1, \"bar\": 2},\n\t\t\tfunc(k string, v int) (string, string) {\n\t\t\t\treturn k, strconv.Itoa(v) + k\n\t\t\t})\n\t\tis.Equal(map[string]string{\"foo\": \"1foo\", \"bar\": \"2bar\"}, r3)\n\t})\n\n\tt.Run(\"NoMutation\", func(t *testing.T) {\n\t\tt.Parallel()\n\n\t\tr1 := map[string]int{\"foo\": 1, \"bar\": 2}\n\t\tMapEntries(r1, func(k string, v int) (string, string) {\n\t\t\treturn k, strconv.Itoa(v) + \"!!\"\n\t\t})\n\t\tassert.Equal(t, map[string]int{\"foo\": 1, \"bar\": 2}, r1)\n\t})\n\n\tt.Run(\"EmptyInput\", func(t *testing.T) {\n\t\tt.Parallel()\n\n\t\tr1 := MapEntries(map[string]int{},\n\t\t\tfunc(k string, v int) (string, string) {\n\t\t\t\treturn k, strconv.Itoa(v) + \"!!\"\n\t\t\t})\n\t\tassert.Empty(t, r1)\n\n\t\tr2 := MapEntries(map[string]any{},\n\t\t\tfunc(k string, v any) (string, any) {\n\t\t\t\treturn k, v\n\t\t\t})\n\t\tassert.Empty(t, r2)\n\t})\n\n\tt.Run(\"Identity\", func(t *testing.T) {\n\t\tt.Parallel()\n\n\t\tr1 := MapEntries(map[string]int{\"foo\": 1, \"bar\": 2},\n\t\t\tfunc(k string, v int) (string, int) {\n\t\t\t\treturn k, v\n\t\t\t})\n\t\tassert.Equal(t, map[string]int{\"foo\": 1, \"bar\": 2}, r1)\n\n\t\tr2 := MapEntries(map[string]any{\"foo\": 1, \"bar\": \"2\", \"ccc\": true},\n\t\t\tfunc(k string, v any) (string, any) {\n\t\t\t\treturn k, v\n\t\t\t})\n\t\tassert.Equal(t, map[string]any{\"foo\": 1, \"bar\": \"2\", \"ccc\": true}, r2)\n\t})\n\n\tt.Run(\"ToConstantEntry\", func(t *testing.T) {\n\t\tt.Parallel()\n\n\t\tr1 := MapEntries(map[string]any{\"foo\": 1, \"bar\": \"2\", \"ccc\": true},\n\t\t\tfunc(k string, v any) (string, any) {\n\t\t\t\treturn \"key\", \"value\"\n\t\t\t})\n\t\tassert.Equal(t, map[string]any{\"key\": \"value\"}, r1)\n\n\t\tr2 := MapEntries(map[string]any{\"foo\": 1, \"bar\": \"2\", \"ccc\": true},\n\t\t\tfunc(k string, v any) (string, any) {\n\t\t\t\treturn \"b\", 5\n\t\t\t})\n\t\tassert.Equal(t, map[string]any{\"b\": 5}, r2)\n\t})\n\n\t// // because using range over map, the order is not guaranteed\n\t// // this test is not deterministic\n\t// t.Run(\"OverlappingKeys\", func(t *testing.T) {\n\t// \t\tt.Parallel()\n\t//\n\t// \tr1 := MapEntries(map[string]any{\"foo\": 1, \"foo2\": 2, \"Foo\": 2, \"Foo2\": \"2\", \"bar\": \"2\", \"ccc\": true},\n\t// \t\tfunc(k string, v any) (string, any) {\n\t// \t\t\treturn string(k[0]), v\n\t// \t\t})\n\t// \tassert.Equal(t, map[string]any{\"F\": \"2\", \"b\": \"2\", \"c\": true, \"f\": 1}, r1)\n\t//\n\t// \tr2 := MapEntries(map[string]string{\"foo\": \"1\", \"foo2\": \"2\", \"Foo\": \"2\", \"Foo2\": \"2\", \"bar\": \"2\", \"ccc\": \"true\"},\n\t// \t\tfunc(k, v string) (string, string) {\n\t// \t\t\treturn v, k\n\t// \t\t})\n\t// \tassert.Equal(t, map[string]string{\"1\": \"foo\", \"2\": \"bar\", \"true\": \"ccc\"}, r2)\n\t// })\n\n\tt.Run(\"NormalMappers\", func(t *testing.T) {\n\t\tt.Parallel()\n\n\t\tr1 := MapEntries(map[string]string{\"foo\": \"1\", \"foo2\": \"2\", \"Foo\": \"2\", \"Foo2\": \"2\", \"bar\": \"2\", \"ccc\": \"true\"},\n\t\t\tfunc(k, v string) (string, string) {\n\t\t\t\treturn k, k + v\n\t\t\t})\n\t\tassert.Equal(t, map[string]string{\"Foo\": \"Foo2\", \"Foo2\": \"Foo22\", \"bar\": \"bar2\", \"ccc\": \"ccctrue\", \"foo\": \"foo1\", \"foo2\": \"foo22\"}, r1)\n\n\t\ttype myStruct struct {\n\t\t\tname string\n\t\t\tage  int\n\t\t}\n\t\tr2 := MapEntries(map[string]myStruct{\"1-11-1\": {name: \"foo\", age: 1}, \"2-22-2\": {name: \"bar\", age: 2}},\n\t\t\tfunc(k string, v myStruct) (string, string) {\n\t\t\t\treturn v.name, k\n\t\t\t})\n\t\tassert.Equal(t, map[string]string{\"bar\": \"2-22-2\", \"foo\": \"1-11-1\"}, r2)\n\t})\n}\n\nfunc TestMapEntriesErr(t *testing.T) {\n\tt.Parallel()\n\n\tt.Run(\"same types\", func(t *testing.T) {\n\t\tt.Parallel()\n\n\t\ttests := []struct {\n\t\t\tname     string\n\t\t\tinput    map[string]int\n\t\t\titeratee func(string, int) (string, int, error)\n\t\t\twant     map[string]int\n\t\t\twantErr  string\n\t\t}{\n\t\t\t{\n\t\t\t\tname:  \"increment values\",\n\t\t\t\tinput: map[string]int{\"foo\": 1, \"bar\": 2},\n\t\t\t\titeratee: func(k string, v int) (string, int, error) {\n\t\t\t\t\treturn k, v + 1, nil\n\t\t\t\t},\n\t\t\t\twant: map[string]int{\"foo\": 2, \"bar\": 3},\n\t\t\t},\n\t\t\t{\n\t\t\t\tname:  \"error on specific key\",\n\t\t\t\tinput: map[string]int{\"foo\": 1, \"bar\": 2, \"baz\": 3},\n\t\t\t\titeratee: func(k string, v int) (string, int, error) {\n\t\t\t\t\tif k == \"bar\" {\n\t\t\t\t\t\treturn \"\", 0, errors.New(\"bar not allowed\")\n\t\t\t\t\t}\n\t\t\t\t\treturn k, v, nil\n\t\t\t\t},\n\t\t\t\twantErr: \"bar not allowed\",\n\t\t\t},\n\t\t\t{\n\t\t\t\tname:  \"empty map\",\n\t\t\t\tinput: map[string]int{},\n\t\t\t\titeratee: func(k string, v int) (string, int, error) {\n\t\t\t\t\treturn k, v, nil\n\t\t\t\t},\n\t\t\t\twant: map[string]int{},\n\t\t\t},\n\t\t\t{\n\t\t\t\tname:  \"to constant entry\",\n\t\t\t\tinput: map[string]int{\"foo\": 1, \"bar\": 2, \"baz\": 3},\n\t\t\t\titeratee: func(k string, v int) (string, int, error) {\n\t\t\t\t\treturn \"key\", 0, nil\n\t\t\t\t},\n\t\t\t\twant: map[string]int{\"key\": 0},\n\t\t\t},\n\t\t\t{\n\t\t\t\tname:  \"identity\",\n\t\t\t\tinput: map[string]int{\"foo\": 1, \"bar\": 2},\n\t\t\t\titeratee: func(k string, v int) (string, int, error) {\n\t\t\t\t\treturn k, v, nil\n\t\t\t\t},\n\t\t\t\twant: map[string]int{\"foo\": 1, \"bar\": 2},\n\t\t\t},\n\t\t}\n\n\t\tfor _, tt := range tests {\n\t\t\ttt := tt // capture range variable\n\t\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\t\tt.Parallel()\n\t\t\t\tis := assert.New(t)\n\n\t\t\t\tgot, err := MapEntriesErr(tt.input, tt.iteratee)\n\n\t\t\t\tif tt.wantErr != \"\" {\n\t\t\t\t\tis.Error(err)\n\t\t\t\t\tis.Equal(tt.wantErr, err.Error())\n\t\t\t\t\tis.Nil(got)\n\t\t\t\t} else {\n\t\t\t\t\tis.NoError(err)\n\t\t\t\t\tis.Equal(tt.want, got)\n\t\t\t\t}\n\t\t\t})\n\t\t}\n\t})\n\n\tt.Run(\"different value type\", func(t *testing.T) {\n\t\tt.Parallel()\n\n\t\ttests := []struct {\n\t\t\tname     string\n\t\t\tinput    map[string]int\n\t\t\titeratee func(string, int) (string, string, error)\n\t\t\twant     map[string]string\n\t\t\twantErr  string\n\t\t}{\n\t\t\t{\n\t\t\t\tname:  \"transform both key and value\",\n\t\t\t\tinput: map[string]int{\"foo\": 1, \"bar\": 2},\n\t\t\t\titeratee: func(k string, v int) (string, string, error) {\n\t\t\t\t\treturn k, k + strconv.Itoa(v), nil\n\t\t\t\t},\n\t\t\t\twant: map[string]string{\"foo\": \"foo1\", \"bar\": \"bar2\"},\n\t\t\t},\n\t\t\t{\n\t\t\t\tname:  \"error on specific value\",\n\t\t\t\tinput: map[string]int{\"foo\": 1, \"bar\": 2, \"baz\": 3},\n\t\t\t\titeratee: func(k string, v int) (string, string, error) {\n\t\t\t\t\tif v == 2 {\n\t\t\t\t\t\treturn \"\", \"\", fmt.Errorf(\"even value not allowed: %d\", v)\n\t\t\t\t\t}\n\t\t\t\t\treturn k, strconv.Itoa(v), nil\n\t\t\t\t},\n\t\t\t\twantErr: \"even value not allowed: 2\",\n\t\t\t},\n\t\t\t{\n\t\t\t\tname:  \"empty map\",\n\t\t\t\tinput: map[string]int{},\n\t\t\t\titeratee: func(k string, v int) (string, string, error) {\n\t\t\t\t\treturn k, strconv.Itoa(v), nil\n\t\t\t\t},\n\t\t\t\twant: map[string]string{},\n\t\t\t},\n\t\t}\n\n\t\tfor _, tt := range tests {\n\t\t\ttt := tt // capture range variable\n\t\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\t\tt.Parallel()\n\t\t\t\tis := assert.New(t)\n\n\t\t\t\tgot, err := MapEntriesErr(tt.input, tt.iteratee)\n\n\t\t\t\tif tt.wantErr != \"\" {\n\t\t\t\t\tis.Error(err)\n\t\t\t\t\tis.Equal(tt.wantErr, err.Error())\n\t\t\t\t\tis.Nil(got)\n\t\t\t\t} else {\n\t\t\t\t\tis.NoError(err)\n\t\t\t\t\tis.Equal(tt.want, got)\n\t\t\t\t}\n\t\t\t})\n\t\t}\n\t})\n\n\tt.Run(\"invert map\", func(t *testing.T) {\n\t\tt.Parallel()\n\n\t\ttests := []struct {\n\t\t\tname     string\n\t\t\tinput    map[string]int\n\t\t\titeratee func(string, int) (int, string, error)\n\t\t\twant     map[int]string\n\t\t\twantErr  string\n\t\t}{\n\t\t\t{\n\t\t\t\tname:  \"successful invert\",\n\t\t\t\tinput: map[string]int{\"a\": 1, \"b\": 2},\n\t\t\t\titeratee: func(k string, v int) (int, string, error) {\n\t\t\t\t\treturn v, k, nil\n\t\t\t\t},\n\t\t\t\twant: map[int]string{1: \"a\", 2: \"b\"},\n\t\t\t},\n\t\t\t{\n\t\t\t\tname:  \"error on specific key\",\n\t\t\t\tinput: map[string]int{\"a\": 1, \"b\": 2},\n\t\t\t\titeratee: func(k string, v int) (int, string, error) {\n\t\t\t\t\tif k == \"b\" {\n\t\t\t\t\t\treturn 0, \"\", errors.New(\"cannot invert b\")\n\t\t\t\t\t}\n\t\t\t\t\treturn v, k, nil\n\t\t\t\t},\n\t\t\t\twantErr: \"cannot invert b\",\n\t\t\t},\n\t\t}\n\n\t\tfor _, tt := range tests {\n\t\t\ttt := tt // capture range variable\n\t\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\t\tt.Parallel()\n\t\t\t\tis := assert.New(t)\n\n\t\t\t\tgot, err := MapEntriesErr(tt.input, tt.iteratee)\n\n\t\t\t\tif tt.wantErr != \"\" {\n\t\t\t\t\tis.Error(err)\n\t\t\t\t\tis.Equal(tt.wantErr, err.Error())\n\t\t\t\t\tis.Nil(got)\n\t\t\t\t} else {\n\t\t\t\t\tis.NoError(err)\n\t\t\t\t\tis.Equal(tt.want, got)\n\t\t\t\t}\n\t\t\t})\n\t\t}\n\t})\n}\n\nfunc TestMapToSlice(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := MapToSlice(map[int]int{1: 5, 2: 6, 3: 7, 4: 8}, func(k, v int) string {\n\t\treturn fmt.Sprintf(\"%d_%d\", k, v)\n\t})\n\tresult2 := MapToSlice(map[int]int{1: 5, 2: 6, 3: 7, 4: 8}, func(k, _ int) string {\n\t\treturn strconv.FormatInt(int64(k), 10)\n\t})\n\n\tis.ElementsMatch(result1, []string{\"1_5\", \"2_6\", \"3_7\", \"4_8\"})\n\tis.ElementsMatch(result2, []string{\"1\", \"2\", \"3\", \"4\"})\n}\n\nfunc TestMapToSliceErr(t *testing.T) {\n\tt.Parallel()\n\n\ttests := []struct {\n\t\tname          string\n\t\tinput         map[int]int64\n\t\titeratee      func(int, int64) (string, error)\n\t\twant          []string\n\t\twantErr       string\n\t\twantCallCount int // 0 means don't check (maps have no order)\n\t}{\n\t\t{\n\t\t\tname:  \"successful transformation\",\n\t\t\tinput: map[int]int64{1: 5, 2: 6, 3: 7},\n\t\t\titeratee: func(k int, v int64) (string, error) {\n\t\t\t\treturn fmt.Sprintf(\"%d_%d\", k, v), nil\n\t\t\t},\n\t\t\twant:          []string{\"1_5\", \"2_6\", \"3_7\"},\n\t\t\twantErr:       \"\",\n\t\t\twantCallCount: 0, // map iteration order is not deterministic\n\t\t},\n\t\t{\n\t\t\tname:  \"empty map\",\n\t\t\tinput: map[int]int64{},\n\t\t\titeratee: func(k int, v int64) (string, error) {\n\t\t\t\treturn fmt.Sprintf(\"%d_%d\", k, v), nil\n\t\t\t},\n\t\t\twant:          []string{},\n\t\t\twantErr:       \"\",\n\t\t\twantCallCount: 0,\n\t\t},\n\t\t{\n\t\t\tname:  \"error on specific key\",\n\t\t\tinput: map[int]int64{1: 5, 2: 6, 3: 7},\n\t\t\titeratee: func(k int, v int64) (string, error) {\n\t\t\t\tif k == 2 {\n\t\t\t\t\treturn \"\", errors.New(\"key 2 not allowed\")\n\t\t\t\t}\n\t\t\t\treturn fmt.Sprintf(\"%d_%d\", k, v), nil\n\t\t\t},\n\t\t\twant:          nil,\n\t\t\twantErr:       \"key 2 not allowed\",\n\t\t\twantCallCount: 0, // map iteration order is not deterministic\n\t\t},\n\t\t{\n\t\t\tname:  \"constant value\",\n\t\t\tinput: map[int]int64{1: 5, 2: 6, 3: 7},\n\t\t\titeratee: func(k int, v int64) (string, error) {\n\t\t\t\treturn \"constant\", nil\n\t\t\t},\n\t\t\twant:          []string{\"constant\", \"constant\", \"constant\"},\n\t\t\twantErr:       \"\",\n\t\t\twantCallCount: 0,\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\ttt := tt // capture range variable\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\tis := assert.New(t)\n\n\t\t\tgot, err := MapToSliceErr(tt.input, tt.iteratee)\n\n\t\t\tif tt.wantErr != \"\" {\n\t\t\t\tis.Error(err)\n\t\t\t\tis.Equal(tt.wantErr, err.Error())\n\t\t\t\tis.Nil(got)\n\t\t\t} else {\n\t\t\t\tis.NoError(err)\n\t\t\t\tis.ElementsMatch(tt.want, got)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestFilterMapToSlice(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := FilterMapToSlice(map[int]int{1: 5, 2: 6, 3: 7, 4: 8}, func(k, v int) (string, bool) {\n\t\treturn fmt.Sprintf(\"%d_%d\", k, v), k%2 == 0\n\t})\n\tresult2 := FilterMapToSlice(map[int]int{1: 5, 2: 6, 3: 7, 4: 8}, func(k, _ int) (string, bool) {\n\t\treturn strconv.FormatInt(int64(k), 10), k%2 == 0\n\t})\n\n\tis.ElementsMatch(result1, []string{\"2_6\", \"4_8\"})\n\tis.ElementsMatch(result2, []string{\"2\", \"4\"})\n}\n\nfunc TestFilterMapToSliceErr(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\ttests := []struct {\n\t\tname     string\n\t\tinput    map[int]int64\n\t\titeratee func(int, int64) (string, bool, error)\n\t\twant     []string\n\t\twantErr  string\n\t}{\n\t\t{\n\t\t\tname:  \"filter even keys and transform\",\n\t\t\tinput: map[int]int64{1: 5, 2: 6, 3: 7, 4: 8},\n\t\t\titeratee: func(k int, v int64) (string, bool, error) {\n\t\t\t\treturn fmt.Sprintf(\"%d_%d\", k, v), k%2 == 0, nil\n\t\t\t},\n\t\t\twant: []string{\"2_6\", \"4_8\"},\n\t\t},\n\t\t{\n\t\t\tname:  \"empty map\",\n\t\t\tinput: map[int]int64{},\n\t\t\titeratee: func(k int, v int64) (string, bool, error) {\n\t\t\t\treturn fmt.Sprintf(\"%d_%d\", k, v), true, nil\n\t\t\t},\n\t\t\twant: []string{},\n\t\t},\n\t\t{\n\t\t\tname:  \"filter all out\",\n\t\t\tinput: map[int]int64{1: 2, 2: 4, 3: 6},\n\t\t\titeratee: func(k int, v int64) (string, bool, error) {\n\t\t\t\treturn fmt.Sprintf(\"%d_%d\", k, v), false, nil\n\t\t\t},\n\t\t\twant: []string{},\n\t\t},\n\t\t{\n\t\t\tname:  \"filter all in\",\n\t\t\tinput: map[int]int64{1: 5, 2: 6, 3: 7},\n\t\t\titeratee: func(k int, v int64) (string, bool, error) {\n\t\t\t\treturn fmt.Sprintf(\"%d_%d\", k, v), true, nil\n\t\t\t},\n\t\t\twant: []string{\"1_5\", \"2_6\", \"3_7\"},\n\t\t},\n\t\t{\n\t\t\tname:  \"constant value\",\n\t\t\tinput: map[int]int64{1: 5, 2: 6, 3: 7},\n\t\t\titeratee: func(k int, v int64) (string, bool, error) {\n\t\t\t\treturn \"constant\", true, nil\n\t\t\t},\n\t\t\twant: []string{\"constant\", \"constant\", \"constant\"},\n\t\t},\n\t\t{\n\t\t\tname:  \"error on specific key\",\n\t\t\tinput: map[int]int64{1: 5, 2: 6, 3: 7},\n\t\t\titeratee: func(k int, v int64) (string, bool, error) {\n\t\t\t\tif k == 2 {\n\t\t\t\t\treturn \"\", false, errors.New(\"key 2 not allowed\")\n\t\t\t\t}\n\t\t\t\treturn fmt.Sprintf(\"%d_%d\", k, v), true, nil\n\t\t\t},\n\t\t\twantErr: \"key 2 not allowed\",\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\ttt := tt\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\n\t\t\tgot, err := FilterMapToSliceErr(tt.input, tt.iteratee)\n\n\t\t\tif tt.wantErr != \"\" {\n\t\t\t\tis.Error(err)\n\t\t\t\tis.Equal(tt.wantErr, err.Error())\n\t\t\t\tis.Nil(got)\n\t\t\t} else {\n\t\t\t\tis.NoError(err)\n\t\t\t\tis.ElementsMatch(tt.want, got)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestFilterKeys(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := FilterKeys(map[int]string{1: \"foo\", 2: \"bar\", 3: \"baz\"}, func(k int, v string) bool {\n\t\treturn v == \"foo\"\n\t})\n\tis.Equal([]int{1}, result1)\n\n\tresult2 := FilterKeys(map[string]int{\"foo\": 1, \"bar\": 2, \"baz\": 3}, func(k string, v int) bool {\n\t\treturn false\n\t})\n\tis.Empty(result2)\n}\n\nfunc TestFilterValues(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := FilterValues(map[int]string{1: \"foo\", 2: \"bar\", 3: \"baz\"}, func(k int, v string) bool {\n\t\treturn v == \"foo\"\n\t})\n\tis.Equal([]string{\"foo\"}, result1)\n\n\tresult2 := FilterValues(map[string]int{\"foo\": 1, \"bar\": 2, \"baz\": 3}, func(k string, v int) bool {\n\t\treturn false\n\t})\n\tis.Empty(result2)\n}\n\nfunc TestFilterKeysErr(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\ttests := []struct {\n\t\tname      string\n\t\tinput     map[int]string\n\t\tpredicate func(int, string) (bool, error)\n\t\twant      []int\n\t\twantErr   string\n\t}{\n\t\t{\n\t\t\tname:  \"filter by value\",\n\t\t\tinput: map[int]string{1: \"foo\", 2: \"bar\", 3: \"baz\"},\n\t\t\tpredicate: func(k int, v string) (bool, error) {\n\t\t\t\treturn v == \"foo\", nil\n\t\t\t},\n\t\t\twant: []int{1},\n\t\t},\n\t\t{\n\t\t\tname:  \"empty map\",\n\t\t\tinput: map[int]string{},\n\t\t\tpredicate: func(k int, v string) (bool, error) {\n\t\t\t\treturn true, nil\n\t\t\t},\n\t\t\twant: []int{},\n\t\t},\n\t\t{\n\t\t\tname:  \"filter all out\",\n\t\t\tinput: map[int]string{1: \"foo\", 2: \"bar\", 3: \"baz\"},\n\t\t\tpredicate: func(k int, v string) (bool, error) {\n\t\t\t\treturn false, nil\n\t\t\t},\n\t\t\twant: []int{},\n\t\t},\n\t\t{\n\t\t\tname:  \"filter all in\",\n\t\t\tinput: map[int]string{1: \"foo\", 2: \"bar\", 3: \"baz\"},\n\t\t\tpredicate: func(k int, v string) (bool, error) {\n\t\t\t\treturn true, nil\n\t\t\t},\n\t\t\twant: []int{1, 2, 3},\n\t\t},\n\t\t{\n\t\t\tname:  \"error on specific key\",\n\t\t\tinput: map[int]string{1: \"foo\", 2: \"bar\", 3: \"baz\"},\n\t\t\tpredicate: func(k int, v string) (bool, error) {\n\t\t\t\tif k == 2 {\n\t\t\t\t\treturn false, errors.New(\"key 2 not allowed\")\n\t\t\t\t}\n\t\t\t\treturn true, nil\n\t\t\t},\n\t\t\twantErr: \"key 2 not allowed\",\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\ttt := tt\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\n\t\t\tgot, err := FilterKeysErr(tt.input, tt.predicate)\n\n\t\t\tif tt.wantErr != \"\" {\n\t\t\t\tis.Error(err)\n\t\t\t\tis.Equal(tt.wantErr, err.Error())\n\t\t\t\tis.Nil(got)\n\t\t\t} else {\n\t\t\t\tis.NoError(err)\n\t\t\t\tis.ElementsMatch(tt.want, got)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestFilterValuesErr(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\ttests := []struct {\n\t\tname      string\n\t\tinput     map[int]string\n\t\tpredicate func(int, string) (bool, error)\n\t\twant      []string\n\t\twantErr   string\n\t}{\n\t\t{\n\t\t\tname:  \"filter by value\",\n\t\t\tinput: map[int]string{1: \"foo\", 2: \"bar\", 3: \"baz\"},\n\t\t\tpredicate: func(k int, v string) (bool, error) {\n\t\t\t\treturn v == \"foo\", nil\n\t\t\t},\n\t\t\twant: []string{\"foo\"},\n\t\t},\n\t\t{\n\t\t\tname:  \"empty map\",\n\t\t\tinput: map[int]string{},\n\t\t\tpredicate: func(k int, v string) (bool, error) {\n\t\t\t\treturn true, nil\n\t\t\t},\n\t\t\twant: []string{},\n\t\t},\n\t\t{\n\t\t\tname:  \"filter all out\",\n\t\t\tinput: map[int]string{1: \"foo\", 2: \"bar\", 3: \"baz\"},\n\t\t\tpredicate: func(k int, v string) (bool, error) {\n\t\t\t\treturn false, nil\n\t\t\t},\n\t\t\twant: []string{},\n\t\t},\n\t\t{\n\t\t\tname:  \"filter all in\",\n\t\t\tinput: map[int]string{1: \"foo\", 2: \"bar\", 3: \"baz\"},\n\t\t\tpredicate: func(k int, v string) (bool, error) {\n\t\t\t\treturn true, nil\n\t\t\t},\n\t\t\twant: []string{\"foo\", \"bar\", \"baz\"},\n\t\t},\n\t\t{\n\t\t\tname:  \"error on specific key\",\n\t\t\tinput: map[int]string{1: \"foo\", 2: \"bar\", 3: \"baz\"},\n\t\t\tpredicate: func(k int, v string) (bool, error) {\n\t\t\t\tif k == 2 {\n\t\t\t\t\treturn false, errors.New(\"key 2 not allowed\")\n\t\t\t\t}\n\t\t\t\treturn true, nil\n\t\t\t},\n\t\t\twantErr: \"key 2 not allowed\",\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\ttt := tt\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\n\t\t\tgot, err := FilterValuesErr(tt.input, tt.predicate)\n\n\t\t\tif tt.wantErr != \"\" {\n\t\t\t\tis.Error(err)\n\t\t\t\tis.Equal(tt.wantErr, err.Error())\n\t\t\t\tis.Nil(got)\n\t\t\t} else {\n\t\t\t\tis.NoError(err)\n\t\t\t\tis.ElementsMatch(tt.want, got)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkAssign(b *testing.B) {\n\tcounts := []int{32768, 1024, 128, 32, 2}\n\n\tallDifferentMap := func(b *testing.B, n int) []map[string]int {\n\t\tb.Helper()\n\t\tdefer b.ResetTimer()\n\t\tm := make([]map[string]int, 0)\n\t\tfor i := 0; i < n; i++ {\n\t\t\tm = append(m, map[string]int{\n\t\t\t\tstrconv.Itoa(i): i,\n\t\t\t\tstrconv.Itoa(i): i,\n\t\t\t\tstrconv.Itoa(i): i,\n\t\t\t\tstrconv.Itoa(i): i,\n\t\t\t\tstrconv.Itoa(i): i,\n\t\t\t\tstrconv.Itoa(i): i,\n\t\t\t},\n\t\t\t)\n\t\t}\n\t\treturn m\n\t}\n\n\tallTheSameMap := func(b *testing.B, n int) []map[string]int {\n\t\tb.Helper()\n\t\tdefer b.ResetTimer()\n\t\tm := make([]map[string]int, 0)\n\t\tfor i := 0; i < n; i++ {\n\t\t\tm = append(m, map[string]int{\n\t\t\t\t\"a\": 1,\n\t\t\t\t\"b\": 2,\n\t\t\t\t\"c\": 3,\n\t\t\t\t\"d\": 4,\n\t\t\t\t\"e\": 5,\n\t\t\t\t\"f\": 6,\n\t\t\t},\n\t\t\t)\n\t\t}\n\t\treturn m\n\t}\n\n\tfor _, count := range counts {\n\t\tdifferentMap := allDifferentMap(b, count)\n\t\tsameMap := allTheSameMap(b, count)\n\n\t\tb.Run(strconv.Itoa(count), func(b *testing.B) {\n\t\t\ttestCases := []struct {\n\t\t\t\tname string\n\t\t\t\tin   []map[string]int\n\t\t\t}{\n\t\t\t\t{\"different\", differentMap},\n\t\t\t\t{\"same\", sameMap},\n\t\t\t}\n\n\t\t\tfor _, tc := range testCases {\n\t\t\t\tb.Run(tc.name, func(b *testing.B) {\n\t\t\t\t\tb.ResetTimer()\n\t\t\t\t\tfor n := 0; n < b.N; n++ {\n\t\t\t\t\t\tresult := Assign(tc.in...)\n\t\t\t\t\t\t_ = result\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "math.go",
    "content": "package lo\n\nimport (\n\t\"math\"\n\n\t\"github.com/samber/lo/internal/constraints\"\n)\n\n// Range creates a slice of numbers (positive and/or negative) with given length.\n// Play: https://go.dev/play/p/rho00R0WuHs\nfunc Range(elementNum int) []int {\n\tstep := Ternary(elementNum < 0, -1, 1)\n\tlength := elementNum * step\n\tresult := make([]int, length)\n\tfor i, j := 0, 0; i < length; i, j = i+1, j+step {\n\t\tresult[i] = j\n\t}\n\treturn result\n}\n\n// RangeFrom creates a slice of numbers from start with specified length.\n// Play: https://go.dev/play/p/0r6VimXAi9H\nfunc RangeFrom[T constraints.Integer | constraints.Float](start T, elementNum int) []T {\n\tstep := Ternary(elementNum < 0, -1, 1)\n\tlength := elementNum * step\n\tresult := make([]T, length)\n\tfor i, j := 0, start; i < length; i, j = i+1, j+T(step) {\n\t\tresult[i] = j\n\t}\n\treturn result\n}\n\n// RangeWithSteps creates a slice of numbers (positive and/or negative) progressing from start up to, but not including end.\n// step set to zero will return an empty slice.\n// Play: https://go.dev/play/p/0r6VimXAi9H\nfunc RangeWithSteps[T constraints.Integer | constraints.Float](start, end, step T) []T {\n\tif start == end || step == 0 {\n\t\treturn []T{}\n\t}\n\n\tcapacity := func(count, delta T) int {\n\t\t// Use math.Ceil instead of (count-1)/delta+1 because integer division\n\t\t// fails for floats (e.g., 5.5/2.5=2.2 → ceil=3, not 2).\n\t\treturn int(math.Ceil(float64(count) / float64(delta)))\n\t}\n\n\tif start < end {\n\t\tif step < 0 {\n\t\t\treturn []T{}\n\t\t}\n\n\t\tresult := make([]T, 0, capacity(end-start, step))\n\t\tfor i := start; i < end; i += step {\n\t\t\tresult = append(result, i)\n\t\t}\n\t\treturn result\n\t}\n\tif step > 0 {\n\t\treturn []T{}\n\t}\n\n\tresult := make([]T, 0, capacity(start-end, -step))\n\tfor i := start; i > end; i += step {\n\t\tresult = append(result, i)\n\t}\n\treturn result\n}\n\n// Clamp clamps number within the inclusive lower and upper bounds.\n// Play: https://go.dev/play/p/RU4lJNC2hlI\nfunc Clamp[T constraints.Ordered](value, mIn, mAx T) T {\n\tif value < mIn {\n\t\treturn mIn\n\t} else if value > mAx {\n\t\treturn mAx\n\t}\n\treturn value\n}\n\n// Sum sums the values in a collection. If collection is empty 0 is returned.\n// Play: https://go.dev/play/p/upfeJVqs4Bt\nfunc Sum[T constraints.Float | constraints.Integer | constraints.Complex](collection []T) T {\n\tvar sum T\n\tfor i := range collection {\n\t\tsum += collection[i]\n\t}\n\treturn sum\n}\n\n// SumBy summarizes the values in a collection using the given return value from the iteration function. If collection is empty 0 is returned.\n// Play: https://go.dev/play/p/Dz_a_7jN_ca\nfunc SumBy[T any, R constraints.Float | constraints.Integer | constraints.Complex](collection []T, iteratee func(item T) R) R {\n\tvar sum R\n\tfor i := range collection {\n\t\tsum += iteratee(collection[i])\n\t}\n\treturn sum\n}\n\n// SumByErr summarizes the values in a collection using the given return value from the iteration function.\n// If the iteratee returns an error, iteration stops and the error is returned.\n// If collection is empty 0 and nil error are returned.\nfunc SumByErr[T any, R constraints.Float | constraints.Integer | constraints.Complex](collection []T, iteratee func(item T) (R, error)) (R, error) {\n\tvar sum R\n\tfor i := range collection {\n\t\tv, err := iteratee(collection[i])\n\t\tif err != nil {\n\t\t\treturn sum, err\n\t\t}\n\t\tsum += v\n\t}\n\treturn sum, nil\n}\n\n// Product gets the product of the values in a collection. If collection is empty 1 is returned.\n// Play: https://go.dev/play/p/2_kjM_smtAH\nfunc Product[T constraints.Float | constraints.Integer | constraints.Complex](collection []T) T {\n\tvar product T = 1\n\tfor i := range collection {\n\t\tproduct *= collection[i]\n\t}\n\treturn product\n}\n\n// ProductBy summarizes the values in a collection using the given return value from the iteration function. If collection is empty 1 is returned.\n// Play: https://go.dev/play/p/wadzrWr9Aer\nfunc ProductBy[T any, R constraints.Float | constraints.Integer | constraints.Complex](collection []T, iteratee func(item T) R) R {\n\tvar product R = 1\n\tfor i := range collection {\n\t\tproduct *= iteratee(collection[i])\n\t}\n\treturn product\n}\n\n// ProductByErr summarizes the values in a collection using the given return value from the iteration function.\n// If the iteratee returns an error, iteration stops and the error is returned.\n// If collection is empty 1 and nil error are returned.\nfunc ProductByErr[T any, R constraints.Float | constraints.Integer | constraints.Complex](collection []T, iteratee func(item T) (R, error)) (R, error) {\n\tvar product R = 1\n\tfor i := range collection {\n\t\tv, err := iteratee(collection[i])\n\t\tif err != nil {\n\t\t\treturn product, err\n\t\t}\n\t\tproduct *= v\n\t}\n\treturn product, nil\n}\n\n// Mean calculates the mean of a collection of numbers.\n// Play: https://go.dev/play/p/tPURSuteUsP\nfunc Mean[T constraints.Float | constraints.Integer](collection []T) T {\n\tlength := T(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\tsum := Sum(collection)\n\treturn sum / length\n}\n\n// MeanBy calculates the mean of a collection of numbers using the given return value from the iteration function.\n// Play: https://go.dev/play/p/j7TsVwBOZ7P\nfunc MeanBy[T any, R constraints.Float | constraints.Integer](collection []T, iteratee func(item T) R) R {\n\tlength := R(len(collection))\n\tif length == 0 {\n\t\treturn 0\n\t}\n\tsum := SumBy(collection, iteratee)\n\treturn sum / length\n}\n\n// MeanByErr calculates the mean of a collection of numbers using the given return value from the iteration function.\n// If the iteratee returns an error, iteration stops and the error is returned.\n// If collection is empty 0 and nil error are returned.\nfunc MeanByErr[T any, R constraints.Float | constraints.Integer](collection []T, iteratee func(item T) (R, error)) (R, error) {\n\tlength := R(len(collection))\n\tif length == 0 {\n\t\treturn 0, nil\n\t}\n\tsum, err := SumByErr(collection, iteratee)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\treturn sum / length, nil\n}\n\n// Mode returns the mode (most frequent value) of a collection.\n// If multiple values have the same highest frequency, then multiple values are returned.\n// If the collection is empty, then the zero value of T is returned.\n// Play: https://go.dev/play/p/PbiviqnV5zX\nfunc Mode[T constraints.Integer | constraints.Float](collection []T) []T {\n\tlength := T(len(collection))\n\tif length == 0 {\n\t\treturn []T{}\n\t}\n\n\tmode := make([]T, 0)\n\tmaxFreq := 0\n\tfrequency := make(map[T]int, len(collection))\n\n\tfor _, item := range collection {\n\t\tfrequency[item]++\n\t\tcount := frequency[item]\n\n\t\tif count > maxFreq {\n\t\t\tmaxFreq = count\n\t\t\tmode = []T{item}\n\t\t} else if count == maxFreq {\n\t\t\tmode = append(mode, item)\n\t\t}\n\t}\n\n\treturn mode\n}\n"
  },
  {
    "path": "math_test.go",
    "content": "package lo\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestRange(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := Range(4)\n\tresult2 := Range(-4)\n\tresult3 := Range(0)\n\tis.Equal([]int{0, 1, 2, 3}, result1)\n\tis.Equal([]int{0, -1, -2, -3}, result2)\n\tis.Empty(result3)\n}\n\nfunc TestRangeFrom(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := RangeFrom(1, 5)\n\tresult2 := RangeFrom(-1, -5)\n\tresult3 := RangeFrom(10, 0)\n\tresult4 := RangeFrom(2.0, 3)\n\tresult5 := RangeFrom(-2.0, -3)\n\tresult6 := RangeFrom(2.5, 3)\n\tresult7 := RangeFrom(-2.5, -3)\n\tis.Equal([]int{1, 2, 3, 4, 5}, result1)\n\tis.Equal([]int{-1, -2, -3, -4, -5}, result2)\n\tis.Empty(result3)\n\tis.Equal([]float64{2.0, 3.0, 4.0}, result4)\n\tis.Equal([]float64{-2.0, -3.0, -4.0}, result5)\n\tis.Equal([]float64{2.5, 3.5, 4.5}, result6)\n\tis.Equal([]float64{-2.5, -3.5, -4.5}, result7)\n}\n\nfunc TestRangeWithSteps(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := RangeWithSteps(0, 20, 6)\n\tresult2 := RangeWithSteps(0, 3, -5)\n\tresult3 := RangeWithSteps(1, 1, 0)\n\tresult4 := RangeWithSteps(3, 2, 1)\n\tresult5 := RangeWithSteps(1.0, 4.0, 2.0)\n\tresult6 := RangeWithSteps[float32](-1.0, -4.0, -1.0)\n\tresult7 := RangeWithSteps(0.0, 0.5, 1.0)\n\tresult8 := RangeWithSteps(0.0, 0.3, 0.1)\n\tresult9 := RangeWithSteps(0.0, 5.5, 2.5)\n\n\ttype f64 float64\n\tresult10 := RangeWithSteps[f64](0.0, 0.3, 0.1)\n\n\tis.Equal([]int{0, 6, 12, 18}, result1)\n\tis.Empty(result2)\n\tis.Empty(result3)\n\tis.Empty(result4)\n\tis.Equal([]float64{1.0, 3.0}, result5)\n\tis.Equal([]float32{-1.0, -2.0, -3.0}, result6)\n\tis.Equal([]float64{0.0}, result7)\n\tis.Equal([]float64{0.0, 0.1, 0.2}, result8)\n\tis.Equal([]float64{0.0, 2.5, 5.0}, result9)\n\tis.Equal([]f64{0.0, 0.1, 0.2}, result10)\n}\n\nfunc TestClamp(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := Clamp(0, -10, 10)\n\tresult2 := Clamp(-42, -10, 10)\n\tresult3 := Clamp(42, -10, 10)\n\n\tis.Zero(result1)\n\tis.Equal(-10, result2)\n\tis.Equal(10, result3)\n}\n\nfunc TestSum(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := Sum([]float32{2.3, 3.3, 4, 5.3})\n\tresult2 := Sum([]int32{2, 3, 4, 5})\n\tresult3 := Sum([]uint32{2, 3, 4, 5})\n\tresult4 := Sum([]uint32{})\n\tresult5 := Sum([]complex128{4_4, 2_2})\n\n\tis.InEpsilon(14.9, result1, 1e-7)\n\tis.Equal(int32(14), result2)\n\tis.Equal(uint32(14), result3)\n\tis.Equal(uint32(0), result4)\n\tis.Equal(complex128(6_6), result5)\n}\n\nfunc TestSumBy(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := SumBy([]float32{2.3, 3.3, 4, 5.3}, func(n float32) float32 { return n })\n\tresult2 := SumBy([]int32{2, 3, 4, 5}, func(n int32) int32 { return n })\n\tresult3 := SumBy([]uint32{2, 3, 4, 5}, func(n uint32) uint32 { return n })\n\tresult4 := SumBy([]uint32{}, func(n uint32) uint32 { return n })\n\tresult5 := SumBy([]complex128{4_4, 2_2}, func(n complex128) complex128 { return n })\n\n\tis.InEpsilon(14.9, result1, 1e-7)\n\tis.Equal(int32(14), result2)\n\tis.Equal(uint32(14), result3)\n\tis.Equal(uint32(0), result4)\n\tis.Equal(complex128(6_6), result5)\n}\n\nfunc TestSumByErr(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\t// Test normal operation (no error)\n\tresult1, err1 := SumByErr([]float32{2.3, 3.3, 4, 5.3}, func(n float32) (float32, error) { return n, nil })\n\tresult2, err2 := SumByErr([]int32{2, 3, 4, 5}, func(n int32) (int32, error) { return n, nil })\n\tresult3, err3 := SumByErr([]uint32{2, 3, 4, 5}, func(n uint32) (uint32, error) { return n, nil })\n\tresult4, err4 := SumByErr([]complex128{4_4, 2_2}, func(n complex128) (complex128, error) { return n, nil })\n\n\tis.NoError(err1)\n\tis.InEpsilon(14.9, result1, 1e-7)\n\tis.NoError(err2)\n\tis.Equal(int32(14), result2)\n\tis.NoError(err3)\n\tis.Equal(uint32(14), result3)\n\tis.NoError(err4)\n\tis.Equal(complex128(6_6), result4)\n\n\t// Test empty collection\n\tresult5, err5 := SumByErr([]uint32{}, func(n uint32) (uint32, error) { return n, nil })\n\tis.NoError(err5)\n\tis.Equal(uint32(0), result5)\n\n\t// Test error - iteratee returns error\n\ttestErr := assert.AnError\n\tresult6, err6 := SumByErr([]int32{1, 2, 3, 4, 5}, func(n int32) (int32, error) {\n\t\tif n == 3 {\n\t\t\treturn 0, testErr\n\t\t}\n\t\treturn n, nil\n\t})\n\tis.ErrorIs(err6, testErr)\n\t// Early return: sum up to 1+2 = 3\n\tis.Equal(int32(3), result6)\n\n\t// Test early return - callback count verification\n\t// With 5 elements and error at 3rd, only 3 callbacks should be made\n\titems := []int32{1, 2, 3, 4, 5}\n\tcallbackCount := 0\n\t_, err7 := SumByErr(items, func(n int32) (int32, error) {\n\t\tcallbackCount++\n\t\tif n == 3 {\n\t\t\treturn 0, testErr\n\t\t}\n\t\treturn n, nil\n\t})\n\tis.ErrorIs(err7, testErr)\n\tis.Equal(3, callbackCount) // Only 3 callbacks before error\n\n\t// Test error at first element\n\tresult8, err8 := SumByErr([]int32{1, 2, 3}, func(n int32) (int32, error) {\n\t\treturn 0, testErr\n\t})\n\tis.ErrorIs(err8, testErr)\n\tis.Equal(int32(0), result8)\n\n\t// Test error at last element\n\tcallbackCount2 := 0\n\tresult9, err9 := SumByErr([]int32{1, 2, 3}, func(n int32) (int32, error) {\n\t\tcallbackCount2++\n\t\tif n == 3 {\n\t\t\treturn 0, testErr\n\t\t}\n\t\treturn n, nil\n\t})\n\t_ = result9 // unused due to error\n\tis.ErrorIs(err9, testErr)\n\tis.Equal(3, callbackCount2) // All 3 callbacks before error at last element\n}\n\nfunc TestProduct(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := Product([]float32{2.3, 3.3, 4, 5.3})\n\tresult2 := Product([]int32{2, 3, 4, 5})\n\tresult3 := Product([]int32{7, 8, 9, 0})\n\tresult4 := Product([]int32{7, -1, 9, 2})\n\tresult5 := Product([]uint32{2, 3, 4, 5})\n\tresult6 := Product([]uint32{})\n\tresult7 := Product([]complex128{4_4, 2_2})\n\tresult8 := Product[uint32](nil)\n\n\tis.InEpsilon(160.908, result1, 1e-7)\n\tis.Equal(int32(120), result2)\n\tis.Equal(int32(0), result3)\n\tis.Equal(int32(-126), result4)\n\tis.Equal(uint32(120), result5)\n\tis.Equal(uint32(1), result6)\n\tis.Equal(complex128(96_8), result7)\n\tis.Equal(uint32(1), result8)\n}\n\nfunc TestProductBy(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := ProductBy([]float32{2.3, 3.3, 4, 5.3}, func(n float32) float32 { return n })\n\tresult2 := ProductBy([]int32{2, 3, 4, 5}, func(n int32) int32 { return n })\n\tresult3 := ProductBy([]int32{7, 8, 9, 0}, func(n int32) int32 { return n })\n\tresult4 := ProductBy([]int32{7, -1, 9, 2}, func(n int32) int32 { return n })\n\tresult5 := ProductBy([]uint32{2, 3, 4, 5}, func(n uint32) uint32 { return n })\n\tresult6 := ProductBy([]uint32{}, func(n uint32) uint32 { return n })\n\tresult7 := ProductBy([]complex128{4_4, 2_2}, func(n complex128) complex128 { return n })\n\tresult8 := ProductBy(nil, func(n uint32) uint32 { return n })\n\n\tis.InEpsilon(160.908, result1, 1e-7)\n\tis.Equal(int32(120), result2)\n\tis.Equal(int32(0), result3)\n\tis.Equal(int32(-126), result4)\n\tis.Equal(uint32(120), result5)\n\tis.Equal(uint32(1), result6)\n\tis.Equal(complex128(96_8), result7)\n\tis.Equal(uint32(1), result8)\n}\n\n//nolint:errcheck,forcetypeassert\nfunc TestProductByErr(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\ttestErr := assert.AnError\n\n\t// Test normal operation (no error) - table driven\n\ttests := []struct {\n\t\tname     string\n\t\tinput    any\n\t\texpected any\n\t}{\n\t\t{\n\t\t\tname:     \"float32 slice\",\n\t\t\tinput:    []float32{2.3, 3.3, 4, 5.3},\n\t\t\texpected: float32(160.908),\n\t\t},\n\t\t{\n\t\t\tname:     \"int32 slice\",\n\t\t\tinput:    []int32{2, 3, 4, 5},\n\t\t\texpected: int32(120),\n\t\t},\n\t\t{\n\t\t\tname:     \"int32 slice with zero\",\n\t\t\tinput:    []int32{7, 8, 9, 0},\n\t\t\texpected: int32(0),\n\t\t},\n\t\t{\n\t\t\tname:     \"int32 slice with negative\",\n\t\t\tinput:    []int32{7, -1, 9, 2},\n\t\t\texpected: int32(-126),\n\t\t},\n\t\t{\n\t\t\tname:     \"uint32 slice\",\n\t\t\tinput:    []uint32{2, 3, 4, 5},\n\t\t\texpected: uint32(120),\n\t\t},\n\t\t{\n\t\t\tname:     \"empty uint32 slice\",\n\t\t\tinput:    []uint32{},\n\t\t\texpected: uint32(1),\n\t\t},\n\t\t{\n\t\t\tname:     \"complex128 slice\",\n\t\t\tinput:    []complex128{4 + 4i, 2 + 2i},\n\t\t\texpected: complex128(0 + 16i),\n\t\t},\n\t\t{\n\t\t\tname:     \"nil int32 slice\",\n\t\t\tinput:    ([]int32)(nil),\n\t\t\texpected: int32(1),\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\ttt := tt\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\n\t\t\tswitch input := tt.input.(type) {\n\t\t\tcase []float32:\n\t\t\t\tresult, err := ProductByErr(input, func(n float32) (float32, error) { return n, nil })\n\t\t\t\tis.NoError(err)\n\t\t\t\tis.InEpsilon(tt.expected.(float32), result, 1e-7)\n\t\t\tcase []int32:\n\t\t\t\tresult, err := ProductByErr(input, func(n int32) (int32, error) { return n, nil })\n\t\t\t\tis.NoError(err)\n\t\t\t\tis.Equal(tt.expected.(int32), result)\n\t\t\tcase []uint32:\n\t\t\t\tresult, err := ProductByErr(input, func(n uint32) (uint32, error) { return n, nil })\n\t\t\t\tis.NoError(err)\n\t\t\t\tis.Equal(tt.expected.(uint32), result)\n\t\t\tcase []complex128:\n\t\t\t\tresult, err := ProductByErr(input, func(n complex128) (complex128, error) { return n, nil })\n\t\t\t\tis.NoError(err)\n\t\t\t\tis.Equal(tt.expected.(complex128), result)\n\t\t\t}\n\t\t})\n\t}\n\n\t// Test error cases - table driven\n\terrorTests := []struct {\n\t\tname          string\n\t\tinput         []int32\n\t\terrorAt       int32\n\t\texpectedProd  int32\n\t\texpectedCalls int\n\t}{\n\t\t{\n\t\t\tname:          \"error at third element\",\n\t\t\tinput:         []int32{1, 2, 3, 4, 5},\n\t\t\terrorAt:       3,\n\t\t\texpectedProd:  2, // 1 * 2\n\t\t\texpectedCalls: 3,\n\t\t},\n\t\t{\n\t\t\tname:          \"error at first element\",\n\t\t\tinput:         []int32{1, 2, 3},\n\t\t\terrorAt:       1,\n\t\t\texpectedProd:  1, // initial value\n\t\t\texpectedCalls: 1,\n\t\t},\n\t\t{\n\t\t\tname:          \"error at last element\",\n\t\t\tinput:         []int32{1, 2, 3},\n\t\t\terrorAt:       3,\n\t\t\texpectedProd:  2, // 1 * 2\n\t\t\texpectedCalls: 3,\n\t\t},\n\t}\n\n\tfor _, tt := range errorTests {\n\t\ttt := tt\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\n\t\t\tcallbackCount := 0\n\t\t\tresult, err := ProductByErr(tt.input, func(n int32) (int32, error) {\n\t\t\t\tcallbackCount++\n\t\t\t\tif n == tt.errorAt {\n\t\t\t\t\treturn 0, testErr\n\t\t\t\t}\n\t\t\t\treturn n, nil\n\t\t\t})\n\t\t\tis.ErrorIs(err, testErr)\n\t\t\tis.Equal(tt.expectedProd, result)\n\t\t\tis.Equal(tt.expectedCalls, callbackCount)\n\t\t})\n\t}\n}\n\nfunc TestMean(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := Mean([]float32{2.3, 3.3, 4, 5.3})\n\tresult2 := Mean([]int32{2, 3, 4, 5})\n\tresult3 := Mean([]uint32{2, 3, 4, 5})\n\tresult4 := Mean([]uint32{})\n\n\tis.InEpsilon(3.725, result1, 1e-7)\n\tis.Equal(int32(3), result2)\n\tis.Equal(uint32(3), result3)\n\tis.Equal(uint32(0), result4)\n}\n\nfunc TestMeanBy(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := MeanBy([]float32{2.3, 3.3, 4, 5.3}, func(n float32) float32 { return n })\n\tresult2 := MeanBy([]int32{2, 3, 4, 5}, func(n int32) int32 { return n })\n\tresult3 := MeanBy([]uint32{2, 3, 4, 5}, func(n uint32) uint32 { return n })\n\tresult4 := MeanBy([]uint32{}, func(n uint32) uint32 { return n })\n\n\tis.InEpsilon(3.725, result1, 1e-7)\n\tis.Equal(int32(3), result2)\n\tis.Equal(uint32(3), result3)\n\tis.Equal(uint32(0), result4)\n}\n\n//nolint:errcheck,forcetypeassert\nfunc TestMeanByErr(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\ttestErr := assert.AnError\n\n\t// Test normal operation (no error) - table driven\n\ttests := []struct {\n\t\tname     string\n\t\tinput    any\n\t\texpected any\n\t}{\n\t\t{\n\t\t\tname:     \"float32 slice\",\n\t\t\tinput:    []float32{2.3, 3.3, 4, 5.3},\n\t\t\texpected: float32(3.725),\n\t\t},\n\t\t{\n\t\t\tname:     \"int32 slice\",\n\t\t\tinput:    []int32{2, 3, 4, 5},\n\t\t\texpected: int32(3),\n\t\t},\n\t\t{\n\t\t\tname:     \"uint32 slice\",\n\t\t\tinput:    []uint32{2, 3, 4, 5},\n\t\t\texpected: uint32(3),\n\t\t},\n\t\t{\n\t\t\tname:     \"empty uint32 slice\",\n\t\t\tinput:    []uint32{},\n\t\t\texpected: uint32(0),\n\t\t},\n\t\t{\n\t\t\tname:     \"nil int32 slice\",\n\t\t\tinput:    ([]int32)(nil),\n\t\t\texpected: int32(0),\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\ttt := tt\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\n\t\t\tswitch input := tt.input.(type) {\n\t\t\tcase []float32:\n\t\t\t\tresult, err := MeanByErr(input, func(n float32) (float32, error) { return n, nil })\n\t\t\t\tis.NoError(err)\n\t\t\t\tis.InEpsilon(tt.expected.(float32), result, 1e-7)\n\t\t\tcase []int32:\n\t\t\t\tresult, err := MeanByErr(input, func(n int32) (int32, error) { return n, nil })\n\t\t\t\tis.NoError(err)\n\t\t\t\tis.Equal(tt.expected.(int32), result)\n\t\t\tcase []uint32:\n\t\t\t\tresult, err := MeanByErr(input, func(n uint32) (uint32, error) { return n, nil })\n\t\t\t\tis.NoError(err)\n\t\t\t\tis.Equal(tt.expected.(uint32), result)\n\t\t\t}\n\t\t})\n\t}\n\n\t// Test error cases - table driven\n\terrorTests := []struct {\n\t\tname          string\n\t\tinput         []int32\n\t\terrorAt       int32\n\t\texpectedCalls int\n\t}{\n\t\t{\n\t\t\tname:          \"error at third element\",\n\t\t\tinput:         []int32{1, 2, 3, 4, 5},\n\t\t\terrorAt:       3,\n\t\t\texpectedCalls: 3,\n\t\t},\n\t\t{\n\t\t\tname:          \"error at first element\",\n\t\t\tinput:         []int32{1, 2, 3},\n\t\t\terrorAt:       1,\n\t\t\texpectedCalls: 1,\n\t\t},\n\t\t{\n\t\t\tname:          \"error at last element\",\n\t\t\tinput:         []int32{1, 2, 3},\n\t\t\terrorAt:       3,\n\t\t\texpectedCalls: 3,\n\t\t},\n\t}\n\n\tfor _, tt := range errorTests {\n\t\ttt := tt\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\n\t\t\tcallbackCount := 0\n\t\t\t_, err := MeanByErr(tt.input, func(n int32) (int32, error) {\n\t\t\t\tcallbackCount++\n\t\t\t\tif n == tt.errorAt {\n\t\t\t\t\treturn 0, testErr\n\t\t\t\t}\n\t\t\t\treturn n, nil\n\t\t\t})\n\t\t\tis.ErrorIs(err, testErr)\n\t\t\tis.Equal(tt.expectedCalls, callbackCount)\n\t\t})\n\t}\n}\n\nfunc TestMode(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := Mode([]float32{2.3, 3.3, 3.3, 5.3})\n\tresult2 := Mode([]int32{2, 2, 3, 4})\n\tresult3 := Mode([]uint32{2, 2, 3, 3})\n\tresult4 := Mode([]uint32{})\n\tresult5 := Mode([]int{1, 2, 3, 4, 5, 6, 7, 8, 9})\n\n\tis.Equal([]float32{3.3}, result1)\n\tis.Equal([]int32{2}, result2)\n\tis.Equal([]uint32{2, 3}, result3)\n\tis.Empty(result4)\n\tis.Equal([]int{1, 2, 3, 4, 5, 6, 7, 8, 9}, result5)\n}\n\nfunc TestModeCapacityConsistency(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tarr := []int{1, 1, 2, 2, 3, 3, 3}\n\n\tresult := Mode(arr)\n\n\tis.Equal([]int{3}, result, \"Mode should return correct mode value\")\n\tis.Equal(len(result), cap(result), \"Mode slice capacity should match its length\")\n}\n"
  },
  {
    "path": "mutable/slice.go",
    "content": "package mutable\n\nimport \"github.com/samber/lo/internal/xrand\"\n\n// Filter is a generic function that modifies the input slice in-place to contain only the elements\n// that satisfy the provided predicate function. The predicate function takes an element of the slice and its index,\n// and should return true for elements that should be kept and false for elements that should be removed.\n// The function returns the modified slice, which may be shorter than the original if some elements were removed.\n// Note that the order of elements in the original slice is preserved in the output.\n// Play: https://go.dev/play/p/0jY3Z0B7O_5\nfunc Filter[T any, Slice ~[]T](collection Slice, predicate func(item T) bool) Slice {\n\tj := 0\n\tfor i := range collection {\n\t\tif predicate(collection[i]) {\n\t\t\tcollection[j] = collection[i]\n\t\t\tj++\n\t\t}\n\t}\n\treturn collection[:j]\n}\n\n// FilterI is a generic function that modifies the input slice in-place to contain only the elements\n// that satisfy the provided predicate function. The predicate function takes an element of the slice and its index,\n// and should return true for elements that should be kept and false for elements that should be removed.\n// The function returns the modified slice, which may be shorter than the original if some elements were removed.\n// Note that the order of elements in the original slice is preserved in the output.\nfunc FilterI[T any, Slice ~[]T](collection Slice, predicate func(item T, index int) bool) Slice {\n\tj := 0\n\tfor i := range collection {\n\t\tif predicate(collection[i], i) {\n\t\t\tcollection[j] = collection[i]\n\t\t\tj++\n\t\t}\n\t}\n\treturn collection[:j]\n}\n\n// Map is a generic function that modifies the input slice in-place to contain the result of applying the provided\n// function to each element of the slice. The function returns the modified slice, which has the same length as the original.\n// Play: https://go.dev/play/p/0jY3Z0B7O_5\nfunc Map[T any, Slice ~[]T](collection Slice, transform func(item T) T) {\n\tfor i := range collection {\n\t\tcollection[i] = transform(collection[i])\n\t}\n}\n\n// MapI is a generic function that modifies the input slice in-place to contain the result of applying the provided\n// function to each element of the slice. The function returns the modified slice, which has the same length as the original.\nfunc MapI[T any, Slice ~[]T](collection Slice, transform func(item T, index int) T) {\n\tfor i := range collection {\n\t\tcollection[i] = transform(collection[i], i)\n\t}\n}\n\n// Shuffle returns a slice of shuffled values. Uses the Fisher-Yates shuffle algorithm.\n// Play: https://go.dev/play/p/2xb3WdLjeSJ\nfunc Shuffle[T any, Slice ~[]T](collection Slice) {\n\txrand.Shuffle(len(collection), func(i, j int) {\n\t\tcollection[i], collection[j] = collection[j], collection[i]\n\t})\n}\n\n// Reverse reverses a slice so that the first element becomes the last, the second element becomes the second to last, and so on.\n// Play: https://go.dev/play/p/O-M5pmCRgzV\nfunc Reverse[T any, Slice ~[]T](collection Slice) {\n\tlength := len(collection)\n\thalf := length / 2\n\n\tfor i := 0; i < half; i++ {\n\t\tj := length - 1 - i\n\t\tcollection[i], collection[j] = collection[j], collection[i]\n\t}\n}\n"
  },
  {
    "path": "mutable/slice_example_test.go",
    "content": "package mutable\n\nimport \"fmt\"\n\nfunc ExampleFilter() {\n\tlist := []int{1, 2, 3, 4}\n\n\tnewList := Filter(list, func(nbr int) bool {\n\t\treturn nbr%2 == 0\n\t})\n\n\tfmt.Printf(\"%v\\n%v\", list, newList)\n\t// Output:\n\t// [2 4 3 4]\n\t// [2 4]\n}\n\nfunc ExampleFilterI() {\n\tlist := []int{1, 2, 3, 4}\n\n\tnewList := Filter(list, func(nbr int) bool {\n\t\treturn nbr%2 == 0\n\t})\n\n\tfmt.Printf(\"%v\\n%v\", list, newList)\n\t// Output:\n\t// [2 4 3 4]\n\t// [2 4]\n}\n\nfunc ExampleMap() {\n\tlist := []int{1, 2, 3, 4}\n\n\tMap(list, func(nbr int) int {\n\t\treturn nbr * 2\n\t})\n\n\tfmt.Printf(\"%v\", list)\n\t// Output: [2 4 6 8]\n}\n\nfunc ExampleMapI() {\n\tlist := []int{1, 2, 3, 4}\n\n\tMapI(list, func(nbr, index int) int {\n\t\treturn nbr * index\n\t})\n\n\tfmt.Printf(\"%v\", list)\n\t// Output: [0 2 6 12]\n}\n\nfunc ExampleShuffle() {\n\tlist := []int{0, 1, 2, 3, 4, 5}\n\n\tShuffle(list)\n\n\tfmt.Printf(\"%v\", list)\n}\n\nfunc ExampleReverse() {\n\tlist := []int{0, 1, 2, 3, 4, 5}\n\n\tReverse(list)\n\n\tfmt.Printf(\"%v\", list)\n\t// Output: [5 4 3 2 1 0]\n}\n\n// Fill fills elements of a slice with `initial` value.\n// Play: https://go.dev/play/p/VwR34GzqEub\nfunc Fill[T any, Slice ~[]T](collection Slice, initial T) {\n\tfor i := range collection {\n\t\tcollection[i] = initial\n\t}\n}\n"
  },
  {
    "path": "mutable/slice_test.go",
    "content": "package mutable\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestFilter(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tinput1 := []int{1, 2, 3, 4}\n\tr1 := Filter(input1, func(x int) bool {\n\t\treturn x%2 == 0\n\t})\n\n\tis.Equal([]int{2, 4, 3, 4}, input1)\n\tis.Equal([]int{2, 4}, r1)\n\n\tinput2 := []string{\"\", \"foo\", \"\", \"bar\", \"\"}\n\tr2 := Filter(input2, func(x string) bool {\n\t\treturn len(x) > 0\n\t})\n\n\tis.Equal([]string{\"foo\", \"bar\", \"\", \"bar\", \"\"}, input2)\n\tis.Equal([]string{\"foo\", \"bar\"}, r2)\n}\n\nfunc TestFilterI(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tr1 := FilterI([]int{1, 2, 3, 4}, func(x, i int) bool {\n\t\tis.Equal(i, x-1)\n\t\treturn x%2 == 0\n\t})\n\n\tis.Equal([]int{2, 4}, r1)\n}\n\nfunc TestMap(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tlist := []int{1, 2, 3, 4}\n\tMap(list, func(x int) int {\n\t\treturn x * 2\n\t})\n\tis.Equal([]int{2, 4, 6, 8}, list)\n\n\tlist = []int{1, 2, 3, 4}\n\tMap(list, func(x int) int {\n\t\treturn x * 4\n\t})\n\tis.Equal([]int{4, 8, 12, 16}, list)\n}\n\nfunc TestMapI(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tlist := []int{1, 2, 3, 4}\n\tMapI(list, func(x, index int) int {\n\t\tis.Equal(index, x-1)\n\t\treturn x * 2\n\t})\n\tis.Equal([]int{2, 4, 6, 8}, list)\n\n\tlist = []int{1, 2, 3, 4}\n\tMapI(list, func(x, index int) int {\n\t\tis.Equal(index, x-1)\n\t\treturn x * 4\n\t})\n\tis.Equal([]int{4, 8, 12, 16}, list)\n}\n\nfunc TestShuffle(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tlist := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}\n\tShuffle(list)\n\tis.NotEqual([]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, list)\n\n\tlist = []int{}\n\tShuffle(list)\n\tis.Empty(list)\n}\n\nfunc TestReverse(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tlist := []int{0, 1, 2, 3, 4, 5}\n\tReverse(list)\n\tis.Equal([]int{5, 4, 3, 2, 1, 0}, list)\n\n\tlist = []int{0, 1, 2, 3, 4, 5, 6}\n\tReverse(list)\n\tis.Equal([]int{6, 5, 4, 3, 2, 1, 0}, list)\n\n\tlist = []int{}\n\tReverse(list)\n\tis.Empty(list)\n\n\ttype myStrings []string\n\tallStrings := myStrings{\"\", \"foo\", \"bar\"}\n\tReverse(allStrings)\n\tis.IsType(myStrings{\"\", \"foo\", \"bar\"}, allStrings, \"type preserved\")\n}\n\nfunc TestFill(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tlist1 := []string{\"a\", \"0\"}\n\tFill(list1, \"b\")\n\tis.Equal([]string{\"b\", \"b\"}, list1)\n\n\tlist2 := []string{}\n\tFill(list2, \"b\")\n\tis.Empty(list2)\n}\n"
  },
  {
    "path": "parallel/slice.go",
    "content": "package parallel\n\nimport \"sync\"\n\n// Map manipulates a slice and transforms it to a slice of another type.\n// `transform` is called in parallel. Result keep the same order.\n// Play: https://go.dev/play/p/sCJaB3quRMC\nfunc Map[T, R any](collection []T, transform func(item T, index int) R) []R {\n\tresult := make([]R, len(collection))\n\n\tvar wg sync.WaitGroup\n\twg.Add(len(collection))\n\n\tfor i, item := range collection {\n\t\tgo func(_item T, _i int) {\n\t\t\tres := transform(_item, _i)\n\n\t\t\tresult[_i] = res\n\n\t\t\twg.Done()\n\t\t}(item, i)\n\t}\n\n\twg.Wait()\n\n\treturn result\n}\n\n// ForEach iterates over elements of collection and invokes callback for each element.\n// `iteratee` is called in parallel.\n// Play: https://go.dev/play/p/sCJaB3quRMC\nfunc ForEach[T any](collection []T, callback func(item T, index int)) {\n\tvar wg sync.WaitGroup\n\twg.Add(len(collection))\n\n\tfor i, item := range collection {\n\t\tgo func(_item T, _i int) {\n\t\t\tcallback(_item, _i)\n\t\t\twg.Done()\n\t\t}(item, i)\n\t}\n\n\twg.Wait()\n}\n\n// Times invokes the iteratee n times, returning a slice of the results of each invocation.\n// The iteratee is invoked with index as argument.\n// `iteratee` is called in parallel.\n// Play: https://go.dev/play/p/ZNnWNcJ4Au-\nfunc Times[T any](count int, iteratee func(index int) T) []T {\n\tresult := make([]T, count)\n\n\tvar wg sync.WaitGroup\n\twg.Add(count)\n\n\tfor i := 0; i < count; i++ {\n\t\tgo func(_i int) {\n\t\t\titem := iteratee(_i)\n\n\t\t\tresult[_i] = item\n\n\t\t\twg.Done()\n\t\t}(i)\n\t}\n\n\twg.Wait()\n\n\treturn result\n}\n\n// GroupBy returns an object composed of keys generated from the results of running each element of collection through iteratee.\n// The order of grouped values is determined by the order they occur in the collection.\n// `iteratee` is called in parallel.\n// Play: https://go.dev/play/p/EkyvA0gw4dj\nfunc GroupBy[T any, U comparable, Slice ~[]T](collection Slice, iteratee func(item T) U) map[U]Slice {\n\tresult := map[U]Slice{}\n\n\tkeys := Map(collection, func(item T, _ int) U {\n\t\treturn iteratee(item)\n\t})\n\n\tfor i, item := range collection {\n\t\tresult[keys[i]] = append(result[keys[i]], item)\n\t}\n\n\treturn result\n}\n\n// PartitionBy returns a slice of elements split into groups. The order of grouped values is\n// determined by the order they occur in collection. The grouping is generated from the results\n// of running each element of collection through iteratee.\n// The order of groups is determined by their first appearance in the collection.\n// `iteratee` is called in parallel.\n// Play: https://go.dev/play/p/GwBQdMgx2nC\nfunc PartitionBy[T any, K comparable, Slice ~[]T](collection Slice, iteratee func(item T) K) []Slice {\n\tresult := []Slice{}\n\tseen := map[K]int{}\n\n\tkeys := Map(collection, func(item T, _ int) K {\n\t\treturn iteratee(item)\n\t})\n\n\tfor i := range collection {\n\t\tresultIndex, ok := seen[keys[i]]\n\t\tif ok {\n\t\t\tresult[resultIndex] = append(result[resultIndex], collection[i])\n\t\t} else {\n\t\t\tseen[keys[i]] = len(result)\n\t\t\tresult = append(result, Slice{collection[i]})\n\t\t}\n\t}\n\n\treturn result\n}\n"
  },
  {
    "path": "parallel/slice_test.go",
    "content": "package parallel\n\nimport (\n\t\"sort\"\n\t\"strconv\"\n\t\"sync/atomic\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestMap(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := Map([]int{1, 2, 3, 4}, func(x, _ int) string {\n\t\treturn \"Hello\"\n\t})\n\tresult2 := Map([]int64{1, 2, 3, 4}, func(x int64, _ int) string {\n\t\treturn strconv.FormatInt(x, 10)\n\t})\n\n\tis.Equal([]string{\"Hello\", \"Hello\", \"Hello\", \"Hello\"}, result1)\n\tis.Equal([]string{\"1\", \"2\", \"3\", \"4\"}, result2)\n}\n\nfunc TestForEach(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tvar counter uint64\n\tcollection := []int{1, 2, 3, 4}\n\tForEach(collection, func(x, i int) {\n\t\tatomic.AddUint64(&counter, 1)\n\t})\n\n\tis.Equal(uint64(4), atomic.LoadUint64(&counter))\n}\n\nfunc TestTimes(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := Times(3, func(i int) string {\n\t\treturn strconv.FormatInt(int64(i), 10)\n\t})\n\n\tis.Equal([]string{\"0\", \"1\", \"2\"}, result1)\n}\n\nfunc TestGroupBy(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := GroupBy([]int{0, 1, 2, 3, 4, 5}, func(i int) int {\n\t\treturn i % 3\n\t})\n\n\t// order\n\tfor x := range result1 {\n\t\tsort.Ints(result1[x])\n\t}\n\n\tis.Equal(map[int][]int{\n\t\t0: {0, 3},\n\t\t1: {1, 4},\n\t\t2: {2, 5},\n\t}, result1)\n\n\ttype myStrings []string\n\tallStrings := myStrings{\"\", \"foo\", \"bar\"}\n\tnonempty := GroupBy(allStrings, func(i string) int {\n\t\treturn 42\n\t})\n\tis.IsType(nonempty[42], allStrings, \"type preserved\")\n}\n\nfunc TestPartitionBy(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\toddEven := func(x int) string {\n\t\tif x < 0 {\n\t\t\treturn \"negative\"\n\t\t} else if x%2 == 0 {\n\t\t\treturn \"even\"\n\t\t}\n\t\treturn \"odd\"\n\t}\n\n\tresult1 := PartitionBy([]int{-2, -1, 0, 1, 2, 3, 4, 5}, oddEven)\n\tresult2 := PartitionBy([]int{}, oddEven)\n\n\t// order\n\tsort.Slice(result1, func(i, j int) bool {\n\t\treturn result1[i][0] < result1[j][0]\n\t})\n\tfor x := range result1 {\n\t\tsort.Ints(result1[x])\n\t}\n\n\tis.ElementsMatch(result1, [][]int{{-2, -1}, {0, 2, 4}, {1, 3, 5}})\n\tis.Empty(result2)\n\n\ttype myStrings []string\n\tallStrings := myStrings{\"\", \"foo\", \"bar\"}\n\tnonempty := PartitionBy(allStrings, func(item string) int {\n\t\treturn len(item)\n\t})\n\tis.IsType(nonempty[0], allStrings, \"type preserved\")\n}\n"
  },
  {
    "path": "retry.go",
    "content": "package lo\n\nimport (\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com/samber/lo/internal/xtime\"\n)\n\ntype debounce struct {\n\tafter     time.Duration\n\tmu        *sync.Mutex\n\ttimer     *time.Timer\n\tdone      bool\n\tcallbacks []func()\n}\n\nfunc (d *debounce) reset() {\n\td.mu.Lock()\n\tdefer d.mu.Unlock()\n\n\tif d.done {\n\t\treturn\n\t}\n\n\tif d.timer != nil {\n\t\td.timer.Stop()\n\t}\n\n\td.timer = time.AfterFunc(d.after, func() {\n\t\t// We need to lock the mutex here to avoid race conditions with 2 concurrent calls to reset()\n\t\td.mu.Lock()\n\t\tcallbacks := append([]func(){}, d.callbacks...)\n\t\td.mu.Unlock()\n\n\t\tfor i := range callbacks {\n\t\t\tcallbacks[i]()\n\t\t}\n\t})\n}\n\nfunc (d *debounce) cancel() {\n\td.mu.Lock()\n\tdefer d.mu.Unlock()\n\n\tif d.timer != nil {\n\t\td.timer.Stop()\n\t\td.timer = nil\n\t}\n\n\td.done = true\n}\n\n// NewDebounce creates a debounced instance that delays invoking functions given until after wait milliseconds have elapsed.\n// Play: https://go.dev/play/p/_IPY7ROzbMk\nfunc NewDebounce(duration time.Duration, f ...func()) (func(), func()) {\n\td := &debounce{\n\t\tafter:     duration,\n\t\tmu:        new(sync.Mutex),\n\t\ttimer:     nil,\n\t\tdone:      false,\n\t\tcallbacks: f,\n\t}\n\n\treturn func() {\n\t\td.reset()\n\t}, d.cancel\n}\n\ntype debounceByItem struct {\n\tmu    *sync.Mutex\n\ttimer *time.Timer\n\tcount int\n}\n\ntype debounceBy[T comparable] struct {\n\tafter     time.Duration\n\tmu        *sync.Mutex\n\titems     map[T]*debounceByItem\n\tcallbacks []func(key T, count int)\n}\n\nfunc (d *debounceBy[T]) reset(key T) {\n\td.mu.Lock()\n\tif _, ok := d.items[key]; !ok {\n\t\td.items[key] = &debounceByItem{\n\t\t\tmu:    new(sync.Mutex),\n\t\t\ttimer: nil,\n\t\t}\n\t}\n\n\titem := d.items[key]\n\n\td.mu.Unlock()\n\n\titem.mu.Lock()\n\tdefer item.mu.Unlock()\n\n\titem.count++\n\n\tif item.timer != nil {\n\t\titem.timer.Stop()\n\t}\n\n\titem.timer = time.AfterFunc(d.after, func() {\n\t\t// We need to lock the mutex here to avoid race conditions with 2 concurrent calls to reset()\n\t\titem.mu.Lock()\n\t\tcount := item.count\n\t\titem.count = 0\n\t\tcallbacks := append([]func(key T, count int){}, d.callbacks...)\n\t\titem.mu.Unlock()\n\n\t\tfor i := range callbacks {\n\t\t\tcallbacks[i](key, count)\n\t\t}\n\t})\n}\n\nfunc (d *debounceBy[T]) cancel(key T) {\n\td.mu.Lock()\n\tdefer d.mu.Unlock()\n\n\tif item, ok := d.items[key]; ok {\n\t\titem.mu.Lock()\n\n\t\tif item.timer != nil {\n\t\t\titem.timer.Stop()\n\t\t\titem.timer = nil\n\t\t}\n\n\t\titem.mu.Unlock()\n\n\t\tdelete(d.items, key)\n\t}\n}\n\n// NewDebounceBy creates a debounced instance for each distinct key, that delays invoking functions given until after wait milliseconds have elapsed.\n// Play: https://go.dev/play/p/Izk7GEzZm2Q\nfunc NewDebounceBy[T comparable](duration time.Duration, f ...func(key T, count int)) (func(key T), func(key T)) {\n\td := &debounceBy[T]{\n\t\tafter:     duration,\n\t\tmu:        new(sync.Mutex),\n\t\titems:     map[T]*debounceByItem{},\n\t\tcallbacks: f,\n\t}\n\n\treturn func(key T) {\n\t\td.reset(key)\n\t}, d.cancel\n}\n\n// Attempt invokes a function N times until it returns valid output. Returns either the caught error or nil.\n// When the first argument is less than `1`, the function runs until a successful response is returned.\n// Play: https://go.dev/play/p/3ggJZ2ZKcMj\nfunc Attempt(maxIteration int, f func(index int) error) (int, error) {\n\tvar err error\n\n\tfor i := 0; maxIteration <= 0 || i < maxIteration; i++ {\n\t\t// for retries >= 0 {\n\t\terr = f(i)\n\t\tif err == nil {\n\t\t\treturn i + 1, nil\n\t\t}\n\t}\n\n\treturn maxIteration, err\n}\n\n// AttemptWithDelay invokes a function N times until it returns valid output,\n// with a pause between each call. Returns either the caught error or nil.\n// When the first argument is less than `1`, the function runs until a successful\n// response is returned.\n// Play: https://go.dev/play/p/tVs6CygC7m1\nfunc AttemptWithDelay(maxIteration int, delay time.Duration, f func(index int, duration time.Duration) error) (int, time.Duration, error) {\n\tvar err error\n\n\tstart := xtime.Now()\n\n\tfor i := 0; maxIteration <= 0 || i < maxIteration; i++ {\n\t\terr = f(i, xtime.Since(start))\n\t\tif err == nil {\n\t\t\treturn i + 1, xtime.Since(start), nil\n\t\t}\n\n\t\tif maxIteration <= 0 || i+1 < maxIteration {\n\t\t\txtime.Sleep(delay)\n\t\t}\n\t}\n\n\treturn maxIteration, xtime.Since(start), err\n}\n\n// AttemptWhile invokes a function N times until it returns valid output.\n// Returns either the caught error or nil, along with a bool value to determine\n// whether the function should be invoked again. It will terminate the invoke\n// immediately if the second return value is false. When the first\n// argument is less than `1`, the function runs until a successful response is\n// returned.\n// Play: https://go.dev/play/p/1VS7HxlYMOG\nfunc AttemptWhile(maxIteration int, f func(int) (error, bool)) (int, error) {\n\tvar err error\n\tvar shouldContinueInvoke bool\n\n\tfor i := 0; maxIteration <= 0 || i < maxIteration; i++ {\n\t\t// for retries >= 0 {\n\t\terr, shouldContinueInvoke = f(i)\n\t\tif !shouldContinueInvoke { // if shouldContinueInvoke is false, then return immediately\n\t\t\treturn i + 1, err\n\t\t}\n\t\tif err == nil {\n\t\t\treturn i + 1, nil\n\t\t}\n\t}\n\n\treturn maxIteration, err\n}\n\n// AttemptWhileWithDelay invokes a function N times until it returns valid output,\n// with a pause between each call. Returns either the caught error or nil, along\n// with a bool value to determine whether the function should be invoked again.\n// It will terminate the invoke immediately if the second return value is false.\n// When the first argument is less than `1`, the function runs until a successful\n// response is returned.\n// Play: https://go.dev/play/p/mhufUjJfLEF\nfunc AttemptWhileWithDelay(maxIteration int, delay time.Duration, f func(int, time.Duration) (error, bool)) (int, time.Duration, error) {\n\tvar err error\n\tvar shouldContinueInvoke bool\n\n\tstart := xtime.Now()\n\n\tfor i := 0; maxIteration <= 0 || i < maxIteration; i++ {\n\t\terr, shouldContinueInvoke = f(i, xtime.Since(start))\n\t\tif !shouldContinueInvoke { // if shouldContinueInvoke is false, then return immediately\n\t\t\treturn i + 1, xtime.Since(start), err\n\t\t}\n\t\tif err == nil {\n\t\t\treturn i + 1, xtime.Since(start), nil\n\t\t}\n\n\t\tif maxIteration <= 0 || i+1 < maxIteration {\n\t\t\txtime.Sleep(delay)\n\t\t}\n\t}\n\n\treturn maxIteration, xtime.Since(start), err\n}\n\ntype transactionStep[T any] struct {\n\texec       func(T) (T, error)\n\tonRollback func(T) T\n}\n\n// NewTransaction instantiate a new transaction.\n// Play: https://go.dev/play/p/7B2o52wEQbj\nfunc NewTransaction[T any]() *Transaction[T] {\n\treturn &Transaction[T]{\n\t\tsteps: []transactionStep[T]{},\n\t}\n}\n\n// Transaction implements a Saga pattern.\ntype Transaction[T any] struct {\n\tsteps []transactionStep[T]\n}\n\n// Then adds a step to the chain of callbacks. Returns the same Transaction.\n// Play: https://go.dev/play/p/Qxrd7MGQGh1 https://go.dev/play/p/xrHb2_kMvTY\nfunc (t *Transaction[T]) Then(exec func(T) (T, error), onRollback func(T) T) *Transaction[T] {\n\tt.steps = append(t.steps, transactionStep[T]{\n\t\texec:       exec,\n\t\tonRollback: onRollback,\n\t})\n\n\treturn t\n}\n\n// Process runs the Transaction steps and rollbacks in case of errors.\n// Play: https://go.dev/play/p/Qxrd7MGQGh1 https://go.dev/play/p/xrHb2_kMvTY\nfunc (t *Transaction[T]) Process(state T) (T, error) {\n\tvar i int\n\tvar err error\n\n\tfor i < len(t.steps) {\n\t\tstate, err = t.steps[i].exec(state)\n\t\tif err != nil {\n\t\t\tbreak\n\t\t}\n\n\t\ti++\n\t}\n\n\tif err == nil {\n\t\treturn state, nil\n\t}\n\n\tfor i > 0 {\n\t\ti--\n\t\tstate = t.steps[i].onRollback(state)\n\t}\n\n\treturn state, err\n}\n\n// @TODO: single mutex per key?\ntype throttleBy[T comparable] struct {\n\tmu         *sync.Mutex\n\ttimer      *time.Timer\n\tinterval   time.Duration\n\tcallbacks  []func(key T)\n\tcountLimit int\n\tcount      map[T]int\n}\n\nfunc (th *throttleBy[T]) throttledFunc(key T) {\n\tth.mu.Lock()\n\tdefer th.mu.Unlock()\n\n\tif th.count[key] < th.countLimit {\n\t\tth.count[key]++\n\n\t\tfor _, f := range th.callbacks {\n\t\t\tf(key)\n\t\t}\n\t}\n\tif th.timer == nil {\n\t\tth.timer = time.AfterFunc(th.interval, func() {\n\t\t\tth.reset()\n\t\t})\n\t}\n}\n\nfunc (th *throttleBy[T]) reset() {\n\tth.mu.Lock()\n\tdefer th.mu.Unlock()\n\n\tif th.timer != nil {\n\t\tth.timer.Stop()\n\t}\n\n\tth.count = map[T]int{}\n\tth.timer = nil\n}\n\n// NewThrottle creates a throttled instance that invokes given functions only once in every interval.\n// This returns 2 functions, First one is throttled function and Second one is a function to reset interval.\n// Play: https://go.dev/play/p/qQn3fm8Z7jS\nfunc NewThrottle(interval time.Duration, f ...func()) (throttle, reset func()) {\n\treturn NewThrottleWithCount(interval, 1, f...)\n}\n\n// NewThrottleWithCount is NewThrottle with count limit, throttled function will be invoked count times in every interval.\n// Play: https://go.dev/play/p/w5nc0MgWtjC\nfunc NewThrottleWithCount(interval time.Duration, count int, f ...func()) (throttle, reset func()) {\n\tcallbacks := Map(f, func(item func(), _ int) func(struct{}) {\n\t\treturn func(struct{}) {\n\t\t\titem()\n\t\t}\n\t})\n\n\tthrottleFn, reset := NewThrottleByWithCount(interval, count, callbacks...)\n\treturn func() {\n\t\tthrottleFn(struct{}{})\n\t}, reset\n}\n\n// NewThrottleBy creates a throttled instance that invokes given functions only once in every interval.\n// This returns 2 functions, First one is throttled function and Second one is a function to reset interval.\n// Play: https://go.dev/play/p/0Wv6oX7dHdC\nfunc NewThrottleBy[T comparable](interval time.Duration, f ...func(key T)) (throttle func(key T), reset func()) {\n\treturn NewThrottleByWithCount(interval, 1, f...)\n}\n\n// NewThrottleByWithCount is NewThrottleBy with count limit, throttled function will be invoked count times in every interval.\n// Play: https://go.dev/play/p/vQk3ECH7_EW\nfunc NewThrottleByWithCount[T comparable](interval time.Duration, count int, f ...func(key T)) (throttle func(key T), reset func()) {\n\tif count <= 0 {\n\t\tcount = 1\n\t}\n\n\tth := &throttleBy[T]{\n\t\tmu:         new(sync.Mutex),\n\t\tinterval:   interval,\n\t\tcallbacks:  f,\n\t\tcountLimit: count,\n\t\tcount:      map[T]int{},\n\t}\n\treturn th.throttledFunc, th.reset\n}\n"
  },
  {
    "path": "retry_example_test.go",
    "content": "//go:build !race\n\npackage lo\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"sync\"\n\t\"sync/atomic\"\n\t\"time\"\n)\n\nfunc ExampleNewDebounce() {\n\ti := int32(0)\n\tcalls := []int32{}\n\tmu := sync.Mutex{}\n\n\tdebounce, cancel := NewDebounce(time.Millisecond, func() {\n\t\tmu.Lock()\n\t\tdefer mu.Unlock()\n\t\tcalls = append(calls, atomic.LoadInt32(&i))\n\t})\n\n\tdebounce()\n\tatomic.AddInt32(&i, 1)\n\n\ttime.Sleep(5 * time.Millisecond)\n\n\tdebounce()\n\tatomic.AddInt32(&i, 1)\n\tdebounce()\n\tatomic.AddInt32(&i, 1)\n\tdebounce()\n\tatomic.AddInt32(&i, 1)\n\n\ttime.Sleep(5 * time.Millisecond)\n\n\tcancel()\n\n\tmu.Lock()\n\tfmt.Printf(\"%v\", calls)\n\tmu.Unlock()\n\t// Output: [1 4]\n}\n\nfunc ExampleNewDebounceBy() {\n\tcalls := map[string][]int{}\n\tmu := sync.Mutex{}\n\n\tdebounce, cancel := NewDebounceBy(time.Millisecond, func(userID string, count int) {\n\t\tmu.Lock()\n\t\tdefer mu.Unlock()\n\n\t\tif _, ok := calls[userID]; !ok {\n\t\t\tcalls[userID] = []int{}\n\t\t}\n\n\t\tcalls[userID] = append(calls[userID], count)\n\t})\n\n\tdebounce(\"samuel\")\n\tdebounce(\"john\")\n\n\ttime.Sleep(5 * time.Millisecond)\n\n\tdebounce(\"john\")\n\tdebounce(\"john\")\n\tdebounce(\"samuel\")\n\tdebounce(\"john\")\n\n\ttime.Sleep(5 * time.Millisecond)\n\n\tcancel(\"samuel\")\n\tcancel(\"john\")\n\n\tmu.Lock()\n\tfmt.Printf(\"samuel: %v\\n\", calls[\"samuel\"])\n\tfmt.Printf(\"john: %v\\n\", calls[\"john\"])\n\tmu.Unlock()\n\t// Output:\n\t// samuel: [1 1]\n\t// john: [1 3]\n}\n\nfunc ExampleAttempt() {\n\tcount1, err1 := Attempt(2, func(i int) error {\n\t\tif i == 0 {\n\t\t\treturn errors.New(\"error\")\n\t\t}\n\n\t\treturn nil\n\t})\n\n\tcount2, err2 := Attempt(2, func(i int) error {\n\t\tif i < 10 {\n\t\t\treturn errors.New(\"error\")\n\t\t}\n\n\t\treturn nil\n\t})\n\n\tfmt.Printf(\"%v %v\\n\", count1, err1)\n\tfmt.Printf(\"%v %v\\n\", count2, err2)\n\t// Output:\n\t// 2 <nil>\n\t// 2 error\n}\n\nfunc ExampleAttemptWithDelay() {\n\tcount1, time1, err1 := AttemptWithDelay(2, time.Millisecond, func(i int, _ time.Duration) error {\n\t\tif i == 0 {\n\t\t\treturn errors.New(\"error\")\n\t\t}\n\n\t\treturn nil\n\t})\n\n\tcount2, time2, err2 := AttemptWithDelay(2, time.Millisecond, func(i int, _ time.Duration) error {\n\t\tif i < 10 {\n\t\t\treturn errors.New(\"error\")\n\t\t}\n\n\t\treturn nil\n\t})\n\n\tfmt.Printf(\"%v %v %v\\n\", count1, time1.Truncate(time.Millisecond), err1)\n\tfmt.Printf(\"%v %v %v\\n\", count2, time2.Truncate(time.Millisecond), err2)\n\t// Output:\n\t// 2 1ms <nil>\n\t// 2 1ms error\n}\n\nfunc ExampleTransaction() {\n\ttransaction := NewTransaction[int]().\n\t\tThen(\n\t\t\tfunc(state int) (int, error) {\n\t\t\t\tfmt.Println(\"step 1\")\n\t\t\t\treturn state + 10, nil\n\t\t\t},\n\t\t\tfunc(state int) int {\n\t\t\t\tfmt.Println(\"rollback 1\")\n\t\t\t\treturn state - 10\n\t\t\t},\n\t\t).\n\t\tThen(\n\t\t\tfunc(state int) (int, error) {\n\t\t\t\tfmt.Println(\"step 2\")\n\t\t\t\treturn state + 15, nil\n\t\t\t},\n\t\t\tfunc(state int) int {\n\t\t\t\tfmt.Println(\"rollback 2\")\n\t\t\t\treturn state - 15\n\t\t\t},\n\t\t).\n\t\tThen(\n\t\t\tfunc(state int) (int, error) {\n\t\t\t\tfmt.Println(\"step 3\")\n\n\t\t\t\tif true {\n\t\t\t\t\treturn state, errors.New(\"error\")\n\t\t\t\t}\n\n\t\t\t\treturn state + 42, nil\n\t\t\t},\n\t\t\tfunc(state int) int {\n\t\t\t\tfmt.Println(\"rollback 3\")\n\t\t\t\treturn state - 42\n\t\t\t},\n\t\t)\n\n\t_, _ = transaction.Process(-5)\n\n\t// Output:\n\t// step 1\n\t// step 2\n\t// step 3\n\t// rollback 2\n\t// rollback 1\n}\n\nfunc ExampleTransaction_ok() {\n\ttransaction := NewTransaction[int]().\n\t\tThen(\n\t\t\tfunc(state int) (int, error) {\n\t\t\t\treturn state + 10, nil\n\t\t\t},\n\t\t\tfunc(state int) int {\n\t\t\t\treturn state - 10\n\t\t\t},\n\t\t).\n\t\tThen(\n\t\t\tfunc(state int) (int, error) {\n\t\t\t\treturn state + 15, nil\n\t\t\t},\n\t\t\tfunc(state int) int {\n\t\t\t\treturn state - 15\n\t\t\t},\n\t\t).\n\t\tThen(\n\t\t\tfunc(state int) (int, error) {\n\t\t\t\treturn state + 42, nil\n\t\t\t},\n\t\t\tfunc(state int) int {\n\t\t\t\treturn state - 42\n\t\t\t},\n\t\t)\n\n\tstate, err := transaction.Process(-5)\n\n\tfmt.Println(state)\n\tfmt.Println(err)\n\t// Output:\n\t// 62\n\t// <nil>\n}\n\nfunc ExampleTransaction_error() {\n\ttransaction := NewTransaction[int]().\n\t\tThen(\n\t\t\tfunc(state int) (int, error) {\n\t\t\t\treturn state + 10, nil\n\t\t\t},\n\t\t\tfunc(state int) int {\n\t\t\t\treturn state - 10\n\t\t\t},\n\t\t).\n\t\tThen(\n\t\t\tfunc(state int) (int, error) {\n\t\t\t\treturn state, errors.New(\"error\")\n\t\t\t},\n\t\t\tfunc(state int) int {\n\t\t\t\treturn state - 15\n\t\t\t},\n\t\t).\n\t\tThen(\n\t\t\tfunc(state int) (int, error) {\n\t\t\t\treturn state + 42, nil\n\t\t\t},\n\t\t\tfunc(state int) int {\n\t\t\t\treturn state - 42\n\t\t\t},\n\t\t)\n\n\tstate, err := transaction.Process(-5)\n\n\tfmt.Println(state)\n\tfmt.Println(err)\n\t// Output:\n\t// -5\n\t// error\n}\n\nfunc ExampleNewThrottle() {\n\tthrottle, reset := NewThrottle(100*time.Millisecond, func() {\n\t\tfmt.Println(\"Called once in every 100ms\")\n\t})\n\n\tfor j := 0; j < 10; j++ {\n\t\tthrottle()\n\t\ttime.Sleep(30 * time.Millisecond)\n\t}\n\n\treset()\n\n\t// Output:\n\t// Called once in every 100ms\n\t// Called once in every 100ms\n\t// Called once in every 100ms\n}\n\nfunc ExampleNewThrottleWithCount() {\n\tthrottle, reset := NewThrottleWithCount(100*time.Millisecond, 2, func() {\n\t\tfmt.Println(\"Called once in every 100ms\")\n\t})\n\n\tfor j := 0; j < 10; j++ {\n\t\tthrottle()\n\t\ttime.Sleep(30 * time.Millisecond)\n\t}\n\n\treset()\n\n\t// Output:\n\t// Called once in every 100ms\n\t// Called once in every 100ms\n\t// Called once in every 100ms\n\t// Called once in every 100ms\n\t// Called once in every 100ms\n\t// Called once in every 100ms\n}\n\nfunc ExampleNewThrottleBy() {\n\tthrottle, reset := NewThrottleBy(100*time.Millisecond, func(key string) {\n\t\tfmt.Println(key, \"Called once in every 100ms\")\n\t})\n\n\tfor j := 0; j < 10; j++ {\n\t\tthrottle(\"foo\")\n\t\tthrottle(\"bar\")\n\t\ttime.Sleep(30 * time.Millisecond)\n\t}\n\n\treset()\n\n\t// Output:\n\t// foo Called once in every 100ms\n\t// bar Called once in every 100ms\n\t// foo Called once in every 100ms\n\t// bar Called once in every 100ms\n\t// foo Called once in every 100ms\n\t// bar Called once in every 100ms\n}\n\nfunc ExampleNewThrottleByWithCount() {\n\tthrottle, reset := NewThrottleByWithCount(100*time.Millisecond, 2, func(key string) {\n\t\tfmt.Println(key, \"Called once in every 100ms\")\n\t})\n\n\tfor j := 0; j < 10; j++ {\n\t\tthrottle(\"foo\")\n\t\tthrottle(\"bar\")\n\t\ttime.Sleep(30 * time.Millisecond)\n\t}\n\n\treset()\n\n\t// Output:\n\t// foo Called once in every 100ms\n\t// bar Called once in every 100ms\n\t// foo Called once in every 100ms\n\t// bar Called once in every 100ms\n\t// foo Called once in every 100ms\n\t// bar Called once in every 100ms\n\t// foo Called once in every 100ms\n\t// bar Called once in every 100ms\n\t// foo Called once in every 100ms\n\t// bar Called once in every 100ms\n\t// foo Called once in every 100ms\n\t// bar Called once in every 100ms\n}\n"
  },
  {
    "path": "retry_test.go",
    "content": "package lo\n\nimport (\n\t\"errors\"\n\t\"sync\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestAttempt(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\terr := errors.New(\"failed\")\n\n\titer1, err1 := Attempt(42, func(i int) error {\n\t\treturn nil\n\t})\n\titer2, err2 := Attempt(42, func(i int) error {\n\t\tif i == 5 {\n\t\t\treturn nil\n\t\t}\n\n\t\treturn err\n\t})\n\titer3, err3 := Attempt(2, func(i int) error {\n\t\tif i == 5 {\n\t\t\treturn nil\n\t\t}\n\n\t\treturn err\n\t})\n\titer4, err4 := Attempt(0, func(i int) error {\n\t\tif i < 42 {\n\t\t\treturn err\n\t\t}\n\n\t\treturn nil\n\t})\n\n\tis.Equal(1, iter1)\n\tis.NoError(err1)\n\tis.Equal(6, iter2)\n\tis.NoError(err2)\n\tis.Equal(2, iter3)\n\tis.ErrorIs(err3, err)\n\tis.Equal(43, iter4)\n\tis.NoError(err4)\n}\n\nfunc TestAttemptWithDelay(t *testing.T) { //nolint:paralleltest\n\t// t.Parallel()\n\tis := assert.New(t)\n\n\terr := errors.New(\"failed\")\n\n\titer1, dur1, err1 := AttemptWithDelay(42, 10*time.Millisecond, func(i int, d time.Duration) error {\n\t\treturn nil\n\t})\n\titer2, dur2, err2 := AttemptWithDelay(42, 10*time.Millisecond, func(i int, d time.Duration) error {\n\t\tif i == 3 {\n\t\t\treturn nil\n\t\t}\n\n\t\treturn err\n\t})\n\titer3, dur3, err3 := AttemptWithDelay(2, 10*time.Millisecond, func(i int, d time.Duration) error {\n\t\tif i == 3 {\n\t\t\treturn nil\n\t\t}\n\n\t\treturn err\n\t})\n\titer4, dur4, err4 := AttemptWithDelay(0, 10*time.Millisecond, func(i int, d time.Duration) error {\n\t\tif i < 10 {\n\t\t\treturn err\n\t\t}\n\n\t\treturn nil\n\t})\n\n\tis.Equal(1, iter1)\n\tis.InDelta(1*time.Microsecond, dur1, float64(1*time.Millisecond))\n\tis.NoError(err1)\n\n\tis.Equal(4, iter2)\n\tis.InDelta(30*time.Millisecond, dur2, float64(5*time.Millisecond))\n\tis.NoError(err2)\n\n\tis.Equal(2, iter3)\n\tis.InDelta(10*time.Millisecond, dur3, float64(5*time.Millisecond))\n\tis.ErrorIs(err3, err)\n\n\tis.Equal(11, iter4)\n\tis.InDelta(100*time.Millisecond, dur4, float64(5*time.Millisecond))\n\tis.NoError(err4)\n}\n\nfunc TestAttemptWhile(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\terr := errors.New(\"failed\")\n\n\titer1, err1 := AttemptWhile(42, func(i int) (error, bool) {\n\t\treturn nil, true\n\t})\n\n\tis.Equal(1, iter1)\n\tis.NoError(err1)\n\n\titer2, err2 := AttemptWhile(42, func(i int) (error, bool) {\n\t\tif i == 5 {\n\t\t\treturn nil, true\n\t\t}\n\n\t\treturn err, true\n\t})\n\n\tis.Equal(6, iter2)\n\tis.NoError(err2)\n\n\titer3, err3 := AttemptWhile(2, func(i int) (error, bool) {\n\t\tif i == 5 {\n\t\t\treturn nil, true\n\t\t}\n\n\t\treturn err, true\n\t})\n\n\tis.Equal(2, iter3)\n\tis.ErrorIs(err3, err)\n\n\titer4, err4 := AttemptWhile(0, func(i int) (error, bool) {\n\t\tif i < 42 {\n\t\t\treturn err, true\n\t\t}\n\n\t\treturn nil, true\n\t})\n\n\tis.Equal(43, iter4)\n\tis.NoError(err4)\n\n\titer5, err5 := AttemptWhile(0, func(i int) (error, bool) {\n\t\tif i == 5 {\n\t\t\treturn nil, false\n\t\t}\n\n\t\treturn err, true\n\t})\n\n\tis.Equal(6, iter5)\n\tis.NoError(err5)\n\n\titer6, err6 := AttemptWhile(0, func(i int) (error, bool) {\n\t\treturn nil, false\n\t})\n\n\tis.Equal(1, iter6)\n\tis.NoError(err6)\n\n\titer7, err7 := AttemptWhile(42, func(i int) (error, bool) {\n\t\tif i == 42 {\n\t\t\treturn nil, false\n\t\t}\n\t\tif i < 41 {\n\t\t\treturn err, true\n\t\t}\n\n\t\treturn nil, true\n\t})\n\n\tis.Equal(42, iter7)\n\tis.NoError(err7)\n}\n\nfunc TestAttemptWhileWithDelay(t *testing.T) { //nolint:paralleltest\n\t// t.Parallel()\n\tis := assert.New(t)\n\n\terr := errors.New(\"failed\")\n\n\titer1, dur1, err1 := AttemptWhileWithDelay(42, 10*time.Millisecond, func(i int, d time.Duration) (error, bool) {\n\t\treturn nil, true\n\t})\n\n\tis.Equal(1, iter1)\n\tis.InDelta(1*time.Microsecond, dur1, float64(3*time.Millisecond))\n\tis.NoError(err1)\n\n\titer2, dur2, err2 := AttemptWhileWithDelay(42, 10*time.Millisecond, func(i int, d time.Duration) (error, bool) {\n\t\tif i == 3 {\n\t\t\treturn nil, true\n\t\t}\n\n\t\treturn err, true\n\t})\n\n\tis.Equal(4, iter2)\n\tis.InDelta(30*time.Millisecond, dur2, float64(5*time.Millisecond))\n\tis.NoError(err2)\n\n\titer3, dur3, err3 := AttemptWhileWithDelay(2, 10*time.Millisecond, func(i int, d time.Duration) (error, bool) {\n\t\tif i == 5 {\n\t\t\treturn nil, true\n\t\t}\n\n\t\treturn err, true\n\t})\n\n\tis.Equal(2, iter3)\n\tis.InDelta(10*time.Millisecond, dur3, float64(5*time.Millisecond))\n\tis.ErrorIs(err3, err)\n\n\titer4, dur4, err4 := AttemptWhileWithDelay(0, 10*time.Millisecond, func(i int, d time.Duration) (error, bool) {\n\t\tif i < 10 {\n\t\t\treturn err, true\n\t\t}\n\n\t\treturn nil, true\n\t})\n\n\tis.Equal(11, iter4)\n\tis.InDelta(100*time.Millisecond, dur4, float64(5*time.Millisecond))\n\tis.NoError(err4)\n\n\titer5, dur5, err5 := AttemptWhileWithDelay(0, 10*time.Millisecond, func(i int, d time.Duration) (error, bool) {\n\t\tif i == 3 {\n\t\t\treturn nil, false\n\t\t}\n\n\t\treturn err, true\n\t})\n\n\tis.Equal(4, iter5)\n\tis.InDelta(30*time.Millisecond, dur5, float64(5*time.Millisecond))\n\tis.NoError(err5)\n\n\titer6, dur6, err6 := AttemptWhileWithDelay(0, 10*time.Millisecond, func(i int, d time.Duration) (error, bool) {\n\t\treturn nil, false\n\t})\n\n\tis.Equal(1, iter6)\n\tis.InDelta(1*time.Microsecond, dur6, float64(5*time.Millisecond))\n\tis.NoError(err6)\n\n\titer7, dur7, err7 := AttemptWhileWithDelay(42, 10*time.Millisecond, func(i int, d time.Duration) (error, bool) {\n\t\tif i == 42 {\n\t\t\treturn nil, false\n\t\t}\n\t\tif i < 41 {\n\t\t\treturn err, true\n\t\t}\n\n\t\treturn nil, true\n\t})\n\n\tis.Equal(42, iter7)\n\tis.InDelta(410*time.Millisecond, dur7, float64(5*time.Millisecond))\n\tis.NoError(err7)\n}\n\nfunc TestDebounce(t *testing.T) { //nolint:paralleltest\n\t// t.Parallel()\n\n\tf1 := func() {\n\t\tprintln(\"1. Called once after 10ms when func stopped invoking!\")\n\t}\n\tf2 := func() {\n\t\tprintln(\"2. Called once after 10ms when func stopped invoking!\")\n\t}\n\tf3 := func() {\n\t\tprintln(\"3. Called once after 10ms when func stopped invoking!\")\n\t}\n\n\td1, _ := NewDebounce(100*time.Millisecond, f1)\n\n\t// execute 3 times\n\tfor i := 0; i < 3; i++ {\n\t\tfor j := 0; j < 10; j++ {\n\t\t\td1()\n\t\t}\n\t\ttime.Sleep(200 * time.Millisecond)\n\t}\n\n\td2, _ := NewDebounce(100*time.Millisecond, f2)\n\n\t// execute once because it is always invoked and only last invoke is worked after 100ms\n\tfor i := 0; i < 3; i++ {\n\t\tfor j := 0; j < 5; j++ {\n\t\t\td2()\n\t\t}\n\t\ttime.Sleep(50 * time.Millisecond)\n\t}\n\n\ttime.Sleep(100 * time.Millisecond)\n\n\t// execute once because it is canceled after 200ms.\n\td3, cancel := NewDebounce(100*time.Millisecond, f3)\n\tfor i := 0; i < 3; i++ {\n\t\tfor j := 0; j < 10; j++ {\n\t\t\td3()\n\t\t}\n\t\ttime.Sleep(200 * time.Millisecond)\n\t\tif i == 0 {\n\t\t\tcancel()\n\t\t}\n\t}\n}\n\nfunc TestDebounceBy(t *testing.T) { //nolint:paralleltest\n\t// t.Parallel()\n\tis := assert.New(t)\n\n\tmu := sync.Mutex{}\n\toutput := map[int]int{0: 0, 1: 0, 2: 0}\n\n\tf1 := func(key, count int) {\n\t\tmu.Lock()\n\t\toutput[key] += count\n\t\tmu.Unlock()\n\t\t// fmt.Printf(\"[key=%d] 1. Called once after 10ms when func stopped invoking!\\n\", key)\n\t}\n\tf2 := func(key, count int) {\n\t\tmu.Lock()\n\t\toutput[key] += count\n\t\tmu.Unlock()\n\t\t// fmt.Printf(\"[key=%d] 2. Called once after 10ms when func stopped invoking!\\n\", key)\n\t}\n\tf3 := func(key, count int) {\n\t\tmu.Lock()\n\t\toutput[key] += count\n\t\tmu.Unlock()\n\t\t// fmt.Printf(\"[key=%d] 3. Called once after 10ms when func stopped invoking!\\n\", key)\n\t}\n\n\td1, _ := NewDebounceBy(100*time.Millisecond, f1)\n\n\t// execute 3 times\n\tfor i := 0; i < 3; i++ {\n\t\tfor j := 0; j < 10; j++ {\n\t\t\tfor k := 0; k < 3; k++ {\n\t\t\t\td1(k)\n\t\t\t}\n\t\t}\n\t\ttime.Sleep(200 * time.Millisecond)\n\t}\n\n\t// Wait for debounced calls to complete\n\ttime.Sleep(150 * time.Millisecond)\n\n\tmu.Lock()\n\tis.Equal(30, output[0])\n\tis.Equal(30, output[1])\n\tis.Equal(30, output[2])\n\tmu.Unlock()\n\n\td2, _ := NewDebounceBy(100*time.Millisecond, f2)\n\n\t// execute once because it is always invoked and only last invoke is worked after 100ms\n\tfor i := 0; i < 3; i++ {\n\t\tfor j := 0; j < 5; j++ {\n\t\t\tfor k := 0; k < 3; k++ {\n\t\t\t\td2(k)\n\t\t\t}\n\t\t}\n\t\ttime.Sleep(50 * time.Millisecond)\n\t}\n\n\t// Wait for debounced calls to complete\n\ttime.Sleep(150 * time.Millisecond)\n\n\tmu.Lock()\n\tis.Equal(45, output[0])\n\tis.Equal(45, output[1])\n\tis.Equal(45, output[2])\n\tmu.Unlock()\n\n\t// execute once because it is canceled after 200ms.\n\td3, cancel := NewDebounceBy(100*time.Millisecond, f3)\n\tfor i := 0; i < 3; i++ {\n\t\tfor j := 0; j < 10; j++ {\n\t\t\tfor k := 0; k < 3; k++ {\n\t\t\t\td3(k)\n\t\t\t}\n\t\t}\n\n\t\ttime.Sleep(200 * time.Millisecond)\n\t\tif i == 0 {\n\t\t\tfor k := 0; k < 3; k++ {\n\t\t\t\tcancel(k)\n\t\t\t}\n\t\t}\n\t}\n\n\t// Wait for debounced calls to complete\n\ttime.Sleep(150 * time.Millisecond)\n\n\tmu.Lock()\n\tis.Equal(75, output[0])\n\tis.Equal(75, output[1])\n\tis.Equal(75, output[2])\n\tmu.Unlock()\n}\n\nfunc TestTransaction(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\t// no error\n\t{\n\t\ttransaction := NewTransaction[int]().\n\t\t\tThen(\n\t\t\t\tfunc(state int) (int, error) {\n\t\t\t\t\treturn state + 100, nil\n\t\t\t\t},\n\t\t\t\tfunc(state int) int {\n\t\t\t\t\treturn state - 100\n\t\t\t\t},\n\t\t\t).\n\t\t\tThen(\n\t\t\t\tfunc(state int) (int, error) {\n\t\t\t\t\treturn state + 21, nil\n\t\t\t\t},\n\t\t\t\tfunc(state int) int {\n\t\t\t\t\treturn state - 21\n\t\t\t\t},\n\t\t\t)\n\n\t\tstate, err := transaction.Process(21)\n\t\tis.Equal(142, state)\n\t\tis.NoError(err)\n\t}\n\n\t// with error\n\t{\n\t\ttransaction := NewTransaction[int]().\n\t\t\tThen(\n\t\t\t\tfunc(state int) (int, error) {\n\t\t\t\t\treturn state + 100, nil\n\t\t\t\t},\n\t\t\t\tfunc(state int) int {\n\t\t\t\t\treturn state - 100\n\t\t\t\t},\n\t\t\t).\n\t\t\tThen(\n\t\t\t\tfunc(state int) (int, error) {\n\t\t\t\t\treturn state, assert.AnError\n\t\t\t\t},\n\t\t\t\tfunc(state int) int {\n\t\t\t\t\treturn state - 21\n\t\t\t\t},\n\t\t\t).\n\t\t\tThen(\n\t\t\t\tfunc(state int) (int, error) {\n\t\t\t\t\treturn state + 42, nil\n\t\t\t\t},\n\t\t\t\tfunc(state int) int {\n\t\t\t\t\treturn state - 42\n\t\t\t\t},\n\t\t\t)\n\n\t\tstate, err := transaction.Process(21)\n\t\tis.Equal(21, state)\n\t\tis.ErrorIs(err, assert.AnError)\n\t}\n\n\t// with error + update value\n\t{\n\t\ttransaction := NewTransaction[int]().\n\t\t\tThen(\n\t\t\t\tfunc(state int) (int, error) {\n\t\t\t\t\treturn state + 100, nil\n\t\t\t\t},\n\t\t\t\tfunc(state int) int {\n\t\t\t\t\treturn state - 100\n\t\t\t\t},\n\t\t\t).\n\t\t\tThen(\n\t\t\t\tfunc(state int) (int, error) {\n\t\t\t\t\treturn state + 21, assert.AnError\n\t\t\t\t},\n\t\t\t\tfunc(state int) int {\n\t\t\t\t\treturn state - 21\n\t\t\t\t},\n\t\t\t).\n\t\t\tThen(\n\t\t\t\tfunc(state int) (int, error) {\n\t\t\t\t\treturn state + 42, nil\n\t\t\t\t},\n\t\t\t\tfunc(state int) int {\n\t\t\t\t\treturn state - 42\n\t\t\t\t},\n\t\t\t)\n\n\t\tstate, err := transaction.Process(21)\n\t\tis.Equal(42, state)\n\t\tis.ErrorIs(err, assert.AnError)\n\t}\n}\n\nfunc TestNewThrottle(t *testing.T) { //nolint:paralleltest\n\t// t.Parallel()\n\tis := assert.New(t)\n\tcallCount := 0\n\tf1 := func() {\n\t\tcallCount++\n\t}\n\tth, reset := NewThrottle(100*time.Millisecond, f1)\n\n\tis.Zero(callCount)\n\tfor j := 0; j < 100; j++ {\n\t\tth()\n\t}\n\tis.Equal(1, callCount)\n\n\ttime.Sleep(150 * time.Millisecond)\n\n\tfor j := 0; j < 100; j++ {\n\t\tth()\n\t}\n\n\tis.Equal(2, callCount)\n\n\t// reset counter\n\treset()\n\tth()\n\tis.Equal(3, callCount)\n}\n\nfunc TestNewThrottleWithCount(t *testing.T) { //nolint:paralleltest\n\t// t.Parallel()\n\tis := assert.New(t)\n\tcallCount := 0\n\tf1 := func() {\n\t\tcallCount++\n\t}\n\tth, reset := NewThrottleWithCount(100*time.Millisecond, 3, f1)\n\n\t// the function does not throttle for initial count number\n\tfor i := 0; i < 20; i++ {\n\t\tth()\n\t}\n\tis.Equal(3, callCount)\n\n\ttime.Sleep(150 * time.Millisecond)\n\n\tfor i := 0; i < 20; i++ {\n\t\tth()\n\t}\n\n\tis.Equal(6, callCount)\n\n\treset()\n\tfor i := 0; i < 20; i++ {\n\t\tth()\n\t}\n\n\tis.Equal(9, callCount)\n}\n\nfunc TestNewThrottleBy(t *testing.T) { //nolint:paralleltest\n\t// t.Parallel()\n\tis := assert.New(t)\n\tcallCountA := 0\n\tcallCountB := 0\n\tf1 := func(key string) {\n\t\tif key == \"a\" {\n\t\t\tcallCountA++\n\t\t} else {\n\t\t\tcallCountB++\n\t\t}\n\t}\n\tth, reset := NewThrottleBy(100*time.Millisecond, f1)\n\n\tis.Zero(callCountA)\n\tis.Zero(callCountB)\n\tfor j := 0; j < 100; j++ {\n\t\tth(\"a\")\n\t\tth(\"b\")\n\t}\n\tis.Equal(1, callCountA)\n\tis.Equal(1, callCountB)\n\n\ttime.Sleep(150 * time.Millisecond)\n\n\tfor j := 0; j < 100; j++ {\n\t\tth(\"a\")\n\t\tth(\"b\")\n\t}\n\n\tis.Equal(2, callCountA)\n\tis.Equal(2, callCountB)\n\n\t// reset counter\n\treset()\n\tth(\"a\")\n\tis.Equal(3, callCountA)\n\tis.Equal(2, callCountB)\n}\n\nfunc TestNewThrottleByWithCount(t *testing.T) { //nolint:paralleltest\n\t// t.Parallel()\n\tis := assert.New(t)\n\n\tcallCountA := 0\n\tcallCountB := 0\n\tf1 := func(key string) {\n\t\tif key == \"a\" {\n\t\t\tcallCountA++\n\t\t} else {\n\t\t\tcallCountB++\n\t\t}\n\t}\n\tth, reset := NewThrottleByWithCount(100*time.Millisecond, 3, f1)\n\n\t// the function does not throttle for initial count number\n\tfor i := 0; i < 20; i++ {\n\t\tth(\"a\")\n\t\tth(\"b\")\n\t}\n\tis.Equal(3, callCountA)\n\tis.Equal(3, callCountB)\n\n\ttime.Sleep(150 * time.Millisecond)\n\n\tfor i := 0; i < 20; i++ {\n\t\tth(\"a\")\n\t\tth(\"b\")\n\t}\n\n\tis.Equal(6, callCountA)\n\tis.Equal(6, callCountB)\n\n\treset()\n\tfor i := 0; i < 20; i++ {\n\t\tth(\"a\")\n\t}\n\n\tis.Equal(9, callCountA)\n\tis.Equal(6, callCountB)\n}\n"
  },
  {
    "path": "slice.go",
    "content": "package lo\n\nimport (\n\t\"sort\"\n\n\t\"github.com/samber/lo/internal/constraints\"\n\t\"github.com/samber/lo/mutable\"\n)\n\n// Filter iterates over elements of collection, returning a slice of all elements predicate returns true for.\n// Play: https://go.dev/play/p/Apjg3WeSi7K\nfunc Filter[T any, Slice ~[]T](collection Slice, predicate func(item T, index int) bool) Slice {\n\tresult := make(Slice, 0, len(collection))\n\n\tfor i := range collection {\n\t\tif predicate(collection[i], i) {\n\t\t\tresult = append(result, collection[i])\n\t\t}\n\t}\n\n\treturn result\n}\n\n// FilterErr iterates over elements of collection, returning a slice of all elements predicate returns true for.\n// If the predicate returns an error, iteration stops immediately and returns the error.\n// Play: https://go.dev/play/p/Apjg3WeSi7K\nfunc FilterErr[T any, Slice ~[]T](collection Slice, predicate func(item T, index int) (bool, error)) (Slice, error) {\n\tresult := make(Slice, 0, len(collection))\n\n\tfor i := range collection {\n\t\tok, err := predicate(collection[i], i)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tif ok {\n\t\t\tresult = append(result, collection[i])\n\t\t}\n\t}\n\n\treturn result, nil\n}\n\n// Map manipulates a slice and transforms it to a slice of another type.\n// Play: https://go.dev/play/p/OkPcYAhBo0D\nfunc Map[T, R any](collection []T, transform func(item T, index int) R) []R {\n\tresult := make([]R, len(collection))\n\n\tfor i := range collection {\n\t\tresult[i] = transform(collection[i], i)\n\t}\n\n\treturn result\n}\n\n// MapErr manipulates a slice and transforms it to a slice of another type.\n// It returns the first error returned by the transform function.\nfunc MapErr[T, R any](collection []T, transform func(item T, index int) (R, error)) ([]R, error) {\n\tresult := make([]R, len(collection))\n\n\tfor i := range collection {\n\t\tr, err := transform(collection[i], i)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tresult[i] = r\n\t}\n\n\treturn result, nil\n}\n\n// UniqMap manipulates a slice and transforms it to a slice of another type with unique values.\n// Play: https://go.dev/play/p/fygzLBhvUdB\nfunc UniqMap[T any, R comparable](collection []T, transform func(item T, index int) R) []R {\n\tresult := make([]R, 0, len(collection))\n\tseen := make(map[R]struct{}, len(collection))\n\n\tfor i := range collection {\n\t\tr := transform(collection[i], i)\n\t\tif _, ok := seen[r]; !ok {\n\t\t\tseen[r] = struct{}{}\n\t\t\tresult = append(result, r)\n\t\t}\n\t}\n\n\treturn result\n}\n\n// FilterMap returns a slice obtained after both filtering and mapping using the given callback function.\n// The callback function should return two values:\n//   - the result of the mapping operation and\n//   - whether the result element should be included or not.\n//\n// Play: https://go.dev/play/p/CgHYNUpOd1I\nfunc FilterMap[T, R any](collection []T, callback func(item T, index int) (R, bool)) []R {\n\tresult := make([]R, 0, len(collection))\n\n\tfor i := range collection {\n\t\tif r, ok := callback(collection[i], i); ok {\n\t\t\tresult = append(result, r)\n\t\t}\n\t}\n\n\treturn result\n}\n\n// FlatMap manipulates a slice and transforms and flattens it to a slice of another type.\n// The transform function can either return a slice or a `nil`, and in the `nil` case\n// no value is added to the final slice.\n// Play: https://go.dev/play/p/pFCF5WVB225\nfunc FlatMap[T, R any](collection []T, transform func(item T, index int) []R) []R {\n\tresult := make([]R, 0, len(collection))\n\n\tfor i := range collection {\n\t\tresult = append(result, transform(collection[i], i)...)\n\t}\n\n\treturn result\n}\n\n// FlatMapErr manipulates a slice and transforms and flattens it to a slice of another type.\n// The transform function can either return a slice or a `nil`, and in the `nil` case\n// no value is added to the final slice.\n// It returns the first error returned by the transform function.\nfunc FlatMapErr[T, R any](collection []T, transform func(item T, index int) ([]R, error)) ([]R, error) {\n\tresult := make([]R, 0, len(collection))\n\n\tfor i := range collection {\n\t\tr, err := transform(collection[i], i)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tresult = append(result, r...)\n\t}\n\n\treturn result, nil\n}\n\n// Reduce reduces collection to a value which is the accumulated result of running each element in collection\n// through accumulator, where each successive invocation is supplied the return value of the previous.\n// Play: https://go.dev/play/p/CgHYNUpOd1I\nfunc Reduce[T, R any](collection []T, accumulator func(agg R, item T, index int) R, initial R) R {\n\tfor i := range collection {\n\t\tinitial = accumulator(initial, collection[i], i)\n\t}\n\n\treturn initial\n}\n\n// ReduceErr reduces collection to a value which is the accumulated result of running each element in collection\n// through accumulator, where each successive invocation is supplied the return value of the previous.\n// It returns the first error returned by the accumulator function.\nfunc ReduceErr[T, R any](collection []T, accumulator func(agg R, item T, index int) (R, error), initial R) (R, error) {\n\tfor i := range collection {\n\t\tresult, err := accumulator(initial, collection[i], i)\n\t\tif err != nil {\n\t\t\tvar zero R\n\t\t\treturn zero, err\n\t\t}\n\t\tinitial = result\n\t}\n\n\treturn initial, nil\n}\n\n// ReduceRight is like Reduce except that it iterates over elements of collection from right to left.\n// Play: https://go.dev/play/p/Fq3W70l7wXF\nfunc ReduceRight[T, R any](collection []T, accumulator func(agg R, item T, index int) R, initial R) R {\n\tfor i := len(collection) - 1; i >= 0; i-- {\n\t\tinitial = accumulator(initial, collection[i], i)\n\t}\n\n\treturn initial\n}\n\n// ReduceRightErr is like ReduceRight except that the accumulator function can return an error.\n// It returns the first error returned by the accumulator function.\nfunc ReduceRightErr[T, R any](collection []T, accumulator func(agg R, item T, index int) (R, error), initial R) (R, error) {\n\tfor i := len(collection) - 1; i >= 0; i-- {\n\t\tresult, err := accumulator(initial, collection[i], i)\n\t\tif err != nil {\n\t\t\tvar zero R\n\t\t\treturn zero, err\n\t\t}\n\t\tinitial = result\n\t}\n\n\treturn initial, nil\n}\n\n// ForEach iterates over elements of collection and invokes callback for each element.\n// Play: https://go.dev/play/p/oofyiUPRf8t\nfunc ForEach[T any](collection []T, callback func(item T, index int)) {\n\tfor i := range collection {\n\t\tcallback(collection[i], i)\n\t}\n}\n\n// ForEachWhile iterates over elements of collection and invokes predicate for each element\n// collection return value decide to continue or break, like do while().\n// Play: https://go.dev/play/p/QnLGt35tnow\nfunc ForEachWhile[T any](collection []T, predicate func(item T, index int) bool) {\n\tfor i := range collection {\n\t\tif !predicate(collection[i], i) {\n\t\t\tbreak\n\t\t}\n\t}\n}\n\n// Times invokes the iteratee n times, returning a slice of the results of each invocation.\n// The iteratee is invoked with index as argument.\n// Play: https://go.dev/play/p/vgQj3Glr6lT\nfunc Times[T any](count int, iteratee func(index int) T) []T {\n\tresult := make([]T, count)\n\n\tfor i := 0; i < count; i++ {\n\t\tresult[i] = iteratee(i)\n\t}\n\n\treturn result\n}\n\n// Uniq returns a duplicate-free version of a slice, in which only the first occurrence of each element is kept.\n// The order of result values is determined by the order they occur in the slice.\n// Play: https://go.dev/play/p/DTzbeXZ6iEN\nfunc Uniq[T comparable, Slice ~[]T](collection Slice) Slice {\n\tresult := make(Slice, 0, len(collection))\n\tseen := make(map[T]struct{}, len(collection))\n\n\tfor i := range collection {\n\t\tif _, ok := seen[collection[i]]; ok {\n\t\t\tcontinue\n\t\t}\n\n\t\tseen[collection[i]] = struct{}{}\n\t\tresult = append(result, collection[i])\n\t}\n\n\treturn result\n}\n\n// UniqBy returns a duplicate-free version of a slice, in which only the first occurrence of each element is kept.\n// The order of result values is determined by the order they occur in the slice. It accepts `iteratee` which is\n// invoked for each element in the slice to generate the criterion by which uniqueness is computed.\n// Play: https://go.dev/play/p/g42Z3QSb53u\nfunc UniqBy[T any, U comparable, Slice ~[]T](collection Slice, iteratee func(item T) U) Slice {\n\tresult := make(Slice, 0, len(collection))\n\tseen := make(map[U]struct{}, len(collection))\n\n\tfor i := range collection {\n\t\tkey := iteratee(collection[i])\n\n\t\tif _, ok := seen[key]; ok {\n\t\t\tcontinue\n\t\t}\n\n\t\tseen[key] = struct{}{}\n\t\tresult = append(result, collection[i])\n\t}\n\n\treturn result\n}\n\n// UniqByErr returns a duplicate-free version of a slice, in which only the first occurrence of each element is kept.\n// The order of result values is determined by the order they occur in the slice. It accepts `iteratee` which is\n// invoked for each element in the slice to generate the criterion by which uniqueness is computed.\n// It returns the first error returned by the iteratee function.\nfunc UniqByErr[T any, U comparable, Slice ~[]T](collection Slice, iteratee func(item T) (U, error)) (Slice, error) {\n\tresult := make(Slice, 0, len(collection))\n\tseen := make(map[U]struct{}, len(collection))\n\n\tfor i := range collection {\n\t\tkey, err := iteratee(collection[i])\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tif _, ok := seen[key]; ok {\n\t\t\tcontinue\n\t\t}\n\n\t\tseen[key] = struct{}{}\n\t\tresult = append(result, collection[i])\n\t}\n\n\treturn result, nil\n}\n\n// GroupBy returns an object composed of keys generated from the results of running each element of collection through iteratee.\n// Play: https://go.dev/play/p/XnQBd_v6brd\nfunc GroupBy[T any, U comparable, Slice ~[]T](collection Slice, iteratee func(item T) U) map[U]Slice {\n\tresult := map[U]Slice{}\n\n\tfor i := range collection {\n\t\tkey := iteratee(collection[i])\n\n\t\tresult[key] = append(result[key], collection[i])\n\t}\n\n\treturn result\n}\n\n// GroupByErr returns an object composed of keys generated from the results of running each element of collection through iteratee.\n// It returns the first error returned by the iteratee function.\n// Play: https://go.dev/play/p/BzKPcY3AdX2\nfunc GroupByErr[T any, U comparable, Slice ~[]T](collection Slice, iteratee func(item T) (U, error)) (map[U]Slice, error) {\n\tresult := map[U]Slice{}\n\n\tfor i := range collection {\n\t\tkey, err := iteratee(collection[i])\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tresult[key] = append(result[key], collection[i])\n\t}\n\n\treturn result, nil\n}\n\n// GroupByMap returns an object composed of keys generated from the results of running each element of collection through transform.\n// Play: https://go.dev/play/p/iMeruQ3_W80\nfunc GroupByMap[T any, K comparable, V any](collection []T, transform func(item T) (K, V)) map[K][]V {\n\tresult := map[K][]V{}\n\n\tfor i := range collection {\n\t\tk, v := transform(collection[i])\n\n\t\tresult[k] = append(result[k], v)\n\t}\n\n\treturn result\n}\n\n// GroupByMapErr returns an object composed of keys generated from the results of running each element of collection through transform.\n// It returns the first error returned by the transform function.\nfunc GroupByMapErr[T any, K comparable, V any](collection []T, transform func(item T) (K, V, error)) (map[K][]V, error) {\n\tresult := map[K][]V{}\n\n\tfor i := range collection {\n\t\tk, v, err := transform(collection[i])\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tresult[k] = append(result[k], v)\n\t}\n\n\treturn result, nil\n}\n\n// Chunk returns a slice of elements split into groups of length size. If the slice can't be split evenly,\n// the final chunk will be the remaining elements.\n// Play: https://go.dev/play/p/kEMkFbdu85g\nfunc Chunk[T any, Slice ~[]T](collection Slice, size int) []Slice {\n\tif size <= 0 {\n\t\tpanic(\"lo.Chunk: size must be greater than 0\")\n\t}\n\n\tchunksNum := len(collection) / size\n\tif len(collection)%size != 0 {\n\t\tchunksNum++\n\t}\n\n\tresult := make([]Slice, 0, chunksNum)\n\n\tfor i := 0; i < chunksNum; i++ {\n\t\tlast := (i + 1) * size\n\t\tif last > len(collection) {\n\t\t\tlast = len(collection)\n\t\t}\n\n\t\t// Copy chunk in a new slice, to prevent memory leak and free memory from initial collection.\n\t\tnewSlice := make(Slice, last-i*size)\n\t\tcopy(newSlice, collection[i*size:last])\n\t\tresult = append(result, newSlice)\n\t}\n\n\treturn result\n}\n\n// PartitionBy returns a slice of elements split into groups. The order of grouped values is\n// determined by the order they occur in collection. The grouping is generated from the results\n// of running each element of collection through iteratee.\n// Play: https://go.dev/play/p/NfQ_nGjkgXW\nfunc PartitionBy[T any, K comparable, Slice ~[]T](collection Slice, iteratee func(item T) K) []Slice {\n\tresult := []Slice{}\n\tseen := map[K]int{}\n\n\tfor i := range collection {\n\t\tkey := iteratee(collection[i])\n\n\t\tresultIndex, ok := seen[key]\n\t\tif ok {\n\t\t\tresult[resultIndex] = append(result[resultIndex], collection[i])\n\t\t} else {\n\t\t\tseen[key] = len(result)\n\t\t\tresult = append(result, Slice{collection[i]})\n\t\t}\n\t}\n\n\treturn result\n\n\t// unordered:\n\t// groups := GroupBy[T, K](collection, iteratee)\n\t// return Values[K, []T](groups)\n}\n\n// PartitionByErr partitions a slice into groups determined by a key computed from each element.\n// The order of the partitions is determined by the order they occur in collection. The grouping\n// is generated from the results of running each element of collection through iteratee.\n// It returns the first error returned by the iteratee function.\nfunc PartitionByErr[T any, K comparable, Slice ~[]T](collection Slice, iteratee func(item T) (K, error)) ([]Slice, error) {\n\tresult := []Slice{}\n\tseen := map[K]int{}\n\n\tfor i := range collection {\n\t\tkey, err := iteratee(collection[i])\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tresultIndex, ok := seen[key]\n\t\tif ok {\n\t\t\tresult[resultIndex] = append(result[resultIndex], collection[i])\n\t\t} else {\n\t\t\tseen[key] = len(result)\n\t\t\tresult = append(result, Slice{collection[i]})\n\t\t}\n\t}\n\n\treturn result, nil\n}\n\n// Flatten returns a slice a single level deep.\n// See also: Concat\n// Play: https://go.dev/play/p/rbp9ORaMpjw\nfunc Flatten[T any, Slice ~[]T](collection []Slice) Slice {\n\ttotalLen := 0\n\tfor i := range collection {\n\t\ttotalLen += len(collection[i])\n\t}\n\n\tresult := make(Slice, 0, totalLen)\n\tfor i := range collection {\n\t\tresult = append(result, collection[i]...)\n\t}\n\n\treturn result\n}\n\n// Concat returns a new slice containing all the elements in collections. Concat conserves the order of the elements.\n// See also: Flatten, Union.\n// Play: https://go.dev/play/p/Ux2UuR2xpRK\nfunc Concat[T any, Slice ~[]T](collections ...Slice) Slice {\n\treturn Flatten(collections)\n}\n\n// Window creates a slice of sliding windows of a given size.\n// Each window overlaps with the previous one by size-1 elements.\n// This is equivalent to Sliding(collection, size, 1).\nfunc Window[T any, Slice ~[]T](collection Slice, size int) []Slice {\n\tif size <= 0 {\n\t\tpanic(\"lo.Window: size must be greater than 0\")\n\t}\n\treturn Sliding(collection, size, 1)\n}\n\n// Sliding creates a slice of sliding windows of a given size with a given step.\n// If step is equal to size, windows don't overlap (similar to Chunk).\n// If step is less than size, windows overlap.\n// Play: https://go.dev/play/p/aIIU6gWxl2T\nfunc Sliding[T any, Slice ~[]T](collection Slice, size, step int) []Slice {\n\tif size <= 0 {\n\t\tpanic(\"lo.Sliding: size must be greater than 0\")\n\t}\n\n\tif step <= 0 {\n\t\tpanic(\"lo.Sliding: step must be greater than 0\")\n\t}\n\n\tn := len(collection) - size\n\tif n < 0 {\n\t\treturn []Slice{}\n\t}\n\n\tresult := make([]Slice, 0, n/step+1)\n\n\tfor i := 0; i <= n; i += step {\n\t\twindow := make(Slice, size)\n\t\tcopy(window, collection[i:i+size])\n\t\tresult = append(result, window)\n\t}\n\n\treturn result\n}\n\n// Interleave round-robin alternating input slices and sequentially appending value at index into result.\n// Play: https://go.dev/play/p/KOVtGUt-tdI\nfunc Interleave[T any, Slice ~[]T](collections ...Slice) Slice {\n\tif len(collections) == 0 {\n\t\treturn Slice{}\n\t}\n\n\tmaxSize := 0\n\ttotalSize := 0\n\tfor i := range collections {\n\t\tsize := len(collections[i])\n\t\ttotalSize += size\n\t\tif size > maxSize {\n\t\t\tmaxSize = size\n\t\t}\n\t}\n\n\tif maxSize == 0 {\n\t\treturn Slice{}\n\t}\n\n\tresult := make(Slice, totalSize)\n\n\tresultIdx := 0\n\tfor i := 0; i < maxSize; i++ {\n\t\tfor j := range collections {\n\t\t\tif len(collections[j])-1 < i {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tresult[resultIdx] = collections[j][i]\n\t\t\tresultIdx++\n\t\t}\n\t}\n\n\treturn result\n}\n\n// Shuffle returns a slice of shuffled values. Uses the Fisher-Yates shuffle algorithm.\n// Play: https://go.dev/play/p/ZTGG7OUCdnp\n//\n// Deprecated: use mutable.Shuffle() instead.\nfunc Shuffle[T any, Slice ~[]T](collection Slice) Slice {\n\tmutable.Shuffle(collection)\n\treturn collection\n}\n\n// Reverse reverses a slice so that the first element becomes the last, the second element becomes the second to last, and so on.\n// Play: https://go.dev/play/p/iv2e9jslfBM\n//\n// Deprecated: use mutable.Reverse() instead.\nfunc Reverse[T any, Slice ~[]T](collection Slice) Slice {\n\tmutable.Reverse(collection)\n\treturn collection\n}\n\n// Fill fills elements of a slice with `initial` value.\n// Play: https://go.dev/play/p/VwR34GzqEub\nfunc Fill[T Clonable[T], Slice ~[]T](collection Slice, initial T) Slice {\n\tresult := make(Slice, len(collection))\n\n\tfor i := range collection {\n\t\tresult[i] = initial.Clone()\n\t}\n\n\treturn result\n}\n\n// Repeat builds a slice with N copies of initial value.\n// Play: https://go.dev/play/p/g3uHXbmc3b6\nfunc Repeat[T Clonable[T]](count int, initial T) []T {\n\tresult := make([]T, count)\n\n\tfor i := 0; i < count; i++ {\n\t\tresult[i] = initial.Clone()\n\t}\n\n\treturn result\n}\n\n// RepeatBy builds a slice with values returned by N calls of callback.\n// Play: https://go.dev/play/p/ozZLCtX_hNU\nfunc RepeatBy[T any](count int, callback func(index int) T) []T {\n\tresult := make([]T, count)\n\n\tfor i := 0; i < count; i++ {\n\t\tresult[i] = callback(i)\n\t}\n\n\treturn result\n}\n\n// RepeatByErr builds a slice with values returned by N calls of callback.\n// It returns the first error returned by the callback function.\nfunc RepeatByErr[T any](count int, callback func(index int) (T, error)) ([]T, error) {\n\tresult := make([]T, 0, count)\n\n\tfor i := 0; i < count; i++ {\n\t\tr, err := callback(i)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tresult = append(result, r)\n\t}\n\n\treturn result, nil\n}\n\n// KeyBy transforms a slice or a slice of structs to a map based on a pivot callback.\n// Play: https://go.dev/play/p/ccUiUL_Lnel\nfunc KeyBy[K comparable, V any](collection []V, iteratee func(item V) K) map[K]V {\n\tresult := make(map[K]V, len(collection))\n\n\tfor i := range collection {\n\t\tk := iteratee(collection[i])\n\t\tresult[k] = collection[i]\n\t}\n\n\treturn result\n}\n\n// KeyByErr transforms a slice or a slice of structs to a map based on a pivot callback to compute keys.\n// Iteratee can return an error to stop iteration immediately.\n// Play: https://go.dev/play/p/ccUiUL_Lnel\nfunc KeyByErr[K comparable, V any](collection []V, iteratee func(item V) (K, error)) (map[K]V, error) {\n\tresult := make(map[K]V, len(collection))\n\n\tfor i := range collection {\n\t\tk, err := iteratee(collection[i])\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tresult[k] = collection[i]\n\t}\n\n\treturn result, nil\n}\n\n// Associate returns a map containing key-value pairs provided by transform function applied to elements of the given slice.\n// If any of two pairs have the same key the last one gets added to the map.\n// The order of keys in returned map is not specified and is not guaranteed to be the same from the original slice.\n// Play: https://go.dev/play/p/WHa2CfMO3Lr\nfunc Associate[T any, K comparable, V any](collection []T, transform func(item T) (K, V)) map[K]V {\n\treturn AssociateI(collection, func(item T, _ int) (K, V) {\n\t\treturn transform(item)\n\t})\n}\n\n// AssociateI returns a map containing key-value pairs provided by transform function applied to elements of the given slice.\n// If any of two pairs have the same key the last one gets added to the map.\n// The order of keys in returned map is not specified and is not guaranteed to be the same from the original slice.\n// Play: https://go.dev/play/p/Ugmz6S22rRO\nfunc AssociateI[T any, K comparable, V any](collection []T, transform func(item T, index int) (K, V)) map[K]V {\n\tresult := make(map[K]V, len(collection))\n\n\tfor index, item := range collection {\n\t\tk, v := transform(item, index)\n\t\tresult[k] = v\n\t}\n\n\treturn result\n}\n\n// SliceToMap returns a map containing key-value pairs provided by transform function applied to elements of the given slice.\n// If any of two pairs have the same key the last one gets added to the map.\n// The order of keys in returned map is not specified and is not guaranteed to be the same from the original slice.\n// Alias of Associate().\n// Play: https://go.dev/play/p/WHa2CfMO3Lr\nfunc SliceToMap[T any, K comparable, V any](collection []T, transform func(item T) (K, V)) map[K]V {\n\treturn Associate(collection, transform)\n}\n\n// SliceToMapI returns a map containing key-value pairs provided by transform function applied to elements of the given slice.\n// If any of two pairs have the same key the last one gets added to the map.\n// The order of keys in returned map is not specified and is not guaranteed to be the same from the original slice.\n// Alias of AssociateI().\n// Play: https://go.dev/play/p/mMBm5GV3_eq\nfunc SliceToMapI[T any, K comparable, V any](collection []T, transform func(item T, index int) (K, V)) map[K]V {\n\treturn AssociateI(collection, transform)\n}\n\n// FilterSliceToMap returns a map containing key-value pairs provided by transform function applied to elements of the given slice.\n// If any of two pairs have the same key the last one gets added to the map.\n// The order of keys in returned map is not specified and is not guaranteed to be the same from the original slice.\n// The third return value of the transform function is a boolean that indicates whether the key-value pair should be included in the map.\n// Play: https://go.dev/play/p/eurMiQEqey2\nfunc FilterSliceToMap[T any, K comparable, V any](collection []T, transform func(item T) (K, V, bool)) map[K]V {\n\treturn FilterSliceToMapI(collection, func(item T, _ int) (K, V, bool) {\n\t\treturn transform(item)\n\t})\n}\n\n// FilterSliceToMapI returns a map containing key-value pairs provided by transform function applied to elements of the given slice.\n// If any of two pairs have the same key the last one gets added to the map.\n// The order of keys in returned map is not specified and is not guaranteed to be the same from the original slice.\n// The third return value of the transform function is a boolean that indicates whether the key-value pair should be included in the map.\n// Play: https://go.dev/play/p/mSz_bUIk9aJ\nfunc FilterSliceToMapI[T any, K comparable, V any](collection []T, transform func(item T, index int) (K, V, bool)) map[K]V {\n\tresult := make(map[K]V, len(collection))\n\n\tfor index, item := range collection {\n\t\tk, v, ok := transform(item, index)\n\t\tif ok {\n\t\t\tresult[k] = v\n\t\t}\n\t}\n\n\treturn result\n}\n\n// Keyify returns a map with each unique element of the slice as a key.\n// Play: https://go.dev/play/p/_d5lXdzfw32\nfunc Keyify[T comparable, Slice ~[]T](collection Slice) map[T]struct{} {\n\tresult := make(map[T]struct{}, len(collection))\n\n\tfor i := range collection {\n\t\tresult[collection[i]] = struct{}{}\n\t}\n\n\treturn result\n}\n\n// Drop drops n elements from the beginning of a slice.\n// Play: https://go.dev/play/p/JswS7vXRJP2\nfunc Drop[T any, Slice ~[]T](collection Slice, n int) Slice {\n\tif n < 0 {\n\t\tpanic(\"lo.Drop: n must not be negative\")\n\t}\n\n\tif len(collection) <= n {\n\t\treturn make(Slice, 0)\n\t}\n\n\tresult := make(Slice, 0, len(collection)-n)\n\n\treturn append(result, collection[n:]...)\n}\n\n// DropRight drops n elements from the end of a slice.\n// Play: https://go.dev/play/p/GG0nXkSJJa3\nfunc DropRight[T any, Slice ~[]T](collection Slice, n int) Slice {\n\tif n < 0 {\n\t\tpanic(\"lo.DropRight: n must not be negative\")\n\t}\n\n\tif len(collection) <= n {\n\t\treturn Slice{}\n\t}\n\n\tresult := make(Slice, 0, len(collection)-n)\n\treturn append(result, collection[:len(collection)-n]...)\n}\n\n// DropWhile drops elements from the beginning of a slice while the predicate returns true.\n// Play: https://go.dev/play/p/b_PYomVQLGy\nfunc DropWhile[T any, Slice ~[]T](collection Slice, predicate func(item T) bool) Slice {\n\ti := 0\n\tfor ; i < len(collection); i++ {\n\t\tif !predicate(collection[i]) {\n\t\t\tbreak\n\t\t}\n\t}\n\n\tresult := make(Slice, 0, len(collection)-i)\n\treturn append(result, collection[i:]...)\n}\n\n// DropRightWhile drops elements from the end of a slice while the predicate returns true.\n// Play: https://go.dev/play/p/HBh8pHl-ZZz\nfunc DropRightWhile[T any, Slice ~[]T](collection Slice, predicate func(item T) bool) Slice {\n\ti := len(collection) - 1\n\tfor ; i >= 0; i-- {\n\t\tif !predicate(collection[i]) {\n\t\t\tbreak\n\t\t}\n\t}\n\n\tresult := make(Slice, 0, i+1)\n\treturn append(result, collection[:i+1]...)\n}\n\n// Take takes the first n elements from a slice.\nfunc Take[T any, Slice ~[]T](collection Slice, n int) Slice {\n\tif n < 0 {\n\t\tpanic(\"lo.Take: n must not be negative\")\n\t}\n\n\tif n == 0 {\n\t\treturn make(Slice, 0)\n\t}\n\n\tsize := len(collection)\n\tif size == 0 {\n\t\treturn make(Slice, 0)\n\t}\n\n\tif n >= size {\n\t\tresult := make(Slice, size)\n\t\tcopy(result, collection)\n\t\treturn result\n\t}\n\n\tresult := make(Slice, n)\n\tcopy(result, collection)\n\treturn result\n}\n\n// TakeWhile takes elements from the beginning of a slice while the predicate returns true.\n// Play: https://go.dev/play/p/NJkLGvyRWm4\nfunc TakeWhile[T any, Slice ~[]T](collection Slice, predicate func(item T) bool) Slice {\n\ti := 0\n\tfor ; i < len(collection); i++ {\n\t\tif !predicate(collection[i]) {\n\t\t\tbreak\n\t\t}\n\t}\n\n\tresult := make(Slice, i)\n\tcopy(result, collection[:i])\n\treturn result\n}\n\n// DropByIndex drops elements from a slice by the index.\n// A negative index will drop elements from the end of the slice.\n// Play: https://go.dev/play/p/bPIH4npZRxS\nfunc DropByIndex[T any, Slice ~[]T](collection Slice, indexes ...int) Slice {\n\tinitialSize := len(collection)\n\tif initialSize == 0 {\n\t\treturn Slice{}\n\t}\n\n\t// do not change the input\n\tindexes = append(make([]int, 0, len(indexes)), indexes...)\n\n\tfor i, index := range indexes {\n\t\tif index < 0 {\n\t\t\tindexes[i] += initialSize\n\t\t}\n\t}\n\n\tsort.Ints(indexes)\n\n\tprev := -1\n\tindexes = mutable.Filter(indexes, func(index int) bool {\n\t\tok := index != prev && // uniq\n\t\t\tuint(index) < uint(initialSize) // in range\n\n\t\tprev = index\n\t\treturn ok\n\t})\n\n\tresult := make(Slice, 0, initialSize-len(indexes))\n\n\ti := 0\n\tfor _, index := range indexes {\n\t\tresult = append(result, collection[i:index]...)\n\t\ti = index + 1\n\t}\n\n\treturn append(result, collection[i:]...)\n}\n\n// TakeFilter filters elements and takes the first n elements that match the predicate.\n// Equivalent to calling Take(Filter(...)), but more efficient as it stops after finding n matches.\n// Play: https://go.dev/play/p/l99lvN4gReF\nfunc TakeFilter[T any, Slice ~[]T](collection Slice, n int, predicate func(item T, index int) bool) Slice {\n\tif n < 0 {\n\t\tpanic(\"lo.TakeFilter: n must not be negative\")\n\t}\n\n\tif n == 0 {\n\t\treturn make(Slice, 0)\n\t}\n\n\tresult := make(Slice, 0, n)\n\tcount := 0\n\n\tfor i := range collection {\n\t\tif predicate(collection[i], i) {\n\t\t\tresult = append(result, collection[i])\n\t\t\tcount++\n\t\t\tif count >= n {\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n\n\treturn result\n}\n\n// Reject is the opposite of Filter, this method returns the elements of collection that predicate does not return true for.\n// Play: https://go.dev/play/p/7Pl-34c19Va\nfunc Reject[T any, Slice ~[]T](collection Slice, predicate func(item T, index int) bool) Slice {\n\tresult := make(Slice, 0, len(collection))\n\n\tfor i := range collection {\n\t\tif !predicate(collection[i], i) {\n\t\t\tresult = append(result, collection[i])\n\t\t}\n\t}\n\n\treturn result\n}\n\n// RejectErr is the opposite of FilterErr, this method returns the elements of collection that predicate does not return true for.\n// If the predicate returns an error, iteration stops immediately and returns the error.\n// Play: https://go.dev/play/p/pFCF5WVB225\nfunc RejectErr[T any, Slice ~[]T](collection Slice, predicate func(item T, index int) (bool, error)) (Slice, error) {\n\tresult := make(Slice, 0, len(collection))\n\n\tfor i := range collection {\n\t\tmatch, err := predicate(collection[i], i)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tif !match {\n\t\t\tresult = append(result, collection[i])\n\t\t}\n\t}\n\n\treturn result, nil\n}\n\n// RejectMap is the opposite of FilterMap, this method returns a slice obtained after both filtering and mapping using the given callback function.\n// The callback function should return two values:\n//   - the result of the mapping operation and\n//   - whether the result element should be included or not.\n//\n// Play: https://go.dev/play/p/W9Ug9r0QFkL\nfunc RejectMap[T, R any](collection []T, callback func(item T, index int) (R, bool)) []R {\n\tresult := make([]R, 0, len(collection))\n\n\tfor i := range collection {\n\t\tif r, ok := callback(collection[i], i); !ok {\n\t\t\tresult = append(result, r)\n\t\t}\n\t}\n\n\treturn result\n}\n\n// FilterReject mixes Filter and Reject, this method returns two slices, one for the elements of collection that\n// predicate returns true for and one for the elements that predicate does not return true for.\n// Play: https://go.dev/play/p/lHSEGSznJjB\nfunc FilterReject[T any, Slice ~[]T](collection Slice, predicate func(T, int) bool) (kept, rejected Slice) {\n\tkept = make(Slice, 0, len(collection))\n\trejected = make(Slice, 0, len(collection))\n\n\tfor i := range collection {\n\t\tif predicate(collection[i], i) {\n\t\t\tkept = append(kept, collection[i])\n\t\t} else {\n\t\t\trejected = append(rejected, collection[i])\n\t\t}\n\t}\n\n\treturn kept, rejected\n}\n\n// Count counts the number of elements in the collection that equal value.\n// Play: https://go.dev/play/p/Y3FlK54yveC\nfunc Count[T comparable](collection []T, value T) int {\n\tvar count int\n\n\tfor i := range collection {\n\t\tif collection[i] == value {\n\t\t\tcount++\n\t\t}\n\t}\n\n\treturn count\n}\n\n// CountBy counts the number of elements in the collection for which predicate is true.\n// Play: https://go.dev/play/p/5GMQP5vNT4q\nfunc CountBy[T any](collection []T, predicate func(item T) bool) int {\n\tvar count int\n\n\tfor i := range collection {\n\t\tif predicate(collection[i]) {\n\t\t\tcount++\n\t\t}\n\t}\n\n\treturn count\n}\n\n// CountByErr counts the number of elements in the collection for which predicate is true.\n// It returns the first error returned by the predicate.\n// Play: https://go.dev/play/p/7BnyPhpG6lW\nfunc CountByErr[T any](collection []T, predicate func(item T) (bool, error)) (int, error) {\n\tvar count int\n\n\tfor i := range collection {\n\t\tok, err := predicate(collection[i])\n\t\tif err != nil {\n\t\t\treturn 0, err\n\t\t}\n\t\tif ok {\n\t\t\tcount++\n\t\t}\n\t}\n\n\treturn count, nil\n}\n\n// CountValues counts the number of each element in the collection.\n// Play: https://go.dev/play/p/-p-PyLT4dfy\nfunc CountValues[T comparable](collection []T) map[T]int {\n\tresult := make(map[T]int, len(collection))\n\n\tfor i := range collection {\n\t\tresult[collection[i]]++\n\t}\n\n\treturn result\n}\n\n// CountValuesBy counts the number of each element returned from transform function.\n// Is equivalent to chaining lo.Map and lo.CountValues.\n// Play: https://go.dev/play/p/2U0dG1SnOmS\nfunc CountValuesBy[T any, U comparable](collection []T, transform func(item T) U) map[U]int {\n\tresult := make(map[U]int)\n\n\tfor i := range collection {\n\t\tresult[transform(collection[i])]++\n\t}\n\n\treturn result\n}\n\n// Subset returns a copy of a slice from `offset` up to `length` elements. Like `slice[start:start+length]`, but does not panic on overflow.\n// Play: https://go.dev/play/p/tOQu1GhFcog\nfunc Subset[T any, Slice ~[]T](collection Slice, offset int, length uint) Slice {\n\tsize := len(collection)\n\n\tif offset < 0 {\n\t\toffset = size + offset\n\t\tif offset < 0 {\n\t\t\toffset = 0\n\t\t}\n\t}\n\n\tif offset > size {\n\t\treturn Slice{}\n\t}\n\n\tif length > uint(size)-uint(offset) {\n\t\tlength = uint(size - offset)\n\t}\n\n\treturn collection[offset : offset+int(length)]\n}\n\n// Slice returns a slice from `start` up to, but not including `end`. Like `slice[start:end]`, but does not panic on overflow.\n// Play: https://go.dev/play/p/8XWYhfMMA1h\nfunc Slice[T any, Slice ~[]T](collection Slice, start, end int) Slice {\n\tif start >= end {\n\t\treturn Slice{}\n\t}\n\n\tsize := len(collection)\n\tif start < 0 {\n\t\tstart = 0\n\t} else if start > size {\n\t\tstart = size\n\t}\n\n\tif end < 0 {\n\t\tend = 0\n\t} else if end > size {\n\t\tend = size\n\t}\n\n\treturn collection[start:end]\n}\n\n// Replace returns a copy of the slice with the first n non-overlapping instances of old replaced by new.\n// Play: https://go.dev/play/p/XfPzmf9gql6\nfunc Replace[T comparable, Slice ~[]T](collection Slice, old, nEw T, n int) Slice {\n\tresult := make(Slice, len(collection))\n\tcopy(result, collection)\n\n\tfor i := range result {\n\t\tif result[i] == old && n != 0 {\n\t\t\tresult[i] = nEw\n\t\t\tn--\n\t\t}\n\t}\n\n\treturn result\n}\n\n// ReplaceAll returns a copy of the slice with all non-overlapping instances of old replaced by new.\n// Play: https://go.dev/play/p/a9xZFUHfYcV\nfunc ReplaceAll[T comparable, Slice ~[]T](collection Slice, old, nEw T) Slice {\n\treturn Replace(collection, old, nEw, -1)\n}\n\n// Clone returns a shallow copy of the collection.\n// Play: https://go.dev/play/p/66LJ2wAF0rN\nfunc Clone[T any, Slice ~[]T](collection Slice) Slice {\n\t// backporting from slices.Clone in Go 1.21\n\t// when we drop support for Go 1.20, this can be replaced with: return slices.Clone(collection)\n\n\t// Preserve nilness in case it matters.\n\tif collection == nil {\n\t\treturn nil\n\t}\n\t// Avoid s[:0:0] as it leads to unwanted liveness when cloning a\n\t// zero-length slice of a large array; see https://go.dev/issue/68488.\n\treturn append(Slice{}, collection...)\n}\n\n// Compact returns a slice of all non-zero elements.\n// Play: https://go.dev/play/p/tXiy-iK6PAc\nfunc Compact[T comparable, Slice ~[]T](collection Slice) Slice {\n\tvar zero T\n\n\tresult := make(Slice, 0, len(collection))\n\n\tfor i := range collection {\n\t\tif collection[i] != zero {\n\t\t\tresult = append(result, collection[i])\n\t\t}\n\t}\n\n\treturn result\n}\n\n// IsSorted checks if a slice is sorted.\n// Play: https://go.dev/play/p/mc3qR-t4mcx\nfunc IsSorted[T constraints.Ordered](collection []T) bool {\n\tfor i := 1; i < len(collection); i++ {\n\t\tif collection[i-1] > collection[i] {\n\t\t\treturn false\n\t\t}\n\t}\n\n\treturn true\n}\n\n// IsSortedBy checks if a slice is sorted by iteratee.\nfunc IsSortedBy[T any, K constraints.Ordered](collection []T, iteratee func(item T) K) bool {\n\tsize := len(collection)\n\n\tfor i := 0; i < size-1; i++ {\n\t\tif iteratee(collection[i]) > iteratee(collection[i+1]) {\n\t\t\treturn false\n\t\t}\n\t}\n\n\treturn true\n}\n\n// IsSortedByKey checks if a slice is sorted by iteratee.\n//\n// Deprecated: Use lo.IsSortedBy instead.\nfunc IsSortedByKey[T any, K constraints.Ordered](collection []T, iteratee func(item T) K) bool {\n\treturn IsSortedBy(collection, iteratee)\n}\n\n// Splice inserts multiple elements at index i. A negative index counts back\n// from the end of the slice. The helper is protected against overflow errors.\n// Play: https://go.dev/play/p/G5_GhkeSUBA\nfunc Splice[T any, Slice ~[]T](collection Slice, i int, elements ...T) Slice {\n\tsizeCollection := len(collection)\n\tsizeElements := len(elements)\n\toutput := make(Slice, 0, sizeCollection+sizeElements) // preallocate memory for the output slice\n\n\tswitch {\n\tcase sizeElements == 0:\n\t\treturn append(output, collection...) // simple copy\n\tcase i > sizeCollection:\n\t\t// positive overflow\n\t\treturn append(append(output, collection...), elements...)\n\tcase i < -sizeCollection:\n\t\t// negative overflow\n\t\treturn append(append(output, elements...), collection...)\n\tcase i < 0:\n\t\t// backward\n\t\ti = sizeCollection + i\n\t}\n\n\treturn append(append(append(output, collection[:i]...), elements...), collection[i:]...)\n}\n\n// Cut slices collection around the first instance of separator, returning the part of collection\n// before and after separator. The found result reports whether separator appears in collection.\n// If separator does not appear in s, cut returns collection, empty slice of []T, false.\n// Play: https://go.dev/play/p/GiL3qhpIP3f\nfunc Cut[T comparable, Slice ~[]T](collection, separator Slice) (before, after Slice, found bool) {\n\tif len(separator) == 0 {\n\t\treturn make(Slice, 0), collection, true\n\t}\n\n\tfor i := 0; i+len(separator) <= len(collection); i++ {\n\t\tmatch := true\n\t\tfor j := 0; j < len(separator); j++ {\n\t\t\tif collection[i+j] != separator[j] {\n\t\t\t\tmatch = false\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tif match {\n\t\t\treturn collection[:i], collection[i+len(separator):], true\n\t\t}\n\t}\n\n\treturn collection, make(Slice, 0), false\n}\n\n// CutPrefix returns collection without the provided leading prefix []T\n// and reports whether it found the prefix.\n// If s doesn't start with prefix, CutPrefix returns collection, false.\n// If prefix is the empty []T, CutPrefix returns collection, true.\n// Play: https://go.dev/play/p/P1scQj53aFa\nfunc CutPrefix[T comparable, Slice ~[]T](collection, separator Slice) (after Slice, found bool) {\n\tif HasPrefix(collection, separator) {\n\t\treturn collection[len(separator):], true\n\t}\n\treturn collection, false\n}\n\n// CutSuffix returns collection without the provided ending suffix []T and reports\n// whether it found the suffix. If s doesn't end with suffix, CutSuffix returns collection, false.\n// If suffix is the empty []T, CutSuffix returns collection, true.\n// Play: https://go.dev/play/p/7FKfBFvPTaT\nfunc CutSuffix[T comparable, Slice ~[]T](collection, separator Slice) (before Slice, found bool) {\n\tif HasSuffix(collection, separator) {\n\t\treturn collection[:len(collection)-len(separator)], true\n\t}\n\treturn collection, false\n}\n\n// Trim removes all the leading and trailing cutset from the collection.\n// Play: https://go.dev/play/p/LZLfLj5C8Lg\nfunc Trim[T comparable, Slice ~[]T](collection, cutset Slice) Slice {\n\tset := Keyify(cutset)\n\n\ti := 0\n\tfor ; i < len(collection); i++ {\n\t\tif _, ok := set[collection[i]]; !ok {\n\t\t\tbreak\n\t\t}\n\t}\n\n\tif i >= len(collection) {\n\t\treturn Slice{}\n\t}\n\n\tj := len(collection) - 1\n\tfor ; j >= 0; j-- {\n\t\tif _, ok := set[collection[j]]; !ok {\n\t\t\tbreak\n\t\t}\n\t}\n\n\tresult := make(Slice, 0, j+1-i)\n\treturn append(result, collection[i:j+1]...)\n}\n\n// TrimLeft removes all the leading cutset from the collection.\n// Play: https://go.dev/play/p/fJK-AhROy9w\nfunc TrimLeft[T comparable, Slice ~[]T](collection, cutset Slice) Slice {\n\tset := Keyify(cutset)\n\n\treturn DropWhile(collection, func(item T) bool {\n\t\t_, ok := set[item]\n\t\treturn ok\n\t})\n}\n\n// TrimPrefix removes all the leading prefix from the collection.\n// Play: https://go.dev/play/p/8O2RoWYzi8J\nfunc TrimPrefix[T comparable, Slice ~[]T](collection, prefix Slice) Slice {\n\tif len(prefix) == 0 {\n\t\treturn collection\n\t}\n\n\tfor HasPrefix(collection, prefix) {\n\t\tcollection = collection[len(prefix):]\n\t}\n\n\treturn collection\n}\n\n// TrimRight removes all the trailing cutset from the collection.\n// Play: https://go.dev/play/p/9V_N8sRyyiZ\nfunc TrimRight[T comparable, Slice ~[]T](collection, cutset Slice) Slice {\n\tset := Keyify(cutset)\n\n\treturn DropRightWhile(collection, func(item T) bool {\n\t\t_, ok := set[item]\n\t\treturn ok\n\t})\n}\n\n// TrimSuffix removes all the trailing suffix from the collection.\n// Play: https://go.dev/play/p/IjEUrV0iofq\nfunc TrimSuffix[T comparable, Slice ~[]T](collection, suffix Slice) Slice {\n\tif len(suffix) == 0 {\n\t\treturn collection\n\t}\n\n\tfor HasSuffix(collection, suffix) {\n\t\tcollection = collection[:len(collection)-len(suffix)]\n\t}\n\n\treturn collection\n}\n"
  },
  {
    "path": "slice_test.go",
    "content": "package lo\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"math\"\n\t\"sort\"\n\t\"strconv\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestFilter(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tr1 := Filter([]int{1, 2, 3, 4}, func(x, _ int) bool {\n\t\treturn x%2 == 0\n\t})\n\tis.Equal([]int{2, 4}, r1)\n\n\tr2 := Filter([]string{\"\", \"foo\", \"\", \"bar\", \"\"}, func(x string, _ int) bool {\n\t\treturn len(x) > 0\n\t})\n\tis.Equal([]string{\"foo\", \"bar\"}, r2)\n\n\ttype myStrings []string\n\tallStrings := myStrings{\"\", \"foo\", \"bar\"}\n\tnonempty := Filter(allStrings, func(x string, _ int) bool {\n\t\treturn len(x) > 0\n\t})\n\tis.IsType(nonempty, allStrings, \"type preserved\")\n}\n\nfunc TestFilterErr(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\ttests := []struct {\n\t\tname      string\n\t\tinput     []int\n\t\tpredicate func(item, index int) (bool, error)\n\t\twant      []int\n\t\twantErr   string\n\t\tcallbacks int // Number of predicates called before error/finish\n\t}{\n\t\t{\n\t\t\tname:  \"filter even numbers\",\n\t\t\tinput: []int{1, 2, 3, 4},\n\t\t\tpredicate: func(x, _ int) (bool, error) {\n\t\t\t\treturn x%2 == 0, nil\n\t\t\t},\n\t\t\twant:      []int{2, 4},\n\t\t\tcallbacks: 4,\n\t\t},\n\t\t{\n\t\t\tname:  \"empty slice\",\n\t\t\tinput: []int{},\n\t\t\tpredicate: func(x, _ int) (bool, error) {\n\t\t\t\treturn true, nil\n\t\t\t},\n\t\t\twant:      []int{},\n\t\t\tcallbacks: 0,\n\t\t},\n\t\t{\n\t\t\tname:  \"filter all out\",\n\t\t\tinput: []int{1, 2, 3, 4},\n\t\t\tpredicate: func(x, _ int) (bool, error) {\n\t\t\t\treturn false, nil\n\t\t\t},\n\t\t\twant:      []int{},\n\t\t\tcallbacks: 4,\n\t\t},\n\t\t{\n\t\t\tname:  \"filter all in\",\n\t\t\tinput: []int{1, 2, 3, 4},\n\t\t\tpredicate: func(x, _ int) (bool, error) {\n\t\t\t\treturn true, nil\n\t\t\t},\n\t\t\twant:      []int{1, 2, 3, 4},\n\t\t\tcallbacks: 4,\n\t\t},\n\t\t{\n\t\t\tname:  \"error on specific index\",\n\t\t\tinput: []int{1, 2, 3, 4},\n\t\t\tpredicate: func(x, _ int) (bool, error) {\n\t\t\t\tif x == 3 {\n\t\t\t\t\treturn false, errors.New(\"number 3 is not allowed\")\n\t\t\t\t}\n\t\t\t\treturn x%2 == 0, nil\n\t\t\t},\n\t\t\tcallbacks: 3,\n\t\t\twantErr:   \"number 3 is not allowed\",\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\ttt := tt\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\n\t\t\tvar callbacks int\n\t\t\twrappedPredicate := func(item, index int) (bool, error) {\n\t\t\t\tcallbacks++\n\t\t\t\treturn tt.predicate(item, index)\n\t\t\t}\n\n\t\t\tgot, err := FilterErr(tt.input, wrappedPredicate)\n\n\t\t\tif tt.wantErr != \"\" {\n\t\t\t\tis.Error(err)\n\t\t\t\tis.Equal(tt.wantErr, err.Error())\n\t\t\t\tis.Nil(got)\n\t\t\t\tis.Equal(tt.callbacks, callbacks, \"callback count should match expected early return\")\n\t\t\t} else {\n\t\t\t\tis.NoError(err)\n\t\t\t\tis.Equal(tt.want, got)\n\t\t\t\tis.Equal(tt.callbacks, callbacks)\n\t\t\t}\n\t\t})\n\t}\n\n\t// Test type preservation\n\ttype myStrings []string\n\tallStrings := myStrings{\"\", \"foo\", \"bar\"}\n\tnonempty, err := FilterErr(allStrings, func(x string, _ int) (bool, error) {\n\t\treturn len(x) > 0, nil\n\t})\n\tis.NoError(err)\n\tis.IsType(nonempty, allStrings, \"type preserved\")\n\tis.Equal(myStrings{\"foo\", \"bar\"}, nonempty)\n}\n\nfunc TestMap(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := Map([]int{1, 2, 3, 4}, func(x, _ int) string {\n\t\treturn \"Hello\"\n\t})\n\tresult2 := Map([]int64{1, 2, 3, 4}, func(x int64, _ int) string {\n\t\treturn strconv.FormatInt(x, 10)\n\t})\n\n\tis.Equal([]string{\"Hello\", \"Hello\", \"Hello\", \"Hello\"}, result1)\n\tis.Equal([]string{\"1\", \"2\", \"3\", \"4\"}, result2)\n}\n\nfunc TestMapErr(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\ttests := []struct {\n\t\tname                  string\n\t\tinput                 []int\n\t\ttransform             func(item, index int) (string, error)\n\t\twantResult            []string\n\t\twantErr               bool\n\t\terrMsg                string\n\t\texpectedCallbackCount int\n\t}{\n\t\t{\n\t\t\tname:  \"successful transformation\",\n\t\t\tinput: []int{1, 2, 3, 4},\n\t\t\ttransform: func(x, _ int) (string, error) {\n\t\t\t\treturn strconv.Itoa(x), nil\n\t\t\t},\n\t\t\twantResult:            []string{\"1\", \"2\", \"3\", \"4\"},\n\t\t\twantErr:               false,\n\t\t\texpectedCallbackCount: 4,\n\t\t},\n\t\t{\n\t\t\tname:  \"error at third element stops iteration\",\n\t\t\tinput: []int{1, 2, 3, 4},\n\t\t\ttransform: func(x, _ int) (string, error) {\n\t\t\t\tif x == 3 {\n\t\t\t\t\treturn \"\", errors.New(\"number 3 is not allowed\")\n\t\t\t\t}\n\t\t\t\treturn strconv.Itoa(x), nil\n\t\t\t},\n\t\t\twantResult:            nil,\n\t\t\twantErr:               true,\n\t\t\terrMsg:                \"number 3 is not allowed\",\n\t\t\texpectedCallbackCount: 3,\n\t\t},\n\t\t{\n\t\t\tname:  \"error at first element stops iteration immediately\",\n\t\t\tinput: []int{1, 2, 3, 4},\n\t\t\ttransform: func(x, _ int) (string, error) {\n\t\t\t\tif x == 1 {\n\t\t\t\t\treturn \"\", errors.New(\"number 1 is not allowed\")\n\t\t\t\t}\n\t\t\t\treturn strconv.Itoa(x), nil\n\t\t\t},\n\t\t\twantResult:            nil,\n\t\t\twantErr:               true,\n\t\t\terrMsg:                \"number 1 is not allowed\",\n\t\t\texpectedCallbackCount: 1,\n\t\t},\n\t\t{\n\t\t\tname:  \"error at last element\",\n\t\t\tinput: []int{1, 2, 3, 4},\n\t\t\ttransform: func(x, _ int) (string, error) {\n\t\t\t\tif x == 4 {\n\t\t\t\t\treturn \"\", errors.New(\"number 4 is not allowed\")\n\t\t\t\t}\n\t\t\t\treturn strconv.Itoa(x), nil\n\t\t\t},\n\t\t\twantResult:            nil,\n\t\t\twantErr:               true,\n\t\t\terrMsg:                \"number 4 is not allowed\",\n\t\t\texpectedCallbackCount: 4,\n\t\t},\n\t\t{\n\t\t\tname:  \"empty input slice\",\n\t\t\tinput: []int{},\n\t\t\ttransform: func(x, _ int) (string, error) {\n\t\t\t\treturn strconv.Itoa(x), nil\n\t\t\t},\n\t\t\twantResult:            []string{},\n\t\t\twantErr:               false,\n\t\t\texpectedCallbackCount: 0,\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\ttt := tt\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\n\t\t\t// Track callback count to test early return\n\t\t\tcallbackCount := 0\n\t\t\twrappedTransform := func(item, index int) (string, error) {\n\t\t\t\tcallbackCount++\n\t\t\t\treturn tt.transform(item, index)\n\t\t\t}\n\n\t\t\tresult, err := MapErr(tt.input, wrappedTransform)\n\n\t\t\tif tt.wantErr {\n\t\t\t\tis.Error(err)\n\t\t\t\tis.Equal(tt.errMsg, err.Error())\n\t\t\t\tis.Nil(result)\n\t\t\t} else {\n\t\t\t\tis.NoError(err)\n\t\t\t\tis.Equal(tt.wantResult, result)\n\t\t\t}\n\n\t\t\t// Verify callback count matches expected\n\t\t\tis.Equal(tt.expectedCallbackCount, callbackCount, \"callback count should match expected\")\n\t\t})\n\t}\n}\n\nfunc TestUniqMap(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\ttype User struct {\n\t\tName string\n\t\tage  int\n\t}\n\n\tusers := []User{{Name: \"Alice\", age: 20}, {Name: \"Alex\", age: 21}, {Name: \"Alex\", age: 22}}\n\tresult := UniqMap(users, func(item User, index int) string {\n\t\treturn item.Name\n\t})\n\n\tsort.Strings(result)\n\n\tis.Equal([]string{\"Alex\", \"Alice\"}, result)\n}\n\nfunc TestFilterMap(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tr1 := FilterMap([]int64{1, 2, 3, 4}, func(x int64, _ int) (string, bool) {\n\t\tif x%2 == 0 {\n\t\t\treturn strconv.FormatInt(x, 10), true\n\t\t}\n\t\treturn \"\", false\n\t})\n\tr2 := FilterMap([]string{\"cpu\", \"gpu\", \"mouse\", \"keyboard\"}, func(x string, _ int) (string, bool) {\n\t\tif strings.HasSuffix(x, \"pu\") {\n\t\t\treturn \"xpu\", true\n\t\t}\n\t\treturn \"\", false\n\t})\n\n\tis.Equal([]string{\"2\", \"4\"}, r1)\n\tis.Equal([]string{\"xpu\", \"xpu\"}, r2)\n}\n\nfunc TestFlatMap(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := FlatMap([]int{0, 1, 2, 3, 4}, func(x, _ int) []string {\n\t\treturn []string{\"Hello\"}\n\t})\n\tresult2 := FlatMap([]int64{0, 1, 2, 3, 4}, func(x int64, _ int) []string {\n\t\tresult := make([]string, 0, x)\n\t\tfor i := int64(0); i < x; i++ {\n\t\t\tresult = append(result, strconv.FormatInt(x, 10))\n\t\t}\n\t\treturn result\n\t})\n\n\tis.Equal([]string{\"Hello\", \"Hello\", \"Hello\", \"Hello\", \"Hello\"}, result1)\n\tis.Equal([]string{\"1\", \"2\", \"2\", \"3\", \"3\", \"3\", \"4\", \"4\", \"4\", \"4\"}, result2)\n}\n\nfunc TestFlatMapErr(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\ttests := []struct {\n\t\tname                  string\n\t\tinput                 []int64\n\t\ttransform             func(item int64, index int) ([]string, error)\n\t\twantResult            []string\n\t\twantErr               bool\n\t\terrMsg                string\n\t\texpectedCallbackCount int\n\t}{\n\t\t{\n\t\t\tname:  \"successful transformation\",\n\t\t\tinput: []int64{0, 1, 2},\n\t\t\ttransform: func(x int64, _ int) ([]string, error) {\n\t\t\t\treturn []string{strconv.FormatInt(x, 10), strconv.FormatInt(x, 10)}, nil\n\t\t\t},\n\t\t\twantResult:            []string{\"0\", \"0\", \"1\", \"1\", \"2\", \"2\"},\n\t\t\twantErr:               false,\n\t\t\texpectedCallbackCount: 3,\n\t\t},\n\t\t{\n\t\t\tname:  \"error at second element stops iteration\",\n\t\t\tinput: []int64{0, 1, 2, 3},\n\t\t\ttransform: func(x int64, _ int) ([]string, error) {\n\t\t\t\tif x == 1 {\n\t\t\t\t\treturn nil, errors.New(\"number 1 is not allowed\")\n\t\t\t\t}\n\t\t\t\treturn []string{strconv.FormatInt(x, 10)}, nil\n\t\t\t},\n\t\t\twantResult:            nil,\n\t\t\twantErr:               true,\n\t\t\terrMsg:                \"number 1 is not allowed\",\n\t\t\texpectedCallbackCount: 2,\n\t\t},\n\t\t{\n\t\t\tname:  \"error at first element stops iteration immediately\",\n\t\t\tinput: []int64{0, 1, 2, 3},\n\t\t\ttransform: func(x int64, _ int) ([]string, error) {\n\t\t\t\tif x == 0 {\n\t\t\t\t\treturn nil, errors.New(\"number 0 is not allowed\")\n\t\t\t\t}\n\t\t\t\treturn []string{strconv.FormatInt(x, 10)}, nil\n\t\t\t},\n\t\t\twantResult:            nil,\n\t\t\twantErr:               true,\n\t\t\terrMsg:                \"number 0 is not allowed\",\n\t\t\texpectedCallbackCount: 1,\n\t\t},\n\t\t{\n\t\t\tname:  \"error at last element\",\n\t\t\tinput: []int64{0, 1, 2},\n\t\t\ttransform: func(x int64, _ int) ([]string, error) {\n\t\t\t\tif x == 2 {\n\t\t\t\t\treturn nil, errors.New(\"number 2 is not allowed\")\n\t\t\t\t}\n\t\t\t\treturn []string{strconv.FormatInt(x, 10)}, nil\n\t\t\t},\n\t\t\twantResult:            nil,\n\t\t\twantErr:               true,\n\t\t\terrMsg:                \"number 2 is not allowed\",\n\t\t\texpectedCallbackCount: 3,\n\t\t},\n\t\t{\n\t\t\tname:  \"empty input slice\",\n\t\t\tinput: []int64{},\n\t\t\ttransform: func(x int64, _ int) ([]string, error) {\n\t\t\t\treturn []string{strconv.FormatInt(x, 10)}, nil\n\t\t\t},\n\t\t\twantResult:            []string{},\n\t\t\twantErr:               false,\n\t\t\texpectedCallbackCount: 0,\n\t\t},\n\t\t{\n\t\t\tname:  \"returns empty slice for each element\",\n\t\t\tinput: []int64{1, 2, 3},\n\t\t\ttransform: func(x int64, _ int) ([]string, error) {\n\t\t\t\treturn []string{}, nil\n\t\t\t},\n\t\t\twantResult:            []string{},\n\t\t\twantErr:               false,\n\t\t\texpectedCallbackCount: 3,\n\t\t},\n\t\t{\n\t\t\tname:  \"returns nil for some elements\",\n\t\t\tinput: []int64{1, 2, 3},\n\t\t\ttransform: func(x int64, _ int) ([]string, error) {\n\t\t\t\tif x == 2 {\n\t\t\t\t\treturn nil, nil\n\t\t\t\t}\n\t\t\t\treturn []string{strconv.FormatInt(x, 10)}, nil\n\t\t\t},\n\t\t\twantResult:            []string{\"1\", \"3\"},\n\t\t\twantErr:               false,\n\t\t\texpectedCallbackCount: 3,\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\ttt := tt\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\n\t\t\t// Track callback count to test early return\n\t\t\tcallbackCount := 0\n\t\t\twrappedTransform := func(item int64, index int) ([]string, error) {\n\t\t\t\tcallbackCount++\n\t\t\t\treturn tt.transform(item, index)\n\t\t\t}\n\n\t\t\tresult, err := FlatMapErr(tt.input, wrappedTransform)\n\n\t\t\tif tt.wantErr {\n\t\t\t\tis.Error(err)\n\t\t\t\tis.Equal(tt.errMsg, err.Error())\n\t\t\t\tis.Nil(result)\n\t\t\t} else {\n\t\t\t\tis.NoError(err)\n\t\t\t\tis.Equal(tt.wantResult, result)\n\t\t\t}\n\n\t\t\t// Verify callback count matches expected\n\t\t\tis.Equal(tt.expectedCallbackCount, callbackCount, \"callback count should match expected\")\n\t\t})\n\t}\n}\n\nfunc TestTimes(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := Times(3, func(i int) string {\n\t\treturn strconv.FormatInt(int64(i), 10)\n\t})\n\tis.Equal([]string{\"0\", \"1\", \"2\"}, result1)\n}\n\nfunc TestReduce(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := Reduce([]int{1, 2, 3, 4}, func(agg, item, _ int) int {\n\t\treturn agg + item\n\t}, 0)\n\tresult2 := Reduce([]int{1, 2, 3, 4}, func(agg, item, _ int) int {\n\t\treturn agg + item\n\t}, 10)\n\n\tis.Equal(10, result1)\n\tis.Equal(20, result2)\n}\n\nfunc TestReduceErr(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\ttests := []struct {\n\t\tname                  string\n\t\tinput                 []int\n\t\taccumulator           func(agg, item, index int) (int, error)\n\t\tinitial               int\n\t\twantResult            int\n\t\twantErr               bool\n\t\terrMsg                string\n\t\texpectedCallbackCount int\n\t}{\n\t\t{\n\t\t\tname:  \"successful reduction\",\n\t\t\tinput: []int{1, 2, 3, 4},\n\t\t\taccumulator: func(agg, item, _ int) (int, error) {\n\t\t\t\treturn agg + item, nil\n\t\t\t},\n\t\t\tinitial:               0,\n\t\t\twantResult:            10,\n\t\t\twantErr:               false,\n\t\t\texpectedCallbackCount: 4,\n\t\t},\n\t\t{\n\t\t\tname:  \"error at third element stops iteration\",\n\t\t\tinput: []int{1, 2, 3, 4},\n\t\t\taccumulator: func(agg, item, _ int) (int, error) {\n\t\t\t\tif item == 3 {\n\t\t\t\t\treturn 0, errors.New(\"number 3 is not allowed\")\n\t\t\t\t}\n\t\t\t\treturn agg + item, nil\n\t\t\t},\n\t\t\tinitial:               0,\n\t\t\twantResult:            0,\n\t\t\twantErr:               true,\n\t\t\terrMsg:                \"number 3 is not allowed\",\n\t\t\texpectedCallbackCount: 3,\n\t\t},\n\t\t{\n\t\t\tname:  \"error at first element stops iteration immediately\",\n\t\t\tinput: []int{1, 2, 3, 4},\n\t\t\taccumulator: func(agg, item, _ int) (int, error) {\n\t\t\t\tif item == 1 {\n\t\t\t\t\treturn 0, errors.New(\"number 1 is not allowed\")\n\t\t\t\t}\n\t\t\t\treturn agg + item, nil\n\t\t\t},\n\t\t\tinitial:               0,\n\t\t\twantResult:            0,\n\t\t\twantErr:               true,\n\t\t\terrMsg:                \"number 1 is not allowed\",\n\t\t\texpectedCallbackCount: 1,\n\t\t},\n\t\t{\n\t\t\tname:  \"error at last element\",\n\t\t\tinput: []int{1, 2, 3, 4},\n\t\t\taccumulator: func(agg, item, _ int) (int, error) {\n\t\t\t\tif item == 4 {\n\t\t\t\t\treturn 0, errors.New(\"number 4 is not allowed\")\n\t\t\t\t}\n\t\t\t\treturn agg + item, nil\n\t\t\t},\n\t\t\tinitial:               0,\n\t\t\twantResult:            0,\n\t\t\twantErr:               true,\n\t\t\terrMsg:                \"number 4 is not allowed\",\n\t\t\texpectedCallbackCount: 4,\n\t\t},\n\t\t{\n\t\t\tname:  \"empty input slice\",\n\t\t\tinput: []int{},\n\t\t\taccumulator: func(agg, item, _ int) (int, error) {\n\t\t\t\treturn agg + item, nil\n\t\t\t},\n\t\t\tinitial:               10,\n\t\t\twantResult:            10,\n\t\t\twantErr:               false,\n\t\t\texpectedCallbackCount: 0,\n\t\t},\n\t\t{\n\t\t\tname:  \"with non-zero initial value\",\n\t\t\tinput: []int{1, 2, 3, 4},\n\t\t\taccumulator: func(agg, item, _ int) (int, error) {\n\t\t\t\treturn agg + item, nil\n\t\t\t},\n\t\t\tinitial:               10,\n\t\t\twantResult:            20,\n\t\t\twantErr:               false,\n\t\t\texpectedCallbackCount: 4,\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\ttt := tt\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\n\t\t\t// Track callback count to test early return\n\t\t\tcallbackCount := 0\n\t\t\twrappedAccumulator := func(agg, item, index int) (int, error) {\n\t\t\t\tcallbackCount++\n\t\t\t\treturn tt.accumulator(agg, item, index)\n\t\t\t}\n\n\t\t\tresult, err := ReduceErr(tt.input, wrappedAccumulator, tt.initial)\n\n\t\t\tif tt.wantErr {\n\t\t\t\tis.Error(err)\n\t\t\t\tis.Equal(tt.errMsg, err.Error())\n\t\t\t} else {\n\t\t\t\tis.NoError(err)\n\t\t\t\tis.Equal(tt.wantResult, result)\n\t\t\t}\n\n\t\t\t// Verify callback count matches expected\n\t\t\tis.Equal(tt.expectedCallbackCount, callbackCount, \"callback count should match expected\")\n\t\t})\n\t}\n}\n\nfunc TestReduceRight(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := ReduceRight([][]int{{0, 1}, {2, 3}, {4, 5}}, func(agg, item []int, _ int) []int {\n\t\treturn append(agg, item...)\n\t}, []int{})\n\n\tis.Equal([]int{4, 5, 2, 3, 0, 1}, result1)\n\n\ttype collection []int\n\tresult3 := ReduceRight(collection{1, 2, 3, 4}, func(agg, item, _ int) int {\n\t\treturn agg + item\n\t}, 10)\n\tis.Equal(20, result3)\n}\n\nfunc TestReduceRightErr(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\ttests := []struct {\n\t\tname                  string\n\t\tinput                 []int\n\t\taccumulator           func(agg, item, index int) (int, error)\n\t\tinitial               int\n\t\twantResult            int\n\t\twantErr               bool\n\t\terrMsg                string\n\t\texpectedCallbackCount int\n\t}{\n\t\t{\n\t\t\tname:  \"successful reduction\",\n\t\t\tinput: []int{1, 2, 3, 4},\n\t\t\taccumulator: func(agg, item, _ int) (int, error) {\n\t\t\t\treturn agg + item, nil\n\t\t\t},\n\t\t\tinitial:               0,\n\t\t\twantResult:            10,\n\t\t\twantErr:               false,\n\t\t\texpectedCallbackCount: 4,\n\t\t},\n\t\t{\n\t\t\tname:  \"error at second element from right stops iteration\",\n\t\t\tinput: []int{1, 2, 3, 4},\n\t\t\taccumulator: func(agg, item, _ int) (int, error) {\n\t\t\t\tif item == 3 {\n\t\t\t\t\treturn 0, errors.New(\"number 3 is not allowed\")\n\t\t\t\t}\n\t\t\t\treturn agg + item, nil\n\t\t\t},\n\t\t\tinitial:               0,\n\t\t\twantResult:            0,\n\t\t\twantErr:               true,\n\t\t\terrMsg:                \"number 3 is not allowed\",\n\t\t\texpectedCallbackCount: 2,\n\t\t},\n\t\t{\n\t\t\tname:  \"error at first element from right stops iteration immediately\",\n\t\t\tinput: []int{1, 2, 3, 4},\n\t\t\taccumulator: func(agg, item, _ int) (int, error) {\n\t\t\t\tif item == 4 {\n\t\t\t\t\treturn 0, errors.New(\"number 4 is not allowed\")\n\t\t\t\t}\n\t\t\t\treturn agg + item, nil\n\t\t\t},\n\t\t\tinitial:               0,\n\t\t\twantResult:            0,\n\t\t\twantErr:               true,\n\t\t\terrMsg:                \"number 4 is not allowed\",\n\t\t\texpectedCallbackCount: 1,\n\t\t},\n\t\t{\n\t\t\tname:  \"error at last element from left\",\n\t\t\tinput: []int{1, 2, 3, 4},\n\t\t\taccumulator: func(agg, item, _ int) (int, error) {\n\t\t\t\tif item == 1 {\n\t\t\t\t\treturn 0, errors.New(\"number 1 is not allowed\")\n\t\t\t\t}\n\t\t\t\treturn agg + item, nil\n\t\t\t},\n\t\t\tinitial:               0,\n\t\t\twantResult:            0,\n\t\t\twantErr:               true,\n\t\t\terrMsg:                \"number 1 is not allowed\",\n\t\t\texpectedCallbackCount: 4,\n\t\t},\n\t\t{\n\t\t\tname:  \"empty input slice\",\n\t\t\tinput: []int{},\n\t\t\taccumulator: func(agg, item, _ int) (int, error) {\n\t\t\t\treturn agg + item, nil\n\t\t\t},\n\t\t\tinitial:               10,\n\t\t\twantResult:            10,\n\t\t\twantErr:               false,\n\t\t\texpectedCallbackCount: 0,\n\t\t},\n\t\t{\n\t\t\tname:  \"with non-zero initial value\",\n\t\t\tinput: []int{1, 2, 3, 4},\n\t\t\taccumulator: func(agg, item, _ int) (int, error) {\n\t\t\t\treturn agg + item, nil\n\t\t\t},\n\t\t\tinitial:               10,\n\t\t\twantResult:            20,\n\t\t\twantErr:               false,\n\t\t\texpectedCallbackCount: 4,\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\ttt := tt\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\n\t\t\t// Track callback count to test early return\n\t\t\tcallbackCount := 0\n\t\t\twrappedAccumulator := func(agg, item, index int) (int, error) {\n\t\t\t\tcallbackCount++\n\t\t\t\treturn tt.accumulator(agg, item, index)\n\t\t\t}\n\n\t\t\tresult, err := ReduceRightErr(tt.input, wrappedAccumulator, tt.initial)\n\n\t\t\tif tt.wantErr {\n\t\t\t\tis.Error(err)\n\t\t\t\tis.Equal(tt.errMsg, err.Error())\n\t\t\t} else {\n\t\t\t\tis.NoError(err)\n\t\t\t\tis.Equal(tt.wantResult, result)\n\t\t\t}\n\n\t\t\t// Verify callback count matches expected\n\t\t\tis.Equal(tt.expectedCallbackCount, callbackCount, \"callback count should match expected\")\n\t\t})\n\t}\n}\n\nfunc TestForEach(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\t// check of callback is called for every element and in proper order\n\n\tcallParams1 := []string{}\n\tcallParams2 := []int{}\n\n\tForEach([]string{\"a\", \"b\", \"c\"}, func(item string, i int) {\n\t\tcallParams1 = append(callParams1, item)\n\t\tcallParams2 = append(callParams2, i)\n\t})\n\n\tis.Equal([]string{\"a\", \"b\", \"c\"}, callParams1)\n\tis.Equal([]int{0, 1, 2}, callParams2)\n\tis.IsIncreasing(callParams2)\n}\n\nfunc TestForEachWhile(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\t// check of callback is called for every element and in proper order\n\n\tvar callParams1 []string\n\tvar callParams2 []int\n\n\tForEachWhile([]string{\"a\", \"b\", \"c\"}, func(item string, i int) bool {\n\t\tif item == \"c\" {\n\t\t\treturn false\n\t\t}\n\t\tcallParams1 = append(callParams1, item)\n\t\tcallParams2 = append(callParams2, i)\n\t\treturn true\n\t})\n\n\tis.Equal([]string{\"a\", \"b\"}, callParams1)\n\tis.Equal([]int{0, 1}, callParams2)\n\tis.IsIncreasing(callParams2)\n}\n\nfunc TestUniq(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := Uniq([]int{1, 2, 2, 1})\n\tis.Equal([]int{1, 2}, result1)\n\n\ttype myStrings []string\n\tallStrings := myStrings{\"\", \"foo\", \"bar\"}\n\tnonempty := Uniq(allStrings)\n\tis.IsType(nonempty, allStrings, \"type preserved\")\n}\n\nfunc TestUniqBy(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := UniqBy([]int{0, 1, 2, 3, 4, 5}, func(i int) int {\n\t\treturn i % 3\n\t})\n\tis.Equal([]int{0, 1, 2}, result1)\n\n\ttype myStrings []string\n\tallStrings := myStrings{\"\", \"foo\", \"bar\"}\n\tnonempty := UniqBy(allStrings, func(i string) string {\n\t\treturn i\n\t})\n\tis.IsType(nonempty, allStrings, \"type preserved\")\n}\n\nfunc TestUniqByErr(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\ttests := []struct {\n\t\tname                  string\n\t\tinput                 []int\n\t\titeratee              func(item int) (int, error)\n\t\twantResult            []int\n\t\twantErr               bool\n\t\terrMsg                string\n\t\texpectedCallbackCount int\n\t}{\n\t\t{\n\t\t\tname:  \"successful uniq\",\n\t\t\tinput: []int{0, 1, 2, 3, 4, 5},\n\t\t\titeratee: func(i int) (int, error) {\n\t\t\t\treturn i % 3, nil\n\t\t\t},\n\t\t\twantResult:            []int{0, 1, 2},\n\t\t\twantErr:               false,\n\t\t\texpectedCallbackCount: 6,\n\t\t},\n\t\t{\n\t\t\tname:  \"error at fourth element stops iteration\",\n\t\t\tinput: []int{0, 1, 2, 3, 4, 5},\n\t\t\titeratee: func(i int) (int, error) {\n\t\t\t\tif i == 3 {\n\t\t\t\t\treturn 0, errors.New(\"number 3 is not allowed\")\n\t\t\t\t}\n\t\t\t\treturn i % 3, nil\n\t\t\t},\n\t\t\twantResult:            nil,\n\t\t\twantErr:               true,\n\t\t\terrMsg:                \"number 3 is not allowed\",\n\t\t\texpectedCallbackCount: 4,\n\t\t},\n\t\t{\n\t\t\tname:  \"error at first element stops iteration immediately\",\n\t\t\tinput: []int{0, 1, 2, 3, 4, 5},\n\t\t\titeratee: func(i int) (int, error) {\n\t\t\t\tif i == 0 {\n\t\t\t\t\treturn 0, errors.New(\"number 0 is not allowed\")\n\t\t\t\t}\n\t\t\t\treturn i % 3, nil\n\t\t\t},\n\t\t\twantResult:            nil,\n\t\t\twantErr:               true,\n\t\t\terrMsg:                \"number 0 is not allowed\",\n\t\t\texpectedCallbackCount: 1,\n\t\t},\n\t\t{\n\t\t\tname:  \"error at last element\",\n\t\t\tinput: []int{0, 1, 2, 3, 4, 5},\n\t\t\titeratee: func(i int) (int, error) {\n\t\t\t\tif i == 5 {\n\t\t\t\t\treturn 0, errors.New(\"number 5 is not allowed\")\n\t\t\t\t}\n\t\t\t\treturn i % 3, nil\n\t\t\t},\n\t\t\twantResult:            nil,\n\t\t\twantErr:               true,\n\t\t\terrMsg:                \"number 5 is not allowed\",\n\t\t\texpectedCallbackCount: 6,\n\t\t},\n\t\t{\n\t\t\tname:  \"empty input slice\",\n\t\t\tinput: []int{},\n\t\t\titeratee: func(i int) (int, error) {\n\t\t\t\treturn i % 3, nil\n\t\t\t},\n\t\t\twantResult:            []int{},\n\t\t\twantErr:               false,\n\t\t\texpectedCallbackCount: 0,\n\t\t},\n\t\t{\n\t\t\tname:  \"all duplicates\",\n\t\t\tinput: []int{1, 1, 1, 1},\n\t\t\titeratee: func(i int) (int, error) {\n\t\t\t\treturn i % 3, nil\n\t\t\t},\n\t\t\twantResult:            []int{1},\n\t\t\twantErr:               false,\n\t\t\texpectedCallbackCount: 4,\n\t\t},\n\t\t{\n\t\t\tname:  \"no duplicates\",\n\t\t\tinput: []int{0, 1, 2, 3},\n\t\t\titeratee: func(i int) (int, error) {\n\t\t\t\treturn i, nil\n\t\t\t},\n\t\t\twantResult:            []int{0, 1, 2, 3},\n\t\t\twantErr:               false,\n\t\t\texpectedCallbackCount: 4,\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\ttt := tt\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\n\t\t\t// Track callback count to test early return\n\t\t\tcallbackCount := 0\n\t\t\twrappedIteratee := func(item int) (int, error) {\n\t\t\t\tcallbackCount++\n\t\t\t\treturn tt.iteratee(item)\n\t\t\t}\n\n\t\t\tresult, err := UniqByErr(tt.input, wrappedIteratee)\n\n\t\t\tif tt.wantErr {\n\t\t\t\tis.Error(err)\n\t\t\t\tis.Equal(tt.errMsg, err.Error())\n\t\t\t\tis.Nil(result)\n\t\t\t} else {\n\t\t\t\tis.NoError(err)\n\t\t\t\tis.Equal(tt.wantResult, result)\n\t\t\t}\n\n\t\t\t// Verify callback count matches expected\n\t\t\tis.Equal(tt.expectedCallbackCount, callbackCount, \"callback count should match expected\")\n\t\t})\n\t}\n}\n\nfunc TestGroupBy(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := GroupBy([]int{0, 1, 2, 3, 4, 5}, func(i int) int {\n\t\treturn i % 3\n\t})\n\tis.Equal(map[int][]int{\n\t\t0: {0, 3},\n\t\t1: {1, 4},\n\t\t2: {2, 5},\n\t}, result1)\n\n\ttype myStrings []string\n\tallStrings := myStrings{\"\", \"foo\", \"bar\"}\n\tnonempty := GroupBy(allStrings, func(i string) int {\n\t\treturn 42\n\t})\n\tis.IsType(nonempty[42], allStrings, \"type preserved\")\n}\n\nfunc TestGroupByErr(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\ttests := []struct {\n\t\tname                  string\n\t\tinput                 []int\n\t\titeratee              func(item int) (int, error)\n\t\twantResult            map[int][]int\n\t\twantErr               bool\n\t\terrMsg                string\n\t\texpectedCallbackCount int\n\t}{\n\t\t{\n\t\t\tname:  \"successful grouping\",\n\t\t\tinput: []int{0, 1, 2, 3, 4, 5},\n\t\t\titeratee: func(i int) (int, error) {\n\t\t\t\treturn i % 3, nil\n\t\t\t},\n\t\t\twantResult: map[int][]int{\n\t\t\t\t0: {0, 3},\n\t\t\t\t1: {1, 4},\n\t\t\t\t2: {2, 5},\n\t\t\t},\n\t\t\twantErr:               false,\n\t\t\texpectedCallbackCount: 6,\n\t\t},\n\t\t{\n\t\t\tname:  \"error at fourth element stops iteration\",\n\t\t\tinput: []int{0, 1, 2, 3, 4, 5},\n\t\t\titeratee: func(i int) (int, error) {\n\t\t\t\tif i == 3 {\n\t\t\t\t\treturn 0, errors.New(\"number 3 is not allowed\")\n\t\t\t\t}\n\t\t\t\treturn i % 3, nil\n\t\t\t},\n\t\t\twantResult:            nil,\n\t\t\twantErr:               true,\n\t\t\terrMsg:                \"number 3 is not allowed\",\n\t\t\texpectedCallbackCount: 4,\n\t\t},\n\t\t{\n\t\t\tname:  \"error at first element stops iteration immediately\",\n\t\t\tinput: []int{0, 1, 2, 3, 4, 5},\n\t\t\titeratee: func(i int) (int, error) {\n\t\t\t\tif i == 0 {\n\t\t\t\t\treturn 0, errors.New(\"number 0 is not allowed\")\n\t\t\t\t}\n\t\t\t\treturn i % 3, nil\n\t\t\t},\n\t\t\twantResult:            nil,\n\t\t\twantErr:               true,\n\t\t\terrMsg:                \"number 0 is not allowed\",\n\t\t\texpectedCallbackCount: 1,\n\t\t},\n\t\t{\n\t\t\tname:  \"error at last element\",\n\t\t\tinput: []int{0, 1, 2, 3, 4, 5},\n\t\t\titeratee: func(i int) (int, error) {\n\t\t\t\tif i == 5 {\n\t\t\t\t\treturn 0, errors.New(\"number 5 is not allowed\")\n\t\t\t\t}\n\t\t\t\treturn i % 3, nil\n\t\t\t},\n\t\t\twantResult:            nil,\n\t\t\twantErr:               true,\n\t\t\terrMsg:                \"number 5 is not allowed\",\n\t\t\texpectedCallbackCount: 6,\n\t\t},\n\t\t{\n\t\t\tname:  \"empty input slice\",\n\t\t\tinput: []int{},\n\t\t\titeratee: func(i int) (int, error) {\n\t\t\t\treturn i % 3, nil\n\t\t\t},\n\t\t\twantResult:            map[int][]int{},\n\t\t\twantErr:               false,\n\t\t\texpectedCallbackCount: 0,\n\t\t},\n\t\t{\n\t\t\tname:  \"all elements in same group\",\n\t\t\tinput: []int{3, 6, 9, 12},\n\t\t\titeratee: func(i int) (int, error) {\n\t\t\t\treturn 0, nil\n\t\t\t},\n\t\t\twantResult: map[int][]int{\n\t\t\t\t0: {3, 6, 9, 12},\n\t\t\t},\n\t\t\twantErr:               false,\n\t\t\texpectedCallbackCount: 4,\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\ttt := tt\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\n\t\t\t// Track callback count to test early return\n\t\t\tcallbackCount := 0\n\t\t\twrappedIteratee := func(item int) (int, error) {\n\t\t\t\tcallbackCount++\n\t\t\t\treturn tt.iteratee(item)\n\t\t\t}\n\n\t\t\tresult, err := GroupByErr(tt.input, wrappedIteratee)\n\n\t\t\tif tt.wantErr {\n\t\t\t\tis.Error(err)\n\t\t\t\tis.Equal(tt.errMsg, err.Error())\n\t\t\t\tis.Nil(result)\n\t\t\t} else {\n\t\t\t\tis.NoError(err)\n\t\t\t\tis.Equal(tt.wantResult, result)\n\t\t\t}\n\n\t\t\t// Verify callback count matches expected\n\t\t\tis.Equal(tt.expectedCallbackCount, callbackCount, \"callback count should match expected\")\n\t\t})\n\t}\n}\n\nfunc TestGroupByMap(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := GroupByMap([]int{0, 1, 2, 3, 4, 5}, func(i int) (int, string) {\n\t\treturn i % 3, strconv.Itoa(i)\n\t})\n\tis.Equal(map[int][]string{\n\t\t0: {\"0\", \"3\"},\n\t\t1: {\"1\", \"4\"},\n\t\t2: {\"2\", \"5\"},\n\t}, result1)\n\n\ttype myInt int\n\ttype myInts []myInt\n\tresult2 := GroupByMap(myInts{1, 0, 2, 3, 4, 5}, func(i myInt) (int, string) {\n\t\treturn int(i % 3), strconv.Itoa(int(i))\n\t})\n\tis.Equal(map[int][]string{\n\t\t0: {\"0\", \"3\"},\n\t\t1: {\"1\", \"4\"},\n\t\t2: {\"2\", \"5\"},\n\t}, result2)\n\n\ttype product struct {\n\t\tID         int64\n\t\tCategoryID int64\n\t}\n\tproducts := []product{\n\t\t{ID: 1, CategoryID: 1},\n\t\t{ID: 2, CategoryID: 1},\n\t\t{ID: 3, CategoryID: 2},\n\t\t{ID: 4, CategoryID: 3},\n\t\t{ID: 5, CategoryID: 3},\n\t}\n\tresult3 := GroupByMap(products, func(item product) (int64, string) {\n\t\treturn item.CategoryID, \"Product \" + strconv.FormatInt(item.ID, 10)\n\t})\n\tis.Equal(map[int64][]string{\n\t\t1: {\"Product 1\", \"Product 2\"},\n\t\t2: {\"Product 3\"},\n\t\t3: {\"Product 4\", \"Product 5\"},\n\t}, result3)\n}\n\nfunc TestGroupByMapErr(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\ttests := []struct {\n\t\tname                  string\n\t\tinput                 []int\n\t\ttransform             func(item int) (int, int, error)\n\t\twantResult            map[int][]int\n\t\twantErr               bool\n\t\terrMsg                string\n\t\texpectedCallbackCount int\n\t}{\n\t\t{\n\t\t\tname:  \"successful grouping\",\n\t\t\tinput: []int{0, 1, 2, 3, 4, 5},\n\t\t\ttransform: func(i int) (int, int, error) {\n\t\t\t\treturn i % 3, i * 2, nil\n\t\t\t},\n\t\t\twantResult: map[int][]int{\n\t\t\t\t0: {0, 6},\n\t\t\t\t1: {2, 8},\n\t\t\t\t2: {4, 10},\n\t\t\t},\n\t\t\twantErr:               false,\n\t\t\texpectedCallbackCount: 6,\n\t\t},\n\t\t{\n\t\t\tname:  \"error at fourth element stops iteration\",\n\t\t\tinput: []int{0, 1, 2, 3, 4, 5},\n\t\t\ttransform: func(i int) (int, int, error) {\n\t\t\t\tif i == 3 {\n\t\t\t\t\treturn 0, 0, errors.New(\"number 3 is not allowed\")\n\t\t\t\t}\n\t\t\t\treturn i % 3, i * 2, nil\n\t\t\t},\n\t\t\twantResult:            nil,\n\t\t\twantErr:               true,\n\t\t\terrMsg:                \"number 3 is not allowed\",\n\t\t\texpectedCallbackCount: 4,\n\t\t},\n\t\t{\n\t\t\tname:  \"error at first element stops iteration immediately\",\n\t\t\tinput: []int{0, 1, 2, 3, 4, 5},\n\t\t\ttransform: func(i int) (int, int, error) {\n\t\t\t\tif i == 0 {\n\t\t\t\t\treturn 0, 0, errors.New(\"number 0 is not allowed\")\n\t\t\t\t}\n\t\t\t\treturn i % 3, i * 2, nil\n\t\t\t},\n\t\t\twantResult:            nil,\n\t\t\twantErr:               true,\n\t\t\terrMsg:                \"number 0 is not allowed\",\n\t\t\texpectedCallbackCount: 1,\n\t\t},\n\t\t{\n\t\t\tname:  \"error at last element\",\n\t\t\tinput: []int{0, 1, 2, 3, 4, 5},\n\t\t\ttransform: func(i int) (int, int, error) {\n\t\t\t\tif i == 5 {\n\t\t\t\t\treturn 0, 0, errors.New(\"number 5 is not allowed\")\n\t\t\t\t}\n\t\t\t\treturn i % 3, i * 2, nil\n\t\t\t},\n\t\t\twantResult:            nil,\n\t\t\twantErr:               true,\n\t\t\terrMsg:                \"number 5 is not allowed\",\n\t\t\texpectedCallbackCount: 6,\n\t\t},\n\t\t{\n\t\t\tname:  \"empty input slice\",\n\t\t\tinput: []int{},\n\t\t\ttransform: func(i int) (int, int, error) {\n\t\t\t\treturn i % 3, i * 2, nil\n\t\t\t},\n\t\t\twantResult:            map[int][]int{},\n\t\t\twantErr:               false,\n\t\t\texpectedCallbackCount: 0,\n\t\t},\n\t\t{\n\t\t\tname:  \"all elements in same group\",\n\t\t\tinput: []int{3, 6, 9, 12},\n\t\t\ttransform: func(i int) (int, int, error) {\n\t\t\t\treturn 0, i, nil\n\t\t\t},\n\t\t\twantResult: map[int][]int{\n\t\t\t\t0: {3, 6, 9, 12},\n\t\t\t},\n\t\t\twantErr:               false,\n\t\t\texpectedCallbackCount: 4,\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\ttt := tt\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\n\t\t\t// Track callback count to test early return\n\t\t\tcallbackCount := 0\n\t\t\twrappedTransform := func(item int) (int, int, error) {\n\t\t\t\tcallbackCount++\n\t\t\t\treturn tt.transform(item)\n\t\t\t}\n\n\t\t\tresult, err := GroupByMapErr(tt.input, wrappedTransform)\n\n\t\t\tif tt.wantErr {\n\t\t\t\tis.Error(err)\n\t\t\t\tis.Equal(tt.errMsg, err.Error())\n\t\t\t\tis.Nil(result)\n\t\t\t} else {\n\t\t\t\tis.NoError(err)\n\t\t\t\tis.Equal(tt.wantResult, result)\n\t\t\t}\n\n\t\t\t// Verify callback count matches expected\n\t\t\tis.Equal(tt.expectedCallbackCount, callbackCount, \"callback count should match expected\")\n\t\t})\n\t}\n}\n\nfunc TestChunk(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := Chunk([]int{0, 1, 2, 3, 4, 5}, 2)\n\tresult2 := Chunk([]int{0, 1, 2, 3, 4, 5, 6}, 2)\n\tresult3 := Chunk([]int{}, 2)\n\tresult4 := Chunk([]int{0}, 2)\n\n\tis.Equal([][]int{{0, 1}, {2, 3}, {4, 5}}, result1)\n\tis.Equal([][]int{{0, 1}, {2, 3}, {4, 5}, {6}}, result2)\n\tis.Empty(result3)\n\tis.Equal([][]int{{0}}, result4)\n\tis.PanicsWithValue(\"lo.Chunk: size must be greater than 0\", func() {\n\t\tChunk([]int{0}, 0)\n\t})\n\n\ttype myStrings []string\n\tallStrings := myStrings{\"\", \"foo\", \"bar\"}\n\tnonempty := Chunk(allStrings, 2)\n\tis.IsType(nonempty[0], allStrings, \"type preserved\")\n\n\t// appending to a chunk should not affect original slice\n\toriginal := []int{0, 1, 2, 3, 4, 5}\n\tresult5 := Chunk(original, 2)\n\tresult5[0] = append(result5[0], 6)\n\tis.Equal([]int{0, 1, 2, 3, 4, 5}, original)\n}\n\nfunc TestWindow(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := Window([]int{1, 2, 3, 4, 5}, 3)\n\tresult2 := Window([]int{1, 2, 3, 4, 5, 6}, 3)\n\tresult3 := Window([]int{1, 2}, 3)\n\tresult4 := Window([]int{1, 2, 3}, 3)\n\tresult5 := Window([]int{1, 2, 3, 4}, 1)\n\n\tis.Equal([][]int{{1, 2, 3}, {2, 3, 4}, {3, 4, 5}}, result1)\n\tis.Equal([][]int{{1, 2, 3}, {2, 3, 4}, {3, 4, 5}, {4, 5, 6}}, result2)\n\tis.Empty(result3)\n\tis.Equal([][]int{{1, 2, 3}}, result4)\n\tis.Equal([][]int{{1}, {2}, {3}, {4}}, result5)\n\n\tis.PanicsWithValue(\"lo.Window: size must be greater than 0\", func() {\n\t\tWindow([]int{1, 2, 3}, 0)\n\t})\n\n\tis.PanicsWithValue(\"lo.Window: size must be greater than 0\", func() {\n\t\tWindow([]int{1, 2, 3}, -1)\n\t})\n\n\ttype myStrings []string\n\tallStrings := myStrings{\"a\", \"b\", \"c\", \"d\"}\n\twindows := Window(allStrings, 2)\n\tis.IsType(windows[0], allStrings, \"type preserved\")\n\tis.Equal(myStrings{\"a\", \"b\"}, windows[0])\n\n\t// appending to a window should not affect original slice\n\toriginal := []int{1, 2, 3, 4, 5}\n\twindows2 := Window(original, 3)\n\twindows2[0] = append(windows2[0], 6)\n\tis.Equal([]int{1, 2, 3, 4, 5}, original)\n}\n\nfunc TestSliding(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\t// Overlapping windows (step < size)\n\tresult1 := Sliding([]int{1, 2, 3, 4, 5, 6}, 3, 1)\n\tis.Equal([][]int{{1, 2, 3}, {2, 3, 4}, {3, 4, 5}, {4, 5, 6}}, result1)\n\n\t// Non-overlapping windows (step == size, like Chunk)\n\tresult2 := Sliding([]int{1, 2, 3, 4, 5, 6}, 3, 3)\n\tis.Equal([][]int{{1, 2, 3}, {4, 5, 6}}, result2)\n\n\t// Step > size (skipping elements)\n\tresult3 := Sliding([]int{1, 2, 3, 4, 5, 6, 7, 8}, 2, 3)\n\tis.Equal([][]int{{1, 2}, {4, 5}, {7, 8}}, result3)\n\n\t// Single element windows\n\tresult4 := Sliding([]int{1, 2, 3, 4}, 1, 1)\n\tis.Equal([][]int{{1}, {2}, {3}, {4}}, result4)\n\n\t// Empty result when collection is too small\n\tresult5 := Sliding([]int{1, 2}, 3, 1)\n\tis.Empty(result5)\n\n\t// Step 2, size 2\n\tresult6 := Sliding([]int{1, 2, 3, 4, 5, 6}, 2, 2)\n\tis.Equal([][]int{{1, 2}, {3, 4}, {5, 6}}, result6)\n\n\tis.PanicsWithValue(\"lo.Sliding: size must be greater than 0\", func() {\n\t\tSliding([]int{1, 2, 3}, 0, 1)\n\t})\n\n\tis.PanicsWithValue(\"lo.Sliding: step must be greater than 0\", func() {\n\t\tSliding([]int{1, 2, 3}, 2, 0)\n\t})\n\n\tis.PanicsWithValue(\"lo.Sliding: step must be greater than 0\", func() {\n\t\tSliding([]int{1, 2, 3}, 2, -1)\n\t})\n\n\ttype myStrings []string\n\tallStrings := myStrings{\"a\", \"b\", \"c\", \"d\", \"e\"}\n\twindows := Sliding(allStrings, 2, 2)\n\tis.IsType(windows[0], allStrings, \"type preserved\")\n\tis.Equal(myStrings{\"a\", \"b\"}, windows[0])\n\n\t// appending to a window should not affect original slice\n\toriginal := []int{1, 2, 3, 4, 5, 6}\n\twindows2 := Sliding(original, 2, 2)\n\twindows2[0] = append(windows2[0], 7)\n\tis.Equal([]int{1, 2, 3, 4, 5, 6}, original)\n}\n\nfunc TestPartitionBy(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\toddEven := func(x int) string {\n\t\tif x < 0 {\n\t\t\treturn \"negative\"\n\t\t} else if x%2 == 0 {\n\t\t\treturn \"even\"\n\t\t}\n\t\treturn \"odd\"\n\t}\n\n\tresult1 := PartitionBy([]int{-2, -1, 0, 1, 2, 3, 4, 5}, oddEven)\n\tresult2 := PartitionBy([]int{}, oddEven)\n\n\tis.Equal([][]int{{-2, -1}, {0, 2, 4}, {1, 3, 5}}, result1)\n\tis.Empty(result2)\n\n\ttype myStrings []string\n\tallStrings := myStrings{\"\", \"foo\", \"bar\"}\n\tnonempty := PartitionBy(allStrings, func(item string) int {\n\t\treturn len(item)\n\t})\n\tis.IsType(nonempty[0], allStrings, \"type preserved\")\n}\n\nfunc TestPartitionByErr(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\toddEven := func(x int) (string, error) {\n\t\tif x < 0 {\n\t\t\treturn \"negative\", nil\n\t\t} else if x%2 == 0 {\n\t\t\treturn \"even\", nil\n\t\t}\n\t\treturn \"odd\", nil\n\t}\n\n\ttests := []struct {\n\t\tname                  string\n\t\tinput                 []int\n\t\titeratee              func(item int) (string, error)\n\t\twantResult            [][]int\n\t\twantErr               bool\n\t\terrMsg                string\n\t\texpectedCallbackCount int\n\t}{\n\t\t{\n\t\t\tname:                  \"successful partition\",\n\t\t\tinput:                 []int{-2, -1, 0, 1, 2, 3, 4, 5},\n\t\t\titeratee:              oddEven,\n\t\t\twantResult:            [][]int{{-2, -1}, {0, 2, 4}, {1, 3, 5}},\n\t\t\twantErr:               false,\n\t\t\texpectedCallbackCount: 8,\n\t\t},\n\t\t{\n\t\t\tname:  \"error at fifth element stops iteration\",\n\t\t\tinput: []int{-2, -1, 0, 1, 2, 3},\n\t\t\titeratee: func(x int) (string, error) {\n\t\t\t\tif x == 2 {\n\t\t\t\t\treturn \"\", errors.New(\"number 2 is not allowed\")\n\t\t\t\t}\n\t\t\t\treturn oddEven(x)\n\t\t\t},\n\t\t\twantResult:            nil,\n\t\t\twantErr:               true,\n\t\t\terrMsg:                \"number 2 is not allowed\",\n\t\t\texpectedCallbackCount: 5,\n\t\t},\n\t\t{\n\t\t\tname:  \"error at first element stops iteration immediately\",\n\t\t\tinput: []int{-2, -1, 0, 1},\n\t\t\titeratee: func(x int) (string, error) {\n\t\t\t\tif x == -2 {\n\t\t\t\t\treturn \"\", errors.New(\"number -2 is not allowed\")\n\t\t\t\t}\n\t\t\t\treturn oddEven(x)\n\t\t\t},\n\t\t\twantResult:            nil,\n\t\t\twantErr:               true,\n\t\t\terrMsg:                \"number -2 is not allowed\",\n\t\t\texpectedCallbackCount: 1,\n\t\t},\n\t\t{\n\t\t\tname:  \"error at last element\",\n\t\t\tinput: []int{-2, -1, 0, 1, 2},\n\t\t\titeratee: func(x int) (string, error) {\n\t\t\t\tif x == 2 {\n\t\t\t\t\treturn \"\", errors.New(\"number 2 is not allowed\")\n\t\t\t\t}\n\t\t\t\treturn oddEven(x)\n\t\t\t},\n\t\t\twantResult:            nil,\n\t\t\twantErr:               true,\n\t\t\terrMsg:                \"number 2 is not allowed\",\n\t\t\texpectedCallbackCount: 5,\n\t\t},\n\t\t{\n\t\t\tname:                  \"empty input slice\",\n\t\t\tinput:                 []int{},\n\t\t\titeratee:              oddEven,\n\t\t\twantResult:            [][]int{},\n\t\t\twantErr:               false,\n\t\t\texpectedCallbackCount: 0,\n\t\t},\n\t\t{\n\t\t\tname:  \"all elements in same partition\",\n\t\t\tinput: []int{1, 3, 5},\n\t\t\titeratee: func(x int) (string, error) {\n\t\t\t\treturn \"odd\", nil\n\t\t\t},\n\t\t\twantResult:            [][]int{{1, 3, 5}},\n\t\t\twantErr:               false,\n\t\t\texpectedCallbackCount: 3,\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\ttt := tt\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\n\t\t\t// Track callback count to test early return\n\t\t\tcallbackCount := 0\n\t\t\twrappedIteratee := func(item int) (string, error) {\n\t\t\t\tcallbackCount++\n\t\t\t\treturn tt.iteratee(item)\n\t\t\t}\n\n\t\t\tresult, err := PartitionByErr(tt.input, wrappedIteratee)\n\n\t\t\tif tt.wantErr {\n\t\t\t\tis.Error(err)\n\t\t\t\tis.Equal(tt.errMsg, err.Error())\n\t\t\t\tis.Nil(result)\n\t\t\t} else {\n\t\t\t\tis.NoError(err)\n\t\t\t\tis.Equal(tt.wantResult, result)\n\t\t\t}\n\n\t\t\t// Verify callback count matches expected\n\t\t\tis.Equal(tt.expectedCallbackCount, callbackCount, \"callback count should match expected\")\n\t\t})\n\t}\n}\n\nfunc TestFlatten(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := Flatten([][]int{{0, 1}, {2, 3, 4, 5}})\n\n\tis.Equal([]int{0, 1, 2, 3, 4, 5}, result1)\n\n\ttype myStrings []string\n\tallStrings := myStrings{\"\", \"foo\", \"bar\"}\n\tnonempty := Flatten([]myStrings{allStrings})\n\tis.IsType(nonempty, allStrings, \"type preserved\")\n}\n\nfunc TestConcat(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := Concat([][]int{{0, 1}, {2, 3, 4, 5}}...)\n\n\tis.Equal([]int{0, 1, 2, 3, 4, 5}, result1)\n\n\ttype myStrings []string\n\tallStrings := myStrings{\"\", \"foo\", \"bar\"}\n\tnonempty := Concat([]myStrings{allStrings}...)\n\tis.IsType(nonempty, allStrings, \"type preserved\")\n}\n\nfunc TestInterleave(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\ttestCases := []struct {\n\t\tname string\n\t\tin   [][]int\n\t\twant []int\n\t}{\n\t\t{\n\t\t\t\"nil\",\n\t\t\t[][]int{nil},\n\t\t\t[]int{},\n\t\t},\n\t\t{\n\t\t\t\"empty\",\n\t\t\t[][]int{},\n\t\t\t[]int{},\n\t\t},\n\t\t{\n\t\t\t\"empties\",\n\t\t\t[][]int{{}, {}},\n\t\t\t[]int{},\n\t\t},\n\t\t{\n\t\t\t\"same length\",\n\t\t\t[][]int{{1, 3, 5}, {2, 4, 6}},\n\t\t\t[]int{1, 2, 3, 4, 5, 6},\n\t\t},\n\t\t{\n\t\t\t\"different length\",\n\t\t\t[][]int{{1, 3, 5, 6}, {2, 4}},\n\t\t\t[]int{1, 2, 3, 4, 5, 6},\n\t\t},\n\t\t{\n\t\t\t\"many slices\",\n\t\t\t[][]int{{1}, {2, 5, 8}, {3, 6}, {4, 7, 9, 10}},\n\t\t\t[]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10},\n\t\t},\n\t}\n\tfor _, tc := range testCases {\n\t\ttc := tc\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\tassert.Equal(t, tc.want, Interleave(tc.in...))\n\t\t})\n\t}\n\n\ttype myStrings []string\n\tallStrings := myStrings{\"\", \"foo\", \"bar\"}\n\tnonempty := Interleave(allStrings)\n\tis.IsType(nonempty, allStrings, \"type preserved\")\n}\n\nfunc TestShuffle(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := Shuffle([]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10})\n\tresult2 := Shuffle([]int{})\n\n\tis.NotEqual([]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, result1)\n\tis.ElementsMatch([]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, result1)\n\tis.Empty(result2)\n\n\ttype myStrings []string\n\tallStrings := myStrings{\"\", \"foo\", \"bar\"}\n\tnonempty := Shuffle(allStrings)\n\tis.IsType(nonempty, allStrings, \"type preserved\")\n}\n\nfunc TestReverse(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := Reverse([]int{0, 1, 2, 3, 4, 5})\n\tresult2 := Reverse([]int{0, 1, 2, 3, 4, 5, 6})\n\tresult3 := Reverse([]int{})\n\n\tis.Equal([]int{5, 4, 3, 2, 1, 0}, result1)\n\tis.Equal([]int{6, 5, 4, 3, 2, 1, 0}, result2)\n\tis.Empty(result3)\n\n\ttype myStrings []string\n\tallStrings := myStrings{\"\", \"foo\", \"bar\"}\n\tnonempty := Reverse(allStrings)\n\tis.IsType(nonempty, allStrings, \"type preserved\")\n}\n\nfunc TestFill(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := Fill([]foo{{\"a\"}, {\"a\"}}, foo{\"b\"})\n\tresult2 := Fill([]foo{}, foo{\"a\"})\n\n\tis.Equal([]foo{{\"b\"}, {\"b\"}}, result1)\n\tis.Empty(result2)\n}\n\nfunc TestRepeat(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := Repeat(2, foo{\"a\"})\n\tresult2 := Repeat(0, foo{\"a\"})\n\n\tis.Equal([]foo{{\"a\"}, {\"a\"}}, result1)\n\tis.Empty(result2)\n}\n\nfunc TestRepeatBy(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tcb := func(i int) int {\n\t\treturn int(math.Pow(float64(i), 2))\n\t}\n\n\tresult1 := RepeatBy(0, cb)\n\tresult2 := RepeatBy(2, cb)\n\tresult3 := RepeatBy(5, cb)\n\n\tis.Empty(result1)\n\tis.Equal([]int{0, 1}, result2)\n\tis.Equal([]int{0, 1, 4, 9, 16}, result3)\n}\n\nfunc TestRepeatByErr(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\ttestErr := errors.New(\"test error\")\n\n\t// Table-driven tests\n\ttests := []struct {\n\t\tname                  string\n\t\tcount                 int\n\t\tcallback              func(index int) (int, error)\n\t\twantResult            []int\n\t\twantErr               bool\n\t\texpectedCallbackCount int\n\t}{\n\t\t{\n\t\t\tname:  \"successful completion\",\n\t\t\tcount: 5,\n\t\t\tcallback: func(i int) (int, error) {\n\t\t\t\treturn i * i, nil\n\t\t\t},\n\t\t\twantResult:            []int{0, 1, 4, 9, 16},\n\t\t\twantErr:               false,\n\t\t\texpectedCallbackCount: 5,\n\t\t},\n\t\t{\n\t\t\tname:  \"error at first iteration\",\n\t\t\tcount: 5,\n\t\t\tcallback: func(i int) (int, error) {\n\t\t\t\tif i == 0 {\n\t\t\t\t\treturn 0, testErr\n\t\t\t\t}\n\t\t\t\treturn i * i, nil\n\t\t\t},\n\t\t\twantResult:            nil,\n\t\t\twantErr:               true,\n\t\t\texpectedCallbackCount: 1,\n\t\t},\n\t\t{\n\t\t\tname:  \"error at third iteration\",\n\t\t\tcount: 5,\n\t\t\tcallback: func(i int) (int, error) {\n\t\t\t\tif i == 2 {\n\t\t\t\t\treturn 0, testErr\n\t\t\t\t}\n\t\t\t\treturn i * i, nil\n\t\t\t},\n\t\t\twantResult:            nil,\n\t\t\twantErr:               true,\n\t\t\texpectedCallbackCount: 3,\n\t\t},\n\t\t{\n\t\t\tname:  \"error at last iteration\",\n\t\t\tcount: 5,\n\t\t\tcallback: func(i int) (int, error) {\n\t\t\t\tif i == 4 {\n\t\t\t\t\treturn 0, testErr\n\t\t\t\t}\n\t\t\t\treturn i * i, nil\n\t\t\t},\n\t\t\twantResult:            nil,\n\t\t\twantErr:               true,\n\t\t\texpectedCallbackCount: 5,\n\t\t},\n\t\t{\n\t\t\tname:  \"zero count - empty result\",\n\t\t\tcount: 0,\n\t\t\tcallback: func(i int) (int, error) {\n\t\t\t\treturn i * i, nil\n\t\t\t},\n\t\t\twantResult:            []int{},\n\t\t\twantErr:               false,\n\t\t\texpectedCallbackCount: 0,\n\t\t},\n\t\t{\n\t\t\tname:  \"single item success\",\n\t\t\tcount: 1,\n\t\t\tcallback: func(i int) (int, error) {\n\t\t\t\treturn 42, nil\n\t\t\t},\n\t\t\twantResult:            []int{42},\n\t\t\twantErr:               false,\n\t\t\texpectedCallbackCount: 1,\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\ttt := tt\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\n\t\t\t// Track callback count to verify early return\n\t\t\tcallbackCount := 0\n\t\t\twrappedCallback := func(i int) (int, error) {\n\t\t\t\tcallbackCount++\n\t\t\t\treturn tt.callback(i)\n\t\t\t}\n\n\t\t\tresult, err := RepeatByErr(tt.count, wrappedCallback)\n\n\t\t\tif tt.wantErr {\n\t\t\t\tis.ErrorIs(err, testErr)\n\t\t\t\tis.Nil(result)\n\t\t\t} else {\n\t\t\t\tis.NoError(err)\n\t\t\t\tis.Equal(tt.wantResult, result)\n\t\t\t}\n\n\t\t\t// Verify callback count matches expected (tests early return)\n\t\t\tis.Equal(tt.expectedCallbackCount, callbackCount, \"callback count should match expected\")\n\t\t})\n\t}\n}\n\nfunc TestKeyBy(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := KeyBy([]string{\"a\", \"aa\", \"aaa\"}, func(str string) int {\n\t\treturn len(str)\n\t})\n\n\tis.Equal(map[int]string{1: \"a\", 2: \"aa\", 3: \"aaa\"}, result1)\n}\n\nfunc TestKeyByErr(t *testing.T) {\n\tt.Parallel()\n\n\ttests := []struct {\n\t\tname                  string\n\t\tinput                 []string\n\t\titeratee              func(item string) (int, error)\n\t\twantResult            map[int]string\n\t\twantErr               bool\n\t\terrMsg                string\n\t\texpectedCallbackCount int\n\t}{\n\t\t{\n\t\t\tname:                  \"empty slice\",\n\t\t\tinput:                 []string{},\n\t\t\titeratee:              func(s string) (int, error) { return len(s), nil },\n\t\t\twantResult:            map[int]string{},\n\t\t\twantErr:               false,\n\t\t\texpectedCallbackCount: 0,\n\t\t},\n\t\t{\n\t\t\tname:                  \"success case\",\n\t\t\tinput:                 []string{\"a\", \"aa\", \"aaa\"},\n\t\t\titeratee:              func(s string) (int, error) { return len(s), nil },\n\t\t\twantResult:            map[int]string{1: \"a\", 2: \"aa\", 3: \"aaa\"},\n\t\t\twantErr:               false,\n\t\t\texpectedCallbackCount: 3,\n\t\t},\n\t\t{\n\t\t\tname:  \"error stops iteration - first item\",\n\t\t\tinput: []string{\"a\", \"aa\", \"aaa\"},\n\t\t\titeratee: func(s string) (int, error) {\n\t\t\t\treturn 0, fmt.Errorf(\"error on %s\", s)\n\t\t\t},\n\t\t\twantResult:            nil,\n\t\t\twantErr:               true,\n\t\t\terrMsg:                \"error on a\",\n\t\t\texpectedCallbackCount: 1,\n\t\t},\n\t\t{\n\t\t\tname:  \"error stops iteration - middle item\",\n\t\t\tinput: []string{\"a\", \"aa\", \"aaa\"},\n\t\t\titeratee: func(s string) (int, error) {\n\t\t\t\tif s == \"aa\" {\n\t\t\t\t\treturn 0, errors.New(\"middle error\")\n\t\t\t\t}\n\t\t\t\treturn len(s), nil\n\t\t\t},\n\t\t\twantResult:            nil,\n\t\t\twantErr:               true,\n\t\t\terrMsg:                \"middle error\",\n\t\t\texpectedCallbackCount: 2,\n\t\t},\n\t\t{\n\t\t\tname:  \"error stops iteration - last item\",\n\t\t\tinput: []string{\"a\", \"aa\", \"aaa\"},\n\t\t\titeratee: func(s string) (int, error) {\n\t\t\t\tif s == \"aaa\" {\n\t\t\t\t\treturn 0, errors.New(\"last error\")\n\t\t\t\t}\n\t\t\t\treturn len(s), nil\n\t\t\t},\n\t\t\twantResult:            nil,\n\t\t\twantErr:               true,\n\t\t\terrMsg:                \"last error\",\n\t\t\texpectedCallbackCount: 3,\n\t\t},\n\t\t{\n\t\t\tname:                  \"duplicate keys\",\n\t\t\tinput:                 []string{\"a\", \"b\", \"c\"},\n\t\t\titeratee:              func(s string) (int, error) { return 1, nil },\n\t\t\twantResult:            map[int]string{1: \"c\"},\n\t\t\twantErr:               false,\n\t\t\texpectedCallbackCount: 3,\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\ttt := tt\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\n\t\t\tcallbackCount := 0\n\t\t\twrappedIteratee := func(s string) (int, error) {\n\t\t\t\tcallbackCount++\n\t\t\t\treturn tt.iteratee(s)\n\t\t\t}\n\n\t\t\tresult, err := KeyByErr(tt.input, wrappedIteratee)\n\n\t\t\tif tt.wantErr {\n\t\t\t\tassert.Error(t, err)\n\t\t\t\tif tt.errMsg != \"\" {\n\t\t\t\t\tassert.Equal(t, tt.errMsg, err.Error())\n\t\t\t\t}\n\t\t\t\tassert.Nil(t, result)\n\t\t\t} else {\n\t\t\t\tassert.NoError(t, err)\n\t\t\t\tassert.Equal(t, tt.wantResult, result)\n\t\t\t}\n\n\t\t\tassert.Equal(t, tt.expectedCallbackCount, callbackCount, \"callback count mismatch\")\n\t\t})\n\t}\n}\n\nfunc TestAssociate(t *testing.T) {\n\tt.Parallel()\n\n\ttype foo struct {\n\t\tbaz string\n\t\tbar int\n\t}\n\ttransform := func(f *foo) (string, int) {\n\t\treturn f.baz, f.bar\n\t}\n\ttestCases := []struct {\n\t\tin   []*foo\n\t\twant map[string]int\n\t}{\n\t\t{\n\t\t\tin:   []*foo{{baz: \"apple\", bar: 1}},\n\t\t\twant: map[string]int{\"apple\": 1},\n\t\t},\n\t\t{\n\t\t\tin:   []*foo{{baz: \"apple\", bar: 1}, {baz: \"banana\", bar: 2}},\n\t\t\twant: map[string]int{\"apple\": 1, \"banana\": 2},\n\t\t},\n\t\t{\n\t\t\tin:   []*foo{{baz: \"apple\", bar: 1}, {baz: \"apple\", bar: 2}},\n\t\t\twant: map[string]int{\"apple\": 2},\n\t\t},\n\t}\n\tfor i, tc := range testCases {\n\t\ttc := tc\n\t\tt.Run(fmt.Sprintf(\"test_%d\", i), func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\tassert.Equal(t, tc.want, Associate(tc.in, transform))\n\t\t})\n\t}\n}\n\nfunc TestAssociateI(t *testing.T) {\n\tt.Parallel()\n\n\ttransform := func(s string, i int) (int, string) {\n\t\treturn i % 2, s\n\t}\n\ttestCases := []struct {\n\t\tin   []string\n\t\twant map[int]string\n\t}{\n\t\t{\n\t\t\tin:   []string{\"zero\"},\n\t\t\twant: map[int]string{0: \"zero\"},\n\t\t},\n\t\t{\n\t\t\tin:   []string{\"zero\", \"one\"},\n\t\t\twant: map[int]string{0: \"zero\", 1: \"one\"},\n\t\t},\n\t\t{\n\t\t\tin:   []string{\"two\", \"one\", \"zero\"},\n\t\t\twant: map[int]string{0: \"zero\", 1: \"one\"},\n\t\t},\n\t}\n\tfor i, tc := range testCases {\n\t\ttc := tc\n\t\tt.Run(fmt.Sprintf(\"test_%d\", i), func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\tassert.Equal(t, tc.want, AssociateI(tc.in, transform))\n\t\t})\n\t}\n}\n\nfunc TestSliceToMap(t *testing.T) {\n\tt.Parallel()\n\n\ttype foo struct {\n\t\tbaz string\n\t\tbar int\n\t}\n\ttransform := func(f *foo) (string, int) {\n\t\treturn f.baz, f.bar\n\t}\n\ttestCases := []struct {\n\t\tin   []*foo\n\t\twant map[string]int\n\t}{\n\t\t{\n\t\t\tin:   []*foo{{baz: \"apple\", bar: 1}},\n\t\t\twant: map[string]int{\"apple\": 1},\n\t\t},\n\t\t{\n\t\t\tin:   []*foo{{baz: \"apple\", bar: 1}, {baz: \"banana\", bar: 2}},\n\t\t\twant: map[string]int{\"apple\": 1, \"banana\": 2},\n\t\t},\n\t\t{\n\t\t\tin:   []*foo{{baz: \"apple\", bar: 1}, {baz: \"apple\", bar: 2}},\n\t\t\twant: map[string]int{\"apple\": 2},\n\t\t},\n\t}\n\tfor i, tc := range testCases {\n\t\ttc := tc\n\t\tt.Run(fmt.Sprintf(\"test_%d\", i), func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\tassert.Equal(t, tc.want, SliceToMap(tc.in, transform))\n\t\t})\n\t}\n}\n\nfunc TestSliceToMapI(t *testing.T) {\n\tt.Parallel()\n\n\ttransform := func(s string, i int) (int, string) {\n\t\treturn i % 2, s\n\t}\n\ttestCases := []struct {\n\t\tin   []string\n\t\twant map[int]string\n\t}{\n\t\t{\n\t\t\tin:   []string{\"zero\"},\n\t\t\twant: map[int]string{0: \"zero\"},\n\t\t},\n\t\t{\n\t\t\tin:   []string{\"zero\", \"one\"},\n\t\t\twant: map[int]string{0: \"zero\", 1: \"one\"},\n\t\t},\n\t\t{\n\t\t\tin:   []string{\"two\", \"one\", \"zero\"},\n\t\t\twant: map[int]string{0: \"zero\", 1: \"one\"},\n\t\t},\n\t}\n\tfor i, tc := range testCases {\n\t\ttc := tc\n\t\tt.Run(fmt.Sprintf(\"test_%d\", i), func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\tassert.Equal(t, tc.want, SliceToMapI(tc.in, transform))\n\t\t})\n\t}\n}\n\nfunc TestFilterSliceToMap(t *testing.T) {\n\tt.Parallel()\n\n\ttype foo struct {\n\t\tbaz string\n\t\tbar int\n\t}\n\ttransform := func(f *foo) (string, int, bool) {\n\t\treturn f.baz, f.bar, f.bar > 1\n\t}\n\ttestCases := []struct {\n\t\tin   []*foo\n\t\twant map[string]int\n\t}{\n\t\t{\n\t\t\tin:   []*foo{{baz: \"apple\", bar: 1}},\n\t\t\twant: map[string]int{},\n\t\t},\n\t\t{\n\t\t\tin:   []*foo{{baz: \"apple\", bar: 1}, {baz: \"banana\", bar: 2}},\n\t\t\twant: map[string]int{\"banana\": 2},\n\t\t},\n\t\t{\n\t\t\tin:   []*foo{{baz: \"apple\", bar: 1}, {baz: \"apple\", bar: 2}},\n\t\t\twant: map[string]int{\"apple\": 2},\n\t\t},\n\t}\n\tfor i, tc := range testCases {\n\t\ttc := tc\n\t\tt.Run(fmt.Sprintf(\"test_%d\", i), func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\tassert.Equal(t, tc.want, FilterSliceToMap(tc.in, transform))\n\t\t})\n\t}\n}\n\nfunc TestFilterSliceToMapI(t *testing.T) {\n\tt.Parallel()\n\n\ttransform := func(s string, i int) (int, string, bool) {\n\t\treturn i % 5, s, i%2 == 0\n\t}\n\ttestCases := []struct {\n\t\tin   []string\n\t\twant map[int]string\n\t}{\n\t\t{\n\t\t\tin:   []string{\"zero\"},\n\t\t\twant: map[int]string{0: \"zero\"},\n\t\t},\n\t\t{\n\t\t\tin:   []string{\"zero\", \"one\", \"two\", \"three\", \"four\"},\n\t\t\twant: map[int]string{0: \"zero\", 2: \"two\", 4: \"four\"},\n\t\t},\n\t\t{\n\t\t\tin:   []string{\"zero\", \"one\", \"two\", \"three\", \"four\", \"five\", \"six\", \"seven\", \"eight\", \"nine\", \"ten\"},\n\t\t\twant: map[int]string{0: \"ten\", 1: \"six\", 2: \"two\", 3: \"eight\", 4: \"four\"},\n\t\t},\n\t}\n\tfor i, tc := range testCases {\n\t\ttc := tc\n\t\tt.Run(fmt.Sprintf(\"test_%d\", i), func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\tassert.Equal(t, tc.want, FilterSliceToMapI(tc.in, transform))\n\t\t})\n\t}\n}\n\nfunc TestKeyify(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := Keyify([]int{1, 2, 3, 4})\n\tresult2 := Keyify([]int{1, 1, 1, 2})\n\tresult3 := Keyify([]int{})\n\tis.Equal(map[int]struct{}{1: {}, 2: {}, 3: {}, 4: {}}, result1)\n\tis.Equal(map[int]struct{}{1: {}, 2: {}}, result2)\n\tis.Empty(result3)\n}\n\nfunc TestDrop(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tis.Equal([]int{0, 1, 2, 3, 4}, Drop([]int{0, 1, 2, 3, 4}, 0))\n\tis.Equal([]int{1, 2, 3, 4}, Drop([]int{0, 1, 2, 3, 4}, 1))\n\tis.Equal([]int{2, 3, 4}, Drop([]int{0, 1, 2, 3, 4}, 2))\n\tis.Equal([]int{3, 4}, Drop([]int{0, 1, 2, 3, 4}, 3))\n\tis.Equal([]int{4}, Drop([]int{0, 1, 2, 3, 4}, 4))\n\tis.Empty(Drop([]int{0, 1, 2, 3, 4}, 5))\n\tis.Empty(Drop([]int{0, 1, 2, 3, 4}, 6))\n\n\tis.PanicsWithValue(\"lo.Drop: n must not be negative\", func() {\n\t\tDrop([]int{0, 1, 2, 3, 4}, -1)\n\t})\n\n\ttype myStrings []string\n\tallStrings := myStrings{\"\", \"foo\", \"bar\"}\n\tnonempty := Drop(allStrings, 2)\n\tis.IsType(nonempty, allStrings, \"type preserved\")\n}\n\nfunc TestDropRight(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tis.Equal([]int{0, 1, 2, 3, 4}, DropRight([]int{0, 1, 2, 3, 4}, 0))\n\tis.Equal([]int{0, 1, 2, 3}, DropRight([]int{0, 1, 2, 3, 4}, 1))\n\tis.Equal([]int{0, 1, 2}, DropRight([]int{0, 1, 2, 3, 4}, 2))\n\tis.Equal([]int{0, 1}, DropRight([]int{0, 1, 2, 3, 4}, 3))\n\tis.Equal([]int{0}, DropRight([]int{0, 1, 2, 3, 4}, 4))\n\tis.Empty(DropRight([]int{0, 1, 2, 3, 4}, 5))\n\tis.Empty(DropRight([]int{0, 1, 2, 3, 4}, 6))\n\n\tis.PanicsWithValue(\"lo.DropRight: n must not be negative\", func() {\n\t\tDropRight([]int{0, 1, 2, 3, 4}, -1)\n\t})\n\n\ttype myStrings []string\n\tallStrings := myStrings{\"\", \"foo\", \"bar\"}\n\tnonempty := DropRight(allStrings, 2)\n\tis.IsType(nonempty, allStrings, \"type preserved\")\n}\n\nfunc TestDropWhile(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tis.Equal([]int{4, 5, 6}, DropWhile([]int{0, 1, 2, 3, 4, 5, 6}, func(t int) bool {\n\t\treturn t != 4\n\t}))\n\n\tis.Empty(DropWhile([]int{0, 1, 2, 3, 4, 5, 6}, func(t int) bool {\n\t\treturn true\n\t}))\n\n\tis.Equal([]int{0, 1, 2, 3, 4, 5, 6}, DropWhile([]int{0, 1, 2, 3, 4, 5, 6}, func(t int) bool {\n\t\treturn t == 10\n\t}))\n\n\ttype myStrings []string\n\tallStrings := myStrings{\"\", \"foo\", \"bar\"}\n\tnonempty := DropWhile(allStrings, func(t string) bool {\n\t\treturn t != \"foo\"\n\t})\n\tis.IsType(nonempty, allStrings, \"type preserved\")\n}\n\nfunc TestDropRightWhile(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tis.Equal([]int{0, 1, 2, 3}, DropRightWhile([]int{0, 1, 2, 3, 4, 5, 6}, func(t int) bool {\n\t\treturn t != 3\n\t}))\n\n\tis.Equal([]int{0, 1}, DropRightWhile([]int{0, 1, 2, 3, 4, 5, 6}, func(t int) bool {\n\t\treturn t != 1\n\t}))\n\n\tis.Equal([]int{0, 1, 2, 3, 4, 5, 6}, DropRightWhile([]int{0, 1, 2, 3, 4, 5, 6}, func(t int) bool {\n\t\treturn t == 10\n\t}))\n\n\tis.Empty(DropRightWhile([]int{0, 1, 2, 3, 4, 5, 6}, func(t int) bool {\n\t\treturn t != 10\n\t}))\n\n\ttype myStrings []string\n\tallStrings := myStrings{\"\", \"foo\", \"bar\"}\n\tnonempty := DropRightWhile(allStrings, func(t string) bool {\n\t\treturn t != \"foo\"\n\t})\n\tis.IsType(nonempty, allStrings, \"type preserved\")\n}\n\nfunc TestTake(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tis.Equal([]int{0, 1, 2}, Take([]int{0, 1, 2, 3, 4}, 3))\n\tis.Equal([]int{0, 1}, Take([]int{0, 1, 2, 3, 4}, 2))\n\tis.Equal([]int{0}, Take([]int{0, 1, 2, 3, 4}, 1))\n\tis.Empty(Take([]int{0, 1, 2, 3, 4}, 0))\n\tis.Equal([]int{0, 1, 2, 3, 4}, Take([]int{0, 1, 2, 3, 4}, 5))\n\tis.Equal([]int{0, 1, 2, 3, 4}, Take([]int{0, 1, 2, 3, 4}, 10))\n\n\tis.PanicsWithValue(\"lo.Take: n must not be negative\", func() {\n\t\tTake([]int{0, 1, 2, 3, 4}, -1)\n\t})\n\n\ttype myStrings []string\n\tallStrings := myStrings{\"foo\", \"bar\", \"baz\"}\n\ttaken := Take(allStrings, 2)\n\tis.IsType(taken, allStrings, \"type preserved\")\n\tis.Equal(myStrings{\"foo\", \"bar\"}, taken)\n}\n\nfunc TestTakeWhile(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tis.Equal([]int{0, 1, 2, 3}, TakeWhile([]int{0, 1, 2, 3, 4, 5, 6}, func(t int) bool {\n\t\treturn t < 4\n\t}))\n\n\tis.Equal([]int{0, 1, 2, 3, 4, 5, 6}, TakeWhile([]int{0, 1, 2, 3, 4, 5, 6}, func(t int) bool {\n\t\treturn t < 10\n\t}))\n\n\tis.Empty(TakeWhile([]int{0, 1, 2, 3, 4, 5, 6}, func(t int) bool {\n\t\treturn t < 0\n\t}))\n\n\tis.Equal([]int{0, 1, 2}, TakeWhile([]int{0, 1, 2, 3, 4, 5, 6}, func(t int) bool {\n\t\treturn t != 3\n\t}))\n\n\ttype myStrings []string\n\tallStrings := myStrings{\"foo\", \"bar\", \"baz\", \"qux\"}\n\ttaken := TakeWhile(allStrings, func(t string) bool {\n\t\treturn t != \"baz\"\n\t})\n\tis.IsType(taken, allStrings, \"type preserved\")\n\tis.Equal(myStrings{\"foo\", \"bar\"}, taken)\n}\n\nfunc TestTakeFilter(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tis.Equal(\n\t\t[]int{2, 4}, TakeFilter([]int{1, 2, 3, 4, 5, 6}, 2, func(item, index int) bool {\n\t\t\treturn item%2 == 0\n\t\t}),\n\t)\n\n\tis.Equal([]int{2, 4, 6}, TakeFilter([]int{1, 2, 3, 4, 5, 6}, 10, func(item, index int) bool {\n\t\treturn item%2 == 0\n\t}))\n\n\tis.Empty(TakeFilter([]int{1, 2, 3, 4, 5, 6}, 0, func(item, index int) bool {\n\t\treturn item%2 == 0\n\t}))\n\n\tis.Empty(TakeFilter([]int{1, 3, 5}, 2, func(item, index int) bool {\n\t\treturn item%2 == 0\n\t}))\n\n\tis.Equal([]int{1}, TakeFilter([]int{1, 2, 3, 4, 5}, 1, func(item, index int) bool {\n\t\treturn item%2 != 0\n\t}))\n\n\tis.PanicsWithValue(\"lo.TakeFilter: n must not be negative\", func() {\n\t\tTakeFilter([]int{1, 2, 3}, -1, func(item, index int) bool { return true })\n\t})\n\n\ttype myStrings []string\n\tallStrings := myStrings{\"foo\", \"bar\", \"baz\", \"qux\"}\n\tfiltered := TakeFilter(allStrings, 2, func(item string, index int) bool {\n\t\treturn len(item) == 3\n\t})\n\tis.IsType(filtered, allStrings, \"type preserved\")\n\tis.Equal(myStrings{\"foo\", \"bar\"}, filtered)\n}\n\nfunc TestDropByIndex(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tis.Equal([]int{1, 2, 3, 4}, DropByIndex([]int{0, 1, 2, 3, 4}, 0))\n\tis.Equal([]int{3, 4}, DropByIndex([]int{0, 1, 2, 3, 4}, 0, 1, 2))\n\tis.Equal([]int{0, 4}, DropByIndex([]int{0, 1, 2, 3, 4}, -4, -2, -3))\n\tis.Equal([]int{0, 2, 3, 4}, DropByIndex([]int{0, 1, 2, 3, 4}, -4, -4))\n\tis.Equal([]int{2, 4}, DropByIndex([]int{0, 1, 2, 3, 4}, 3, 1, 0))\n\tis.Equal([]int{0, 1, 3, 4}, DropByIndex([]int{0, 1, 2, 3, 4}, 2))\n\tis.Equal([]int{0, 1, 2, 3}, DropByIndex([]int{0, 1, 2, 3, 4}, 4))\n\tis.Equal([]int{0, 1, 2, 3, 4}, DropByIndex([]int{0, 1, 2, 3, 4}))\n\tis.Equal([]int{0, 1, 2, 3, 4}, DropByIndex([]int{0, 1, 2, 3, 4}, 5))\n\tis.Equal([]int{0, 1, 2, 3, 4}, DropByIndex([]int{0, 1, 2, 3, 4}, 100))\n\tis.Equal([]int{0, 1, 2, 3, 4}, DropByIndex([]int{0, 1, 2, 3, 4}, -100))\n\tis.Equal([]int{0, 1, 2, 3}, DropByIndex([]int{0, 1, 2, 3, 4}, -1))\n\tis.Equal([]int{0, 1, 2, 3}, DropByIndex([]int{0, 1, 2, 3, 4}, -1, 4))\n\tis.Equal([]int{0, 1, 2, 3}, DropByIndex([]int{0, 1, 2, 3, 4}, -100, 4))\n\tis.Empty(DropByIndex([]int{}, 0, 1))\n\tis.Empty(DropByIndex([]int{42}, 0, 1))\n\tis.Empty(DropByIndex([]int{42}, 1, 0))\n\tis.Empty(DropByIndex([]int{}, 1))\n\tis.Empty(DropByIndex([]int{1}, 0))\n\n\ttype myStrings []string\n\tallStrings := myStrings{\"\", \"foo\", \"bar\"}\n\tnonempty := DropByIndex(allStrings, 0)\n\tis.IsType(nonempty, allStrings, \"type preserved\")\n}\n\nfunc TestReject(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tr1 := Reject([]int{1, 2, 3, 4}, func(x, _ int) bool {\n\t\treturn x%2 == 0\n\t})\n\n\tis.Equal([]int{1, 3}, r1)\n\n\tr2 := Reject([]string{\"Smith\", \"foo\", \"Domin\", \"bar\", \"Olivia\"}, func(x string, _ int) bool {\n\t\treturn len(x) > 3\n\t})\n\n\tis.Equal([]string{\"foo\", \"bar\"}, r2)\n\n\ttype myStrings []string\n\tallStrings := myStrings{\"\", \"foo\", \"bar\"}\n\tnonempty := Reject(allStrings, func(x string, _ int) bool {\n\t\treturn len(x) > 0\n\t})\n\tis.IsType(nonempty, allStrings, \"type preserved\")\n}\n\nfunc TestRejectErr(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\ttests := []struct {\n\t\tname      string\n\t\tinput     []int\n\t\tpredicate func(item, index int) (bool, error)\n\t\twant      []int\n\t\twantErr   string\n\t\tcallbacks int // Number of predicates called before error/finish\n\t}{\n\t\t{\n\t\t\tname:  \"reject even numbers\",\n\t\t\tinput: []int{1, 2, 3, 4},\n\t\t\tpredicate: func(x, _ int) (bool, error) {\n\t\t\t\treturn x%2 == 0, nil\n\t\t\t},\n\t\t\twant:      []int{1, 3},\n\t\t\tcallbacks: 4,\n\t\t},\n\t\t{\n\t\t\tname:  \"empty slice\",\n\t\t\tinput: []int{},\n\t\t\tpredicate: func(x, _ int) (bool, error) {\n\t\t\t\treturn true, nil\n\t\t\t},\n\t\t\twant:      []int{},\n\t\t\tcallbacks: 0,\n\t\t},\n\t\t{\n\t\t\tname:  \"reject all out\",\n\t\t\tinput: []int{1, 2, 3, 4},\n\t\t\tpredicate: func(x, _ int) (bool, error) {\n\t\t\t\treturn false, nil\n\t\t\t},\n\t\t\twant:      []int{1, 2, 3, 4},\n\t\t\tcallbacks: 4,\n\t\t},\n\t\t{\n\t\t\tname:  \"reject all in\",\n\t\t\tinput: []int{1, 2, 3, 4},\n\t\t\tpredicate: func(x, _ int) (bool, error) {\n\t\t\t\treturn true, nil\n\t\t\t},\n\t\t\twant:      []int{},\n\t\t\tcallbacks: 4,\n\t\t},\n\t\t{\n\t\t\tname:  \"error on specific index\",\n\t\t\tinput: []int{1, 2, 3, 4},\n\t\t\tpredicate: func(x, _ int) (bool, error) {\n\t\t\t\tif x == 3 {\n\t\t\t\t\treturn false, errors.New(\"number 3 is not allowed\")\n\t\t\t\t}\n\t\t\t\treturn x%2 == 0, nil\n\t\t\t},\n\t\t\tcallbacks: 3,\n\t\t\twantErr:   \"number 3 is not allowed\",\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\ttt := tt\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\n\t\t\tvar callbacks int\n\t\t\twrappedPredicate := func(item, index int) (bool, error) {\n\t\t\t\tcallbacks++\n\t\t\t\treturn tt.predicate(item, index)\n\t\t\t}\n\n\t\t\tgot, err := RejectErr(tt.input, wrappedPredicate)\n\n\t\t\tif tt.wantErr != \"\" {\n\t\t\t\tis.Error(err)\n\t\t\t\tis.Equal(tt.wantErr, err.Error())\n\t\t\t\tis.Nil(got)\n\t\t\t\tis.Equal(tt.callbacks, callbacks, \"callback count should match expected early return\")\n\t\t\t} else {\n\t\t\t\tis.NoError(err)\n\t\t\t\tis.Equal(tt.want, got)\n\t\t\t\tis.Equal(tt.callbacks, callbacks)\n\t\t\t}\n\t\t})\n\t}\n\n\t// Test type preservation\n\ttype myStrings []string\n\tallStrings := myStrings{\"\", \"foo\", \"bar\"}\n\tnonempty, err := RejectErr(allStrings, func(x string, _ int) (bool, error) {\n\t\treturn len(x) > 0, nil\n\t})\n\tis.NoError(err)\n\tis.IsType(nonempty, allStrings, \"type preserved\")\n\tis.Equal(myStrings{\"\"}, nonempty)\n}\n\nfunc TestRejectMap(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tr1 := RejectMap([]int64{1, 2, 3, 4}, func(x int64, _ int) (string, bool) {\n\t\tif x%2 == 0 {\n\t\t\treturn strconv.FormatInt(x, 10), false\n\t\t}\n\t\treturn \"\", true\n\t})\n\tr2 := RejectMap([]string{\"cpu\", \"gpu\", \"mouse\", \"keyboard\"}, func(x string, _ int) (string, bool) {\n\t\tif strings.HasSuffix(x, \"pu\") {\n\t\t\treturn \"xpu\", false\n\t\t}\n\t\treturn \"\", true\n\t})\n\n\tis.Equal([]string{\"2\", \"4\"}, r1)\n\tis.Equal([]string{\"xpu\", \"xpu\"}, r2)\n}\n\nfunc TestFilterReject(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tleft1, right1 := FilterReject([]int{1, 2, 3, 4}, func(x, _ int) bool {\n\t\treturn x%2 == 0\n\t})\n\n\tis.Equal([]int{2, 4}, left1)\n\tis.Equal([]int{1, 3}, right1)\n\n\tleft2, right2 := FilterReject([]string{\"Smith\", \"foo\", \"Domin\", \"bar\", \"Olivia\"}, func(x string, _ int) bool {\n\t\treturn len(x) > 3\n\t})\n\n\tis.Equal([]string{\"Smith\", \"Domin\", \"Olivia\"}, left2)\n\tis.Equal([]string{\"foo\", \"bar\"}, right2)\n\n\ttype myStrings []string\n\tallStrings := myStrings{\"\", \"foo\", \"bar\"}\n\ta, b := FilterReject(allStrings, func(x string, _ int) bool {\n\t\treturn len(x) > 0\n\t})\n\tis.IsType(a, allStrings, \"type preserved\")\n\tis.IsType(b, allStrings, \"type preserved\")\n}\n\nfunc TestCount(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tcount1 := Count([]int{1, 2, 1}, 1)\n\tcount2 := Count([]int{1, 2, 1}, 3)\n\tcount3 := Count([]int{}, 1)\n\n\tis.Equal(2, count1)\n\tis.Zero(count2)\n\tis.Zero(count3)\n}\n\nfunc TestCountBy(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tcount1 := CountBy([]int{1, 2, 1}, func(i int) bool {\n\t\treturn i < 2\n\t})\n\n\tcount2 := CountBy([]int{1, 2, 1}, func(i int) bool {\n\t\treturn i > 2\n\t})\n\n\tcount3 := CountBy([]int{}, func(i int) bool {\n\t\treturn i <= 2\n\t})\n\n\tis.Equal(2, count1)\n\tis.Zero(count2)\n\tis.Zero(count3)\n}\n\nfunc TestCountByErr(t *testing.T) {\n\tt.Parallel()\n\n\ttests := []struct {\n\t\tname          string\n\t\tinput         []int\n\t\tpredicate     func(int) (bool, error)\n\t\twant          int\n\t\twantErr       string\n\t\twantCallCount int\n\t}{\n\t\t{\n\t\t\tname:  \"count elements less than 2\",\n\t\t\tinput: []int{1, 2, 1},\n\t\t\tpredicate: func(i int) (bool, error) {\n\t\t\t\treturn i < 2, nil\n\t\t\t},\n\t\t\twant:          2,\n\t\t\twantErr:       \"\",\n\t\t\twantCallCount: 3,\n\t\t},\n\t\t{\n\t\t\tname:  \"count elements greater than 2\",\n\t\t\tinput: []int{1, 2, 1},\n\t\t\tpredicate: func(i int) (bool, error) {\n\t\t\t\treturn i > 2, nil\n\t\t\t},\n\t\t\twant:          0,\n\t\t\twantErr:       \"\",\n\t\t\twantCallCount: 3,\n\t\t},\n\t\t{\n\t\t\tname:  \"empty slice\",\n\t\t\tinput: []int{},\n\t\t\tpredicate: func(i int) (bool, error) {\n\t\t\t\treturn i <= 2, nil\n\t\t\t},\n\t\t\twant:          0,\n\t\t\twantErr:       \"\",\n\t\t\twantCallCount: 0,\n\t\t},\n\t\t{\n\t\t\tname:  \"error on third element\",\n\t\t\tinput: []int{1, 2, 3, 4, 5},\n\t\t\tpredicate: func(i int) (bool, error) {\n\t\t\t\tif i == 3 {\n\t\t\t\t\treturn false, fmt.Errorf(\"error at %d\", i)\n\t\t\t\t}\n\t\t\t\treturn i < 3, nil\n\t\t\t},\n\t\t\twant:          0,\n\t\t\twantErr:       \"error at 3\",\n\t\t\twantCallCount: 3, // stops early at error\n\t\t},\n\t\t{\n\t\t\tname:  \"error on first element\",\n\t\t\tinput: []int{1, 2, 3},\n\t\t\tpredicate: func(i int) (bool, error) {\n\t\t\t\treturn false, errors.New(\"first element error\")\n\t\t\t},\n\t\t\twant:          0,\n\t\t\twantErr:       \"first element error\",\n\t\t\twantCallCount: 1,\n\t\t},\n\t\t{\n\t\t\tname:  \"all match\",\n\t\t\tinput: []int{1, 2, 3},\n\t\t\tpredicate: func(i int) (bool, error) {\n\t\t\t\treturn i > 0, nil\n\t\t\t},\n\t\t\twant:          3,\n\t\t\twantErr:       \"\",\n\t\t\twantCallCount: 3,\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\ttt := tt // capture range variable\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\tis := assert.New(t)\n\n\t\t\tcallCount := 0\n\t\t\twrappedPredicate := func(i int) (bool, error) {\n\t\t\t\tcallCount++\n\t\t\t\treturn tt.predicate(i)\n\t\t\t}\n\n\t\t\tgot, err := CountByErr(tt.input, wrappedPredicate)\n\n\t\t\tif tt.wantErr != \"\" {\n\t\t\t\tis.Error(err)\n\t\t\t\tis.Equal(tt.wantErr, err.Error())\n\t\t\t\tis.Equal(tt.want, got)\n\t\t\t\tif tt.wantCallCount > 0 {\n\t\t\t\t\tis.Equal(tt.wantCallCount, callCount, \"should stop early on error\")\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tis.NoError(err)\n\t\t\t\tis.Equal(tt.want, got)\n\t\t\t\tis.Equal(tt.wantCallCount, callCount)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestCountValues(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tis.Empty(CountValues([]int{}))\n\tis.Equal(map[int]int{1: 1, 2: 1}, CountValues([]int{1, 2}))\n\tis.Equal(map[int]int{1: 1, 2: 2}, CountValues([]int{1, 2, 2}))\n\tis.Equal(map[string]int{\"\": 1, \"foo\": 1, \"bar\": 1}, CountValues([]string{\"foo\", \"bar\", \"\"}))\n\tis.Equal(map[string]int{\"foo\": 1, \"bar\": 2}, CountValues([]string{\"foo\", \"bar\", \"bar\"}))\n}\n\nfunc TestCountValuesBy(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\toddEven := func(v int) bool {\n\t\treturn v%2 == 0\n\t}\n\tlength := func(v string) int {\n\t\treturn len(v)\n\t}\n\n\tresult1 := CountValuesBy([]int{}, oddEven)\n\tresult2 := CountValuesBy([]int{1, 2}, oddEven)\n\tresult3 := CountValuesBy([]int{1, 2, 2}, oddEven)\n\tresult4 := CountValuesBy([]string{\"foo\", \"bar\", \"\"}, length)\n\tresult5 := CountValuesBy([]string{\"foo\", \"bar\", \"bar\"}, length)\n\n\tis.Empty(result1)\n\tis.Equal(map[bool]int{true: 1, false: 1}, result2)\n\tis.Equal(map[bool]int{true: 2, false: 1}, result3)\n\tis.Equal(map[int]int{0: 1, 3: 2}, result4)\n\tis.Equal(map[int]int{3: 3}, result5)\n}\n\nfunc TestSubset(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tin := []int{0, 1, 2, 3, 4}\n\n\tout1 := Subset(in, 0, 0)\n\tout2 := Subset(in, 10, 2)\n\tout3 := Subset(in, -10, 2)\n\tout4 := Subset(in, 0, 10)\n\tout5 := Subset(in, 0, 2)\n\tout6 := Subset(in, 2, 2)\n\tout7 := Subset(in, 2, 5)\n\tout8 := Subset(in, 2, 3)\n\tout9 := Subset(in, 2, 4)\n\tout10 := Subset(in, -2, 4)\n\tout11 := Subset(in, -4, 1)\n\tout12 := Subset(in, -4, math.MaxUint)\n\n\tis.Empty(out1)\n\tis.Empty(out2)\n\tis.Equal([]int{0, 1}, out3)\n\tis.Equal([]int{0, 1, 2, 3, 4}, out4)\n\tis.Equal([]int{0, 1}, out5)\n\tis.Equal([]int{2, 3}, out6)\n\tis.Equal([]int{2, 3, 4}, out7)\n\tis.Equal([]int{2, 3, 4}, out8)\n\tis.Equal([]int{2, 3, 4}, out9)\n\tis.Equal([]int{3, 4}, out10)\n\tis.Equal([]int{1}, out11)\n\tis.Equal([]int{1, 2, 3, 4}, out12)\n\n\ttype myStrings []string\n\tallStrings := myStrings{\"\", \"foo\", \"bar\"}\n\tnonempty := Subset(allStrings, 0, 2)\n\tis.IsType(nonempty, allStrings, \"type preserved\")\n}\n\nfunc TestSlice(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tin := []int{0, 1, 2, 3, 4}\n\n\tout1 := Slice(in, 0, 0)\n\tout2 := Slice(in, 0, 1)\n\tout3 := Slice(in, 0, 5)\n\tout4 := Slice(in, 0, 6)\n\tout5 := Slice(in, 1, 1)\n\tout6 := Slice(in, 1, 5)\n\tout7 := Slice(in, 1, 6)\n\tout8 := Slice(in, 4, 5)\n\tout9 := Slice(in, 5, 5)\n\tout10 := Slice(in, 6, 5)\n\tout11 := Slice(in, 6, 6)\n\tout12 := Slice(in, 1, 0)\n\tout13 := Slice(in, 5, 0)\n\tout14 := Slice(in, 6, 4)\n\tout15 := Slice(in, 6, 7)\n\tout16 := Slice(in, -10, 1)\n\tout17 := Slice(in, -1, 3)\n\tout18 := Slice(in, -10, 7)\n\tout19 := Slice(in, -10, -1)\n\n\tis.Empty(out1)\n\tis.Equal([]int{0}, out2)\n\tis.Equal([]int{0, 1, 2, 3, 4}, out3)\n\tis.Equal([]int{0, 1, 2, 3, 4}, out4)\n\tis.Empty(out5)\n\tis.Equal([]int{1, 2, 3, 4}, out6)\n\tis.Equal([]int{1, 2, 3, 4}, out7)\n\tis.Equal([]int{4}, out8)\n\tis.Empty(out9)\n\tis.Empty(out10)\n\tis.Empty(out11)\n\tis.Empty(out12)\n\tis.Empty(out13)\n\tis.Empty(out14)\n\tis.Empty(out15)\n\tis.Equal([]int{0}, out16)\n\tis.Equal([]int{0, 1, 2}, out17)\n\tis.Equal([]int{0, 1, 2, 3, 4}, out18)\n\tis.Empty(out19)\n\n\ttype myStrings []string\n\tallStrings := myStrings{\"\", \"foo\", \"bar\"}\n\tnonempty := Slice(allStrings, 0, 2)\n\tis.IsType(nonempty, allStrings, \"type preserved\")\n}\n\nfunc TestReplace(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tin := []int{0, 1, 0, 1, 2, 3, 0}\n\n\tout1 := Replace(in, 0, 42, 2)\n\tout2 := Replace(in, 0, 42, 1)\n\tout3 := Replace(in, 0, 42, 0)\n\tout4 := Replace(in, 0, 42, -1)\n\tout5 := Replace(in, 0, 42, -1)\n\tout6 := Replace(in, -1, 42, 2)\n\tout7 := Replace(in, -1, 42, 1)\n\tout8 := Replace(in, -1, 42, 0)\n\tout9 := Replace(in, -1, 42, -1)\n\tout10 := Replace(in, -1, 42, -1)\n\n\tis.Equal([]int{42, 1, 42, 1, 2, 3, 0}, out1)\n\tis.Equal([]int{42, 1, 0, 1, 2, 3, 0}, out2)\n\tis.Equal([]int{0, 1, 0, 1, 2, 3, 0}, out3)\n\tis.Equal([]int{42, 1, 42, 1, 2, 3, 42}, out4)\n\tis.Equal([]int{42, 1, 42, 1, 2, 3, 42}, out5)\n\tis.Equal([]int{0, 1, 0, 1, 2, 3, 0}, out6)\n\tis.Equal([]int{0, 1, 0, 1, 2, 3, 0}, out7)\n\tis.Equal([]int{0, 1, 0, 1, 2, 3, 0}, out8)\n\tis.Equal([]int{0, 1, 0, 1, 2, 3, 0}, out9)\n\tis.Equal([]int{0, 1, 0, 1, 2, 3, 0}, out10)\n\n\ttype myStrings []string\n\tallStrings := myStrings{\"\", \"foo\", \"bar\"}\n\tnonempty := Replace(allStrings, \"0\", \"2\", 1)\n\tis.IsType(nonempty, allStrings, \"type preserved\")\n}\n\nfunc TestReplaceAll(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tin := []int{0, 1, 0, 1, 2, 3, 0}\n\n\tout1 := ReplaceAll(in, 0, 42)\n\tout2 := ReplaceAll(in, -1, 42)\n\n\tis.Equal([]int{42, 1, 42, 1, 2, 3, 42}, out1)\n\tis.Equal([]int{0, 1, 0, 1, 2, 3, 0}, out2)\n\n\ttype myStrings []string\n\tallStrings := myStrings{\"\", \"foo\", \"bar\"}\n\tnonempty := ReplaceAll(allStrings, \"0\", \"2\")\n\tis.IsType(nonempty, allStrings, \"type preserved\")\n}\n\nfunc TestClone(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\t// Test with int slice\n\toriginal1 := []int{1, 2, 3, 4, 5}\n\tresult1 := Clone(original1)\n\tis.Equal([]int{1, 2, 3, 4, 5}, result1)\n\n\t// Verify it's a different slice by checking that modifying one doesn't affect the other\n\toriginal1[0] = 99\n\tis.Equal([]int{99, 2, 3, 4, 5}, original1)\n\tis.Equal([]int{1, 2, 3, 4, 5}, result1)\n\n\t// Test with string slice\n\toriginal2 := []string{\"a\", \"b\", \"c\"}\n\tresult2 := Clone(original2)\n\tis.Equal([]string{\"a\", \"b\", \"c\"}, result2)\n\n\t// Test with empty slice\n\toriginal3 := []int{}\n\tresult3 := Clone(original3)\n\tis.Equal([]int{}, result3)\n\tis.Empty(result3)\n\n\t// Test with nil slice\n\tvar original4 []int\n\tresult4 := Clone(original4)\n\tis.Nil(result4)\n\n\t// Verify shallow copy behavior - modifying clone doesn't affect original\n\toriginal5 := []int{1, 2, 3}\n\tresult5 := Clone(original5)\n\tresult5[0] = 99\n\tis.Equal([]int{1, 2, 3}, original5) // Original unchanged\n\tis.Equal([]int{99, 2, 3}, result5)  // Clone changed\n\n\ttype myStrings []string\n\toriginal6 := myStrings{\"\", \"foo\", \"bar\"}\n\tresult6 := Clone(original6)\n\tresult6[0] = \"baz\"\n\tis.Equal(myStrings{\"\", \"foo\", \"bar\"}, original6)  // Original unchanged\n\tis.Equal(myStrings{\"baz\", \"foo\", \"bar\"}, result6) // Clone changed\n}\n\nfunc TestCompact(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tr1 := Compact([]int{2, 0, 4, 0})\n\n\tis.Equal([]int{2, 4}, r1)\n\n\tr2 := Compact([]string{\"\", \"foo\", \"\", \"bar\", \"\"})\n\n\tis.Equal([]string{\"foo\", \"bar\"}, r2)\n\n\tr3 := Compact([]bool{true, false, true, false})\n\n\tis.Equal([]bool{true, true}, r3)\n\n\ttype foo struct {\n\t\tbar int\n\t\tbaz string\n\t}\n\n\t// slice of structs\n\t// If all fields of an element are zero values, Compact removes it.\n\n\tr4 := Compact([]foo{\n\t\t{bar: 1, baz: \"a\"}, // all fields are non-zero values\n\t\t{bar: 0, baz: \"\"},  // all fields are zero values\n\t\t{bar: 2, baz: \"\"},  // bar is non-zero\n\t})\n\n\tis.Equal([]foo{{bar: 1, baz: \"a\"}, {bar: 2, baz: \"\"}}, r4)\n\n\t// slice of pointers to structs\n\t// If an element is nil, Compact removes it.\n\n\te1, e2, e3 := foo{bar: 1, baz: \"a\"}, foo{bar: 0, baz: \"\"}, foo{bar: 2, baz: \"\"}\n\t// NOTE: e2 is a zero value of foo, but its pointer &e2 is not a zero value of *foo.\n\tr5 := Compact([]*foo{&e1, &e2, nil, &e3})\n\n\tis.Equal([]*foo{&e1, &e2, &e3}, r5)\n\n\ttype myStrings []string\n\tallStrings := myStrings{\"\", \"foo\", \"bar\"}\n\tnonempty := Compact(allStrings)\n\tis.IsType(nonempty, allStrings, \"type preserved\")\n}\n\nfunc TestIsSorted(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tis.True(IsSorted([]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}))\n\tis.True(IsSorted([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\", \"h\", \"i\", \"j\"}))\n\n\tis.False(IsSorted([]int{0, 1, 4, 3, 2, 5, 6, 7, 8, 9, 10}))\n\tis.False(IsSorted([]string{\"a\", \"b\", \"d\", \"c\", \"e\", \"f\", \"g\", \"h\", \"i\", \"j\"}))\n}\n\nfunc TestIsSortedBy(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tis.True(IsSortedBy([]string{\"a\", \"bb\", \"ccc\"}, func(s string) int {\n\t\treturn len(s)\n\t}))\n\n\tis.False(IsSortedBy([]string{\"aa\", \"b\", \"ccc\"}, func(s string) int {\n\t\treturn len(s)\n\t}))\n\n\tis.True(IsSortedBy([]string{\"1\", \"2\", \"3\", \"11\"}, func(s string) int {\n\t\tret, _ := strconv.Atoi(s)\n\t\treturn ret\n\t}))\n}\n\nfunc TestSplice(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tsample := []string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}\n\n\t// normal case\n\tresults := Splice(sample, 1, \"1\", \"2\")\n\tis.Equal([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, sample)\n\tis.Equal([]string{\"a\", \"1\", \"2\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, results)\n\n\t// check there is no side effect\n\tresults = Splice(sample, 1)\n\tresults[0] = \"b\"\n\tis.Equal([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, sample)\n\n\t// positive overflow\n\tresults = Splice(sample, 42, \"1\", \"2\")\n\tis.Equal([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, sample)\n\tis.Equal([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\", \"1\", \"2\"}, results)\n\n\t// negative overflow\n\tresults = Splice(sample, -42, \"1\", \"2\")\n\tis.Equal([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, sample)\n\tis.Equal([]string{\"1\", \"2\", \"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, results)\n\n\t// backward\n\tresults = Splice(sample, -2, \"1\", \"2\")\n\tis.Equal([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, sample)\n\tis.Equal([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"1\", \"2\", \"f\", \"g\"}, results)\n\n\tresults = Splice(sample, -7, \"1\", \"2\")\n\tis.Equal([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, sample)\n\tis.Equal([]string{\"1\", \"2\", \"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, results)\n\n\t// other\n\tis.Equal([]string{\"1\", \"2\"}, Splice([]string{}, 0, \"1\", \"2\"))\n\tis.Equal([]string{\"1\", \"2\"}, Splice([]string{}, 1, \"1\", \"2\"))\n\tis.Equal([]string{\"1\", \"2\"}, Splice([]string{}, -1, \"1\", \"2\"))\n\tis.Equal([]string{\"1\", \"2\", \"0\"}, Splice([]string{\"0\"}, 0, \"1\", \"2\"))\n\tis.Equal([]string{\"0\", \"1\", \"2\"}, Splice([]string{\"0\"}, 1, \"1\", \"2\"))\n\tis.Equal([]string{\"1\", \"2\", \"0\"}, Splice([]string{\"0\"}, -1, \"1\", \"2\"))\n\n\t// type preserved\n\ttype myStrings []string\n\tallStrings := myStrings{\"\", \"foo\", \"bar\"}\n\tnonempty := Splice(allStrings, 1, \"1\", \"2\")\n\tis.IsType(nonempty, allStrings, \"type preserved\")\n}\n\nfunc TestCutSuccess(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\t// case 1\n\tactualLeft, actualRight, result := Cut([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, []string{\"a\", \"b\"})\n\tis.True(result)\n\tis.Equal([]string{}, actualLeft)\n\tis.Equal([]string{\"c\", \"d\", \"e\", \"f\", \"g\"}, actualRight)\n\n\t// case 2\n\tactualLeft, actualRight, result = Cut([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, []string{\"f\", \"g\"})\n\tis.True(result)\n\tis.Equal([]string{\"a\", \"b\", \"c\", \"d\", \"e\"}, actualLeft)\n\tis.Equal([]string{}, actualRight)\n\n\t// case 3\n\tactualLeft, actualRight, result = Cut([]string{\"g\"}, []string{\"g\"})\n\tis.True(result)\n\tis.Equal([]string{}, actualLeft)\n\tis.Equal([]string{}, actualRight)\n\n\t// case 4\n\tactualLeft, actualRight, result = Cut([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, []string{\"b\", \"c\"})\n\tis.True(result)\n\tis.Equal([]string{\"a\"}, actualLeft)\n\tis.Equal([]string{\"d\", \"e\", \"f\", \"g\"}, actualRight)\n\n\t// case 5\n\tactualLeft, actualRight, result = Cut([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, []string{\"e\", \"f\"})\n\tis.True(result)\n\tis.Equal([]string{\"a\", \"b\", \"c\", \"d\"}, actualLeft)\n\tis.Equal([]string{\"g\"}, actualRight)\n\n\t// case 6\n\tactualLeft, actualRight, result = Cut([]string{\"a\", \"b\"}, []string{\"b\"})\n\tis.True(result)\n\tis.Equal([]string{\"a\"}, actualLeft)\n\tis.Equal([]string{}, actualRight)\n\n\t// case 7\n\tactualLeft, actualRight, result = Cut([]string{\"a\", \"b\"}, []string{\"a\"})\n\tis.True(result)\n\tis.Equal([]string{}, actualLeft)\n\tis.Equal([]string{\"b\"}, actualRight)\n}\n\nfunc TestCutFail(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\t// case 1\n\tactualLeft, actualRight, result := Cut([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, []string{\"z\"})\n\tis.False(result)\n\tis.Equal([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, actualLeft)\n\tis.Equal([]string{}, actualRight)\n\n\t// case 2\n\tactualLeft, actualRight, result = Cut([]string{}, []string{\"z\"})\n\tis.False(result)\n\tis.Equal([]string{}, actualLeft)\n\tis.Equal([]string{}, actualRight)\n\n\t// case 3\n\tactualLeft, actualRight, result = Cut([]string{\"a\"}, []string{\"z\"})\n\tis.False(result)\n\tis.Equal([]string{\"a\"}, actualLeft)\n\tis.Equal([]string{}, actualRight)\n}\n\ntype TestCutStruct struct {\n\tid   int\n\tdata string\n}\n\nfunc TestCutPrefix(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\t// case 1\n\tactualAfter, result := CutPrefix(\n\t\t[]TestCutStruct{{id: 1, data: \"a\"}, {id: 2, data: \"a\"}, {id: 2, data: \"b\"}},\n\t\t[]TestCutStruct{{id: 1, data: \"a\"}},\n\t)\n\tis.True(result)\n\tis.Equal([]TestCutStruct{{id: 2, data: \"a\"}, {id: 2, data: \"b\"}}, actualAfter)\n\n\t// case 2\n\tactualAfter, result = CutPrefix(\n\t\t[]TestCutStruct{{id: 1, data: \"a\"}, {id: 2, data: \"a\"}, {id: 2, data: \"b\"}},\n\t\t[]TestCutStruct{},\n\t)\n\tis.True(result)\n\tis.Equal([]TestCutStruct{{id: 1, data: \"a\"}, {id: 2, data: \"a\"}, {id: 2, data: \"b\"}}, actualAfter)\n\n\t// case 3\n\tactualAfter, result = CutPrefix(\n\t\t[]TestCutStruct{{id: 1, data: \"a\"}, {id: 2, data: \"a\"}, {id: 2, data: \"b\"}},\n\t\t[]TestCutStruct{{id: 2, data: \"b\"}},\n\t)\n\tis.False(result)\n\tis.Equal([]TestCutStruct{{id: 1, data: \"a\"}, {id: 2, data: \"a\"}, {id: 2, data: \"b\"}}, actualAfter)\n\n\t// case 4\n\tactualAfter, result = CutPrefix(\n\t\t[]TestCutStruct{},\n\t\t[]TestCutStruct{{id: 2, data: \"b\"}},\n\t)\n\tis.False(result)\n\tis.Equal([]TestCutStruct{}, actualAfter)\n\n\t// case 5\n\tactualAfterS, result := CutPrefix([]string{\"a\", \"a\", \"b\"}, []string{})\n\tis.True(result)\n\tis.Equal([]string{\"a\", \"a\", \"b\"}, actualAfterS)\n}\n\nfunc TestCutSuffix(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\t// case 1\n\tactualBefore, result := CutSuffix(\n\t\t[]TestCutStruct{{id: 1, data: \"a\"}, {id: 2, data: \"a\"}, {id: 2, data: \"b\"}},\n\t\t[]TestCutStruct{{id: 3, data: \"b\"}},\n\t)\n\tis.False(result)\n\tis.Equal([]TestCutStruct{{id: 1, data: \"a\"}, {id: 2, data: \"a\"}, {id: 2, data: \"b\"}}, actualBefore)\n\n\t// case 2\n\tactualBefore, result = CutSuffix(\n\t\t[]TestCutStruct{{id: 1, data: \"a\"}, {id: 2, data: \"a\"}, {id: 2, data: \"b\"}},\n\t\t[]TestCutStruct{{id: 2, data: \"b\"}},\n\t)\n\tis.True(result)\n\tis.Equal([]TestCutStruct{{id: 1, data: \"a\"}, {id: 2, data: \"a\"}}, actualBefore)\n\n\t// case 3\n\tactualBefore, result = CutSuffix(\n\t\t[]TestCutStruct{{id: 1, data: \"a\"}, {id: 2, data: \"a\"}, {id: 2, data: \"b\"}},\n\t\t[]TestCutStruct{},\n\t)\n\tis.True(result)\n\tis.Equal([]TestCutStruct{{id: 1, data: \"a\"}, {id: 2, data: \"a\"}, {id: 2, data: \"b\"}}, actualBefore)\n\n\t// case 4\n\tactualBefore, result = CutSuffix(\n\t\t[]TestCutStruct{{id: 1, data: \"a\"}, {id: 2, data: \"a\"}, {id: 2, data: \"b\"}},\n\t\t[]TestCutStruct{{id: 2, data: \"a\"}},\n\t)\n\tis.False(result)\n\tis.Equal([]TestCutStruct{{id: 1, data: \"a\"}, {id: 2, data: \"a\"}, {id: 2, data: \"b\"}}, actualBefore)\n\n\t// case 5\n\tactualAfterS, result := CutSuffix([]string{\"a\", \"a\", \"b\"}, []string{})\n\tis.True(result)\n\tis.Equal([]string{\"a\", \"a\", \"b\"}, actualAfterS)\n}\n\nfunc TestTrim(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tactual := Trim([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, []string{\"a\", \"b\"})\n\tis.Equal([]string{\"c\", \"d\", \"e\", \"f\", \"g\"}, actual)\n\tactual = Trim([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, []string{\"g\", \"f\"})\n\tis.Equal([]string{\"a\", \"b\", \"c\", \"d\", \"e\"}, actual)\n\tactual = Trim([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, []string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"})\n\tis.Equal([]string{}, actual)\n\tactual = Trim([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, []string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\", \"h\"})\n\tis.Equal([]string{}, actual)\n\tactual = Trim([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, []string{})\n\tis.Equal([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, actual)\n}\n\nfunc TestTrimLeft(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tactual := TrimLeft([]string{\"a\", \"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, []string{\"a\", \"b\"})\n\tis.Equal([]string{\"c\", \"d\", \"e\", \"f\", \"g\"}, actual)\n\tactual = TrimLeft([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, []string{\"b\", \"a\"})\n\tis.Equal([]string{\"c\", \"d\", \"e\", \"f\", \"g\"}, actual)\n\tactual = TrimLeft([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, []string{\"g\", \"f\"})\n\tis.Equal([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, actual)\n\tactual = TrimLeft([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, []string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"})\n\tis.Equal([]string{}, actual)\n\tactual = TrimLeft([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, []string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\", \"h\"})\n\tis.Equal([]string{}, actual)\n\tactual = TrimLeft([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, []string{})\n\tis.Equal([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, actual)\n}\n\nfunc TestTrimPrefix(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tactual := TrimPrefix([]string{\"a\", \"b\", \"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, []string{\"a\", \"b\"})\n\tis.Equal([]string{\"c\", \"d\", \"e\", \"f\", \"g\"}, actual)\n\tactual = TrimPrefix([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, []string{\"b\", \"a\"})\n\tis.Equal([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, actual)\n\tactual = TrimPrefix([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, []string{\"g\", \"f\"})\n\tis.Equal([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, actual)\n\tactual = TrimPrefix([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, []string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"})\n\tis.Equal([]string{}, actual)\n\tactual = TrimPrefix([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, []string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\", \"h\"})\n\tis.Equal([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, actual)\n\tactual = TrimPrefix([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, []string{})\n\tis.Equal([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, actual)\n}\n\nfunc TestTrimRight(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tactual := TrimRight([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, []string{\"a\", \"b\"})\n\tis.Equal([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, actual)\n\tactual = TrimRight([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\", \"g\"}, []string{\"g\", \"f\"})\n\tis.Equal([]string{\"a\", \"b\", \"c\", \"d\", \"e\"}, actual)\n\tactual = TrimRight([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, []string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"})\n\tis.Equal([]string{}, actual)\n\tactual = TrimRight([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, []string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\", \"h\"})\n\tis.Equal([]string{}, actual)\n\tactual = TrimRight([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, []string{})\n\tis.Equal([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, actual)\n}\n\nfunc TestTrimSuffix(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tactual := TrimSuffix([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, []string{\"a\", \"b\"})\n\tis.Equal([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, actual)\n\tactual = TrimSuffix([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\", \"f\", \"g\"}, []string{\"f\", \"g\"})\n\tis.Equal([]string{\"a\", \"b\", \"c\", \"d\", \"e\"}, actual)\n\tactual = TrimSuffix([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\", \"f\", \"g\"}, []string{\"g\", \"f\"})\n\tis.Equal([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\", \"f\", \"g\"}, actual)\n\tactual = TrimSuffix([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, []string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"})\n\tis.Equal([]string{}, actual)\n\tactual = TrimSuffix([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, []string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\", \"h\"})\n\tis.Equal([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, actual)\n\tactual = TrimSuffix([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, []string{})\n\tis.Equal([]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"}, actual)\n}\n"
  },
  {
    "path": "string.go",
    "content": "package lo\n\nimport (\n\t\"math\"\n\t\"regexp\"\n\t\"strings\"\n\t\"unicode\"\n\t\"unicode/utf8\"\n\n\t\"golang.org/x/text/cases\"\n\t\"golang.org/x/text/language\"\n\n\t\"github.com/samber/lo/internal/xrand\"\n)\n\nvar (\n\t//nolint:revive\n\tLowerCaseLettersCharset = []rune(\"abcdefghijklmnopqrstuvwxyz\")\n\tUpperCaseLettersCharset = []rune(\"ABCDEFGHIJKLMNOPQRSTUVWXYZ\")\n\tLettersCharset          = append(LowerCaseLettersCharset, UpperCaseLettersCharset...)\n\tNumbersCharset          = []rune(\"0123456789\")\n\tAlphanumericCharset     = append(LettersCharset, NumbersCharset...)\n\tSpecialCharset          = []rune(\"!@#$%^&*()_+-=[]{}|;':\\\",./<>?\")\n\tAllCharset              = append(AlphanumericCharset, SpecialCharset...)\n\n\t// bearer:disable go_lang_permissive_regex_validation\n\tsplitWordReg = regexp.MustCompile(`([a-z])([A-Z0-9])|([a-zA-Z])([0-9])|([0-9])([a-zA-Z])|([A-Z])([A-Z])([a-z])`)\n\t// bearer:disable go_lang_permissive_regex_validation\n\tsplitNumberLetterReg = regexp.MustCompile(`([0-9])([a-zA-Z])`)\n\tmaximumCapacity      = math.MaxInt>>1 + 1\n)\n\n// RandomString return a random string.\n// Play: https://go.dev/play/p/rRseOQVVum4\nfunc RandomString(size int, charset []rune) string {\n\tif size <= 0 {\n\t\tpanic(\"lo.RandomString: size must be greater than 0\")\n\t}\n\tif len(charset) == 0 {\n\t\tpanic(\"lo.RandomString: charset must not be empty\")\n\t}\n\n\t// see https://stackoverflow.com/questions/22892120/how-to-generate-a-random-string-of-a-fixed-length-in-go\n\tvar sb strings.Builder\n\tsb.Grow(size)\n\n\tif len(charset) == 1 {\n\t\t// Edge case, because if the charset is a single character,\n\t\t// it will panic below (divide by zero).\n\t\t// -> https://github.com/samber/lo/issues/679\n\t\tfor i := 0; i < size; i++ {\n\t\t\tsb.WriteRune(charset[0])\n\t\t}\n\t\treturn sb.String()\n\t}\n\n\t// Calculate the number of bits required to represent the charset,\n\t// e.g., for 62 characters, it would need 6 bits (since 62 -> 64 = 2^6)\n\tletterIDBits := int(math.Log2(float64(nearestPowerOfTwo(len(charset)))))\n\t// Determine the corresponding bitmask,\n\t// e.g., for 62 characters, the bitmask would be 111111.\n\tvar letterIDMask int64 = 1<<letterIDBits - 1\n\t// Available count, since xrand.Int64() returns a non-negative number, the first bit is fixed, so there are 63 random bits\n\t// e.g., for 62 characters, this value is 10 (63 / 6).\n\tletterIDMax := 63 / letterIDBits\n\t// Generate the random string in a loop.\n\tfor i, cache, remain := size-1, xrand.Int64(), letterIDMax; i >= 0; {\n\t\t// Regenerate the random number if all available bits have been used\n\t\tif remain == 0 {\n\t\t\tcache, remain = xrand.Int64(), letterIDMax\n\t\t}\n\t\t// Select a character from the charset\n\t\tif idx := int(cache & letterIDMask); idx < len(charset) {\n\t\t\tsb.WriteRune(charset[idx])\n\t\t\ti--\n\t\t}\n\t\t// Shift the bits to the right to prepare for the next character selection,\n\t\t// e.g., for 62 characters, shift by 6 bits.\n\t\tcache >>= letterIDBits\n\t\t// Decrease the remaining number of uses for the current random number.\n\t\tremain--\n\t}\n\treturn sb.String()\n}\n\n// nearestPowerOfTwo returns the nearest power of two.\nfunc nearestPowerOfTwo(capacity int) int {\n\tn := capacity - 1\n\tn |= n >> 1\n\tn |= n >> 2\n\tn |= n >> 4\n\tn |= n >> 8\n\tn |= n >> 16\n\tif n < 0 {\n\t\treturn 1\n\t}\n\tif n >= maximumCapacity {\n\t\treturn maximumCapacity\n\t}\n\treturn n + 1\n}\n\n// Substring extracts a substring from a string with Unicode character (rune) awareness.\n// offset - starting position of the substring (can be positive, negative, or zero)\n// length - number of characters to extract\n// With positive offset, counting starts from the beginning of the string\n// With negative offset, counting starts from the end of the string\n// Play: https://go.dev/play/p/emzCC9zBjHu\nfunc Substring[T ~string](str T, offset int, length uint) T {\n\tstr = substring(str, offset, length)\n\n\t// Validate UTF-8 and fix invalid sequences\n\tif !utf8.ValidString(string(str)) {\n\t\t// Convert to []rune to replicate behavior with duplicated �\n\t\tstr = T([]rune(str))\n\t}\n\n\t// Remove null bytes from result\n\treturn T(strings.ReplaceAll(string(str), \"\\x00\", \"\"))\n}\n\nfunc substring[T ~string](str T, offset int, length uint) T {\n\tswitch {\n\t// Empty length or offset beyond string bounds - return empty string\n\tcase length == 0, offset >= len(str):\n\t\treturn \"\"\n\n\t// Positive offset - count from the beginning\n\tcase offset > 0:\n\t\t// Skip offset runes from the start\n\t\tfor i, r := range str {\n\t\t\tif offset--; offset == 0 {\n\t\t\t\tstr = str[i+utf8.RuneLen(r):]\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\n\t\t// If couldn't skip enough runes - string is shorter than offset\n\t\tif offset != 0 {\n\t\t\treturn \"\"\n\t\t}\n\n\t\t// If remaining string is shorter than or equal to length - return it entirely\n\t\tif uint(len(str)) <= length {\n\t\t\treturn str\n\t\t}\n\n\t\t// Otherwise proceed to trimming by length\n\t\tfallthrough\n\n\t// Zero offset or offset less than minus string length - start from beginning\n\tcase offset < -len(str), offset == 0:\n\t\t// Count length runes from the start\n\t\tfor i := range str {\n\t\t\tif length == 0 {\n\t\t\t\treturn str[:i]\n\t\t\t}\n\t\t\tlength--\n\t\t}\n\n\t\treturn str\n\n\t// Negative offset - count from the end of string\n\tdefault: // -len(str) < offset < 0\n\t\t// Helper function to move backward through runes\n\t\tbackwardPos := func(end int, count uint) (start int) {\n\t\t\tfor {\n\t\t\t\t_, i := utf8.DecodeLastRuneInString(string(str[:end]))\n\t\t\t\tend -= i\n\n\t\t\t\tif count--; count == 0 || end == 0 {\n\t\t\t\t\treturn end\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\toffset := uint(-offset)\n\n\t\t// If offset is less than or equal to length - take from position to end\n\t\tif offset <= length {\n\t\t\tstart := backwardPos(len(str), offset)\n\t\t\treturn str[start:]\n\t\t}\n\n\t\t// Otherwise calculate start and end positions\n\t\tend := backwardPos(len(str), offset-length)\n\t\tstart := backwardPos(end, length)\n\n\t\treturn str[start:end]\n\t}\n}\n\n// ChunkString returns a slice of strings split into groups of length size. If the string can't be split evenly,\n// the final chunk will be the remaining characters.\n// Play: https://go.dev/play/p/__FLTuJVz54\n//\n// Note: lo.ChunkString and lo.Chunk functions behave inconsistently for empty input: lo.ChunkString(\"\", n) returns [\"\"] instead of [].\n// See https://github.com/samber/lo/issues/788\nfunc ChunkString[T ~string](str T, size int) []T {\n\tif size <= 0 {\n\t\tpanic(\"lo.ChunkString: size must be greater than 0\")\n\t}\n\n\tif size >= len(str) {\n\t\treturn []T{str}\n\t}\n\n\tchunks := make([]T, 0, ((len(str)-1)/size)+1)\n\tcurrentLen := 0\n\tcurrentStart := 0\n\tfor i := range str {\n\t\tif currentLen == size {\n\t\t\tchunks = append(chunks, str[currentStart:i])\n\t\t\tcurrentLen = 0\n\t\t\tcurrentStart = i\n\t\t}\n\t\tcurrentLen++\n\t}\n\tchunks = append(chunks, str[currentStart:])\n\treturn chunks\n}\n\n// RuneLength is an alias to utf8.RuneCountInString which returns the number of runes in string.\n// Play: https://go.dev/play/p/BXT52mBk0zO\nfunc RuneLength(str string) int {\n\treturn utf8.RuneCountInString(str)\n}\n\n// PascalCase converts string to pascal case.\n// Play: https://go.dev/play/p/uxER7XpRHLB\nfunc PascalCase(str string) string {\n\titems := Words(str)\n\tfor i := range items {\n\t\titems[i] = Capitalize(items[i])\n\t}\n\treturn strings.Join(items, \"\")\n}\n\n// CamelCase converts string to camel case.\n// Play: https://go.dev/play/p/4JNDzaMwXkm\nfunc CamelCase(str string) string {\n\titems := Words(str)\n\tfor i, item := range items {\n\t\titem = strings.ToLower(item)\n\t\tif i > 0 {\n\t\t\titem = Capitalize(item)\n\t\t}\n\t\titems[i] = item\n\t}\n\treturn strings.Join(items, \"\")\n}\n\n// KebabCase converts string to kebab case.\n// Play: https://go.dev/play/p/ZBeMB4-pq45\nfunc KebabCase(str string) string {\n\titems := Words(str)\n\tfor i := range items {\n\t\titems[i] = strings.ToLower(items[i])\n\t}\n\treturn strings.Join(items, \"-\")\n}\n\n// SnakeCase converts string to snake case.\n// Play: https://go.dev/play/p/ziB0V89IeVH\nfunc SnakeCase(str string) string {\n\titems := Words(str)\n\tfor i := range items {\n\t\titems[i] = strings.ToLower(items[i])\n\t}\n\treturn strings.Join(items, \"_\")\n}\n\n// Words splits string into a slice of its words.\n// Play: https://go.dev/play/p/-f3VIQqiaVw\nfunc Words(str string) []string {\n\tstr = splitWordReg.ReplaceAllString(str, `$1$3$5$7 $2$4$6$8$9`)\n\t// example: Int8Value => Int 8Value => Int 8 Value\n\tstr = splitNumberLetterReg.ReplaceAllString(str, \"$1 $2\")\n\tvar result strings.Builder\n\tresult.Grow(len(str))\n\tfor _, r := range str {\n\t\tif unicode.IsLetter(r) || unicode.IsDigit(r) {\n\t\t\tresult.WriteRune(r)\n\t\t} else {\n\t\t\tresult.WriteRune(' ')\n\t\t}\n\t}\n\treturn strings.Fields(result.String())\n}\n\n// Capitalize converts the first character of string to upper case and the remaining to lower case.\n// Play: https://go.dev/play/p/uLTZZQXqnsa\nfunc Capitalize(str string) string {\n\treturn cases.Title(language.English).String(str)\n}\n\n// Ellipsis trims and truncates a string to a specified length in runes and appends an ellipsis\n// if truncated. The length parameter counts Unicode code points (runes), not bytes, so multi-byte\n// characters such as emoji or CJK ideographs are never split in the middle.\n// Play: https://go.dev/play/p/qE93rgqe1TW\nfunc Ellipsis(str string, length int) string {\n\tstr = strings.TrimSpace(str)\n\n\tconst ellipsis = \"...\"\n\n\tcutPosition := 0\n\tfor i := range str {\n\t\tif length == len(ellipsis) {\n\t\t\tcutPosition = i\n\t\t}\n\n\t\tif length--; length < 0 {\n\t\t\treturn strings.TrimSpace(str[:cutPosition]) + ellipsis\n\t\t}\n\t}\n\n\treturn str\n}\n"
  },
  {
    "path": "string_test.go",
    "content": "package lo\n\nimport (\n\t\"fmt\"\n\t\"math\"\n\t\"strings\"\n\t\"testing\"\n\t\"unicode/utf8\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestRandomString(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tstr1 := RandomString(100, LowerCaseLettersCharset)\n\tis.Equal(100, RuneLength(str1))\n\tis.Subset(LowerCaseLettersCharset, []rune(str1))\n\n\tstr2 := RandomString(100, LowerCaseLettersCharset)\n\tis.NotEqual(str1, str2)\n\n\tnoneUtf8Charset := []rune(\"明1好休2林森\")\n\tstr3 := RandomString(100, noneUtf8Charset)\n\tis.Equal(100, RuneLength(str3))\n\tis.Subset(noneUtf8Charset, []rune(str3))\n\n\tis.PanicsWithValue(\"lo.RandomString: charset must not be empty\", func() { RandomString(100, []rune{}) })\n\tis.PanicsWithValue(\"lo.RandomString: size must be greater than 0\", func() { RandomString(0, LowerCaseLettersCharset) })\n\n\tstr4 := RandomString(10, []rune{65})\n\tis.Equal(10, RuneLength(str4))\n\tis.Subset([]rune{65, 65, 65, 65, 65, 65, 65, 65, 65, 65}, []rune(str4))\n}\n\nfunc TestChunkString(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := ChunkString(\"12345\", 2)\n\tis.Equal([]string{\"12\", \"34\", \"5\"}, result1)\n\n\tresult2 := ChunkString(\"123456\", 2)\n\tis.Equal([]string{\"12\", \"34\", \"56\"}, result2)\n\n\tresult3 := ChunkString(\"123456\", 6)\n\tis.Equal([]string{\"123456\"}, result3)\n\n\tresult4 := ChunkString(\"123456\", 10)\n\tis.Equal([]string{\"123456\"}, result4)\n\n\tresult5 := ChunkString(\"\", 2)\n\tis.Equal([]string{\"\"}, result5) // @TODO: should be [] - see https://github.com/samber/lo/issues/788\n\n\tresult6 := ChunkString(\"明1好休2林森\", 2)\n\tis.Equal([]string{\"明1\", \"好休\", \"2林\", \"森\"}, result6)\n\n\tis.PanicsWithValue(\"lo.ChunkString: size must be greater than 0\", func() {\n\t\tChunkString(\"12345\", 0)\n\t})\n}\n\nfunc TestSubstring(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tstr0 := Substring(\"hello\", 5, 10)\n\tstr1 := Substring(\"hello\", 0, 0)\n\tstr2 := Substring(\"hello\", 10, 2)\n\tstr3 := Substring(\"hello\", -10, 2)\n\tstr4 := Substring(\"hello\", 0, 10)\n\tstr5 := Substring(\"hello\", 0, 2)\n\tstr6 := Substring(\"hello\", 2, 2)\n\tstr7 := Substring(\"hello\", 2, 5)\n\tstr8 := Substring(\"hello\", 2, 3)\n\tstr9 := Substring(\"hello\", 2, 4)\n\tstr10 := Substring(\"hello\", -2, 4)\n\tstr11 := Substring(\"hello\", -4, 1)\n\tstr12 := Substring(\"hello\", -4, math.MaxUint)\n\tstr13 := Substring(\"🏠🐶🐱\", 0, 2)\n\tstr14 := Substring(\"你好，世界\", 0, 3)\n\tstr15 := Substring(\"🏠🐶🐱\", 1, 2)\n\tstr16 := Substring(\"🏠🐶🐱\", -2, 2)\n\tstr17 := Substring(\"🏠🐶🐱\", 3, 3)\n\tstr18 := Substring(\"🏠🐶🐱\", 4, 3)\n\tstr19 := Substring(\"hello\", 5, 1)\n\tstr20 := Substring(\"hello\", -5, 5)\n\tstr21 := Substring(\"hello\", -5, 4)\n\tstr22 := Substring(\"hello\", -5, math.MaxUint)\n\tstr23 := Substring(\"\\x00\\x00\\x00\", 0, math.MaxUint)\n\tstr24 := Substring(string(utf8.RuneError), 0, math.MaxUint)\n\tstr25 := Substring(\"привет\"[1:], 0, 6)\n\tstr26 := Substring(\"привет\"[:2*5+1], 0, 6)\n\tstr27 := Substring(\"привет\"[:2*5+1], -2, math.MaxUint)\n\tstr28 := Substring(\"🏠🐶🐱\"[1:], 0, math.MaxUint)\n\tstr29 := Substring(\"🏠🐶🐱\"[1:], 0, 2)\n\tstr30 := Substring(\"привет\", 6, math.MaxUint)\n\tstr31 := Substring(\"привет\", 6+1, math.MaxUint)\n\n\tis.Empty(str0)\n\tis.Empty(str1)\n\tis.Empty(str2)\n\tis.Equal(\"he\", str3)\n\tis.Equal(\"hello\", str4)\n\tis.Equal(\"he\", str5)\n\tis.Equal(\"ll\", str6)\n\tis.Equal(\"llo\", str7)\n\tis.Equal(\"llo\", str8)\n\tis.Equal(\"llo\", str9)\n\tis.Equal(\"lo\", str10)\n\tis.Equal(\"e\", str11)\n\tis.Equal(\"ello\", str12)\n\tis.Equal(\"🏠🐶\", str13)\n\tis.Equal(\"你好，\", str14)\n\tis.Equal(\"🐶🐱\", str15)\n\tis.Equal(\"🐶🐱\", str16)\n\tis.Empty(str17)\n\tis.Empty(str18)\n\tis.Empty(str19)\n\tis.Equal(\"hello\", str20)\n\tis.Equal(\"hell\", str21)\n\tis.Equal(\"hello\", str22)\n\tis.Empty(str23)\n\tis.Equal(\"�\", str24)\n\tis.Equal(\"�ривет\", str25)\n\tis.Equal(\"приве�\", str26)\n\tis.Equal(\"е�\", str27)\n\tis.Equal(\"���🐶🐱\", str28)\n\tis.Equal(\"��\", str29)\n\tis.Empty(str30)\n\tis.Empty(str31)\n}\n\nfunc BenchmarkSubstring(b *testing.B) {\n\tstr := strings.Repeat(\"1\", 100)\n\n\tfor _, test := range []struct {\n\t\toffset int\n\t\tlength uint\n\t}{\n\t\t{10, 10},\n\t\t{50, 50},\n\t\t{50, 45},\n\t\t{-50, 50},\n\t\t{-10, 10},\n\t} {\n\t\tfmt.Println(test)\n\t\tb.Run(fmt.Sprint(test), func(b *testing.B) {\n\t\t\tfor i := 0; i < b.N; i++ {\n\t\t\t\t_ = Substring(str, test.offset, test.length)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestRuneLength(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tis.Equal(5, RuneLength(\"hellô\"))\n\tis.Len(\"hellô\", 6)\n}\n\nfunc TestAllCase(t *testing.T) {\n\tt.Parallel()\n\n\ttype output struct {\n\t\tPascalCase string\n\t\tCamelCase  string\n\t\tKebabCase  string\n\t\tSnakeCase  string\n\t}\n\ttestCases := []struct {\n\t\tname string\n\t\tin   string\n\t\twant output\n\t}{\n\t\t{want: output{}},\n\t\t{in: \".\", want: output{}},\n\t\t{in: \"Hello world!\", want: output{\n\t\t\tPascalCase: \"HelloWorld\",\n\t\t\tCamelCase:  \"helloWorld\",\n\t\t\tKebabCase:  \"hello-world\",\n\t\t\tSnakeCase:  \"hello_world\",\n\t\t}},\n\t\t{in: \"A\", want: output{\n\t\t\tPascalCase: \"A\",\n\t\t\tCamelCase:  \"a\",\n\t\t\tKebabCase:  \"a\",\n\t\t\tSnakeCase:  \"a\",\n\t\t}},\n\t\t{in: \"a\", want: output{\n\t\t\tPascalCase: \"A\",\n\t\t\tCamelCase:  \"a\",\n\t\t\tKebabCase:  \"a\",\n\t\t\tSnakeCase:  \"a\",\n\t\t}},\n\t\t{in: \"foo\", want: output{\n\t\t\tPascalCase: \"Foo\",\n\t\t\tCamelCase:  \"foo\",\n\t\t\tKebabCase:  \"foo\",\n\t\t\tSnakeCase:  \"foo\",\n\t\t}},\n\t\t{in: \"snake_case\", want: output{\n\t\t\tPascalCase: \"SnakeCase\",\n\t\t\tCamelCase:  \"snakeCase\",\n\t\t\tKebabCase:  \"snake-case\",\n\t\t\tSnakeCase:  \"snake_case\",\n\t\t}},\n\t\t{in: \"SNAKE_CASE\", want: output{\n\t\t\tPascalCase: \"SnakeCase\",\n\t\t\tCamelCase:  \"snakeCase\",\n\t\t\tKebabCase:  \"snake-case\",\n\t\t\tSnakeCase:  \"snake_case\",\n\t\t}},\n\t\t{in: \"kebab-case\", want: output{\n\t\t\tPascalCase: \"KebabCase\",\n\t\t\tCamelCase:  \"kebabCase\",\n\t\t\tKebabCase:  \"kebab-case\",\n\t\t\tSnakeCase:  \"kebab_case\",\n\t\t}},\n\t\t{in: \"PascalCase\", want: output{\n\t\t\tPascalCase: \"PascalCase\",\n\t\t\tCamelCase:  \"pascalCase\",\n\t\t\tKebabCase:  \"pascal-case\",\n\t\t\tSnakeCase:  \"pascal_case\",\n\t\t}},\n\t\t{in: \"camelCase\", want: output{\n\t\t\tPascalCase: \"CamelCase\",\n\t\t\tCamelCase:  \"camelCase\",\n\t\t\tKebabCase:  `camel-case`,\n\t\t\tSnakeCase:  \"camel_case\",\n\t\t}},\n\t\t{in: \"Title Case\", want: output{\n\t\t\tPascalCase: \"TitleCase\",\n\t\t\tCamelCase:  \"titleCase\",\n\t\t\tKebabCase:  \"title-case\",\n\t\t\tSnakeCase:  \"title_case\",\n\t\t}},\n\t\t{in: \"point.case\", want: output{\n\t\t\tPascalCase: \"PointCase\",\n\t\t\tCamelCase:  \"pointCase\",\n\t\t\tKebabCase:  \"point-case\",\n\t\t\tSnakeCase:  \"point_case\",\n\t\t}},\n\t\t{in: \"snake_case_with_more_words\", want: output{\n\t\t\tPascalCase: \"SnakeCaseWithMoreWords\",\n\t\t\tCamelCase:  \"snakeCaseWithMoreWords\",\n\t\t\tKebabCase:  \"snake-case-with-more-words\",\n\t\t\tSnakeCase:  \"snake_case_with_more_words\",\n\t\t}},\n\t\t{in: \"SNAKE_CASE_WITH_MORE_WORDS\", want: output{\n\t\t\tPascalCase: \"SnakeCaseWithMoreWords\",\n\t\t\tCamelCase:  \"snakeCaseWithMoreWords\",\n\t\t\tKebabCase:  \"snake-case-with-more-words\",\n\t\t\tSnakeCase:  \"snake_case_with_more_words\",\n\t\t}},\n\t\t{in: \"kebab-case-with-more-words\", want: output{\n\t\t\tPascalCase: \"KebabCaseWithMoreWords\",\n\t\t\tCamelCase:  \"kebabCaseWithMoreWords\",\n\t\t\tKebabCase:  \"kebab-case-with-more-words\",\n\t\t\tSnakeCase:  \"kebab_case_with_more_words\",\n\t\t}},\n\t\t{in: \"PascalCaseWithMoreWords\", want: output{\n\t\t\tPascalCase: \"PascalCaseWithMoreWords\",\n\t\t\tCamelCase:  \"pascalCaseWithMoreWords\",\n\t\t\tKebabCase:  \"pascal-case-with-more-words\",\n\t\t\tSnakeCase:  \"pascal_case_with_more_words\",\n\t\t}},\n\t\t{in: \"camelCaseWithMoreWords\", want: output{\n\t\t\tPascalCase: \"CamelCaseWithMoreWords\",\n\t\t\tCamelCase:  \"camelCaseWithMoreWords\",\n\t\t\tKebabCase:  \"camel-case-with-more-words\",\n\t\t\tSnakeCase:  \"camel_case_with_more_words\",\n\t\t}},\n\t\t{in: \"Title Case With More Words\", want: output{\n\t\t\tPascalCase: \"TitleCaseWithMoreWords\",\n\t\t\tCamelCase:  \"titleCaseWithMoreWords\",\n\t\t\tKebabCase:  \"title-case-with-more-words\",\n\t\t\tSnakeCase:  \"title_case_with_more_words\",\n\t\t}},\n\t\t{in: \"point.case.with.more.words\", want: output{\n\t\t\tPascalCase: \"PointCaseWithMoreWords\",\n\t\t\tCamelCase:  \"pointCaseWithMoreWords\",\n\t\t\tKebabCase:  \"point-case-with-more-words\",\n\t\t\tSnakeCase:  \"point_case_with_more_words\",\n\t\t}},\n\t\t{in: \"snake_case__with___multiple____delimiters\", want: output{\n\t\t\tPascalCase: \"SnakeCaseWithMultipleDelimiters\",\n\t\t\tCamelCase:  \"snakeCaseWithMultipleDelimiters\",\n\t\t\tKebabCase:  \"snake-case-with-multiple-delimiters\",\n\t\t\tSnakeCase:  \"snake_case_with_multiple_delimiters\",\n\t\t}},\n\t\t{in: \"SNAKE_CASE__WITH___multiple____DELIMITERS\", want: output{\n\t\t\tPascalCase: \"SnakeCaseWithMultipleDelimiters\",\n\t\t\tCamelCase:  \"snakeCaseWithMultipleDelimiters\",\n\t\t\tKebabCase:  \"snake-case-with-multiple-delimiters\",\n\t\t\tSnakeCase:  \"snake_case_with_multiple_delimiters\",\n\t\t}},\n\t\t{in: \"kebab-case--with---multiple----delimiters\", want: output{\n\t\t\tPascalCase: \"KebabCaseWithMultipleDelimiters\",\n\t\t\tCamelCase:  \"kebabCaseWithMultipleDelimiters\",\n\t\t\tKebabCase:  \"kebab-case-with-multiple-delimiters\",\n\t\t\tSnakeCase:  \"kebab_case_with_multiple_delimiters\",\n\t\t}},\n\t\t{in: \"Title Case  With   Multiple    Delimiters\", want: output{\n\t\t\tPascalCase: \"TitleCaseWithMultipleDelimiters\",\n\t\t\tCamelCase:  \"titleCaseWithMultipleDelimiters\",\n\t\t\tKebabCase:  \"title-case-with-multiple-delimiters\",\n\t\t\tSnakeCase:  \"title_case_with_multiple_delimiters\",\n\t\t}},\n\t\t{in: \"point.case..with...multiple....delimiters\", want: output{\n\t\t\tPascalCase: \"PointCaseWithMultipleDelimiters\",\n\t\t\tCamelCase:  \"pointCaseWithMultipleDelimiters\",\n\t\t\tKebabCase:  \"point-case-with-multiple-delimiters\",\n\t\t\tSnakeCase:  \"point_case_with_multiple_delimiters\",\n\t\t}},\n\t\t{in: \" leading space\", want: output{\n\t\t\tPascalCase: \"LeadingSpace\",\n\t\t\tCamelCase:  \"leadingSpace\",\n\t\t\tKebabCase:  \"leading-space\",\n\t\t\tSnakeCase:  \"leading_space\",\n\t\t}},\n\t\t{in: \"   leading spaces\", want: output{\n\t\t\tPascalCase: \"LeadingSpaces\",\n\t\t\tCamelCase:  \"leadingSpaces\",\n\t\t\tKebabCase:  \"leading-spaces\",\n\t\t\tSnakeCase:  \"leading_spaces\",\n\t\t}},\n\t\t{in: \"\\t\\t\\r\\n leading whitespaces\", want: output{\n\t\t\tPascalCase: \"LeadingWhitespaces\",\n\t\t\tCamelCase:  \"leadingWhitespaces\",\n\t\t\tKebabCase:  \"leading-whitespaces\",\n\t\t\tSnakeCase:  \"leading_whitespaces\",\n\t\t}},\n\t\t{in: \"trailing space \", want: output{\n\t\t\tPascalCase: \"TrailingSpace\",\n\t\t\tCamelCase:  \"trailingSpace\",\n\t\t\tKebabCase:  \"trailing-space\",\n\t\t\tSnakeCase:  \"trailing_space\",\n\t\t}},\n\t\t{in: \"trailing spaces   \", want: output{\n\t\t\tPascalCase: \"TrailingSpaces\",\n\t\t\tCamelCase:  \"trailingSpaces\",\n\t\t\tKebabCase:  \"trailing-spaces\",\n\t\t\tSnakeCase:  \"trailing_spaces\",\n\t\t}},\n\t\t{in: \"trailing whitespaces\\t\\t\\r\\n\", want: output{\n\t\t\tPascalCase: \"TrailingWhitespaces\",\n\t\t\tCamelCase:  \"trailingWhitespaces\",\n\t\t\tKebabCase:  \"trailing-whitespaces\",\n\t\t\tSnakeCase:  \"trailing_whitespaces\",\n\t\t}},\n\t\t{in: \" on both sides \", want: output{\n\t\t\tPascalCase: \"OnBothSides\",\n\t\t\tCamelCase:  \"onBothSides\",\n\t\t\tKebabCase:  \"on-both-sides\",\n\t\t\tSnakeCase:  \"on_both_sides\",\n\t\t}},\n\t\t{in: \"    many on both sides  \", want: output{\n\t\t\tPascalCase: \"ManyOnBothSides\",\n\t\t\tCamelCase:  \"manyOnBothSides\",\n\t\t\tKebabCase:  \"many-on-both-sides\",\n\t\t\tSnakeCase:  \"many_on_both_sides\",\n\t\t}},\n\t\t{in: \"\\r whitespaces on both sides\\t\\t\\r\\n\", want: output{\n\t\t\tPascalCase: \"WhitespacesOnBothSides\",\n\t\t\tCamelCase:  \"whitespacesOnBothSides\",\n\t\t\tKebabCase:  \"whitespaces-on-both-sides\",\n\t\t\tSnakeCase:  \"whitespaces_on_both_sides\",\n\t\t}},\n\t\t{in: \"  extraSpaces in_This TestCase Of MIXED_CASES\\t\", want: output{\n\t\t\tPascalCase: \"ExtraSpacesInThisTestCaseOfMixedCases\",\n\t\t\tCamelCase:  \"extraSpacesInThisTestCaseOfMixedCases\",\n\t\t\tKebabCase:  \"extra-spaces-in-this-test-case-of-mixed-cases\",\n\t\t\tSnakeCase:  \"extra_spaces_in_this_test_case_of_mixed_cases\",\n\t\t}},\n\t\t{in: \"CASEBreak\", want: output{\n\t\t\tPascalCase: \"CaseBreak\",\n\t\t\tCamelCase:  \"caseBreak\",\n\t\t\tKebabCase:  \"case-break\",\n\t\t\tSnakeCase:  \"case_break\",\n\t\t}},\n\t\t{in: \"ID\", want: output{\n\t\t\tPascalCase: \"Id\",\n\t\t\tCamelCase:  \"id\",\n\t\t\tKebabCase:  \"id\",\n\t\t\tSnakeCase:  \"id\",\n\t\t}},\n\t\t{in: \"userID\", want: output{\n\t\t\tPascalCase: \"UserId\",\n\t\t\tCamelCase:  \"userId\",\n\t\t\tKebabCase:  \"user-id\",\n\t\t\tSnakeCase:  \"user_id\",\n\t\t}},\n\t\t{in: \"JSON_blob\", want: output{\n\t\t\tPascalCase: \"JsonBlob\",\n\t\t\tCamelCase:  \"jsonBlob\",\n\t\t\tKebabCase:  \"json-blob\",\n\t\t\tSnakeCase:  \"json_blob\",\n\t\t}},\n\t\t{in: \"HTTPStatusCode\", want: output{\n\t\t\tPascalCase: \"HttpStatusCode\",\n\t\t\tCamelCase:  \"httpStatusCode\",\n\t\t\tKebabCase:  \"http-status-code\",\n\t\t\tSnakeCase:  \"http_status_code\",\n\t\t}},\n\t\t{in: \"FreeBSD and SSLError are not golang initialisms\", want: output{\n\t\t\tPascalCase: \"FreeBsdAndSslErrorAreNotGolangInitialisms\",\n\t\t\tCamelCase:  \"freeBsdAndSslErrorAreNotGolangInitialisms\",\n\t\t\tKebabCase:  \"free-bsd-and-ssl-error-are-not-golang-initialisms\",\n\t\t\tSnakeCase:  \"free_bsd_and_ssl_error_are_not_golang_initialisms\",\n\t\t}},\n\t\t{in: \"David's Computer\", want: output{\n\t\t\tPascalCase: \"DavidSComputer\",\n\t\t\tCamelCase:  \"davidSComputer\",\n\t\t\tKebabCase:  \"david-s-computer\",\n\t\t\tSnakeCase:  \"david_s_computer\",\n\t\t}},\n\t\t{in: \"http200\", want: output{\n\t\t\tPascalCase: \"Http200\",\n\t\t\tCamelCase:  \"http200\",\n\t\t\tKebabCase:  \"http-200\",\n\t\t\tSnakeCase:  \"http_200\",\n\t\t}},\n\t\t{in: \"NumberSplittingVersion1.0r3\", want: output{\n\t\t\tPascalCase: \"NumberSplittingVersion10R3\",\n\t\t\tCamelCase:  \"numberSplittingVersion10R3\",\n\t\t\tKebabCase:  \"number-splitting-version-1-0-r3\",\n\t\t\tSnakeCase:  \"number_splitting_version_1_0_r3\",\n\t\t}},\n\t\t{in: \"When you have a comma, odd results\", want: output{\n\t\t\tPascalCase: \"WhenYouHaveACommaOddResults\",\n\t\t\tCamelCase:  \"whenYouHaveACommaOddResults\",\n\t\t\tKebabCase:  \"when-you-have-a-comma-odd-results\",\n\t\t\tSnakeCase:  \"when_you_have_a_comma_odd_results\",\n\t\t}},\n\t\t{in: \"Ordinal numbers work: 1st 2nd and 3rd place\", want: output{\n\t\t\tPascalCase: \"OrdinalNumbersWork1St2NdAnd3RdPlace\",\n\t\t\tCamelCase:  \"ordinalNumbersWork1St2NdAnd3RdPlace\",\n\t\t\tKebabCase:  \"ordinal-numbers-work-1-st-2-nd-and-3-rd-place\",\n\t\t\tSnakeCase:  \"ordinal_numbers_work_1_st_2_nd_and_3_rd_place\",\n\t\t}},\n\t\t{in: \"BadUTF8\\xe2\\xe2\\xa1\", want: output{\n\t\t\tPascalCase: \"BadUtf8\",\n\t\t\tCamelCase:  \"badUtf8\",\n\t\t\tKebabCase:  \"bad-utf-8\",\n\t\t\tSnakeCase:  \"bad_utf_8\",\n\t\t}},\n\t\t{in: \"IDENT3\", want: output{\n\t\t\tPascalCase: \"Ident3\",\n\t\t\tCamelCase:  \"ident3\",\n\t\t\tKebabCase:  \"ident-3\",\n\t\t\tSnakeCase:  \"ident_3\",\n\t\t}},\n\t\t{in: \"LogRouterS3BucketName\", want: output{\n\t\t\tPascalCase: \"LogRouterS3BucketName\",\n\t\t\tCamelCase:  \"logRouterS3BucketName\",\n\t\t\tKebabCase:  \"log-router-s3-bucket-name\",\n\t\t\tSnakeCase:  \"log_router_s3_bucket_name\",\n\t\t}},\n\t\t{in: \"PINEAPPLE\", want: output{\n\t\t\tPascalCase: \"Pineapple\",\n\t\t\tCamelCase:  \"pineapple\",\n\t\t\tKebabCase:  \"pineapple\",\n\t\t\tSnakeCase:  \"pineapple\",\n\t\t}},\n\t\t{in: \"Int8Value\", want: output{\n\t\t\tPascalCase: \"Int8Value\",\n\t\t\tCamelCase:  \"int8Value\",\n\t\t\tKebabCase:  \"int-8-value\",\n\t\t\tSnakeCase:  \"int_8_value\",\n\t\t}},\n\t\t{in: \"first.last\", want: output{\n\t\t\tPascalCase: \"FirstLast\",\n\t\t\tCamelCase:  \"firstLast\",\n\t\t\tKebabCase:  \"first-last\",\n\t\t\tSnakeCase:  \"first_last\",\n\t\t}},\n\t}\n\n\tfor _, tc := range testCases {\n\t\ttc := tc\n\t\tt.Run(tc.in, func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\tis := assert.New(t)\n\t\t\tis.Equalf(tc.want.PascalCase, PascalCase(tc.in), \"PascalCase(%v)\", tc.in)\n\t\t\tis.Equalf(tc.want.CamelCase, CamelCase(tc.in), \"CamelCase(%v)\", tc.in)\n\t\t\tis.Equalf(tc.want.KebabCase, KebabCase(tc.in), \"KebabCase(%v)\", tc.in)\n\t\t\tis.Equalf(tc.want.SnakeCase, SnakeCase(tc.in), \"SnakeCase(%v)\", tc.in)\n\t\t})\n\t}\n}\n\nfunc TestWords(t *testing.T) {\n\tt.Parallel()\n\n\ttestCases := []struct {\n\t\tin   string\n\t\twant []string\n\t}{\n\t\t{\"PascalCase\", []string{\"Pascal\", \"Case\"}},\n\t\t{\"camelCase\", []string{\"camel\", \"Case\"}},\n\t\t{\"snake_case\", []string{\"snake\", \"case\"}},\n\t\t{\"kebab_case\", []string{\"kebab\", \"case\"}},\n\t\t{\"_test text_\", []string{\"test\", \"text\"}},\n\t\t{\"UPPERCASE\", []string{\"UPPERCASE\"}},\n\t\t{\"HTTPCode\", []string{\"HTTP\", \"Code\"}},\n\t\t{\"Int8Value\", []string{\"Int\", \"8\", \"Value\"}},\n\t}\n\tfor _, tc := range testCases {\n\t\ttc := tc\n\t\tt.Run(tc.in, func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\tassert.Equalf(t, tc.want, Words(tc.in), \"Words(%v)\", tc.in)\n\t\t})\n\t}\n}\n\nfunc TestCapitalize(t *testing.T) {\n\tt.Parallel()\n\n\ttestCases := []struct {\n\t\tname string\n\t\tin   string\n\t\twant string\n\t}{\n\t\t{\"lower case\", \"hello\", \"Hello\"},\n\t\t{\"mixed case\", \"heLLO\", \"Hello\"},\n\t}\n\tfor _, tc := range testCases {\n\t\ttc := tc\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tt.Parallel()\n\t\t\tassert.Equalf(t, tc.want, Capitalize(tc.in), \"Capitalize(%v)\", tc.in)\n\t\t})\n\t}\n}\n\nfunc TestEllipsis(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tis.Equal(\"...\", Ellipsis(\"12\", 0))\n\tis.Equal(\"...\", Ellipsis(\"12\", 1))\n\tis.Equal(\"12\", Ellipsis(\"12\", 2))\n\tis.Equal(\"12\", Ellipsis(\"12\", 3))\n\tis.Equal(\"12345\", Ellipsis(\"12345\", 5))\n\tis.Equal(\"1...\", Ellipsis(\"12345\", 4))\n\tis.Equal(\"1...\", Ellipsis(\"\t12345  \", 4))\n\tis.Equal(\"12345\", Ellipsis(\"12345\", 6))\n\tis.Equal(\"12345\", Ellipsis(\"12345\", 10))\n\tis.Equal(\"12345\", Ellipsis(\"  12345  \", 10))\n\tis.Equal(\"...\", Ellipsis(\"12345\", 3))\n\tis.Equal(\"...\", Ellipsis(\"12345\", 2))\n\tis.Equal(\"...\", Ellipsis(\"12345\", -1))\n\tis.Equal(\"hello...\", Ellipsis(\" hello   world \", 9))\n\n\t// Unicode: rune-based truncation (not byte-based)\n\tis.Equal(\"hello...\", Ellipsis(\"hello 世界! 你好\", 8))      // CJK characters: \"hello\" (5 runes) + \"...\" = 8 runes\n\tis.Equal(\"hello 世界...\", Ellipsis(\"hello 世界! 你好\", 11))  // truncate within CJK text\n\tis.Equal(\"hello 世界! 你好\", Ellipsis(\"hello 世界! 你好\", 12)) // exact length, no truncation\n\tis.Equal(\"hello 世界! 你好\", Ellipsis(\"hello 世界! 你好\", 20)) // length exceeds string, no truncation\n\tis.Equal(\"🏠🐶🐱🌟\", Ellipsis(\"🏠🐶🐱🌟\", 5))                  // length > rune count, no truncation\n\tis.Equal(\"🏠🐶🐱🌟\", Ellipsis(\"🏠🐶🐱🌟\", 4))                  // exact length, no truncation\n\tis.Equal(\"...\", Ellipsis(\"🏠🐶🐱🌟\", 3))                   // length == 3, returns \"...\"\n\tis.Equal(\"...\", Ellipsis(\"🏠🐶🐱🌟\", 2))                   // length < 3, returns \"...\"\n\tis.Equal(\"🏠🐶...\", Ellipsis(\"🏠🐶🐱🌟🎉🌈\", 5))               // 6 emoji, truncate to 2 + \"...\"\n\tis.Equal(\"café\", Ellipsis(\"café\", 4))                  // accented char counts as 1 rune\n\tis.Equal(\"...\", Ellipsis(\"café\", 3))                   // length == 3, returns \"...\"\n\tis.Equal(\"ca...\", Ellipsis(\"café au lait\", 5))         // mixed ASCII and accented\n\n\t// Combining emoji (Rainbow Flag is 4 runes: U+1F3F3 + U+FE0F + U+200D + U+1F308)\n\t// \"aà😁🏳️‍🌈pabc\" = 1 + 1 + 1 + 4 + 1 + 1 + 1 + 1 = 11 runes total\n\tis.Equal(\"...\", Ellipsis(\"aà😁🏳️‍🌈pabc\", 2))    // only \"...\"\n\tis.Equal(\"...\", Ellipsis(\"aà😁🏳️‍🌈pabc\", 3))    // only \"...\"\n\tis.Equal(\"a...\", Ellipsis(\"aà😁🏳️‍🌈pabc\", 4))   // 1 rune + \"...\"\n\tis.Equal(\"aà...\", Ellipsis(\"aà😁🏳️‍🌈pabc\", 5))  // 2 runes + \"...\"\n\tis.Equal(\"aà😁...\", Ellipsis(\"aà😁🏳️‍🌈pabc\", 6)) // 3 runes + \"...\"\n\t// @TODO: fix these tests\n\t// is.Equal(\"aà😁🏳️‍🌈...\", Ellipsis(\"aà😁🏳️‍🌈pabc\", 7)) // 4 runes + \"...\"\n\t// is.Equal(\"aà😁🏳️‍🌈p...\", Ellipsis(\"aà😁🏳️‍🌈pabc\", 8))  // 5 runes + \"...\"\n\t// is.Equal(\"aà😁🏳️‍🌈pabc\", Ellipsis(\"aà😁🏳️‍🌈pabc\", 9))  // exact length, no truncation\n\t// is.Equal(\"aà😁🏳️‍🌈pabc\", Ellipsis(\"aà😁🏳️‍🌈pabc\", 10)) // length exceeds string, no truncation\n}\n"
  },
  {
    "path": "time.go",
    "content": "package lo\n\nimport (\n\t\"time\"\n)\n\n// Duration returns the time taken to execute a function.\n// Play: https://go.dev/play/p/LFhKq2vY9Ty\nfunc Duration(callback func()) time.Duration {\n\treturn Duration0(callback)\n}\n\n// Duration0 returns the time taken to execute a function.\n// Play: https://go.dev/play/p/HQfbBbAXaFP\nfunc Duration0(callback func()) time.Duration {\n\tstart := time.Now()\n\tcallback()\n\treturn time.Since(start)\n}\n\n// Duration1 returns the time taken to execute a function.\n// Play: https://go.dev/play/p/HQfbBbAXaFP\nfunc Duration1[A any](callback func() A) (A, time.Duration) {\n\tstart := time.Now()\n\ta := callback()\n\treturn a, time.Since(start)\n}\n\n// Duration2 returns the time taken to execute a function.\n// Play: https://go.dev/play/p/HQfbBbAXaFP\nfunc Duration2[A, B any](callback func() (A, B)) (A, B, time.Duration) {\n\tstart := time.Now()\n\ta, b := callback()\n\treturn a, b, time.Since(start)\n}\n\n// Duration3 returns the time taken to execute a function.\n// Play: https://go.dev/play/p/xr863iwkAxQ\nfunc Duration3[A, B, C any](callback func() (A, B, C)) (A, B, C, time.Duration) {\n\tstart := time.Now()\n\ta, b, c := callback()\n\treturn a, b, c, time.Since(start)\n}\n\n// Duration4 returns the time taken to execute a function.\n// Play: https://go.dev/play/p/xr863iwkAxQ\nfunc Duration4[A, B, C, D any](callback func() (A, B, C, D)) (A, B, C, D, time.Duration) {\n\tstart := time.Now()\n\ta, b, c, d := callback()\n\treturn a, b, c, d, time.Since(start)\n}\n\n// Duration5 returns the time taken to execute a function.\n// Play: https://go.dev/play/p/xr863iwkAxQ\nfunc Duration5[A, B, C, D, E any](callback func() (A, B, C, D, E)) (A, B, C, D, E, time.Duration) {\n\tstart := time.Now()\n\ta, b, c, d, e := callback()\n\treturn a, b, c, d, e, time.Since(start)\n}\n\n// Duration6 returns the time taken to execute a function.\n// Play: https://go.dev/play/p/mR4bTQKO-Tf\nfunc Duration6[A, B, C, D, E, F any](callback func() (A, B, C, D, E, F)) (A, B, C, D, E, F, time.Duration) {\n\tstart := time.Now()\n\ta, b, c, d, e, f := callback()\n\treturn a, b, c, d, e, f, time.Since(start)\n}\n\n// Duration7 returns the time taken to execute a function.\n// Play: https://go.dev/play/p/jgIAcBWWInS\nfunc Duration7[A, B, C, D, E, F, G any](callback func() (A, B, C, D, E, F, G)) (A, B, C, D, E, F, G, time.Duration) {\n\tstart := time.Now()\n\ta, b, c, d, e, f, g := callback()\n\treturn a, b, c, d, e, f, g, time.Since(start)\n}\n\n// Duration8 returns the time taken to execute a function.\n// Play: https://go.dev/play/p/T8kxpG1c5Na\nfunc Duration8[A, B, C, D, E, F, G, H any](callback func() (A, B, C, D, E, F, G, H)) (A, B, C, D, E, F, G, H, time.Duration) {\n\tstart := time.Now()\n\ta, b, c, d, e, f, g, h := callback()\n\treturn a, b, c, d, e, f, g, h, time.Since(start)\n}\n\n// Duration9 returns the time taken to execute a function.\n// Play: https://go.dev/play/p/bg9ix2VrZ0j\nfunc Duration9[A, B, C, D, E, F, G, H, I any](callback func() (A, B, C, D, E, F, G, H, I)) (A, B, C, D, E, F, G, H, I, time.Duration) {\n\tstart := time.Now()\n\ta, b, c, d, e, f, g, h, i := callback()\n\treturn a, b, c, d, e, f, g, h, i, time.Since(start)\n}\n\n// Duration10 returns the time taken to execute a function.\n// Play: https://go.dev/play/p/Y3n7oJXqJbk\nfunc Duration10[A, B, C, D, E, F, G, H, I, J any](callback func() (A, B, C, D, E, F, G, H, I, J)) (A, B, C, D, E, F, G, H, I, J, time.Duration) {\n\tstart := time.Now()\n\ta, b, c, d, e, f, g, h, i, j := callback()\n\treturn a, b, c, d, e, f, g, h, i, j, time.Since(start)\n}\n"
  },
  {
    "path": "time_test.go",
    "content": "package lo\n\nimport (\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestDuration(t *testing.T) { //nolint:paralleltest\n\t// t.Parallel()\n\tis := assert.New(t)\n\ttestWithTimeout(t, 200*time.Millisecond)\n\n\tresult := Duration(func() { time.Sleep(100 * time.Millisecond) })\n\tis.InDelta(100*time.Millisecond, result, float64(20*time.Millisecond))\n}\n\nfunc TestDurationX(t *testing.T) { //nolint:paralleltest\n\t// t.Parallel()\n\tis := assert.New(t)\n\ttestWithTimeout(t, 1500*time.Millisecond)\n\n\t{\n\t\tresult := Duration0(func() { time.Sleep(100 * time.Millisecond) })\n\t\tis.InDelta(100*time.Millisecond, result, float64(20*time.Millisecond))\n\t}\n\n\t{\n\t\ta, result := Duration1(func() string { time.Sleep(100 * time.Millisecond); return \"a\" })\n\t\tis.InDelta(100*time.Millisecond, result, float64(20*time.Millisecond))\n\t\tis.Equal(\"a\", a)\n\t}\n\n\t{\n\t\ta, b, result := Duration2(func() (string, string) { time.Sleep(100 * time.Millisecond); return \"a\", \"b\" })\n\t\tis.InDelta(100*time.Millisecond, result, float64(20*time.Millisecond))\n\t\tis.Equal(\"a\", a)\n\t\tis.Equal(\"b\", b)\n\t}\n\n\t{\n\t\ta, b, c, result := Duration3(func() (string, string, string) { time.Sleep(100 * time.Millisecond); return \"a\", \"b\", \"c\" })\n\t\tis.InDelta(100*time.Millisecond, result, float64(20*time.Millisecond))\n\t\tis.Equal(\"a\", a)\n\t\tis.Equal(\"b\", b)\n\t\tis.Equal(\"c\", c)\n\t}\n\n\t{\n\t\ta, b, c, d, result := Duration4(func() (string, string, string, string) {\n\t\t\ttime.Sleep(100 * time.Millisecond)\n\t\t\treturn \"a\", \"b\", \"c\", \"d\"\n\t\t})\n\t\tis.InDelta(100*time.Millisecond, result, float64(20*time.Millisecond))\n\t\tis.Equal(\"a\", a)\n\t\tis.Equal(\"b\", b)\n\t\tis.Equal(\"c\", c)\n\t\tis.Equal(\"d\", d)\n\t}\n\n\t{\n\t\ta, b, c, d, e, result := Duration5(func() (string, string, string, string, string) {\n\t\t\ttime.Sleep(100 * time.Millisecond)\n\t\t\treturn \"a\", \"b\", \"c\", \"d\", \"e\"\n\t\t})\n\t\tis.InDelta(100*time.Millisecond, result, float64(20*time.Millisecond))\n\t\tis.Equal(\"a\", a)\n\t\tis.Equal(\"b\", b)\n\t\tis.Equal(\"c\", c)\n\t\tis.Equal(\"d\", d)\n\t\tis.Equal(\"e\", e)\n\t}\n\n\t{\n\t\ta, b, c, d, e, f, result := Duration6(func() (string, string, string, string, string, string) {\n\t\t\ttime.Sleep(100 * time.Millisecond)\n\t\t\treturn \"a\", \"b\", \"c\", \"d\", \"e\", \"f\"\n\t\t})\n\t\tis.InDelta(100*time.Millisecond, result, float64(20*time.Millisecond))\n\t\tis.Equal(\"a\", a)\n\t\tis.Equal(\"b\", b)\n\t\tis.Equal(\"c\", c)\n\t\tis.Equal(\"d\", d)\n\t\tis.Equal(\"e\", e)\n\t\tis.Equal(\"f\", f)\n\t}\n\n\t{\n\t\ta, b, c, d, e, f, g, result := Duration7(func() (string, string, string, string, string, string, string) {\n\t\t\ttime.Sleep(100 * time.Millisecond)\n\t\t\treturn \"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"\n\t\t})\n\t\tis.InDelta(100*time.Millisecond, result, float64(20*time.Millisecond))\n\t\tis.Equal(\"a\", a)\n\t\tis.Equal(\"b\", b)\n\t\tis.Equal(\"c\", c)\n\t\tis.Equal(\"d\", d)\n\t\tis.Equal(\"e\", e)\n\t\tis.Equal(\"f\", f)\n\t\tis.Equal(\"g\", g)\n\t}\n\n\t{\n\t\ta, b, c, d, e, f, g, h, result := Duration8(func() (string, string, string, string, string, string, string, string) {\n\t\t\ttime.Sleep(100 * time.Millisecond)\n\t\t\treturn \"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\", \"h\"\n\t\t})\n\t\tis.InDelta(100*time.Millisecond, result, float64(20*time.Millisecond))\n\t\tis.Equal(\"a\", a)\n\t\tis.Equal(\"b\", b)\n\t\tis.Equal(\"c\", c)\n\t\tis.Equal(\"d\", d)\n\t\tis.Equal(\"e\", e)\n\t\tis.Equal(\"f\", f)\n\t\tis.Equal(\"g\", g)\n\t\tis.Equal(\"h\", h)\n\t}\n\n\t{\n\t\ta, b, c, d, e, f, g, h, i, result := Duration9(func() (string, string, string, string, string, string, string, string, string) {\n\t\t\ttime.Sleep(100 * time.Millisecond)\n\t\t\treturn \"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\", \"h\", \"i\"\n\t\t})\n\t\tis.InDelta(100*time.Millisecond, result, float64(20*time.Millisecond))\n\t\tis.Equal(\"a\", a)\n\t\tis.Equal(\"b\", b)\n\t\tis.Equal(\"c\", c)\n\t\tis.Equal(\"d\", d)\n\t\tis.Equal(\"e\", e)\n\t\tis.Equal(\"f\", f)\n\t\tis.Equal(\"g\", g)\n\t\tis.Equal(\"h\", h)\n\t\tis.Equal(\"i\", i)\n\t}\n\n\t{\n\t\ta, b, c, d, e, f, g, h, i, j, result := Duration10(func() (string, string, string, string, string, string, string, string, string, string) {\n\t\t\ttime.Sleep(100 * time.Millisecond)\n\t\t\treturn \"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\", \"h\", \"i\", \"j\"\n\t\t})\n\t\tis.InDelta(100*time.Millisecond, result, float64(20*time.Millisecond))\n\t\tis.Equal(\"a\", a)\n\t\tis.Equal(\"b\", b)\n\t\tis.Equal(\"c\", c)\n\t\tis.Equal(\"d\", d)\n\t\tis.Equal(\"e\", e)\n\t\tis.Equal(\"f\", f)\n\t\tis.Equal(\"g\", g)\n\t\tis.Equal(\"h\", h)\n\t\tis.Equal(\"i\", i)\n\t\tis.Equal(\"j\", j)\n\t}\n}\n"
  },
  {
    "path": "tuples.go",
    "content": "package lo\n\n// T2 creates a tuple from a list of values.\n// Play: https://go.dev/play/p/IllL3ZO4BQm\nfunc T2[A, B any](a A, b B) Tuple2[A, B] {\n\treturn Tuple2[A, B]{A: a, B: b}\n}\n\n// T3 creates a tuple from a list of values.\n// Play: https://go.dev/play/p/IllL3ZO4BQm\nfunc T3[A, B, C any](a A, b B, c C) Tuple3[A, B, C] {\n\treturn Tuple3[A, B, C]{A: a, B: b, C: c}\n}\n\n// T4 creates a tuple from a list of values.\n// Play: https://go.dev/play/p/IllL3ZO4BQm\nfunc T4[A, B, C, D any](a A, b B, c C, d D) Tuple4[A, B, C, D] {\n\treturn Tuple4[A, B, C, D]{A: a, B: b, C: c, D: d}\n}\n\n// T5 creates a tuple from a list of values.\n// Play: https://go.dev/play/p/IllL3ZO4BQm\nfunc T5[A, B, C, D, E any](a A, b B, c C, d D, e E) Tuple5[A, B, C, D, E] {\n\treturn Tuple5[A, B, C, D, E]{A: a, B: b, C: c, D: d, E: e}\n}\n\n// T6 creates a tuple from a list of values.\n// Play: https://go.dev/play/p/IllL3ZO4BQm\nfunc T6[A, B, C, D, E, F any](a A, b B, c C, d D, e E, f F) Tuple6[A, B, C, D, E, F] {\n\treturn Tuple6[A, B, C, D, E, F]{A: a, B: b, C: c, D: d, E: e, F: f}\n}\n\n// T7 creates a tuple from a list of values.\n// Play: https://go.dev/play/p/IllL3ZO4BQm\nfunc T7[A, B, C, D, E, F, G any](a A, b B, c C, d D, e E, f F, g G) Tuple7[A, B, C, D, E, F, G] {\n\treturn Tuple7[A, B, C, D, E, F, G]{A: a, B: b, C: c, D: d, E: e, F: f, G: g}\n}\n\n// T8 creates a tuple from a list of values.\n// Play: https://go.dev/play/p/IllL3ZO4BQm\nfunc T8[A, B, C, D, E, F, G, H any](a A, b B, c C, d D, e E, f F, g G, h H) Tuple8[A, B, C, D, E, F, G, H] {\n\treturn Tuple8[A, B, C, D, E, F, G, H]{A: a, B: b, C: c, D: d, E: e, F: f, G: g, H: h}\n}\n\n// T9 creates a tuple from a list of values.\n// Play: https://go.dev/play/p/IllL3ZO4BQm\nfunc T9[A, B, C, D, E, F, G, H, I any](a A, b B, c C, d D, e E, f F, g G, h H, i I) Tuple9[A, B, C, D, E, F, G, H, I] {\n\treturn Tuple9[A, B, C, D, E, F, G, H, I]{A: a, B: b, C: c, D: d, E: e, F: f, G: g, H: h, I: i}\n}\n\n// Unpack2 returns values contained in a tuple.\n// Play: https://go.dev/play/p/xVP_k0kJ96W\nfunc Unpack2[A, B any](tuple Tuple2[A, B]) (A, B) {\n\treturn tuple.A, tuple.B\n}\n\n// Unpack3 returns values contained in a tuple.\n// Play: https://go.dev/play/p/xVP_k0kJ96W\nfunc Unpack3[A, B, C any](tuple Tuple3[A, B, C]) (A, B, C) {\n\treturn tuple.A, tuple.B, tuple.C\n}\n\n// Unpack4 returns values contained in a tuple.\n// Play: https://go.dev/play/p/xVP_k0kJ96W\nfunc Unpack4[A, B, C, D any](tuple Tuple4[A, B, C, D]) (A, B, C, D) {\n\treturn tuple.A, tuple.B, tuple.C, tuple.D\n}\n\n// Unpack5 returns values contained in a tuple.\n// Play: https://go.dev/play/p/xVP_k0kJ96W\nfunc Unpack5[A, B, C, D, E any](tuple Tuple5[A, B, C, D, E]) (A, B, C, D, E) {\n\treturn tuple.A, tuple.B, tuple.C, tuple.D, tuple.E\n}\n\n// Unpack6 returns values contained in a tuple.\n// Play: https://go.dev/play/p/xVP_k0kJ96W\nfunc Unpack6[A, B, C, D, E, F any](tuple Tuple6[A, B, C, D, E, F]) (A, B, C, D, E, F) {\n\treturn tuple.A, tuple.B, tuple.C, tuple.D, tuple.E, tuple.F\n}\n\n// Unpack7 returns values contained in a tuple.\n// Play: https://go.dev/play/p/xVP_k0kJ96W\nfunc Unpack7[A, B, C, D, E, F, G any](tuple Tuple7[A, B, C, D, E, F, G]) (A, B, C, D, E, F, G) {\n\treturn tuple.A, tuple.B, tuple.C, tuple.D, tuple.E, tuple.F, tuple.G\n}\n\n// Unpack8 returns values contained in a tuple.\n// Play: https://go.dev/play/p/xVP_k0kJ96W\nfunc Unpack8[A, B, C, D, E, F, G, H any](tuple Tuple8[A, B, C, D, E, F, G, H]) (A, B, C, D, E, F, G, H) {\n\treturn tuple.A, tuple.B, tuple.C, tuple.D, tuple.E, tuple.F, tuple.G, tuple.H\n}\n\n// Unpack9 returns values contained in a tuple.\n// Play: https://go.dev/play/p/xVP_k0kJ96W\nfunc Unpack9[A, B, C, D, E, F, G, H, I any](tuple Tuple9[A, B, C, D, E, F, G, H, I]) (A, B, C, D, E, F, G, H, I) {\n\treturn tuple.A, tuple.B, tuple.C, tuple.D, tuple.E, tuple.F, tuple.G, tuple.H, tuple.I\n}\n\n// Zip2 creates a slice of grouped elements, the first of which contains the first elements\n// of the given slices, the second of which contains the second elements of the given slices, and so on.\n// When collections are different sizes, the Tuple attributes are filled with zero value.\n// Play: https://go.dev/play/p/jujaA6GaJTp\nfunc Zip2[A, B any](a []A, b []B) []Tuple2[A, B] {\n\tsize := Max([]int{len(a), len(b)})\n\n\tresult := make([]Tuple2[A, B], size)\n\n\t// Perf: separate loops per input slice improve CPU cache locality (each loop reads\n\t// one contiguous memory region) and enable bounds-check elimination by the compiler.\n\tfor i := range a {\n\t\tresult[i].A = a[i]\n\t}\n\tfor i := range b {\n\t\tresult[i].B = b[i]\n\t}\n\n\treturn result\n}\n\n// Zip3 creates a slice of grouped elements, the first of which contains the first elements\n// of the given slices, the second of which contains the second elements of the given slices, and so on.\n// When collections are different sizes, the Tuple attributes are filled with zero value.\n// Play: https://go.dev/play/p/jujaA6GaJTp\nfunc Zip3[A, B, C any](a []A, b []B, c []C) []Tuple3[A, B, C] {\n\tsize := Max([]int{len(a), len(b), len(c)})\n\n\tresult := make([]Tuple3[A, B, C], size)\n\n\tfor i := range a {\n\t\tresult[i].A = a[i]\n\t}\n\tfor i := range b {\n\t\tresult[i].B = b[i]\n\t}\n\tfor i := range c {\n\t\tresult[i].C = c[i]\n\t}\n\n\treturn result\n}\n\n// Zip4 creates a slice of grouped elements, the first of which contains the first elements\n// of the given slices, the second of which contains the second elements of the given slices, and so on.\n// When collections are different sizes, the Tuple attributes are filled with zero value.\n// Play: https://go.dev/play/p/jujaA6GaJTp\nfunc Zip4[A, B, C, D any](a []A, b []B, c []C, d []D) []Tuple4[A, B, C, D] {\n\tsize := Max([]int{len(a), len(b), len(c), len(d)})\n\n\tresult := make([]Tuple4[A, B, C, D], size)\n\n\tfor i := range a {\n\t\tresult[i].A = a[i]\n\t}\n\tfor i := range b {\n\t\tresult[i].B = b[i]\n\t}\n\tfor i := range c {\n\t\tresult[i].C = c[i]\n\t}\n\tfor i := range d {\n\t\tresult[i].D = d[i]\n\t}\n\n\treturn result\n}\n\n// Zip5 creates a slice of grouped elements, the first of which contains the first elements\n// of the given slices, the second of which contains the second elements of the given slices, and so on.\n// When collections are different sizes, the Tuple attributes are filled with zero value.\n// Play: https://go.dev/play/p/jujaA6GaJTp\nfunc Zip5[A, B, C, D, E any](a []A, b []B, c []C, d []D, e []E) []Tuple5[A, B, C, D, E] {\n\tsize := Max([]int{len(a), len(b), len(c), len(d), len(e)})\n\n\tresult := make([]Tuple5[A, B, C, D, E], size)\n\n\tfor i := range a {\n\t\tresult[i].A = a[i]\n\t}\n\tfor i := range b {\n\t\tresult[i].B = b[i]\n\t}\n\tfor i := range c {\n\t\tresult[i].C = c[i]\n\t}\n\tfor i := range d {\n\t\tresult[i].D = d[i]\n\t}\n\tfor i := range e {\n\t\tresult[i].E = e[i]\n\t}\n\n\treturn result\n}\n\n// Zip6 creates a slice of grouped elements, the first of which contains the first elements\n// of the given slices, the second of which contains the second elements of the given slices, and so on.\n// When collections are different sizes, the Tuple attributes are filled with zero value.\n// Play: https://go.dev/play/p/jujaA6GaJTp\nfunc Zip6[A, B, C, D, E, F any](a []A, b []B, c []C, d []D, e []E, f []F) []Tuple6[A, B, C, D, E, F] {\n\tsize := Max([]int{len(a), len(b), len(c), len(d), len(e), len(f)})\n\n\tresult := make([]Tuple6[A, B, C, D, E, F], size)\n\n\tfor i := range a {\n\t\tresult[i].A = a[i]\n\t}\n\tfor i := range b {\n\t\tresult[i].B = b[i]\n\t}\n\tfor i := range c {\n\t\tresult[i].C = c[i]\n\t}\n\tfor i := range d {\n\t\tresult[i].D = d[i]\n\t}\n\tfor i := range e {\n\t\tresult[i].E = e[i]\n\t}\n\tfor i := range f {\n\t\tresult[i].F = f[i]\n\t}\n\n\treturn result\n}\n\n// Zip7 creates a slice of grouped elements, the first of which contains the first elements\n// of the given slices, the second of which contains the second elements of the given slices, and so on.\n// When collections are different sizes, the Tuple attributes are filled with zero value.\n// Play: https://go.dev/play/p/jujaA6GaJTp\nfunc Zip7[A, B, C, D, E, F, G any](a []A, b []B, c []C, d []D, e []E, f []F, g []G) []Tuple7[A, B, C, D, E, F, G] {\n\tsize := Max([]int{len(a), len(b), len(c), len(d), len(e), len(f), len(g)})\n\n\tresult := make([]Tuple7[A, B, C, D, E, F, G], size)\n\n\tfor i := range a {\n\t\tresult[i].A = a[i]\n\t}\n\tfor i := range b {\n\t\tresult[i].B = b[i]\n\t}\n\tfor i := range c {\n\t\tresult[i].C = c[i]\n\t}\n\tfor i := range d {\n\t\tresult[i].D = d[i]\n\t}\n\tfor i := range e {\n\t\tresult[i].E = e[i]\n\t}\n\tfor i := range f {\n\t\tresult[i].F = f[i]\n\t}\n\tfor i := range g {\n\t\tresult[i].G = g[i]\n\t}\n\n\treturn result\n}\n\n// Zip8 creates a slice of grouped elements, the first of which contains the first elements\n// of the given slices, the second of which contains the second elements of the given slices, and so on.\n// When collections are different sizes, the Tuple attributes are filled with zero value.\n// Play: https://go.dev/play/p/jujaA6GaJTp\nfunc Zip8[A, B, C, D, E, F, G, H any](a []A, b []B, c []C, d []D, e []E, f []F, g []G, h []H) []Tuple8[A, B, C, D, E, F, G, H] {\n\tsize := Max([]int{len(a), len(b), len(c), len(d), len(e), len(f), len(g), len(h)})\n\n\tresult := make([]Tuple8[A, B, C, D, E, F, G, H], size)\n\n\tfor i := range a {\n\t\tresult[i].A = a[i]\n\t}\n\tfor i := range b {\n\t\tresult[i].B = b[i]\n\t}\n\tfor i := range c {\n\t\tresult[i].C = c[i]\n\t}\n\tfor i := range d {\n\t\tresult[i].D = d[i]\n\t}\n\tfor i := range e {\n\t\tresult[i].E = e[i]\n\t}\n\tfor i := range f {\n\t\tresult[i].F = f[i]\n\t}\n\tfor i := range g {\n\t\tresult[i].G = g[i]\n\t}\n\tfor i := range h {\n\t\tresult[i].H = h[i]\n\t}\n\n\treturn result\n}\n\n// Zip9 creates a slice of grouped elements, the first of which contains the first elements\n// of the given slices, the second of which contains the second elements of the given slices, and so on.\n// When collections are different sizes, the Tuple attributes are filled with zero value.\n// Play: https://go.dev/play/p/jujaA6GaJTp\nfunc Zip9[A, B, C, D, E, F, G, H, I any](a []A, b []B, c []C, d []D, e []E, f []F, g []G, h []H, in []I) []Tuple9[A, B, C, D, E, F, G, H, I] {\n\tsize := Max([]int{len(a), len(b), len(c), len(d), len(e), len(f), len(g), len(h), len(in)})\n\n\tresult := make([]Tuple9[A, B, C, D, E, F, G, H, I], size)\n\n\tfor i := range a {\n\t\tresult[i].A = a[i]\n\t}\n\tfor i := range b {\n\t\tresult[i].B = b[i]\n\t}\n\tfor i := range c {\n\t\tresult[i].C = c[i]\n\t}\n\tfor i := range d {\n\t\tresult[i].D = d[i]\n\t}\n\tfor i := range e {\n\t\tresult[i].E = e[i]\n\t}\n\tfor i := range f {\n\t\tresult[i].F = f[i]\n\t}\n\tfor i := range g {\n\t\tresult[i].G = g[i]\n\t}\n\tfor i := range h {\n\t\tresult[i].H = h[i]\n\t}\n\tfor i := range in {\n\t\tresult[i].I = in[i]\n\t}\n\n\treturn result\n}\n\n// ZipBy2 creates a slice of transformed elements, the first of which contains the first elements\n// of the given slices, the second of which contains the second elements of the given slices, and so on.\n// When collections are different sizes, the Tuple attributes are filled with zero value.\n// Play: https://go.dev/play/p/wlHur6yO8rR\nfunc ZipBy2[A, B, Out any](a []A, b []B, iteratee func(a A, b B) Out) []Out {\n\tsize := uint(Max([]int{len(a), len(b)}))\n\n\tresult := make([]Out, size)\n\n\tfor index := uint(0); index < size; index++ {\n\t\tresult[index] = iteratee(\n\t\t\tNthOrEmpty(a, index),\n\t\t\tNthOrEmpty(b, index),\n\t\t)\n\t}\n\n\treturn result\n}\n\n// ZipBy3 creates a slice of transformed elements, the first of which contains the first elements\n// of the given slices, the second of which contains the second elements of the given slices, and so on.\n// When collections are different sizes, the Tuple attributes are filled with zero value.\n// Play: https://go.dev/play/p/j9maveOnSQX\nfunc ZipBy3[A, B, C, Out any](a []A, b []B, c []C, iteratee func(a A, b B, c C) Out) []Out {\n\tsize := uint(Max([]int{len(a), len(b), len(c)}))\n\n\tresult := make([]Out, size)\n\n\tfor index := uint(0); index < size; index++ {\n\t\tresult[index] = iteratee(\n\t\t\tNthOrEmpty(a, index),\n\t\t\tNthOrEmpty(b, index),\n\t\t\tNthOrEmpty(c, index),\n\t\t)\n\t}\n\n\treturn result\n}\n\n// ZipBy4 creates a slice of transformed elements, the first of which contains the first elements\n// of the given slices, the second of which contains the second elements of the given slices, and so on.\n// When collections are different sizes, the Tuple attributes are filled with zero value.\n// Play: https://go.dev/play/p/Y1eF2Ke0Ayz\nfunc ZipBy4[A, B, C, D, Out any](a []A, b []B, c []C, d []D, iteratee func(a A, b B, c C, d D) Out) []Out {\n\tsize := uint(Max([]int{len(a), len(b), len(c), len(d)}))\n\n\tresult := make([]Out, size)\n\n\tfor index := uint(0); index < size; index++ {\n\t\tresult[index] = iteratee(\n\t\t\tNthOrEmpty(a, index),\n\t\t\tNthOrEmpty(b, index),\n\t\t\tNthOrEmpty(c, index),\n\t\t\tNthOrEmpty(d, index),\n\t\t)\n\t}\n\n\treturn result\n}\n\n// ZipBy5 creates a slice of transformed elements, the first of which contains the first elements\n// of the given slices, the second of which contains the second elements of the given slices, and so on.\n// When collections are different sizes, the Tuple attributes are filled with zero value.\n// Play: https://go.dev/play/p/SLynyalh5Oa\nfunc ZipBy5[A, B, C, D, E, Out any](a []A, b []B, c []C, d []D, e []E, iteratee func(a A, b B, c C, d D, e E) Out) []Out {\n\tsize := uint(Max([]int{len(a), len(b), len(c), len(d), len(e)}))\n\n\tresult := make([]Out, size)\n\n\tfor index := uint(0); index < size; index++ {\n\t\tresult[index] = iteratee(\n\t\t\tNthOrEmpty(a, index),\n\t\t\tNthOrEmpty(b, index),\n\t\t\tNthOrEmpty(c, index),\n\t\t\tNthOrEmpty(d, index),\n\t\t\tNthOrEmpty(e, index),\n\t\t)\n\t}\n\n\treturn result\n}\n\n// ZipBy6 creates a slice of transformed elements, the first of which contains the first elements\n// of the given slices, the second of which contains the second elements of the given slices, and so on.\n// When collections are different sizes, the Tuple attributes are filled with zero value.\n// Play: https://go.dev/play/p/IK6KVgw9e-S\nfunc ZipBy6[A, B, C, D, E, F, Out any](a []A, b []B, c []C, d []D, e []E, f []F, iteratee func(a A, b B, c C, d D, e E, f F) Out) []Out {\n\tsize := uint(Max([]int{len(a), len(b), len(c), len(d), len(e), len(f)}))\n\n\tresult := make([]Out, size)\n\n\tfor index := uint(0); index < size; index++ {\n\t\tresult[index] = iteratee(\n\t\t\tNthOrEmpty(a, index),\n\t\t\tNthOrEmpty(b, index),\n\t\t\tNthOrEmpty(c, index),\n\t\t\tNthOrEmpty(d, index),\n\t\t\tNthOrEmpty(e, index),\n\t\t\tNthOrEmpty(f, index),\n\t\t)\n\t}\n\n\treturn result\n}\n\n// ZipBy7 creates a slice of transformed elements, the first of which contains the first elements\n// of the given slices, the second of which contains the second elements of the given slices, and so on.\n// When collections are different sizes, the Tuple attributes are filled with zero value.\n// Play: https://go.dev/play/p/4uW6a2vXh8w\nfunc ZipBy7[A, B, C, D, E, F, G, Out any](a []A, b []B, c []C, d []D, e []E, f []F, g []G, iteratee func(a A, b B, c C, d D, e E, f F, g G) Out) []Out {\n\tsize := uint(Max([]int{len(a), len(b), len(c), len(d), len(e), len(f), len(g)}))\n\n\tresult := make([]Out, size)\n\n\tfor index := uint(0); index < size; index++ {\n\t\tresult[index] = iteratee(\n\t\t\tNthOrEmpty(a, index),\n\t\t\tNthOrEmpty(b, index),\n\t\t\tNthOrEmpty(c, index),\n\t\t\tNthOrEmpty(d, index),\n\t\t\tNthOrEmpty(e, index),\n\t\t\tNthOrEmpty(f, index),\n\t\t\tNthOrEmpty(g, index),\n\t\t)\n\t}\n\n\treturn result\n}\n\n// ZipBy8 creates a slice of transformed elements, the first of which contains the first elements\n// of the given slices, the second of which contains the second elements of the given slices, and so on.\n// When collections are different sizes, the Tuple attributes are filled with zero value.\n// Play: https://go.dev/play/p/tk8xW7XzY4v\nfunc ZipBy8[A, B, C, D, E, F, G, H, Out any](a []A, b []B, c []C, d []D, e []E, f []F, g []G, h []H, iteratee func(a A, b B, c C, d D, e E, f F, g G, h H) Out) []Out {\n\tsize := uint(Max([]int{len(a), len(b), len(c), len(d), len(e), len(f), len(g), len(h)}))\n\n\tresult := make([]Out, size)\n\n\tfor index := uint(0); index < size; index++ {\n\t\tresult[index] = iteratee(\n\t\t\tNthOrEmpty(a, index),\n\t\t\tNthOrEmpty(b, index),\n\t\t\tNthOrEmpty(c, index),\n\t\t\tNthOrEmpty(d, index),\n\t\t\tNthOrEmpty(e, index),\n\t\t\tNthOrEmpty(f, index),\n\t\t\tNthOrEmpty(g, index),\n\t\t\tNthOrEmpty(h, index),\n\t\t)\n\t}\n\n\treturn result\n}\n\n// ZipBy9 creates a slice of transformed elements, the first of which contains the first elements\n// of the given slices, the second of which contains the second elements of the given slices, and so on.\n// When collections are different sizes, the Tuple attributes are filled with zero value.\n// Play: https://go.dev/play/p/VGqjDmQ9YqX\nfunc ZipBy9[A, B, C, D, E, F, G, H, I, Out any](a []A, b []B, c []C, d []D, e []E, f []F, g []G, h []H, i []I, iteratee func(a A, b B, c C, d D, e E, f F, g G, h H, i I) Out) []Out {\n\tsize := uint(Max([]int{len(a), len(b), len(c), len(d), len(e), len(f), len(g), len(h), len(i)}))\n\n\tresult := make([]Out, size)\n\n\tfor index := uint(0); index < size; index++ {\n\t\tresult[index] = iteratee(\n\t\t\tNthOrEmpty(a, index),\n\t\t\tNthOrEmpty(b, index),\n\t\t\tNthOrEmpty(c, index),\n\t\t\tNthOrEmpty(d, index),\n\t\t\tNthOrEmpty(e, index),\n\t\t\tNthOrEmpty(f, index),\n\t\t\tNthOrEmpty(g, index),\n\t\t\tNthOrEmpty(h, index),\n\t\t\tNthOrEmpty(i, index),\n\t\t)\n\t}\n\n\treturn result\n}\n\n// ZipByErr2 creates a slice of transformed elements, the first of which contains the first elements\n// of the given slices, the second of which contains the second elements of the given slices, and so on.\n// When collections are different sizes, the Tuple attributes are filled with zero value.\n// It returns the first error returned by the iteratee.\nfunc ZipByErr2[A, B, Out any](a []A, b []B, iteratee func(a A, b B) (Out, error)) ([]Out, error) {\n\tsize := uint(Max([]int{len(a), len(b)}))\n\tresult := make([]Out, size)\n\n\tfor index := uint(0); index < size; index++ {\n\t\tr, err := iteratee(\n\t\t\tNthOrEmpty(a, index),\n\t\t\tNthOrEmpty(b, index),\n\t\t)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tresult[index] = r\n\t}\n\n\treturn result, nil\n}\n\n// ZipByErr3 creates a slice of transformed elements, the first of which contains the first elements\n// of the given slices, the second of which contains the second elements of the given slices, and so on.\n// When collections are different sizes, the Tuple attributes are filled with zero value.\n// It returns the first error returned by the iteratee.\nfunc ZipByErr3[A, B, C, Out any](a []A, b []B, c []C, iteratee func(a A, b B, c C) (Out, error)) ([]Out, error) {\n\tsize := uint(Max([]int{len(a), len(b), len(c)}))\n\tresult := make([]Out, size)\n\n\tfor index := uint(0); index < size; index++ {\n\t\tr, err := iteratee(\n\t\t\tNthOrEmpty(a, index),\n\t\t\tNthOrEmpty(b, index),\n\t\t\tNthOrEmpty(c, index),\n\t\t)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tresult[index] = r\n\t}\n\n\treturn result, nil\n}\n\n// ZipByErr4 creates a slice of transformed elements, the first of which contains the first elements\n// of the given slices, the second of which contains the second elements of the given slices, and so on.\n// When collections are different sizes, the Tuple attributes are filled with zero value.\n// It returns the first error returned by the iteratee.\nfunc ZipByErr4[A, B, C, D, Out any](a []A, b []B, c []C, d []D, iteratee func(a A, b B, c C, d D) (Out, error)) ([]Out, error) {\n\tsize := uint(Max([]int{len(a), len(b), len(c), len(d)}))\n\tresult := make([]Out, size)\n\n\tfor index := uint(0); index < size; index++ {\n\t\tr, err := iteratee(\n\t\t\tNthOrEmpty(a, index),\n\t\t\tNthOrEmpty(b, index),\n\t\t\tNthOrEmpty(c, index),\n\t\t\tNthOrEmpty(d, index),\n\t\t)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tresult[index] = r\n\t}\n\n\treturn result, nil\n}\n\n// ZipByErr5 creates a slice of transformed elements, the first of which contains the first elements\n// of the given slices, the second of which contains the second elements of the given slices, and so on.\n// When collections are different sizes, the Tuple attributes are filled with zero value.\n// It returns the first error returned by the iteratee.\nfunc ZipByErr5[A, B, C, D, E, Out any](a []A, b []B, c []C, d []D, e []E, iteratee func(a A, b B, c C, d D, e E) (Out, error)) ([]Out, error) {\n\tsize := uint(Max([]int{len(a), len(b), len(c), len(d), len(e)}))\n\tresult := make([]Out, size)\n\n\tfor index := uint(0); index < size; index++ {\n\t\tr, err := iteratee(\n\t\t\tNthOrEmpty(a, index),\n\t\t\tNthOrEmpty(b, index),\n\t\t\tNthOrEmpty(c, index),\n\t\t\tNthOrEmpty(d, index),\n\t\t\tNthOrEmpty(e, index),\n\t\t)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tresult[index] = r\n\t}\n\n\treturn result, nil\n}\n\n// ZipByErr6 creates a slice of transformed elements, the first of which contains the first elements\n// of the given slices, the second of which contains the second elements of the given slices, and so on.\n// When collections are different sizes, the Tuple attributes are filled with zero value.\n// It returns the first error returned by the iteratee.\nfunc ZipByErr6[A, B, C, D, E, F, Out any](a []A, b []B, c []C, d []D, e []E, f []F, iteratee func(a A, b B, c C, d D, e E, f F) (Out, error)) ([]Out, error) {\n\tsize := uint(Max([]int{len(a), len(b), len(c), len(d), len(e), len(f)}))\n\tresult := make([]Out, size)\n\n\tfor index := uint(0); index < size; index++ {\n\t\tr, err := iteratee(\n\t\t\tNthOrEmpty(a, index),\n\t\t\tNthOrEmpty(b, index),\n\t\t\tNthOrEmpty(c, index),\n\t\t\tNthOrEmpty(d, index),\n\t\t\tNthOrEmpty(e, index),\n\t\t\tNthOrEmpty(f, index),\n\t\t)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tresult[index] = r\n\t}\n\n\treturn result, nil\n}\n\n// ZipByErr7 creates a slice of transformed elements, the first of which contains the first elements\n// of the given slices, the second of which contains the second elements of the given slices, and so on.\n// When collections are different sizes, the Tuple attributes are filled with zero value.\n// It returns the first error returned by the iteratee.\nfunc ZipByErr7[A, B, C, D, E, F, G, Out any](a []A, b []B, c []C, d []D, e []E, f []F, g []G, iteratee func(a A, b B, c C, d D, e E, f F, g G) (Out, error)) ([]Out, error) {\n\tsize := uint(Max([]int{len(a), len(b), len(c), len(d), len(e), len(f), len(g)}))\n\tresult := make([]Out, size)\n\n\tfor index := uint(0); index < size; index++ {\n\t\tr, err := iteratee(\n\t\t\tNthOrEmpty(a, index),\n\t\t\tNthOrEmpty(b, index),\n\t\t\tNthOrEmpty(c, index),\n\t\t\tNthOrEmpty(d, index),\n\t\t\tNthOrEmpty(e, index),\n\t\t\tNthOrEmpty(f, index),\n\t\t\tNthOrEmpty(g, index),\n\t\t)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tresult[index] = r\n\t}\n\n\treturn result, nil\n}\n\n// ZipByErr8 creates a slice of transformed elements, the first of which contains the first elements\n// of the given slices, the second of which contains the second elements of the given slices, and so on.\n// When collections are different sizes, the Tuple attributes are filled with zero value.\n// It returns the first error returned by the iteratee.\nfunc ZipByErr8[A, B, C, D, E, F, G, H, Out any](a []A, b []B, c []C, d []D, e []E, f []F, g []G, h []H, iteratee func(a A, b B, c C, d D, e E, f F, g G, h H) (Out, error)) ([]Out, error) {\n\tsize := uint(Max([]int{len(a), len(b), len(c), len(d), len(e), len(f), len(g), len(h)}))\n\tresult := make([]Out, size)\n\n\tfor index := uint(0); index < size; index++ {\n\t\tr, err := iteratee(\n\t\t\tNthOrEmpty(a, index),\n\t\t\tNthOrEmpty(b, index),\n\t\t\tNthOrEmpty(c, index),\n\t\t\tNthOrEmpty(d, index),\n\t\t\tNthOrEmpty(e, index),\n\t\t\tNthOrEmpty(f, index),\n\t\t\tNthOrEmpty(g, index),\n\t\t\tNthOrEmpty(h, index),\n\t\t)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tresult[index] = r\n\t}\n\n\treturn result, nil\n}\n\n// ZipByErr9 creates a slice of transformed elements, the first of which contains the first elements\n// of the given slices, the second of which contains the second elements of the given slices, and so on.\n// When collections are different sizes, the Tuple attributes are filled with zero value.\n// It returns the first error returned by the iteratee.\nfunc ZipByErr9[A, B, C, D, E, F, G, H, I, Out any](a []A, b []B, c []C, d []D, e []E, f []F, g []G, h []H, i []I, iteratee func(a A, b B, c C, d D, e E, f F, g G, h H, i I) (Out, error)) ([]Out, error) {\n\tsize := uint(Max([]int{len(a), len(b), len(c), len(d), len(e), len(f), len(g), len(h), len(i)}))\n\tresult := make([]Out, size)\n\n\tfor index := uint(0); index < size; index++ {\n\t\tr, err := iteratee(\n\t\t\tNthOrEmpty(a, index),\n\t\t\tNthOrEmpty(b, index),\n\t\t\tNthOrEmpty(c, index),\n\t\t\tNthOrEmpty(d, index),\n\t\t\tNthOrEmpty(e, index),\n\t\t\tNthOrEmpty(f, index),\n\t\t\tNthOrEmpty(g, index),\n\t\t\tNthOrEmpty(h, index),\n\t\t\tNthOrEmpty(i, index),\n\t\t)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tresult[index] = r\n\t}\n\n\treturn result, nil\n}\n\n// Unzip2 accepts a slice of grouped elements and creates a slice regrouping the elements\n// to their pre-zip configuration.\n// Play: https://go.dev/play/p/K-vG9tyD3Kf\nfunc Unzip2[A, B any](tuples []Tuple2[A, B]) ([]A, []B) {\n\tsize := len(tuples)\n\tr1 := make([]A, 0, size)\n\tr2 := make([]B, 0, size)\n\n\tfor i := range tuples {\n\t\tr1 = append(r1, tuples[i].A)\n\t\tr2 = append(r2, tuples[i].B)\n\t}\n\n\treturn r1, r2\n}\n\n// Unzip3 accepts a slice of grouped elements and creates a slice regrouping the elements\n// to their pre-zip configuration.\n// Play: https://go.dev/play/p/ciHugugvaAW\nfunc Unzip3[A, B, C any](tuples []Tuple3[A, B, C]) ([]A, []B, []C) {\n\tsize := len(tuples)\n\tr1 := make([]A, 0, size)\n\tr2 := make([]B, 0, size)\n\tr3 := make([]C, 0, size)\n\n\tfor i := range tuples {\n\t\tr1 = append(r1, tuples[i].A)\n\t\tr2 = append(r2, tuples[i].B)\n\t\tr3 = append(r3, tuples[i].C)\n\t}\n\n\treturn r1, r2, r3\n}\n\n// Unzip4 accepts a slice of grouped elements and creates a slice regrouping the elements\n// to their pre-zip configuration.\n// Play: https://go.dev/play/p/ciHugugvaAW\nfunc Unzip4[A, B, C, D any](tuples []Tuple4[A, B, C, D]) ([]A, []B, []C, []D) {\n\tsize := len(tuples)\n\tr1 := make([]A, 0, size)\n\tr2 := make([]B, 0, size)\n\tr3 := make([]C, 0, size)\n\tr4 := make([]D, 0, size)\n\n\tfor i := range tuples {\n\t\tr1 = append(r1, tuples[i].A)\n\t\tr2 = append(r2, tuples[i].B)\n\t\tr3 = append(r3, tuples[i].C)\n\t\tr4 = append(r4, tuples[i].D)\n\t}\n\n\treturn r1, r2, r3, r4\n}\n\n// Unzip5 accepts a slice of grouped elements and creates a slice regrouping the elements\n// to their pre-zip configuration.\n// Play: https://go.dev/play/p/ciHugugvaAW\nfunc Unzip5[A, B, C, D, E any](tuples []Tuple5[A, B, C, D, E]) ([]A, []B, []C, []D, []E) {\n\tsize := len(tuples)\n\tr1 := make([]A, 0, size)\n\tr2 := make([]B, 0, size)\n\tr3 := make([]C, 0, size)\n\tr4 := make([]D, 0, size)\n\tr5 := make([]E, 0, size)\n\n\tfor i := range tuples {\n\t\tr1 = append(r1, tuples[i].A)\n\t\tr2 = append(r2, tuples[i].B)\n\t\tr3 = append(r3, tuples[i].C)\n\t\tr4 = append(r4, tuples[i].D)\n\t\tr5 = append(r5, tuples[i].E)\n\t}\n\n\treturn r1, r2, r3, r4, r5\n}\n\n// Unzip6 accepts a slice of grouped elements and creates a slice regrouping the elements\n// to their pre-zip configuration.\n// Play: https://go.dev/play/p/ciHugugvaAW\nfunc Unzip6[A, B, C, D, E, F any](tuples []Tuple6[A, B, C, D, E, F]) ([]A, []B, []C, []D, []E, []F) {\n\tsize := len(tuples)\n\tr1 := make([]A, 0, size)\n\tr2 := make([]B, 0, size)\n\tr3 := make([]C, 0, size)\n\tr4 := make([]D, 0, size)\n\tr5 := make([]E, 0, size)\n\tr6 := make([]F, 0, size)\n\n\tfor i := range tuples {\n\t\tr1 = append(r1, tuples[i].A)\n\t\tr2 = append(r2, tuples[i].B)\n\t\tr3 = append(r3, tuples[i].C)\n\t\tr4 = append(r4, tuples[i].D)\n\t\tr5 = append(r5, tuples[i].E)\n\t\tr6 = append(r6, tuples[i].F)\n\t}\n\n\treturn r1, r2, r3, r4, r5, r6\n}\n\n// Unzip7 accepts a slice of grouped elements and creates a slice regrouping the elements\n// to their pre-zip configuration.\n// Play: https://go.dev/play/p/ciHugugvaAW\nfunc Unzip7[A, B, C, D, E, F, G any](tuples []Tuple7[A, B, C, D, E, F, G]) ([]A, []B, []C, []D, []E, []F, []G) {\n\tsize := len(tuples)\n\tr1 := make([]A, 0, size)\n\tr2 := make([]B, 0, size)\n\tr3 := make([]C, 0, size)\n\tr4 := make([]D, 0, size)\n\tr5 := make([]E, 0, size)\n\tr6 := make([]F, 0, size)\n\tr7 := make([]G, 0, size)\n\n\tfor i := range tuples {\n\t\tr1 = append(r1, tuples[i].A)\n\t\tr2 = append(r2, tuples[i].B)\n\t\tr3 = append(r3, tuples[i].C)\n\t\tr4 = append(r4, tuples[i].D)\n\t\tr5 = append(r5, tuples[i].E)\n\t\tr6 = append(r6, tuples[i].F)\n\t\tr7 = append(r7, tuples[i].G)\n\t}\n\n\treturn r1, r2, r3, r4, r5, r6, r7\n}\n\n// Unzip8 accepts a slice of grouped elements and creates a slice regrouping the elements\n// to their pre-zip configuration.\n// Play: https://go.dev/play/p/ciHugugvaAW\nfunc Unzip8[A, B, C, D, E, F, G, H any](tuples []Tuple8[A, B, C, D, E, F, G, H]) ([]A, []B, []C, []D, []E, []F, []G, []H) {\n\tsize := len(tuples)\n\tr1 := make([]A, 0, size)\n\tr2 := make([]B, 0, size)\n\tr3 := make([]C, 0, size)\n\tr4 := make([]D, 0, size)\n\tr5 := make([]E, 0, size)\n\tr6 := make([]F, 0, size)\n\tr7 := make([]G, 0, size)\n\tr8 := make([]H, 0, size)\n\n\tfor i := range tuples {\n\t\tr1 = append(r1, tuples[i].A)\n\t\tr2 = append(r2, tuples[i].B)\n\t\tr3 = append(r3, tuples[i].C)\n\t\tr4 = append(r4, tuples[i].D)\n\t\tr5 = append(r5, tuples[i].E)\n\t\tr6 = append(r6, tuples[i].F)\n\t\tr7 = append(r7, tuples[i].G)\n\t\tr8 = append(r8, tuples[i].H)\n\t}\n\n\treturn r1, r2, r3, r4, r5, r6, r7, r8\n}\n\n// Unzip9 accepts a slice of grouped elements and creates a slice regrouping the elements\n// to their pre-zip configuration.\n// Play: https://go.dev/play/p/ciHugugvaAW\nfunc Unzip9[A, B, C, D, E, F, G, H, I any](tuples []Tuple9[A, B, C, D, E, F, G, H, I]) ([]A, []B, []C, []D, []E, []F, []G, []H, []I) {\n\tsize := len(tuples)\n\tr1 := make([]A, 0, size)\n\tr2 := make([]B, 0, size)\n\tr3 := make([]C, 0, size)\n\tr4 := make([]D, 0, size)\n\tr5 := make([]E, 0, size)\n\tr6 := make([]F, 0, size)\n\tr7 := make([]G, 0, size)\n\tr8 := make([]H, 0, size)\n\tr9 := make([]I, 0, size)\n\n\tfor i := range tuples {\n\t\tr1 = append(r1, tuples[i].A)\n\t\tr2 = append(r2, tuples[i].B)\n\t\tr3 = append(r3, tuples[i].C)\n\t\tr4 = append(r4, tuples[i].D)\n\t\tr5 = append(r5, tuples[i].E)\n\t\tr6 = append(r6, tuples[i].F)\n\t\tr7 = append(r7, tuples[i].G)\n\t\tr8 = append(r8, tuples[i].H)\n\t\tr9 = append(r9, tuples[i].I)\n\t}\n\n\treturn r1, r2, r3, r4, r5, r6, r7, r8, r9\n}\n\n// UnzipBy2 iterates over a collection and creates a slice regrouping the elements\n// to their pre-zip configuration.\n// Play: https://go.dev/play/p/tN8yqaRZz0r\nfunc UnzipBy2[In, A, B any](items []In, iteratee func(In) (a A, b B)) ([]A, []B) {\n\tsize := len(items)\n\tr1 := make([]A, 0, size)\n\tr2 := make([]B, 0, size)\n\n\tfor i := range items {\n\t\ta, b := iteratee(items[i])\n\t\tr1 = append(r1, a)\n\t\tr2 = append(r2, b)\n\t}\n\n\treturn r1, r2\n}\n\n// UnzipBy3 iterates over a collection and creates a slice regrouping the elements\n// to their pre-zip configuration.\n// Play: https://go.dev/play/p/36ITO2DlQq1\nfunc UnzipBy3[In, A, B, C any](items []In, iteratee func(In) (a A, b B, c C)) ([]A, []B, []C) {\n\tsize := len(items)\n\tr1 := make([]A, 0, size)\n\tr2 := make([]B, 0, size)\n\tr3 := make([]C, 0, size)\n\n\tfor i := range items {\n\t\ta, b, c := iteratee(items[i])\n\t\tr1 = append(r1, a)\n\t\tr2 = append(r2, b)\n\t\tr3 = append(r3, c)\n\t}\n\n\treturn r1, r2, r3\n}\n\n// UnzipBy4 iterates over a collection and creates a slice regrouping the elements\n// to their pre-zip configuration.\n// Play: https://go.dev/play/p/zJ6qY1dD1rL\nfunc UnzipBy4[In, A, B, C, D any](items []In, iteratee func(In) (a A, b B, c C, d D)) ([]A, []B, []C, []D) {\n\tsize := len(items)\n\tr1 := make([]A, 0, size)\n\tr2 := make([]B, 0, size)\n\tr3 := make([]C, 0, size)\n\tr4 := make([]D, 0, size)\n\n\tfor i := range items {\n\t\ta, b, c, d := iteratee(items[i])\n\t\tr1 = append(r1, a)\n\t\tr2 = append(r2, b)\n\t\tr3 = append(r3, c)\n\t\tr4 = append(r4, d)\n\t}\n\n\treturn r1, r2, r3, r4\n}\n\n// UnzipBy5 iterates over a collection and creates a slice regrouping the elements\n// to their pre-zip configuration.\n// Play: https://go.dev/play/p/3f7jKkV9xZt\nfunc UnzipBy5[In, A, B, C, D, E any](items []In, iteratee func(In) (a A, b B, c C, d D, e E)) ([]A, []B, []C, []D, []E) {\n\tsize := len(items)\n\tr1 := make([]A, 0, size)\n\tr2 := make([]B, 0, size)\n\tr3 := make([]C, 0, size)\n\tr4 := make([]D, 0, size)\n\tr5 := make([]E, 0, size)\n\n\tfor i := range items {\n\t\ta, b, c, d, e := iteratee(items[i])\n\t\tr1 = append(r1, a)\n\t\tr2 = append(r2, b)\n\t\tr3 = append(r3, c)\n\t\tr4 = append(r4, d)\n\t\tr5 = append(r5, e)\n\t}\n\n\treturn r1, r2, r3, r4, r5\n}\n\n// UnzipBy6 iterates over a collection and creates a slice regrouping the elements\n// to their pre-zip configuration.\n// Play: https://go.dev/play/p/8Y1b7tKu2pL\nfunc UnzipBy6[In, A, B, C, D, E, F any](items []In, iteratee func(In) (a A, b B, c C, d D, e E, f F)) ([]A, []B, []C, []D, []E, []F) {\n\tsize := len(items)\n\tr1 := make([]A, 0, size)\n\tr2 := make([]B, 0, size)\n\tr3 := make([]C, 0, size)\n\tr4 := make([]D, 0, size)\n\tr5 := make([]E, 0, size)\n\tr6 := make([]F, 0, size)\n\n\tfor i := range items {\n\t\ta, b, c, d, e, f := iteratee(items[i])\n\t\tr1 = append(r1, a)\n\t\tr2 = append(r2, b)\n\t\tr3 = append(r3, c)\n\t\tr4 = append(r4, d)\n\t\tr5 = append(r5, e)\n\t\tr6 = append(r6, f)\n\t}\n\n\treturn r1, r2, r3, r4, r5, r6\n}\n\n// UnzipBy7 iterates over a collection and creates a slice regrouping the elements\n// to their pre-zip configuration.\n// Play: https://go.dev/play/p/7j1kLmVn3pM\nfunc UnzipBy7[In, A, B, C, D, E, F, G any](items []In, iteratee func(In) (a A, b B, c C, d D, e E, f F, g G)) ([]A, []B, []C, []D, []E, []F, []G) {\n\tsize := len(items)\n\tr1 := make([]A, 0, size)\n\tr2 := make([]B, 0, size)\n\tr3 := make([]C, 0, size)\n\tr4 := make([]D, 0, size)\n\tr5 := make([]E, 0, size)\n\tr6 := make([]F, 0, size)\n\tr7 := make([]G, 0, size)\n\n\tfor i := range items {\n\t\ta, b, c, d, e, f, g := iteratee(items[i])\n\t\tr1 = append(r1, a)\n\t\tr2 = append(r2, b)\n\t\tr3 = append(r3, c)\n\t\tr4 = append(r4, d)\n\t\tr5 = append(r5, e)\n\t\tr6 = append(r6, f)\n\t\tr7 = append(r7, g)\n\t}\n\n\treturn r1, r2, r3, r4, r5, r6, r7\n}\n\n// UnzipBy8 iterates over a collection and creates a slice regrouping the elements\n// to their pre-zip configuration.\n// Play: https://go.dev/play/p/1n2k3L4m5N6\nfunc UnzipBy8[In, A, B, C, D, E, F, G, H any](items []In, iteratee func(In) (a A, b B, c C, d D, e E, f F, g G, h H)) ([]A, []B, []C, []D, []E, []F, []G, []H) {\n\tsize := len(items)\n\tr1 := make([]A, 0, size)\n\tr2 := make([]B, 0, size)\n\tr3 := make([]C, 0, size)\n\tr4 := make([]D, 0, size)\n\tr5 := make([]E, 0, size)\n\tr6 := make([]F, 0, size)\n\tr7 := make([]G, 0, size)\n\tr8 := make([]H, 0, size)\n\n\tfor i := range items {\n\t\ta, b, c, d, e, f, g, h := iteratee(items[i])\n\t\tr1 = append(r1, a)\n\t\tr2 = append(r2, b)\n\t\tr3 = append(r3, c)\n\t\tr4 = append(r4, d)\n\t\tr5 = append(r5, e)\n\t\tr6 = append(r6, f)\n\t\tr7 = append(r7, g)\n\t\tr8 = append(r8, h)\n\t}\n\n\treturn r1, r2, r3, r4, r5, r6, r7, r8\n}\n\n// UnzipBy9 iterates over a collection and creates a slice regrouping the elements\n// to their pre-zip configuration.\n// Play: https://go.dev/play/p/7o8p9q0r1s2\nfunc UnzipBy9[In, A, B, C, D, E, F, G, H, I any](items []In, iteratee func(In) (a A, b B, c C, d D, e E, f F, g G, h H, i I)) ([]A, []B, []C, []D, []E, []F, []G, []H, []I) {\n\tsize := len(items)\n\tr1 := make([]A, 0, size)\n\tr2 := make([]B, 0, size)\n\tr3 := make([]C, 0, size)\n\tr4 := make([]D, 0, size)\n\tr5 := make([]E, 0, size)\n\tr6 := make([]F, 0, size)\n\tr7 := make([]G, 0, size)\n\tr8 := make([]H, 0, size)\n\tr9 := make([]I, 0, size)\n\n\tfor i := range items {\n\t\ta, b, c, d, e, f, g, h, i := iteratee(items[i])\n\t\tr1 = append(r1, a)\n\t\tr2 = append(r2, b)\n\t\tr3 = append(r3, c)\n\t\tr4 = append(r4, d)\n\t\tr5 = append(r5, e)\n\t\tr6 = append(r6, f)\n\t\tr7 = append(r7, g)\n\t\tr8 = append(r8, h)\n\t\tr9 = append(r9, i)\n\t}\n\n\treturn r1, r2, r3, r4, r5, r6, r7, r8, r9\n}\n\n// UnzipByErr2 iterates over a collection and creates a slice regrouping the elements\n// to their pre-zip configuration.\n// It returns the first error returned by the iteratee.\n// Play: https://go.dev/play/p/G2pyXQa1SUD\nfunc UnzipByErr2[In, A, B any](items []In, iteratee func(In) (a A, b B, err error)) ([]A, []B, error) {\n\tsize := len(items)\n\tr1 := make([]A, 0, size)\n\tr2 := make([]B, 0, size)\n\n\tfor i := range items {\n\t\ta, b, err := iteratee(items[i])\n\t\tif err != nil {\n\t\t\treturn nil, nil, err\n\t\t}\n\t\tr1 = append(r1, a)\n\t\tr2 = append(r2, b)\n\t}\n\n\treturn r1, r2, nil\n}\n\n// UnzipByErr3 iterates over a collection and creates a slice regrouping the elements\n// to their pre-zip configuration.\n// It returns the first error returned by the iteratee.\nfunc UnzipByErr3[In, A, B, C any](items []In, iteratee func(In) (a A, b B, c C, err error)) ([]A, []B, []C, error) {\n\tsize := len(items)\n\tr1 := make([]A, 0, size)\n\tr2 := make([]B, 0, size)\n\tr3 := make([]C, 0, size)\n\n\tfor i := range items {\n\t\ta, b, c, err := iteratee(items[i])\n\t\tif err != nil {\n\t\t\treturn nil, nil, nil, err\n\t\t}\n\t\tr1 = append(r1, a)\n\t\tr2 = append(r2, b)\n\t\tr3 = append(r3, c)\n\t}\n\n\treturn r1, r2, r3, nil\n}\n\n// UnzipByErr4 iterates over a collection and creates a slice regrouping the elements\n// to their pre-zip configuration.\n// It returns the first error returned by the iteratee.\nfunc UnzipByErr4[In, A, B, C, D any](items []In, iteratee func(In) (a A, b B, c C, d D, err error)) ([]A, []B, []C, []D, error) {\n\tsize := len(items)\n\tr1 := make([]A, 0, size)\n\tr2 := make([]B, 0, size)\n\tr3 := make([]C, 0, size)\n\tr4 := make([]D, 0, size)\n\n\tfor i := range items {\n\t\ta, b, c, d, err := iteratee(items[i])\n\t\tif err != nil {\n\t\t\treturn nil, nil, nil, nil, err\n\t\t}\n\t\tr1 = append(r1, a)\n\t\tr2 = append(r2, b)\n\t\tr3 = append(r3, c)\n\t\tr4 = append(r4, d)\n\t}\n\n\treturn r1, r2, r3, r4, nil\n}\n\n// UnzipByErr5 iterates over a collection and creates a slice regrouping the elements\n// to their pre-zip configuration.\n// It returns the first error returned by the iteratee.\nfunc UnzipByErr5[In, A, B, C, D, E any](items []In, iteratee func(In) (a A, b B, c C, d D, e E, err error)) ([]A, []B, []C, []D, []E, error) {\n\tsize := len(items)\n\tr1 := make([]A, 0, size)\n\tr2 := make([]B, 0, size)\n\tr3 := make([]C, 0, size)\n\tr4 := make([]D, 0, size)\n\tr5 := make([]E, 0, size)\n\n\tfor i := range items {\n\t\ta, b, c, d, e, err := iteratee(items[i])\n\t\tif err != nil {\n\t\t\treturn nil, nil, nil, nil, nil, err\n\t\t}\n\t\tr1 = append(r1, a)\n\t\tr2 = append(r2, b)\n\t\tr3 = append(r3, c)\n\t\tr4 = append(r4, d)\n\t\tr5 = append(r5, e)\n\t}\n\n\treturn r1, r2, r3, r4, r5, nil\n}\n\n// UnzipByErr6 iterates over a collection and creates a slice regrouping the elements\n// to their pre-zip configuration.\n// It returns the first error returned by the iteratee.\nfunc UnzipByErr6[In, A, B, C, D, E, F any](items []In, iteratee func(In) (a A, b B, c C, d D, e E, f F, err error)) ([]A, []B, []C, []D, []E, []F, error) {\n\tsize := len(items)\n\tr1 := make([]A, 0, size)\n\tr2 := make([]B, 0, size)\n\tr3 := make([]C, 0, size)\n\tr4 := make([]D, 0, size)\n\tr5 := make([]E, 0, size)\n\tr6 := make([]F, 0, size)\n\n\tfor i := range items {\n\t\ta, b, c, d, e, f, err := iteratee(items[i])\n\t\tif err != nil {\n\t\t\treturn nil, nil, nil, nil, nil, nil, err\n\t\t}\n\t\tr1 = append(r1, a)\n\t\tr2 = append(r2, b)\n\t\tr3 = append(r3, c)\n\t\tr4 = append(r4, d)\n\t\tr5 = append(r5, e)\n\t\tr6 = append(r6, f)\n\t}\n\n\treturn r1, r2, r3, r4, r5, r6, nil\n}\n\n// UnzipByErr7 iterates over a collection and creates a slice regrouping the elements\n// to their pre-zip configuration.\n// It returns the first error returned by the iteratee.\nfunc UnzipByErr7[In, A, B, C, D, E, F, G any](items []In, iteratee func(In) (a A, b B, c C, d D, e E, f F, g G, err error)) ([]A, []B, []C, []D, []E, []F, []G, error) {\n\tsize := len(items)\n\tr1 := make([]A, 0, size)\n\tr2 := make([]B, 0, size)\n\tr3 := make([]C, 0, size)\n\tr4 := make([]D, 0, size)\n\tr5 := make([]E, 0, size)\n\tr6 := make([]F, 0, size)\n\tr7 := make([]G, 0, size)\n\n\tfor i := range items {\n\t\ta, b, c, d, e, f, g, err := iteratee(items[i])\n\t\tif err != nil {\n\t\t\treturn nil, nil, nil, nil, nil, nil, nil, err\n\t\t}\n\t\tr1 = append(r1, a)\n\t\tr2 = append(r2, b)\n\t\tr3 = append(r3, c)\n\t\tr4 = append(r4, d)\n\t\tr5 = append(r5, e)\n\t\tr6 = append(r6, f)\n\t\tr7 = append(r7, g)\n\t}\n\n\treturn r1, r2, r3, r4, r5, r6, r7, nil\n}\n\n// UnzipByErr8 iterates over a collection and creates a slice regrouping the elements\n// to their pre-zip configuration.\n// It returns the first error returned by the iteratee.\nfunc UnzipByErr8[In, A, B, C, D, E, F, G, H any](items []In, iteratee func(In) (a A, b B, c C, d D, e E, f F, g G, h H, err error)) ([]A, []B, []C, []D, []E, []F, []G, []H, error) {\n\tsize := len(items)\n\tr1 := make([]A, 0, size)\n\tr2 := make([]B, 0, size)\n\tr3 := make([]C, 0, size)\n\tr4 := make([]D, 0, size)\n\tr5 := make([]E, 0, size)\n\tr6 := make([]F, 0, size)\n\tr7 := make([]G, 0, size)\n\tr8 := make([]H, 0, size)\n\n\tfor i := range items {\n\t\ta, b, c, d, e, f, g, h, err := iteratee(items[i])\n\t\tif err != nil {\n\t\t\treturn nil, nil, nil, nil, nil, nil, nil, nil, err\n\t\t}\n\t\tr1 = append(r1, a)\n\t\tr2 = append(r2, b)\n\t\tr3 = append(r3, c)\n\t\tr4 = append(r4, d)\n\t\tr5 = append(r5, e)\n\t\tr6 = append(r6, f)\n\t\tr7 = append(r7, g)\n\t\tr8 = append(r8, h)\n\t}\n\n\treturn r1, r2, r3, r4, r5, r6, r7, r8, nil\n}\n\n// UnzipByErr9 iterates over a collection and creates a slice regrouping the elements\n// to their pre-zip configuration.\n// It returns the first error returned by the iteratee.\nfunc UnzipByErr9[In, A, B, C, D, E, F, G, H, I any](items []In, iteratee func(In) (a A, b B, c C, d D, e E, f F, g G, h H, i I, err error)) ([]A, []B, []C, []D, []E, []F, []G, []H, []I, error) {\n\tsize := len(items)\n\tr1 := make([]A, 0, size)\n\tr2 := make([]B, 0, size)\n\tr3 := make([]C, 0, size)\n\tr4 := make([]D, 0, size)\n\tr5 := make([]E, 0, size)\n\tr6 := make([]F, 0, size)\n\tr7 := make([]G, 0, size)\n\tr8 := make([]H, 0, size)\n\tr9 := make([]I, 0, size)\n\n\tfor i := range items {\n\t\ta, b, c, d, e, f, g, h, i, err := iteratee(items[i])\n\t\tif err != nil {\n\t\t\treturn nil, nil, nil, nil, nil, nil, nil, nil, nil, err\n\t\t}\n\t\tr1 = append(r1, a)\n\t\tr2 = append(r2, b)\n\t\tr3 = append(r3, c)\n\t\tr4 = append(r4, d)\n\t\tr5 = append(r5, e)\n\t\tr6 = append(r6, f)\n\t\tr7 = append(r7, g)\n\t\tr8 = append(r8, h)\n\t\tr9 = append(r9, i)\n\t}\n\n\treturn r1, r2, r3, r4, r5, r6, r7, r8, r9, nil\n}\n\n// CrossJoin2 combines every item from one list with every item from others.\n// It is the cartesian product of lists received as arguments.\n// Returns an empty list if a list is empty.\n// Play: https://go.dev/play/p/LSRL5DmdPag\nfunc CrossJoin2[A, B any](listA []A, listB []B) []Tuple2[A, B] {\n\treturn CrossJoinBy2(listA, listB, T2[A, B])\n}\n\n// CrossJoin3 combines every item from one list with every item from others.\n// It is the cartesian product of lists received as arguments.\n// Returns an empty list if a list is empty.\n// Play: https://go.dev/play/p/2WGeHyJj4fK\nfunc CrossJoin3[A, B, C any](listA []A, listB []B, listC []C) []Tuple3[A, B, C] {\n\treturn CrossJoinBy3(listA, listB, listC, T3[A, B, C])\n}\n\n// CrossJoin4 combines every item from one list with every item from others.\n// It is the cartesian product of lists received as arguments.\n// Returns an empty list if a list is empty.\n// Play: https://go.dev/play/p/6XhKjLmMnNp\nfunc CrossJoin4[A, B, C, D any](listA []A, listB []B, listC []C, listD []D) []Tuple4[A, B, C, D] {\n\treturn CrossJoinBy4(listA, listB, listC, listD, T4[A, B, C, D])\n}\n\n// CrossJoin5 combines every item from one list with every item from others.\n// It is the cartesian product of lists received as arguments.\n// Returns an empty list if a list is empty.\n// Play: https://go.dev/play/p/7oPqRsTuVwX\nfunc CrossJoin5[A, B, C, D, E any](listA []A, listB []B, listC []C, listD []D, listE []E) []Tuple5[A, B, C, D, E] {\n\treturn CrossJoinBy5(listA, listB, listC, listD, listE, T5[A, B, C, D, E])\n}\n\n// CrossJoin6 combines every item from one list with every item from others.\n// It is the cartesian product of lists received as arguments.\n// Returns an empty list if a list is empty.\n// Play: https://go.dev/play/p/8yZ1aB2cD3e\nfunc CrossJoin6[A, B, C, D, E, F any](listA []A, listB []B, listC []C, listD []D, listE []E, listF []F) []Tuple6[A, B, C, D, E, F] {\n\treturn CrossJoinBy6(listA, listB, listC, listD, listE, listF, T6[A, B, C, D, E, F])\n}\n\n// CrossJoin7 combines every item from one list with every item from others.\n// It is the cartesian product of lists received as arguments.\n// Returns an empty list if a list is empty.\n// Play: https://go.dev/play/p/9f4g5h6i7j8\nfunc CrossJoin7[A, B, C, D, E, F, G any](listA []A, listB []B, listC []C, listD []D, listE []E, listF []F, listG []G) []Tuple7[A, B, C, D, E, F, G] {\n\treturn CrossJoinBy7(listA, listB, listC, listD, listE, listF, listG, T7[A, B, C, D, E, F, G])\n}\n\n// CrossJoin8 combines every item from one list with every item from others.\n// It is the cartesian product of lists received as arguments.\n// Returns an empty list if a list is empty.\n// Play: https://go.dev/play/p/0k1l2m3n4o5\nfunc CrossJoin8[A, B, C, D, E, F, G, H any](listA []A, listB []B, listC []C, listD []D, listE []E, listF []F, listG []G, listH []H) []Tuple8[A, B, C, D, E, F, G, H] {\n\treturn CrossJoinBy8(listA, listB, listC, listD, listE, listF, listG, listH, T8[A, B, C, D, E, F, G, H])\n}\n\n// CrossJoin9 combines every item from one list with every item from others.\n// It is the cartesian product of lists received as arguments.\n// Returns an empty list if a list is empty.\n// Play: https://go.dev/play/p/6p7q8r9s0t1\nfunc CrossJoin9[A, B, C, D, E, F, G, H, I any](listA []A, listB []B, listC []C, listD []D, listE []E, listF []F, listG []G, listH []H, listI []I) []Tuple9[A, B, C, D, E, F, G, H, I] {\n\treturn CrossJoinBy9(listA, listB, listC, listD, listE, listF, listG, listH, listI, T9[A, B, C, D, E, F, G, H, I])\n}\n\n// CrossJoinBy2 combines every item from one list with every item from others.\n// It is the cartesian product of lists received as arguments. The transform function\n// is used to create the output values.\n// Returns an empty list if a list is empty.\n// Play: https://go.dev/play/p/VLy8iyrPN8X\nfunc CrossJoinBy2[A, B, Out any](listA []A, listB []B, transform func(a A, b B) Out) []Out {\n\tsize := len(listA) * len(listB)\n\tif size == 0 {\n\t\treturn []Out{}\n\t}\n\n\tresult := make([]Out, 0, size)\n\n\tfor _, a := range listA {\n\t\tfor _, b := range listB {\n\t\t\tresult = append(result, transform(a, b))\n\t\t}\n\t}\n\n\treturn result\n}\n\n// CrossJoinBy3 combines every item from one list with every item from others.\n// It is the cartesian product of lists received as arguments. The transform function\n// is used to create the output values.\n// Returns an empty list if a list is empty.\n// Play: https://go.dev/play/p/3z4y5x6w7v8\nfunc CrossJoinBy3[A, B, C, Out any](listA []A, listB []B, listC []C, transform func(a A, b B, c C) Out) []Out {\n\tsize := len(listA) * len(listB) * len(listC)\n\tif size == 0 {\n\t\treturn []Out{}\n\t}\n\n\tresult := make([]Out, 0, size)\n\n\tfor _, a := range listA {\n\t\tfor _, b := range listB {\n\t\t\tfor _, c := range listC {\n\t\t\t\tresult = append(result, transform(a, b, c))\n\t\t\t}\n\t\t}\n\t}\n\n\treturn result\n}\n\n// CrossJoinBy4 combines every item from one list with every item from others.\n// It is the cartesian product of lists received as arguments. The transform function\n// is used to create the output values.\n// Returns an empty list if a list is empty.\n// Play: https://go.dev/play/p/8b9c0d1e2f3\nfunc CrossJoinBy4[A, B, C, D, Out any](listA []A, listB []B, listC []C, listD []D, transform func(a A, b B, c C, d D) Out) []Out {\n\tsize := len(listA) * len(listB) * len(listC) * len(listD)\n\tif size == 0 {\n\t\treturn []Out{}\n\t}\n\n\tresult := make([]Out, 0, size)\n\n\tfor _, a := range listA {\n\t\tfor _, b := range listB {\n\t\t\tfor _, c := range listC {\n\t\t\t\tfor _, d := range listD {\n\t\t\t\t\tresult = append(result, transform(a, b, c, d))\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn result\n}\n\n// CrossJoinBy5 combines every item from one list with every item from others.\n// It is the cartesian product of lists received as arguments. The transform function\n// is used to create the output values.\n// Returns an empty list if a list is empty.\n// Play: https://go.dev/play/p/4g5h6i7j8k9\nfunc CrossJoinBy5[A, B, C, D, E, Out any](listA []A, listB []B, listC []C, listD []D, listE []E, transform func(a A, b B, c C, d D, e E) Out) []Out {\n\tsize := len(listA) * len(listB) * len(listC) * len(listD) * len(listE)\n\tif size == 0 {\n\t\treturn []Out{}\n\t}\n\n\tresult := make([]Out, 0, size)\n\n\tfor _, a := range listA {\n\t\tfor _, b := range listB {\n\t\t\tfor _, c := range listC {\n\t\t\t\tfor _, d := range listD {\n\t\t\t\t\tfor _, e := range listE {\n\t\t\t\t\t\tresult = append(result, transform(a, b, c, d, e))\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn result\n}\n\n// CrossJoinBy6 combines every item from one list with every item from others.\n// It is the cartesian product of lists received as arguments. The transform function\n// is used to create the output values.\n// Returns an empty list if a list is empty.\n// Play: https://go.dev/play/p/1l2m3n4o5p6\nfunc CrossJoinBy6[A, B, C, D, E, F, Out any](listA []A, listB []B, listC []C, listD []D, listE []E, listF []F, transform func(a A, b B, c C, d D, e E, f F) Out) []Out {\n\tsize := len(listA) * len(listB) * len(listC) * len(listD) * len(listE) * len(listF)\n\tif size == 0 {\n\t\treturn []Out{}\n\t}\n\n\tresult := make([]Out, 0, size)\n\n\tfor _, a := range listA {\n\t\tfor _, b := range listB {\n\t\t\tfor _, c := range listC {\n\t\t\t\tfor _, d := range listD {\n\t\t\t\t\tfor _, e := range listE {\n\t\t\t\t\t\tfor _, f := range listF {\n\t\t\t\t\t\t\tresult = append(result, transform(a, b, c, d, e, f))\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn result\n}\n\n// CrossJoinBy7 combines every item from one list with every item from others.\n// It is the cartesian product of lists received as arguments. The transform function\n// is used to create the output values.\n// Returns an empty list if a list is empty.\n// Play: https://go.dev/play/p/7q8r9s0t1u2\nfunc CrossJoinBy7[A, B, C, D, E, F, G, Out any](listA []A, listB []B, listC []C, listD []D, listE []E, listF []F, listG []G, transform func(a A, b B, c C, d D, e E, f F, g G) Out) []Out {\n\tsize := len(listA) * len(listB) * len(listC) * len(listD) * len(listE) * len(listF) * len(listG)\n\tif size == 0 {\n\t\treturn []Out{}\n\t}\n\n\tresult := make([]Out, 0, size)\n\n\tfor _, a := range listA {\n\t\tfor _, b := range listB {\n\t\t\tfor _, c := range listC {\n\t\t\t\tfor _, d := range listD {\n\t\t\t\t\tfor _, e := range listE {\n\t\t\t\t\t\tfor _, f := range listF {\n\t\t\t\t\t\t\tfor _, g := range listG {\n\t\t\t\t\t\t\t\tresult = append(result, transform(a, b, c, d, e, f, g))\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn result\n}\n\n// CrossJoinBy8 combines every item from one list with every item from others.\n// It is the cartesian product of lists received as arguments. The transform function\n// is used to create the output values.\n// Returns an empty list if a list is empty.\n// Play: https://go.dev/play/p/3v4w5x6y7z8\nfunc CrossJoinBy8[A, B, C, D, E, F, G, H, Out any](listA []A, listB []B, listC []C, listD []D, listE []E, listF []F, listG []G, listH []H, transform func(a A, b B, c C, d D, e E, f F, g G, h H) Out) []Out {\n\tsize := len(listA) * len(listB) * len(listC) * len(listD) * len(listE) * len(listF) * len(listG) * len(listH)\n\tif size == 0 {\n\t\treturn []Out{}\n\t}\n\n\tresult := make([]Out, 0, size)\n\n\tfor _, a := range listA {\n\t\tfor _, b := range listB {\n\t\t\tfor _, c := range listC {\n\t\t\t\tfor _, d := range listD {\n\t\t\t\t\tfor _, e := range listE {\n\t\t\t\t\t\tfor _, f := range listF {\n\t\t\t\t\t\t\tfor _, g := range listG {\n\t\t\t\t\t\t\t\tfor _, h := range listH {\n\t\t\t\t\t\t\t\t\tresult = append(result, transform(a, b, c, d, e, f, g, h))\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn result\n}\n\n// CrossJoinBy9 combines every item from one list with every item from others.\n// It is the cartesian product of lists received as arguments. The transform function\n// is used to create the output values.\n// Returns an empty list if a list is empty.\n// Play: https://go.dev/play/p/9a0b1c2d3e4\nfunc CrossJoinBy9[A, B, C, D, E, F, G, H, I, Out any](listA []A, listB []B, listC []C, listD []D, listE []E, listF []F, listG []G, listH []H, listI []I, transform func(a A, b B, c C, d D, e E, f F, g G, h H, i I) Out) []Out {\n\tsize := len(listA) * len(listB) * len(listC) * len(listD) * len(listE) * len(listF) * len(listG) * len(listH) * len(listI)\n\tif size == 0 {\n\t\treturn []Out{}\n\t}\n\n\tresult := make([]Out, 0, size)\n\n\tfor _, a := range listA {\n\t\tfor _, b := range listB {\n\t\t\tfor _, c := range listC {\n\t\t\t\tfor _, d := range listD {\n\t\t\t\t\tfor _, e := range listE {\n\t\t\t\t\t\tfor _, f := range listF {\n\t\t\t\t\t\t\tfor _, g := range listG {\n\t\t\t\t\t\t\t\tfor _, h := range listH {\n\t\t\t\t\t\t\t\t\tfor _, i := range listI {\n\t\t\t\t\t\t\t\t\t\tresult = append(result, transform(a, b, c, d, e, f, g, h, i))\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn result\n}\n\n// CrossJoinByErr2 combines every item from one list with every item from others.\n// It is the cartesian product of lists received as arguments. The transform function\n// is used to create the output values.\n// Returns an empty list if a list is empty.\n// It returns the first error returned by the transform function.\nfunc CrossJoinByErr2[A, B, Out any](listA []A, listB []B, transform func(a A, b B) (Out, error)) ([]Out, error) {\n\tsize := len(listA) * len(listB)\n\tif size == 0 {\n\t\treturn []Out{}, nil\n\t}\n\n\tresult := make([]Out, 0, size)\n\n\tfor _, a := range listA {\n\t\tfor _, b := range listB {\n\t\t\tr, err := transform(a, b)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tresult = append(result, r)\n\t\t}\n\t}\n\n\treturn result, nil\n}\n\n// CrossJoinByErr3 combines every item from one list with every item from others.\n// It is the cartesian product of lists received as arguments. The transform function\n// is used to create the output values.\n// Returns an empty list if a list is empty.\n// It returns the first error returned by the transform function.\nfunc CrossJoinByErr3[A, B, C, Out any](listA []A, listB []B, listC []C, transform func(a A, b B, c C) (Out, error)) ([]Out, error) {\n\tsize := len(listA) * len(listB) * len(listC)\n\tif size == 0 {\n\t\treturn []Out{}, nil\n\t}\n\n\tresult := make([]Out, 0, size)\n\n\tfor _, a := range listA {\n\t\tfor _, b := range listB {\n\t\t\tfor _, c := range listC {\n\t\t\t\tr, err := transform(a, b, c)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, err\n\t\t\t\t}\n\t\t\t\tresult = append(result, r)\n\t\t\t}\n\t\t}\n\t}\n\n\treturn result, nil\n}\n\n// CrossJoinByErr4 combines every item from one list with every item from others.\n// It is the cartesian product of lists received as arguments. The transform function\n// is used to create the output values.\n// Returns an empty list if a list is empty.\n// It returns the first error returned by the transform function.\nfunc CrossJoinByErr4[A, B, C, D, Out any](listA []A, listB []B, listC []C, listD []D, transform func(a A, b B, c C, d D) (Out, error)) ([]Out, error) {\n\tsize := len(listA) * len(listB) * len(listC) * len(listD)\n\tif size == 0 {\n\t\treturn []Out{}, nil\n\t}\n\n\tresult := make([]Out, 0, size)\n\n\tfor _, a := range listA {\n\t\tfor _, b := range listB {\n\t\t\tfor _, c := range listC {\n\t\t\t\tfor _, d := range listD {\n\t\t\t\t\tr, err := transform(a, b, c, d)\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\treturn nil, err\n\t\t\t\t\t}\n\t\t\t\t\tresult = append(result, r)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn result, nil\n}\n\n// CrossJoinByErr5 combines every item from one list with every item from others.\n// It is the cartesian product of lists received as arguments. The transform function\n// is used to create the output values.\n// Returns an empty list if a list is empty.\n// It returns the first error returned by the transform function.\nfunc CrossJoinByErr5[A, B, C, D, E, Out any](listA []A, listB []B, listC []C, listD []D, listE []E, transform func(a A, b B, c C, d D, e E) (Out, error)) ([]Out, error) {\n\tsize := len(listA) * len(listB) * len(listC) * len(listD) * len(listE)\n\tif size == 0 {\n\t\treturn []Out{}, nil\n\t}\n\n\tresult := make([]Out, 0, size)\n\n\tfor _, a := range listA {\n\t\tfor _, b := range listB {\n\t\t\tfor _, c := range listC {\n\t\t\t\tfor _, d := range listD {\n\t\t\t\t\tfor _, e := range listE {\n\t\t\t\t\t\tr, err := transform(a, b, c, d, e)\n\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\treturn nil, err\n\t\t\t\t\t\t}\n\t\t\t\t\t\tresult = append(result, r)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn result, nil\n}\n\n// CrossJoinByErr6 combines every item from one list with every item from others.\n// It is the cartesian product of lists received as arguments. The transform function\n// is used to create the output values.\n// Returns an empty list if a list is empty.\n// It returns the first error returned by the transform function.\nfunc CrossJoinByErr6[A, B, C, D, E, F, Out any](listA []A, listB []B, listC []C, listD []D, listE []E, listF []F, transform func(a A, b B, c C, d D, e E, f F) (Out, error)) ([]Out, error) {\n\tsize := len(listA) * len(listB) * len(listC) * len(listD) * len(listE) * len(listF)\n\tif size == 0 {\n\t\treturn []Out{}, nil\n\t}\n\n\tresult := make([]Out, 0, size)\n\n\tfor _, a := range listA {\n\t\tfor _, b := range listB {\n\t\t\tfor _, c := range listC {\n\t\t\t\tfor _, d := range listD {\n\t\t\t\t\tfor _, e := range listE {\n\t\t\t\t\t\tfor _, f := range listF {\n\t\t\t\t\t\t\tr, err := transform(a, b, c, d, e, f)\n\t\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\t\treturn nil, err\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tresult = append(result, r)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn result, nil\n}\n\n// CrossJoinByErr7 combines every item from one list with every item from others.\n// It is the cartesian product of lists received as arguments. The transform function\n// is used to create the output values.\n// Returns an empty list if a list is empty.\n// It returns the first error returned by the transform function.\nfunc CrossJoinByErr7[A, B, C, D, E, F, G, Out any](listA []A, listB []B, listC []C, listD []D, listE []E, listF []F, listG []G, transform func(a A, b B, c C, d D, e E, f F, g G) (Out, error)) ([]Out, error) {\n\tsize := len(listA) * len(listB) * len(listC) * len(listD) * len(listE) * len(listF) * len(listG)\n\tif size == 0 {\n\t\treturn []Out{}, nil\n\t}\n\n\tresult := make([]Out, 0, size)\n\n\tfor _, a := range listA {\n\t\tfor _, b := range listB {\n\t\t\tfor _, c := range listC {\n\t\t\t\tfor _, d := range listD {\n\t\t\t\t\tfor _, e := range listE {\n\t\t\t\t\t\tfor _, f := range listF {\n\t\t\t\t\t\t\tfor _, g := range listG {\n\t\t\t\t\t\t\t\tr, err := transform(a, b, c, d, e, f, g)\n\t\t\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\t\t\treturn nil, err\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tresult = append(result, r)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn result, nil\n}\n\n// CrossJoinByErr8 combines every item from one list with every item from others.\n// It is the cartesian product of lists received as arguments. The transform function\n// is used to create the output values.\n// Returns an empty list if a list is empty.\n// It returns the first error returned by the transform function.\nfunc CrossJoinByErr8[A, B, C, D, E, F, G, H, Out any](listA []A, listB []B, listC []C, listD []D, listE []E, listF []F, listG []G, listH []H, transform func(a A, b B, c C, d D, e E, f F, g G, h H) (Out, error)) ([]Out, error) {\n\tsize := len(listA) * len(listB) * len(listC) * len(listD) * len(listE) * len(listF) * len(listG) * len(listH)\n\tif size == 0 {\n\t\treturn []Out{}, nil\n\t}\n\n\tresult := make([]Out, 0, size)\n\n\tfor _, a := range listA {\n\t\tfor _, b := range listB {\n\t\t\tfor _, c := range listC {\n\t\t\t\tfor _, d := range listD {\n\t\t\t\t\tfor _, e := range listE {\n\t\t\t\t\t\tfor _, f := range listF {\n\t\t\t\t\t\t\tfor _, g := range listG {\n\t\t\t\t\t\t\t\tfor _, h := range listH {\n\t\t\t\t\t\t\t\t\tr, err := transform(a, b, c, d, e, f, g, h)\n\t\t\t\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\t\t\t\treturn nil, err\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tresult = append(result, r)\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn result, nil\n}\n\n// CrossJoinByErr9 combines every item from one list with every item from others.\n// It is the cartesian product of lists received as arguments. The transform function\n// is used to create the output values.\n// Returns an empty list if a list is empty.\n// It returns the first error returned by the transform function.\nfunc CrossJoinByErr9[A, B, C, D, E, F, G, H, I, Out any](listA []A, listB []B, listC []C, listD []D, listE []E, listF []F, listG []G, listH []H, listI []I, transform func(a A, b B, c C, d D, e E, f F, g G, h H, i I) (Out, error)) ([]Out, error) {\n\tsize := len(listA) * len(listB) * len(listC) * len(listD) * len(listE) * len(listF) * len(listG) * len(listH) * len(listI)\n\tif size == 0 {\n\t\treturn []Out{}, nil\n\t}\n\n\tresult := make([]Out, 0, size)\n\n\tfor _, a := range listA {\n\t\tfor _, b := range listB {\n\t\t\tfor _, c := range listC {\n\t\t\t\tfor _, d := range listD {\n\t\t\t\t\tfor _, e := range listE {\n\t\t\t\t\t\tfor _, f := range listF {\n\t\t\t\t\t\t\tfor _, g := range listG {\n\t\t\t\t\t\t\t\tfor _, h := range listH {\n\t\t\t\t\t\t\t\t\tfor _, i := range listI {\n\t\t\t\t\t\t\t\t\t\tr, err := transform(a, b, c, d, e, f, g, h, i)\n\t\t\t\t\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\t\t\t\t\treturn nil, err\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\tresult = append(result, r)\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn result, nil\n}\n"
  },
  {
    "path": "tuples_test.go",
    "content": "package lo\n\nimport (\n\t\"errors\"\n\t\"strconv\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestT(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tr1 := T2(\"a\", 1)\n\tr2 := T3[string, int, float32](\"b\", 2, 3.0)\n\tr3 := T4[string, int, float32](\"c\", 3, 4.0, true)\n\tr4 := T5[string, int, float32](\"d\", 4, 5.0, false, \"e\")\n\tr5 := T6[string, int, float32](\"f\", 5, 6.0, true, \"g\", 7)\n\tr6 := T7[string, int, float32](\"h\", 6, 7.0, false, \"i\", 8, 9.0)\n\tr7 := T8[string, int, float32](\"j\", 7, 8.0, true, \"k\", 9, 10.0, false)\n\tr8 := T9[string, int, float32](\"l\", 8, 9.0, false, \"m\", 10, 11.0, true, \"n\")\n\n\tis.Equal(Tuple2[string, int]{A: \"a\", B: 1}, r1)\n\tis.Equal(Tuple3[string, int, float32]{A: \"b\", B: 2, C: 3.0}, r2)\n\tis.Equal(Tuple4[string, int, float32, bool]{A: \"c\", B: 3, C: 4.0, D: true}, r3)\n\tis.Equal(Tuple5[string, int, float32, bool, string]{A: \"d\", B: 4, C: 5.0, D: false, E: \"e\"}, r4)\n\tis.Equal(Tuple6[string, int, float32, bool, string, int]{A: \"f\", B: 5, C: 6.0, D: true, E: \"g\", F: 7}, r5)\n\tis.Equal(Tuple7[string, int, float32, bool, string, int, float64]{A: \"h\", B: 6, C: 7.0, D: false, E: \"i\", F: 8, G: 9.0}, r6)\n\tis.Equal(Tuple8[string, int, float32, bool, string, int, float64, bool]{A: \"j\", B: 7, C: 8.0, D: true, E: \"k\", F: 9, G: 10.0, H: false}, r7)\n\tis.Equal(Tuple9[string, int, float32, bool, string, int, float64, bool, string]{A: \"l\", B: 8, C: 9.0, D: false, E: \"m\", F: 10, G: 11.0, H: true, I: \"n\"}, r8)\n}\n\nfunc TestUnpack(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\t{\n\t\ttuple := Tuple2[string, int]{\"a\", 1}\n\n\t\tr1, r2 := Unpack2(tuple)\n\n\t\tis.Equal(\"a\", r1)\n\t\tis.Equal(1, r2)\n\n\t\tr1, r2 = tuple.Unpack()\n\n\t\tis.Equal(\"a\", r1)\n\t\tis.Equal(1, r2)\n\t}\n\n\t{\n\t\ttuple := Tuple3[string, int, float64]{\"a\", 1, 1.0}\n\n\t\tr1, r2, r3 := Unpack3(tuple)\n\n\t\tis.Equal(\"a\", r1)\n\t\tis.Equal(1, r2)\n\t\tis.Equal(1.0, r3)\n\n\t\tr1, r2, r3 = tuple.Unpack()\n\n\t\tis.Equal(\"a\", r1)\n\t\tis.Equal(1, r2)\n\t\tis.Equal(1.0, r3)\n\t}\n\n\t{\n\t\ttuple := Tuple4[string, int, float64, bool]{\"a\", 1, 1.0, true}\n\n\t\tr1, r2, r3, r4 := Unpack4(tuple)\n\n\t\tis.Equal(\"a\", r1)\n\t\tis.Equal(1, r2)\n\t\tis.Equal(1.0, r3)\n\t\tis.True(r4)\n\n\t\tr1, r2, r3, r4 = tuple.Unpack()\n\n\t\tis.Equal(\"a\", r1)\n\t\tis.Equal(1, r2)\n\t\tis.Equal(1.0, r3)\n\t\tis.True(r4)\n\t}\n\n\t{\n\t\ttuple := Tuple5[string, int, float64, bool, string]{\"a\", 1, 1.0, true, \"b\"}\n\n\t\tr1, r2, r3, r4, r5 := Unpack5(tuple)\n\n\t\tis.Equal(\"a\", r1)\n\t\tis.Equal(1, r2)\n\t\tis.Equal(1.0, r3)\n\t\tis.True(r4)\n\t\tis.Equal(\"b\", r5)\n\n\t\tr1, r2, r3, r4, r5 = tuple.Unpack()\n\n\t\tis.Equal(\"a\", r1)\n\t\tis.Equal(1, r2)\n\t\tis.Equal(1.0, r3)\n\t\tis.True(r4)\n\t\tis.Equal(\"b\", r5)\n\t}\n\n\t{\n\t\ttuple := Tuple6[string, int, float64, bool, string, int]{\"a\", 1, 1.0, true, \"b\", 2}\n\n\t\tr1, r2, r3, r4, r5, r6 := Unpack6(tuple)\n\n\t\tis.Equal(\"a\", r1)\n\t\tis.Equal(1, r2)\n\t\tis.Equal(1.0, r3)\n\t\tis.True(r4)\n\t\tis.Equal(\"b\", r5)\n\t\tis.Equal(2, r6)\n\n\t\tr1, r2, r3, r4, r5, r6 = tuple.Unpack()\n\n\t\tis.Equal(\"a\", r1)\n\t\tis.Equal(1, r2)\n\t\tis.Equal(1.0, r3)\n\t\tis.True(r4)\n\t\tis.Equal(\"b\", r5)\n\t\tis.Equal(2, r6)\n\t}\n\n\t{\n\t\ttuple := Tuple7[string, int, float64, bool, string, int, float64]{\"a\", 1, 1.0, true, \"b\", 2, 3.0}\n\n\t\tr1, r2, r3, r4, r5, r6, r7 := Unpack7(tuple)\n\n\t\tis.Equal(\"a\", r1)\n\t\tis.Equal(1, r2)\n\t\tis.Equal(1.0, r3)\n\t\tis.True(r4)\n\t\tis.Equal(\"b\", r5)\n\t\tis.Equal(2, r6)\n\t\tis.Equal(3.0, r7)\n\n\t\tr1, r2, r3, r4, r5, r6, r7 = tuple.Unpack()\n\n\t\tis.Equal(\"a\", r1)\n\t\tis.Equal(1, r2)\n\t\tis.Equal(1.0, r3)\n\t\tis.True(r4)\n\t\tis.Equal(\"b\", r5)\n\t\tis.Equal(2, r6)\n\t\tis.Equal(3.0, r7)\n\t}\n\n\t{\n\t\ttuple := Tuple8[string, int, float64, bool, string, int, float64, bool]{\"a\", 1, 1.0, true, \"b\", 2, 3.0, true}\n\n\t\tr1, r2, r3, r4, r5, r6, r7, r8 := Unpack8(tuple)\n\n\t\tis.Equal(\"a\", r1)\n\t\tis.Equal(1, r2)\n\t\tis.Equal(1.0, r3)\n\t\tis.True(r4)\n\t\tis.Equal(\"b\", r5)\n\t\tis.Equal(2, r6)\n\t\tis.Equal(3.0, r7)\n\t\tis.True(r8)\n\n\t\tr1, r2, r3, r4, r5, r6, r7, r8 = tuple.Unpack()\n\n\t\tis.Equal(\"a\", r1)\n\t\tis.Equal(1, r2)\n\t\tis.Equal(1.0, r3)\n\t\tis.True(r4)\n\t\tis.Equal(\"b\", r5)\n\t\tis.Equal(2, r6)\n\t\tis.Equal(3.0, r7)\n\t\tis.True(r8)\n\t}\n\n\t{\n\t\ttuple := Tuple9[string, int, float64, bool, string, int, float64, bool, string]{\"a\", 1, 1.0, true, \"b\", 2, 3.0, true, \"c\"}\n\n\t\tr1, r2, r3, r4, r5, r6, r7, r8, r9 := Unpack9(tuple)\n\n\t\tis.Equal(\"a\", r1)\n\t\tis.Equal(1, r2)\n\t\tis.Equal(1.0, r3)\n\t\tis.True(r4)\n\t\tis.Equal(\"b\", r5)\n\t\tis.Equal(2, r6)\n\t\tis.Equal(3.0, r7)\n\t\tis.True(r8)\n\t\tis.Equal(\"c\", r9)\n\n\t\tr1, r2, r3, r4, r5, r6, r7, r8, r9 = tuple.Unpack()\n\n\t\tis.Equal(\"a\", r1)\n\t\tis.Equal(1, r2)\n\t\tis.Equal(1.0, r3)\n\t\tis.True(r4)\n\t\tis.Equal(\"b\", r5)\n\t\tis.Equal(2, r6)\n\t\tis.Equal(3.0, r7)\n\t\tis.True(r8)\n\t\tis.Equal(\"c\", r9)\n\t}\n}\n\nfunc TestZip(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tr1 := Zip2(\n\t\t[]string{\"a\", \"b\"},\n\t\t[]int{1, 2},\n\t)\n\n\tr2 := Zip3(\n\t\t[]string{\"a\", \"b\", \"c\"},\n\t\t[]int{1, 2, 3},\n\t\t[]int{4, 5, 6},\n\t)\n\n\tr3 := Zip4(\n\t\t[]string{\"a\", \"b\", \"c\", \"d\"},\n\t\t[]int{1, 2, 3, 4},\n\t\t[]int{5, 6, 7, 8},\n\t\t[]bool{true, true, true, true},\n\t)\n\n\tr4 := Zip5(\n\t\t[]string{\"a\", \"b\", \"c\", \"d\", \"e\"},\n\t\t[]int{1, 2, 3, 4, 5},\n\t\t[]int{6, 7, 8, 9, 10},\n\t\t[]bool{true, true, true, true, true},\n\t\t[]float32{0.1, 0.2, 0.3, 0.4, 0.5},\n\t)\n\n\tr5 := Zip6(\n\t\t[]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\"},\n\t\t[]int{1, 2, 3, 4, 5, 6},\n\t\t[]int{7, 8, 9, 10, 11, 12},\n\t\t[]bool{true, true, true, true, true, true},\n\t\t[]float32{0.1, 0.2, 0.3, 0.4, 0.5, 0.6},\n\t\t[]float64{0.01, 0.02, 0.03, 0.04, 0.05, 0.06},\n\t)\n\n\tr6 := Zip7(\n\t\t[]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"},\n\t\t[]int{1, 2, 3, 4, 5, 6, 7},\n\t\t[]int{8, 9, 10, 11, 12, 13, 14},\n\t\t[]bool{true, true, true, true, true, true, true},\n\t\t[]float32{0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7},\n\t\t[]float64{0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07},\n\t\t[]int8{1, 2, 3, 4, 5, 6, 7},\n\t)\n\n\tr7 := Zip8(\n\t\t[]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\", \"h\"},\n\t\t[]int{1, 2, 3, 4, 5, 6, 7, 8},\n\t\t[]int{9, 10, 11, 12, 13, 14, 15, 16},\n\t\t[]bool{true, true, true, true, true, true, true, true},\n\t\t[]float32{0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8},\n\t\t[]float64{0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08},\n\t\t[]int8{1, 2, 3, 4, 5, 6, 7, 8},\n\t\t[]int16{1, 2, 3, 4, 5, 6, 7, 8},\n\t)\n\n\tr8 := Zip9(\n\t\t[]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\", \"h\", \"i\"},\n\t\t[]int{1, 2, 3, 4, 5, 6, 7, 8, 9},\n\t\t[]int{10, 11, 12, 13, 14, 15, 16, 17, 18},\n\t\t[]bool{true, true, true, true, true, true, true, true, true},\n\t\t[]float32{0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9},\n\t\t[]float64{0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09},\n\t\t[]int8{1, 2, 3, 4, 5, 6, 7, 8, 9},\n\t\t[]int16{1, 2, 3, 4, 5, 6, 7, 8, 9},\n\t\t[]int32{1, 2, 3, 4, 5, 6, 7, 8, 9},\n\t)\n\n\tis.Equal([]Tuple2[string, int]{\n\t\t{A: \"a\", B: 1},\n\t\t{A: \"b\", B: 2},\n\t}, r1)\n\n\tis.Equal([]Tuple3[string, int, int]{\n\t\t{A: \"a\", B: 1, C: 4},\n\t\t{A: \"b\", B: 2, C: 5},\n\t\t{A: \"c\", B: 3, C: 6},\n\t}, r2)\n\n\tis.Equal([]Tuple4[string, int, int, bool]{\n\t\t{A: \"a\", B: 1, C: 5, D: true},\n\t\t{A: \"b\", B: 2, C: 6, D: true},\n\t\t{A: \"c\", B: 3, C: 7, D: true},\n\t\t{A: \"d\", B: 4, C: 8, D: true},\n\t}, r3)\n\n\tis.Equal([]Tuple5[string, int, int, bool, float32]{\n\t\t{A: \"a\", B: 1, C: 6, D: true, E: 0.1},\n\t\t{A: \"b\", B: 2, C: 7, D: true, E: 0.2},\n\t\t{A: \"c\", B: 3, C: 8, D: true, E: 0.3},\n\t\t{A: \"d\", B: 4, C: 9, D: true, E: 0.4},\n\t\t{A: \"e\", B: 5, C: 10, D: true, E: 0.5},\n\t}, r4)\n\n\tis.Equal([]Tuple6[string, int, int, bool, float32, float64]{\n\t\t{A: \"a\", B: 1, C: 7, D: true, E: 0.1, F: 0.01},\n\t\t{A: \"b\", B: 2, C: 8, D: true, E: 0.2, F: 0.02},\n\t\t{A: \"c\", B: 3, C: 9, D: true, E: 0.3, F: 0.03},\n\t\t{A: \"d\", B: 4, C: 10, D: true, E: 0.4, F: 0.04},\n\t\t{A: \"e\", B: 5, C: 11, D: true, E: 0.5, F: 0.05},\n\t\t{A: \"f\", B: 6, C: 12, D: true, E: 0.6, F: 0.06},\n\t}, r5)\n\n\tis.Equal([]Tuple7[string, int, int, bool, float32, float64, int8]{\n\t\t{A: \"a\", B: 1, C: 8, D: true, E: 0.1, F: 0.01, G: 1},\n\t\t{A: \"b\", B: 2, C: 9, D: true, E: 0.2, F: 0.02, G: 2},\n\t\t{A: \"c\", B: 3, C: 10, D: true, E: 0.3, F: 0.03, G: 3},\n\t\t{A: \"d\", B: 4, C: 11, D: true, E: 0.4, F: 0.04, G: 4},\n\t\t{A: \"e\", B: 5, C: 12, D: true, E: 0.5, F: 0.05, G: 5},\n\t\t{A: \"f\", B: 6, C: 13, D: true, E: 0.6, F: 0.06, G: 6},\n\t\t{A: \"g\", B: 7, C: 14, D: true, E: 0.7, F: 0.07, G: 7},\n\t}, r6)\n\n\tis.Equal([]Tuple8[string, int, int, bool, float32, float64, int8, int16]{\n\t\t{A: \"a\", B: 1, C: 9, D: true, E: 0.1, F: 0.01, G: 1, H: 1},\n\t\t{A: \"b\", B: 2, C: 10, D: true, E: 0.2, F: 0.02, G: 2, H: 2},\n\t\t{A: \"c\", B: 3, C: 11, D: true, E: 0.3, F: 0.03, G: 3, H: 3},\n\t\t{A: \"d\", B: 4, C: 12, D: true, E: 0.4, F: 0.04, G: 4, H: 4},\n\t\t{A: \"e\", B: 5, C: 13, D: true, E: 0.5, F: 0.05, G: 5, H: 5},\n\t\t{A: \"f\", B: 6, C: 14, D: true, E: 0.6, F: 0.06, G: 6, H: 6},\n\t\t{A: \"g\", B: 7, C: 15, D: true, E: 0.7, F: 0.07, G: 7, H: 7},\n\t\t{A: \"h\", B: 8, C: 16, D: true, E: 0.8, F: 0.08, G: 8, H: 8},\n\t}, r7)\n\n\tis.Equal([]Tuple9[string, int, int, bool, float32, float64, int8, int16, int32]{\n\t\t{A: \"a\", B: 1, C: 10, D: true, E: 0.1, F: 0.01, G: 1, H: 1, I: 1},\n\t\t{A: \"b\", B: 2, C: 11, D: true, E: 0.2, F: 0.02, G: 2, H: 2, I: 2},\n\t\t{A: \"c\", B: 3, C: 12, D: true, E: 0.3, F: 0.03, G: 3, H: 3, I: 3},\n\t\t{A: \"d\", B: 4, C: 13, D: true, E: 0.4, F: 0.04, G: 4, H: 4, I: 4},\n\t\t{A: \"e\", B: 5, C: 14, D: true, E: 0.5, F: 0.05, G: 5, H: 5, I: 5},\n\t\t{A: \"f\", B: 6, C: 15, D: true, E: 0.6, F: 0.06, G: 6, H: 6, I: 6},\n\t\t{A: \"g\", B: 7, C: 16, D: true, E: 0.7, F: 0.07, G: 7, H: 7, I: 7},\n\t\t{A: \"h\", B: 8, C: 17, D: true, E: 0.8, F: 0.08, G: 8, H: 8, I: 8},\n\t\t{A: \"i\", B: 9, C: 18, D: true, E: 0.9, F: 0.09, G: 9, H: 9, I: 9},\n\t}, r8)\n}\n\nfunc TestZipBy(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tr1 := ZipBy2(\n\t\t[]string{\"a\", \"b\"},\n\t\t[]int{1, 2},\n\t\tT2[string, int],\n\t)\n\n\tr2 := ZipBy3(\n\t\t[]string{\"a\", \"b\", \"c\"},\n\t\t[]int{1, 2, 3},\n\t\t[]int{4, 5, 6},\n\t\tT3[string, int, int],\n\t)\n\n\tr3 := ZipBy4(\n\t\t[]string{\"a\", \"b\", \"c\", \"d\"},\n\t\t[]int{1, 2, 3, 4},\n\t\t[]int{5, 6, 7, 8},\n\t\t[]bool{true, true, true, true},\n\t\tT4[string, int, int, bool],\n\t)\n\n\tr4 := ZipBy5(\n\t\t[]string{\"a\", \"b\", \"c\", \"d\", \"e\"},\n\t\t[]int{1, 2, 3, 4, 5},\n\t\t[]int{6, 7, 8, 9, 10},\n\t\t[]bool{true, true, true, true, true},\n\t\t[]float32{0.1, 0.2, 0.3, 0.4, 0.5},\n\t\tT5[string, int, int, bool, float32],\n\t)\n\n\tr5 := ZipBy6(\n\t\t[]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\"},\n\t\t[]int{1, 2, 3, 4, 5, 6},\n\t\t[]int{7, 8, 9, 10, 11, 12},\n\t\t[]bool{true, true, true, true, true, true},\n\t\t[]float32{0.1, 0.2, 0.3, 0.4, 0.5, 0.6},\n\t\t[]float64{0.01, 0.02, 0.03, 0.04, 0.05, 0.06},\n\t\tT6[string, int, int, bool, float32, float64],\n\t)\n\n\tr6 := ZipBy7(\n\t\t[]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"},\n\t\t[]int{1, 2, 3, 4, 5, 6, 7},\n\t\t[]int{8, 9, 10, 11, 12, 13, 14},\n\t\t[]bool{true, true, true, true, true, true, true},\n\t\t[]float32{0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7},\n\t\t[]float64{0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07},\n\t\t[]int8{1, 2, 3, 4, 5, 6, 7},\n\t\tT7[string, int, int, bool, float32, float64, int8],\n\t)\n\n\tr7 := ZipBy8(\n\t\t[]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\", \"h\"},\n\t\t[]int{1, 2, 3, 4, 5, 6, 7, 8},\n\t\t[]int{9, 10, 11, 12, 13, 14, 15, 16},\n\t\t[]bool{true, true, true, true, true, true, true, true},\n\t\t[]float32{0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8},\n\t\t[]float64{0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08},\n\t\t[]int8{1, 2, 3, 4, 5, 6, 7, 8},\n\t\t[]int16{1, 2, 3, 4, 5, 6, 7, 8},\n\t\tT8[string, int, int, bool, float32, float64, int8, int16],\n\t)\n\n\tr8 := ZipBy9(\n\t\t[]string{\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\", \"h\", \"i\"},\n\t\t[]int{1, 2, 3, 4, 5, 6, 7, 8, 9},\n\t\t[]int{10, 11, 12, 13, 14, 15, 16, 17, 18},\n\t\t[]bool{true, true, true, true, true, true, true, true, true},\n\t\t[]float32{0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9},\n\t\t[]float64{0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09},\n\t\t[]int8{1, 2, 3, 4, 5, 6, 7, 8, 9},\n\t\t[]int16{1, 2, 3, 4, 5, 6, 7, 8, 9},\n\t\t[]int32{1, 2, 3, 4, 5, 6, 7, 8, 9},\n\t\tT9[string, int, int, bool, float32, float64, int8, int16, int32],\n\t)\n\n\tis.Equal([]Tuple2[string, int]{\n\t\t{A: \"a\", B: 1},\n\t\t{A: \"b\", B: 2},\n\t}, r1)\n\n\tis.Equal([]Tuple3[string, int, int]{\n\t\t{A: \"a\", B: 1, C: 4},\n\t\t{A: \"b\", B: 2, C: 5},\n\t\t{A: \"c\", B: 3, C: 6},\n\t}, r2)\n\n\tis.Equal([]Tuple4[string, int, int, bool]{\n\t\t{A: \"a\", B: 1, C: 5, D: true},\n\t\t{A: \"b\", B: 2, C: 6, D: true},\n\t\t{A: \"c\", B: 3, C: 7, D: true},\n\t\t{A: \"d\", B: 4, C: 8, D: true},\n\t}, r3)\n\n\tis.Equal([]Tuple5[string, int, int, bool, float32]{\n\t\t{A: \"a\", B: 1, C: 6, D: true, E: 0.1},\n\t\t{A: \"b\", B: 2, C: 7, D: true, E: 0.2},\n\t\t{A: \"c\", B: 3, C: 8, D: true, E: 0.3},\n\t\t{A: \"d\", B: 4, C: 9, D: true, E: 0.4},\n\t\t{A: \"e\", B: 5, C: 10, D: true, E: 0.5},\n\t}, r4)\n\n\tis.Equal([]Tuple6[string, int, int, bool, float32, float64]{\n\t\t{A: \"a\", B: 1, C: 7, D: true, E: 0.1, F: 0.01},\n\t\t{A: \"b\", B: 2, C: 8, D: true, E: 0.2, F: 0.02},\n\t\t{A: \"c\", B: 3, C: 9, D: true, E: 0.3, F: 0.03},\n\t\t{A: \"d\", B: 4, C: 10, D: true, E: 0.4, F: 0.04},\n\t\t{A: \"e\", B: 5, C: 11, D: true, E: 0.5, F: 0.05},\n\t\t{A: \"f\", B: 6, C: 12, D: true, E: 0.6, F: 0.06},\n\t}, r5)\n\n\tis.Equal([]Tuple7[string, int, int, bool, float32, float64, int8]{\n\t\t{A: \"a\", B: 1, C: 8, D: true, E: 0.1, F: 0.01, G: 1},\n\t\t{A: \"b\", B: 2, C: 9, D: true, E: 0.2, F: 0.02, G: 2},\n\t\t{A: \"c\", B: 3, C: 10, D: true, E: 0.3, F: 0.03, G: 3},\n\t\t{A: \"d\", B: 4, C: 11, D: true, E: 0.4, F: 0.04, G: 4},\n\t\t{A: \"e\", B: 5, C: 12, D: true, E: 0.5, F: 0.05, G: 5},\n\t\t{A: \"f\", B: 6, C: 13, D: true, E: 0.6, F: 0.06, G: 6},\n\t\t{A: \"g\", B: 7, C: 14, D: true, E: 0.7, F: 0.07, G: 7},\n\t}, r6)\n\n\tis.Equal([]Tuple8[string, int, int, bool, float32, float64, int8, int16]{\n\t\t{A: \"a\", B: 1, C: 9, D: true, E: 0.1, F: 0.01, G: 1, H: 1},\n\t\t{A: \"b\", B: 2, C: 10, D: true, E: 0.2, F: 0.02, G: 2, H: 2},\n\t\t{A: \"c\", B: 3, C: 11, D: true, E: 0.3, F: 0.03, G: 3, H: 3},\n\t\t{A: \"d\", B: 4, C: 12, D: true, E: 0.4, F: 0.04, G: 4, H: 4},\n\t\t{A: \"e\", B: 5, C: 13, D: true, E: 0.5, F: 0.05, G: 5, H: 5},\n\t\t{A: \"f\", B: 6, C: 14, D: true, E: 0.6, F: 0.06, G: 6, H: 6},\n\t\t{A: \"g\", B: 7, C: 15, D: true, E: 0.7, F: 0.07, G: 7, H: 7},\n\t\t{A: \"h\", B: 8, C: 16, D: true, E: 0.8, F: 0.08, G: 8, H: 8},\n\t}, r7)\n\n\tis.Equal([]Tuple9[string, int, int, bool, float32, float64, int8, int16, int32]{\n\t\t{A: \"a\", B: 1, C: 10, D: true, E: 0.1, F: 0.01, G: 1, H: 1, I: 1},\n\t\t{A: \"b\", B: 2, C: 11, D: true, E: 0.2, F: 0.02, G: 2, H: 2, I: 2},\n\t\t{A: \"c\", B: 3, C: 12, D: true, E: 0.3, F: 0.03, G: 3, H: 3, I: 3},\n\t\t{A: \"d\", B: 4, C: 13, D: true, E: 0.4, F: 0.04, G: 4, H: 4, I: 4},\n\t\t{A: \"e\", B: 5, C: 14, D: true, E: 0.5, F: 0.05, G: 5, H: 5, I: 5},\n\t\t{A: \"f\", B: 6, C: 15, D: true, E: 0.6, F: 0.06, G: 6, H: 6, I: 6},\n\t\t{A: \"g\", B: 7, C: 16, D: true, E: 0.7, F: 0.07, G: 7, H: 7, I: 7},\n\t\t{A: \"h\", B: 8, C: 17, D: true, E: 0.8, F: 0.08, G: 8, H: 8, I: 8},\n\t\t{A: \"i\", B: 9, C: 18, D: true, E: 0.9, F: 0.09, G: 9, H: 9, I: 9},\n\t}, r8)\n}\n\nfunc TestUnzip(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tr1, r2 := Unzip2([]Tuple2[string, int]{{A: \"a\", B: 1}, {A: \"b\", B: 2}})\n\n\tis.Equal([]string{\"a\", \"b\"}, r1)\n\tis.Equal([]int{1, 2}, r2)\n}\n\nfunc TestUnzipBy(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tr1, r2 := UnzipBy2([]Tuple2[string, int]{{A: \"a\", B: 1}, {A: \"b\", B: 2}}, func(i Tuple2[string, int]) (string, int) {\n\t\treturn i.A + i.A, i.B + i.B\n\t})\n\n\tis.Equal([]string{\"aa\", \"bb\"}, r1)\n\tis.Equal([]int{2, 4}, r2)\n}\n\nfunc TestZipByErr(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\t// Test ZipByErr2\n\tt.Run(\"ZipByErr2\", func(t *testing.T) {\n\t\tt.Parallel()\n\n\t\ttests := []struct {\n\t\t\tname                  string\n\t\t\ta                     []string\n\t\t\tb                     []int\n\t\t\titeratee              func(a string, b int) (string, error)\n\t\t\twantResult            []string\n\t\t\twantErr               bool\n\t\t\terrMsg                string\n\t\t\texpectedCallbackCount int\n\t\t}{\n\t\t\t{\n\t\t\t\tname: \"successful transformation\",\n\t\t\t\ta:    []string{\"a\", \"b\"},\n\t\t\t\tb:    []int{1, 2},\n\t\t\t\titeratee: func(a string, b int) (string, error) {\n\t\t\t\t\treturn a + \"-\" + strconv.Itoa(b), nil\n\t\t\t\t},\n\t\t\t\twantResult:            []string{\"a-1\", \"b-2\"},\n\t\t\t\twantErr:               false,\n\t\t\t\texpectedCallbackCount: 2,\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"error at second element stops iteration\",\n\t\t\t\ta:    []string{\"a\", \"b\"},\n\t\t\t\tb:    []int{1, 2},\n\t\t\t\titeratee: func(a string, b int) (string, error) {\n\t\t\t\t\tif b == 2 {\n\t\t\t\t\t\treturn \"\", errors.New(\"number 2 is not allowed\")\n\t\t\t\t\t}\n\t\t\t\t\treturn a + \"-\" + strconv.Itoa(b), nil\n\t\t\t\t},\n\t\t\t\twantResult:            nil,\n\t\t\t\twantErr:               true,\n\t\t\t\terrMsg:                \"number 2 is not allowed\",\n\t\t\t\texpectedCallbackCount: 2,\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"error at first element stops iteration immediately\",\n\t\t\t\ta:    []string{\"a\", \"b\"},\n\t\t\t\tb:    []int{1, 2},\n\t\t\t\titeratee: func(a string, b int) (string, error) {\n\t\t\t\t\treturn \"\", errors.New(\"first error\")\n\t\t\t\t},\n\t\t\t\twantResult:            nil,\n\t\t\t\twantErr:               true,\n\t\t\t\terrMsg:                \"first error\",\n\t\t\t\texpectedCallbackCount: 1,\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"empty input slices\",\n\t\t\t\ta:    []string{},\n\t\t\t\tb:    []int{},\n\t\t\t\titeratee: func(a string, b int) (string, error) {\n\t\t\t\t\treturn a + \"-\" + strconv.Itoa(b), nil\n\t\t\t\t},\n\t\t\t\twantResult:            []string{},\n\t\t\t\twantErr:               false,\n\t\t\t\texpectedCallbackCount: 0,\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"unequal slice lengths - zero value filled\",\n\t\t\t\ta:    []string{\"a\", \"b\", \"c\"},\n\t\t\t\tb:    []int{1},\n\t\t\t\titeratee: func(a string, b int) (string, error) {\n\t\t\t\t\tif b == 0 {\n\t\t\t\t\t\treturn \"\", errors.New(\"zero value not allowed\")\n\t\t\t\t\t}\n\t\t\t\t\treturn a + \"-\" + strconv.Itoa(b), nil\n\t\t\t\t},\n\t\t\t\twantResult:            nil,\n\t\t\t\twantErr:               true,\n\t\t\t\terrMsg:                \"zero value not allowed\",\n\t\t\t\texpectedCallbackCount: 2,\n\t\t\t},\n\t\t}\n\n\t\tfor _, tt := range tests {\n\t\t\ttt := tt\n\t\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\t\tt.Parallel()\n\n\t\t\t\tcallbackCount := 0\n\t\t\t\titeratee := func(a string, b int) (string, error) {\n\t\t\t\t\tcallbackCount++\n\t\t\t\t\treturn tt.iteratee(a, b)\n\t\t\t\t}\n\n\t\t\t\tresult, err := ZipByErr2(tt.a, tt.b, iteratee)\n\n\t\t\t\tis.Equal(tt.wantResult, result)\n\t\t\t\tif tt.wantErr {\n\t\t\t\t\tis.Error(err)\n\t\t\t\t\tif tt.errMsg != \"\" {\n\t\t\t\t\t\tis.ErrorContains(err, tt.errMsg)\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tis.NoError(err)\n\t\t\t\t}\n\t\t\t\tis.Equal(tt.expectedCallbackCount, callbackCount)\n\t\t\t})\n\t\t}\n\t})\n\n\t// Test ZipByErr3\n\tt.Run(\"ZipByErr3\", func(t *testing.T) {\n\t\tt.Parallel()\n\n\t\ttests := []struct {\n\t\t\tname                  string\n\t\t\ta                     []string\n\t\t\tb                     []int\n\t\t\tc                     []bool\n\t\t\titeratee              func(a string, b int, c bool) (string, error)\n\t\t\twantResult            []string\n\t\t\twantErr               bool\n\t\t\terrMsg                string\n\t\t\texpectedCallbackCount int\n\t\t}{\n\t\t\t{\n\t\t\t\tname: \"successful transformation\",\n\t\t\t\ta:    []string{\"a\", \"b\"},\n\t\t\t\tb:    []int{1, 2},\n\t\t\t\tc:    []bool{true, false},\n\t\t\t\titeratee: func(a string, b int, c bool) (string, error) {\n\t\t\t\t\treturn a + \"-\" + strconv.Itoa(b) + \"-\" + strconv.FormatBool(c), nil\n\t\t\t\t},\n\t\t\t\twantResult:            []string{\"a-1-true\", \"b-2-false\"},\n\t\t\t\twantErr:               false,\n\t\t\t\texpectedCallbackCount: 2,\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"error at second element stops iteration\",\n\t\t\t\ta:    []string{\"a\", \"b\"},\n\t\t\t\tb:    []int{1, 2},\n\t\t\t\tc:    []bool{true, false},\n\t\t\t\titeratee: func(a string, b int, c bool) (string, error) {\n\t\t\t\t\tif b == 2 {\n\t\t\t\t\t\treturn \"\", errors.New(\"number 2 is not allowed\")\n\t\t\t\t\t}\n\t\t\t\t\treturn a + \"-\" + strconv.Itoa(b) + \"-\" + strconv.FormatBool(c), nil\n\t\t\t\t},\n\t\t\t\twantResult:            nil,\n\t\t\t\twantErr:               true,\n\t\t\t\terrMsg:                \"number 2 is not allowed\",\n\t\t\t\texpectedCallbackCount: 2,\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"error at first element\",\n\t\t\t\ta:    []string{\"a\", \"b\"},\n\t\t\t\tb:    []int{1, 2},\n\t\t\t\tc:    []bool{true, false},\n\t\t\t\titeratee: func(a string, b int, c bool) (string, error) {\n\t\t\t\t\treturn \"\", errors.New(\"first error\")\n\t\t\t\t},\n\t\t\t\twantResult:            nil,\n\t\t\t\twantErr:               true,\n\t\t\t\terrMsg:                \"first error\",\n\t\t\t\texpectedCallbackCount: 1,\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"empty input slices\",\n\t\t\t\ta:    []string{},\n\t\t\t\tb:    []int{},\n\t\t\t\tc:    []bool{},\n\t\t\t\titeratee: func(a string, b int, c bool) (string, error) {\n\t\t\t\t\treturn a + \"-\" + strconv.Itoa(b) + \"-\" + strconv.FormatBool(c), nil\n\t\t\t\t},\n\t\t\t\twantResult:            []string{},\n\t\t\t\twantErr:               false,\n\t\t\t\texpectedCallbackCount: 0,\n\t\t\t},\n\t\t}\n\n\t\tfor _, tt := range tests {\n\t\t\ttt := tt\n\t\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\t\tt.Parallel()\n\n\t\t\t\tcallbackCount := 0\n\t\t\t\titeratee := func(a string, b int, c bool) (string, error) {\n\t\t\t\t\tcallbackCount++\n\t\t\t\t\treturn tt.iteratee(a, b, c)\n\t\t\t\t}\n\n\t\t\t\tresult, err := ZipByErr3(tt.a, tt.b, tt.c, iteratee)\n\n\t\t\t\tis.Equal(tt.wantResult, result)\n\t\t\t\tif tt.wantErr {\n\t\t\t\t\tis.Error(err)\n\t\t\t\t\tif tt.errMsg != \"\" {\n\t\t\t\t\t\tis.ErrorContains(err, tt.errMsg)\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tis.NoError(err)\n\t\t\t\t}\n\t\t\t\tis.Equal(tt.expectedCallbackCount, callbackCount)\n\t\t\t})\n\t\t}\n\t})\n\n\t// Test ZipByErr4\n\tt.Run(\"ZipByErr4\", func(t *testing.T) {\n\t\tt.Parallel()\n\t\tis := assert.New(t)\n\n\t\ttests := []struct {\n\t\t\tname                  string\n\t\t\ta                     []string\n\t\t\tb                     []int\n\t\t\tc                     []bool\n\t\t\td                     []float32\n\t\t\titeratee              func(a string, b int, c bool, d float32) (string, error)\n\t\t\twantResult            []string\n\t\t\twantErr               bool\n\t\t\texpectedCallbackCount int\n\t\t}{\n\t\t\t{\n\t\t\t\tname: \"successful transformation\",\n\t\t\t\ta:    []string{\"a\", \"b\"},\n\t\t\t\tb:    []int{1, 2},\n\t\t\t\tc:    []bool{true, false},\n\t\t\t\td:    []float32{1.1, 2.2},\n\t\t\t\titeratee: func(a string, b int, c bool, d float32) (string, error) {\n\t\t\t\t\treturn a + \"-\" + strconv.Itoa(b), nil\n\t\t\t\t},\n\t\t\t\twantResult:            []string{\"a-1\", \"b-2\"},\n\t\t\t\twantErr:               false,\n\t\t\t\texpectedCallbackCount: 2,\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"error stops iteration\",\n\t\t\t\ta:    []string{\"a\", \"b\"},\n\t\t\t\tb:    []int{1, 2},\n\t\t\t\tc:    []bool{true, false},\n\t\t\t\td:    []float32{1.1, 2.2},\n\t\t\t\titeratee: func(a string, b int, c bool, d float32) (string, error) {\n\t\t\t\t\tif b == 2 {\n\t\t\t\t\t\treturn \"\", errors.New(\"error\")\n\t\t\t\t\t}\n\t\t\t\t\treturn a + \"-\" + strconv.Itoa(b), nil\n\t\t\t\t},\n\t\t\t\twantResult:            nil,\n\t\t\t\twantErr:               true,\n\t\t\t\texpectedCallbackCount: 2,\n\t\t\t},\n\t\t}\n\n\t\tfor _, tt := range tests {\n\t\t\ttt := tt\n\t\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\t\tt.Parallel()\n\n\t\t\t\tcallbackCount := 0\n\t\t\t\titeratee := func(a string, b int, c bool, d float32) (string, error) {\n\t\t\t\t\tcallbackCount++\n\t\t\t\t\treturn tt.iteratee(a, b, c, d)\n\t\t\t\t}\n\n\t\t\t\tresult, err := ZipByErr4(tt.a, tt.b, tt.c, tt.d, iteratee)\n\n\t\t\t\tis.Equal(tt.wantResult, result)\n\t\t\t\tif tt.wantErr {\n\t\t\t\t\tis.Error(err)\n\t\t\t\t} else {\n\t\t\t\t\tis.NoError(err)\n\t\t\t\t}\n\t\t\t\tis.Equal(tt.expectedCallbackCount, callbackCount)\n\t\t\t})\n\t\t}\n\t})\n\n\t// Test ZipByErr5\n\tt.Run(\"ZipByErr5\", func(t *testing.T) {\n\t\tt.Parallel()\n\t\tis := assert.New(t)\n\n\t\tcallbackCount := 0\n\t\tresult, err := ZipByErr5(\n\t\t\t[]string{\"a\", \"b\"},\n\t\t\t[]int{1, 2},\n\t\t\t[]bool{true, false},\n\t\t\t[]float32{1.1, 2.2},\n\t\t\t[]float64{0.1, 0.2},\n\t\t\tfunc(a string, b int, c bool, d float32, e float64) (string, error) {\n\t\t\t\tcallbackCount++\n\t\t\t\treturn a + \"-\" + strconv.Itoa(b), nil\n\t\t\t},\n\t\t)\n\n\t\tis.Equal([]string{\"a-1\", \"b-2\"}, result)\n\t\tis.NoError(err)\n\t\tis.Equal(2, callbackCount)\n\t})\n\n\t// Test ZipByErr6\n\tt.Run(\"ZipByErr6\", func(t *testing.T) {\n\t\tt.Parallel()\n\t\tis := assert.New(t)\n\n\t\tcallbackCount := 0\n\t\tresult, err := ZipByErr6(\n\t\t\t[]string{\"a\", \"b\"},\n\t\t\t[]int{1, 2},\n\t\t\t[]bool{true, false},\n\t\t\t[]float32{1.1, 2.2},\n\t\t\t[]float64{0.1, 0.2},\n\t\t\t[]int8{1, 2},\n\t\t\tfunc(a string, b int, c bool, d float32, e float64, f int8) (string, error) {\n\t\t\t\tcallbackCount++\n\t\t\t\treturn a + \"-\" + strconv.Itoa(b), nil\n\t\t\t},\n\t\t)\n\n\t\tis.Equal([]string{\"a-1\", \"b-2\"}, result)\n\t\tis.NoError(err)\n\t\tis.Equal(2, callbackCount)\n\t})\n\n\t// Test ZipByErr7\n\tt.Run(\"ZipByErr7\", func(t *testing.T) {\n\t\tt.Parallel()\n\t\tis := assert.New(t)\n\n\t\tcallbackCount := 0\n\t\tresult, err := ZipByErr7(\n\t\t\t[]string{\"a\", \"b\"},\n\t\t\t[]int{1, 2},\n\t\t\t[]bool{true, false},\n\t\t\t[]float32{1.1, 2.2},\n\t\t\t[]float64{0.1, 0.2},\n\t\t\t[]int8{1, 2},\n\t\t\t[]int16{3, 4},\n\t\t\tfunc(a string, b int, c bool, d float32, e float64, f int8, g int16) (string, error) {\n\t\t\t\tcallbackCount++\n\t\t\t\treturn a + \"-\" + strconv.Itoa(b), nil\n\t\t\t},\n\t\t)\n\n\t\tis.Equal([]string{\"a-1\", \"b-2\"}, result)\n\t\tis.NoError(err)\n\t\tis.Equal(2, callbackCount)\n\t})\n\n\t// Test ZipByErr8\n\tt.Run(\"ZipByErr8\", func(t *testing.T) {\n\t\tt.Parallel()\n\t\tis := assert.New(t)\n\n\t\tcallbackCount := 0\n\t\tresult, err := ZipByErr8(\n\t\t\t[]string{\"a\", \"b\"},\n\t\t\t[]int{1, 2},\n\t\t\t[]bool{true, false},\n\t\t\t[]float32{1.1, 2.2},\n\t\t\t[]float64{0.1, 0.2},\n\t\t\t[]int8{1, 2},\n\t\t\t[]int16{3, 4},\n\t\t\t[]int32{5, 6},\n\t\t\tfunc(a string, b int, c bool, d float32, e float64, f int8, g int16, h int32) (string, error) {\n\t\t\t\tcallbackCount++\n\t\t\t\treturn a + \"-\" + strconv.Itoa(b), nil\n\t\t\t},\n\t\t)\n\n\t\tis.Equal([]string{\"a-1\", \"b-2\"}, result)\n\t\tis.NoError(err)\n\t\tis.Equal(2, callbackCount)\n\t})\n\n\t// Test ZipByErr9\n\tt.Run(\"ZipByErr9\", func(t *testing.T) {\n\t\tt.Parallel()\n\t\tis := assert.New(t)\n\n\t\tcallbackCount := 0\n\t\tresult, err := ZipByErr9(\n\t\t\t[]string{\"a\", \"b\"},\n\t\t\t[]int{1, 2},\n\t\t\t[]bool{true, false},\n\t\t\t[]float32{1.1, 2.2},\n\t\t\t[]float64{0.1, 0.2},\n\t\t\t[]int8{1, 2},\n\t\t\t[]int16{3, 4},\n\t\t\t[]int32{5, 6},\n\t\t\t[]int64{7, 8},\n\t\t\tfunc(a string, b int, c bool, d float32, e float64, f int8, g int16, h int32, i int64) (string, error) {\n\t\t\t\tcallbackCount++\n\t\t\t\treturn a + \"-\" + strconv.Itoa(b), nil\n\t\t\t},\n\t\t)\n\n\t\tis.Equal([]string{\"a-1\", \"b-2\"}, result)\n\t\tis.NoError(err)\n\t\tis.Equal(2, callbackCount)\n\t})\n}\n\nfunc TestCrossJoin(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tlistOne := []string{\"a\", \"b\", \"c\"}\n\tlistTwo := []int{1, 2, 3}\n\temptyList := []any{}\n\tmixedList := []any{9.6, 4, \"foobar\"}\n\n\tresults1 := CrossJoin2(emptyList, listTwo)\n\tis.Empty(results1)\n\n\tresults2 := CrossJoin2(listOne, emptyList)\n\tis.Empty(results2)\n\n\tresults3 := CrossJoin2(emptyList, emptyList)\n\tis.Empty(results3)\n\n\tresults4 := CrossJoin2([]string{\"a\"}, listTwo)\n\tis.Equal([]Tuple2[string, int]{T2(\"a\", 1), T2(\"a\", 2), T2(\"a\", 3)}, results4)\n\n\tresults5 := CrossJoin2(listOne, []int{1})\n\tis.Equal([]Tuple2[string, int]{T2(\"a\", 1), T2(\"b\", 1), T2(\"c\", 1)}, results5)\n\n\tresults6 := CrossJoin2(listOne, listTwo)\n\tis.Equal([]Tuple2[string, int]{T2(\"a\", 1), T2(\"a\", 2), T2(\"a\", 3), T2(\"b\", 1), T2(\"b\", 2), T2(\"b\", 3), T2(\"c\", 1), T2(\"c\", 2), T2(\"c\", 3)}, results6)\n\n\tresults7 := CrossJoin2(listOne, mixedList)\n\tis.Equal([]Tuple2[string, any]{T2[string, any](\"a\", 9.6), T2[string, any](\"a\", 4), T2[string, any](\"a\", \"foobar\"), T2[string, any](\"b\", 9.6), T2[string, any](\"b\", 4), T2[string, any](\"b\", \"foobar\"), T2[string, any](\"c\", 9.6), T2[string, any](\"c\", 4), T2[string, any](\"c\", \"foobar\")}, results7)\n}\n\nfunc TestCrossJoinBy(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tlistOne := []string{\"a\", \"b\", \"c\"}\n\tlistTwo := []int{1, 2, 3}\n\temptyList := []any{}\n\tmixedList := []any{9.6, 4, \"foobar\"}\n\n\tresults1 := CrossJoinBy2(emptyList, listTwo, T2[any, int])\n\tis.Empty(results1)\n\n\tresults2 := CrossJoinBy2(listOne, emptyList, T2[string, any])\n\tis.Empty(results2)\n\n\tresults3 := CrossJoinBy2(emptyList, emptyList, T2[any, any])\n\tis.Empty(results3)\n\n\tresults4 := CrossJoinBy2([]string{\"a\"}, listTwo, T2[string, int])\n\tis.Equal([]Tuple2[string, int]{T2(\"a\", 1), T2(\"a\", 2), T2(\"a\", 3)}, results4)\n\n\tresults5 := CrossJoinBy2(listOne, []int{1}, T2[string, int])\n\tis.Equal([]Tuple2[string, int]{T2(\"a\", 1), T2(\"b\", 1), T2(\"c\", 1)}, results5)\n\n\tresults6 := CrossJoinBy2(listOne, listTwo, T2[string, int])\n\tis.Equal([]Tuple2[string, int]{T2(\"a\", 1), T2(\"a\", 2), T2(\"a\", 3), T2(\"b\", 1), T2(\"b\", 2), T2(\"b\", 3), T2(\"c\", 1), T2(\"c\", 2), T2(\"c\", 3)}, results6)\n\n\tresults7 := CrossJoinBy2(listOne, mixedList, T2[string, any])\n\tis.Equal([]Tuple2[string, any]{T2[string, any](\"a\", 9.6), T2[string, any](\"a\", 4), T2[string, any](\"a\", \"foobar\"), T2[string, any](\"b\", 9.6), T2[string, any](\"b\", 4), T2[string, any](\"b\", \"foobar\"), T2[string, any](\"c\", 9.6), T2[string, any](\"c\", 4), T2[string, any](\"c\", \"foobar\")}, results7)\n}\n\nfunc TestCrossJoinByErr(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\t// Test CrossJoinByErr2\n\tt.Run(\"CrossJoinByErr2\", func(t *testing.T) {\n\t\tt.Parallel()\n\n\t\ttests := []struct {\n\t\t\tname                  string\n\t\t\tlistA                 []string\n\t\t\tlistB                 []int\n\t\t\ttransform             func(a string, b int) (string, error)\n\t\t\twantResult            []string\n\t\t\twantErr               bool\n\t\t\terrMsg                string\n\t\t\texpectedCallbackCount int\n\t\t}{\n\t\t\t{\n\t\t\t\tname:  \"successful transformation\",\n\t\t\t\tlistA: []string{\"a\", \"b\"},\n\t\t\t\tlistB: []int{1, 2},\n\t\t\t\ttransform: func(a string, b int) (string, error) {\n\t\t\t\t\treturn a + \"-\" + strconv.Itoa(b), nil\n\t\t\t\t},\n\t\t\t\twantResult:            []string{\"a-1\", \"a-2\", \"b-1\", \"b-2\"},\n\t\t\t\twantErr:               false,\n\t\t\t\texpectedCallbackCount: 4,\n\t\t\t},\n\t\t\t{\n\t\t\t\tname:  \"error stops iteration early\",\n\t\t\t\tlistA: []string{\"a\", \"b\"},\n\t\t\t\tlistB: []int{1, 2},\n\t\t\t\ttransform: func(a string, b int) (string, error) {\n\t\t\t\t\tif a == \"b\" {\n\t\t\t\t\t\treturn \"\", errors.New(\"b not allowed\")\n\t\t\t\t\t}\n\t\t\t\t\treturn a + \"-\" + strconv.Itoa(b), nil\n\t\t\t\t},\n\t\t\t\twantResult:            nil,\n\t\t\t\twantErr:               true,\n\t\t\t\terrMsg:                \"b not allowed\",\n\t\t\t\texpectedCallbackCount: 3, // a-1, a-2, then b-1 errors\n\t\t\t},\n\t\t\t{\n\t\t\t\tname:                  \"empty list returns empty result\",\n\t\t\t\tlistA:                 []string{},\n\t\t\t\tlistB:                 []int{1, 2},\n\t\t\t\ttransform:             func(a string, b int) (string, error) { return a + \"-\" + strconv.Itoa(b), nil },\n\t\t\t\twantResult:            []string{},\n\t\t\t\twantErr:               false,\n\t\t\t\texpectedCallbackCount: 0,\n\t\t\t},\n\t\t}\n\n\t\tfor _, tt := range tests {\n\t\t\ttt := tt\n\t\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\t\tt.Parallel()\n\n\t\t\t\tcallbackCount := 0\n\t\t\t\ttransform := func(a string, b int) (string, error) {\n\t\t\t\t\tcallbackCount++\n\t\t\t\t\treturn tt.transform(a, b)\n\t\t\t\t}\n\n\t\t\t\tresult, err := CrossJoinByErr2(tt.listA, tt.listB, transform)\n\n\t\t\t\tis.Equal(tt.wantResult, result)\n\t\t\t\tif tt.wantErr {\n\t\t\t\t\tis.Error(err)\n\t\t\t\t\tif tt.errMsg != \"\" {\n\t\t\t\t\t\tis.ErrorContains(err, tt.errMsg)\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tis.NoError(err)\n\t\t\t\t}\n\t\t\t\tis.Equal(tt.expectedCallbackCount, callbackCount)\n\t\t\t})\n\t\t}\n\t})\n\n\t// Test CrossJoinByErr3\n\tt.Run(\"CrossJoinByErr3\", func(t *testing.T) {\n\t\tt.Parallel()\n\n\t\ttests := []struct {\n\t\t\tname                  string\n\t\t\tlistA                 []string\n\t\t\tlistB                 []int\n\t\t\tlistC                 []bool\n\t\t\ttransform             func(a string, b int, c bool) (string, error)\n\t\t\twantResult            []string\n\t\t\twantErr               bool\n\t\t\texpectedCallbackCount int\n\t\t}{\n\t\t\t{\n\t\t\t\tname:  \"successful transformation\",\n\t\t\t\tlistA: []string{\"a\", \"b\"},\n\t\t\t\tlistB: []int{1, 2},\n\t\t\t\tlistC: []bool{true, false},\n\t\t\t\ttransform: func(a string, b int, c bool) (string, error) {\n\t\t\t\t\treturn a + \"-\" + strconv.Itoa(b), nil\n\t\t\t\t},\n\t\t\t\twantResult:            []string{\"a-1\", \"a-1\", \"a-2\", \"a-2\", \"b-1\", \"b-1\", \"b-2\", \"b-2\"},\n\t\t\t\twantErr:               false,\n\t\t\t\texpectedCallbackCount: 8,\n\t\t\t},\n\t\t\t{\n\t\t\t\tname:  \"error stops iteration early\",\n\t\t\t\tlistA: []string{\"a\", \"b\"},\n\t\t\t\tlistB: []int{1, 2},\n\t\t\t\tlistC: []bool{true, false},\n\t\t\t\ttransform: func(a string, b int, c bool) (string, error) {\n\t\t\t\t\tif a == \"b\" && b == 2 {\n\t\t\t\t\t\treturn \"\", errors.New(\"error\")\n\t\t\t\t\t}\n\t\t\t\t\treturn a + \"-\" + strconv.Itoa(b), nil\n\t\t\t\t},\n\t\t\t\twantResult:            nil,\n\t\t\t\twantErr:               true,\n\t\t\t\texpectedCallbackCount: 7,\n\t\t\t},\n\t\t}\n\n\t\tfor _, tt := range tests {\n\t\t\ttt := tt\n\t\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\t\tt.Parallel()\n\n\t\t\t\tcallbackCount := 0\n\t\t\t\ttransform := func(a string, b int, c bool) (string, error) {\n\t\t\t\t\tcallbackCount++\n\t\t\t\t\treturn tt.transform(a, b, c)\n\t\t\t\t}\n\n\t\t\t\tresult, err := CrossJoinByErr3(tt.listA, tt.listB, tt.listC, transform)\n\n\t\t\t\tis.Equal(tt.wantResult, result)\n\t\t\t\tif tt.wantErr {\n\t\t\t\t\tis.Error(err)\n\t\t\t\t} else {\n\t\t\t\t\tis.NoError(err)\n\t\t\t\t}\n\t\t\t\tis.Equal(tt.expectedCallbackCount, callbackCount)\n\t\t\t})\n\t\t}\n\t})\n\n\t// Test CrossJoinByErr4\n\tt.Run(\"CrossJoinByErr4\", func(t *testing.T) {\n\t\tt.Parallel()\n\t\tis := assert.New(t)\n\n\t\tcallbackCount := 0\n\t\tresult, err := CrossJoinByErr4(\n\t\t\t[]string{\"a\", \"b\"},\n\t\t\t[]int{1, 2},\n\t\t\t[]bool{true},\n\t\t\t[]float32{1.1},\n\t\t\tfunc(a string, b int, c bool, d float32) (string, error) {\n\t\t\t\tcallbackCount++\n\t\t\t\treturn a + \"-\" + strconv.Itoa(b), nil\n\t\t\t},\n\t\t)\n\n\t\tis.Len(result, 4)\n\t\tis.NoError(err)\n\t\tis.Equal(4, callbackCount)\n\t})\n\n\t// Test CrossJoinByErr5\n\tt.Run(\"CrossJoinByErr5\", func(t *testing.T) {\n\t\tt.Parallel()\n\t\tis := assert.New(t)\n\n\t\tcallbackCount := 0\n\t\tresult, err := CrossJoinByErr5(\n\t\t\t[]string{\"a\", \"b\"},\n\t\t\t[]int{1},\n\t\t\t[]bool{true},\n\t\t\t[]float32{1.1},\n\t\t\t[]float64{2.2},\n\t\t\tfunc(a string, b int, c bool, d float32, e float64) (string, error) {\n\t\t\t\tcallbackCount++\n\t\t\t\treturn a + \"-\" + strconv.Itoa(b), nil\n\t\t\t},\n\t\t)\n\n\t\tis.Len(result, 2)\n\t\tis.NoError(err)\n\t\tis.Equal(2, callbackCount)\n\t})\n\n\t// Test CrossJoinByErr6\n\tt.Run(\"CrossJoinByErr6\", func(t *testing.T) {\n\t\tt.Parallel()\n\t\tis := assert.New(t)\n\n\t\tcallbackCount := 0\n\t\tresult, err := CrossJoinByErr6(\n\t\t\t[]string{\"a\"},\n\t\t\t[]int{1},\n\t\t\t[]bool{true},\n\t\t\t[]float32{1.1},\n\t\t\t[]float64{2.2},\n\t\t\t[]int8{3},\n\t\t\tfunc(a string, b int, c bool, d float32, e float64, f int8) (string, error) {\n\t\t\t\tcallbackCount++\n\t\t\t\treturn a + \"-\" + strconv.Itoa(b), nil\n\t\t\t},\n\t\t)\n\n\t\tis.Len(result, 1)\n\t\tis.NoError(err)\n\t\tis.Equal(1, callbackCount)\n\t})\n\n\t// Test CrossJoinByErr7\n\tt.Run(\"CrossJoinByErr7\", func(t *testing.T) {\n\t\tt.Parallel()\n\t\tis := assert.New(t)\n\n\t\tcallbackCount := 0\n\t\tresult, err := CrossJoinByErr7(\n\t\t\t[]string{\"a\"},\n\t\t\t[]int{1},\n\t\t\t[]bool{true},\n\t\t\t[]float32{1.1},\n\t\t\t[]float64{2.2},\n\t\t\t[]int8{3},\n\t\t\t[]int16{4},\n\t\t\tfunc(a string, b int, c bool, d float32, e float64, f int8, g int16) (string, error) {\n\t\t\t\tcallbackCount++\n\t\t\t\treturn a + \"-\" + strconv.Itoa(b), nil\n\t\t\t},\n\t\t)\n\n\t\tis.Len(result, 1)\n\t\tis.NoError(err)\n\t\tis.Equal(1, callbackCount)\n\t})\n\n\t// Test CrossJoinByErr8\n\tt.Run(\"CrossJoinByErr8\", func(t *testing.T) {\n\t\tt.Parallel()\n\t\tis := assert.New(t)\n\n\t\tcallbackCount := 0\n\t\tresult, err := CrossJoinByErr8(\n\t\t\t[]string{\"a\"},\n\t\t\t[]int{1},\n\t\t\t[]bool{true},\n\t\t\t[]float32{1.1},\n\t\t\t[]float64{2.2},\n\t\t\t[]int8{3},\n\t\t\t[]int16{4},\n\t\t\t[]int32{5},\n\t\t\tfunc(a string, b int, c bool, d float32, e float64, f int8, g int16, h int32) (string, error) {\n\t\t\t\tcallbackCount++\n\t\t\t\treturn a + \"-\" + strconv.Itoa(b), nil\n\t\t\t},\n\t\t)\n\n\t\tis.Len(result, 1)\n\t\tis.NoError(err)\n\t\tis.Equal(1, callbackCount)\n\t})\n\n\t// Test CrossJoinByErr9\n\tt.Run(\"CrossJoinByErr9\", func(t *testing.T) {\n\t\tt.Parallel()\n\t\tis := assert.New(t)\n\n\t\tcallbackCount := 0\n\t\tresult, err := CrossJoinByErr9(\n\t\t\t[]string{\"a\"},\n\t\t\t[]int{1},\n\t\t\t[]bool{true},\n\t\t\t[]float32{1.1},\n\t\t\t[]float64{2.2},\n\t\t\t[]int8{3},\n\t\t\t[]int16{4},\n\t\t\t[]int32{5},\n\t\t\t[]int64{6},\n\t\t\tfunc(a string, b int, c bool, d float32, e float64, f int8, g int16, h int32, i int64) (string, error) {\n\t\t\t\tcallbackCount++\n\t\t\t\treturn a + \"-\" + strconv.Itoa(b), nil\n\t\t\t},\n\t\t)\n\n\t\tis.Len(result, 1)\n\t\tis.NoError(err)\n\t\tis.Equal(1, callbackCount)\n\t})\n}\n\nfunc TestUnzipByErr(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\t// Test UnzipByErr2\n\tt.Run(\"UnzipByErr2\", func(t *testing.T) {\n\t\tt.Parallel()\n\n\t\ttests := []struct {\n\t\t\tname                  string\n\t\t\titems                 []string\n\t\t\titeratee              func(str string) (string, int, error)\n\t\t\twantR1                []string\n\t\t\twantR2                []int\n\t\t\twantErr               bool\n\t\t\terrMsg                string\n\t\t\texpectedCallbackCount int\n\t\t}{\n\t\t\t{\n\t\t\t\tname:  \"successful transformation\",\n\t\t\t\titems: []string{\"hello\", \"world\"},\n\t\t\t\titeratee: func(str string) (string, int, error) {\n\t\t\t\t\treturn strings.ToUpper(str), len(str), nil\n\t\t\t\t},\n\t\t\t\twantR1:                []string{\"HELLO\", \"WORLD\"},\n\t\t\t\twantR2:                []int{5, 5},\n\t\t\t\twantErr:               false,\n\t\t\t\texpectedCallbackCount: 2,\n\t\t\t},\n\t\t\t{\n\t\t\t\tname:  \"error at second element stops iteration\",\n\t\t\t\titems: []string{\"hello\", \"error\", \"world\"},\n\t\t\t\titeratee: func(str string) (string, int, error) {\n\t\t\t\t\tif str == \"error\" {\n\t\t\t\t\t\treturn \"\", 0, errors.New(\"error string not allowed\")\n\t\t\t\t\t}\n\t\t\t\t\treturn strings.ToUpper(str), len(str), nil\n\t\t\t\t},\n\t\t\t\twantR1:                nil,\n\t\t\t\twantR2:                nil,\n\t\t\t\twantErr:               true,\n\t\t\t\terrMsg:                \"error string not allowed\",\n\t\t\t\texpectedCallbackCount: 2,\n\t\t\t},\n\t\t\t{\n\t\t\t\tname:  \"error at first element stops immediately\",\n\t\t\t\titems: []string{\"error\", \"hello\", \"world\"},\n\t\t\t\titeratee: func(str string) (string, int, error) {\n\t\t\t\t\treturn \"\", 0, errors.New(\"first error\")\n\t\t\t\t},\n\t\t\t\twantR1:                nil,\n\t\t\t\twantR2:                nil,\n\t\t\t\twantErr:               true,\n\t\t\t\terrMsg:                \"first error\",\n\t\t\t\texpectedCallbackCount: 1,\n\t\t\t},\n\t\t\t{\n\t\t\t\tname:  \"empty input slices\",\n\t\t\t\titems: []string{},\n\t\t\t\titeratee: func(str string) (string, int, error) {\n\t\t\t\t\treturn strings.ToUpper(str), len(str), nil\n\t\t\t\t},\n\t\t\t\twantR1:                []string{},\n\t\t\t\twantR2:                []int{},\n\t\t\t\twantErr:               false,\n\t\t\t\texpectedCallbackCount: 0,\n\t\t\t},\n\t\t}\n\n\t\tfor _, tt := range tests {\n\t\t\ttt := tt\n\t\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\t\tt.Parallel()\n\n\t\t\t\tcallbackCount := 0\n\t\t\t\titeratee := func(str string) (string, int, error) {\n\t\t\t\t\tcallbackCount++\n\t\t\t\t\treturn tt.iteratee(str)\n\t\t\t\t}\n\n\t\t\t\tr1, r2, err := UnzipByErr2(tt.items, iteratee)\n\n\t\t\t\tis.Equal(tt.wantR1, r1)\n\t\t\t\tis.Equal(tt.wantR2, r2)\n\t\t\t\tif tt.wantErr {\n\t\t\t\t\tis.Error(err)\n\t\t\t\t\tif tt.errMsg != \"\" {\n\t\t\t\t\t\tis.ErrorContains(err, tt.errMsg)\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tis.NoError(err)\n\t\t\t\t}\n\t\t\t\tis.Equal(tt.expectedCallbackCount, callbackCount)\n\t\t\t})\n\t\t}\n\t})\n\n\t// Test UnzipByErr3\n\tt.Run(\"UnzipByErr3\", func(t *testing.T) {\n\t\tt.Parallel()\n\n\t\ttests := []struct {\n\t\t\tname                  string\n\t\t\titems                 []string\n\t\t\titeratee              func(str string) (string, int, bool, error)\n\t\t\twantR1                []string\n\t\t\twantR2                []int\n\t\t\twantR3                []bool\n\t\t\twantErr               bool\n\t\t\terrMsg                string\n\t\t\texpectedCallbackCount int\n\t\t}{\n\t\t\t{\n\t\t\t\tname:  \"successful transformation\",\n\t\t\t\titems: []string{\"hello\", \"world\"},\n\t\t\t\titeratee: func(str string) (string, int, bool, error) {\n\t\t\t\t\treturn strings.ToUpper(str), len(str), len(str) > 4, nil\n\t\t\t\t},\n\t\t\t\twantR1:                []string{\"HELLO\", \"WORLD\"},\n\t\t\t\twantR2:                []int{5, 5},\n\t\t\t\twantR3:                []bool{true, true},\n\t\t\t\twantErr:               false,\n\t\t\t\texpectedCallbackCount: 2,\n\t\t\t},\n\t\t\t{\n\t\t\t\tname:  \"error at second element stops iteration\",\n\t\t\t\titems: []string{\"hello\", \"error\", \"world\"},\n\t\t\t\titeratee: func(str string) (string, int, bool, error) {\n\t\t\t\t\tif str == \"error\" {\n\t\t\t\t\t\treturn \"\", 0, false, errors.New(\"error string not allowed\")\n\t\t\t\t\t}\n\t\t\t\t\treturn strings.ToUpper(str), len(str), len(str) > 4, nil\n\t\t\t\t},\n\t\t\t\twantR1:                nil,\n\t\t\t\twantR2:                nil,\n\t\t\t\twantR3:                nil,\n\t\t\t\twantErr:               true,\n\t\t\t\terrMsg:                \"error string not allowed\",\n\t\t\t\texpectedCallbackCount: 2,\n\t\t\t},\n\t\t\t{\n\t\t\t\tname:  \"error at first element\",\n\t\t\t\titems: []string{\"error\", \"hello\", \"world\"},\n\t\t\t\titeratee: func(str string) (string, int, bool, error) {\n\t\t\t\t\treturn \"\", 0, false, errors.New(\"first error\")\n\t\t\t\t},\n\t\t\t\twantR1:                nil,\n\t\t\t\twantR2:                nil,\n\t\t\t\twantR3:                nil,\n\t\t\t\twantErr:               true,\n\t\t\t\terrMsg:                \"first error\",\n\t\t\t\texpectedCallbackCount: 1,\n\t\t\t},\n\t\t\t{\n\t\t\t\tname:  \"empty input slices\",\n\t\t\t\titems: []string{},\n\t\t\t\titeratee: func(str string) (string, int, bool, error) {\n\t\t\t\t\treturn strings.ToUpper(str), len(str), len(str) > 4, nil\n\t\t\t\t},\n\t\t\t\twantR1:                []string{},\n\t\t\t\twantR2:                []int{},\n\t\t\t\twantR3:                []bool{},\n\t\t\t\twantErr:               false,\n\t\t\t\texpectedCallbackCount: 0,\n\t\t\t},\n\t\t}\n\n\t\tfor _, tt := range tests {\n\t\t\ttt := tt\n\t\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\t\tt.Parallel()\n\n\t\t\t\tcallbackCount := 0\n\t\t\t\titeratee := func(str string) (string, int, bool, error) {\n\t\t\t\t\tcallbackCount++\n\t\t\t\t\treturn tt.iteratee(str)\n\t\t\t\t}\n\n\t\t\t\tr1, r2, r3, err := UnzipByErr3(tt.items, iteratee)\n\n\t\t\t\tis.Equal(tt.wantR1, r1)\n\t\t\t\tis.Equal(tt.wantR2, r2)\n\t\t\t\tis.Equal(tt.wantR3, r3)\n\t\t\t\tif tt.wantErr {\n\t\t\t\t\tis.Error(err)\n\t\t\t\t\tif tt.errMsg != \"\" {\n\t\t\t\t\t\tis.ErrorContains(err, tt.errMsg)\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tis.NoError(err)\n\t\t\t\t}\n\t\t\t\tis.Equal(tt.expectedCallbackCount, callbackCount)\n\t\t\t})\n\t\t}\n\t})\n\n\t// Test UnzipByErr4\n\tt.Run(\"UnzipByErr4\", func(t *testing.T) {\n\t\tt.Parallel()\n\n\t\ttests := []struct {\n\t\t\tname                  string\n\t\t\titems                 []string\n\t\t\titeratee              func(str string) (string, int, bool, float32, error)\n\t\t\twantErr               bool\n\t\t\texpectedCallbackCount int\n\t\t}{\n\t\t\t{\n\t\t\t\tname:  \"successful transformation\",\n\t\t\t\titems: []string{\"hello\", \"world\"},\n\t\t\t\titeratee: func(str string) (string, int, bool, float32, error) {\n\t\t\t\t\treturn strings.ToUpper(str), len(str), len(str) > 4, float32(len(str)), nil\n\t\t\t\t},\n\t\t\t\twantErr:               false,\n\t\t\t\texpectedCallbackCount: 2,\n\t\t\t},\n\t\t\t{\n\t\t\t\tname:  \"error at second element stops iteration\",\n\t\t\t\titems: []string{\"hello\", \"error\", \"world\"},\n\t\t\t\titeratee: func(str string) (string, int, bool, float32, error) {\n\t\t\t\t\tif str == \"error\" {\n\t\t\t\t\t\treturn \"\", 0, false, 0, errors.New(\"error string not allowed\")\n\t\t\t\t\t}\n\t\t\t\t\treturn strings.ToUpper(str), len(str), len(str) > 4, float32(len(str)), nil\n\t\t\t\t},\n\t\t\t\twantErr:               true,\n\t\t\t\texpectedCallbackCount: 2,\n\t\t\t},\n\t\t\t{\n\t\t\t\tname:  \"empty input slices\",\n\t\t\t\titems: []string{},\n\t\t\t\titeratee: func(str string) (string, int, bool, float32, error) {\n\t\t\t\t\treturn strings.ToUpper(str), len(str), len(str) > 4, float32(len(str)), nil\n\t\t\t\t},\n\t\t\t\twantErr:               false,\n\t\t\t\texpectedCallbackCount: 0,\n\t\t\t},\n\t\t}\n\n\t\tfor _, tt := range tests {\n\t\t\ttt := tt\n\t\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\t\tt.Parallel()\n\n\t\t\t\tcallbackCount := 0\n\t\t\t\titeratee := func(str string) (string, int, bool, float32, error) {\n\t\t\t\t\tcallbackCount++\n\t\t\t\t\treturn tt.iteratee(str)\n\t\t\t\t}\n\n\t\t\t\t_, _, _, _, err := UnzipByErr4(tt.items, iteratee)\n\n\t\t\t\tif tt.wantErr {\n\t\t\t\t\tis.Error(err)\n\t\t\t\t} else {\n\t\t\t\t\tis.NoError(err)\n\t\t\t\t}\n\t\t\t\tis.Equal(tt.expectedCallbackCount, callbackCount)\n\t\t\t})\n\t\t}\n\t})\n\n\t// Test UnzipByErr5\n\tt.Run(\"UnzipByErr5\", func(t *testing.T) {\n\t\tt.Parallel()\n\n\t\tcallbackCount := 0\n\t\t_, _, _, _, _, err := UnzipByErr5([]string{\"hello\", \"world\"}, func(str string) (string, int, bool, float32, float64, error) {\n\t\t\tcallbackCount++\n\t\t\treturn strings.ToUpper(str), len(str), len(str) > 4, float32(len(str)), float64(len(str)), nil\n\t\t})\n\n\t\tis.NoError(err)\n\t\tis.Equal(2, callbackCount)\n\t})\n\n\t// Test UnzipByErr6\n\tt.Run(\"UnzipByErr6\", func(t *testing.T) {\n\t\tt.Parallel()\n\n\t\tcallbackCount := 0\n\t\t_, _, _, _, _, _, err := UnzipByErr6([]string{\"hello\", \"world\"}, func(str string) (string, int, bool, float32, float64, int8, error) {\n\t\t\tcallbackCount++\n\t\t\treturn strings.ToUpper(str), len(str), len(str) > 4, float32(len(str)), float64(len(str)), int8(len(str)), nil\n\t\t})\n\n\t\tis.NoError(err)\n\t\tis.Equal(2, callbackCount)\n\t})\n\n\t// Test UnzipByErr7\n\tt.Run(\"UnzipByErr7\", func(t *testing.T) {\n\t\tt.Parallel()\n\n\t\tcallbackCount := 0\n\t\t_, _, _, _, _, _, _, err := UnzipByErr7([]string{\"hello\", \"world\"}, func(str string) (string, int, bool, float32, float64, int8, int16, error) {\n\t\t\tcallbackCount++\n\t\t\treturn strings.ToUpper(str), len(str), len(str) > 4, float32(len(str)), float64(len(str)), int8(len(str)), int16(len(str)), nil\n\t\t})\n\n\t\tis.NoError(err)\n\t\tis.Equal(2, callbackCount)\n\t})\n\n\t// Test UnzipByErr8\n\tt.Run(\"UnzipByErr8\", func(t *testing.T) {\n\t\tt.Parallel()\n\n\t\tcallbackCount := 0\n\t\t_, _, _, _, _, _, _, _, err := UnzipByErr8([]string{\"hello\", \"world\"}, func(str string) (string, int, bool, float32, float64, int8, int16, int32, error) {\n\t\t\tcallbackCount++\n\t\t\treturn strings.ToUpper(str), len(str), len(str) > 4, float32(len(str)), float64(len(str)), int8(len(str)), int16(len(str)), int32(len(str)), nil\n\t\t})\n\n\t\tis.NoError(err)\n\t\tis.Equal(2, callbackCount)\n\t})\n\n\t// Test UnzipByErr9\n\tt.Run(\"UnzipByErr9\", func(t *testing.T) {\n\t\tt.Parallel()\n\n\t\tcallbackCount := 0\n\t\t_, _, _, _, _, _, _, _, _, err := UnzipByErr9([]string{\"hello\", \"world\"}, func(str string) (string, int, bool, float32, float64, int8, int16, int32, int64, error) {\n\t\t\tcallbackCount++\n\t\t\treturn strings.ToUpper(str), len(str), len(str) > 4, float32(len(str)), float64(len(str)), int8(len(str)), int16(len(str)), int32(len(str)), int64(len(str)), nil\n\t\t})\n\n\t\tis.NoError(err)\n\t\tis.Equal(2, callbackCount)\n\t})\n}\n"
  },
  {
    "path": "type_manipulation.go",
    "content": "package lo\n\nimport \"reflect\"\n\n// IsNil checks if a value is nil or if it's a reference type with a nil underlying value.\n// Play: https://go.dev/play/p/P2sD0PMXw4F\nfunc IsNil(x any) bool {\n\tif x == nil {\n\t\treturn true\n\t}\n\tv := reflect.ValueOf(x)\n\tswitch v.Kind() { //nolint:exhaustive\n\tcase reflect.Chan, reflect.Func, reflect.Map, reflect.Pointer, reflect.UnsafePointer, reflect.Interface, reflect.Slice:\n\t\treturn v.IsNil()\n\tdefault:\n\t\treturn false\n\t}\n}\n\n// IsNotNil checks if a value is not nil or if it's not a reference type with a nil underlying value.\n// Play: https://go.dev/play/p/P2sD0PMXw4F\nfunc IsNotNil(x any) bool {\n\treturn !IsNil(x)\n}\n\n// ToPtr returns a pointer copy of value.\n// Play: https://go.dev/play/p/P2sD0PMXw4F\nfunc ToPtr[T any](x T) *T {\n\treturn &x\n}\n\n// Nil returns a nil pointer of type.\n// Play: https://go.dev/play/p/P2sD0PMXw4F\nfunc Nil[T any]() *T {\n\treturn nil\n}\n\n// EmptyableToPtr returns a pointer copy of value if it's nonzero.\n// Otherwise, returns nil pointer.\n// Play: https://go.dev/play/p/P2sD0PMXw4F\nfunc EmptyableToPtr[T any](x T) *T {\n\t// 🤮\n\tisZero := reflect.ValueOf(&x).Elem().IsZero()\n\tif isZero {\n\t\treturn nil\n\t}\n\n\treturn &x\n}\n\n// FromPtr returns the pointer value or empty.\n// Play: https://go.dev/play/p/mhD9CwO3X0m\nfunc FromPtr[T any](x *T) T {\n\tif x == nil {\n\t\treturn Empty[T]()\n\t}\n\n\treturn *x\n}\n\n// FromPtrOr returns the pointer value or the fallback value.\n// Play: https://go.dev/play/p/mhD9CwO3X0m\nfunc FromPtrOr[T any](x *T, fallback T) T {\n\tif x == nil {\n\t\treturn fallback\n\t}\n\n\treturn *x\n}\n\n// ToSlicePtr returns a slice of pointers to each value.\n// Play: https://go.dev/play/p/P2sD0PMXw4F\nfunc ToSlicePtr[T any](collection []T) []*T {\n\tresult := make([]*T, len(collection))\n\n\tfor i := range collection {\n\t\tresult[i] = &collection[i]\n\t}\n\treturn result\n}\n\n// FromSlicePtr returns a slice with the pointer values.\n// Returns a zero value in case of a nil pointer element.\n// Play: https://go.dev/play/p/lbunFvzlUDX\nfunc FromSlicePtr[T any](collection []*T) []T {\n\tresult := make([]T, len(collection))\n\n\tfor i := range collection {\n\t\tif collection[i] != nil {\n\t\t\tresult[i] = *collection[i]\n\t\t}\n\t}\n\n\treturn result\n}\n\n// FromSlicePtrOr returns a slice with the pointer values or the fallback value.\n// Play: https://go.dev/play/p/lbunFvzlUDX\nfunc FromSlicePtrOr[T any](collection []*T, fallback T) []T {\n\tresult := make([]T, len(collection))\n\n\tfor i := range collection {\n\t\tif collection[i] != nil {\n\t\t\tresult[i] = *collection[i]\n\t\t} else {\n\t\t\tresult[i] = fallback\n\t\t}\n\t}\n\n\treturn result\n}\n\n// ToAnySlice returns a slice with all elements mapped to `any` type.\n// Play: https://go.dev/play/p/P2sD0PMXw4F\nfunc ToAnySlice[T any](collection []T) []any {\n\tresult := make([]any, len(collection))\n\tfor i := range collection {\n\t\tresult[i] = collection[i]\n\t}\n\treturn result\n}\n\n// FromAnySlice returns a slice with all elements mapped to a type.\n// Returns false in case of type conversion failure.\n// Play: https://go.dev/play/p/P2sD0PMXw4F\nfunc FromAnySlice[T any](in []any) ([]T, bool) {\n\tout := make([]T, len(in))\n\tfor i := range in {\n\t\tt, ok := in[i].(T)\n\t\tif !ok {\n\t\t\treturn []T{}, false\n\t\t}\n\t\tout[i] = t\n\t}\n\treturn out, true\n}\n\n// Empty returns the zero value (https://go.dev/ref/spec#The_zero_value).\n// Play: https://go.dev/play/p/P2sD0PMXw4F\nfunc Empty[T any]() T {\n\tvar zero T\n\treturn zero\n}\n\n// IsEmpty returns true if argument is a zero value.\n// Play: https://go.dev/play/p/P2sD0PMXw4F\nfunc IsEmpty[T comparable](v T) bool {\n\tvar zero T\n\treturn zero == v\n}\n\n// IsNotEmpty returns true if argument is not a zero value.\n// Play: https://go.dev/play/p/P2sD0PMXw4F\nfunc IsNotEmpty[T comparable](v T) bool {\n\tvar zero T\n\treturn zero != v\n}\n\n// Coalesce returns the first non-empty arguments. Arguments must be comparable.\n// Play: https://go.dev/play/p/Gyo9otyvFHH\nfunc Coalesce[T comparable](values ...T) (T, bool) {\n\tvar zero T\n\n\tfor i := range values {\n\t\tif values[i] != zero {\n\t\t\treturn values[i], true\n\t\t}\n\t}\n\n\treturn zero, false\n}\n\n// CoalesceOrEmpty returns the first non-empty arguments. Arguments must be comparable.\n// Play: https://go.dev/play/p/Gyo9otyvFHH\nfunc CoalesceOrEmpty[T comparable](v ...T) T {\n\tresult, _ := Coalesce(v...)\n\treturn result\n}\n\n// CoalesceSlice returns the first non-zero slice.\n// Play: https://go.dev/play/p/Gyo9otyvFHH\nfunc CoalesceSlice[T any](v ...[]T) ([]T, bool) {\n\tfor i := range v {\n\t\tif len(v[i]) > 0 {\n\t\t\treturn v[i], true\n\t\t}\n\t}\n\treturn []T{}, false\n}\n\n// CoalesceSliceOrEmpty returns the first non-zero slice.\n// Play: https://go.dev/play/p/Gyo9otyvFHH\nfunc CoalesceSliceOrEmpty[T any](v ...[]T) []T {\n\tfor i := range v {\n\t\tif len(v[i]) > 0 {\n\t\t\treturn v[i]\n\t\t}\n\t}\n\treturn []T{}\n}\n\n// CoalesceMap returns the first non-zero map.\n// Play: https://go.dev/play/p/Gyo9otyvFHH\nfunc CoalesceMap[K comparable, V any](v ...map[K]V) (map[K]V, bool) {\n\tfor i := range v {\n\t\tif len(v[i]) > 0 {\n\t\t\treturn v[i], true\n\t\t}\n\t}\n\treturn map[K]V{}, false\n}\n\n// CoalesceMapOrEmpty returns the first non-zero map.\n// Play: https://go.dev/play/p/Gyo9otyvFHH\nfunc CoalesceMapOrEmpty[K comparable, V any](v ...map[K]V) map[K]V {\n\tfor i := range v {\n\t\tif len(v[i]) > 0 {\n\t\t\treturn v[i]\n\t\t}\n\t}\n\treturn map[K]V{}\n}\n"
  },
  {
    "path": "type_manipulation_test.go",
    "content": "package lo\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestIsNil(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tvar x int\n\tis.False(IsNil(x))\n\n\tvar k struct{}\n\tis.False(IsNil(k))\n\n\tvar s *string\n\tis.True(IsNil(s))\n\n\tvar i *int\n\tis.True(IsNil(i))\n\n\tvar b *bool\n\tis.True(IsNil(b))\n\n\tvar ifaceWithNilValue any = (*string)(nil) //nolint:staticcheck\n\tis.True(IsNil(ifaceWithNilValue))\n\tis.False(ifaceWithNilValue == nil) //nolint:staticcheck,testifylint\n}\n\nfunc TestIsNotNil(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tvar x int\n\tis.True(IsNotNil(x))\n\n\tvar k struct{}\n\tis.True(IsNotNil(k))\n\n\tvar s *string\n\tis.False(IsNotNil(s))\n\n\tvar i *int\n\tis.False(IsNotNil(i))\n\n\tvar b *bool\n\tis.False(IsNotNil(b))\n\n\tvar ifaceWithNilValue any = (*string)(nil) //nolint:staticcheck\n\tis.False(IsNotNil(ifaceWithNilValue))\n\tis.True(ifaceWithNilValue != nil) //nolint:staticcheck,testifylint\n}\n\nfunc TestToPtr(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tresult1 := ToPtr([]int{1, 2})\n\n\tis.Equal([]int{1, 2}, *result1)\n}\n\nfunc TestNil(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tnilFloat64 := Nil[float64]()\n\tvar expNilFloat64 *float64\n\n\tnilString := Nil[string]()\n\tvar expNilString *string\n\n\tis.Equal(expNilFloat64, nilFloat64)\n\tis.Nil(nilFloat64)\n\tis.NotEqual(nil, nilFloat64) //nolint:testifylint\n\n\tis.Equal(expNilString, nilString)\n\tis.Nil(nilString)\n\tis.NotEqual(nil, nilString) //nolint:testifylint\n\n\tis.NotEqual(nilString, nilFloat64)\n}\n\nfunc TestEmptyableToPtr(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tis.Nil(EmptyableToPtr(0))\n\tis.Nil(EmptyableToPtr(\"\"))\n\tis.Nil(EmptyableToPtr[[]int](nil))\n\tis.Nil(EmptyableToPtr[map[int]int](nil))\n\tis.Nil(EmptyableToPtr[error](nil))\n\n\tis.Equal(42, *EmptyableToPtr(42))\n\tis.Equal(\"nonempty\", *EmptyableToPtr(\"nonempty\"))\n\tis.Empty(*EmptyableToPtr([]int{}))\n\tis.Equal([]int{1, 2}, *EmptyableToPtr([]int{1, 2}))\n\tis.Empty(*EmptyableToPtr(map[int]int{}))\n\tis.Equal(assert.AnError, *EmptyableToPtr(assert.AnError))\n}\n\nfunc TestFromPtr(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tstr1 := \"foo\"\n\tptr := &str1\n\n\tis.Equal(\"foo\", FromPtr(ptr))\n\tis.Empty(FromPtr[string](nil))\n\tis.Zero(FromPtr[int](nil))\n\tis.Nil(FromPtr[*string](nil))\n\tis.Equal(ptr, FromPtr(&ptr))\n}\n\nfunc TestFromPtrOr(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tconst fallbackStr = \"fallback\"\n\tstr := \"foo\"\n\tptrStr := &str\n\n\tconst fallbackInt = -1\n\ti := 9\n\tptrInt := &i\n\n\tis.Equal(str, FromPtrOr(ptrStr, fallbackStr))\n\tis.Equal(fallbackStr, FromPtrOr(nil, fallbackStr))\n\tis.Equal(i, FromPtrOr(ptrInt, fallbackInt))\n\tis.Equal(fallbackInt, FromPtrOr(nil, fallbackInt))\n}\n\nfunc TestToSlicePtr(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tstr1 := \"foo\"\n\tstr2 := \"bar\"\n\tresult1 := ToSlicePtr([]string{str1, str2})\n\n\tis.Equal([]*string{&str1, &str2}, result1)\n}\n\nfunc TestFromSlicePtr(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tstr1 := \"foo\"\n\tstr2 := \"bar\"\n\tresult1 := FromSlicePtr([]*string{&str1, &str2, nil})\n\n\tis.Equal([]string{str1, str2, \"\"}, result1)\n}\n\nfunc TestFromSlicePtrOr(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tstr1 := \"foo\"\n\tstr2 := \"bar\"\n\tresult1 := FromSlicePtrOr([]*string{&str1, &str2, nil}, \"fallback\")\n\n\tis.Equal([]string{str1, str2, \"fallback\"}, result1)\n}\n\nfunc TestToAnySlice(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tin1 := []int{0, 1, 2, 3}\n\tin2 := []int{}\n\tout1 := ToAnySlice(in1)\n\tout2 := ToAnySlice(in2)\n\n\tis.Equal([]any{0, 1, 2, 3}, out1)\n\tis.Empty(out2)\n}\n\nfunc TestFromAnySlice(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tis.NotPanics(func() {\n\t\tout1, ok1 := FromAnySlice[string]([]any{\"foobar\", 42})\n\t\tout2, ok2 := FromAnySlice[string]([]any{\"foobar\", \"42\"})\n\n\t\tis.Empty(out1)\n\t\tis.False(ok1)\n\t\tis.Equal([]string{\"foobar\", \"42\"}, out2)\n\t\tis.True(ok2)\n\t})\n}\n\nfunc TestEmpty(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\ttype test struct{}\n\n\tis.Empty(Empty[string]())\n\tis.Empty(Empty[int64]())\n\tis.Empty(Empty[test]())\n\tis.Empty(Empty[chan string]())\n\tis.Nil(Empty[[]int]())\n\tis.Nil(Empty[map[string]int]())\n}\n\nfunc TestIsEmpty(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\ttype test struct {\n\t\tfoobar string\n\t}\n\n\tis.True(IsEmpty(\"\"))\n\tis.False(IsEmpty(\"foo\"))\n\tis.True(IsEmpty[int64](0))\n\tis.False(IsEmpty[int64](42))\n\tis.True(IsEmpty(test{foobar: \"\"}))\n\tis.False(IsEmpty(test{foobar: \"foo\"}))\n}\n\nfunc TestIsNotEmpty(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\ttype test struct {\n\t\tfoobar string\n\t}\n\n\tis.False(IsNotEmpty(\"\"))\n\tis.True(IsNotEmpty(\"foo\"))\n\tis.False(IsNotEmpty[int64](0))\n\tis.True(IsNotEmpty[int64](42))\n\tis.False(IsNotEmpty(test{foobar: \"\"}))\n\tis.True(IsNotEmpty(test{foobar: \"foo\"}))\n}\n\nfunc TestCoalesce(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tnewStr := func(v string) *string { return &v }\n\tvar nilStr *string\n\tstr1 := newStr(\"str1\")\n\tstr2 := newStr(\"str2\")\n\n\ttype structType struct {\n\t\tfield1 int\n\t\tfield2 float64\n\t}\n\tvar zeroStruct structType\n\tstruct1 := structType{1, 1.0}\n\tstruct2 := structType{2, 2.0}\n\n\tresult1, ok1 := Coalesce[int]()\n\tresult2, ok2 := Coalesce(3)\n\tresult3, ok3 := Coalesce(nil, nilStr)\n\tresult4, ok4 := Coalesce(nilStr, str1)\n\tresult5, ok5 := Coalesce(nilStr, str1, str2)\n\tresult6, ok6 := Coalesce(str1, str2, nilStr)\n\tresult7, ok7 := Coalesce(0, 1, 2, 3)\n\tresult8, ok8 := Coalesce(zeroStruct)\n\tresult9, ok9 := Coalesce(zeroStruct, struct1)\n\tresult10, ok10 := Coalesce(zeroStruct, struct1, struct2)\n\n\tis.Zero(result1)\n\tis.False(ok1)\n\n\tis.Equal(3, result2)\n\tis.True(ok2)\n\n\tis.Nil(result3)\n\tis.False(ok3)\n\n\tis.Equal(str1, result4)\n\tis.True(ok4)\n\n\tis.Equal(str1, result5)\n\tis.True(ok5)\n\n\tis.Equal(str1, result6)\n\tis.True(ok6)\n\n\tis.Equal(1, result7)\n\tis.True(ok7)\n\n\tis.Zero(result8)\n\tis.False(ok8)\n\n\tis.Equal(struct1, result9)\n\tis.True(ok9)\n\n\tis.Equal(struct1, result10)\n\tis.True(ok10)\n}\n\nfunc TestCoalesceOrEmpty(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tnewStr := func(v string) *string { return &v }\n\tvar nilStr *string\n\tstr1 := newStr(\"str1\")\n\tstr2 := newStr(\"str2\")\n\n\ttype structType struct {\n\t\tfield1 int\n\t\tfield2 float64\n\t}\n\tvar zeroStruct structType\n\tstruct1 := structType{1, 1.0}\n\tstruct2 := structType{2, 2.0}\n\n\tresult1 := CoalesceOrEmpty[int]()\n\tresult2 := CoalesceOrEmpty(3)\n\tresult3 := CoalesceOrEmpty(nil, nilStr)\n\tresult4 := CoalesceOrEmpty(nilStr, str1)\n\tresult5 := CoalesceOrEmpty(nilStr, str1, str2)\n\tresult6 := CoalesceOrEmpty(str1, str2, nilStr)\n\tresult7 := CoalesceOrEmpty(0, 1, 2, 3)\n\tresult8 := CoalesceOrEmpty(zeroStruct)\n\tresult9 := CoalesceOrEmpty(zeroStruct, struct1)\n\tresult10 := CoalesceOrEmpty(zeroStruct, struct1, struct2)\n\n\tis.Zero(result1)\n\tis.Equal(3, result2)\n\tis.Nil(result3)\n\tis.Equal(str1, result4)\n\tis.Equal(str1, result5)\n\tis.Equal(str1, result6)\n\tis.Equal(1, result7)\n\tis.Zero(result8)\n\tis.Equal(struct1, result9)\n\tis.Equal(struct1, result10)\n}\n\nfunc TestCoalesceSlice(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tvar sliceNil []int\n\tslice0 := []int{}\n\tslice1 := []int{1}\n\tslice2 := []int{1, 2}\n\n\tresult1, ok1 := CoalesceSlice[int]()\n\tresult2, ok2 := CoalesceSlice[int](nil)\n\tresult3, ok3 := CoalesceSlice(sliceNil)\n\tresult4, ok4 := CoalesceSlice(slice0)\n\tresult5, ok5 := CoalesceSlice(nil, sliceNil, slice0)\n\tresult6, ok6 := CoalesceSlice(slice2)\n\tresult7, ok7 := CoalesceSlice(slice1)\n\tresult8, ok8 := CoalesceSlice(slice1, slice2)\n\tresult9, ok9 := CoalesceSlice(slice2, slice1)\n\tresult10, ok10 := CoalesceSlice(sliceNil, slice0, slice1, slice2)\n\n\tis.NotNil(result1)\n\tis.Empty(result1)\n\tis.False(ok1)\n\n\tis.NotNil(result2)\n\tis.Empty(result2)\n\tis.False(ok2)\n\n\tis.NotNil(result3)\n\tis.Empty(result3)\n\tis.False(ok3)\n\n\tis.NotNil(result4)\n\tis.Empty(result4)\n\tis.False(ok4)\n\n\tis.NotNil(result5)\n\tis.Empty(result5)\n\tis.False(ok5)\n\n\tis.NotNil(result6)\n\tis.Equal(slice2, result6)\n\tis.True(ok6)\n\n\tis.NotNil(result7)\n\tis.Equal(slice1, result7)\n\tis.True(ok7)\n\n\tis.NotNil(result8)\n\tis.Equal(slice1, result8)\n\tis.True(ok8)\n\n\tis.NotNil(result9)\n\tis.Equal(slice2, result9)\n\tis.True(ok9)\n\n\tis.NotNil(result10)\n\tis.Equal(slice1, result10)\n\tis.True(ok10)\n}\n\nfunc TestCoalesceSliceOrEmpty(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tvar sliceNil []int\n\tslice0 := []int{}\n\tslice1 := []int{1}\n\tslice2 := []int{1, 2}\n\n\tresult1 := CoalesceSliceOrEmpty[int]()\n\tresult2 := CoalesceSliceOrEmpty[int](nil)\n\tresult3 := CoalesceSliceOrEmpty(sliceNil)\n\tresult4 := CoalesceSliceOrEmpty(slice0)\n\tresult5 := CoalesceSliceOrEmpty(nil, sliceNil, slice0)\n\tresult6 := CoalesceSliceOrEmpty(slice2)\n\tresult7 := CoalesceSliceOrEmpty(slice1)\n\tresult8 := CoalesceSliceOrEmpty(slice1, slice2)\n\tresult9 := CoalesceSliceOrEmpty(slice2, slice1)\n\tresult10 := CoalesceSliceOrEmpty(sliceNil, slice0, slice1, slice2)\n\n\tis.NotNil(result1)\n\tis.Empty(result1)\n\tis.NotNil(result2)\n\tis.Empty(result2)\n\tis.NotNil(result3)\n\tis.Empty(result3)\n\tis.NotNil(result4)\n\tis.Empty(result4)\n\tis.NotNil(result5)\n\tis.Empty(result5)\n\tis.NotNil(result6)\n\tis.Equal(slice2, result6)\n\tis.NotNil(result7)\n\tis.Equal(slice1, result7)\n\tis.NotNil(result8)\n\tis.Equal(slice1, result8)\n\tis.NotNil(result9)\n\tis.Equal(slice2, result9)\n\tis.NotNil(result10)\n\tis.Equal(slice1, result10)\n}\n\nfunc TestCoalesceMap(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tvar mapNil map[int]int\n\tmap0 := map[int]int{}\n\tmap1 := map[int]int{1: 1}\n\tmap2 := map[int]int{1: 1, 2: 2}\n\n\tresult1, ok1 := CoalesceMap[int, int]()\n\tresult2, ok2 := CoalesceMap[int, int](nil)\n\tresult3, ok3 := CoalesceMap(mapNil)\n\tresult4, ok4 := CoalesceMap(map0)\n\tresult5, ok5 := CoalesceMap(nil, mapNil, map0)\n\tresult6, ok6 := CoalesceMap(map2)\n\tresult7, ok7 := CoalesceMap(map1)\n\tresult8, ok8 := CoalesceMap(map1, map2)\n\tresult9, ok9 := CoalesceMap(map2, map1)\n\tresult10, ok10 := CoalesceMap(mapNil, map0, map1, map2)\n\n\tis.NotNil(result1)\n\tis.Empty(result1)\n\tis.False(ok1)\n\n\tis.NotNil(result2)\n\tis.Empty(result2)\n\tis.False(ok2)\n\n\tis.NotNil(result3)\n\tis.Empty(result3)\n\tis.False(ok3)\n\n\tis.NotNil(result4)\n\tis.Empty(result4)\n\tis.False(ok4)\n\n\tis.NotNil(result5)\n\tis.Empty(result5)\n\tis.False(ok5)\n\n\tis.NotNil(result6)\n\tis.Equal(map2, result6)\n\tis.True(ok6)\n\n\tis.NotNil(result7)\n\tis.Equal(map1, result7)\n\tis.True(ok7)\n\n\tis.NotNil(result8)\n\tis.Equal(map1, result8)\n\tis.True(ok8)\n\n\tis.NotNil(result9)\n\tis.Equal(map2, result9)\n\tis.True(ok9)\n\n\tis.NotNil(result10)\n\tis.Equal(map1, result10)\n\tis.True(ok10)\n}\n\nfunc TestCoalesceMapOrEmpty(t *testing.T) {\n\tt.Parallel()\n\tis := assert.New(t)\n\n\tvar mapNil map[int]int\n\tmap0 := map[int]int{}\n\tmap1 := map[int]int{1: 1}\n\tmap2 := map[int]int{1: 1, 2: 2}\n\n\tresult1 := CoalesceMapOrEmpty[int, int]()\n\tresult2 := CoalesceMapOrEmpty[int, int](nil)\n\tresult3 := CoalesceMapOrEmpty(mapNil)\n\tresult4 := CoalesceMapOrEmpty(map0)\n\tresult5 := CoalesceMapOrEmpty(nil, mapNil, map0)\n\tresult6 := CoalesceMapOrEmpty(map2)\n\tresult7 := CoalesceMapOrEmpty(map1)\n\tresult8 := CoalesceMapOrEmpty(map1, map2)\n\tresult9 := CoalesceMapOrEmpty(map2, map1)\n\tresult10 := CoalesceMapOrEmpty(mapNil, map0, map1, map2)\n\n\tis.NotNil(result1)\n\tis.Empty(result1)\n\tis.NotNil(result2)\n\tis.Empty(result2)\n\tis.NotNil(result3)\n\tis.Empty(result3)\n\tis.NotNil(result4)\n\tis.Empty(result4)\n\tis.NotNil(result5)\n\tis.Empty(result5)\n\tis.NotNil(result6)\n\tis.Equal(map2, result6)\n\tis.NotNil(result7)\n\tis.Equal(map1, result7)\n\tis.NotNil(result8)\n\tis.Equal(map1, result8)\n\tis.NotNil(result9)\n\tis.Equal(map2, result9)\n\tis.NotNil(result10)\n\tis.Equal(map1, result10)\n}\n"
  },
  {
    "path": "types.go",
    "content": "package lo\n\n// Entry defines a key/value pairs.\ntype Entry[K comparable, V any] struct {\n\tKey   K\n\tValue V\n}\n\n// Tuple2 is a group of 2 elements (pair).\ntype Tuple2[A, B any] struct {\n\tA A\n\tB B\n}\n\n// Unpack returns values contained in a tuple.\n// Play: https://go.dev/play/p/yrtn7QJTmL_E\nfunc (t Tuple2[A, B]) Unpack() (A, B) {\n\treturn t.A, t.B\n}\n\n// Tuple3 is a group of 3 elements.\ntype Tuple3[A, B, C any] struct {\n\tA A\n\tB B\n\tC C\n}\n\n// Unpack returns values contained in a tuple.\n// Play: https://go.dev/play/p/yrtn7QJTmL_E\nfunc (t Tuple3[A, B, C]) Unpack() (A, B, C) {\n\treturn t.A, t.B, t.C\n}\n\n// Tuple4 is a group of 4 elements.\ntype Tuple4[A, B, C, D any] struct {\n\tA A\n\tB B\n\tC C\n\tD D\n}\n\n// Unpack returns values contained in a tuple.\n// Play: https://go.dev/play/p/yrtn7QJTmL_E\nfunc (t Tuple4[A, B, C, D]) Unpack() (A, B, C, D) {\n\treturn t.A, t.B, t.C, t.D\n}\n\n// Tuple5 is a group of 5 elements.\ntype Tuple5[A, B, C, D, E any] struct {\n\tA A\n\tB B\n\tC C\n\tD D\n\tE E\n}\n\n// Unpack returns values contained in a tuple.\n// Play: https://go.dev/play/p/7J4KrtgtK3M\nfunc (t Tuple5[A, B, C, D, E]) Unpack() (A, B, C, D, E) {\n\treturn t.A, t.B, t.C, t.D, t.E\n}\n\n// Tuple6 is a group of 6 elements.\ntype Tuple6[A, B, C, D, E, F any] struct {\n\tA A\n\tB B\n\tC C\n\tD D\n\tE E\n\tF F\n}\n\n// Unpack returns values contained in a tuple.\n// Play: https://go.dev/play/p/7J4KrtgtK3M\nfunc (t Tuple6[A, B, C, D, E, F]) Unpack() (A, B, C, D, E, F) {\n\treturn t.A, t.B, t.C, t.D, t.E, t.F\n}\n\n// Tuple7 is a group of 7 elements.\ntype Tuple7[A, B, C, D, E, F, G any] struct {\n\tA A\n\tB B\n\tC C\n\tD D\n\tE E\n\tF F\n\tG G\n}\n\n// Unpack returns values contained in a tuple.\n// Play: https://go.dev/play/p/Ow9Zgf_zeiA\nfunc (t Tuple7[A, B, C, D, E, F, G]) Unpack() (A, B, C, D, E, F, G) {\n\treturn t.A, t.B, t.C, t.D, t.E, t.F, t.G\n}\n\n// Tuple8 is a group of 8 elements.\ntype Tuple8[A, B, C, D, E, F, G, H any] struct {\n\tA A\n\tB B\n\tC C\n\tD D\n\tE E\n\tF F\n\tG G\n\tH H\n}\n\n// Unpack returns values contained in a tuple.\n// Play: https://go.dev/play/p/Ow9Zgf_zeiA\nfunc (t Tuple8[A, B, C, D, E, F, G, H]) Unpack() (A, B, C, D, E, F, G, H) {\n\treturn t.A, t.B, t.C, t.D, t.E, t.F, t.G, t.H\n}\n\n// Tuple9 is a group of 9 elements.\ntype Tuple9[A, B, C, D, E, F, G, H, I any] struct {\n\tA A\n\tB B\n\tC C\n\tD D\n\tE E\n\tF F\n\tG G\n\tH H\n\tI I\n}\n\n// Unpack returns values contained in a tuple.\n// Play: https://go.dev/play/p/Ow9Zgf_zeiA\nfunc (t Tuple9[A, B, C, D, E, F, G, H, I]) Unpack() (A, B, C, D, E, F, G, H, I) {\n\treturn t.A, t.B, t.C, t.D, t.E, t.F, t.G, t.H, t.I\n}\n"
  }
]