I used to be big into programming language design, but eventually decided that there just wasn't enough headroom to do something innovative enough to warrant the switching costs. The world doesn't need yet another syntax on top of basic C-style or Lisp-style semantic constructs.

Lately I've been wondering if I should reconsider, though, and have had a bunch of ideas that blur the lines of what should be considered in-scope for a programming language. Things like:

1. Universal constructs for serial & parallel execution, but with user-defined semantics for where the code should execute. So for example, at low-scale you'd execute in a loop on the CPU. At mid-scale it'd run on the GPU. At high-scale you could transparently distribute across thousands of GPU boxes.

2. Profiling and execution statistics built into the language. Write your code, run it on representative data, and instantly get statistics on how many times each function is called, what the average size of data structures is, how much memory is used, etc. Profilers do this, but often not at a granularity that's particularly useful (ever tried to find out how many Strings are created within a particular dynamic call-tree?), and most new languages overlook implementing a profiler, leaving it to third-party vendors. This is a shame, because a standardized programmatic API to a profiler could be a very effective compiler tool, leading to...

3. A way of defining transformations between data representations, benchmarking the cost of those transformations, and then having the compiler automatically decide whether it's worth bulk-converting data based on typical profiler results. The motivating example for this is the AoS-SoA transformation, but they also feature in common system design questions like "Do you unpack all of the fields of this wire protocol, or lazily construct an object only when necessary?" or "Should you zip your data before sending it in an RPC?" or "Do you do this work at indexing or serving time?"

4. The ability to dump intermediate data from any function call site to disk, and then restart program execution from there without re-running the whole program. Handy when iterating on a complex algorithm.

5. Drill-down data visualizations for large collections. If you've ever tried to find the logic bug in a 500,000 element array using a standard IDE debugger, you'll know about this pain point.

6. Built-in support for machine-learning. In particular, many ML applications need extensive preprocessing, and you need to preprocess the data in exactly the same way for training and serving. Wouldn't it be neat if you could write your traditional algorithms, dump out your signals at the particular call-site of the classifier, and then have the development environment automatically send it to Mechanical Turk or Craigslist for labeling? Then have the system return the labeled data in a format easily suited for your ML framework of choice, do your data analysis & training, and import the finished model back into the call site of the language.

7. GPU-native, with language constructs that lead to efficient GPU code. This is becoming increasingly important not just for execution speed, but for developer velocity, because devs in data-intensive areas can waste a significant amount of time waiting for their program to run.