« first day (523 days earlier)      last day (123 days later) » 

09:15
am i the only one that thinks the answer to those recent CPS questions are all sorta lackluster
<https://langdev.stackexchange.com/questions/2079/what-are-the-disadvantages-of-using-cps-form> no offence to davislor, it's a very good answer, but i feel like there's a lot more to explore there
maybe i'll see if i can find the time to add some more
09:43
I agree that the recent CPS question has not really gotten a good answer, but I don’t think I know enough offhand to write a good one, and I haven’t taken the time to do the necessary research
But it would definitely be good if someone did
yeah, would be
I think my immediate response to the recent question is that a good answer should explain the difference between using CPS as an intermediate representation and using CPS as your actual runtime strategy
i have a hunch CPS is going to be more interesting (as a strategy) as/if effect systems start becoming more popular (especially now that OCaml has effects)
That may be true, though I think native delimited continuations seem to be growing in popularity, and I think there are lots of advantages to them over CPS (source: I added them to GHC specifically because of those advantages; people have been doing CPS in Haskell to implement them for a very long time)
I do think the fact that CPS is used to mean several different things (compiler IR, language runtime strategy, library implementation strategy) is a frequent source of confusion
yeah delimited continuations do have their benefits (very cool work btw haha)
@AlexisKing absolutely
09:49
It would be nice to have a canonical Q&A that thoroughly explains the distinction and talks about both Compiling with Continuations (and related work) and various implementations
I don't think there's been a useful "non-lisp" language that's gone full runtime-CPS yet, so I definitely would like to see how that might stack up perf wise against something like OCaml, but there are obvious downsides besides perf
@AlexisKing if/when I have some free time I might be able to draft up something like this, i've been reading the related works quite a bit recently
although I don't have access to a copy of the original unfortunately, so someone else might have to step in there
@blueberry Yes, I think if I were to write such an answer I would probably essentially make the case that going full runtime CPS is largely considered a toy strategy (albeit one with certain benefits if you care about making a very simple system) and is not usually what people mean when they talk about “compiling to CPS”
@blueberry That would be great! :)
As a GHC person I think I’m biased against CPS as an IR (and there’s even a tongue-in-cheek GHC paper called Compiling Without Continuations), but I’d find it very interesting to see a perspective from someone who favors it
@AlexisKing which is rather unfortunate really, because "easy" stackless execution lets you do some really neat "tricks" in the realm of async-by-default languages and effects, but alas
I do think it’s interesting that Rust async/await and similar systems basically work that way, and that would be interesting to discuss as well
Rust is a particularly interesting implementation because it is basically compiled as CPS, but because it uses structs to represent the environment, there’s a lot more copying rather than pointer chasing, which has very different tradeoffs relative to most CPS implementations
it's not quite defunctionalized CPS, but it's vaguely close I think
in a certain sense of the word
09:57
Yeah, I can agree with that
but yeah no, if your default execution model is "frequently pausing and resuming processes", you ideally want to make that as seamless as possible - no need to do stack shuffling if there's no stack
I think lightweight stackful coroutines are still pretty seamless (Go and GHC use them, and they work quite well), but they do require a runtime and a GC (because they rely on being able to move stacks to grow them)
There are definitely different tradeoffs. It’s honestly very unclear to me which approach I’d prefer in general
One of the amusing things about Rust async/await is that it can be necessary to manually introduce Box to break up the context to avoid having to copy around an absolutely massive struct every time the coroutine yields
i'm currently working on something that would ideally mirror Erlang and Go in the "auto-async" department and have been looking into CPS-likes for a runtime scheme, so I'll report back on that, but I am keeping my hopes medium-ish
@AlexisKing async rust really does fall into the Box-hole a lot, huh
I don’t actually know anything about Erlang async; I think I just assumed it did everything with actors
yeah basically
what Erlang has going is what we would now call "Async", as far as I am aware
every N reduction steps (VM perks) your current process/actor gets swapped out for a different one that's on the run queue
10:05
I think there’s a pretty big difference between actors and async/await? There’s no await in the actor model!
My mental model of systems with true concurrency (i.e. not JavaScript) and async/await is essentially CSP with extensions, whereas I think of the Erlang model as fundamentally different (in ways with its own tradeoffs)
apologies - give me a moment, am thinking haha
what await does is yield control while you wait for a computation to run, right
in erlang that's automagic; you never yield control yourself, control is yoinked out from under you
when you take processes into account, and message passing, it basically does turn into several "communicating" processes, all running "on their own"
I think you’re just describing that Erlang concurrency is preemptive rather than cooperatively scheduled, which is true, but also applies to, say, Go or even .NET Tasks
I mean, yeah? I'm sorry I don't quite follow
I just don’t think that has much to do with async/await per se (though in practice many async/await implementations do use cooperative scheduling for various reasons, and I think that’s what popularized the async/await terminology)
@AlexisKing In response to this - why is Erlang fundamentally different, then? I think that's what I'm not quite following
10:13
Because Erlang doesn’t use CSP, it uses the actor model!
I'm reading the wikipedia page for CSP and it seems like something that Erlang can very much do
Erlang doesn’t have rendezvous channels to my knowledge
ah, that's the difference
ok, I see what you mean now yeah
right ok
hm
I also don’t think Erlang has the ability to have a “channel” as distinct from a process, right? Like, you can emulate it with a process that pumps messages, but that has different characteristics
yeah
alright yeah, that makes sense - thank you for the explanation, I appreciate it
10:17
I usually think of the Erlang model as in some sense being more first-order because everything is explicitly stratified into processes, which is what allows those processes to be automatically distributed (which is something CSP can’t really do)
And yeah, glad it was helpful :)
@AlexisKing that sounds right to me
and indeed is one of the big benefits of "the actor model"
I think one way to think about that is that in Erlang you have to do the defunctionalization yourself
(i quote it because i've been told "the actor model" has about four different definitions, depending on who you're talking to)
ah apologies, I have to run
Yeah, I’m definitely not an expert on anything Erlang related, but I had the opportunity to chat with some Erlang people last year and they helped me understand it a bit better
See you around!
nice to talk to you! and yeah i'll try to see what I can do with that CPS stuff
10:20
as I understand it, the difference is: async/await keeps the current stack and resumes there, but Erlang awaits the next message statelessly
I tried to dig into the erlang code not too long ago, wish I had some people to guide me haha
you can tell parts of it are pushing 30
@EldritchConundrum Right, this is what I meant by “you have to do the defunctionalization yourself”
hmm.. I don't understand it like that yet.
thanks for this interesting conversation. I really hope someone will write the post explaining the meanings of CPS
@AlexisKing I’m actually looking into this now, and I think I (and by extension @EldritchConundrum) might be wrong about this, because it seems like a receive expression is allowed to have context that has to be saved if the process suspends. I guess I’m not sure how serialization works in that case
10:37
After a little more investigation, it seems like Erlang processes are in fact stackful, so they’re basically just lightweight threads, and the main restriction is just that sends never block. As far as I can tell, if a new version of a module is loaded, existing processes continue to run the old code until they return from whatever function they’re currently suspended in.
That’s actually a little more liberal than I’d realized—I was under the impression that receive was more restricted.
same. I should try actually using Erlang sometime... I've been putting this off for so many years
11:12
@AlexisKing yeah! you can do a lot with it
i don’t see why you couldn’t model async/await in erlang (although i think it would be a pretty bad idea)
hm might have issues with argument lists though
 
3 hours later…
14:25
@EldritchConundrum It was actually one of my first functional languages, even though I never really learned how to do most of the actor stuff that makes it actually worth using
Fun memories
@EldritchConundrum same lol
@AlexisKing i happen to know that koltin coroutines (basically async/await) use CPS too
15:16
I am going to be physically at LIVE all day, but IWACO probably interests some people here, and there are some interesting-looking slots in SLE and SAS too
15:32
yeah IWACO looks interesting
15:55
It is in the room next door to me and I may sneak over once or twice
The effects one and the visualisation one in particular look good
 
4 hours later…
19:46
eyyy my a-language-something-like-c to Chef compiler just compiled its first line of code!
the code
@entry
fun main() {
    let a = 1 + 1;
}
was compiled to the Chef code
test.

Ingredients.
a
0 b
1 c
d
e
f
h
i
j
k

Method.
Put b into mixing bowl.
Fold a into mixing bowl.
Put c into 5th mixing bowl.
Put a into mixing bowl.
Remove c from mixing bowl.
Fold d into mixing bowl.
V the d.
Put b into 6th mixing bowl.
Remove c from 6th mixing bowl.
Put c into 6th mixing bowl.
Stir d into the 6th mixing bowl.
Fold e into 6th mixing bowl.
Fold e into 6th mixing bowl.
Put e into mixing bowl.
Set aside.
V until ved.
Put c into 6th mixing bowl.
Put b into 6th mixing bowl.
Stir d into the 6th mixing bowl.
the intermediate is
def $state 0;
def @returns;
@returns.push 1;
while {
  push $state;
  lt 1;
} {
  push $state;
  eq 0;
  if {
    def $ap0t6d9db2c35480dbcd;
    push 1;
    push 1;
    add { nop; };
    pop $ap0t6d9db2c35480dbcd;
    del $ap0t6d9db2c35480dbcd;
    @returns.pop $state;
  };
};
20:43
NICE??
21:23
Uhh... Is that akin to Haskell's when :: Applicative m => Bool -> m () -> m () or guard :: Alternative m => Bool -> m ()?
what haskell does to a person...
5
@DannyuNDos when is a simplified form of pattern matching
this feature adds the ability to have additional checks before executing an arm of the when statement
So... Kotlin needed a separate keyword for that, unlike C#?
21:52
Ah, you can indeed do "naive" async/await in Erlang (Here Elixer, but you could obviously do the same in Erlang) <https://hexdocs.pm/elixir/1.13/Task.html#async/1>
@Ginger ?
@DannyuNDos no when is pretty much equivalent to switch
and when guards is basically when (foo) { bar if foo.baz == 2 -> eggs() }
the if foo.baz is a guard
22:37
(worse switch)
how is it worse?
@Ginger What’s funny about this is that Haskell (even Haskell 98) literally has a language feature called “guards” that work exactly like this. I don’t know what @DannyuNDos is on about
@Seggan my understanding is that "when" can't do true computation, right? you can do method calls and stuff, but not write a program inside your case
entirely possible that isn't true
oh wait, i wrote "worse switch"
oops, that was meant to be "worse match", sorry about that
i'm apparently too tired to be on the internet today
not sure what you mean, when is very general in kotlin
yeah apparently i'm misremembering
apologies
it's still not true pattern matching I don't think, so could be better, but it looks pretty good for what it is
22:47
funny bit: kotlin's "guard in when" is "when in match" in F#
```
// kotlin
when (x) {
is A if x.a > 41 -> x.a
// F#
match x with
| A a when a > 41 -> a
```
can't find how to do that here
@blueberry yeah its not true pattern matching (yet), but its more powerful than switch
23:03
kotlin's when is not as powerful as F#'s match, but it does type refinement and it's usually good enough that it could be used instead of if without looking bad
@AlexisKing Yeah... Monads did this to me.
@Seggan are sealed classes an actual viable alternative to ADTs
this determines whether full pattern matching would actually be useful or not
I mean... Isn't it mind-blowing that return and for are just functions in Haskell?
not really; there's nothing saying those "have" to be fundamental concepts
in functional programming, everything is a function :D
23:09
also whether "return" is "just" a function depends on whether you mean functions returning (not a function) or the monadic "return" (yes a function)
i figure you mean the latter
@EldritchConundrum if you go hard enough even basic control flow is a function
in OO everything is an object too.
if you design your language around a single thing, everything can be that thing (that doesn't mean it's a good idea)
ah smalltalk my beloved
languages like java are cowardly and don't truely embrace everything is an object
Write in C#.
well, java is old
smalltalk is older :P
23:18
@blueberry IMO yes
slightly bulky but polymorphism is nice
hmm... maybe in the 90s, the languages that made OO mainstream were cowards because they didn't want to alienate existing programmers, who didn't want to think of primitive types as objects? or maybe because it didn't go well with C++'s performance concerns...
i don't blame them
tbh
smalltalk is weird
and C++ was meant to be C with classes, not "pure OOP"
java has less of an excuse, because it was ground up
They say C++ minus C is C#.
23:33
@blueberry kotlin
I mean... if it's disregarded that C# needs garbage collection.
@Seggan I am very happy about this :3

« first day (523 days earlier)      last day (123 days later) »