← Back to context

Comment by CivBase

4 days ago

What is a table other than an array of structs?

It’s not that you can’t model data that way (or indeed with structs of arrays), it’s just that the user experience starts to suck. You might want a dataset bigger than RAM, or that you can transparently back by the filesystem, RAM or VRAM. You might want to efficiently index and query the data. You might want to dynamically join and project the data with other arrays of structs. You might want to know when you’re multiplying data of the wrong shapes together. You might want really excellent reflection support. All of this is obviously possible in current languages because that’s where it happens, but it could definitely be easier and feel more of a first class citizen.

Well it could be a struct of arrays.

Nitpicking aside, a nice library for doing “table stuff” without “the whole ass big table framework” would be nice.

It’s not hard to roll this stuff by hand, but again, a nicer way wouldn’t be bad.

The difference is semantics.

What is a paragraph but an array of sentences? What is a sentence but an array of words? What's a word but an array of letters? You can do this all the way down. Eventually you need to assign meaning to things, and when you do, it helps to know what the thing actually is, specifically, because an array of structs can be many things that aren't a table.

I would argue that's about how the data is stored. What I'm trying to express is the idea of the programming language itself supporting high level tabular abstractions/transformations such as grouping, aggregation, joins and so on.

  • Implementing all of those things is an order of magnitude more complex than any other first class primitive datatype in most languages, and there's no obvious "one right way" to do it that would fit everyones use cases - seems like libraries and standalone databases are the way to do it, and that's what we do now.

  • Map/filter/reduce are idiomatic Java/Kotlin/Scala.

    SELECT thing1, thing2 FROM things WHERE thing2 != 2;

    val thingMap = things.map { it.thing2 to it.thing2 }.filter { it.thing2 !=2 }

    Then you've got distinct(), sorting methods, take/drop for limits, count/sumOf/average/minOf/maxOf.

    There are set operations, so you can do unions and differences, check for presence, etc.

    Joins are the hard part, but map() and some lambda work can pull it off.

  • Yeah, that's LINQ+EF. People have hated ORMs for so long (with some justification) that perhaps they've forgotten what the use case is.

    (and yes there's special language support for LINQ so it counts as "part of the language" rather than "a library")