Live data from Hacker News

Revisiting the principles of data-oriented programming

blog.klipse.tech

81–90 of 117 posts

Re: Revisiting the principles of data-oriented programming

#81
post #75

Earlier quoted context omitted.

Multiple dispatch solves that question. I wish it was better known. Dispatch is on both wizard (or generally, user) and wand (or generally, item used)

Right but now it’s also raining and a full moon and the goblin is a werewolf and wands also have AOE spells that hit multiple opponents, except when those opponents are blocking… Sure, the code kinda sucks either way, but the data oriented approach works exponentially better as the object interactions become more complicated. A “cast” function called as part of the event loop can look up all the game state in the sta…

> Right but now it’s also raining and a full moon and the goblin is a werewolf and wands also have AOE spells that hit multiple opponents, except when those opponents are blocking

What exactly does this change? In a well-written program you should be able to write code that adapts to context so that you don't have to pass absolutely everything.

> Sure, the code kinda sucks either way, but the data oriented approach works exponentially better as the object interactions become more complicated

Maybe what you want is actually https://mitpress.mit.edu/books/software-design-flexibility.

Re: Revisiting the principles of data-oriented programming

#82

Earlier quoted context omitted.

It's not impossible to type check heterogeneous maps at compile time, but most static type systems don't support this. I think you'd certainly see much more friction trying to program like this in C# than you would in Clojure.

> It's not impossible to type check heterogeneous maps at compile time, but most static type systems don't support this I guess you mean dependent types[1], but if you don't, I'd appreciate an elaboration. If you do mean DTs, how might it look for a hetero collection? [1] If anybody has any good intros to dependent typing in C#, that'd be much appreciated. A web search throws up some pretty intimidating stuff.

Dependent types are types that depend on values, possibly runtime values. In C# types can only depend on other types when using generics: List depends on T. In C++ there is std::array (array with length encoded in type), where n must be known in compile time.

With full dependent types one can write generic types like std::array and use them with runtime parameters. In dependently-typed languages there are two main types: Sigma (dependent pair) and Pi (dependent function). Example of Sigma type in pseudo C#:

  (uint n, Array a); // array of any size
Pi:

  Array push(Type T, uint n, Array a, T x) { ... }
  Array x = push(int, 2, [1, 2], 3); // [1, 2, 3]
Generic function f is similar to a dependently typed one with `Type T` argument (requires first class types and many DT-langs have them). Values, on which types may depend, shouldn't be mutable, while C# function arguments are mutable.

A bit larger example:

  void Console.WriteLine(string format, params object[] args);
Using dependent types you can transform `format` into a heterogeneous array type containing only arguments specified in the format string.

  WriteLine("{%int} {%bool}", ?); // ?'s type is an array with an int value and a boolean value.
A heterogeneous map may be implemented as a map T with keys mapped to types and another map where keys are mapped to the values of a corresponding type in T. Probably this is not a good representation, but it is a valid one.

Re: Revisiting the principles of data-oriented programming

#83
post #5

"Anything"-oriented programming is dumb. Every big problem is a collection of smaller, different problems. Different problems call for different approaches. Sometimes the best approach has data-oriented features, sometimes object, sometimes functional, sometimes piped. For big problems you want a language good at all of them. It is why C++ continues to grow. Some complain about that, but every single feature got ther…

I wouldn't call C++ "good" at any of those problems. "Good enough" - maybe.

No language is good compared to those that will come after we are all of us dead. But C++ is the best we have. If any other language were to catch up and pass it, we would have another choice. But C++ is not sitting still.

Re: Revisiting the principles of data-oriented programming

#84

Reading the discussion here, I can't help but thinking that people are defending their own philosophies: OOP vs FP vs DOP vs etc. I wish the author had killer applications or killer examples in different categories, like can I code an operating system easier, can I code a database easier, can I create a complex streaming job easier, can I write a library as complex as Apache BEAM easier, can I write a compiler easier…

I have to agree here - there is total disconnect from context in these discussions.

I am writing business line applications - I don't have much need for "generic" functions like outlined in the article. My framework/language provides for example generic .Sum() I could use if I implement specific interface.

But usually I have to make specific sum and put it in database or in the interface.

Like I need to sum age or sum prices or sum amount of items in inventory - and I have to show these in the interface. I think it is quite BS to say there can be "generic" data structure and "generic" functions in context of business line application.

Other stuff I was doing was warehouse automation system and if I had X,Y,Z coordinates I had these in generic data structure named Coordinates - but any function that was going to do anything with coordinates had to be implemented in the context of machine. For example lift should never operate on X cooridinate I could calculate distances - but then there was never use case to calculate distance between machines because these had static access points and one would calculate distances to these access points only.

Re: Revisiting the principles of data-oriented programming

#85
I believe the easiest way to think about it is to get away from your programming tools and to start modeling your problem domain as tables in excel.

Once you have a relational schema that the business can look at and understand, then you go implement it with whatever tools and techniques you see fit.

This is what “data-oriented” programming means to me. It’s not some elegant code abstraction. It’s mostly just a process involving people and business.

Even for non serious business, these techniques can wrangle complexity that would otherwise be insurmountable.

I still think the central piece of magic is embracing a relational model. This allows for things like circular dependencies to be modeled exactly as they are in reality.

Re: Revisiting the principles of data-oriented programming

#87
post #82

Earlier quoted context omitted.

> It's not impossible to type check heterogeneous maps at compile time, but most static type systems don't support this I guess you mean dependent types[1], but if you don't, I'd appreciate an elaboration. If you do mean DTs, how might it look for a hetero collection? [1] If anybody has any good intros to dependent typing in C#, that'd be much appreciated. A web search throws up some pretty intimidating stuff.

Dependent types are types that depend on values, possibly runtime values. In C# types can only depend on other types when using generics: List depends on T. In C++ there is std::array (array with length encoded in type), where n must be known in compile time. With full dependent types one can write generic types like std::array and use them with runtime parameters. In dependently-typed languages there are two main ty…

Ouch! But thanks! I'll have a good chew over this evening.

I know it's possible to have DT in C#, I think your literal of '3' in the above example is constructed using the successor function (well, its moral equivalent) at compile time, I just can't find the article I read and there's very little out there for DT in C# at all. And it's over my head until I sit down with a good example and work it through.

I could use some simple DT for list lengths in my project.

Re: Revisiting the principles of data-oriented programming

#88

Earlier quoted context omitted.

Wouldn’t closures and let’s say “type-driven” also support your definition? It’s quite tricky as sometuple.fun() and fun(sometuple) might as well be interchangeable. If you really want to support a formal definition it would probably be best to have it in denotational semantics… not an easy task.

Closures aren't reusable across a whole program unlike classes since their type isn't named, and they don't allow to have more than one operation on the data held by the closure. They really are "poor man's objects" ;p

they allow as many operations as you need, just pass in a "method name" :)

  const p = Point(3, 5)
  p('getX') // 3
  p('up', 11)('toString') // "Point(3, 16)"


  const Point = (x, y) => (method, ...args) => {
    switch (method) {
      case 'getX': return x;
      case 'getY': return y;
      case 'toString': return `Point(${x}, ${y})`
      case 'up': return Point(x, y+args[0]);
      // ...
    }
  }
(unfortunately statically typing this statically requires... some work, either sth like [typescript overloads + literal types] or full on dependent types)

Re: Revisiting the principles of data-oriented programming

#90

Earlier quoted context omitted.

It's not impossible to type check heterogeneous maps at compile time, but most static type systems don't support this. I think you'd certainly see much more friction trying to program like this in C# than you would in Clojure.

> It's not impossible to type check heterogeneous maps at compile time, but most static type systems don't support this I guess you mean dependent types[1], but if you don't, I'd appreciate an elaboration. If you do mean DTs, how might it look for a hetero collection? [1] If anybody has any good intros to dependent typing in C#, that'd be much appreciated. A web search throws up some pretty intimidating stuff.

while you probably can do this with dependent types, i'd imagine GP means something along the lines of typescript's structural typing, i.e.

  const post = {
    id: 123,
    content: "...",
    published: true,
  }
  // TS infers the type of `post` to be an unnamed "map-ish" type: 
  // { id: number, content: string, published: boolean }
JS objects are map-like, and this one is "heterogenous" in that the values are of different types (unlike most maps in statically typed langs, which need to be uniform). this just "structural typing", the easier way to do stuff like this.

now, dependent types allow you to express pretty much arbitrary shapes of data, so you can do heterogenous collections as well. i haven't read about it enough to do a map, but a list of tuples (equivalent if you squint) is "easy" enough:

  [
    ("id", 123),
    ("content", "..."),
    ("published", True),
  ]
in Idris, you could type it as something like this:

  -- a function describing what type the values of each key are
  postKeyValue : String -> Type
  postKeyValue k =
    case k of
      "id" -> Int
      "content" -> String
      "published" -> Bool
      _ -> Void  -- i.e. "no other keys allowed"
  
  -- now we're gonna use postKeyValue *at the type level*.

  type Post = List (k : String ** postKeyValue k)

  -- "a Post is a list of pairs `(key, val)` where the type of each `val` is given by applying `postKeyValue` to `key`.
  -- (read `**` like a weird comma, indicating that this is a "dependent pair")
more on dependent pairs: https://docs.idris-lang.org/en/latest/tutorial/typesfuns.htm...

in general if you want to learn more about DT's, i'd probably recommend looking at a language like Idris with "native support" for them. backporting DT's onto an existing typesystem usually makes them much harder to read/understand that they actually are (and don't get me wrong, they're mindbending enough on their own).

if you don't want to bother with that, i'd look at Typescript - it's combination of "literal types", "type guards" and "function overloads" can get you some of the power of DT's. see this article for some examples: https://www.javiercasas.com/articles/typescript-dependent-ty...

Post reply on HN