This is not about The Witness, but it may be relevant future games that we do! In my spare time I am building a new programming language. Today I made a bunch of tweets about something I was thinking about there... but the ideas are hard to follow on Twitter so I am crossposting them here. I started out by lamenting that so many people thought that a language without member functions was unthinkable, then continued:
Even the idea of UFCS is just a massive overcomplication. It only seems simple compared to baseline C++.
I should say that the biggest problem I find with the idea of member functions is that they are extremely anti-code-reuse. I know this may seem paradoxical, because the whole point is to encapsulate code in an easy-to-reuse way, but I'll give an example.
Let's say you have some basic data type like a 3D Vector called Vector3. You want everyone to be motivated to use Vector3 so that there's no friction when passing data between the main program and various libraries, etc.
All that is necessary for compatibility in a fast program is that everyone agrees on the data layout of Vector3. But as soon as you tie member functions to the data, you are insisting that everyone needs to think the same way about the data that is in a Vector3, and operate on it the same way. And that will never be true, because different code needs to think about data types in different ways; and also because programmers express their personality in programs, and different programmers want to think in different ways about the most common data types.
So if you force people to think a certain way about Vector3 or other basic data types, you are motivating them (or *requiring* them) to go against that grain and make their own alternatives. Then the system is fragmented and you have all these data types that need to be converted again. Or, if people don't do that, they just end up passive-aggressively hating the task of programming, which is not what you want.
So in reality, you want Vector3 to define only a common piece of data to be exchanged. You can provide default functions for operating on Vector3, but in a way that people can easily shadow them with their own functions or else use a completely disjoint set. That is just not what most "object models" encourage. Thus they put huge amounts of friction onreuse in this particular kind of case, which is very common and very important.
(I wish people would stop telling me that member functions are good because you can do obj . and get a list of procs in the IDE after typing the dot. You can obviously do this with flat functions too. Please stop telling me this kthx.)
Because this came out as a series of tweets, it is probably less coherent than what I would have written if it were a straight-up essay, but hey, this is how it went.