<ELLIOTTCABLE>
the rest of these, are sub-categories, so to speak: they're nested within another object, at creation-time, with another label.
<ELLIOTTCABLE>
`infrastructure label clone()(label)`: create a new Label with the same codepoint-content, and empty object-data.
<ELLIOTTCABLE>
`infra label compare()(a)(b)`: only resumes the caller if both are labels, and both have the same codepoint-content (so, symbol comparison)
<whitequark>
what?
<whitequark>
labels = symbols ?
<ELLIOTTCABLE>
?
<ELLIOTTCABLE>
yes? Labels are most similar to Ruby's symbols, or, errr, is it atoms, in lisp?
<glowcoil>
yeah that whole thing
<ELLIOTTCABLE>
comparison-oriented string-ish type
<ELLIOTTCABLE>
interned strings.
<whitequark>
then how can you even have a new label with same codepoint-content?
<whitequark>
it will be by definition be same label.
<whitequark>
because, duh, interned.
<ELLIOTTCABLE>
`infra label explode()(label)`: returns a newly-created list, with each codepoint from `label`, as an individual label, placed into the list at the corresponding index (starting at 1).
<ELLIOTTCABLE>
maybe I misunderstand interned. It can't *always* be memory-location-comparison for the *object itself*, because different Units could have different objects for a given label, with different object-data.
<ELLIOTTCABLE>
i.e. different objects with the same string-content.
<ELLIOTTCABLE>
It's the *string-content* of the label that's interned, not the Label object.
<ELLIOTTCABLE>
glowcoil: help? idk cs words enough.
<glowcoil>
whitequark: like, making a *new* label gives you like:
<whitequark>
glowcoil: no need, I got it
<glowcoil>
ok
<ELLIOTTCABLE>
oh, goodie
<glowcoil>
pointer to same string
<whitequark>
ELLIOTTCABLE: you can have both ways
<glowcoil>
but different paws properties
<whitequark>
eg in ruby it's the same object
<ELLIOTTCABLE>
I used to want all Labels with the same content, to be the same object.
<whitequark>
you totally can have different objects but still with fast string comparison, yeah.
<ELLIOTTCABLE>
glowcoil actually talked me out of that one, and with good reason.
<glowcoil>
ELLIOTTCABLE: don't even remember that
<glowcoil>
:p
<ELLIOTTCABLE>
really fucks up the data-graph, and the OO-ey seperation-of-concerns stuff that's fairly important to writing sane Paws (not to mention concurrency-sane.)
<whitequark>
yeah that's right.
<ELLIOTTCABLE>
next:
<alexgordon>
hi ELLIOTTCABLE
<ELLIOTTCABLE>
`infra execution branch()(xec)`: clones the execution-data in question, as described yesterday, and returns it to the calling execution
<ELLIOTTCABLE>
`infra execution stage()(xec)(value)`: think `yield`. queues the execution in question for evaluation, with `value` as the resumption-value. does not return to the caller.
<whitequark>
how is that different from "xec value" ?
<ELLIOTTCABLE>
the default-handelr for executions preforms what's called a “call pattern.” That's actually, conceptually, *three* operations composed:
<ELLIOTTCABLE>
1. unstage the caller,
<ELLIOTTCABLE>
2. clone the callee,
<ELLIOTTCABLE>
3. stage the callee.
<ELLIOTTCABLE>
in reality, since it's a handler, the first operation is unnecessary, because it's implicitly unstated by the fact that it's processing a combination using that handler … so, it boils down to the last two. clone-and-stage.
<whitequark>
yep, was going to say that.
<ELLIOTTCABLE>
whereas `infra exe stage` is *direct* staging, without cloning first. substantially different.
<ELLIOTTCABLE>
`infrastructure execution unstage void`: conceptually, unstage the caller.
<ELLIOTTCABLE>
now, this one's a bit gnarly:
<ELLIOTTCABLE>
in the current design, it's basically a no-op.
<ELLIOTTCABLE>
but there's a lot, a *lot*, of talk about re-designing the reactor to not treat holes indiscriminately, as it currently does … at which point, the purpose of this would be to create an ‘untagged hole’ that can receive any value.
<ELLIOTTCABLE>
ugh, really hard to words, maybe glowcoil can. But later.
<ELLIOTTCABLE>
point is, right now, it's a no-op. You call it, and it doesn't resume you, so you're paused.
<glowcoil>
whitequark: i want syntactic lambdas to replace priming
<ELLIOTTCABLE>
glowcoil: you keep saying that, and I don't think it means what you think it means
<whitequark>
yeah agreed with ec
<ELLIOTTCABLE>
rephrased, not what I'm talking about
<whitequark>
I don't think we necessarily need lambdas and scoping on this level
<ELLIOTTCABLE>
whitequark: (oh, that's something *else* he wants, but, not this thing)
<whitequark>
it's really an IR
<whitequark>
ELLIOTTCABLE: they're linked
<ELLIOTTCABLE>
just, hold on
<ELLIOTTCABLE>
three to go, that I can remember, an then we can talk about it
<glowcoil>
whitequark: what i mean is, i think this is too high level for an ir
<glowcoil>
whitequark: and too low level for a syntax
<whitequark>
glowcoil: nah, it's just right for an IR
<glowcoil>
whitequark: ok i guess i'll trust you
<whitequark>
I mean, Foundry IR was on about the same level
<whitequark>
±
<ELLIOTTCABLE>
`infra exe charge()(value)`: queues the caller, with a responsibility mask-request for `value`.
<glowcoil>
i just think that this ir like, precludes certain causality-network-topologies
<glowcoil>
without requiring runtime connections
<whitequark>
mmm
<whitequark>
what?
<glowcoil>
whereas llvm SSA lets you accomplish everything you want
<whitequark>
ah
<whitequark>
LLVM IR is a C IR
<ELLIOTTCABLE>
`infra exe discharge()(value)`: discards the mask for `value`, if the caller has it. does not return.
<whitequark>
if your surface language isn't C/C++, it's a wrong idea to use it
<whitequark>
in general
<whitequark>
e.g. even Rust has a lot of pain related to IR being a C IR.
<ELLIOTTCABLE>
`infra exe share()(value)(exe)`: up in the air right now, but theoretically should both allow for A) sharing of existing responsibility that the caller has, with `exe` in question … and B) of requesting responsibility that the caller *doesn't* have, on *behalf* of `exe`.
<ELLIOTTCABLE>
meh. done.
<ELLIOTTCABLE>
so.
<ELLIOTTCABLE>
what came up up there, for a moment, was a long-standing issue with the design, and one that I've waffled back and forth on for a solid three years.
<ELLIOTTCABLE>
what you've learned right now, is the “simple” staging/ordering mechanism.
<glowcoil>
whitequark: right i don't want llvm
<glowcoil>
whitequark: what i'm saying is like, suppose you want two things to depend on the same function, you have to introudce a runtime variable/opererty or whatever and a little object that passes things on
<glowcoil>
at minimum
<glowcoil>
whereas you can just write f(g) and then f is hooked up to g
<whitequark>
glowcoil: ah that, yeah, I was going to say it
<glowcoil>
that's why i want scope
<glowcoil>
and thus lambdas
<glowcoil>
like watch:
<glowcoil>
a <- g
<glowcoil>
f(a)
<glowcoil>
h(a)
<glowcoil>
there ya go
<whitequark>
not sure if this is related to scope
<whitequark>
well
<glowcoil>
like not necessarily scope i guess
<ELLIOTTCABLE>
wat
<glowcoil>
i just mean named things
<ELLIOTTCABLE>
glowcoil: re-phrase for me, I'm confused
<whitequark>
but there are locals
<whitequark>
I think you can do like
<ELLIOTTCABLE>
oh, got it
<whitequark>
set () a (g)
<whitequark>
something like that
<ELLIOTTCABLE>
still not sure how syntactic names are inherently superior to graphed names.
<ELLIOTTCABLE>
you *know* I prefer putting everything Paws does into/on the graph. Makes it more modifiable, flexible, introspectable …
<ELLIOTTCABLE>
BUT
<ELLIOTTCABLE>
glowcoil: hold on before you reply
<ELLIOTTCABLE>
glowcoil: lemme finish what I was saying above, because it clearly requires syntactic names *anyway*. I see no point for them in your example, but …
<ELLIOTTCABLE>
basically, if something wants to pass a value into a paused execution, it's first-come, first-serve: the first person to queue that execution for evaluation, with a value, will get their value in to the *first* hole (i.e. where it's waiting), and somebody else who wants to pass a value into the *same execution* will have their value instead go to the second
<ELLIOTTCABLE>
‘hole’ (i.e. it'll be left on the queue, and the next time the execution unstages, it'll immediately resume with that value as the result.)
<ELLIOTTCABLE>
the issues with that are obvious; there's also solutions, and good-caveats, which are less obvious, and all of which I won't go into right now
<whitequark>
combined with dynamic typing, this is disastrous
<ELLIOTTCABLE>
yep. exactly. or, sounds like it is.
<whitequark>
(well, it's only possible with dynamic typing)
<ELLIOTTCABLE>
one of the solutions involves modifying the semantics of staging, as a whole, to *include responsibility*. Basically, treat resuming an execution as sequentially modifying it (which you are. lol. that's kind of the point)., meaning “call-pattern” necessarily involves acquiring responsibility-lock first.
<purr>
lol
<glowcoil>
that's why i don't want theym to be mutable executions by default
<ELLIOTTCABLE>
more on that at another date. Point of this conversation is to talk about the long-discussed alternative:
<whitequark>
glowcoil: no, mutable executions are important for freezing computations
<ELLIOTTCABLE>
tagged holes and resumptions.
<glowcoil>
ok whitequark's way smarter than me he's promoted to paws codesigner
<glowcoil>
i steop down
<ELLIOTTCABLE>
basically, the innovation is, all ‘holes’ (unstagings-which-are-waiting-for-a-resumption-value) are not created equal.
<ELLIOTTCABLE>
glowcoil: lol'ing hard
<ELLIOTTCABLE>
glowcoil: you'll always be paws codesigner in my heart, bby
<glowcoil>
ELLIOTTCABLE: <3
<ELLIOTTCABLE>
-learn CodeSigner = glowcoil
<purr>
ELLIOTTCABLE: Learned `CodeSigner`.
<ELLIOTTCABLE>
we introduce a *huge* amount of extra complexity to the design, but the idea being that that is an acceptable cost, because it reduces a *huge* amount of back-flips necessary to safely use indiscriminate-holes in the real world.
<whitequark>
ELLIOTTCABLE: go on, but there is a very simple solution to your problem
<whitequark>
idk if you ever considered it
<ELLIOTTCABLE>
(it's not as much of a U/X issue as it sounds, as all of those backflips would necessarily be abstracted away … it's really more of a performance issue, actually.)
<ELLIOTTCABLE>
okay tell me when I finish
<whitequark>
oh god elliott speculating about performance again
* whitequark
sighs
<ELLIOTTCABLE>
ISAWWYJESUS
<whitequark>
didn't you tell me, years ago, that you explicitly don't care about perf?
<ELLIOTTCABLE>
Yes. That's supposed to be the case.
<whitequark>
lol
<purr>
lol
<whitequark>
LOL
<ELLIOTTCABLE>
I'm just bad at explicitly-not-caring-about-perf. ;)
<ELLIOTTCABLE>
basically, re-design the staging system so that when something calls *out*, it gives enough extra data that the later resumption, by the callee, goes into the hole it's supposed to.
<ELLIOTTCABLE>
that concept is called first-class holes
<ELLIOTTCABLE>
alexgordon: exactly as complete as it was last time.
<alexgordon>
ELLIOTTCABLE: :|
<alexgordon>
so it's done?
<ELLIOTTCABLE>
i.e., very complete, as long as all you want to do is say “I am able to run Paws code,” without actually running any meaningful Paws code.
<ELLIOTTCABLE>
yes. spec is done.
<ELLIOTTCABLE>
it's *terrible*, but done.
<ELLIOTTCABLE>
what's missing, is all the ‘natives.’
<ELLIOTTCABLE>
really simple libside functions to, you know, ACTUALLY DO THINGS.
<ELLIOTTCABLE>
create a new list. append to the list. search a list. compare two labels.
<ELLIOTTCABLE>
I just described them all here in chat, to whitequark, because I can't be arsed to add them to the spec, because the current spec is doomed, and because they're wildly simple.
<alexgordon>
ELLIOTTCABLE: hm well I have a bit of free time
<ELLIOTTCABLE>
alexgordon: yay!
<ELLIOTTCABLE>
alexgordon: let me listen to whitequark's response here, and then I'll happily hand-hold you through getting started.
<ELLIOTTCABLE>
anyway … long story short, that idea is called ‘first-class holes.’
* alexgordon
laughs
<alexgordon>
is this the official name? xD
<ELLIOTTCABLE>
introduce a new data-type, that represents a **particular** unstaging of an execution.
<ELLIOTTCABLE>
alexgordon: if it happens, yes, the Sillyname™ for the type will almost certainly be Hole.
<whitequark>
glowcoil: if it is not clear
<ELLIOTTCABLE>
the problems I have with this are both complexity added to the design, *and* complexity added to the concept.
<whitequark>
I'm playing Goat Simulator
<alexgordon>
ELLIOTTCABLE: whatever you do, don't let the feminist software foundation know about it
<ELLIOTTCABLE>
whitequark: ARE YOU REALLY
<ELLIOTTCABLE>
whitequark: OH MY GOD DYING LOL
<purr>
LOL
<whitequark>
I am, for like hours on end already
<ELLIOTTCABLE>
omfg
<whitequark>
got it running under linux like
<whitequark>
lemme check
<whitequark>
six hours ago
<whitequark>
and playing nonstop
<ELLIOTTCABLE>
oh gods :P
<ELLIOTTCABLE>
making me want to do so.
<whitequark>
hang on
<ELLIOTTCABLE>
so! alexgordon! you beautiful bastard!
<whitequark>
so basically two possible solutions
<whitequark>
to your hole problem.
<ELLIOTTCABLE>
yah?
<glowcoil>
whitequark: oh ok haha
<whitequark>
one is to introduce traditional CPS. you disregard mutable executions, instead you have something like a global table of currently executing stuff or something
<whitequark>
and then you just pass an execution which should be launched upon completing whatever it is you want to run, explicitly.
<whitequark>
it's a variation on the topic of foo(), but the thing is, since they're now immutable, there is absolutely no ambiguity.
<glowcoil>
god i'm glad we have whitequark on this
<whitequark>
the idea is that when you call anything, the current execution disappears, and a new one, for the rest of computation, appears and is passed to whatever it is you're calling
<alexgordon>
goat simulator looks cool
<whitequark>
so it's not the regular continuations you (rightly) dislike, it's basically delimited ones
<whitequark>
it is a variation on the existing concept of executions essentially.
<whitequark>
now, there is another possible way!
<whitequark>
you keep mutable executions, but you perform a kind of inversion of control
<whitequark>
hm, how do I explain.
<whitequark>
since it is basically a clone of OCaml's Lwt (which looks *very* similar to Paws's asynchronity, except for the holes, which is another interesting thing),
<whitequark>
I'll start by quickly explaining Lwt
<whitequark>
so, basically, Lwt is a monad and your main tools are the bind and return endofunctors
<whitequark>
...
<whitequark>
joking :p
<whitequark>
(though it is)
<ELLIOTTCABLE>
reading
<whitequark>
comment after I finish.
<ELLIOTTCABLE>
k
<whitequark>
so, Lwt has a really really simple concept at its core.
<whitequark>
you have so-called "lightweight threads". internally (since we're talking about Paws internals, it's relevant),
<whitequark>
a lightweight thread is a single mutable cell with three possible states.
<ELLIOTTCABLE>
(by the way, what you're calling immutable executions, is basically Paws-conveyable as “ALWAYS CLONE.” Conflating cloning and staging permanently.)
<ELLIOTTCABLE>
(listening.)
<whitequark>
these states are, Sleep, Result and Fail. (you probably won't have Fail.)
<whitequark>
there are two main functions in Lwt, upon which everything else is built.
<whitequark>
well, three, actually. anyway.
<whitequark>
there's "Lwt.return a", which creates a thread in state "Result (a)"
<whitequark>
there's "Lwt.bind a b", which waits (in an abstract way) until "a" transitions from Sleep and when it does, invokes "b" with the result.
<ELLIOTTCABLE>
a in the second case being a ‘cell?’
<ELLIOTTCABLE>
er, a thread?
<whitequark>
yep
<ELLIOTTCABLE>
k
<ELLIOTTCABLE>
b also being a cell thread?
<whitequark>
no, b is a function here
<ELLIOTTCABLE>
k
<whitequark>
basically, despite being called "threads", Lwt threads don't actually have any code to run.
<ELLIOTTCABLE>
mmmm, I see that
<whitequark>
they're synchronisation primitives, essentially, coordinating execution of some other code on some other VM
<ELLIOTTCABLE>
what's the purpose / use?
<ELLIOTTCABLE>
also, something just came up, and I have to jet very soon
<ELLIOTTCABLE>
glad we got over the natives in time D:
<ELLIOTTCABLE>
if alexgordon needs help, whitequark / glowcoil, are you two capable of providing it?
<ELLIOTTCABLE>
I'll still be on IRC via phone for any crucial shit.
<ELLIOTTCABLE>
just not super interactive. (Dinner with friend's mother.)
<whitequark>
Lwt is a sane solution to the problem nodejs fails to solve
<whitequark>
basically
<ELLIOTTCABLE>
mmmmmm, how so
<ELLIOTTCABLE>
I mean, the concept is simple enough, but I'm not seeing the whole picture. How it's applied / useful / whatever. Just looks like a simple lock-ish thingie to me.
<whitequark>
nah, it's orthogonal to locks.
<whitequark>
basic usage is like this.
<ELLIOTTCABLE>
wait hold on
<ELLIOTTCABLE>
mis-read
<ELLIOTTCABLE>
"return" *creates* a cell, already in result-state?
<ELLIOTTCABLE>
how do you change an existing cell?
<whitequark>
yep, creates a cell
<ELLIOTTCABLE>
wat. now I'm totally confused. So, they're mutable … how?
<whitequark>
hang on
<whitequark>
5AM here, explanation abilities may suffer.
<whitequark>
so the idea is that there are basically two modes of usage for threads.
<whitequark>
the first is chaining them together, e.g. suppose you have a function http_get which does the obvious thing
<whitequark>
...
<whitequark>
do you want js-syntax or ocaml-syntax?
<ELLIOTTCABLE>
js
<whitequark>
ok
<ELLIOTTCABLE>
JSON is ideal structure-conveying format, and JS itself is a fairly ideal boring-code conveying format.
<whitequark>
first: http_get and http_post immediately return a thread, regardless of whatever happens with IO.
<whitequark>
then: bind immediately returns a thread, too
<whitequark>
so basically, that whole construct immediately returns a thread, most likely in Sleep state, when it's executed.
<whitequark>
the main idea here is that you don't *pass* a callback, an ephemeral argument-y thingy, you *get* back a Thing You Can Feel, store, basically do whatever you want,
<whitequark>
which serves the same purpose as a callback.
<whitequark>
makes sense?
<ELLIOTTCABLE>
errrrrrrrrrrrrm
<ELLIOTTCABLE>
mostly, except,
<ELLIOTTCABLE>
why the Lwtreturn in the middle
<whitequark>
because bind accepts a thread, not a result.
<ELLIOTTCABLE>
why not just return the value directly; it's available.
<ELLIOTTCABLE>
oh.
<ELLIOTTCABLE>
so it's just wrapping an already-extent body into it.
<whitequark>
in general, the value will not be always available
<whitequark>
yes
<ELLIOTTCABLE>
but:
<whitequark>
if it's not, you only have a thread
<whitequark>
and there is no function for giving you value of a thread now!
<ELLIOTTCABLE>
I see no way that anything except http_get and http_post get to *use* this.
<ELLIOTTCABLE>
I can't generate a lwt, do some work, and then fulfill it.
<ELLIOTTCABLE>
right?
<whitequark>
you can, it's called waiter/wakener
<whitequark>
there's really nothing to explain, it's just the backside of the same API
<whitequark>
you have a "waiter" function, which returns you two objects,
<whitequark>
essentially, a thread in permanent sleep, and a function to transition it from Sleep to Result or Fail.
<whitequark>
that's actually the way the Lwt reactor binds epoll() unix async IO to the Lwt infrastructure
<whitequark>
when you make a request, it schedules it wherever, returns you a waiter, and attaches wakener to that scheduled thing.
<whitequark>
when it completes, it invokes wakener.
<whitequark>
another *very* important thing in Lwt is that there are no errbacks.
<whitequark>
it's more or less tainting.
<whitequark>
if you bind on a thread which Fails, then the thread bind just returned will Fail, too.
<whitequark>
so there's no way to just forget or ignore errbacks by default, they propagate up not unlike exceptions
<whitequark>
Lwt, unlike node.js API, is *incredibly* convenient to write.
<whitequark>
traditional sequental code is just a sequence of binds.
<whitequark>
in fact, I find Lwt markedly similar to Paws you described in the spec (hence my earlier commentary on your PL design abilities.)
<ELLIOTTCABLE>
holon
<ELLIOTTCABLE>
bbrbr >.<
<ELLIOTTCABLE>
ihave to go.
<ELLIOTTCABLE>
poooppppuhij'k
<whitequark>
read it later then
<glowcoil>
popupjkghkhldskfjksjhar
<ELLIOTTCABLE>
whitequark: will have to read response later, but: I'm not connecting the dots on how this solves the concerns with resumptions filling the wrong holes.
<ELLIOTTCABLE>
how do you mean, "turn it inside out?"
<whitequark>
currently, the problem with your system is that a thread of execution must return a value to something that mutates independently of it
<whitequark>
i.e. shared mutable state
<whitequark>
both proposals limit this shared mutable state in a way that becomes manageable;
<whitequark>
the first one gets rid of it entirely (a pure functional way, in its essence)
<whitequark>
the second one reduces it to an object with very strict rules, i.e. which only can transition from Sleep to Result once and that's it.
<whitequark>
the "inversion of control" is just an apparent surface effect resulting from implementing the second one,
<whitequark>
since you come from the callee telling the caller what to do, to the caller binding to the callee's result.
<whitequark>
(in Lwt case)
<whitequark>
in CPS case, there's none of this apparent inversion, BUT you must convert *all* of your code into CPS form, i.e. essentially make combinations and executions one thing.
<whitequark>
so, there would be no "execution which independently executes a tree of combinations". there would only be a mutable set of currently pending (staged, I think?) immutable combinations
<whitequark>
there really isn't a lot of arguments for either of these styles, except aesthetics.
<whitequark>
I mean, arguments to select one over another, for an IR.
prophile has quit [Quit: The Game]
<ELLIOTTCABLE>
I understand the purist CPS version; it's very un-paws.
<ELLIOTTCABLE>
Trying to wrap my head around how to apply the second to Paws.
<ELLIOTTCABLE>
In fact, I'm pretty sure that's exactly what Holes are, in a way:
<ELLIOTTCABLE>
A hole is a single-use "target" into an Execution.
<ELLIOTTCABLE>
Execution is still shared mutable state, but holes are a lens through which it's immutable, kinda, then?
<whitequark>
ummm, not quite, I think.
<whitequark>
I would imagine that you will make Executions itself single-use.
<whitequark>
(in a way, they are now)
<whitequark>
I think that this is actually really similar to your current approach, except to successfully make the Lwt-Paws, you'd need to remove the Node-tree-traversing stuff.
* whitequark
ponders at it
<whitequark>
okay, let's try it another way
<whitequark>
so, there's an Execution. it can be Finished and Unfinished. if Finished, it has some value.
<whitequark>
it's perfectly legal for an execution to be permanently unfinished (an counterpart of your never-returning combinations).
<whitequark>
Execution can only change its state from Unfinished to Finished. how exactly this happens is of no concern to the code *referring* to the execution.
<alexgordon>
ELLIOTTCABLE: don't let whitequark get you down... the main thing is to get the interface down -- any implementation can choose to implement it any way it wants
<whitequark>
alexgordon: we were arguing exactly about the interface, lol.
<purr>
lol
<whitequark>
ELLIOTTCABLE: so, continuing.
<alexgordon>
whitequark: oh ok. elliott said earlier that the spec was complete but he didn't like the way it was specified or something
<whitequark>
yes, it's really really ambiguous
<whitequark>
incredibly so
<alexgordon>
nothing new there :P
<whitequark>
ELLIOTTCABLE: in particular, every Expression (hence combination) in the source gives rise to an Execution
<whitequark>
when that combination finishes executing, the resulting Execution receives a value.
<whitequark>
now, what about the expressions it refers to? basically, it seems that in cPaws the bind operation would be essentially implicit
<whitequark>
i.e. a combination binds, *concurrently*, to all other combinations it refers to (Expressions nested into it syntactically),
<ELLIOTTCABLE>
whitequark: errr hold on
<whitequark>
and when they all finish, that combination is evaluated.
<ELLIOTTCABLE>
Crap. Later. UGH.
<ELLIOTTCABLE>
Maybe about an hour. This is absorbing all my attention and I'm rudely buried in my phone.
<ELLIOTTCABLE>
Ugh.
<ELLIOTTCABLE>
Soon.
<whitequark>
so, what you have is an Execution-dependence-graph, with the leaf nodes being the ones which are going to execute earliest (at next "tick", using your terms),
<whitequark>
and the root node would be the main program.
<whitequark>
well, main script or whatever. main something.
<whitequark>
i.e. when the root node Finishes, Paws VM quits.
<whitequark>
before you ask: yes, the dependence graph is a tree. it is capable of representing loops via some magic which is completely irrelevant to this high-level explanation.
<whitequark>
(tl;dr: you need magic because otherwise nothing ever gets GC'd and you just insert new and new executions when you loop. a certain trick allows you to actually run such programs in limited memory space. :p)
<whitequark>
ELLIOTTCABLE: so to summarize: in this model there is no mutable pc, because every Execution corresponds to exactly one Expression,
<whitequark>
there is no stack in Execution, because the stack is *laid out explicitly in the Execution graph, which is also Paws object graph*--I think you'll really like the ability to easily examine what waits on what
<whitequark>
(it's actually very useful on Lwt, too)
cloudhead has quit [Ping timeout: 268 seconds]
<whitequark>
oh, also, a few words on the () and {}
<whitequark>
basically, "foo (bar)" means: create an execution for "bar", then bind execution of "foo" to it and, when the "bar" is Finished, evaluate the combination "foo <value of bar>"
<whitequark>
whereas "foo {bar}" means: create an execution for "bar", then *immediately* evaluate the combination "foo <execution for bar>"
<whitequark>
I think this is just truly beautiful.
<whitequark>
the Ultimate Asynchronous Language™
<whitequark>
in fact this is so fucking beautiful, I'm probably going to implement it regardless of what you sau
<whitequark>
*say
<whitequark>
this also solves the Freezing problem (explicit dependency graph), the spec-ing problem (I've just explained the semantics in a few sentences), and likely a few others
<whitequark>
so. now let me describe a set of primitives (proper term for "natives") for this scheme
<whitequark>
1. `ignore (expr)', most likely used as `ignore {expr}' though. Schedules expr for execution ("stages") without binding the tree of executions to it. Essentially, creates another root node in the dependency tree.
<whitequark>
2. `seq (expr1) (expr2)', most likely used as `seq (expr1) {expr2}' again. Ignores its first argument, when invoked, binds the second one and returns its value (Finishes with it. Essentially, the Execution for the seq combination just becomes the Execution of {expr2}).
<whitequark>
used, obviously, for doing things sequentially.
<whitequark>
3. `choose (expr1) (expr2)', most likely used as `choose {expr1} {expr2}'. Finishes with the value of whichever of expr1 and expr2 finishes first.
<whitequark>
Could, for example, ignore tainted values, if you so like it, and become tainted itself if both expr1 and expr2 become tainted.
<glowcoil>
2:09:06 <+whitequark> I think this is just truly beautiful.
<glowcoil>
2:09:44 <+whitequark> the Ultimate Asynchronous Language™
<glowcoil>
2:09:55 <+whitequark> in fact this is so fucking beautiful, I'm probably going to implement it regardless of what you sau
<glowcoil>
so happy
<glowcoil>
c:
<whitequark>
okay, now how the fuck do I actually loop here
<whitequark>
need some kind of y combinator I guess
<whitequark>
not unlike regular paws though
<whitequark>
ah, well, trivial. put the Execution which wants to recur into locals.
<whitequark>
oh no, that would not quite be it
<whitequark>
4. `clone (expr)', most likely used as `clone {expr}'. creates a new Unfinished execution performing the same computation as expr.
<whitequark>
ah, talking about the locals problem, this is solved too.
<whitequark>
both the implicitly created Executions inherit the locals of whatever created it. clone also sets the locals reference to the same object.
<whitequark>
therefore, 5. `call (locals) (expr)', bla bla `call (locals) {expr}'. does the same thing as `clone', but sets the locals to whatever is provided.
<whitequark>
in fact, could get rid of call. just make clone accept two args by default. so, you'd just usually call it `clone (locals) {expr}'.
<whitequark>
s,by default,,
<whitequark>
so, 5. `set (obj) (expr)'. could be used to set an lvar as `set varname (expr)'. read is performed simply via `varname'.
<whitequark>
now I can make recursion!
<whitequark>
hm, no, wait, I can't read just via `varname'
* whitequark
grumbles
<whitequark>
what did I miss?
<whitequark>
ah, the resolution
<whitequark>
all of the above must be prefixed with "infra" to have a valid receiver
<whitequark>
so
<whitequark>
1. `infra ignore (expr)'
<whitequark>
2. `infra seq (expr1) (expr2)'
<whitequark>
3. `infra choose (expr1) (expr2)'
<whitequark>
4. `infra clone (locals) (expr)'
<whitequark>
5. `infra get (obj) (name)'
<whitequark>
6. `infra set (obj) (name) (expr)'
<whitequark>
recursion.
<whitequark>
ahhhh right, another thing missing.
<whitequark>
or not. hm.
<whitequark>
I need an identity wrapping for binding expressions
* whitequark
sighs
<whitequark>
actually, why the fuck even *have* infra? I don't need it!
<whitequark>
at all.
<whitequark>
let's rather use the cool functionality Paws provides and do this properlt.
<whitequark>
*properly.
<whitequark>
basically, set the default receiver on executions to handle several predefined messages.
<whitequark>
1. `exec ignore'. detaches it to another root node.
<whitequark>
er
<whitequark>
no.
<alexgordon>
holy shit whitequark
<alexgordon>
HOLY SHIT IT JUST HIT ME
<alexgordon>
whitequark is a White Russian
<whitequark>
...
<whitequark>
I thought it was about Paws.
<whitequark>
whatever, cocktails, not interested.
<whitequark>
so.
<alexgordon>
<+whitequark> whatever, cocktails, not interested.
<alexgordon>
don't let elliott hear that
<whitequark>
0. `exec call'. if Finished, returns the value. if Unfinished, waits until Finished and returns value.
<alexgordon>
whitequark: so this is a derivative of paws?
<whitequark>
1. `exec ignore'. immediately returns, schedules exec as a separate root node.
<alexgordon>
(welcome to the club)
<whitequark>
alexgordon: it's a proposal for redesign.
<alexgordon>
mmhmm
<whitequark>
2. `exec1 seq (expr)'. expects (expr) to evaluate to an execution. waits until exec1 is Finished, ignores its value; then waits until exec2 is Finished and returns its value.
<whitequark>
3. `exec1 choose (expr)'. expects (expr) to evaluate to an execution. waits until either exec1 or exec2 are Finished, returns the value of whatever was quicker.
<whitequark>
4. `exec clone (locals)'. returns a clone of exec with locals field set to result of (locals). (locals) may be omitted.
<whitequark>
5. `locals set name (value)'. that's right, the locals object will have another custom default receiver!
<whitequark>
now, recursion is trivial.
<whitequark>
{ locals set f { (f clone) call } } seq { f call }
<whitequark>
YAY!
<whitequark>
I've made elegant Paws, capable of conveniently expressing any interesting computation, with precisely 6 primitives.
<whitequark>
though it's probably more like this
<whitequark>
{ locals set f { ((f) clone) call } } seq { (f) call }
<whitequark>
{ (locals) set f { ((f) clone) call } } seq { (f) call }
<whitequark>
even
<whitequark>
otherwise it would be impossible to send any messages to Symbols
<whitequark>
*shrug* or you could bite the bullet and make that impossible as well. irrelevant.
<purr>
¯\(º_o)/¯
jesusabdullah has quit [Ping timeout: 246 seconds]
<whitequark>
brb implementing
<whitequark>
though I feel like this has, like
<whitequark>
literally nothing whatsoever in common with old paws execution model
<whitequark>
hm, could actually make this a bit more elegant
jesusabdullah has joined #elliottcable
<whitequark>
maybe
<whitequark>
really, the hardest thing to track in this scheme is where an Execution is explicit and where it is implicit
<whitequark>
okay so. the 2nd element of an expression is a message. could be a symbol literal, could be another expression evaluating to a symbol literal.
<whitequark>
or maybe just any object whatsoever
<whitequark>
the 3rd and next elements of an expression are parameters. could be a symbol literal, in which case it evaluates to itself, could be an expression, in which case the current one is bound to it, could be an execution, which is then created
<whitequark>
an execution literal.
<whitequark>
which is created as an execution.
<whitequark>
ah, I think I know what I've missed
<whitequark>
grmbl
<whitequark>
yeah, right, I accidentally introduced smalltalk semantics here. it's not really how it should perfectly be
<whitequark>
and in fact invalidates everything I said about primitives
<whitequark>
okay, scratch almost everything on the above
<whitequark>
I think I figured it out, though I'll explain later
<whitequark>
ok, on a second thought it actually makes perfect sense, but not for the reasons I thought it does
<whitequark>
though it means that for >0-ary calls you essentially want a mechanism to construct curried functions
<whitequark>
I *think* it can be built on top of seq, with slight modification
<whitequark>
essentially, reversing the order of its arguments
alexgordon has quit [Quit: My iMac has gone to sleep. ZZZzzz…]
<ELLIOTTCABLE>
whitequark: on my way home.
<ELLIOTTCABLE>
If you're around.
<purr>
<vil> it's like, programming is the problem, java is a poorly-molded nail, and Eclipse it a rock made of nails
<SwooshyCueb>
omg ELLIOTTCABLE GW2's April Fool's joke
<vigs>
purr: which is why vil should be using IntelliJ
<purr>
* Nuck runs back to the 90's
<SwooshyCueb>
I'm tempted to trade Twitter accounts with someone for the day as my April Fool's thing
eligrey has quit [Quit: Leaving]
<SwooshyCueb>
Bedtime!
sharkbot has quit [Remote host closed the connection]
<w00f>
Paws.ml/master 0acf339 Peter Zotov: Rename to Paws.ml.
<w00f>
Paws.ml/master df4bc01 Peter Zotov: Tests for Lexer.format_error.
<w00f>
Paws.ml/master f3c0905 Peter Zotov: Implement LL(1) recursive descent parser for cPaws.
<w00f>
[Paws.ml] whitequark force-pushed lwt-style-async from a594de7 to 4290ae5: http://git.io/VxNktw
<w00f>
Paws.ml/lwt-style-async 4290ae5 Peter Zotov: Implement combination evaluation.
<whitequark>
so basically, what I figured out yesterday was how to refactor the advance() and stack madness
<whitequark>
mostly
<whitequark>
I do have some more ideas though
upgrayeddd has joined #elliottcable
<ELLIOTTCABLE>
THAT POST. whitequark
<ELLIOTTCABLE>
Dying
<ELLIOTTCABLE>
So, I need to go read everything from last night
eligrey has joined #elliottcable
<whitequark>
ELLIOTTCABLE: don't bother
<whitequark>
half of it was my mis-reasoning, and the other half has *extremely* confusing terminolog
<whitequark>
like, it is actually better if you don't read that
<whitequark>
because we have it bad enough already
<whitequark>
basically I accidentally swapped executions and combinations
<whitequark>
ELLIOTTCABLE: buuuuut
<whitequark>
I think I just had an epiphany
<whitequark>
and I've untangled your Paws VM mess into well-known CS concepts
<ELLIOTTCABLE>
ohhmaar: so, the exciting part starts after you've learned enough JS and ObjC to be relevant in those fields. Focus on them for a few months, preferably *build something* in each (hey, wanna write a Paws? :P ),
<ELLIOTTCABLE>
And then come ask me that question again. :P
<whitequark>
lol I tweeted a fragment of anime and nine people unfollowed me
<purr>
lol
<ELLIOTTCABLE>
And I'll get to tell you to learn LISP and Haskell and maybe OCaml with whitequark and I and Lua and Factor and …
<whitequark>
OR I have finally got a grasp on the twitter bug, where I *suspect* that it randomly unfollows people for you
<whitequark>
because I'm pretty sure it did that on me at least once
<whitequark>
I mean, if it happens on a @monthly cronjob, that's at least plausible. need to wait another month.
<ohhmaar>
sounds good
<whitequark>
ELLIOTTCABLE: ping
<ELLIOTTCABLE>
hi
<purr>
ELLIOTTCABLE: hi!
<ELLIOTTCABLE>
-pong @ whitequark
<ELLIOTTCABLE>
-ping @ whitequark
<purr>
whitequark: pong
<glowcoil>
hi all
<ELLIOTTCABLE>
glowcoil!
<ELLIOTTCABLE>
now we just need alexgordon …
<glowcoil>
7:19:55 <+whitequark> lol I tweeted a fragment of anime and nine people unfollowed me
<purr>
lol
<ELLIOTTCABLE>
ohhmaar: just let me know when you're coming into downtown. :P
<ELLIOTTCABLE>
ohhmaar: you got a Facebook?
<glowcoil>
glazed donut~
<whitequark>
glowcoil: what?
<glowcoil>
eating one
<glowcoil>
lol that's all
<glowcoil>
and it's sweeter than this macchiato :/
<glowcoil>
i
<glowcoil>
am
<glowcoil>
buzzin
<glowcoil>
why do all of you hate me
<ohhmaar>
ELLIOTTCABLE: I don't but I'll let you know
<ELLIOTTCABLE>
glowcoil: wat
<whitequark>
ELLIOTTCABLE: so
<whitequark>
you're here?
<whitequark>
wanted to discuss.
<ELLIOTTCABLE>
I want to shower and dogs and shit, but yes, am here
<whitequark>
I think I actually found a critical bug in the spec
<ELLIOTTCABLE>
glowcoil: you here, too?
<whitequark>
as in, it simply cannot work as it is described
<ELLIOTTCABLE>
whitequark: wouldn't be surprised. that's what were here to catch.
<whitequark>
explaining
<whitequark>
so for example the idea is that the current execution is stopped after each combination and resumed whenever it explicitly passes itself to something else and *that* resumes it, right?
<whitequark>
"Notes: The current execution is implicitly stopped after each combination; that is, it has been processed, and then the call-pattern invoked in step 3 of this algorithm leaves it stopped."
<whitequark>
so for example you want to do `infra clone()(thing)'. I assume it's the actual Paws code, I believe it is
<ELLIOTTCABLE>
go ahead
<ELLIOTTCABLE>
think I've run into this one before, and just forgot about it
<ELLIOTTCABLE>
:P
<whitequark>
so the first combination is `infra clone'. the default receiver for `infra' receives the `clone' symbol, and the execution executing this is stopped
<whitequark>
and it will *never be resumed*
<whitequark>
because, duh, nothing knows that it should be resumed.
<ELLIOTTCABLE>
“This came to me from much of my reading on all sorts of matters but mostly from the Aztecs calendar ending on 12-21-12, the difference of the first two, 9, and difference of the last two, 9. And with the geomagnetic reversal this year, Solar Cycle 24, while I am 24, I figured why the fuck not try now, because I also don’t believe in luck or
<ELLIOTTCABLE>
coincidences, and that god is in the details.”
<ELLIOTTCABLE>
“If I transposed EVERYTHING is my life, could my difference be 9? Could I be 90% fulfilled with my life when I was done if I did this for one year?”
<ELLIOTTCABLE>
“… even dumped a whole cup of water on my Mac to show my sister those things don’t matter but also to show her that if you let the water dry completely, then it will actually do no damage to the computer,”
<ELLIOTTCABLE>
… I think I *gave* her that Mac. ಠ_ಠ
<whitequark>
What.
<whitequark>
okay
* alexgordon
is here
<alexgordon>
ELLIOTTCABLE: hi
<whitequark>
so if all combinations receive the calling execution
<whitequark>
then why `infra prefix()(thing)(val)' should even include `()' at all?
<ELLIOTTCABLE>
“ where my family are the naturally selected rebirth of Greek Gods, me being Gaia, my Dad Apollo, my baby sister Uranus…and the second coming of Jesus Christ!”
<ELLIOTTCABLE>
sorry
<whitequark>
ELLIOTTCABLE: I suppose she needs some serious medical help. *shrug*
<purr>
¯\(º_o)/¯
<ELLIOTTCABLE>
whitequark: **combination receivers** receive it. And that's a hack. It's not *specially* treated, from the point of view of libside, anywhere else.
eligrey_ has joined #elliottcable
<ELLIOTTCABLE>
if you want somebody to have a handle on you, you *give* them that handle.\
<ELLIOTTCABLE>
this is intentional:
alexgord_ has joined #elliottcable
* whitequark
sighs
<ELLIOTTCABLE>
lots of useful invocation-patterns involve *multiple* ‘callers’ passing value in.
<glowcoil>
I AM JUST A COPY OF A COPY OF A
<ELLIOTTCABLE>
We originally had an implicit caller-passing pattern (i.e. you could “get the caller” from the API), but the problem is, ‘What does caller mean?’ got trapped up in that, and ended up preventing some invocation-patterns.
<ELLIOTTCABLE>
it's much easier to let the routine in question define, and document, its own invocation pattern; and then in that definition it can require that its callers pass themselves to it, if necessary (the way `infra prefix`, for instance, is documented to be coconsumptive.)
<ELLIOTTCABLE>
as nice as that system is, it doesn't work for combination receivers.
<ELLIOTTCABLE>
rather obviously. although I didn't notice it for ages.
eligrey has quit [Disconnected by services]
eligrey_ is now known as eligrey
<ELLIOTTCABLE>
receivers *require* three arguments. and coconsuming three arguments, require three stagings. Which would mean that every single staging, requires three more stagings … yep. infinite recursion, a mess of it.
<whitequark>
yeah yeah
<whitequark>
so
<ELLIOTTCABLE>
solved by making combination-receivers operate on exactly one staging.
<ELLIOTTCABLE>
go ahead
<whitequark>
basically your problem is, as I understand it
<whitequark>
that *between* any ticks, all executions are essentially stopped
<whitequark>
and when it is stopped, it can be resumed by whoever sending it a message
<whitequark>
and the result of sending such a message is basically (N of possible messages × M of possible stopped states, i.e. number of words)
<whitequark>
which quickly becomes a mess to understand.
<whitequark>
in other words, in presence of concurrent execution, you don't really know what the execution will do when it gets a message
<whitequark>
it will get inserted *somewhere* and *something* will be combined with it
<whitequark>
right?
<ELLIOTTCABLE>
sorry, was reading the rest of that ‘friend's’ post
<ELLIOTTCABLE>
ugh
<ELLIOTTCABLE>
okay, reading
<ELLIOTTCABLE>
yes, exactly.
<whitequark>
ok, good.
<ELLIOTTCABLE>
Mind you, I'm not dead-set on “solving” that problem, because it's eminently solvable lib side.
<whitequark>
well
<ELLIOTTCABLE>
documentation, sane invocation patterns, the aid of locking …
<ELLIOTTCABLE>
but. yeah.
<ELLIOTTCABLE>
so,
<ELLIOTTCABLE>
here's my issue with the two systems you proposed yesterday:
<whitequark>
I think I can change Paws VM so that this problem will simply disappear
<ELLIOTTCABLE>
the first, is very un-Paws-y, but I can cover that more, later.
<ELLIOTTCABLE>
the bigger issue with them both, is that they both intentionally remove what I consider to be the most important design-aspect *of* Paws, which is the mutability of Executions:
<ELLIOTTCABLE>
I want to solve this problem *without* taking away from the fact that two locations in the code can be holding an Execution, and they can both resume it separately.
<ELLIOTTCABLE>
(basically, the way it works now Is A Feature, Not A Bug.)
<ELLIOTTCABLE>
I just want a way around the-way-it-works-now, when the-way-it-works-now is *inconvenient* or *dangerous*.
<ELLIOTTCABLE>
so, what glowcoil's tagging / holes / whatever is, is basically wrapping your solution *around* the current system, instead of replacing it.
<ELLIOTTCABLE>
in the same way that you propose *all* Executions be inherently “call it once, and it's destroyed, with a new one being created next time”,
<ELLIOTTCABLE>
we instead provide a sort of call-it-once *interface* to Executions.
<whitequark>
ELLIOTTCABLE: I told you I do not actually propose that.
<whitequark>
19:17 <+whitequark> half of it was my mis-reasoning, and the other half has *extremely* confusing terminolog
<whitequark>
19:17 <+whitequark> like, it is actually better if you don't read that
<ELLIOTTCABLE>
okay
<whitequark>
19:17 <+whitequark> because we have it bad enough already
<whitequark>
19:17 <+whitequark> basically I accidentally swapped executions and combinations
<ELLIOTTCABLE>
oh, you meant the stuff we'd already talked about, too?
<ELLIOTTCABLE>
okay. cool. so we're on the same page, already, then, lol.
<purr>
lol
<ELLIOTTCABLE>
go ahead.
<whitequark>
well, I went ahead and tried to implement something, that gave me some insight into my ideas
<whitequark>
so basically, Lwt threads I proposed yesterday aren't really equivalent to Paws Executions
<whitequark>
instead, Lwt threads ≡ Combinations.
<whitequark>
Executions would be entirely independent and, yes, still mutable
<ELLIOTTCABLE>
mmmmmm, sounds closer, isn,
<ELLIOTTCABLE>
ish*
<whitequark>
yes
<ELLIOTTCABLE>
alexgordon: hi!
<ELLIOTTCABLE>
alexgordon: sorry, missed that in the conversation
<alexgordon>
ELLIOTTCABLE: hi
<whitequark>
ELLIOTTCABLE: so basically, so far I've replaced your horrible pc-mutating node-traversing stack-push-popping thing with something much simpler.
<whitequark>
and it actually works, even more so, with a direct implementation of term rewriting
<ELLIOTTCABLE>
*direct* impl of rewriting?
<ELLIOTTCABLE>
I would think it would, but remember, that's really messy with mutable Scripts.
<ELLIOTTCABLE>
so remember to account for that in your attempted design changes, even if you aren't implementing any sort of homoiconicity or mutation APIs or whatever
<whitequark>
well, it's a bit cleverly done
<whitequark>
so
<alexgordon>
lol whitequark is micah 2.0
<purr>
lol
<ELLIOTTCABLE>
alexgordon: wat.
<purr>
beep.
<whitequark>
I'm for now explicitly leaving the {} (scripts/executions) thing unexplored
<whitequark>
could as well not exist.
<alexgordon>
whitequark: you think you get it now, but then you'll meet the crushing realization that elliott has other ideas
<whitequark>
alexgordon: if he would have too much, eventually I'll simply stop giving a fuck
<ELLIOTTCABLE>
huh?
<whitequark>
ELLIOTTCABLE: huh what?
<ELLIOTTCABLE>
@ alexgordon
<whitequark>
specify the goddamn context
<ELLIOTTCABLE>
and @ your reply
<whitequark>
well
<ELLIOTTCABLE>
“if he would have too much” what?
<alexgordon>
ELLIOTTCABLE: remember strata?
<whitequark>
I mean, I'll describe my beautiful idea, and you will break it with some usecase I didn't know about
* ELLIOTTCABLE
laughs
<whitequark>
and after that happens a few dozens of times I'll stop caring probably
<ELLIOTTCABLE>
reasonable.
<whitequark>
anyway.
<whitequark>
there is an object called Combination.
<ELLIOTTCABLE>
as in, first-class?
<whitequark>
mm, it will appear in object graph and will be serialized for transfer
<whitequark>
I don't know if that implies that you can somehow explore it, by default
<whitequark>
if yes, then first-class.
<ELLIOTTCABLE>
go on
<whitequark>
ok. Combination has two states (for now. when I actually add {}, there will be a third, I believe.)
<whitequark>
A) Finished(value).
<whitequark>
B) Unfinished(subject, message).
<whitequark>
`value' could be any Paws object. it's simply whatever the combination has evaluated to.
<ELLIOTTCABLE>
yrhyeh
<whitequark>
`subject' and `message' are strictly other Combinations.
<ELLIOTTCABLE>
glowcoil: wake up, you
<ELLIOTTCABLE>
yep, tree approach to Scripts, again, makes sense
<whitequark>
so basically, when you invoke a Script, the VM translates the expression tree into a bunch of nested Combinations
<ELLIOTTCABLE>
how are they “in the object-graph?” suddenly realizing you probably didn't mean by that, what I thought you meant.
<whitequark>
and then, when the VM 'ticks', basically each tick just finds one Unfinished combination which refers to two Finished ones,
<ELLIOTTCABLE>
does a Combination have members, too? i.e. Relations, references to other objects.
<whitequark>
and passes it to receiver.
<whitequark>
ELLIOTTCABLE: I don't see a reason it must be exposed to user code, except debugging
<ELLIOTTCABLE>
okay, so, not first-class, good, makes sense
<ELLIOTTCABLE>
was just mildly confused
<whitequark>
ok
<ELLIOTTCABLE>
mkay, so, several questions:
<ELLIOTTCABLE>
if you're done? sorry. go on, if not.
<whitequark>
hang on, I'll just demonstrate how it works
<whitequark>
for the purpose of the demo, combining Nothing with a Symbol produces that Symbol, and combining two Symbols concatenates them.
<ELLIOTTCABLE>
glowcoil: talking with whitequark has me waffling back towards hole'd execution.
<ELLIOTTCABLE>
glowcoil: fyi.
<ELLIOTTCABLE>
so we'll see how that goes.
<glowcoil>
ELLIOTTCABLE: so basically the "diagonal" shit was just going to be the syntactical way to express the graph (tree)
<ELLIOTTCABLE>
I don't see how.
<whitequark>
ELLIOTTCABLE: so do you see how did I fix your issue here? there's nothing that actively pokes a mutating process
<ELLIOTTCABLE>
it's making it non-tree, more graphy.
<ELLIOTTCABLE>
whitequark: errrrrr, mutation wasn't the issue
<ELLIOTTCABLE>
don't see how fix
<whitequark>
ELLIOTTCABLE: if you combine something with an object, or an execution, or whatever, the caller already knows where to get the result
<whitequark>
because it explicitly binds to that result, as opposed to the result being pushed back by the receiver
<ELLIOTTCABLE>
Hold on, k, reading that a couple times. :P
<ELLIOTTCABLE>
need to climb out of bed and shower soon, fyi
<ELLIOTTCABLE>
then I'll be back
<glowcoil>
i like "combination"
<ELLIOTTCABLE>
but not until I understand this.
<whitequark>
I mean, if you have "a b", the receiver doesn't combine the caller with whatever it wants to respond to "b"
<ELLIOTTCABLE>
glowcoil: yeah, exchanged jux for comb, at least for now
<ELLIOTTCABLE>
glowcoil: read the spec if you haven't, btw
<whitequark>
rather, the receiver essentially mutates the *combination `a b' itself*, setting its value to whatever it wants to respond
<ELLIOTTCABLE>
lot of terminology changes (AGAAAAAIN *rips hair out and screams and dies*)
<whitequark>
and then the next combination *already waits* on this one, because that was preset by the expression-to-combination translation process
<ELLIOTTCABLE>
hold on
<ELLIOTTCABLE>
oh, I getcha, I think
<ELLIOTTCABLE>
I don't think it solves the problem.
<ELLIOTTCABLE>
but let me double-check that i understand, first:
<ELLIOTTCABLE>
errrrrrr, lots of issues here, because it fucks up ordering of operations, I think, errrrrr,
<whitequark>
no, with my fix
* whitequark
patiently waits
<w00f>
[Paws.ml] whitequark pushed 1 new commit to lwt-style-async: http://git.io/QmW13g
<w00f>
Paws.ml/lwt-style-async 286f98d Peter Zotov: Make reduction strictly ordered.
<ELLIOTTCABLE>
so *specifically*, that default receiver for combinations on Objects, instead of re-staging the caller, simply directly modifies the Execution that called it, with a result of the combination.
<ELLIOTTCABLE>
and your new architecture for Executions allows that direct-modification.
<whitequark>
ELLIOTTCABLE: no.
<ELLIOTTCABLE>
ick damn
<whitequark>
in my model, receivers don't even know about executions. I mean, I could add proper custom receivers right now and I don't have any executions at all.
<whitequark>
essentially, you could view it this way: it directly replaces the combination that invoked it with the value which was the result.
<ELLIOTTCABLE>
yes, that I get
<whitequark>
it's basically syntactical. static. it doesn't in any way depend on the state of any hypothetical Execution
<whitequark>
so how doesn't this fix the problem?
<ELLIOTTCABLE>
how does that work for a libside execution? *How* does it replace a combination, in the caller, with ‘a result,’ when it has one?
<whitequark>
or rather, I suppose this could fix only part of the problem
<whitequark>
i.e. how do you write a custom receiver?
<ELLIOTTCABLE>
I must be misunderstanding, because this only seems relevant to native implementations of handlers
<ELLIOTTCABLE>
as opposed to libside implementations
<whitequark>
it's pretty simple actually. basically the receiver would be something that returns a value
<glowcoil>
whitequark: how does this interact with multiple returns
<ELLIOTTCABLE>
or non-returning
<glowcoil>
which is a *big part* of paws
<ELLIOTTCABLE>
I mean, that's the wrong question
<whitequark>
the logic inside the VM which invokes the custom receiver takes care of taking that returned value and putting it inside the combination which invoked the receiver.
<ELLIOTTCABLE>
what does “something that returns a value” even *mean* in the context of the Paws VM?
<whitequark>
ELLIOTTCABLE: yes, or non-returns,
<ELLIOTTCABLE>
okay, so, that makes sense
<ELLIOTTCABLE>
basically, your logic has to be moved post-resume
<whitequark>
in which case the calling combination will never resume.
<ELLIOTTCABLE>
same as our current logic is
<whitequark>
ELLIOTTCABLE: "what does it mean in the context of the Paws VM?"
<whitequark>
I have some ideas about that,
<ELLIOTTCABLE>
when/if the receiver produces a value, it stages the caller, and then *in that process*,
<whitequark>
the least radical of it is simply that the receiver does "infra yield()(value)"
<ELLIOTTCABLE>
the value is injected into the tree of Combinations.
<ELLIOTTCABLE>
or rather could say the Combination is resolved.
<whitequark>
that's a correct way to view it, I suppose.
<whitequark>
except there's no "staging" anymore really
<ELLIOTTCABLE>
… that absolutely makes no sense
<ELLIOTTCABLE>
how so?
<whitequark>
well, there is, except it is merged with other things
<ELLIOTTCABLE>
okay, so, slow down.
<whitequark>
in other words, Finishing a combination allows the Execution which is stuck waiting for that combination to proceed,
<ELLIOTTCABLE>
we can talk more about this later: I frankly don't see how it *changes* anything, seems very much like an implementation detail, for the most part,
<whitequark>
hence, Finishing a combination is equivalent to staging.
<ELLIOTTCABLE>
go on?
<whitequark>
it is not by any means a radical change. it's essentially a reinterpretation of your existing semantics, hence the "implementation detail" vibe you get
<ELLIOTTCABLE>
no, I'm definitely not with you. my fault, not yours, but let me munch.
<ELLIOTTCABLE>
okay.
<ELLIOTTCABLE>
“the execution which is stuck waiting” … define
<whitequark>
well, that sentence refers to what, in your current spec, is defined as unstaging the execution after encountering a combination
<whitequark>
except instead of an explicit staging/unstaging model, in my model whether combinations will be processed is defined by and only by whether it is possible to process them,
<whitequark>
i.e. whether there exist any Unfinished combinations for which both subject and message are Finished.
<ELLIOTTCABLE>
well, that makes sense
<ELLIOTTCABLE>
the term “staging” then refers to the exact same semantics, though.
<ELLIOTTCABLE>
in your implementation, the act of staging would be made a little less confusing, and a little more explicit, so that's nice.
<whitequark>
well, no, if you take natives into account
<whitequark>
since you can't stage an execution at your whim
<whitequark>
you could say I implement your intent a bit more clear.
<ELLIOTTCABLE>
‘staging’ becomes ‘the act of giving a value for a pending Combination’, such that the next combination can be dispatched
<whitequark>
*nod*
<whitequark>
yesyesyes
<ELLIOTTCABLE>
but I don't see how this solves any problems.
<glowcoil>
fuck dude it's terrifying that my credit score can be affected by me forgetting to pay off my credit card, with money that i do have in my checking account, for one day more than i'm supposed to
<ELLIOTTCABLE>
I'm all for term-rewriting as a thingie, trust me.
<ELLIOTTCABLE>
I've long since seen how clean it would be if it were *possible* (again: reservations about mutable Scripts.)
<whitequark>
staging thing doesn't really affect anything, it's an accidental minor cleanup
<ELLIOTTCABLE>
glowcoil: yes. that's why I haven't gotten around to getting a credit card yet. o_o
<whitequark>
I never explicitly intended to modify it.
<ELLIOTTCABLE>
gotcha, so, let me read the scroll back again
<ELLIOTTCABLE>
you mentioned how it fixes something, so let me see if I can suss that out
<whitequark>
yep, it does have a very subtle semantic difference
<glowcoil>
ELLIOTTCABLE: i believe i just incurred a few dollars of interest
<glowcoil>
because the due date was *yesterday*
<glowcoil>
i just really don't want to spend debit cards online yknow
<glowcoil>
etc.
<whitequark>
glowcoil: why do you live on credit?
<whitequark>
oh
<glowcoil>
also building at least a bit of credit score seems important
<glowcoil>
whitequark: yeah i never ever spend w a credit card that i don't haev
<whitequark>
yes, right, forgot about that
<whitequark>
re online: I dunno about USA
<whitequark>
but here if something is stolen from your credit card, the bank security will fuck you in the ass
<whitequark>
i.e. they will pester you for hours on the phone before they give the money back
<whitequark>
and that probably may have some other ramifications
<w00f>
[Paws.ml] whitequark pushed 1 new commit to lwt-style-async: http://git.io/wzjnkQ
<w00f>
Paws.ml/lwt-style-async 6c8e7a4 Peter Zotov: Fix broken nested match.
<whitequark>
and re credit: I don't have a credit card even for that purpose, simply because there are wide instances of abuse by banks
<whitequark>
such as, despite never having any outstanding debt, they will still claim that you do, and keep your account forcibly open, and that apparently counts as a huge negative if you are getting a visa
* glowcoil
nods
<glowcoil>
i'm with a credit union which is hopefully less abusive
<whitequark>
like I want to see bitcoin do well even despite the fact that it is a horrible store of value, banks are basically a bunch of mobsters I wish I would never ever have any business with
<ELLIOTTCABLE>
still don't see it.
<whitequark>
ELLIOTTCABLE: okay so
<ELLIOTTCABLE>
so, obviously there must be some, as you put it, subtle difference,
<ELLIOTTCABLE>
if it solves the issue in question.
<ELLIOTTCABLE>
so let' work backwards
<ELLIOTTCABLE>
show me *how* it solves the issue in question.
<whitequark>
ok
<ELLIOTTCABLE>
code example:
<whitequark>
ELLIOTTCABLE: probably not possible yet
<ELLIOTTCABLE>
not you, me, was going to try and show
<ELLIOTTCABLE>
with pseudo-code / pseudo-paws
<whitequark>
lemme explain. I don't fully have a mental model for executions
<ELLIOTTCABLE>
okay
<whitequark>
so let me rather just say what it does fix
<whitequark>
basically, say, you have an Execution, executing `foo bar baz'
<glowcoil>
yeah in theory i like cryptocurrencies
<glowcoil>
but not ones that are inherently pyramid schemes
<whitequark>
so it just evaluated `Nothing foo' and is now evaluating `<foo> bar'
<whitequark>
it unstages (I'm demonstrating the issue on spec-Paws) the current execution and stages the custom receiver of <foo>,
<whitequark>
which happens to be a bunch of Paws code.
<whitequark>
now, *something entirely else*, possibly just unrelated, possibly invoked by the custom receiver before it returns, invokes the execution which was just unstaged.
<whitequark>
and all hell breaks loose; nothing that happens in it makes sense anymore.
<whitequark>
because whatever it was invoked with, will now be combined with `bar'.
<whitequark>
in my scheme, that's not possible.
<whitequark>
do you see it?
<whitequark>
I mean, you could say that you can work around that with higher-level code, but I think it's nice to have a VM which behaves consistently :p
<ELLIOTTCABLE>
hold on slow down reading
<ELLIOTTCABLE>
never forget that ELLIOTTCABLE is dumb
<ELLIOTTCABLE>
well, you described the problem, but not how it's prevented by your scheme, at all.
<ELLIOTTCABLE>
:
<whitequark>
what does that : mean ?
<ELLIOTTCABLE>
(rather agreed, about the consistency thing. or, rephrase, YES I KNOW THIS IS PROBABLY A PROBLEM)
<glowcoil>
whitequark: emote
<whitequark>
lol good, my work wasn't in vain them
<purr>
lol
<whitequark>
*then
<glowcoil>
w no mouth?
<ELLIOTTCABLE>
(just remember that, to me, *complicating* the core language is anathema. It just shows *how much* I am concerned about this issue, that I would even *consider* adding something like Holes to the language we have.)
<whitequark>
ELLIOTTCABLE: so it's very simple
<whitequark>
yes yes I agree about complicating
<whitequark>
Paws shouldn't get more complex than it is, this is 100% my design constraint
<ELLIOTTCABLE>
If your minor change in semantics here actually solved it, that'd be spectacular
<ELLIOTTCABLE>
I just still don't see how it does :P
<whitequark>
ok, so
<ELLIOTTCABLE>
oh, it will.
<ELLIOTTCABLE>
it *absolutely* will.
<whitequark>
\o/
<ELLIOTTCABLE>
The problem is, my complexity has a *budget*
<ELLIOTTCABLE>
and I've got huge, huge writeoffs coming for distribution and time-travel.
<whitequark>
oh, you didn't mean you got my solution
<whitequark>
sure, sure
<ELLIOTTCABLE>
LOL
<whitequark>
I know
<whitequark>
explaining then.
<ELLIOTTCABLE>
“it absolutely will!” <excitement>
<ELLIOTTCABLE>
okay listening
<whitequark>
in wq-Paws, unlike in spec-Paws, the receiver is not communicating back the result of combination by re-staging the execution (aka combining the execution with a message)
<whitequark>
since these two are independent processes not using any shared resource, they cannot interfere with each other.
<whitequark>
in more practical terms, this means that the Execution is now (only/mainly) a unit of communication,
<ELLIOTTCABLE>
oh. that change is *completely* independent from what you've been describing.
<ELLIOTTCABLE>
you're basically talking about what issue, uhhh,
<ELLIOTTCABLE>
just with different words and a different reason.
<whitequark>
um, no, it's not about performance. it's about communication between executions.
<ELLIOTTCABLE>
yes I know
<ELLIOTTCABLE>
I know I know
<whitequark>
basically, you now have the same mechanism responsible for two things
<ELLIOTTCABLE>
but it's the *same discussion* in a way
<whitequark>
getting back the result of combination and communication between executions
<whitequark>
I just untangled them
<ELLIOTTCABLE>
hold on hold on.
<whitequark>
ok
<ELLIOTTCABLE>
of *course* executing some subset of receivers “on the stack” so to speak (without going through the staging queue, or any form thereof), would make **those** receivers not susceptible to interception (the name for the problem we're dealing with).
<ELLIOTTCABLE>
but A) there's problems with doing so, (get there in a sec), and more importantly B) that *doesn't solve the problem overall*. Just for the most common **instance** of the problem.
<ELLIOTTCABLE>
let's not talk about receivers for a moment.
<whitequark>
yep, I told you it probably was solving only part of the problem
<ELLIOTTCABLE>
the *canonical* example of interception is a situation like this:
<ELLIOTTCABLE>
xec AA “calls” xec MM. Call-pattern involves unstaging, so AA is waiting for a ‘return value’, synchronous-style, for from MM.
<ELLIOTTCABLE>
xec AA is *also* designed to wait, in a queue, for coroutine-style resumption with work-to-do.
<ELLIOTTCABLE>
however, *in this particular instance*, instead of AA being paused at one of the ‘holes’ where it expects results from that queue, it just **happens** to be waiting for a response from MM …
<whitequark>
yesyesyes this is the same exact problem I am talking about
<whitequark>
you just didn't listen to the end
<ELLIOTTCABLE>
… so when the queue-handler, BB, calls AA with a value, that value is dropped into the hole expecting a return from MM.
<ELLIOTTCABLE>
mkay
<whitequark>
please do realize that when you call MM, you combine MM with something
<ELLIOTTCABLE>
mmhmm
<whitequark>
and when MM `returns' that something to you, it also goes through the same mechanism I just described.
<ELLIOTTCABLE>
er
<ELLIOTTCABLE>
same <something> in above two sentences? not making sense
<whitequark>
er, different
<ELLIOTTCABLE>
why would the result be the same as the ‘something’ you combined to it?
<ELLIOTTCABLE>
okay thought so, just checking
<whitequark>
basically, when AA calls MM, nothing else can physically interfere here, because of what I described above
<ELLIOTTCABLE>
I don't see how.
<whitequark>
how it would?
<ELLIOTTCABLE>
AA calls MM, MM takes five minutes to make a network request on a very very slow network …
<ELLIOTTCABLE>
Paws is asynchronous, at all junctures, that's Sort Of The Point™ of the entire project, bottom to top, every nook and cranny …
* ELLIOTTCABLE
re-reads your suggestions again
<whitequark>
ooooooh I think I realize
<whitequark>
in old-Paws, after AA called MM, it would be unstaged, but *something else* could stage it and in theory make it do useful work.
<whitequark>
isn't it?
<ELLIOTTCABLE>
basically, you're suggesting that we make all of paws non-asynch (or, a subset of paws, such as “just receivers,” which is just as bad to me), as far as I can tell :x
<ELLIOTTCABLE>
'course, yeah
<whitequark>
right.
<ELLIOTTCABLE>
AA can do useful-work for multiple sources-of-work. That's what staging is, I suppose, at some sort of high, conceptual, level. Providing work to be done.
<whitequark>
the patch I just put in was wrong.
<whitequark>
sure.
<ELLIOTTCABLE>
problem is interleaving the sources-of-work.
<whitequark>
*my* solution to that is to remove the sequencing restriction from Execution.
<whitequark>
i.e. *that* combination with MM will still wait, but other combinations in AA will proceed.
<ELLIOTTCABLE>
for instance, the *result* of a simple function call (the simplest example of interception-problem), which is what you were endeavoring to fix, is a source-of-work in a way
<ELLIOTTCABLE>
errrrrrrrrrrrrrrrrr
<ELLIOTTCABLE>
yes, that's a verrrrry big change, and requires a lot of redesign work
<ELLIOTTCABLE>
that's also what micah wanted
<ELLIOTTCABLE>
but, and here's the key,
<ELLIOTTCABLE>
that solution is two things, conflated:
<whitequark>
I believe that your current scheme is internally inconsistent, and the "interference" you're seeing is just the result of that inconsistency
<whitequark>
so, in my view, there's no way to avoid this or similar change.
<ELLIOTTCABLE>
A) basically, another way of doing ‘holes’ (the *place* that a particular combination-result will be placed, still has to somehow be identified or named or key'd),
<whitequark>
hm.
<ELLIOTTCABLE>
and B) finding a way to ‘speed things up’ so to speak, by concurrentifying *more* things within a Script
<whitequark>
nonononono, you're wrong about B)
<whitequark>
absolutely wrong.
<ELLIOTTCABLE>
(i.e. when a particular Hole isn't filled yet, finding a way that that *doesn't* have to mean that we can't process any *other* holes.)
<ELLIOTTCABLE>
how so?
<whitequark>
basically, the `speeding things up' was already present in spec-Paws.
<whitequark>
compare this:
<whitequark>
A) in spec-Paws, Execution gets processed by reactor when it it staged, either by result from MM or a request from (say) QQ, ...
<whitequark>
B) in wq-Paws, Execution gets processed by VM when there is an available result from MM or a request from QQ.
<ELLIOTTCABLE>
same thing
<ELLIOTTCABLE>
how's different?
<whitequark>
*exactly*
<whitequark>
wq-Paws don't "concurrentify" more things than spec-Paws already does
<ELLIOTTCABLE>
well duh, I know that
<ELLIOTTCABLE>
but your design isn't fixing anything except, and only sometimes even this, receivers. it's special-casing native receivers to not be intercepted.
<whitequark>
what?
<ELLIOTTCABLE>
unless I'm still missing something.
<whitequark>
it absolutely does not special case native receivers in any way.
<whitequark>
it is *all about* Paws code.
<whitequark>
I don't even *have* any native code to think about.
<ELLIOTTCABLE>
then I'm clearly confused :x
<ELLIOTTCABLE>
ickickickickick
<ELLIOTTCABLE>
glowcoil: YOU WITH THE WORDS, COME TRANSLATE
<whitequark>
it fixes, for starters, an issue where Paws script calls an object with a Paws receiver
<whitequark>
because native receivers, *by definition*, will not be interleaved with *anything*
<ELLIOTTCABLE>
I need to shower and procure food, I'm *starving*. Thought this discussion would reach a stopping-point sooner
<ELLIOTTCABLE>
I'mma have to afk, for a bit. Be back soon?
<whitequark>
ELLIOTTCABLE: I need that too
<whitequark>
so, let's go get some water and food.
<w00f>
[Paws.ml] whitequark force-pushed lwt-style-async from 6c8e7a4 to 4290ae5: http://git.io/VxNktw
<glowcoil>
ELLIOTTCABLE: THAT'S WHY WE NEED TO LOOK AT A WHOLE PROGRAM NOT AS DIVIDED UP INTO EXECUTIONS BUT A BIG OLD DEPENDENCY GRAPH, AND EVERYTHING YOU HAVE A HANDLE ON IS A HOLE
<glowcoil>
ELLIOTTCABLE: SO CALLING THE SAME THING TWICE WILL NEVER PUT IT INTO A DIFFERENT HOLE
<ELLIOTTCABLE>
I don't want *everything* you have to be a hole.
<ELLIOTTCABLE>
I still want indiscriminate resumption, in places where the pausing was indiscriminate.
<ELLIOTTCABLE>
just gotta figure out a way to reconcile the two.
<glowcoil>
ELLIOTTCABLE: you can make it userspace
<glowcoil>
ELLIOTTCABLE: the same hole results in different things based on state
<glowcoil>
that is entirely possible
<ELLIOTTCABLE>
hm?
<glowcoil>
but you *choose* to do it rather than it accidntally fucking things up
<glowcoil>
watch:
<glowcoil>
{ a <- <HOLE>
<glowcoil>
case some state:
<glowcoil>
OSMETHING: print a
<glowcoil>
SOMETHING ELSE: shit your pants
<glowcoil>
}
<ELLIOTTCABLE>
that's not, exactly, my issue.
<ELLIOTTCABLE>
hmmmmmmm
<ELLIOTTCABLE>
I should really be in the shower i suck at life
upgrayeddd has quit [Quit: Connection closed for inactivity]
<glowcoil>
it returns a *different hole*
<whitequark>
ELLIOTTCABLE: eh don't listen to glowcoil
<whitequark>
listen to me
<whitequark>
so basically, I got it.
<glowcoil>
whitequark: this makes things ridiculously cleaner
<glowcoil>
whitequark: but i'm very wiling to admit you have a deeper understadning
<whitequark>
glowcoil: I guess that also makes it unpawsy and hence irrelevant
<glowcoil>
whitequark: ...lol
<purr>
lol
<ELLIOTTCABLE>
no, I'm very open to glowcoil's thoughts
<ELLIOTTCABLE>
we've discussed this at some length, before,
<whitequark>
ELLIOTTCABLE: hang on
<whitequark>
I believe I understand what he means and considered this too
<ELLIOTTCABLE>
I'm very turned off by adding to the Script representation.
<whitequark>
so.
<whitequark>
(no, I'm not adding anything to the Script.)
<glowcoil>
so actually i guess every "function"/"hole" you're holding *is* a continuation
<glowcoil>
not delimited because it has to call back to give you a value
<ELLIOTTCABLE>
whitequark: not you, glowcoil
<glowcoil>
but there's built-in call/cc
<ELLIOTTCABLE>
go on
<glowcoil>
no whitequark can explain
<whitequark>
uhh
<whitequark>
lemme explain.
<glowcoil>
i haven't fully understood what he proposes really
<ELLIOTTCABLE>
I mean, whitequark, go on
<glowcoil>
yeah do taht
<whitequark>
glowcoil: obviously, I didnt even start
<whitequark>
so
<whitequark>
your systemic problem is that Execution is, fundamentally, a mailbox,
<whitequark>
and the operation to fetch messages from that mailbox is implicit and unavoidable.
<whitequark>
this directly results in the receiver-fiasco I fixed,
<whitequark>
and in the interference-fiasco I did not, as you've entirely correctly noticed, in fact fix.
<ELLIOTTCABLE>
hey before you go on
<ELLIOTTCABLE>
side-note, just so you're on the same page, and we're all considering the same problems:
<whitequark>
continuing. your systemic problem is that Execution is a mailbox, because you want everything to be asynchronous in the sense that you can drop a message and possibly do anything else,
<glowcoil>
NOW I'M ALL MESSED UP
<glowcoil>
SICK AND TIRED OF WONDERING WHERE
<glowcoil>
WHERE YOU'RE LEAVING YOUR MAKEUP
<ELLIOTTCABLE>
not a bad description, bteedubstep
<glowcoil>
GO
<glowcoil>
GO
<glowcoil>
GO IF YOU WANT
<glowcoil>
HOW CAN I STOP YOU
<whitequark>
what the fuck is happening here
<ELLIOTTCABLE>
glowcoil is singing, because he's glowcoil,
<ELLIOTTCABLE>
and you're explaining something. gogogo.
<whitequark>
glowcoil: please temporarily don't do that
<whitequark>
ELLIOTTCABLE: waiting for your side-note
<ELLIOTTCABLE>
oh
<ELLIOTTCABLE>
you said ‘continuing’
<ELLIOTTCABLE>
okay:
<whitequark>
well I was typing it earlier
<ELLIOTTCABLE>
I know you dismissed the GH issue I linked as irrelevant, but it *does* bring up the second problem I had with your other solution, there: if we take ‘receivers’ out of the queue (for any reason, for the reason the issue is discussion, *or* for your reason),
<ELLIOTTCABLE>
then I'm really worried about the concurrency side-effects. The queue is a centralized, ALL-POWERFUL place that controls ordering.
<ELLIOTTCABLE>
I realllllly need to get nasty with the details and figure out whether it's possible for it to actually cause problems for receivers to jump the queue, but … I suspect it is. So I need to look into that in detail. And, at the moment, I don't like the idea, because of those fears.
<ELLIOTTCABLE>
just so you're on the same page I'm on, on the topic.
<whitequark>
no, receivers aren't entirely taken out of the queue.
<whitequark>
only *the returning of the value* from a receiver gets taken off the queue,
<whitequark>
and in fact in my new proposal that probably won't happen anyway.
<ELLIOTTCABLE>
go on
<whitequark>
so. (putting this back) your systemic problem is that Execution is a mailbox, because you want everything to be asynchronous in the sense that you can drop a message and possibly do anything else,
<whitequark>
but in several places, e.g. the combination-receiver interface, the interference issue you've mentioned, and possibly other places too, what you want is a request-reply pattern.
<ELLIOTTCABLE>
mmhmm
<whitequark>
a pattern for controlled blocking, essentially.
<ELLIOTTCABLE>
problem boils down to:
<whitequark>
no, don't
<ELLIOTTCABLE>
A) me wanting a request-reply pattern that doesn't add *too much* complexity,
<whitequark>
ok, yes, A)
<whitequark>
continue then
<ELLIOTTCABLE>
and B) me wanting both to be available. request-reply and mailbox.
<whitequark>
yeah, that's exactly what I was thinking about.
<ELLIOTTCABLE>
kk assumed as much
<ELLIOTTCABLE>
just clarifying go on
<whitequark>
I believe I have the most minimalistic sane way to do exactly A) and B), I'm thinking in exact same terms.
<whitequark>
so I'll cut to the chase.
<whitequark>
we make combinations first-class. we already have executions first-class. then, we combine them to get both mailbox and request-reply.
<whitequark>
elaborating:
<ELLIOTTCABLE>
(pretty close to holes, sounding, go on)
<whitequark>
1) the receiver will not get an "execution" caller. rather, it will get a "combination" caller. when it wants to return, it combines the combination it just got with the value it wants to return.
<whitequark>
2) when you combine an execution with something, it doesn't interfere with its normal processing. rather, it (the calling combination, again, and the message) gets posted into an (explicit) mailbox associated with the execution.
<whitequark>
when the execution wants to get a message, it invokes `() get' or `infra get ()' or something, which basically returns the incoming thingy.
<purr>
<sullytaylor> I just spent three minuits looking for somthing, then I realised it was in my mouth
<whitequark>
brb, food needs attention
<ELLIOTTCABLE>
so, yes, implicit, passed holes, with explicit general-yield.
<ELLIOTTCABLE>
so, glowcoil, you remember your suggestions here, and the objections I raised, I presume?
<ELLIOTTCABLE>
two really big problems here, for me, well, almost the same problem, but two aspects of it:
<ELLIOTTCABLE>
oh, of note, first:
<whitequark>
btw, I finished
<whitequark>
there's no 3). I thought there was, but there isn't
<ELLIOTTCABLE>
so, first, I guess I need to validate / ensure, that holes and this are the same thing. So we can sanely talk about it. Best to sync-up before processing more data.
<glowcoil>
whitequark: i feel like we don't need executions to be a thing
<glowcoil>
whitequark: they can emerge as particular organizations of the graph
<ELLIOTTCABLE>
glowcoil: save for later?
<glowcoil>
ELLIOTTCABLE: thought i was being perfectly relevant?
<ELLIOTTCABLE>
hole is a first-class representation of a *particular* pending-resumption of an execution.
<ELLIOTTCABLE>
glowcoil: then I must not understand it :P
<ELLIOTTCABLE>
taking a hole *out* of an execution, implicitly prevents that execution from continuing until the now-first-class hole is filled.
<glowcoil>
well i think executions are too linear
<glowcoil>
we shouldn't think of a program as a bunch of executions
<glowcoil>
it makes things all lumpy
<ELLIOTTCABLE>
wat
<glowcoil>
like,
<glowcoil>
weird implicit dependency shit
<glowcoil>
a program is:
<glowcoil>
a graph of dependencies
<ELLIOTTCABLE>
that's probably the least coherent objection to Paws I've ever heard, by the way. congratulations new record.
<glowcoil>
a tree with y combinator or whatever like whitequark said
<glowcoil>
or whatever
<glowcoil>
but like
<ELLIOTTCABLE>
“it makes it lumpy.” <3
<glowcoil>
you can have things that depend on completion, or on values
<glowcoil>
but like, writing {} would only be a syntactic tool for expressing graphs
<ELLIOTTCABLE>
wat
<ELLIOTTCABLE>
all going over my head. *specific* suggestions.
<glowcoil>
like
<ELLIOTTCABLE>
what're you saying we change? give me examples.
<glowcoil>
stop making executions even a thing
<glowcoil>
they're not values
<glowcoil>
they're not types
<ELLIOTTCABLE>
all this CS stuff is both over my head, *and* not of interest to me.
<glowcoil>
the thing you can *hold*
<glowcoil>
is a hole
<glowcoil>
a continuation basically
<ELLIOTTCABLE>
I get that.
<ELLIOTTCABLE>
idsee how holes == continuations, at all,
<ELLIOTTCABLE>
but before you explain that,
<ELLIOTTCABLE>
all I can see that you're suggesting is that we require *all* resumptions to be of a particular hole, instead of of either a particular hole, or in general of an execution.
<ELLIOTTCABLE>
yes?
<glowcoil>
yes
<glowcoil>
like insisting on having executions be a thing is needless complexity
<ELLIOTTCABLE>
I believe the opposite to be true,
<glowcoil>
having only holes vastly simplifies the whole thing, and resolves *every* problem you're having
<ELLIOTTCABLE>
but sans ‘needless.’
<whitequark>
glowcoil: re unnecessary executions: not convinced really
<ELLIOTTCABLE>
No, it doesn't.
<ELLIOTTCABLE>
It *does* resolve a lot of problems, but it's also a **very different language**.
<whitequark>
ELLIOTTCABLE: please on my suggestions.
<glowcoil>
it's not at all a different language
<ELLIOTTCABLE>
whitequark: huh?
<whitequark>
er, please comment
<ELLIOTTCABLE>
hold on one at a time, glowcoil's grabbed my attention, lemme try and coherently respond
* whitequark
sighs
<ELLIOTTCABLE>
SAWWWWY I WILL GO RE-READ IN A SEC
<whitequark>
it's just that glowcoil's objections are very similar to mine
<whitequark>
but ok
<ELLIOTTCABLE>
okay jesus, glowcoil, you'll have to wait a sec, then. whitequarking.
<ELLIOTTCABLE>
yes you're a verb.
<whitequark>
I mean, it's like, the suggestion I laid out really addresses quite a bit of glowcoil's objections
<ELLIOTTCABLE>
Yesyesyes I know, hold on
<whitequark>
without using terms that aggravate ec
<ELLIOTTCABLE>
it addresses all of them, basically, because it's the same thing
<ELLIOTTCABLE>
and, for the sake of continuity with previous discussions, I'm just going to keep calling this ‘holes.’
<whitequark>
ELLIOTTCABLE: I disagree with both points
<ELLIOTTCABLE>
?
<whitequark>
I think they're not same and maybe calling them holes would hence be confusing
<ELLIOTTCABLE>
that's *really*, at least as I see it, a pedantic difference.
<ELLIOTTCABLE>
Either you only have pends *sometimes*, in which case executions are still somehow accessible and usable, or you have them *all* the time, in which executions are invisible, and basically an implementation detail.
<ELLIOTTCABLE>
i.e. how I read micah's suggestion.
<ELLIOTTCABLE>
but, back up. just, hold on.
<Rusky>
how would you use an execution without pends?
<ELLIOTTCABLE>
can't wrap my head around the problem I'm trying to convey
<ELLIOTTCABLE>
Paws discussions always make me feel impossibly, unreasonably dumb.
<ELLIOTTCABLE>
first off, with pends *or* holes, there's another necessary change, or part of the puzzle, that hasn't been discussed at all.
<ELLIOTTCABLE>
micah always bugged me about this: naming.
<ELLIOTTCABLE>
if we pass a given “handler procedure” to, say, a server routine … as a random example, something that handles HTTP requests, or something … whatever. If we pass a handler in, and store it in a queue as one possible thing to resume *later* with a value to be handled, how do we say **at which point** in that execution, the resumer's
<ELLIOTTCABLE>
value-to-be-handled will go?
<ELLIOTTCABLE>
badly written. ugh.
<ELLIOTTCABLE>
okay. with traditional coroutines, there's an element of syntax that says “here, here, and here are where I put incoming values.” `yield` and similar constructs.
<whitequark>
oh my god this pork is *delicious*
<Rusky>
with coroutines, you'd be passing in a stateful/mutable object that could potentially be resumed while it's sitting in the queue, changing where the server will resume to
<whitequark>
I love my cooking so much
<ELLIOTTCABLE>
that's intimately tied into a discussion of holes, or of these: How do I get a handle on *a later hole* for an execution? If there's an element of syntax, we can do that by names, but I hate adding syntax; and if there's *not* a way to do that (i.e. no syntax, unless somebody can think of a way to do it only with semantics), then there's no way to do that at
<ELLIOTTCABLE>
all.
<ELLIOTTCABLE>
Rusky: yes.
<ELLIOTTCABLE>
Rusky: that's **exactly** the problem we're discussing, and that micah hopes to solve with holes, and whitequark with his stuff.
<whitequark>
ELLIOTTCABLE: my answer to this: same as earlier. you used to get a handle of execution *somehow*
<ELLIOTTCABLE>
it's called interception.
<ELLIOTTCABLE>
whitequark: yah, I get that.
<whitequark>
now, if you don't have a specific pend to put your result in, you just post it to the execution mailbox
<Rusky>
so do you want to allow interception, or ban it, or both
<Rusky>
by both I mean make it depend on the implementation of the resumee
<ELLIOTTCABLE>
Rusky: I want to allow a way around it. In Paws, as with coroutines, it's a problem right now … but that problem is *literally everywhere*, because literally everything is asynchronous like that.
<ELLIOTTCABLE>
Rusky: like, with Paws, the *result of a function call* is a coconsumption just like that.
<ELLIOTTCABLE>
Rusky: which means somebody somewhere else could intercept the routine in question, and the value it's trying to pass in gets used as the “result of the call to X procedure.” Very very bad.
<Rusky>
like you hand the function you're calling a handle to resume you, which is actually async?
<ELLIOTTCABLE>
Rusky: yep, that's paws in a single-line nutshell.
<ELLIOTTCABLE>
or at least the Paws machine we're designing here.
<Rusky>
and then somebody else could get that handle as well and say "haha take this instead of what you really expected"
<ELLIOTTCABLE>
there's ways around it WITHOUT all of this, just to remind everybody present.
<whitequark>
ELLIOTTCABLE: so basically, the only difference that instead of being resumed at whatever place, the execution will be resumed at any pending `infra getmail()' call
<ELLIOTTCABLE>
I'm still not sold on *any* of these, even after this conversation, I intend to explore examples of solving it using only ownership.
<ELLIOTTCABLE>
But, for now, I'm very pro-holes, at least compared to where I have been in the past.
<ELLIOTTCABLE>
whitequark: yah, I understand, believe me
<ELLIOTTCABLE>
so. back to what I was saying pre-rusky.
<ELLIOTTCABLE>
trying to express my issues with this.
<Rusky>
I CAN ALTER THE COURSE OF THE PAWSIVERSE
<ELLIOTTCABLE>
Hey. Guys.
<ELLIOTTCABLE>
I'm sorry to disrupt, but I'm moving us. This tears me to pieces, because I love the life that Paws-discussions bring to my little community, and all, but,
<ELLIOTTCABLE>
/join #Paws.Nucleus
<ELLIOTTCABLE>
Sorry for the trouble. I have good reason, believe me. /=
<ELLIOTTCABLE>
alexgordon, glowcoil
<glowcoil>
ELLIOTTCABLE: it should just be ##paws
<glowcoil>
ELLIOTTCABLE: everyone will be chill with that
<glowcoil>
ELLIOTTCABLE: imo
* alexgordon
is in ##paws
<alexgordon>
and that other place
<ELLIOTTCABLE>
##Paws is dead, you can leave that.
<ELLIOTTCABLE>
It was “off-topic discussion by the developers of Paws.” That's #ELLIOTTCABLE now, clearly. :P
<ELLIOTTCABLE>
and #Paws is taken, so .Nucleus it is.
<ELLIOTTCABLE>
I'll ask Freenode, later, I guess.
<ELLIOTTCABLE>
this'll do, for now.
<purr>
<prophile> is the Y combinator defined on boobs?
yorick has quit [Remote host closed the connection]