Felix Schlitter [5:30 PM]
@natefaubion I got a basic makeAff
going in pure-c:
testAff = void $ launchAff do
msg <- makeAff \cb -> do
cb (Right "Hello from Aff")
pure (unsafeCoerce unit)
liftEffect $ Console.log msg
i need to figure out how to do error handling next though as there’s no such thing as exceptions. I wonder if this will lead into Aff e a
chexxor [5:51 PM]
I think the error channel is Aff refers to the JS errorback-callback error channel
i.e. function someAsyncFn (arg1, arg2, cbFn, ebFn)
Felix Schlitter [5:52 PM]
yes, but in C there’s no exceptions at all, so all “errors” are essentially just values
usually indicated based on status codes
chexxor [5:52 PM]
No Exception
type, you mean?
Felix Schlitter [5:53 PM]
yeah, no way to blow up like that
someone mentioned long jumps that could mimic that, but heck why bother. the simplicity of status codes is kind of beautiful
chexxor [5:54 PM]
Could just copy the JS type, something like { message :: String, name :: String }
status code is like 1
for success?
Felix Schlitter [5:55 PM]
usually it’s like negative = error, 0 = success, positive = may or may not have meaning
chexxor [5:56 PM]
ah, cool.
Felix Schlitter [5:56 PM]
and you’d have functions like strerr to go from some int to some message, so no need to carry that object around
chexxor [5:57 PM]
Yeah, but would be nice to “catch SomeError” rather than “catch -5”
idk what I’m talking about though.
Felix Schlitter [5:58 PM]
yeah of course
still working through it though, Aff Int _
would be superuseless
for example, in libuv often u might get EAGAIN or sth, but only makes sense in the context of the function that tried to run
if you have a big Aff computation and it just comes back with EAGAIN that would be pretty useless
natefaubion [6:26 PM]
Aff just has a custom error channel. It just propagates values, but fixes the error channel to Error
.
It uses Error
for both exceptions and interruption
Felix Schlitter [6:28 PM]
but it seems like it only has to because exceptions are lingering in every function call
what i mean is that the Throw
and Catch
constructors don’t need Error
at all
natefaubion [6:30 PM]
You don’t have to add it, but if you support cancellation/termination and bracket, you’ll have to deal with it anyway
Felix Schlitter [6:31 PM]
i’ll need to see where it leads me. it’s not that i choose not to throw, it’s just not a thing in C
natefaubion [6:31 PM]
Right, but I’m saying throwing in Aff is not throwing in JS
Aff handles it’s own “exception” propagation
Felix Schlitter [6:31 PM]
yup
natefaubion [6:31 PM]
Aff will wrap Effect
calls with a try/catch, but that’s about it
Felix Schlitter [6:32 PM]
yes that’s what i linked to above. because there’s no try/catch in C, there’s no way for Error
to enter the game
natefaubion [6:33 PM]
Yes, it’s only if you want to model exceptions
You don’t have to add it
Felix Schlitter [6:33 PM]
it’d be nice if it was possible, if run_sync
returned some Either e a
instead
natefaubion [6:33 PM]
I’m just saying that, if you have cancellation and bracket, you’ll have to implement all the machinery anyway
Felix Schlitter [6:34 PM]
oh yes, i just haven’t gotten to it
i was wondering, by the way, why the scheduler exists. is it a performance optimization?
natefaubion [6:53 PM]
@Felix Schlitter it ensures fairness of async execution
it’s not strictly necessary
but it does mean that an async boundary always yields to other fibers
Felix Schlitter [6:54 PM]
i see, i’ll re-read the code with that in mind
i saw that join
does not enqueue but just calls run
directly
natefaubion [6:54 PM]
basically, whenever an async action resolves, it puts it in the scheduler (edited)
otherwise you can get into the situation where a single fiber starves the CPU
if it says its async and still resolves synchronously
you are using uv though, so it’s not the same
Felix Schlitter [6:56 PM]
same as node.js though
sorry, we use purescript for work a lot for node.js (and react-native), i forget it’s also used in the browser
natefaubion [6:59 PM]
JS on node is still all single threaded, so the scheduler is useful there as well
I think the biggest place it comes up is AVar
but like I said, it’s not critical, just has some nicer properties for the system as a whole
Felix Schlitter [7:07 PM]
what i don’t understand though is that it seems like it’s doing everything synchronous, for example: https://github.com/slamdata/purescript-aff/blob/master/src/Effect/Aff.js#L112-L123 - there should be no way on earth that any code can run while it’s executing the while
loop, for example
ooooh, unless in a thunk
?
natefaubion [7:09 PM]
thunk()
ends up being a callback that evaluates that fiber up until the next async boundary
it only pertains to Async
Felix Schlitter [7:11 PM]
yeah makes sense. tell me, how did you conceive aff???
natefaubion [7:12 PM]
jdegoes was working on the beginnings of ZIO at the time and we hashed out parts of the API
then it was just about making it fast, I guess
ZIO and Aff share similar APIs and concepts (edited)
stack-safety is a big part of what makes it complex
ParAff is like half the src, and if it didn’t need to be stack safe, it could be implemented in a very small fraction of the code
To me, lack of stack-safety is a showstopper
Felix Schlitter [7:26 PM]
yeah, agreed