Hacker News new | past | comments | ask | show | jobs | submit login

Fair point on PFP.

> I'm not entirely sure what you mean by "this usage" (lists?) [...]

By "this usage", I meant containers, generally. Maybe algebraic data types would be more specific.

> [...] blocking actors like Erlang's (or our own Quasar) make great use of (lightweight) threads [...]

Have you been following the Reactive Manifesto [1] and reactive streams [2]? If so, do you have any thoughts on whether this it builds out design practice in a complementary way to your suggestion here, or is it divergent?

> Using them to create lightweight threads solves almost all of the problems with the monadic style, [...]

My concern here would be whether you'd then be recreating the old problem you mentioned of having many implicitly monadic constructs in imperative programming but no good way of adding your own. In the analogous case in PFP, even if the continuation monad is the mother of all monads (and I haven't finished reading that post you linked to), I'd have to imagine it wouldn't be a whole lot of fun to use it exclusively. Or else people would do it!

> Where does Java's verbosity bother you here?

I probably should have withheld comment on Java's verbosity. There's probably nothing wrong with it. I think I'm just used to Scala and dynamically typed languages.

Anyway, awesome work. You make a lot of great points.

[1] http://www.reactivemanifesto.org/

[2] http://www.reactive-streams.org/




> Have you been following the Reactive Manifesto [1] and reactive streams [2]? If so, do you have any thoughts on whether this it builds out design practice in a complementary way to your suggestion here, or is it divergent?

Reactive streams' design is the dual to threads/fibers/continuations, and I believe that as a user facing construct it is the wrong one (I'll get to that in a minute), but, as Java does not yet have a standard, built-in implementation of continuations/fibers, Reactive Streams is meant as an interoperability standard and does a very good job at that. I like that it exists and I like the spec, which is why Quasar is also RS compliant (turning every stream to a channel and vice-versa).

I don't like the reactive manifesto, though. It conflates some well-known design practices -- which we simply used to call "robust soft-realtime" -- with a specific implementation (nonblocking), and in the process, overloads a term, "reactive programming", which has a very different meaning (dataflow, i.e. spreadsheet style). Even Erlang, the inspiration to the manifesto, doesn't conform to it (because it discusses implementation). Also, I'm not too fond of manifestos in general.

As to push-based streams, I didn't have time to get into that in the talk (the slide is there, though), but I believe that in imperative languages a pull-based API (like channels) is always superior to a push API for several reasons:

* It is more general -- both are duals, but going from pull to push only requires a while loop. Going the other way requires adding a queue.

* It conveys more information to the developer -- in the push approach, the concurrency is clear: the item is received on the same thread that calls `receive` (the only thing you need is maybe just a tag saying if `receive` itself is thread-safe or not). With a push API, the developer needs to read the documentation to figure out whether the callback can be called on multiple threads concurrently, and, if not, whether it's always called on the same thread.

* It conveys more information to the library -- a pull API has implicit, automatic backpressure. Calling `receive` means we're ready to receive more. With a push API you either don't have backpressure, or, like with reactive streams, you need explicit backpressure (`request`) along with more documentation on when `request` may be called. Look how much of the RS spec is devoted to specifying exactly that, and how much shorter it would be if it were a pull API (like Go or Quasar channels).

> My concern here would be whether you'd then be recreating the old problem you mentioned of having many implicitly monadic constructs in imperative programming but no good way of adding your own.

Well, yeah, but that's a secondary issue. I'm not a language purist, and you always need to weigh which is better -- a very general abstraction that is then put to use by everyone to create their own incompatible DSLs, or choose the most useful specific abstractions and make sure everyone can read everybody's code, even if not everything now has the most elegant expression. For large projects I think the latter is preferable.




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: