Skip to content

Commit e7a3992

Browse files
authored
Merge pull request #39 from mgomes/mgomes/v0-9-array-phase2
Expand Array helpers for v0.9.0
2 parents 37bc4fa + c215c03 commit e7a3992

File tree

5 files changed

+1009
-0
lines changed

5 files changed

+1009
-0
lines changed

docs/arrays.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ Common enumerable helpers include:
1212

1313
- `map` to transform elements.
1414
- `select` to filter items.
15+
- `find` / `find_index` to locate the first matching item.
1516
- `reduce` to accumulate values.
1617
- `first(n)` / `last(n)` to slice without mutating.
1718
- `push`/`pop` for building or removing values while keeping the original array untouched.
@@ -32,6 +33,42 @@ def total_by_multiplier(values, multiplier)
3233
end
3334
```
3435

36+
## Search and predicates
37+
38+
- `include?(value)` for membership checks.
39+
- `index(value, offset = 0)` / `rindex(value, offset = last_index)` for positional lookup.
40+
- `count`, `count(value)`, or `count { ... }`.
41+
- `any?`, `all?`, `none?` with optional blocks.
42+
43+
```vibe
44+
def health_checks(values)
45+
{
46+
has_zero: values.include?(0),
47+
first_large_idx: values.index(100),
48+
all_non_negative: values.all? { |v| v >= 0 }
49+
}
50+
end
51+
```
52+
53+
## Ordering and grouping
54+
55+
- `reverse`, `sort`, and `sort_by`.
56+
- `partition` to split into matching and non-matching arrays.
57+
- `group_by` to collect values by key.
58+
- `tally` to count symbol/string occurrences.
59+
60+
```vibe
61+
def summarize(players)
62+
grouped = players.group_by { |p| p[:status] }
63+
counts = players.map { |p| p[:status] }.tally
64+
65+
{
66+
by_status: grouped,
67+
totals: counts
68+
}
69+
end
70+
```
71+
3572
## Set-like Operations
3673

3774
Use `+` to concatenate and `-` to subtract values:

examples/arrays/extras.vibe

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,79 @@ end
3838
def subtract_values(first, second)
3939
first - second
4040
end
41+
42+
def include_value(values, value)
43+
values.include?(value)
44+
end
45+
46+
def first_match(values, threshold)
47+
values.find do |value|
48+
value > threshold
49+
end
50+
end
51+
52+
def first_match_index(values, threshold)
53+
values.find_index do |value|
54+
value > threshold
55+
end
56+
end
57+
58+
def count_value(values, value)
59+
values.count(value)
60+
end
61+
62+
def count_large(values, threshold)
63+
values.count do |value|
64+
value > threshold
65+
end
66+
end
67+
68+
def predicate_snapshot(values)
69+
any_large = values.any? do |value|
70+
value > 10
71+
end
72+
all_positive = values.all? do |value|
73+
value > 0
74+
end
75+
none_negative = values.none? do |value|
76+
value < 0
77+
end
78+
79+
{
80+
any_large: any_large,
81+
all_positive: all_positive,
82+
none_negative: none_negative
83+
}
84+
end
85+
86+
def sort_values(values)
87+
values.sort
88+
end
89+
90+
def sort_desc(values)
91+
values.sort do |a, b|
92+
b - a
93+
end
94+
end
95+
96+
def sort_words_by_length(words)
97+
words.sort_by do |word|
98+
word.length
99+
end
100+
end
101+
102+
def partition_even(values)
103+
values.partition do |value|
104+
value % 2 == 0
105+
end
106+
end
107+
108+
def group_by_status(players)
109+
players.group_by do |player|
110+
player[:status]
111+
end
112+
end
113+
114+
def tally_statuses(statuses)
115+
statuses.tally
116+
end

vibes/examples_test.go

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,151 @@ func TestExamples(t *testing.T) {
346346
},
347347
want: arrayVal(intVal(1), intVal(3)),
348348
},
349+
{
350+
name: "arrays/include_value_true",
351+
file: "arrays/extras.vibe",
352+
function: "include_value",
353+
args: []Value{
354+
arrayVal(intVal(1), intVal(2), intVal(3)),
355+
intVal(2),
356+
},
357+
want: boolVal(true),
358+
},
359+
{
360+
name: "arrays/include_value_false",
361+
file: "arrays/extras.vibe",
362+
function: "include_value",
363+
args: []Value{
364+
arrayVal(intVal(1), intVal(2), intVal(3)),
365+
intVal(9),
366+
},
367+
want: boolVal(false),
368+
},
369+
{
370+
name: "arrays/first_match",
371+
file: "arrays/extras.vibe",
372+
function: "first_match",
373+
args: []Value{
374+
arrayVal(intVal(2), intVal(5), intVal(7)),
375+
intVal(4),
376+
},
377+
want: intVal(5),
378+
},
379+
{
380+
name: "arrays/first_match_index",
381+
file: "arrays/extras.vibe",
382+
function: "first_match_index",
383+
args: []Value{
384+
arrayVal(intVal(2), intVal(5), intVal(7)),
385+
intVal(4),
386+
},
387+
want: intVal(1),
388+
},
389+
{
390+
name: "arrays/count_value",
391+
file: "arrays/extras.vibe",
392+
function: "count_value",
393+
args: []Value{
394+
arrayVal(intVal(1), intVal(2), intVal(1), intVal(3)),
395+
intVal(1),
396+
},
397+
want: intVal(2),
398+
},
399+
{
400+
name: "arrays/count_large",
401+
file: "arrays/extras.vibe",
402+
function: "count_large",
403+
args: []Value{
404+
arrayVal(intVal(1), intVal(5), intVal(6)),
405+
intVal(4),
406+
},
407+
want: intVal(2),
408+
},
409+
{
410+
name: "arrays/predicate_snapshot",
411+
file: "arrays/extras.vibe",
412+
function: "predicate_snapshot",
413+
args: []Value{
414+
arrayVal(intVal(2), intVal(11), intVal(4)),
415+
},
416+
want: hashVal(map[string]Value{
417+
"any_large": boolVal(true),
418+
"all_positive": boolVal(true),
419+
"none_negative": boolVal(true),
420+
}),
421+
},
422+
{
423+
name: "arrays/sort_values",
424+
file: "arrays/extras.vibe",
425+
function: "sort_values",
426+
args: []Value{
427+
arrayVal(intVal(3), intVal(1), intVal(2)),
428+
},
429+
want: arrayVal(intVal(1), intVal(2), intVal(3)),
430+
},
431+
{
432+
name: "arrays/sort_desc",
433+
file: "arrays/extras.vibe",
434+
function: "sort_desc",
435+
args: []Value{
436+
arrayVal(intVal(3), intVal(1), intVal(2)),
437+
},
438+
want: arrayVal(intVal(3), intVal(2), intVal(1)),
439+
},
440+
{
441+
name: "arrays/sort_words_by_length",
442+
file: "arrays/extras.vibe",
443+
function: "sort_words_by_length",
444+
args: []Value{
445+
arrayVal(strVal("bbb"), strVal("a"), strVal("cc")),
446+
},
447+
want: arrayVal(strVal("a"), strVal("cc"), strVal("bbb")),
448+
},
449+
{
450+
name: "arrays/partition_even",
451+
file: "arrays/extras.vibe",
452+
function: "partition_even",
453+
args: []Value{
454+
arrayVal(intVal(1), intVal(2), intVal(3), intVal(4)),
455+
},
456+
want: arrayVal(
457+
arrayVal(intVal(2), intVal(4)),
458+
arrayVal(intVal(1), intVal(3)),
459+
),
460+
},
461+
{
462+
name: "arrays/group_by_status",
463+
file: "arrays/extras.vibe",
464+
function: "group_by_status",
465+
args: []Value{
466+
arrayVal(
467+
hashVal(map[string]Value{"id": strVal("p1"), "status": strVal("active")}),
468+
hashVal(map[string]Value{"id": strVal("p2"), "status": strVal("complete")}),
469+
hashVal(map[string]Value{"id": strVal("p3"), "status": strVal("active")}),
470+
),
471+
},
472+
want: hashVal(map[string]Value{
473+
"active": arrayVal(
474+
hashVal(map[string]Value{"id": strVal("p1"), "status": strVal("active")}),
475+
hashVal(map[string]Value{"id": strVal("p3"), "status": strVal("active")}),
476+
),
477+
"complete": arrayVal(
478+
hashVal(map[string]Value{"id": strVal("p2"), "status": strVal("complete")}),
479+
),
480+
}),
481+
},
482+
{
483+
name: "arrays/tally_statuses",
484+
file: "arrays/extras.vibe",
485+
function: "tally_statuses",
486+
args: []Value{
487+
arrayVal(strVal("active"), strVal("active"), strVal("complete")),
488+
},
489+
want: hashVal(map[string]Value{
490+
"active": intVal(2),
491+
"complete": intVal(1),
492+
}),
493+
},
349494
{
350495
name: "collections/make_player",
351496
file: "collections/hashes.vibe",

0 commit comments

Comments
 (0)