{"owner":"samber","repo":"lo","hasSkills":true,"totalSkillsCount":2,"totalTokensCount":3847,"categories":["claude-rule"],"hasMcp":false,"mcpConfig":null,"found":["docs/CLAUDE.md","benchmark/CLAUDE.md"],"skills":{"docs/CLAUDE.md":"# 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## Keeping sourceRef in Sync\n\nThe `sourceRef` field (format `file.go#L123`) points to a specific line number in the Go source. Any change to a `.go` file (adding, removing, or reordering functions) shifts line numbers for everything below the change in that file, which can make existing `sourceRef` values stale — not just for the function being edited, but for every other documented helper in the same file.\n\nWhenever Go source code is modified:\n\n1. Run `gopls symbols <file>` for every changed `.go` file to list all symbols (functions/methods/types) with their current line numbers.\n2. Cross-reference each symbol against the `sourceRef` fields in `docs/data/*.md` files that document helpers from that file.\n3. Update any `sourceRef` whose line number no longer matches.\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 the `goexperiment.simd` build tag (Go 1.27+), 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","benchmark/CLAUDE.md":"# 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"},"files":{"docs/CLAUDE.md":"# 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## Keeping sourceRef in Sync\n\nThe `sourceRef` field (format `file.go#L123`) points to a specific line number in the Go source. Any change to a `.go` file (adding, removing, or reordering functions) shifts line numbers for everything below the change in that file, which can make existing `sourceRef` values stale — not just for the function being edited, but for every other documented helper in the same file.\n\nWhenever Go source code is modified:\n\n1. Run `gopls symbols <file>` for every changed `.go` file to list all symbols (functions/methods/types) with their current line numbers.\n2. Cross-reference each symbol against the `sourceRef` fields in `docs/data/*.md` files that document helpers from that file.\n3. Update any `sourceRef` whose line number no longer matches.\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 the `goexperiment.simd` build tag (Go 1.27+), 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","benchmark/CLAUDE.md":"# 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"},"items":[{"name":"CLAUDE.md","path":"benchmark/CLAUDE.md","rawUrl":"https://raw.githubusercontent.com/samber/lo/HEAD/benchmark/CLAUDE.md","title":"benchmark - Claude Agent Guidelines & System Prompt","category":"claude-rule","format":"markdown","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","isInternal":false,"tokens":592,"sizeBytes":2337},{"name":"CLAUDE.md","path":"docs/CLAUDE.md","rawUrl":"https://raw.githubusercontent.com/samber/lo/HEAD/docs/CLAUDE.md","title":"docs - Claude Agent Guidelines & System Prompt","category":"claude-rule","format":"markdown","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## Keeping sourceRef in Sync\n\nThe `sourceRef` field (format `file.go#L123`) points to a specific line number in the Go source. Any change to a `.go` file (adding, removing, or reordering functions) shifts line numbers for everything below the change in that file, which can make existing `sourceRef` values stale — not just for the function being edited, but for every other documented helper in the same file.\n\nWhenever Go source code is modified:\n\n1. Run `gopls symbols <file>` for every changed `.go` file to list all symbols (functions/methods/types) with their current line numbers.\n2. Cross-reference each symbol against the `sourceRef` fields in `docs/data/*.md` files that document helpers from that file.\n3. Update any `sourceRef` whose line number no longer matches.\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 the `goexperiment.simd` build tag (Go 1.27+), 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","isInternal":false,"tokens":3255,"sizeBytes":13192}],"systemPromptSnippet":"<yakaai_skills repo=\"samber/lo\">\n<!-- File: benchmark/CLAUDE.md (Tokens: ~592 | Category: claude-rule) -->\n# 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\n<!-- File: docs/CLAUDE.md (Tokens: ~3255 | Category: claude-rule) -->\n# 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## Keeping sourceRef in Sync\n\nThe `sourceRef` field (format `file.go#L123`) points to a specific line number in the Go source. Any change to a `.go` file (adding, removing, or reordering functions) shifts line numbers for everything below the change in that file, which can make existing `sourceRef` values stale — not just for the function being edited, but for every other documented helper in the same file.\n\nWhenever Go source code is modified:\n\n1. Run `gopls symbols <file>` for every changed `.go` file to list all symbols (functions/methods/types) with their current line numbers.\n2. Cross-reference each symbol against the `sourceRef` fields in `docs/data/*.md` files that document helpers from that file.\n3. Update any `sourceRef` whose line number no longer matches.\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 the `goexperiment.simd` build tag (Go 1.27+), 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</yakaai_skills>"}