Hacker News new | ask | show | jobs
by valenterry 1331 days ago
> I/O usually means syscalls, I guess. If I install a library to encode and decode a protocol and it has no mode of operation that performs 0 syscalls, it is defective.

I agree, but that wasn't really the point that I was trying to make. Even without IO, there can still be different interfaces, such as specific interfaces for errors, attaching meta information like tracing, logging etc.

I don't know how ZIG solves that, but in Java this is a PITA because the language isn't capable enough - so everyone falls back to global runtime configurations, e.g. some file being somewhere that configures it. It doesn't compose and is super hard to debug. And that's just an example.

> I'm not sure how "write does not even return until the writing is done" can avoid handling backpressure.

That doesn't matter. The point is that you are using the reader/writer interface. So if you want to plug this library into another library that works with different interfaces then you now have to convert stuff around by hand all the time.

You could say that everyone should just use "standard" interfaces, but often they don't exist or lack certain properties or it's simply hard to standardize everything. Think about how many libraries for dates/times there are in Java or python.

EDIT: I can see that it might be a bit hard to wrap your head around what I mean because as developers (including myself) we learn to do plumbing all the time and it feels like you just have to do it in almost any language I always used.

1 comments

What sorts of features do you mean? I explained how I would achieve the desired thing. It's been a good decade since I used Scala.
Sorry, I'm not sure what you are asking me to explain - I didn't use the term features at all. Can you elaborate?
What features of Scala allow the claimed things that are missing from other languages? Can you provide an example?
It's the typeclasses that allow orphan instances.

For instance, let's say a library uses this interfaces:

    def doSomething[F[_]: Monad](param: F[Param]): F[Result] = ...
This allows to provide the effect on the callsite. This could simply by "Id (which means regulary executed code) or it could be async, an error type, something with logging or a combination of all those and more at the same type. The library doesn't know and doesn't care, it only constraints the interface if it needs to.
More precisely, since the concept of typeclasses is modeled in Scala using values, it is a bit more powerful and expressive (but also harder to use correctly) than for example Haskells counterpart.

And to add more: typeclasses are usually not enough here, you also need higher kinded types or the whole thing is useless for a lot of meaningful abstractions (such as dealing with errors or async code).