Re:Loopless Programming
by jadbox on Saturday October 19, 2019 @05:22PM
(#21300856)
As far as explicit loops, I probably use write out a loop once a month and maybe not even that often. Using map/filter/reduce [as well as sugar funcs until/any/all] solves virtually all the common cases of working with lists. Granting it's not sufficient if you're writing specialized code like sorting arrays efficiently, but for general development, going higher-order is the way to go.
[ Parent
| on HN ]
As the song says:
All I ever wanted
All I ever needed
Is here
In ML
Loops are very
Unnecessary
map will work just as well
But the function you pass to map or filter is called once for every sequence element, and reduce is nothing more than a foreach loop with explicit dataflow. So, although I agree that these are often better than a for loop, they are not the same thing as making the looping implicit.You can say this now but not long ago map/filter/reduce were almost esoteric.
Re:Loopless Programming
by whateveracct on Saturday October 19, 2019 @09:00PM
(#21301688)
I'd say even just 5 years ago they were weird FP features, with LINQ being the most mainstream version. Now Go is the only mainstream language without them hehe.
You can write your own LINQ in Go with a very short program.
See https://github.com/nukata/linq-in-go for example.
Here is a self-contained excerpt:
type Any = interface{}
type Enumerator func(yield func(element Any))
// Select creates an Enumerator which applies f to each of elements.
func (loop Enumerator) Select(f func(Any) Any) Enumerator {
return func(yield func(Any)) {
loop(func(element Any) {
value := f(element)
yield(value)
})
}
}
// Range creates an Enumerator which counts from start
// up to start + count - 1.
func Range(start, count int) Enumerator {
end := start + count
return func(yield func(Any)) {
for i := start; i < end; i++ {
yield(i)
}
}
}
Now you can write the following: squares := Range(1, 10).Select(func(x Any) Any { return x.(int) * x.(int) })
squares(func(num Any) {
Println(num)
})
// Output:
// 1
// 4
// 9
// 16
// 25
// 36
// 49
// 64
// 81
// 100
I'd say it is so elegant in Go!It's a little annoying though to be forced to use interface{} as type parameters for higher order list operations as there's a performance overhead when using it. Hopefully this is remedied when Go gets type generic support.
Re:Loopless Programming
by whateveracct on Tuesday October 22, 2019 @12:08PM
(#21325305)
Not to mention the complete lack of type safety (there are unsafe-style casts even in the example code.)
Good point!
I'm looking forward to generics in Go.
It's my #1 problem with Go, and there's no good solution imho other than Go getting some kind of generic type support.