News for hackers. Stuff that matters.
Re:The Way of the Gopher: Making the Switch from Node.js to ... by kasey_junk on Sunday March 27, 2016 @10:06AM (#11369978)
He is speaking to the idea that you don't need to care about whether a function blocks or not. It's simply untrue (I'd go further and say if its untrue in all languages but that's a digression).

To have an abstraction where you really don't care about blocking or not you need promises/futures. Go's futures are bad. Real bad.

If you don't want the function to be non-blocking then you are fine with either method signature.

Re:The Way of the Gopher: Making the Switch from Node.js to ... by ashearer on Sunday March 27, 2016 @01:20PM (#11370660)
I took it to mean that with Node, some functions have a traditional return value, like functions in most common languages. But if there's even the possibility that they may indirectly invoke an async function, they need to have a different signature using callbacks or promises. For example, here's a simple function:

  function isValidFoo(val) {
      ...return boolean
  }
This function is synchronous now, but its contract needs to change if it internally calls something async (say, it's updated to check a value from a cache, which may trigger a DB lookup). The new signature has to add a callback parameter and drop the return value, or return a promise. Then its callers have to change how they invoke the function, and if they were previously synchronous their signatures have to change as well. Every synchronous function up the call stack needs to care about this internal change.

To avoid a ripple effect, all functions have to be designed to be asynchronous from the beginning, but this increases program complexity significantly. It means avoiding built-in language features such as direct return values, and often means substituting async library functions for built-in looping constructs.

Other languages including Go aren't like that. You don't need to wrap a simple return value in a promise or callback just because retrieving it might someday involve I/O. Execution of the thread/goroutine simply resumes whenever the value is ready, and the function returns normally. In those languages, Node's distinction between sync and async is artificial and unnecessary.

Re:The Way of the Gopher: Making the Switch from Node.js to ... by _ak on Sunday March 27, 2016 @03:54PM (#11371257)
...what? The point is that when any function in Go is blocking, it will obviously block the current flow of your own program until it returns. But it only ever blocks the flow of the current goroutine. Other goroutines will continue running just fine, and the runtime will schedule all the ready-to-run goroutines over the OS threads it has available, and that's nothing you need to take care of in your Go program. It essentially abstracts away what Node.js does in its event loop and the programmer does by manually splitting up the program into a series of function callbacks. Just use that knowledge to structure your program accordingly, and don't tried to badly reinvent futures.
Re:The Way of the Gopher: Making the Switch from Node.js to ... by kasey_junk on Sunday March 27, 2016 @04:22PM (#11371379)
How is that different than any language that supports parallel concurrency?

You can literally say that about every labguafe that has concurrency abstractions.

The whole point of the argument is that golangs abstractions just push the callbacks (or blocking sync) to the application layer.

Re:The Way of the Gopher: Making the Switch from Node.js to ... by tptacek on Sunday March 27, 2016 @12:57PM (#11370572)
I think I follow. But why do I want general-purpose functions to ever be non-blocking in Go?

To me, idiomatic Go suggests that libraries, data structures, business logic, &c is encapsulated in blocking functions, and that concurrency is expressed in glue code.

Re:The Way of the Gopher: Making the Switch from Node.js to ... by kasey_junk on Sunday March 27, 2016 @03:45PM (#11371208)
That doesn't seem to be the argument to me (though I'm totally ignorant about the Node aspect of this).

The argument to me is that Go advertises itself as being easy to write that concurrent glue code & then fails to provide basic abstractions around it.

Everything you mention about things being expressed in glue code would be easier if Golang provided a modern promises library & holds just as reasonably for other modern languages that do.

The "node requires callback hell" is a red herring because so does Golang (that or blocking code), just it does it at the app layer instead of the framework layer.

Re:The Way of the Gopher: Making the Switch from Node.js to ... by wtbob on Sunday March 27, 2016 @10:08PM (#11372347)
> The argument to me is that Go advertises itself as being easy to write that concurrent glue code & then fails to provide basic abstractions around it.

What‽ It provides channels, which are a really nice abstraction for concurrency.

> Everything you mention about things being expressed in glue code would be easier if Golang provided a modern promises library & holds just as reasonably for other modern languages that do.

Have you actually written any Go? Using channels in Go is much nicer than using callbacks. Callbacks basically force one to write one's code in continuation-passing style, while callbacks let one work about sync points only where you need.

Re:The Way of the Gopher: Making the Switch from Node.js to ... by kasey_junk on Monday March 28, 2016 @08:32AM (#11373834)
> What‽ It provides channels, which are a really nice abstraction for concurrency.

Channels are a concurrent safe queue, nothing more. They are not even particularly well implemented concurrent queues as they are highly contended.

What go provides for abstractions around those queues are range and select. Range is a nice way to make simple concurrency cases look like traditional for loops (and is very rarely used in practice as simple concurrency cases are rare, at least for me).

Select is a nice addition to the language, yet the edge cases around channels make it very difficult to reason about without keeping http://dave.cheney.net/2013/04/30/curious-channels open.

> Have you actually written any Go? Using channels in Go is much nicer than using callbacks.

I have, for 2 years, full time. I have not used node. Have you ever used a language that supports concurrency besides Go? Go does not provide, as part of its concurrency abstractions, things that are deemed bare necessities by other languages such as timeouts, cancellation, supervision, lock free structures, etc.

The entirety of the Golang concurrency story can be wrapped up with 3 things a) the culture of the language prefers message passing concurrency b) the scheduler is a very good example of when simplicity gets you great performance in the main cases c) select as a language keyword is interesting.

By leaving the basics out you push all of that work to the application level, which is why I think the callbacks argument is a red herring. At the application level you are either going to encounter callbacks (as in the stdlib http handler) or blocking code (subject to races, deadlocks, etc).

Re:The Way of the Gopher: Making the Switch from Node.js to ... by Lukasa on Sunday March 27, 2016 @03:07PM (#11371064)
You wouldn't.

What I was respond to was this specific sentiment: "With Go it doesn't matter if an operation is blocking or non blocking, that fact can totally be abstracted from the client code." My argument was that that is simply not true. Client code must know the difference between blocking and non-blocking code because it affects the flow of information around the program.

Re:The Way of the Gopher: Making the Switch from Node.js to ... by adrusi on Sunday March 27, 2016 @10:43AM (#11370082)
I haven't looked too deeply into Haskell's io model, but it think it might offer an exception to your "untrue in all languages" claim.
Re:The Way of the Gopher: Making the Switch from Node.js to ... by fooster on Sunday March 27, 2016 @11:18AM (#11370218)
> To have an abstraction where you really don't care about blocking or not you need promises/futures. Go's futures are bad. Real bad.

Please explain.

Re:The Way of the Gopher: Making the Switch from Node.js to ... by kasey_junk on Monday March 28, 2016 @08:35AM (#11373856)
Well it's possible I over stated the necessity for futures as their might be other abstractions that allow you to compose concurrent/non-concurrent systems in a way that is transparent to the api. Its just one of the easier ones to reason about. That said, I don't believe concurrency should be transparent to the api, rather it should be front and center to it.

As for the go futures being bad, channels generally are a bad concurrent queue (contended, lack basic abstractions, etc) and using a single item queue as a future isn't in and of itself bad, but does mean you can't optimize for different usages that futures might have over message passing queues.