5 ms·
I had no clue this was about async functions. I assumed it was safe/unsafe functions until I got to the part about it not being. I think that is a much stronger
by malfist 12y ago
I had no clue this was about async functions. I assumed it was safe/unsafe functions until I got to the part about it not being. I think that is a much stronger issue than sync/async.
- kazagistar 12y agoI was convinced it was going to be about pure vs impure (monadic) code, but then he just picked out one particular monad instance (coroutines/asynchronous operations). Any time you have side effects, you potentially have "red" code, in that it can add arbitrary restrictions on how you must use the functions.
- lmm 12y agoThese kind of distinctions happen all the time. The classic http://www.joelonsoftware.com/articles/Wrong.html http://www.joelonsoftware.com/articles/Wrong.html - one colour for html-encoded strings, one colour for plain strings. Functions that might fail with an error or functions that never fail. Logging versus non-logging. Database-accessing or not. Callable from user scripts or not. Keeping track of colour - in a way where correctness is guaranteed by the computer - is such a useful general feature that any serious modern programming language should support it. We should have easy, simple syntax for specifying colour, and should make polychromatic functions almost as easy as monochromatic ones. When you do that - when the red of "async" is just one colour among a whole rainbow that your program is already tracking - then the cost of making an explicit distinction between async and not is minimal, and the benefits - being able to track, control, and see instantly whether a function is async or not - are more than worth it.
- tel 12y agoI'm not sure if you're leading this or not, but to be clear... this is exactly a type system. (Edit: read your blog; it's clear you're leading it. Poe's Law is in effect sometimes here, sorry 'bout that!)
- JoshTriplett 12y agoIt's a good type system. Many programming languages don't support this kind of type information, notably C.
- tel 12y agoI'm always curious how far a sufficiently motivated masochist could go with C... I guess it's just C++ ;)
- lmm 12y agoYou can write very safe code by using structs (even 1-element structs) for everything. But there's no generics system and very little in the way of safe tools for making one; writing a safe "generics runtime" and macros to use it puts you halfway to writing a new language.
- proveanegative 12y ago>structs (even 1-element structs) for everything. Are there any large C projects written in this style?
- lmm 12y agoAll I'm aware of is a friend's private project of around 20KLOC.
- dllthomas 12y agoI don't recall the LOC, but I used this style at a recent position. Basically, the idea is not to use bare primitive types anywhere - instead wrapping them in something semantic. Probably the two biggest wins from this approach were distinguishing types of indexes and (in the particular project) distinguishing price from quantity. It does add a bit of boilerplate. For the indexes in particular, foo_lookup(foo, idx) is substantially safer than foo[idx.value] - but then you've gotta write the lookup functions (which may just be a macro but is still a bit of cruft). Locally, if using var.value everywhere in math is getting ugly, you can of course pull things out into temporary primitive variables - enforcing things at the boundaries between functions provides almost all of the benefit.
- deleted 12y ago[deleted]
- lmkg 12y agoI guess more generally, it's about effects. The same rant could apply to any particular effect, because they share the property of being infectious: async, unsafe (in C#, not Rust), throws (checked exceptions), IO, etc. My question is: In a language that has a first-class effect system, does the red/blue problem disappear? Does being able to generalize over effect allow you to avoid cutting the world in half, and allow you to compose effects easier?
- malka 12y agoAt first, it reminded me about const-correctness in c++.
- tel 12y agoAbsolutely, yes. For instance, here is an abstraction of code which reads and writes class Monad m => MonadTeletype m where writeLn :: String -> m () readLn :: m String Here is one which receives the current time class Monad m => MonadNow m where now :: m UTCTime And here is code which transparently combines them echoTime :: (MonadNow m, MonadTeletype m) => m () echoTime = do line <- readLn t0 <- now writeLine (show t0 ++ ": " ++ line) You then, when actually executing echoTime, have to create a monadic implementation which you prove to instantiate both MonadTeletype and MonadNow. For instance, we can always show that `echoTime` can be satisfied by the Haskell "sin bin" type, IO: instance MonadTeletype IO where writeLn = putStrLn readLn = getLine instance MonadTeletype IO where now = getCurrentTime That said, it's easy to write monadic languages like MonadTeletype and MonadNow which aren't trivially satisfied by IO. This occurs when you've imputed new meaning and language into your monad, which is really cool. IO is the "sum of all evils", but it's not terrifically expressive.
- pron 12y agoExcept that's not an effect systems because you only have one real effect - the IO type. The challenge of effect systems is to describe effects and how they interact. For example, you'll have an effect that says "a lock is obtained" and one that says "a lock is released", and if you call them both, in the right order, in the same function, then that function has an effect of "mutating something under lock".