[21:57:02]  <@ihkafyawe>	hey any y'all ever see a thing like this? https://gist.github.com/anonymous/b5563228b7cf97a0c9671c9de16b303f

[00:09:46]  <@hbw>	um

[00:10:51]  <@hbw>	is that not, uh, a heavily OOP-ified callback + context/userdata API?

[00:18:42]  <@ihkafyawe>	more or less yeah

[00:19:04]  <@ihkafyawe>	it's a way to encapsulate inheritance

[00:19:52]  <@ihkafyawe>	you can have the `SomeThing` struct also provide a method for returning a reference to its internal Doer as areference to a Interface

[00:20:14]  <@ihkafyawe>	or you can give the SomeThing struct in its constructor a handle to wherever you want to register the Doer

[00:20:29]  <@ihkafyawe>	but the nice thing is now you don't have Interface mixed with your Something class

[00:21:24]  <@ihkafyawe>	and the *lifetime* of the "callback" is managed by the owning instance

[00:21:49]  <@ihkafyawe>	and it's more generalized than a single callback since you could have associated needed data, multiple functions from the interface implemented, etc

[00:22:02]  <@ihkafyawe>	but idk, i see OOP as largely about organizing data and lifetimes thereof

[00:32:39]  <@ihkafyawe>	though i do feel like there are better ways to describe lifetime bindings than classes

[01:33:02]  <@hbw>	i think the thing that really bugs me about classical OOP, particularly in C++ (and to some extent, GC'd OOP languages like java, C#), is that it (a) relies on you, the programmer, decoding implicit lifetime semantics from the language semantics, and (b) it forces an implicit, hardcoded binding between a special set of language constructs and the implicit-yet-forced memory/ownership model

[01:34:07]  <@hbw>	so what you end up seeing in codebases written in these languages is structural webs of classes and objects with relationships to each other that try to convey explicit lifetime models, but all implemented in terms of nouns acting "on behalf of" actions

[01:35:07]  <@hbw>	like, i think OOP (and C++ by extension, as the most low-level OOP language) is way too top-heavy in how it coerces you to "nounify" all of your program's semantics

[01:36:03]  <@hbw>	idk, like, to me it makes it harder to reason about what data you're dealing with

[01:36:50]  <@hbw>	because OOP-style architecture effectively conflates (and thus mixes in the same conceptual space) data with execution/ownership model

[01:38:37]  <@hbw>	that is, there's no clear structural division between data and protocol: they're just sort of mixed into one flat namespace of "structures that are tied to behavior"

[01:40:13]  <@hbw>	i guess that seems backward, to me. for certain types of systems, i can reason about complex relationships much easier when the data is organized based on "tying behavior to structures"

[01:42:44]  <@hbw>	as in, the data model is declarative (you declare that a function applies to a class of data), rather than encapsulating (you define a class of data that contains functions that apply only to it)

[01:43:03]  <@hbw>	i mean, to be fair, encapsulation isn't categorically *bad*

[01:45:06]  <@hbw>	but rampant encapsulation adds too much cognitive overhead, i think. and i've found that, moreso than not, it makes hard problems way harder than they should be (because your basic primitives are strung together across lots of encapsulation boundaries), and it doesn't really make the easy problems any easier

[01:45:37]  <@hbw>	it's just kind of, like, really fine-grained locking of data out of speculative fear, uncertainty, and doubt

[01:47:25]  <@hbw>	so idk, i feel like OOP and encapsulation/isolation makes a lot more sense in a garbage collected model, because focusing on hiding data leads to a lot of unnecessary opaque-yet-heavyweight objects

[01:49:12]  <@hbw>	and making the semantics of the lifetimes of references/pointers/handles to those objects, of which there are many, implicit unless you wrap them in an encapsulated object... it obscures the structural nature of lifetimes

[01:49:53]  <@hbw>	and i guess that's ultimately what you were saying, i.e. there are probably better ways to describe lifetime bindings than classes

[01:50:23]  <@hbw>	however! this is why i feel like herb sutter's proposed metaclass construct might actually help legitimately address that issue

[01:50:41]  <@hbw>	in that you can define metaclasses that generate different types of classes

[01:51:30]  <@hbw>	so you can implement, say, interfaces you can pass around, or guaranteed plain-old-data structures, or structures that you can explicitly tie to a lifetime/source of memory

[01:51:47]  <@hbw>	(or resources even... you could probably implement a metaclass for, like, a "locked" data structure)

[01:52:08]  <@hbw>	instead of weaving it together with the data representation, i.e. via RAII

[01:55:35]  <@hbw>	hell, you could implement non-blocking resource semantics *into* the language rules, so you can basically move resource ownership logic into a compile-time system that is enforced via type construction

[01:56:31]  <@hbw>	like, you could probably finally implement linear types *that compose with each other* in C++ with metaclasses...