Skip to content

Commit dcb4225

Browse files
committed
reduce: simplify the calcualtion
Hacker news didn't understand why we needed to "prime the pump". Because we don't. https://www.reddit.com/r/golang/comments/peh2m6/a_question_on_rob_pikes_reduce_function/
1 parent 2984852 commit dcb4225

File tree

3 files changed

+22
-19
lines changed

3 files changed

+22
-19
lines changed

go.mod

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module robpike.io/filter
2+
3+
go 1.17

reduce.go

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,25 +24,19 @@ func Reduce(slice, pairFunction, zero interface{}) interface{} {
2424
panic("reduce: not slice")
2525
}
2626
n := in.Len()
27-
switch n {
28-
case 0:
27+
if n == 0 {
2928
return zero
30-
case 1:
31-
return in.Index(0)
3229
}
3330
elemType := in.Type().Elem()
3431
fn := reflect.ValueOf(pairFunction)
3532
if !goodFunc(fn, elemType, elemType, elemType) {
3633
str := elemType.String()
3734
panic("apply: function must be of type func(" + str + ", " + str + ") " + str)
3835
}
39-
// Do the first two by hand to prime the pump.
4036
var ins [2]reflect.Value
41-
ins[0] = in.Index(0)
42-
ins[1] = in.Index(1)
43-
out := fn.Call(ins[:])[0]
44-
// Run from index 2 to the end.
45-
for i := 2; i < n; i++ {
37+
out := in.Index(0) // By convention, fn(zero, in[0]) = in[0].
38+
// Run from index 1 to the end.
39+
for i := 1; i < n; i++ {
4640
ins[0] = out
4741
ins[1] = in.Index(i)
4842
out = fn.Call(ins[:])[0]

reduce_test.go

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,24 @@ func mul(a, b int) int {
1212
return a * b
1313
}
1414

15+
func fac(n int) int {
16+
if n <= 1 {
17+
return 1
18+
}
19+
return n * fac(n-1)
20+
}
21+
1522
func TestReduce(t *testing.T) {
16-
a := make([]int, 10)
23+
const size = 10
24+
a := make([]int, size)
1725
for i := range a {
1826
a[i] = i + 1
1927
}
20-
// Compute 10!
21-
out := Reduce(a, mul, 1).(int)
22-
expect := 1
23-
for i := range a {
24-
expect *= a[i]
25-
}
26-
if expect != out {
27-
t.Fatalf("expected %d got %d", expect, out)
28+
for i := 1; i < 10; i++ {
29+
out := Reduce(a[:i], mul, 1).(int)
30+
expect := fac(i)
31+
if expect != out {
32+
t.Fatalf("expected %d got %d", expect, out)
33+
}
2834
}
2935
}

0 commit comments

Comments
 (0)