Mixins in C?

Hello guys,

I can't get the idea of mixins in C from my head.

Do you have any clue how Casey is going to approach that?

I'm sorry for my impatience, but I really like the idea and would like to give it a try.

Edited by Martin Cohen on
I'm almost certain he'll be using some form of aggregation. Since he's allocating memory with a known base address I'm guessing he'll just be using pointer relations. Maybe you can think of a simple implementation where you can construct a game object from a known set of functionalities through some kind of aggregation.

Also I'm sure Casey will get into these details when the time comes for it to be implemented in HMH. Maybe we ought to just be patient and wait to see :)
Thanks for the answer, Randy. I'm going to bash at least something to play around with to ease the wait. :)

I'm trying to be at least one (lame) step ahead and then compare my solution with Casey's. Of course he always will do it better, but I already know what problems I had to deal with and I learn a lot by comparing that to his solution. Especially when he goes for a completely different approach where the problems just do not exist.
I missed the part where Casey talked about that. Is it in day 25? Does anyone have a pointer to the time?

My understanding of mixin is that it's a shiny new name for multiple inheritance, trying to work around its traditional pitfalls. I could talk at length about that, but since we're very pointedly not doing object-orientation in Handmade Hero, not sure where it comes in.

Is it per chance just about a distinction between interface and implementation? Like we have different structures with different layouts holding slightly different data on which we would like to run identical operations (i.e., functions). If that's it, then we need to define some primitive functions, and implement them for each structure, and then we can write "generic" functions that use only these primitive functions to manipulate the structures. The generic functions know which version of the primitive functions to call based on some kind of function table (like the C++ vtable Casey mentionned a couple times).

Edited by norswap on
It's in a much earlier video. Multiple inheritance is a very poorly thought out and executed attempt at language support to solve problems that the *idea* of mixins solve. Note that a mixin is an idea and not an implementation.

The way Casey described it is to form an aggregate out of distinguished building parts. This would be a form of aggregation.
@norswap: He mentions it here (Intro to C, Day 5, Q&A): https://www.youtube.com/watch?v=rFA1SzRCRWc#t=1266 (time 21:07 in case YouTube won't point you there automatically).
One way to do mixins without function pointers, that is more powerful than (multiple) inheritance, and that is pretty popular in game engines, is an entity-component system.

In-game objects, or entities are just ids, with no data whatsoever, and then all their various behaviors are implemented as structs of data, or components, managed by the game's subsystems.

This lets you combine those behaviors in any way you want, without function pointers or the layout problems of multiple inheritance, and it lets you do it at runtime, adding and removing them at will.
Let's step back for a minute and think about what you're actually trying to do.

There is a deep sense in which, at least for nontrivial programs, you never really program "in" a language. What you have is some real-world (or surreal-world in the case of games) thing that you are trying to capture in a more-or-less formal model. You translate that model "into" a language.

One of the goals of programming language design is to provide constructs which match various real-world situations. Structured programming is a case in point; it caught on because it matches structured data. You can think of structured data as being made out of three main primitives: tuples/structs, discriminated unions, and arrays/sequences. More complex data structures are made out of these (e.g. array-of-structs or struct-of-arraus).

These match pretty much exactly with the three main control structures in structured programs: sequences of instructions (i.e. the semicolon operator), alternation (if-then-else, switch statements, etc), and iteration (loops).

Any implementable abstract model can be translated into any Turing-complete language. When people say "you can do OO in C", this is 100% correct. And as anyone who has tried to customise a Windows common control in C will tell you, it can be damned inconvenient.

(I brought up that example, by the way, because WIMP-ish GUIs are one of the few things which seem to be very naturally modelled using Simula-style objects. The fact that the two paradigms grew up together is not a coincidence. Whenever you see a generic object system written in C, there's a GUI framework not far behind. GLib and Xt are two of the more famous examples.)

The reason why I bring all this up is to point out that you do need to be clear whether you're talking about an abstract concept, or a concrete programming language feature. Sometimes, they're so close that the distinction is overly pedantic (e.g. calling a C++ member function a "method" confuses the implementation detail with the abstract concept, but it's close enough). But sometimes, it's important to keep the distinctions clear in your head.

A "mixin" is an abstract concept; it's a little piece of data or behaviour which you want to be able to reuse in different scenarios. "Inheritance", however, is a programming language feature. It's one way to realise mixins, but it's not the only way.

Oh, and "reuse"? About 99% of the time, when someone says "reuse", they really mean "source code reuse", no more and no less. Shared libraries are one way to realise this, headers full of template hackery are another way, the C preprocessor is another way, and code generation is another way. "Semantic compression" is based on the same idea. Ultimately, what you're trying to do is share source code so it doesn't have to exist in two places.