Adds generics
This fork converts Ben's immutable types with generics. Tests are passing. I haven't really test driven this, but tests are passing...
Notes and open points:
- List was easier to port. No major changes
- Map: existing hashing / comparison functions are used, but adjusted
- Map:
exp/constraints.Orderedis used for map keys - this was mainly for the SortedMap support, but it seemed a lot easier to use the same constraint across the board. Note thatcomparabledoesn't support greater-than/less-than, only equality. I'm thinking it might be best to define our own constraint here, for future-proofing as much as anything. I'll aim to implement that on the weekend - Map: BREAKING CHANGE: byte slices are no longer supported as hash keys, because of the Ordered constraint. I figure a
string(b)conversion is easy enough? - I don't know the best way to arrange the go mod.
github.com/benjohnson/immutable/v2seemed appropriate because it's a breaking change. - I don't know if there's a nicer way to design the API with further changes - I've gone for the least resistance (there was already a fair bit of resistance, but it fell into place eventually)
- e.g. could we be using
hash/maphashnow? I experimented with it, but tests failed
- e.g. could we be using
- WARNING: I did a LOT of repetitive fiddly changes here, and I may have messed up. Honestly I've been away from Go for a year and I just wanted a challenge, so this is the result. If someone is using the original, I'd be grateful for feedback.
this addresses #22
Here's the benchmarks for before/after on my Macbook air ... it seems faster, for some things more than others, and there's got to be opportunities to optimize ...
Before (behnbjohnson/master):
goos: darwin
goarch: arm64
pkg: github.com/benbjohnson/immutable
BenchmarkList_Append-8 1443585 875.8 ns/op 3016 B/op 7 allocs/op
BenchmarkList_Prepend-8 1774755 745.6 ns/op 2521 B/op 6 allocs/op
BenchmarkList_Set-8 2509384 474.4 ns/op 2280 B/op 6 allocs/op
BenchmarkList_Iterator/Forward-8 192071424 6.183 ns/op
BenchmarkList_Iterator/Reverse-8 191412490 6.270 ns/op
BenchmarkBuiltinSlice_Append/Int-8 300424912 11.17 ns/op 46 B/op 0 allocs/op
BenchmarkBuiltinSlice_Append/Interface-8 21144768 57.92 ns/op 103 B/op 0 allocs/op
BenchmarkListBuilder_Append-8 33901096 35.69 ns/op 24 B/op 1 allocs/op
BenchmarkListBuilder_Prepend-8 40533464 32.22 ns/op 24 B/op 1 allocs/op
BenchmarkListBuilder_Set-8 55060813 21.26 ns/op 8 B/op 0 allocs/op
BenchmarkBuiltinMap_Set-8 12485011 114.7 ns/op 59 B/op 0 allocs/op
BenchmarkBuiltinMap_Delete-8 211588881 4.982 ns/op 0 B/op 0 allocs/op
BenchmarkMap_Set-8 1000000 1022 ns/op 2192 B/op 9 allocs/op
BenchmarkMap_Delete-8 1000000 1033 ns/op 2537 B/op 8 allocs/op
BenchmarkMap_Iterator/Forward-8 100000000 10.07 ns/op
BenchmarkMapBuilder_Set-8 8836093 161.3 ns/op 121 B/op 4 allocs/op
BenchmarkMapBuilder_Delete-8 10081660 111.5 ns/op 16 B/op 1 allocs/op
BenchmarkSortedMap_Set-8 1000000 1200 ns/op 3671 B/op 13 allocs/op
BenchmarkSortedMap_Delete-8 1505666 796.1 ns/op 1869 B/op 10 allocs/op
BenchmarkSortedMap_Iterator/Forward-8 201211854 5.942 ns/op
BenchmarkSortedMap_Iterator/Reverse-8 204755415 5.861 ns/op
BenchmarkSortedMapBuilder_Set-8 7003861 198.0 ns/op 95 B/op 3 allocs/op
BenchmarkSortedMapBuilder_Delete-8 98165811 10.84 ns/op 8 B/op 1 allocs/op
PASS
ok github.com/benbjohnson/immutable 129.150s
After (this PR):
goos: darwin
goarch: arm64
pkg: github.com/benbjohnson/immutable/v2
BenchmarkList_Append-8 2332291 627.7 ns/op 2909 B/op 6 allocs/op
BenchmarkList_Prepend-8 2791215 515.3 ns/op 2377 B/op 5 allocs/op
BenchmarkList_Set-8 3069924 389.2 ns/op 2016 B/op 5 allocs/op
BenchmarkList_Iterator/Forward-8 184800504 6.486 ns/op
BenchmarkList_Iterator/Reverse-8 186225578 6.455 ns/op
BenchmarkBuiltinSlice_Append/Int-8 306112687 8.559 ns/op 45 B/op 0 allocs/op
BenchmarkBuiltinSlice_Append/Interface-8 17291928 64.86 ns/op 101 B/op 0 allocs/op
BenchmarkListBuilder_Append-8 46185006 30.13 ns/op 8 B/op 0 allocs/op
BenchmarkListBuilder_Prepend-8 63284326 26.48 ns/op 8 B/op 0 allocs/op
BenchmarkListBuilder_Set-8 80127535 15.00 ns/op 0 B/op 0 allocs/op
BenchmarkBuiltinMap_Set-8 12888039 116.1 ns/op 58 B/op 0 allocs/op
BenchmarkBuiltinMap_Delete-8 212144166 4.973 ns/op 0 B/op 0 allocs/op
BenchmarkMap_Set-8 1269951 969.8 ns/op 2206 B/op 7 allocs/op
BenchmarkMap_Delete-8 1221712 990.8 ns/op 2522 B/op 8 allocs/op
BenchmarkMap_Iterator/Forward-8 122431260 9.824 ns/op
BenchmarkMapBuilder_Set-8 12529899 138.8 ns/op 72 B/op 2 allocs/op
BenchmarkMapBuilder_Delete-8 10718444 96.90 ns/op 1 B/op 0 allocs/op
BenchmarkSortedMap_Set-8 1525124 796.2 ns/op 2670 B/op 11 allocs/op
BenchmarkSortedMap_Delete-8 2183881 549.2 ns/op 1335 B/op 10 allocs/op
BenchmarkSortedMap_Iterator/Forward-8 233916456 5.103 ns/op
BenchmarkSortedMap_Iterator/Reverse-8 241015518 4.996 ns/op
BenchmarkSortedMapBuilder_Set-8 9526461 146.9 ns/op 39 B/op 1 allocs/op
BenchmarkSortedMapBuilder_Delete-8 440195383 2.636 ns/op 0 B/op 0 allocs/op
PASS
ok github.com/benbjohnson/immutable/v2 119.909s
@laher Thanks for having a go at this. I've been on a Rust project for the last month so I haven't had a chance to dig into the Go generics yet. I took a quick once over and I think it's looking good. I'll probably defer merging this until Go 1.19 is out just so folks have time to move over. The immutable library is still pre-1.0 so I'm not worried about breaking compatibility. I'll just bump this to v0.4.0 once it's merged.
In the meantime, if anyone else gets a chance to try this branch out, please drop your feedback here in this issue.
Cool, makes sense. That also gives me time to ask a few best practice questions on gophers slack #generics channel. For now I have fixed the github action (it was on go1.15 and didn't recognise the [T] syntax), and I removed that v2 module change.
On Fri, May 20, 2022 at 12:00 PM Ben Johnson @.***> wrote:
@laher https://github.com/laher Thanks for having a go at this. I've been on a Rust project for the last month so I haven't had a chance to dig into the Go generics yet. I took a quick once over and I think it's looking good. I'll probably defer merging this until Go 1.19 is out just so folks have time to move over. The immutable library is still pre-1.0 so I'm not worried about breaking compatibility. I'll just bump this to v0.4.0 once it's merged.
In the meantime, if anyone else gets a chance to try this branch out, please drop your feedback here in this issue.
— Reply to this email directly, view it on GitHub https://github.com/benbjohnson/immutable/pull/23#issuecomment-1132309803, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAA6XFIYQF5N2YOM2UHZQ2TVK3IYTANCNFSM5WL5NLFQ . You are receiving this because you were mentioned.Message ID: @.***>
Hi @benbjohnson. Go 1.19 is out now, so maybe it's time to revisit this?
I had another look through it, it looks pretty straightforward. I've been exploring generics quite a bit more since writing this PR, and this still looks like the natural approach to me. I don't have any improvements to add.
What do you think?
@laher I actually still haven't used generics yet since they were released. I'll take a look over this PR tomorrow and probably merge it in. 👍
I gave this a review and it looks pretty straightforward. I'll go ahead and merge and cut a new release. If anyone comes across issues with the API then we can address that in future PRs. Thanks, @laher!