Skip to content

Feat/#5/map collections#11

Merged
maciej-sz merged 21 commits intomainfrom
feat/#5/map-collections
Mar 10, 2025
Merged

Feat/#5/map collections#11
maciej-sz merged 21 commits intomainfrom
feat/#5/map-collections

Conversation

@maciej-sz
Copy link
Copy Markdown
Contributor

@maciej-sz maciej-sz commented Mar 10, 2025

Summary by CodeRabbit

  • Documentation

    • Enhanced the README with clearer guidance on the Comfy Gopher toolset and detailed objectives for the Collections package.
  • New Features

    • Introduced a utility to count occurrences within collections.
    • Added enhanced collection operations that now return additional result details (e.g., removed elements).
    • Implemented a new map structure with improved key-value pair handling and additional methods for manipulation.
    • Added new methods for sequences and maps to facilitate better value management and retrieval.
  • Refactor

    • Standardized type definitions and method signatures across collection-related APIs for improved consistency and error handling.
    • Updated internal structures to simplify and enhance functionality in various collection types.
  • Tests

    • Expanded and refined test scenarios to ensure robust handling of duplicate items and various edge cases.
    • Introduced new tests for the updated map and sequence functionalities, including value counting and error handling.
    • Added tests for the new valuesCounter functionality to validate counting operations.
  • Chores

    • Updated build configurations to streamline resource management.

@maciej-sz maciej-sz linked an issue Mar 10, 2025 that may be closed by this pull request
@codecov
Copy link
Copy Markdown

codecov bot commented Mar 10, 2025

Codecov Report

Attention: Patch coverage is 96.94019% with 22 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
functions_internal.go 76.40% 19 Missing and 2 partials ⚠️
functions.go 0.00% 1 Missing ⚠️
Files with missing lines Coverage Δ
cmp.go 100.00% <100.00%> (ø)
definitions.go 100.00% <100.00%> (+50.00%) ⬆️
definitions_internal.go 100.00% <100.00%> (ø)
map.go 100.00% <100.00%> (+100.00%) ⬆️
mapcmp.go 100.00% <100.00%> (+100.00%) ⬆️
sequence.go 100.00% <100.00%> (ø)
sequencecmp.go 100.00% <100.00%> (ø)
functions.go 0.00% <0.00%> (ø)
functions_internal.go 79.89% <76.40%> (+29.23%) ⬆️
🚀 New features to boost your workflow:
  • Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@maciej-sz
Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 10, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 10, 2025

Walkthrough

The changes update the module configuration and documentation, refactor core collection APIs and internal type signatures, and enhance extensive test suites. New generic types, interfaces, and methods such as a values counter (in cmp.go) and a revamped pair structure (in map.go/mapcmp.go) have been introduced. Error handling and method signatures (e.g., for removal and sorting) were also improved. Overall, the library’s internal consistency, clarity, and test coverage have been significantly enhanced.

Changes

File(s) Change Summary
.idea/collections.iml
README.adoc
Updated module configuration to exclude the var folder; revised README title and expanded description for the Comfy Gopher Collections package.
definitions.go
definitions_internal.go
functions.go
functions_internal.go
cmp.go
set.go
map.go
mapcmp.go
sequence.go
sequencecmp.go
Improved error handling and naming consistency; modified method signatures (e.g., RemoveAt now returns the removed element and error); introduced new generic types and interfaces (such as valuesCounter in cmp.go and internal interfaces with baseInternal, indexedInternal, etc.); refactored key collection operations (e.g., pair handling in maps and updated sort, append, and fold methods).
base_cases_test.go
cmp_cases_test.go
cmpmutable_cases_test.go
common_test.go
indexed_cases_test.go
indexedmutable_cases_test.go
linear_cases_test.go
linearmutable_cases_test.go
list_cases_test.go
mutable_cases_test.go
sequence_test.go
sequencecmp_test.go
map_pairref_cases_test.go
map_test.go
mapcmp_test.go
Revised test types and case definitions to use updated internal types (e.g., replacing Base, Linear, List, etc. with baseInternal, linearInternal, listInternal, etc.); adjusted function signatures to support generics; added new test cases for duplicate handling and value count verification; introduced helper extraction methods to compare underlying slices, maps, and key–value counts.

Sequence Diagram(s)

Below is a high-level sequence diagram outlining the interactions when processing collection operations with value counting and removal:

sequenceDiagram
    participant Client
    participant Collection
    participant ValuesCounter

    Client->>Collection: Append(item)
    Collection->>ValuesCounter: Increment(item)
    ValuesCounter-->>Collection: Updated count
    Client->>Collection: RemoveAt(index)
    Collection->>ValuesCounter: Decrement(removed_item)
    ValuesCounter-->>Collection: Updated count
    Client->>Collection: GetItem(index)
    Collection-->>Client: Returns item
Loading

Poem

I'm a rabbit with a keen coder's eye,
Hopping through collections as the days go by.
New counters and tests, so neat and true,
Every method refined, every bug bid adieu.
With whiskers twitching in code-filled delight,
I celebrate our changes—oh, what a sight!
🐇✨ Happy coding under the moonlight!

Warning

There were issues while running some tools. Please review the errors and either fix the tool’s configuration or disable the tool if it’s a critical failure.

🔧 golangci-lint (1.62.2)

Error: can't load config: the Go language version (go1.23) used to build golangci-lint is lower than the targeted Go version (1.24)
Failed executing command with error: can't load config: the Go language version (go1.23) used to build golangci-lint is lower than the targeted Go version (1.24)


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 22ca276 and cc006e7.

📒 Files selected for processing (1)
  • cmp_test.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • cmp_test.go

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🔭 Outside diff range comments (1)
sequence_test.go (1)

287-291: ⚠️ Potential issue

Logic error in deep copy validation loop.

for v := range c2.(*comfySeq[int]).s {
    if v == 999 {
        t.Error("copy() did not create a deep copy")
    }
}

Here, v is the index, not the slice element. This mistakenly checks for 999 in the index. Use something like for i, val := range c2.(*comfySeq[int]).s { ... } or compare val directly to ensure correctness.

🧹 Nitpick comments (26)
map_pairref_cases_test.go (2)

108-152: Added tests to verify copy semantics for maps

These tests ensure that copying a map creates a deep copy where modifying values in the copy doesn't affect the original. This is important for maintaining collection immutability when expected.

One suggestion: the test name "Values() on three-item collection, modify values" at line 110 doesn't clearly reflect that this is testing copy semantics. Consider renaming it to something like "Copy() creates independent pairs that don't affect the original".


141-144: Verify type assertion safety in copy operation

The code performs a type assertion without checking if it's successful:

copiedMap := tt.coll.copy().(mapInternal[int, int])

Consider adding a type assertion check to handle potential runtime errors gracefully:

-copiedMap := tt.coll.copy().(mapInternal[int, int])
+copied, ok := tt.coll.copy().(mapInternal[int, int])
+if !ok {
+    t.Fatalf("Failed to cast copied collection to mapInternal[int, int]")
+}
+copiedMap := copied
definitions_internal.go (2)

1-4: Establish consistent package documentation.

The package-level comment is concise, but consider including a brief overview of the collection interfaces and their usage to help users quickly grasp the library’s purpose.


82-86: Consider clarity around comparison constraints in map-based interfaces.

These interfaces (cmpMapBaseInternal) couple key comparison (via comparable) with cmp.Ordered for values. Verify this combined requirement is intentional. If value ordering is not always needed, splitting them might improve flexibility.

indexedmutable_cases_test.go (4)

37-39: Consistency in verifying removed elements.

Again, verifying the “removed” element in the test is a robust check. Keep consistent naming for test variables for clarity.


45-47: Check for ordering in the final array.

Verifying the final slice after removal ensures correctness. Consider also testing corner cases such as repeated removals at the same index.


74-81: Validate duplicates handling.

The test “RemoveAt() on six-item with duplicates” is indispensable for correctness. Looks good; further coverage might include removing from the start/end in duplicates scenario, if not already tested.


150-154: Confirm test coverage for Sort.

You updated the expected sorted slice to []int(nil) in certain cases (empty). This is consistent. Ensure any usage across the code respects nil vs. empty slice differences.

linearmutable_cases_test.go (1)

100-110: Consolidate repeated logic.

testAppendMany() and related test blocks reuse a pattern of extracting slice and value-count. If the pattern grows, consider a small helper to reduce duplication.

sequencecmp.go (2)

38-41: Increment counters after each append.

The loop approach is straightforward. If performance becomes critical for large slices, consider a batch increment approach in the future.


174-174: Increment after insert.

Slicing logic plus increment for the inserted item is consistent. Watch out for future concurrency needs, though not a concern here.

Also applies to: 178-179

sequencecmp_test.go (1)

1-1: Nolint comment noted.

Ensure the linter exceptions are intentional or remove if unneeded.

cmpmutable_cases_test.go (1)

229-232: Mismatched error messages for SortDesc.
Although functionally correct, the error messages reference “SortAsc()” instead of “SortDesc()”. Consider updating for clarity.

- t.Errorf("SortAsc() resulted in: %v, but wanted %v", actualSlice, tt.want1)
+ t.Errorf("SortDesc() resulted in: %v, but wanted %v", actualSlice, tt.want1)

- t.Errorf("SortAsc() did not sort correctly from values counter")
+ t.Errorf("SortDesc() did not sort correctly from values counter")
map.go (1)

16-17: Outdated doc comment regarding NewMapFrom.
Lines 16-17 claim that no NewMapFrom constructor exists, but it's actually defined at line 25. Consider removing or updating this comment for correctness.

- // Note that there is no NewMapFrom constructor, because it would create collection in random order.
+ // Creates a new Map in the order of the provided slice of pairs.
functions_internal.go (4)

35-40: Add dedicated tests for comfyContainsValue.
These lines introduce a new helper without coverage, as indicated by static analysis. Adding a direct test ensures no regressions in matching logic.

Would you like help generating a test function snippet for this utility?

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 35-38: functions_internal.go#L35-L38
Added lines #L35 - L38 were not covered by tests


41-44: comfyContainsKV also lacks patch coverage.
Consider adding a targeted unit test that invokes comfyContainsKV with various key-value predicates.

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 41-41: functions_internal.go#L41
Added line #L41 was not covered by tests


[warning] 43-44: functions_internal.go#L43-L44
Added lines #L43 - L44 were not covered by tests


160-160: Missing coverage for else-if path.
If the new value is not less than the accumulator, confirm you have a test that exercises this path in comfyMinOfPairs.

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 160-160: functions_internal.go#L160
Added line #L160 was not covered by tests


180-184: Lack of test coverage in comfyFoldSliceRev.
These lines iterate items in reverse, but might not be invoked in your tests.

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 180-180: functions_internal.go#L180
Added line #L180 was not covered by tests


[warning] 182-184: functions_internal.go#L182-L184
Added lines #L182 - L184 were not covered by tests

definitions.go (4)

37-38: Name mismatch in comment vs. type.
The comment states "KKVistor" whereas the type name is KVVistor. Consider updating one or the other to maintain naming consistency.


72-73: TODO comment for reverse values iteration.
A placeholder exists for ValuesRev(). If reverse iteration is critical, consider implementing to avoid code drift.


87-87: Commented-out TODO.
// LinearValues() indicates an intended feature. Make sure to address or remove this TODO to keep the codebase clean.


145-145: Multi-value removal is hinted as a TODO.
RemoveValues(v V) references replacing with ...V. This can be valuable for batch operations. Could be worth implementing to align with flexible usage.

map_test.go (2)

64-71: Add nil check for slice before attempting extraction

The extractRawValues method doesn't check if the slice is nil before attempting to iterate through it. This could cause a panic if extractUnderlyingSlice returns a nil slice.

Recommended change:

func (lcb *comfyMapIntBuilder[C]) extractRawValues(c C) any {
	s := lcb.extractUnderlyingSlice(c).([]Pair[int, int])
+	if s == nil {
+		return []int(nil)
+	}
	flat := make([]int, 0, len(s))
	for _, pair := range s {
		flat = append(flat, pair.Val())
	}
	return flat
}

85-87: Document why this method always returns nil

The extractUnderlyingValsCount method always returns nil, which suggests that the comfyMap implementation doesn't maintain a value counter (unlike comfyCmpMap). Consider adding a comment to explain why this is intentional.

func (lcb *comfyMapIntBuilder[C]) extractUnderlyingValsCount(_ C) any {
+	// comfyMap doesn't implement a values counter
	return nil
}
mapcmp_test.go (2)

88-94: Consider a more graceful error handling approach

The current implementation panics if the values counter is nil. While panicking is acceptable in tests, consider a more graceful approach like returning nil or a default value, especially for a utility method.

func (lcb *comfyCmpMapIntBuilder[C]) extractUnderlyingValsCount(c C) any {
	vc := (any(c)).(*comfyCmpMap[int, int]).vc.counter
	if vc == nil {
-		panic("Could not extract Values Counter from comfyCmpMap")
+		// Log an error instead of panicking
+		return map[int]int{}
	}
	return vc
}

393-406: Initialize all required fields in the test object

The comfyCmpMap instance in this test is missing the s and kp fields that are initialized in make and other tests. While this might not affect the specific test cases here, it's better to fully initialize objects for consistency.

c1 := &comfyCmpMap[int, int]{
+	s:  []Pair[int, int]{
+		NewPair(1, 111),
+		NewPair(2, 222),
+		NewPair(3, 333),
+	},
	m: map[int]Pair[int, int]{
	},
+	kp: map[int]int{
+		1: 0,
+		2: 1,
+		3: 2,
+	},
	vc: &valuesCounter[int]{
		counter: map[int]int{
		},
	},
}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a1e315b and 08cdbe4.

📒 Files selected for processing (27)
  • .idea/collections.iml (1 hunks)
  • README.adoc (1 hunks)
  • base_cases_test.go (9 hunks)
  • cmp.go (1 hunks)
  • cmp_cases_test.go (10 hunks)
  • cmpmutable_cases_test.go (4 hunks)
  • common_test.go (1 hunks)
  • definitions.go (9 hunks)
  • definitions_internal.go (1 hunks)
  • functions.go (1 hunks)
  • functions_internal.go (5 hunks)
  • indexed_cases_test.go (1 hunks)
  • indexedmutable_cases_test.go (4 hunks)
  • linear_cases_test.go (1 hunks)
  • linearmutable_cases_test.go (14 hunks)
  • list_cases_test.go (3 hunks)
  • map.go (2 hunks)
  • map_pairref_cases_test.go (1 hunks)
  • map_test.go (1 hunks)
  • mapcmp.go (1 hunks)
  • mapcmp_test.go (1 hunks)
  • mutable_cases_test.go (6 hunks)
  • sequence.go (5 hunks)
  • sequence_test.go (4 hunks)
  • sequencecmp.go (8 hunks)
  • sequencecmp_test.go (6 hunks)
  • set.go (1 hunks)
🧰 Additional context used
🪛 GitHub Check: codecov/patch
functions.go

[warning] 6-6: functions.go#L6
Added line #L6 was not covered by tests

functions_internal.go

[warning] 35-38: functions_internal.go#L35-L38
Added lines #L35 - L38 were not covered by tests


[warning] 41-41: functions_internal.go#L41
Added line #L41 was not covered by tests


[warning] 43-44: functions_internal.go#L43-L44
Added lines #L43 - L44 were not covered by tests


[warning] 146-147: functions_internal.go#L146-L147
Added lines #L146 - L147 were not covered by tests


[warning] 160-160: functions_internal.go#L160
Added line #L160 was not covered by tests


[warning] 180-180: functions_internal.go#L180
Added line #L180 was not covered by tests


[warning] 182-184: functions_internal.go#L182-L184
Added lines #L182 - L184 were not covered by tests


[warning] 208-208: functions_internal.go#L208
Added line #L208 was not covered by tests


[warning] 210-210: functions_internal.go#L210
Added line #L210 was not covered by tests


[warning] 215-215: functions_internal.go#L215
Added line #L215 was not covered by tests


[warning] 217-217: functions_internal.go#L217
Added line #L217 was not covered by tests


[warning] 220-220: functions_internal.go#L220
Added line #L220 was not covered by tests

🔇 Additional comments (295)
.idea/collections.iml (1)

5-7: IDE configuration update looks good.

The change to exclude the var directory from the module's content is a standard IDE configuration update that won't affect runtime behavior. This is useful for excluding build artifacts or temporary files from IDE indexing.

set.go (1)

9-9: Interface simplification is a good improvement.

Simplifying the CmpMap type parameter from CmpMap[*comfyPair[K, V], K, V] to CmpMap[K, V] removes the dependency on the implementation detail (comfyPair) and makes the interface cleaner. This change aligns with Go's philosophy of simple, focused interfaces.

README.adoc (3)

1-3: Clear title and description improvement.

The updated title "What is Comfy Gopher?" and enhanced description provide better context about the project's purpose. This makes it immediately clear to new users what they're looking at.


9-18: Well-defined goals provide clear direction.

The explicit listing of goals for the Collections package is excellent. It helps users understand the specific problems the library aims to solve, such as providing abstractions for collections, reducing repetition, and addressing the missing ordered map data structure.


19-29: Important limitations clearly communicated.

Explicitly stating the non-goals (thread-safety and exceptional efficiency) sets appropriate expectations for users. This honesty about limitations is a best practice in library documentation and helps prevent misuse.

linear_cases_test.go (1)

8-10: Type alias refactoring looks good!

The change from Linear[int] to linearInternal[int] in these type aliases aligns with good testing practices by focusing on testing implementation details directly. This refactoring is consistent with similar changes in other test files and maintains the same test behavior while providing more precise testing of internal structures.

indexed_cases_test.go (1)

8-10: Type alias refactoring looks good!

The change from Indexed[int] to indexedInternal[int] in these type aliases follows the same pattern as in other test files. This refactoring improves consistency in the testing framework while maintaining the same test functionality.

sequence.go (7)

27-29: Good optimization for empty input slices

Adding this early return for empty slice inputs avoids unnecessary operations and improves performance.


61-61: Efficient memory usage with nil slices

Using []V(nil) instead of an empty slice with capacity provides better memory efficiency as it resets the underlying array.


128-128: Method implementation refactoring looks good

Changing to comfyFoldSlice suggests a more specialized implementation for slices, which should improve code organization and maintainability.


166-168: Good optimization for empty input slices

Similar to the change in Append, this early return for empty slice inputs avoids unnecessary operations and improves performance.


173-173: Method implementation refactoring looks good

Similar to the Fold method change, using comfyReduceSlice provides a more specialized implementation for slices.


176-182: API improvement with better return values

The updated signature improves API consistency by returning the removed element along with an error. The implementation is also cleaner by directly assigning the results of sliceRemoveAt.


249-259: Properly implemented copy method

The reinstated copy method correctly creates a deep copy of the sequence. The //nolint:unused directive is appropriate for methods that may be used in the future or required by interfaces but aren't currently called.

cmp.go (4)

5-7: Good generic type constraint for counter

Using cmp.Ordered as a constraint ensures that the counter works with any comparable and orderable type, which is appropriate for a map key.


9-13: Clean constructor initialization

The constructor properly initializes the counter map, ensuring that the struct is ready to use immediately after creation.


15-20: Proper handling of non-existent keys

The Count method correctly checks for key existence before accessing the map value, returning 0 for non-existent keys.


22-28: Good increment implementation with key existence check

The Increment method properly handles both existing and non-existing keys, initializing new entries correctly.

list_cases_test.go (4)

9-11: Updated type signatures to use internal implementation instead of exported types

The type definitions have been changed to use listInternal instead of List, reflecting a shift to testing the internal implementation rather than the exported API surface. This approach allows for more thorough testing of implementation details.


20-20: Added value counter verification for test cases

The test cases now include a want2 field containing a map that tracks the expected value counts after insertion. This provides an additional validation mechanism to ensure the internal counting mechanism works correctly.

Also applies to: 27-27, 34-34


64-77: Added test cases for collections with duplicates

These new test cases are valuable additions that verify insertion behavior with collections containing duplicate values, testing both appending at the end and insertion in the middle of the collection.


125-134: Enhanced verification logic for test cases

The verification logic now properly extracts the underlying slice and value counts using the builder's extraction methods. This matches the updated test case structure and provides more thorough verification of the internal state after operations.

common_test.go (4)

3-19: Enhanced testArgs structure with additional fields

The testArgs structure has been expanded with new fields to support more comprehensive test cases:

  • key and keys for testing map-like operations
  • defaultRawValue for testing with untyped values
  • intPredicate for testing integer-specific predicates

These additions enable more versatile test scenarios, particularly for the new map collections.


21-27: Added helper method for type conversion

The new valuesAsAnySlice method provides a convenient way to convert typed values to any slices, which is useful for testing generic collection builders that accept interface{} values.


29-45: Enhanced testCase structure with additional fields

The testCase structure has been expanded with:

  • collBuilder for dynamic collection creation
  • want4 for additional validation
  • metaInt1 for numeric metadata
  • modify function for testing mutation operations

These additions support more complex test scenarios, particularly for reference type testing.


47-61: Improved testCollectionBuilder interface with extraction methods

The interface has been simplified by removing the type parameter V and enhanced with:

  • ThreeRev() for reversed collection testing
  • FromValues() for creating collections from arbitrary values
  • Various extraction methods for accessing internal collection state

These changes enable more thorough testing of implementation details while maintaining a clean public API.

mutable_cases_test.go (6)

8-10: Updated type signatures to use internal implementation

Similar to the changes in list_cases_test.go, the type definitions have been updated to use mutableInternal instead of Mutable, allowing for better testing of internal implementation details.


18-19: Updated empty collection representation and added value counter verification

Empty collections are now represented as []int(nil) instead of []int{}, and value counter maps have been added for verification. This ensures consistency in how empty collections are represented and adds an additional layer of validation.

Also applies to: 26-26


35-41: Added test case for collections with duplicates

This new test case verifies the Apply operation on collections with duplicate values, ensuring that the mapper function correctly transforms each value and the value counter properly tracks the result.


51-59: Enhanced verification logic for Apply tests

The verification logic now extracts and validates both the underlying slice and the value counts using the builder's extraction methods, providing more thorough validation of the internal state after operations.


93-101: Enhanced verification logic for Clear tests

Similar to the Apply tests, the Clear test verification has been updated to validate both the underlying slice and value counts, ensuring that Clear properly resets all internal data structures.


173-181: Enhanced verification logic for RemoveMatching tests

The RemoveMatching test verification has been updated to validate both the underlying slice and value counts, ensuring that elements are properly removed from all internal data structures.

map_pairref_cases_test.go (2)

8-62: Added comprehensive test cases for map append operations with reference types

These tests verify that appending key-value pairs to maps works correctly, especially when the pairs contain mutable reference values. The tests include:

  • Verification of both slice and map representations
  • Testing reference modification after append
  • Testing behavior with both empty and non-empty collections

This is a valuable addition that ensures reference semantics are handled correctly in map collections.


64-106: Added tests for map value modification through iteration

These tests verify that modifying values obtained through iteration properly updates the underlying collection. This is critical for ensuring that the Values() method returns references that are connected to the original collection, not detached copies.

definitions_internal.go (3)

10-14: Interfaces appear well-structured.

The baseInternal interface cleanly specifies a copy method on top of the Base[V] operations. This design is consistent and shows good separation of concerns.


88-110: comfyPair struct design looks clean.

The Key(), Val(), SetVal(), and copy() methods are straightforward. Consider adding a doc comment for copy() to clarify that it returns a new instance, distinct from the original.


66-74:

Details

✅ Verification successful

Validate naming and usage for map-specific operations.

Methods like prependAll or removeMany are somewhat unusual for a map abstraction. Ensure these method names match your domain’s conventions and do not conflict with typical map usage patterns.

Do you already have tests that confirm these operations behave as intended across edge cases (e.g., empty map, duplicate keys)? We can verify them by scanning the test files:


🏁 Script executed:

#!/bin/bash
# Searching for unit tests referring to prependAll, removeMany, or set
rg -A 5 -B 3 '(prependAll|removeMany|set)\('

Length of output: 6540


Final Verification of Map Operation Naming

The investigation confirms that our domain-specific naming (e.g., prependAll, removeMany, and set) is consistently used and thoroughly tested. The unit tests in files such as map.go, mapcmp_test.go, and map_test.go verify their behavior across typical edge cases (empty inputs, duplicate keys, etc.), ensuring that the operations perform as intended and align with our project's conventions.

  • Consistency Check: Naming conventions in definitions_internal.go match those used throughout the codebase.
  • Test Coverage: Existing tests cover these methods, confirming correct behavior in edge cases.
  • Recommendation: No modifications are needed. Just ensure that future changes remain consistent with these established patterns.
indexedmutable_cases_test.go (9)

9-11: Good approach to unify type definitions.

Using indexedMutableInternal[int] clarifies the test coverage for these internal structures without duplicating code.


19-21: Ensure zero-value usage is intentional.

Using want2 = 0 in the test indicates the removed value is expected to be zero when out of bounds. Confirm that this behavior aligns with your error handling approach and default values.


28-31: Verifying new want fields.

You’ve introduced want2 (the removed value) and want3 (value counts). This extra detail helps ensure correctness thoroughly—nice improvement for test clarity.


53-55: Comprehensive approach for want3.

Tracking value counts after each removal helps catch potential index shift or repeated element issues. Good thoroughness.


61-63: Edge case coverage.

Ensuring out-of-bounds indices check both scenarios (negative and too large) is vital. Great coverage.


70-72: Negative index test is consistent.

The negative index path returning an error and zero removed value is consistent with the out-of-bounds scenario. Good defensive testing.


89-89: Removed value assignment.

Assigning removed, err := tt.coll.RemoveAt(...) clarifies the function’s new return signature. Good usage.


99-110: Solid verification of slice and counter.

Ensuring actualSlice and actualVC match expectations is thorough. Great test design for internal state checks.


121-121: No changes to review at this line.

Skipping further commentary since there's no additional logic.

linearmutable_cases_test.go (9)

8-10: Refactor to use linearMutableInternal[int].

Similar to the indexed case, switching to linearMutableInternal[int] ensures synergy with the newly introduced internal interfaces.


19-19: Explicitly track counts in want2.

Adding a map[int]int is beneficial for verifying final state. This detail can catch duplication or missed increments in the library code.


26-27: Verify new item count.

map[int]int{111: 1, 1: 1} in the test ensures appended items are tracked. Useful for ensuring internal counters are correct.


33-34: Meaningful test coverage for multi-item append.

Checking a mix of existing and new values enhances reliability.


44-46: Ensure big appends respect capacity.

Appending multiple items to the underlying slice can trigger expansions. The test coverage plus value-count verification is robust.

Also applies to: 50-51


64-65: Edge-case coverage for appending none.

Verifying appending empty slices to both empty and non-empty collections ensures no side effects. Good practice.

Also applies to: 71-72, 78-79, 84-86, 91-93


121-121: Slice and counts after single-item append from another collection.

Checks consistency across collection boundaries. Nicely done.

Also applies to: 123-123


130-131: Appending collections and verifying final distribution.

The approach ensures that appended elements are all accounted for in both slice order and value counts. Looks thorough.

Also applies to: 137-138, 143-145, 150-152


182-183: Prepend tests mirror Append’s thoroughness.

Ensuring both forward and reverse insertion operations handle counts properly is well covered.

Also applies to: 189-190, 195-197

sequencecmp.go (17)

12-13: Initialization with empty slice and new counter.

Good practice to keep the slice nil initially while still having a valid counter. Simplifies memory usage for empty sequences.


18-21: Constructing from slice.

Creating a fresh sequence and appending the elements leverages shared logic and ensures counters are incremented properly.


25-26: Track sequence data with vc.

Storing a *valuesCounter[V] is consistent with the entire design. This automatically updates counts on operations.


31-31: Mapping function updates.

Decrement the old value, apply the transform, then increment the new value—this ensures correct internal counts.

Also applies to: 33-34


45-48: Appending from another collection.

Ensuring each item is appended and counted individually is consistent with your design. Looks good.


66-68: Re-initialize counters when clearing.

Resetting the slice and reassigning a fresh counter thoroughly cleans up existing references. Safe approach.


72-72: No changes at line 72.

Skipping further commentary since there's no alteration here.


90-91: CountValues usage.

Directly returning the counter’s count is significantly more efficient than scanning the slice. Good improvement.


140-141: Leverage comfyFoldSlice.

Delegating the fold logic fosters reuse. The approach is consistent with your pattern in Fold, Reduce, and other aggregator methods.


143-145: HasValue delegates to ContainsValue.

This small convenience method is clean and prevents repeated logic.


163-165: Short-circuit zero counts in IndexOf.

If the counter says zero, there is no need to scan the slice. Great optimization.


188-190: Symmetry in LastIndexOf.

Similar optimization to IndexOf. Good for performance on large collections.


212-214: Prepending while updating counts.

Prepending slices might reallocate internally. Thanks to the subsequent increment, the new values remain tracked properly.

Also applies to: 216-218


222-223: Reuse existing reduce helpers.

Again, using comfyReduceSlice standardizes approach. This consistency fosters easier maintenance.


225-232: Return removed value from RemoveAt.

This is a user-friendly approach allowing callers to handle the removed value. Decrementing it in the counter is crucial for consistency.


235-245: Synchronized removal while updating vc.

Building a new slice and a new counter is a simple way to ensure no leftover references. This approach helps maintain internal consistency at the cost of reallocation—likely acceptable here.

Also applies to: 248-258


343-351: Cloning the sequence.

The copy method returns a new comfyCmpSeq with a fresh counter—ensuring the original remains untouched. Good design for immutability patterns.

base_cases_test.go (6)

9-11: Good transition to baseInternal[int].

These type aliases properly align with the baseInternal[int] approach used throughout. No issues found.


13-15: Consistent naming for pair-based type aliases.

Renaming the pair-based type aliases to use baseInternal[Pair[int, int]] is consistent with the rest of the refactoring. Good job.


601-631: Extended coverage for duplicates in Find().

The new getFindCasesWithDupes() function covers scenarios with repeated pairs. This adds valuable test coverage for verifying that the first matching occurrence is returned. Nicely done.


633-643: Proper test harness for Find() with duplicates.

testFindWithDupes() ensures that the newly introduced duplicate-handling logic is tested thoroughly. No issues spotted.


706-736: Extended coverage for duplicates in FindLast().

The new getFindLastCasesWithDupes() function verifies correct behavior for the last matching occurrence with repeated pairs. Looks good.


738-748: Validating FindLast() with duplicates.

testFindLastWithDupes() offers comprehensive coverage for last-occurrence scenarios. Implementation appears correct.

sequence_test.go (42)

8-8: Refactor to generic parameter for comfySeqIntBuilder.

Using [C baseInternal[int]] refines the builder’s generic constraint. This aligns with the baseInternal[...] approach across the codebase.


12-12: Potential subtlety with returning a nil slice.

Switching from []int{} to []int(nil) for the empty slice is typically harmless in Go but can lead to subtle differences when comparing slices by pointer. Please verify that downstream code doesn’t rely on a non-nil empty slice.


27-31: Addition of ThreeRev() for reversed initialization.

Providing a reversed sequence builder adds flexibility to tests and usage scenarios. Implementation looks consistent.


35-41: Generic FromValues() method improves test flexibility.

Allowing appends from a slice of any broadens the builder’s utility. Code is straightforward and clear.


43-43: Updated make() signature.

Defining make(items []int) linearMutableInternal[int] clarifies the builder’s return type. No concerns.


51-57: New extraction helpers for raw and underlying slices.

The methods extractRawValues and extractUnderlyingSlice neatly expose the internal slice for testing. Code matches naming conventions.


59-69: Nil returns in extractUnderlying methods.*

extractUnderlyingMap, extractUnderlyingKp, and extractUnderlyingValsCount currently return nil. If these placeholders are intended for future expansions, that’s fine; otherwise, confirm their usage.


94-109: Increased test coverage for NewSequence().

Ensuring non-nil and verifying the internal comfySeq structure. The checks for both int and string sequences look correct.


114-132: NewSequenceFrom() test coverage.

The test verifies creation from []int and []string. No issues spotted.


135-138: Appending one or many elements.

Tests testAppendOne and testAppendMany confirm correct behavior for single and bulk appends. Nicely done.


140-142: Appending collections.

testAppendColl checks appending entire collections. Straightforward coverage.


145-146: Applying functions to each element.

Valid coverage with testApply. No concerns.


149-150: Index-based element access with testAt.

Ensures At() is correct. Implementation looks fine.


153-154: Default-based element access with testAtOrDefault.

Zero-index edge cases are covered. Good approach.


157-158: Clearing the sequence.

testClear checks full removal of items. Looks good.


161-162: Contains() test.

Verifies correct predicate matching. Straightforward.


165-166: Count() test.

Ensures correct counting logic with multiple conditions. No issues.


169-170: Each() iteration test.

Simple iteration coverage. Approved.


173-174: Reverse iteration with EachRev().

Confirmed coverage for iterating in reverse order.


177-178: Conditional reverse iteration with EachRevUntil().

Verifies early-stop logic in reverse iteration.


181-182: Conditional forward iteration with EachUntil().

Ensures early-stop logic in normal iteration.


185-187: Extended duplicate testing in Find().

Including testFindWithDupes broadens coverage for repeated elements.


190-192: Extended duplicate testing in FindLast().

Ensures correct retrieval of the last matching element.


195-196: Folding sequence elements.

testFold checks accumulation logic. Looks fine.


199-200: Head() test coverage.

Confirms retrieval of the first element.


203-204: HeadOrDefault() test coverage.

Ensures safe retrieval of the first element or default.


207-208: Index-based insertion.

testInsertAt checks that items are inserted at the correct position.


211-212: Empty check.

testIsEmpty carefully verifies empty vs. non-empty sequences.


215-216: Len() coverage.

Ensures the length is reported correctly.


219-221: Prepending items.

testPrependOne and testPrependMany confirm behavior at the front of the sequence.


224-225: Reduce() test coverage.

Validates reduction logic with or without empty collection.


228-229: Removal by index.

testRemoveAt checks correct removal at specified positions.


232-233: Removal by matching predicate.

testRemoveMatching ensures items meeting certain conditions are removed.


236-238: Reverse logic validation.

testReverse and testReverseTwice confirm reversing the sequence multiple times.


241-243: Linear search coverage.

testSearch and testSearchPair handle normal search scenarios for single and pair-based sequences.


246-248: Reverse search coverage.

testSearchRev and testSearchRevPair confirm backward search.


251-252: Sort() coverage.

Ensures items are sorted correctly.


255-256: Tail() test coverage.

Checks retrieval of last element in the sequence.


259-260: TailOrDefault() test coverage.

Ensures safe retrieval of the last element or default.


263-264: Converting to slice.

testToSlice checks that sequences convert properly.


267-269: Breaking from Values() iteration.

testValues and testValuesBreak confirm partial iteration logic.


272-273: Copying the sequence.

testCopy verifies a new sequence instance with equivalent data.

sequencecmp_test.go (48)

13-13: Empty sequence creation returning a nil slice.

Similar to sequence_test.go, confirm that returning []int(nil) is acceptable for your use cases.


28-31: ThreeRev() method for reverse order.

Provides a reversed sequence for testing or usage. Approved.


36-42: FromValues() builder for comfyCmpSeq.

Populates the sequence from arbitrary inputs. Straightforward approach.


44-46: Extracting raw values.

extractRawValues delegates to extractUnderlyingSlice, a clean separation of concerns.


48-50: Underlying slice extraction.

Exposes s from the comfyCmpSeq for testing. Straightforward.


52-58: Unimplemented extraction methods returning nil.

extractUnderlyingMap and extractUnderlyingKp currently return nil. If these are placeholders, that’s fine; otherwise clarify their usage plans.


60-66: Extracting the values counter.

Good introduction of extractUnderlyingValsCount(). The panic is helpful to catch missing counters.


68-79: make() function with new values counter logic.

Populating vc via Increment ensures accurate counts for later operations. Implementation looks correct.


86-87: Verifying default comfyCmpSeq is empty.

Reflection-based check for []int(nil) plus a fresh valuesCounter is thorough.


94-95: String-based empty sequence check.

Ensures []string(nil) plus an empty counter is also handled.


99-131: NewCmpSequenceFrom tests.

Checks initialization of underlying slice and the values counter. Good demonstration of the new counting logic.


134-136: Appending elements.

testAppendOne and testAppendMany confirm appended items update both s and the counter.


139-140: Appending collections.

Ensures multiple items are appended and counted correctly.


143-144: Apply() coverage.

Confirms the function is applied to each element properly.


147-148: At() coverage.

Ensures correct index-based retrieval.


151-152: AtOrDefault() coverage.

Checks safe retrieval for out-of-bounds.


155-156: Clear() coverage.

Ensures clearing the sequence also resets the values counter.


159-160: Contains() coverage.

Simple predicate-based contain check.


163-164: ContainsValue() coverage.

Leverages the values counter for O(1) membership checks. Looks good.


167-168: Count() coverage.

Verifies predicate-based counts. No issues.


171-172: CountValues() coverage.

Ensures that the entire valuesCounter is used to get counts.


175-176: Forward iteration with Each().

Checks simple iteration logic. Approved.


179-180: Backward iteration with EachRev().

Ensures correct reverse iteration.


183-184: EachRevUntil() coverage.

Verifies early stopping in reverse iteration.


187-188: EachUntil() coverage.

Ensures early stopping in normal iteration.


191-192: Find() coverage.

Checks single match logic with the new counting approach.


195-196: FindLast() coverage.

Validates last-match behavior.


198-200: Fold() coverage.

Ensures accumulation logic works properly with counted sequences.


202-204: HasValue() coverage.

Confirms membership checks using the valuesCounter.


215-216: IndexOf() coverage.

Ensures correct index discovery for existing elements.


218-233: IndexOf() invalid internal state test.

Panic on mismatch between vc and s is a solid safeguard. Great test.


247-262: LastIndexOf() invalid internal state test.

Similar to IndexOfInvalidState, verifying mismatch gracefully triggers a panic.


265-266: Len() coverage.

Verifies length matches the slice size.


269-270: Max() coverage.

Ensures correct maximum detection with the cmpBaseInternal approach.


273-274: Min() coverage.

Similar approach to finding the minimum. Looks good.


277-279: Prepend coverage.

Verifies adding elements at the beginning updates the sequence and counter.


281-283: Reduce coverage.

Checks the reduce function on a counted sequence.


286-287: RemoveAt coverage.

Ensures removing by index updates sequence and counter.


290-291: RemoveMatching coverage.

Confirms removing items via predicate updates both structures.


298-300: Reverse coverage.

testReverse and testReverseTwice confirm reversing. No issues.


303-304: Search coverage.

Ensures standard searching logic works with the counting approach.


307-308: Reverse search coverage.

testSearchRev checks backward searching.


311-312: Sort coverage.

Ensures correct sorting with index-based logic.


315-316: Ascending sort coverage.

testSortAsc verifies ascending ordering with comparators.


323-324: Sum coverage.

testSum ensures numeric summation logic with cmpBaseInternal.


335-336: ToSlice coverage.

Confirms correct slice extraction.


339-341: Values iteration coverage.

testValues and testValuesBreak confirm iteration with possible early breaks.


344-345: Copy coverage.

Ensures a newly allocated instance with matching data and counts.

cmpmutable_cases_test.go (25)

10-10: Generalization of builder type signature looks good.
This refactor to remove the second type parameter in orderedMutableCollIntBuilder helps maintain a cleaner interface.


18-19: Improved test verification for empty collections.
Replacing []int{} with []int(nil) and adding a want2 map is a neat approach to verify both the slice content and internal value counts for empty collections.


25-26: Consistent approach for single-item collection.
Great job ensuring that the new want2 verification is also applied for one-item cases.


33-33: Enhanced coverage for removal tests.
Including want2: map[int]int{222: 1, 333: 1} is helpful to confirm the internal count logic for partial removals.


40-40: Consistent test verification for second removal scenario.
Using want2: map[int]int{111: 1, 333: 1} aligns well with the new counting approach.


47-47: Removal test coverage is comprehensive.
Verifying removal of the third item with want2: map[int]int{111: 1, 222: 1} ensures correctness.


54-54: Correctly verifying no removal.
want2: map[int]int{111: 1, 222: 1, 333: 1} underscores that the collection remains unchanged if the value isn't found.


61-61: Multiple duplicates removal test improved.
want2: map[int]int{222: 2, 333: 2} after removing two 111s is an excellent validation of duplicate handling.


68-68: Increased clarity for removing repeated values.
Tracking want2: map[int]int{111: 2, 333: 2} ensures that the correct duplicates are removed.


75-75: Ensuring multi-duplicate removal logic.
This test case for 333 duplicates further cements consistent behavior (want2: map[int]int{111: 2, 222: 2}).


85-91: Enhanced result verification in testRemoveValues.
Good job extracting both the raw slice (actualSlice) and the underlying values count (actualVC) to validate removal logic thoroughly.


97-97: Generics-based function signature for sorting tests.
Switching to a func getSortAscCases[C any](...) approach increases reusability of the test builder.


99-103: Nil slice vs. empty map for empty collection.
Declaring both want1: []int(nil) and want2: map[int]int{} ensures consistent representation of an empty state.


106-106: One-item collection test case logic is correct.
The transition to a generic test case structure provides uniform coverage for single-element scenarios.


110-110: Value count verification for single item.
want2: map[int]int{111: 1} demonstrates that sorting preserves item counts correctly.


113-113: Validating ascending sort with multiple items.
Explicitly enumerating [111, 222, 333] verifies correct sorting for standard ascending sequences.


117-117: Ensuring counts remain intact post-sort.
want2: map[int]int{111: 1, 222: 1, 333: 1} reconfirms that sorting didn’t alter duplicates count.


120-120: Testing sorting with duplicates.
want1: []int{111, 111, 222, 222, 333, 333} is a comprehensive approach for verifying stable sorting.


124-124: Confirmed correct value count for duplicates after sort.
want2 remains consistent: {111: 2, 222: 2, 333: 2}.


127-131: Reversed collection sorting coverage.
Handling of reversed sequences is now validated with builder.ThreeRev() and verifying both slice and map via want2.


134-138: Six-item reversed collection test.
The logic neatly checks for correct ascending order and ensures duplicates remain valid in want2.


141-141: Return statement for test cases is straightforward.
Good to see them all grouped into a single slice.


151-151: Generic signature for testSortAsc.
This change aligns sorting tests with the new internal constraints.


156-164: Detailed validation after SortAsc().
Extracting raw values and verifying the underlying values count fosters robust coverage.


168-220: Comprehensive descending sort test scenarios.
All lines ensure thorough coverage with reversed order, duplicates, etc.

map.go (2)

5-425: Overall structural refactor from kvPair to Pair[K, V].
The conversion to store Pair[K, V] across comfyMap improves clarity and consistency. The updated set/get logic and new methods (e.g., RemoveAt) appear correct and cohesive.


63-65:

Details

✅ Verification successful

Check interface usage for Pair return values.
Returning nil for a Pair[K, V] suggests Pair is an interface. Confirm that all usage sites handle potential nil values correctly.


🏁 Script executed:

#!/bin/bash
# Search for references to At() usage to ensure nil-checks are in place.
rg -A 5 'At\s*\('

Length of output: 26713


Verified: Pair Interface Usage is Consistent and Safe

After checking across the codebase, we’ve confirmed that the At() methods in both map.go and related implementations (e.g., in mapcmp.go) correctly return nil when the index is out of bounds. The associated tests (in files like map_cases_test.go and map_test.go) verify that all usage sites properly handle the potential nil values returned for a Pair[K, V].

No further modifications are required.

functions_internal.go (3)

146-147: Min comparison logic not covered by tests.
The lines handling the current < acc check in comfyMin remain untested. Ensure you include a scenario that triggers a new minimum in your test suite.

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 146-147: functions_internal.go#L146-L147
Added lines #L146 - L147 were not covered by tests


243-259: Summation logic introduced for ordered values.
comfySum and comfySumOfPairs unify summation across collections. Implementation looks sound.


261-274: sliceRemoveAt enhancements are correct.
Returning the removed element and ensuring an out-of-bounds error fosters safer usage.

definitions.go (13)

20-20: Parameter rename looks good.
Switching from v to val enhances clarity and consistency in function signatures.


23-23: Parameter rename looks good.
Again, using val instead of v improves consistency.


29-29: Parameter rename looks good.
This is consistent with other mapper function signatures.


31-35: Introducing comparator types.
Defining Comparator and PairComparator clearly separates element comparison from key-value comparison, improving reusability.


41-41: Key-Value predicate signature.
The updated parameter names improve readability and align with the naming convention established.


64-67: Added forward and reverse search methods.
Search and SearchRev provide symmetrical lookup patterns. Ensure any references to the old search methods are updated, and incorporate appropriate tests if not already present.


75-78: BasePairs interface refinement.
Embedding Base[Pair[K, V]] clarifies that pairs remain the fundamental unit. This interface flattening helps maintain a consistent abstraction.


118-119: Enhanced IndexedMutable.
Adding (removed V, err error) return signature for RemoveAt and introducing a Sort method fosters a more robust API for mutable indexed collections.


132-134: Index-based access for values.
HasValue, IndexOf, and LastIndexOf round out typical collection operations. Usage looks straightforward.


187-208: Comprehensive Map interface augmentation.
Composing BasePairs, IndexedMutable, and LinearMutable broadens map capabilities. Ensure that the newly added methods (e.g., SetMany, RemoveMany) are consistently tested.


211-214: CmpMap interface extension.
Deriving from Map[K, V] while adding CmpMutable[V] merges map operations with ordering semantics. This design clarifies typed constraints on map values.


221-222: Pair now supports value mutation.
Val() plus SetVal() fosters a more open approach to pair modifications. Ensure concurrency concerns (if any) are addressed.


226-231: NewPair constructor.
Straightforward constructor returning a handled implementation of Pair[K, V]. Good addition for standardizing pair creation.

mapcmp.go (64)

8-8: Additional import for map utilities.
Importing "maps" can simplify operations like maps.Collect(...).


13-20: New CmpMap creation.
The constructor initializes slices, maps, and the valuesCounter, setting a foundation for powerful typed operations.


22-27: Factory method to build map from pairs.
NewCmpMapFrom clarifies usage by letting clients provide pairs directly. Implementation references setMany, promoting code reuse.


30-34: Internal structure for comfyCmpMap.
Storing pairs in both a slice (s) and a map (m), plus kp for indexing, appears well structured for combined index-based and hash-based lookups.


36-38: Append method.
Delegation to comfyAppendMap retains consistent logic. Straightforward approach for adding new pairs.


40-42: AppendColl method.
Accepts another Linear collection, converting it to a slice for append. Good extension for composability.


44-64: Apply method re-initialization.
Reconstructing the entire internal state ensures correct mapping results without partial updates. Performance is O(n), which is acceptable unless extremely large collections require more incremental updates.


66-71: At method returns nil for out-of-bounds.
Returning nil for Pair[K, V] when out of range might raise nil dereferences if callers forget the found check. Document thoroughly or provide a no-op pair to avoid potential runtime issues.


73-78: AtOrDefault method.
Simple fallback approach if index is out of range. This is consistent with typical "or default" patterns.


80-85: Clear method.
Re-initializes all fields, effectively resetting. Straightforward and easy to reason about.


87-88: Contains with a helper.
comfyContains usage ensures consistency with the rest of the codebase’s utility approach.


91-95: Value-based containment check.
ContainsValue logic is well aligned with the element-based approach in Contains.


97-99: Count method.
Good usage of the comfyCount helper, consistent with parallel APIs.


101-105: CountValues for duplicates.
Allows direct counting of how many times a certain value appears. Minimal overhead beyond standard iteration.


107-110: Forward iteration with Each.
Direct iteration over the underlying slice. Implementation is straightforward.


113-116: Reverse iteration with EachRev.
Iterating in reverse is helpful for cases needing the last entry first. Clean approach.


119-125: Reverse iteration with early exit.
Provides a short-circuit mechanism. Be mindful that the condition might be inverted (stop on !f). Implementation is consistent with the forward variant.


127-133: Forward iteration with early exit.
Mirrors the logic in EachRevUntil. Behavior remains predictable.


135-137: Find method.
Fallback to defaultValue if not found. Clean helper usage of comfyFind.


139-141: FindLast method.
Mirrors Find logic but in reverse. Symmetry is good for search-based operations.


143-144: Fold method.
Aggregates pairs in a manner consistent with typical functional fold.


147-154: Get method.
Retrieves from the map quickly while preserving pair semantics. Returning false if missing is standard.


156-162: GetOrDefault method.
Simple fallback ensures we return a user-specified default if the pair is absent.


164-167: Has key check.
A straightforward membership check that complements Get.


169-171: HasValue delegates to ContainsValue.
This minor convenience function is consistent with existing patterns.


173-178: Head method returns nil for empty.
Similar to At, returning nil when empty might lead to unguarded calls to .Key(). Ensure usage is well documented.


180-185: HeadOrDefault.
Gives a default pair when no head is present. Good approach for safe retrieval.


187-195: IndexOf method.
Detects the first occurrence of a value. Standard approach.


196-204: (Additional IndexOf logic).
Continues searching for duplicates in larger collections. Follows a consistent pattern.


196-198: IsEmpty method.
Zero-length check for slice-based collections.


200-208: KeyValues method.
Returns a lazy factory that yields key-value pairs. Alignment with iter.Seq2 is consistent.


210-218: Keys method.
Similar lazy approach for keys only.


220-222: KeysToSlice method.
Builds on top of Keys. slices.Collect usage is straightforward.


224-231: LastIndexOf method.
Searching from the end for a matching value. Matches forward IndexOf logic.


233-235: Len method.
Returns slice length, minimal overhead.


237-239: Max function.
Uses the comfyMaxOfPairs helper. Integrates well with generic type constraints.


241-243: Min function.
Implemented similarly to Max for symmetrical behavior.


245-247: Prepend operation.
Defers logic to a dedicated method (prependAll). Good for consistency with Append.


249-251: Reduce operation.
Reuses comfyReduceSlice, matching the approach used elsewhere.


253-255: Remove by key.
A direct call to internal remove. Straightforward single-key removal.


257-265: RemoveAt method.
Leverages sliceRemoveAt, updates maps, and decrements value count. Implementation is thorough.


267-269: RemoveMany method.
Extends the single-key removal logic. Useful for batch deletions.


271-292: RemoveMatching method.
Filters out pairs that match a predicate, re-allocating internal structures. Standard pattern for selective removal.


294-299: RemoveValues convenience.
Focuses on a single value match. Internally calls RemoveMatching.


300-309: Reverse method.
Reverses the slice in place, re-indexes kp. Implementation looks consistent.


311-318: Search returning nil for unfound pairs.
Same caveat as At: ensure users always check the boolean before accessing the interface.


320-327: SearchRev reversing the search.
Consistent approach to Search. Just note the same nil caveat if not found.


329-331: Set method.
Adds or replaces a key’s pair, updating the supporting data structures.


333-335: SetMany method.
Batch version of Set; reuses setMany.


337-339: Sort method.
Uses comfySortSliceAndKP to reorder pairs. This is critical for maintaining a consistent kp index post-sort.


341-349: SortAsc method.
Default ascending sort by pair values. Basic comparison logic is correct.


352-361: SortDesc method.
Mirrors SortAsc with reversed comparison. Keeps the code symmetrical.


363-365: Sum method.
Computes sum of values in the map, reusing a helper function. Straightforward.


367-372: Tail method returns nil if empty.
Analogous to Head. Same potential risk of nil usage if callers do not check.


374-379: TailOrDefault method.
Provides a default for empty maps, skipping nil.


381-383: ToMap method.
Builds a native map[K]V. The underlying iteration uses maps.Collect for convenience.


385-387: ToSlice method.
Collects pairs into a slice, aligning well with Values().


389-397: Values method.
Returns a lazy enumerator for content. This matches the approach used in KeyValues().


401-408: copy method.
Generates a new map instance by reusing set logic and creating fresh pair copies.


410-423: set method.
Handles insertion or replacement, adjusting counters and indexes. Code structure is direct.


425-455: prependAll method.
Works in two passes: first adds new pairs, then re-adds existing ones. Implementation is well-structured.


457-474: remove method.
Removes the pair from both slice and maps, carefully reindexing the remaining elements.


476-508: removeMany method.
Extends single-key removal while batching keys. Good approach to avoid repeated overhead in multiple remove calls.


510-514: setMany method.
Batched version of set. Contributes to performance improvements when adding multiple pairs.

cmp_cases_test.go (15)

8-47: Test cases for ContainsValue.
The variety of scenarios (empty, one-item, multi-item with duplicates) ensures robust coverage.


49-58: testContainsValue function.
Iterates over cases, validating correctness. Straightforward usage of table-driven tests.


60-69: testHasValue duplicates testContainsValue logic.
Consistent with the library’s naming patterns. The reuse ensures alignment between analogous methods.


71-128: getCountValuesCases.
Covers single, multiple, and zero occurrences. Thorough for verifying CountValues.


130-140: testCountValues function.
Prints both result and wanted outcome. Keep or remove the error messages for clarity.


142-210: getIndexOfCases.
Drills edge cases, including empty collections and duplicates. Good coverage.


212-225: testIndexOf function.
Checks both index and boolean. Fulfills thorough testing for partial or absent values.


227-293: getLastIndexOfCases.
Mirrors getIndexOfCases with reversed logic. Good parallel structure.


295-308: testLastIndexOf function.
Similar approach to testIndexOf, verifying last match. Straightforward.


310-334: getMaxCases.
Tests extremes (empty, single, multi). Accuracy for Max is well validated.


336-350: testMax function.
Ensures error handling for empty input and correct detection of the highest value.


352-376: getMinCases.
Parallel coverage for Min. Looks consistent with getMaxCases.


378-392: testMin function.
Mirrors testMax for verifying minimum detection.


394-417: getSumCases.
Examines summation across various collection sizes and duplicates.


419-429: testSum function.
Uses table-driven tests to validate the sum of items, including empty and multi-item scenarios.

map_test.go (2)

103-117: The test structure looks good

This test validates that NewMap[int, int]() returns a properly initialized map with all required internal structures.


328-364: Good test for deep copy behavior

This test effectively verifies that copy() creates both a new instance (pointer equality) and a deep copy (modifying the original doesn't affect the copy).

mapcmp_test.go (3)

111-126: Test structure matches collection implementation

The test properly validates that NewCmpMap[int, int]() returns a correctly initialized map with all internal structures, including the values counter.


325-327: Good test coverage for value-specific operations

Tests like Test_comfyCmpMap_RemoveValues cover important functionality specific to the enhanced map implementation. This shows good test coverage for the new features.


337-339: Comprehensive test suite

The test file provides excellent coverage of the new map implementation's functionality, including both standard map operations and the additional comparison features.

Comment on lines +30 to +36
func (c *valuesCounter[V]) Decrement(v V) {
if c.counter[v] == 1 {
delete(c.counter, v)
} else {
c.counter[v]--
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add check for key existence in Decrement method

The current implementation assumes the key exists in the map before checking if its count is 1. If a key doesn't exist, accessing it will return 0, causing incorrect behavior.

func (c *valuesCounter[V]) Decrement(v V) {
-	if c.counter[v] == 1 {
+	count, exists := c.counter[v]
+	if !exists {
+		return
+	}
+	if count == 1 {
		delete(c.counter, v)
	} else {
		c.counter[v]--
	}
}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
func (c *valuesCounter[V]) Decrement(v V) {
if c.counter[v] == 1 {
delete(c.counter, v)
} else {
c.counter[v]--
}
}
func (c *valuesCounter[V]) Decrement(v V) {
count, exists := c.counter[v]
if !exists {
return
}
if count == 1 {
delete(c.counter, v)
} else {
c.counter[v]--
}
}

Comment on lines 35 to 42
},
{
name: "InsertAt() on one-item collection at beginning",
coll: builder.One(),
args: listIntArgs{index: 0, value: 1},
want1: []int{1, 111},
want2: map[int]int{1: 1, 111: 1},
},
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Added duplicate test case for insertion at the beginning

This test case appears to be a duplicate of the one at lines 22-28, as both test "InsertAt() on one-item collection at beginning" with identical inputs and expected outputs.

Consider removing this duplicated test case, or if it's intended to test a different edge case, rename it to clarify the distinction.

Comment on lines +348 to +358
c1 := &comfyCmpSeq[int]{
s: []int{123, 234, 345},
vc: &valuesCounter[int]{
counter: map[int]int{
123: 1,
234: 1,
345: 1,
},
},
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Logic error in the deep copy test loop.

for v := range c2.(*comfyCmpSeq[int]).s {
    if v == 999 {
        t.Error("copy() did not create a deep copy")
    }
}

Again, v here is the index, not the actual element. Use:

for i, val := range c2.(*comfyCmpSeq[int]).s {
    if val == 999 {
        t.Error(...)
    }
}

to check elements correctly.

Also applies to: 368-369

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
cmp.go (2)

15-20: Consider simplifying the Count method.

While the current implementation is correct, Go maps return the zero value (0 for int) for non-existent keys, so you could potentially simplify this to just return c.counter[v]. However, the explicit check does make the code's intent clearer, so this is more of a stylistic suggestion.

func (c *valuesCounter[V]) Count(v V) int {
-	if _, ok := c.counter[v]; !ok {
-		return 0
-	}
-	return c.counter[v]
+	return c.counter[v]
}

22-28: Consider simplifying the Increment method.

Similar to the Count method, you could potentially simplify this by leveraging Go's zero value behavior for maps. However, the explicit check does make the code's intent clearer.

func (c *valuesCounter[V]) Increment(v V) {
-	if _, ok := c.counter[v]; !ok {
-		c.counter[v] = 1
-	} else {
-		c.counter[v]++
-	}
+	c.counter[v]++
}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 08cdbe4 and 6cc8677.

📒 Files selected for processing (3)
  • cmp.go (1 hunks)
  • list_cases_test.go (3 hunks)
  • sequencecmp_test.go (6 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • list_cases_test.go
  • sequencecmp_test.go
🧰 Additional context used
🪛 GitHub Check: codecov/patch
cmp.go

[warning] 33-34: cmp.go#L33-L34
Added lines #L33 - L34 were not covered by tests

🔇 Additional comments (2)
cmp.go (2)

1-7: Well-structured generic type declaration.

The valuesCounter type is properly defined with a generic parameter V constrained to cmp.Ordered, which ensures values can be compared and used as map keys. This is a good design choice for a counter implementation.


9-13: Constructor implementation looks good.

The constructor function properly initializes the counter map. The lowercase function name indicates it's package-private, which is appropriate if this type is meant to be used only internally within the package.

Comment on lines +30 to +40
func (c *valuesCounter[V]) Decrement(v V) {
count, exists := c.counter[v]
if !exists {
return
}
if count == 1 {
delete(c.counter, v)
} else {
c.counter[v]--
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

❓ Verification inconclusive

Add test coverage for the non-existent key case in Decrement.

The implementation correctly checks for key existence before attempting to decrement, which addresses the issue raised in the previous review. However, static analysis indicates that lines 33-34 (the early return when a key doesn't exist) aren't covered by tests.

Please add test cases that verify the behavior when attempting to decrement a non-existent key to ensure complete test coverage.


🏁 Script executed:

#!/bin/bash
# Check if there are any existing tests that might cover this code path
rg -A 5 -B 5 "Decrement" --glob "**/*_test.go"

Length of output: 46


Action Required: Add Test Case for Non-Existent Key in Decrement

The Decrement method in cmp.go (lines 30–40) handles the non-existent key case by returning early when the key isn't found. However, our repository lacks tests covering this branch (as indicated by the absence of test output for references to Decrement in *_test.go files). Please add a unit test that calls Decrement on a key not present in the counter to verify that it exits gracefully without modifying the counter.

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 33-34: cmp.go#L33-L34
Added lines #L33 - L34 were not covered by tests

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (4)
cmp_test.go (4)

5-35: Good test for valuesCounter but could be improved with table-driven testing

The test covers key functionality, including edge cases like decrementing before incrementing (line 8) and checking for non-existent values (line 31-33). However, consider using a table-driven test approach to reduce repetition in the assertion blocks.

func Test_valuesCounter(t *testing.T) {
	t.Run("Increment() and Count()", func(t *testing.T) {
		vc := newValuesCounter[int]()
		vc.Decrement(1)
		vc.Increment(1)
		vc.Increment(1)
		vc.Increment(2)
		vc.Increment(3)
		vc.Increment(3)
		vc.Increment(3)
		vc.Increment(4)
		vc.Increment(4)
		vc.Increment(4)
		vc.Increment(4)
-		if vc.Count(1) != 2 {
-			t.Errorf("Count(1) = %v, want %v", vc.Count(1), 2)
-		}
-		if vc.Count(2) != 1 {
-			t.Errorf("Count(2) = %v, want %v", vc.Count(2), 1)
-		}
-		if vc.Count(3) != 3 {
-			t.Errorf("Count(3) = %v, want %v", vc.Count(3), 3)
-		}
-		if vc.Count(4) != 4 {
-			t.Errorf("Count(4) = %v, want %v", vc.Count(4), 4)
-		}
-		if vc.Count(5) != 0 {
-			t.Errorf("Count(5) = %v, want %v", vc.Count(5), 0)
-		}
+		testCases := []struct {
+			value    int
+			expected int
+		}{
+			{1, 2},
+			{2, 1},
+			{3, 3},
+			{4, 4},
+			{5, 0}, // Non-existent value
+		}
+		
+		for _, tc := range testCases {
+			t.Run(fmt.Sprintf("Count(%d)", tc.value), func(t *testing.T) {
+				if count := vc.Count(tc.value); count != tc.expected {
+					t.Errorf("Count(%d) = %v, want %v", tc.value, count, tc.expected)
+				}
+			})
+		}
	})
}

Remember to add "fmt" to the imports if you implement this refactoring.


6-6: Update subtest name to reflect all tested methods

The subtest name only mentions "Increment() and Count()", but the test also exercises the Decrement() method on line 8.

-	t.Run("Increment() and Count()", func(t *testing.T) {
+	t.Run("Increment(), Decrement(), and Count()", func(t *testing.T) {

6-34: Consider adding separate subtests for each method

The current approach tests multiple methods in a single test. Consider restructuring to test each method separately for better isolation and clearer failure messages.

You could split this into separate subtests:

  1. A test for basic Increment() and Count() behavior
  2. A test specifically for Decrement() behavior
  3. A test for the zero/default behavior (e.g., counting non-existent values)

This would make the test more maintainable and easier to debug if failures occur.


8-18: Consider documenting the test pattern or setup with comments

The test performs a specific sequence of operations, but it's not immediately clear why these exact operations were chosen. Adding a brief comment to explain the test setup would improve readability.

func Test_valuesCounter(t *testing.T) {
	t.Run("Increment() and Count()", func(t *testing.T) {
+		// Create counter and test:
+		// - Decrementing a non-existent value
+		// - Multiple increments with different frequencies
+		// - Counting both existing and non-existing values
		vc := newValuesCounter[int]()
		vc.Decrement(1)
		vc.Increment(1)
		vc.Increment(1)
		// ...rest of the code
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6cc8677 and 22ca276.

📒 Files selected for processing (2)
  • cmp.go (1 hunks)
  • cmp_test.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • cmp.go

@maciej-sz maciej-sz merged commit 197498c into main Mar 10, 2025
4 checks passed
@maciej-sz maciej-sz deleted the feat/#5/map-collections branch March 10, 2025 22:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implement Map collections

1 participant