docs: update Last documentation to reflect panic behavior

Document that Last panics on empty slices with a clear error message.
Add examples for single element and empty slice cases.

Related to Issue 13 (PR #41)

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Ruidy 2025-11-16 08:49:04 +01:00
parent bcb4dd1e9d
commit 3617c2de8f
No known key found for this signature in database
GPG key ID: 705C24D202990805
13 changed files with 228 additions and 221 deletions

View file

@ -9,23 +9,23 @@ date: 2025-01-16T00:00:00-00:00
package main package main
import ( import (
"fmt" "fmt"
u "github.com/rjNemo/underscore" u "github.com/rjNemo/underscore"
) )
func main() { func main() {
nums := []int{1, 2, 3, 4, 5} nums := []int{1, 2, 3, 4, 5}
first, err := u.First(nums) first, err := u.First(nums)
if err != nil { if err != nil {
panic(err) panic(err)
} }
fmt.Println(first) // 1 fmt.Println(first) // 1
// Handle empty slice // Handle empty slice
empty := []int{} empty := []int{}
_, err = u.First(empty) _, err = u.First(empty)
if err != nil { if err != nil {
fmt.Println("Error:", err) // Error: underscore: empty slice fmt.Println("Error:", err) // Error: underscore: empty slice
} }
} }
``` ```

View file

@ -9,15 +9,15 @@ date: 2025-01-16T00:00:00-00:00
package main package main
import ( import (
"fmt" "fmt"
u "github.com/rjNemo/underscore" u "github.com/rjNemo/underscore"
) )
func main() { func main() {
nums := []int{1, 2, 3, 4, 5, 6, 7, 8, 9} nums := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
fmt.Println(u.FirstN(nums, 3)) // [1, 2, 3] fmt.Println(u.FirstN(nums, 3)) // [1, 2, 3]
fmt.Println(u.FirstN(nums, 0)) // [] fmt.Println(u.FirstN(nums, 0)) // []
fmt.Println(u.FirstN(nums, 10)) // [1, 2, 3, 4, 5, 6, 7, 8, 9] fmt.Println(u.FirstN(nums, 10)) // [1, 2, 3, 4, 5, 6, 7, 8, 9]
fmt.Println(u.FirstN(nums, -5)) // [] fmt.Println(u.FirstN(nums, -5)) // []
} }
``` ```

View file

@ -9,31 +9,31 @@ date: 2025-01-16T00:00:00-00:00
package main package main
import ( import (
"fmt" "fmt"
u "github.com/rjNemo/underscore" u "github.com/rjNemo/underscore"
) )
func main() { func main() {
// Subtraction is non-associative // Subtraction is non-associative
nums := []int{1, 2, 3} nums := []int{1, 2, 3}
// FoldRight: 1 - (2 - (3 - 0)) = 1 - (2 - 3) = 1 - (-1) = 2 // FoldRight: 1 - (2 - (3 - 0)) = 1 - (2 - 3) = 1 - (-1) = 2
result := u.FoldRight(nums, 0, func(n, acc int) int { return n - acc }) result := u.FoldRight(nums, 0, func(n, acc int) int { return n - acc })
fmt.Println(result) // 2 fmt.Println(result) // 2
// Compare with Reduce (left fold): (0 - 1) - 2 - 3 = -6 // Compare with Reduce (left fold): (0 - 1) - 2 - 3 = -6
leftResult := u.Reduce(nums, func(n, acc int) int { return acc - n }, 0) leftResult := u.Reduce(nums, func(n, acc int) int { return acc - n }, 0)
fmt.Println(leftResult) // -6 fmt.Println(leftResult) // -6
// Building a list in order // Building a list in order
buildList := u.FoldRight(nums, []int{}, func(n int, acc []int) []int { buildList := u.FoldRight(nums, []int{}, func(n int, acc []int) []int {
return append([]int{n}, acc...) return append([]int{n}, acc...)
}) })
fmt.Println(buildList) // [1, 2, 3] fmt.Println(buildList) // [1, 2, 3]
// String concatenation // String concatenation
words := []string{"a", "b", "c"} words := []string{"a", "b", "c"}
concat := u.FoldRight(words, "", func(s, acc string) string { return s + acc }) concat := u.FoldRight(words, "", func(s, acc string) string { return s + acc })
fmt.Println(concat) // "abc" fmt.Println(concat) // "abc"
} }
``` ```

View file

@ -9,24 +9,24 @@ date: 2025-01-16T00:00:00-00:00
package main package main
import ( import (
"fmt" "fmt"
u "github.com/rjNemo/underscore" u "github.com/rjNemo/underscore"
) )
func main() { func main() {
nums := []int{1, 2, 3, 4, 5} nums := []int{1, 2, 3, 4, 5}
init, last := u.Init(nums) init, last := u.Init(nums)
fmt.Println(init) // [1, 2, 3, 4] fmt.Println(init) // [1, 2, 3, 4]
fmt.Println(last) // 5 fmt.Println(last) // 5
// Single element // Single element
single, val := u.Init([]int{42}) single, val := u.Init([]int{42})
fmt.Println(single) // [] fmt.Println(single) // []
fmt.Println(val) // 42 fmt.Println(val) // 42
// Empty slice // Empty slice
empty, zero := u.Init([]int{}) empty, zero := u.Init([]int{})
fmt.Println(empty) // [] fmt.Println(empty) // []
fmt.Println(zero) // 0 fmt.Println(zero) // 0
} }
``` ```

View file

@ -9,20 +9,20 @@ date: 2025-01-16T00:00:00-00:00
package main package main
import ( import (
"fmt" "fmt"
u "github.com/rjNemo/underscore" u "github.com/rjNemo/underscore"
) )
func main() { func main() {
nums := []int{1, 2, 3, 4, 5} nums := []int{1, 2, 3, 4, 5}
fmt.Println(u.Intersperse(nums, 0)) // [1, 0, 2, 0, 3, 0, 4, 0, 5] fmt.Println(u.Intersperse(nums, 0)) // [1, 0, 2, 0, 3, 0, 4, 0, 5]
// Useful for formatting // Useful for formatting
words := []string{"apple", "banana", "cherry"} words := []string{"apple", "banana", "cherry"}
fmt.Println(u.Intersperse(words, ",")) // ["apple", ",", "banana", ",", "cherry"] fmt.Println(u.Intersperse(words, ",")) // ["apple", ",", "banana", ",", "cherry"]
// Single element - no separator added // Single element - no separator added
single := []int{42} single := []int{42}
fmt.Println(u.Intersperse(single, 0)) // [42] fmt.Println(u.Intersperse(single, 0)) // [42]
} }
``` ```

View file

@ -3,19 +3,26 @@ title: "Last"
date: 2022-03-21T13:46:24-04:00 date: 2022-03-21T13:46:24-04:00
--- ---
`Last` returns the last element of the slice. `Last` returns the last element of the slice. Panics if the slice is empty with a clear error message.
```go ```go
package main package main
import ( import (
"fmt" "fmt"
u "github.com/rjNemo/underscore" u "github.com/rjNemo/underscore"
) )
func main() { func main() {
nums := []int{1, 9, 2, 8, 3, 7, 4, 6, 5} nums := []int{1, 9, 2, 8, 3, 7, 4, 6, 5}
fmt.Println(u.Last(nums)) // 5
fmt.Println(u.Last(nums)) // 5 // Single element
single := []int{42}
fmt.Println(u.Last(single)) // 42
// Empty slice panics with clear message
// empty := []int{}
// u.Last(empty) // panic: underscore.Last: empty slice
} }
``` ```

View file

@ -11,40 +11,40 @@ date: 2025-01-16T00:00:00-00:00
package main package main
import ( import (
"context" "context"
"fmt" "fmt"
"time" "time"
u "github.com/rjNemo/underscore" u "github.com/rjNemo/underscore"
) )
func main() { func main() {
nums := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10} nums := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
ctx := context.Background() ctx := context.Background()
// Parallel sum (safe - addition is associative and commutative) // Parallel sum (safe - addition is associative and commutative)
result, err := u.ParallelReduce(ctx, nums, 4, func(ctx context.Context, n int, acc int) (int, error) { result, err := u.ParallelReduce(ctx, nums, 4, func(ctx context.Context, n int, acc int) (int, error) {
// Simulate expensive computation // Simulate expensive computation
time.Sleep(10 * time.Millisecond) time.Sleep(10 * time.Millisecond)
return n + acc, nil return n + acc, nil
}, 0) }, 0)
if err != nil { if err != nil {
panic(err) panic(err)
} }
fmt.Println(result) // Result will vary due to parallel execution fmt.Println(result) // Result will vary due to parallel execution
// With context cancellation // With context cancellation
ctx, cancel := context.WithTimeout(context.Background(), 50*time.Millisecond) ctx, cancel := context.WithTimeout(context.Background(), 50*time.Millisecond)
defer cancel() defer cancel()
_, err = u.ParallelReduce(ctx, nums, 4, func(ctx context.Context, n int, acc int) (int, error) { _, err = u.ParallelReduce(ctx, nums, 4, func(ctx context.Context, n int, acc int) (int, error) {
time.Sleep(100 * time.Millisecond) time.Sleep(100 * time.Millisecond)
return n + acc, nil return n + acc, nil
}, 0) }, 0)
if err != nil { if err != nil {
fmt.Println("Operation was cancelled:", err) fmt.Println("Operation was cancelled:", err)
} }
} }
``` ```

View file

@ -9,35 +9,35 @@ date: 2025-01-16T00:00:00-00:00
package main package main
import ( import (
"fmt" "fmt"
u "github.com/rjNemo/underscore" u "github.com/rjNemo/underscore"
) )
func main() { func main() {
// Basic usage // Basic usage
fmt.Println(u.Replicate(3, "hello")) fmt.Println(u.Replicate(3, "hello"))
// ["hello", "hello", "hello"] // ["hello", "hello", "hello"]
// Numbers // Numbers
fmt.Println(u.Replicate(5, 0)) fmt.Println(u.Replicate(5, 0))
// [0, 0, 0, 0, 0] // [0, 0, 0, 0, 0]
// Zero count // Zero count
fmt.Println(u.Replicate(0, 42)) fmt.Println(u.Replicate(0, 42))
// [] // []
// Negative count // Negative count
fmt.Println(u.Replicate(-5, "x")) fmt.Println(u.Replicate(-5, "x"))
// [] // []
// Use case: initialize with default values // Use case: initialize with default values
defaultScores := u.Replicate(10, 100) defaultScores := u.Replicate(10, 100)
fmt.Println(defaultScores) fmt.Println(defaultScores)
// [100, 100, 100, 100, 100, 100, 100, 100, 100, 100] // [100, 100, 100, 100, 100, 100, 100, 100, 100, 100]
// Use case: creating separators // Use case: creating separators
separator := u.Replicate(40, "-") separator := u.Replicate(40, "-")
fmt.Println(u.Reduce(separator, func(s, acc string) string { return acc + s }, "")) fmt.Println(u.Reduce(separator, func(s, acc string) string { return acc + s }, ""))
// ---------------------------------------- // ----------------------------------------
} }
``` ```

View file

@ -9,29 +9,29 @@ date: 2025-01-16T00:00:00-00:00
package main package main
import ( import (
"fmt" "fmt"
u "github.com/rjNemo/underscore" u "github.com/rjNemo/underscore"
) )
func main() { func main() {
// Running sum // Running sum
nums := []int{1, 2, 3, 4} nums := []int{1, 2, 3, 4}
add := func(acc, n int) int { return acc + n } add := func(acc, n int) int { return acc + n }
fmt.Println(u.Scan(nums, 0, add)) // [1, 3, 6, 10] fmt.Println(u.Scan(nums, 0, add)) // [1, 3, 6, 10]
// Running maximum // Running maximum
values := []int{3, 1, 4, 1, 5, 9, 2} values := []int{3, 1, 4, 1, 5, 9, 2}
max := func(acc, n int) int { max := func(acc, n int) int {
if n > acc { if n > acc {
return n return n
} }
return acc return acc
} }
fmt.Println(u.Scan(values, 0, max)) // [3, 3, 4, 4, 5, 9, 9] fmt.Println(u.Scan(values, 0, max)) // [3, 3, 4, 4, 5, 9, 9]
// String concatenation // String concatenation
words := []string{"hello", "world", "!"} words := []string{"hello", "world", "!"}
concat := func(acc, s string) string { return acc + s } concat := func(acc, s string) string { return acc + s }
fmt.Println(u.Scan(words, "", concat)) // ["hello", "helloworld", "helloworld!"] fmt.Println(u.Scan(words, "", concat)) // ["hello", "helloworld", "helloworld!"]
} }
``` ```

View file

@ -9,17 +9,17 @@ date: 2025-01-16T00:00:00-00:00
package main package main
import ( import (
"fmt" "fmt"
u "github.com/rjNemo/underscore" u "github.com/rjNemo/underscore"
) )
func main() { func main() {
nums := []int{1, 2, 3, 4, 5, 6, 7, 8, 9} nums := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
lessThan5 := func(n int) bool { return n < 5 } lessThan5 := func(n int) bool { return n < 5 }
fmt.Println(u.TakeWhile(nums, lessThan5)) // [1, 2, 3, 4] fmt.Println(u.TakeWhile(nums, lessThan5)) // [1, 2, 3, 4]
words := []string{"apple", "banana", "cherry", "date"} words := []string{"apple", "banana", "cherry", "date"}
shortWords := func(s string) bool { return len(s) < 6 } shortWords := func(s string) bool { return len(s) < 6 }
fmt.Println(u.TakeWhile(words, shortWords)) // ["apple"] fmt.Println(u.TakeWhile(words, shortWords)) // ["apple"]
} }
``` ```

View file

@ -9,39 +9,39 @@ date: 2025-01-16T00:00:00-00:00
package main package main
import ( import (
"fmt" "fmt"
u "github.com/rjNemo/underscore" u "github.com/rjNemo/underscore"
) )
func main() { func main() {
// Debugging a pipeline // Debugging a pipeline
nums := []int{1, 2, 3, 4, 5} nums := []int{1, 2, 3, 4, 5}
result := u.Tap( result := u.Tap(
u.Map( u.Map(
u.Filter(nums, func(n int) bool { return n%2 == 0 }), u.Filter(nums, func(n int) bool { return n%2 == 0 }),
func(n int) int { return n * 2 }, func(n int) int { return n * 2 },
), ),
func(n int) { func(n int) {
fmt.Printf("Debug: %d\n", n) // Prints each value fmt.Printf("Debug: %d\n", n) // Prints each value
}, },
) )
fmt.Println(result) // [4, 8] fmt.Println(result) // [4, 8]
// Counting elements that pass through // Counting elements that pass through
count := 0 count := 0
filtered := u.Tap( filtered := u.Tap(
u.Filter(nums, func(n int) bool { return n > 2 }), u.Filter(nums, func(n int) bool { return n > 2 }),
func(n int) { count++ }, func(n int) { count++ },
) )
fmt.Printf("Found %d elements: %v\n", count, filtered) fmt.Printf("Found %d elements: %v\n", count, filtered)
// Found 3 elements: [3 4 5] // Found 3 elements: [3 4 5]
// Logging transformations // Logging transformations
data := []string{"hello", "world"} data := []string{"hello", "world"}
u.Tap(data, func(s string) { u.Tap(data, func(s string) {
fmt.Printf("Processing: %s\n", s) fmt.Printf("Processing: %s\n", s)
}) })
} }
``` ```

View file

@ -9,37 +9,37 @@ date: 2025-01-16T00:00:00-00:00
package main package main
import ( import (
"fmt" "fmt"
u "github.com/rjNemo/underscore" u "github.com/rjNemo/underscore"
) )
func main() { func main() {
// 2x3 matrix becomes 3x2 matrix // 2x3 matrix becomes 3x2 matrix
matrix := [][]int{ matrix := [][]int{
{1, 2, 3}, {1, 2, 3},
{4, 5, 6}, {4, 5, 6},
} }
transposed := u.Transpose(matrix) transposed := u.Transpose(matrix)
fmt.Println(transposed) fmt.Println(transposed)
// [[1, 4], [2, 5], [3, 6]] // [[1, 4], [2, 5], [3, 6]]
// Square matrix // Square matrix
square := [][]int{ square := [][]int{
{1, 2}, {1, 2},
{3, 4}, {3, 4},
} }
fmt.Println(u.Transpose(square)) fmt.Println(u.Transpose(square))
// [[1, 3], [2, 4]] // [[1, 3], [2, 4]]
// Use case: converting rows to columns for processing // Use case: converting rows to columns for processing
data := [][]string{ data := [][]string{
{"Name", "Age", "City"}, {"Name", "Age", "City"},
{"Alice", "30", "NYC"}, {"Alice", "30", "NYC"},
{"Bob", "25", "LA"}, {"Bob", "25", "LA"},
} }
byColumn := u.Transpose(data) byColumn := u.Transpose(data)
fmt.Println("Names:", byColumn[0]) // [Name Alice Bob] fmt.Println("Names:", byColumn[0]) // [Name Alice Bob]
fmt.Println("Ages:", byColumn[1]) // [Age 30 25] fmt.Println("Ages:", byColumn[1]) // [Age 30 25]
fmt.Println("Cities:", byColumn[2]) // [City NYC LA] fmt.Println("Cities:", byColumn[2]) // [City NYC LA]
} }
``` ```

View file

@ -9,35 +9,35 @@ date: 2025-01-16T00:00:00-00:00
package main package main
import ( import (
"fmt" "fmt"
u "github.com/rjNemo/underscore" u "github.com/rjNemo/underscore"
) )
func main() { func main() {
// Basic usage // Basic usage
pairs := []u.Tuple[int, string]{ pairs := []u.Tuple[int, string]{
{Left: 1, Right: "a"}, {Left: 1, Right: "a"},
{Left: 2, Right: "b"}, {Left: 2, Right: "b"},
{Left: 3, Right: "c"}, {Left: 3, Right: "c"},
} }
nums, letters := u.Unzip(pairs) nums, letters := u.Unzip(pairs)
fmt.Println(nums) // [1, 2, 3] fmt.Println(nums) // [1, 2, 3]
fmt.Println(letters) // ["a", "b", "c"] fmt.Println(letters) // ["a", "b", "c"]
// Use case: separating keys and values // Use case: separating keys and values
keyValuePairs := []u.Tuple[string, int]{ keyValuePairs := []u.Tuple[string, int]{
{Left: "apple", Right: 5}, {Left: "apple", Right: 5},
{Left: "banana", Right: 3}, {Left: "banana", Right: 3},
{Left: "cherry", Right: 8}, {Left: "cherry", Right: 8},
} }
items, counts := u.Unzip(keyValuePairs) items, counts := u.Unzip(keyValuePairs)
fmt.Println("Items:", items) // Items: [apple banana cherry] fmt.Println("Items:", items) // Items: [apple banana cherry]
fmt.Println("Counts:", counts) // Counts: [5 3 8] fmt.Println("Counts:", counts) // Counts: [5 3 8]
// Empty slice // Empty slice
emptyNums, emptyStrs := u.Unzip([]u.Tuple[int, string]{}) emptyNums, emptyStrs := u.Unzip([]u.Tuple[int, string]{})
fmt.Println(emptyNums, emptyStrs) // [] [] fmt.Println(emptyNums, emptyStrs) // [] []
} }
``` ```