ysaie

31 / ⚧ / code, music, art, games

──────────────────────────────
🌸 many-shaped creature
✨ too many projects
🚀 cannot be stopped
🌙 stayed up too late
:eggbug: eggbug enjoyer
──────────────────────────────
header image: chapter 8 complete from celeste
avatar: made using this character builder


📩 email
contact@echowritescode.dev

brain suddenly consumed by thoughts of "what if i restructured my entire programming paradigm around Not Having Methods"


basically using this:

class Foo
{
public:
  friend auto do_thing(Foo const &foo) -> void;

  Foo(int x);

private:
  int my_x { 0 };
};

int main()
{
  Foo foo { 5 };
  do_thing(foo);
  return 0;
}

instead of this:

class Foo
{
public:
  auto do_thing() -> void;

  Foo(int x);

private:
  int my_x { 0 };
};

int main()
{
  Foo foo { 5 };
  foo.do_thing();
  return 0;
}

reasoning: nothing super rigorous, but i kind of like the idea of aggregate (class/struct) types being just Bundles Of Stuff and writing functions that operate on them instead of having this special different kind of callable.

the thought that led me here was about how nice record types in functional languages are because of exactly this paradigm. a type in, say, Haskell, is just the material stuff that makes it up, plus a tag saying "this ball of junk is a Bingus"; then even though some functions may have privileged access to the insides of the Bingus due to whatever accessibility convention, they're still just functions. you can do all the same things with them as you can with any random function, because the notion of "privileged access" is compile-time, not run-time.

the only downsides to this that i can see are:

  • more typing: buffer.push(item) vs. crucible::core::memory::push(buffer, item)
  • needing to rely on the (imo) unintuitive argument-dependent lookup rules in generic contexts: e.describe() is easier to resolve than describe(e), especially for humans

and of course, some functions have to be member functions, by the rules of the language (mainly constructors, destructors, and assignment/subscript/call operators), but that's not really a big problem.

curious for opinions about this! might be a terrible idea for reasons i haven't foreseen, or might be something worth experimenting with...


You must log in to comment.

in reply to @ysaie's post:

Aren't these essentially equivalent, just a change in syntax aesthetic? Basically foregoing the dot syntax for method calls by manually adding this to the function signature. (not entirely sure tho, it's late and I might be missing a key C++ism)
(...is it about using friend to allow for "free" functions to access private fields?)

i admit aesthetic consistency is part of what i like about it, but there are some semantic effects:

  • "pointer to function" and "pointer to member function" are different things and need a wrapper like std::function to seamlessly interoperate. i'm pretty sure you can't pass member function pointers to C code, for example.
  • method lookup works differently than function lookup (resolving T::foo() is a different set of rules than resolving foo(T))
  • you can define free functions that take forwarding references to the "self" object, but not member functions
  • higher order functions are a lot less cumbersome when everything else is already a free function; you can still use them with member functions, but then you just end up wrapping the member function call in a lambda anyway

mostly though, i like the mental model of "a type is a tag and some data". i think it declutters the idea a lot.

yes, this almost exactly matches my first (inadvertent) foray into functional programming. i was learning C++ and i kept basically reinventing functional programming style before i knew that functional programming was a thing

i'm determined (for the moment) to make it work... but there is definitely a universe where i end up burning my C++ codebase to the ground and starting again in OCaml or Haskell or something.

C++ feels sooooo close to being able to encode a bunch of useful functional building blocks, but comes up short more often than i'd like...