some notes for tomorrow's work
This commit is contained in:
parent
888f5b62da
commit
00ebac17ce
|
@ -1231,14 +1231,33 @@ fn yield! {
|
||||||
() -> base :process (:yield)
|
() -> base :process (:yield)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
& TODO: implement these in the VM
|
||||||
|
fn alive? {
|
||||||
|
"Tells if the passed keyword is the id for a live process."
|
||||||
|
(pid as :keyword) -> base :process (:alive, pid)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn link! {
|
||||||
|
"Creates a 'hard link' between two processes: if either one dies, they both do."
|
||||||
|
(pid1 as :keyword, pid2 as :keyword) -> link! (pid1, pid2, :report)
|
||||||
|
(pid1 as :keyword, pid2 as :keyword, :report) -> base :process (:link_report, pid1, pid2)
|
||||||
|
(pid1 as :keyword, pid2 as :keyword, :panic) -> base :process (:link_panic, pid1, pid2)
|
||||||
|
}
|
||||||
|
|
||||||
fn msgs () -> base :process (:msgs)
|
fn msgs () -> base :process (:msgs)
|
||||||
|
|
||||||
|
fn flush! () -> base :process (:flush)
|
||||||
|
|
||||||
|
fn sleep! (ms as :number) -> base :process (:sleep, ms)
|
||||||
|
|
||||||
#{
|
#{
|
||||||
self
|
self
|
||||||
send
|
send
|
||||||
msgs
|
msgs
|
||||||
spawn!
|
spawn!
|
||||||
yield!
|
yield!
|
||||||
|
alive?
|
||||||
|
link!
|
||||||
|
|
||||||
abs
|
abs
|
||||||
abs
|
abs
|
||||||
|
|
|
@ -827,3 +827,50 @@ Thus we can use it to communicate with the process.
|
||||||
But everything else? Seems pretty straightforward.
|
But everything else? Seems pretty straightforward.
|
||||||
|
|
||||||
|
|
||||||
|
#### Some time later...
|
||||||
|
I've implemented what I decribe above. It works! I'm low-key astonished.
|
||||||
|
It perfectly handles an infinitely recurring process! What the fuck.
|
||||||
|
Anyway, things left to do:
|
||||||
|
* [ ] `receive` forms are the big one: they require threading through the whole interpreter
|
||||||
|
* [ ] implement the missing process functions at the end of prelude
|
||||||
|
* [ ] research how Elixir/Erlang's abstractions over processes work (I'm especially interested in how to make synchronous-looking calls); take a look especially at https://medium.com/qixxit-development/build-your-own-genserver-in-49-lines-of-code-1a9db07b6f13
|
||||||
|
* [ ] write some examples just using these simple tools (not even GenServer, etc.) to see how they work, and to start building curriculum
|
||||||
|
* [ ] develop a design for how to deal with asynchronous io with js
|
||||||
|
|
||||||
|
```
|
||||||
|
fn agent/get (pid) -> {
|
||||||
|
send (pid, (:get, self ()))
|
||||||
|
receive {
|
||||||
|
(:response, value) -> value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn agent/store (pid, x) -> {
|
||||||
|
send (pid, (:store, x))
|
||||||
|
:ok
|
||||||
|
}
|
||||||
|
|
||||||
|
fn agent/update (pix, f) -> {
|
||||||
|
send (pid, (:update, f))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn agent (state) -> receive {
|
||||||
|
(:get, pid) -> {
|
||||||
|
send (pid, (:response, state))
|
||||||
|
agent (state)
|
||||||
|
}
|
||||||
|
(:update, pid, f) -> {
|
||||||
|
agent (f (state))
|
||||||
|
}
|
||||||
|
(:store, pid, x) -> {
|
||||||
|
agent (x)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Two things that pop out to me:
|
||||||
|
* The way this works is just to yield immediately. This actually makes a lot of sense. If we put them next to one another, there's no risk that there'll be backlogged `(:response, x)` messages in the mbx, right? But that makes me a little queasy.
|
||||||
|
* The way `gen_server` works is pretty deep inversion of control; you effectively write callbacks for the `gen_server` to call. I'm not sure that's how we want to do things in Ludus; it's a handy pattern, and easy. But it's not simple. But also worth investigating. In any event, it's the foundation of all the other process patterns Elixir has developed. I need an intuiation around it.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
17
sandbox.ld
17
sandbox.ld
|
@ -1,10 +1,15 @@
|
||||||
let pid = spawn! (fn () -> {
|
fn simple_reporter () -> {
|
||||||
print! (self ())
|
print! (self (), msgs ())
|
||||||
print! (msgs ())
|
}
|
||||||
})
|
|
||||||
|
|
||||||
send (pid, :foo)
|
fn hanger () -> hanger ()
|
||||||
send (pid, :bar)
|
|
||||||
|
let foo = spawn! (hanger)
|
||||||
|
let bar = spawn! (simple_reporter)
|
||||||
|
let baz = spawn! (fn () -> panic! :oops)
|
||||||
|
|
||||||
|
send (foo, [:foo, :bar, :baz])
|
||||||
|
send (bar, (1, 2, 3))
|
||||||
|
|
||||||
yield! ()
|
yield! ()
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user