Live data from Hacker News

What Color Is Your Function?

journal.stuffwithstuff.com

81–90 of 153 posts

Re: What Color Is Your Function?

#81
post #76
post #73

Earlier quoted context omitted.

Effect Typing and Monads are yet another colour for the lipstick you put on the pig. You still have non-composability (i.e. the async monad spreads through your code), you still have the complexity, you still don't have proper tracebacks without special runtime support, and you still have the inefficiency that Bob didn't actually mention (unwinding all those stacks all the time). Languages with threads (Java, C#) don…

Go seems to have solved the IO problem, but what about the general asynchronous issue? How do you handle calling a function several thousand times on dozens of threads and combine the results?

Is there any reason you couldn't just spin up so goroutines to do this?

Re: What Color Is Your Function?

#82
post #21

I don't get it ... But hey, it took about six month for me to figure out how to write asynchronous JavaScript ... The key is to not use anonymous functions, it will flatten out the "Christmas tree" of callbacks. And it makes it possible to read what the code does, or at least what the programmer wants the code to do. It's much better then "then", then what, but, then, why complicate things when it's actually possible…

It helps syntactically but does nothing about the main problem: composability. Each of your functions has to know which function to call next, instead of just having one function that invokes n other functions in order. That's what next() is meant for.

Re: What Color Is Your Function?

#83

Earlier quoted context omitted.

Thank you! I know the reader's time is precious so I try to cram as much entertainment and information in there as I can.

Spidermouth the Night Clown will stay with me for years.

At some point, the phrase "Night Clown" popped into my head and it's so deliciously evocative I've had it stuck rattling around in there since then.

Re: What Color Is Your Function?

#84
post #76
post #73

Earlier quoted context omitted.

Effect Typing and Monads are yet another colour for the lipstick you put on the pig. You still have non-composability (i.e. the async monad spreads through your code), you still have the complexity, you still don't have proper tracebacks without special runtime support, and you still have the inefficiency that Bob didn't actually mention (unwinding all those stacks all the time). Languages with threads (Java, C#) don…

Go seems to have solved the IO problem, but what about the general asynchronous issue? How do you handle calling a function several thousand times on dozens of threads and combine the results?

How does Go solve "the IO problem"? (Probably what I want to ask is: which IO problem does Go solve? It can't be the one about purity and side-effects, and if it doesn't solve that...)

Re: What Color Is Your Function?

#85
post #34

His solutions is threads ? Really? Has he read no history? There are problems with threads. That's why async I/O is hot right now. Threads is a limited resource. Threads are expensive to create and dispose. Context switches are espensive. Threads must be synchronized. Threads can have race conditions. Good rant, but I didn't expect him to serve such a shallow conclusion after a solid and insightful introduction.

His solution isn't raw OS-level threads. Thread semantics are the solution. It could be greenthreads that all run within the same OS-level thread. Basically, when a function A calls function B, if function B blocks it blocks function A as well. The entire stack blocks on whatever it going on the top frame. I've wondered that myself. node-fibers basically does this, but for some reason it's pretty hated in the JS worl…

I really don't understand this point of the article: I hated the fact that in Java any call might block. To me, this isn't some better abstraction, this is like a language being impure by default: any function can make changes to global state. So actually I preferred seeing the color of the functions - it made the program much more understandable and "safer".

Re: What Color Is Your Function?

#86
post #73
post #10

We can massively generalize this by calling "blue" "pure" and "red" "impure". The end result is essentially Haskell (but you can take it much further, too!). --- There's something horrifyingly restrictive about having merely (blue -> pure, red -> impure), though. All "blue" functions behave roughly the same (e.g., very, very nicely and compositionally) but "red" functions come in many classes: async, stateful, except…

Effect Typing and Monads are yet another colour for the lipstick you put on the pig. You still have non-composability (i.e. the async monad spreads through your code), you still have the complexity, you still don't have proper tracebacks without special runtime support, and you still have the inefficiency that Bob didn't actually mention (unwinding all those stacks all the time). Languages with threads (Java, C#) don…

This assumes that the primary problem is merely asynchronous code. If that's the main problem you're facing then there's no reason in the world to believe that having more distinction at no gain is the right tradeoff.

I'm not claiming that you must program in a language which distinguishes lipstick colors. I'm merely claiming that you can and that it's a valuable tool.

To respond to your concrete criticisms:

The non-composability you refer to is actually what I call composability itself. You want the isolation of effectful worlds so that you have different things to choose to compose in the first place. You can do this "horizontally" with binding or "vertically" with free products or lifting (or any number of other techniques). Without this distinction things "compose automatically", but only because you've decided to mix all of your colors and go with brown.

Proper tracebacks and stack unwinding can be a problem, but fundamentally these are problems of how you compile/interpret languages like this instead of semantically whether these languages allow you to express what you would like to at high fidelity. Both of those problems can be addressed, though. The degree to which they're painful in practice is also a question.

The comment about threads is somewhat off topic. There's nothing in what I was saying which precludes the introduction of nice green threads and competitive scheduling. You can implement Go in Haskell quite neatly, for instance.

But yes, I agree. If your problem is pure multithreading then languages like Go and Erlang make it go away completely. They do so by collapsing layers of semantics down to a single one (completely antithetical to the red/blue distinction here) but choosing one such that multithreading is nice.

This can be an excellent spot in solution space for many problems. I would never suggest otherwise.

But as long as we're ostensibly on the topic of "blue/red"-ness of your language then it's high time to talk about effect typing.

Re: What Color Is Your Function?

#87
It seems like a lot of people are interested in fixing this, and would be keen to see a solution. I believe StratifiedJS is precisely that solution (for JS at least), and it has existed in working form for years: http://stratifiedjs.org/ (it's not just an experiment - it's remarkably stable).

StratidiedJS completely eliminates the sync/async distinction at the syntax level, with the compiler/runtime managing continuations automatically. A `map` function in SJS works just like you would want, regardless of whether the mapping function is synchronous or not.

In addition, it provides _structured_ forms of concurrency at the language level, as well as cancellation (which most async APIs don't support).

Disclosure: I work on StratifiedJS, and just wish more people knew about it.

Re: What Color Is Your Function?

#88
post #35

Earlier quoted context omitted.

> Effects are the most important -- and most bug prone -- of any interesting software aside from compilers, and monads take this central element and make it un-composable. Can you elaborate on this? Because, AFAICT, the big selling point for monads for dealing with effects is precisely composability.

I think the point is that there is no good effect-union type; this has to be pieced together with monad transformers where you might have that types "Atransformer (Btransformer C)" is not equal to "Btransformer (Atransformer C)". This is, for example, why Haskell has one monolithic "IO" monad instead of one for hitting the filesystem, one for HTTP requests, one for IORefs, etc. Haskell does not, for example, represen…

I'm kind of interested in knowing why you don't think that there isn't an isomorphism along the ordering of the monad transformers. Wouldn't it just be a question of rebuilding combinators so that they're targetting the right depth? Or am I missing something

Re: What Color Is Your Function?

#89
post #57

You can always make a function that sync all async operations: sleep until a global variable is changed by the callback. A pain, but still not that bad.

Yes, I've used a similar technique myself; however I consider it only a last resort. But doesn't that require your language to have threads? Is it possible to do this in eg. Javascript?

For node.js, there is a module: https://www.npmjs.com/package/deasync

Re: What Color Is Your Function?

#90
I'm really out on most of the "async" stuff, after having used it. (Mostly in Node and Tornado)

Remember in the early 90s when Windows and Mac OS were "cooperatively" multitasked? Which is to say, you had to explicitly yield to allow other applications to run (or risk locking up the entire system). And then it was replaced with pre-emptive multitasking, which allowed the scheduler to figure out what process deserved CPU time, while allowing the programmer not to have to think about it. You could call a blocking IO function, and the OS would just go do something else while you waited.

All this "async" stuff seems like a return of cooperative multitasking, only worse. Not only do I have to explicitly yield, but now it's to some event loop that can't even properly use multiple cores, or keep a coherent stack trace. It's a nightmare to debug. It's theoretically fast... except if one request forgets to yield, it can clog up the entire thing. I guess you use multiple processes for that and a dispatcher, but at that point you've basically reinvented preemptive multitasking... badly.

Threads aren't perfect, but excluding STM and actor models they definitely suck the least.

Post reply on HN