News for hackers. Stuff that matters.
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.
Re:Loopless Programming by kragen on Saturday October 19, 2019 @09:45PM (#21301845)
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.
Re:Loopless Programming by agumonkey on Saturday October 19, 2019 @07:41PM (#21301393)
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.
Re:Loopless Programming by suzuki on Monday October 21, 2019 @09:09AM (#21311820)
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!
Re:Loopless Programming by jadbox on Tuesday October 22, 2019 @11:26AM (#21324712)
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.)
Re:Loopless Programming by suzuki on Thursday October 24, 2019 @09:44AM (#21344596)
Good point! I'm looking forward to generics in Go.
Re:Loopless Programming by jadbox on Tuesday October 22, 2019 @11:24AM (#21324680)
It's my #1 problem with Go, and there's no good solution imho other than Go getting some kind of generic type support.
Re:Loopless Programming by banhfun on Saturday October 19, 2019 @05:37PM (#21300927)
I agree, the only time I write a loop out is when I need to break out of it