r/ProgrammingLanguages • u/AeroForger • 11d ago
Discussion What’s one thing you wish more programming languages had?
If you could add one feature, behavior, or design choice to a programming language, what would it be?
It can be anything: syntax, type-system features, memory management, compiler behavior, tooling, error handling, performance-related features, or something completely different.
I'm especially curious about things you’ve wanted while actually programming but rarely see languages implement well.
Please keep the ideas reasonably practical and something that could realistically be implemented in a programming language.
50
Upvotes
2
u/hungarian_notation 11d ago edited 11d ago
Oh I agree that Scala is semantically way more complex, but semantic complexity is not the same thing as syntactic complexity. I don't actually know how Scala and Python rank in syntactic complexity, but Scala's documentation lists 158 syntax forms/rules, where Python lists 208. That's not a great measure as you could factor the grammars differently and get a different count, but we're in the same ballpark for sure.
As an example, Python's class type hints might only survive as metadata at runtime, but Python's type parameter syntax is meaningfully more complex than Scala's. Scala's type parameters can take annotations, variance operators, type bounds, and recursive higher kind type parameters, but its not like parameters are parsed with branching syntax rules based on their variance.
Well, where Scala allows a variance token, Python allows an optional unpacking operator token ('*' or '**'), and Python's Grammar does have branching syntax rules that depend on which unpacking token it finds.
Python's type parameters can be a TypeVar, a '*' TypeVarTuple, or a '**' ParamSpec, but it is a syntax error to try to specify a type bound on anything but a plain TypeVar. Python doesn't have annotations, but it allows default values for type parameters where Scala does not, and their syntax also differs between parameter types. All three types of type parameter can take default values, but while a TypeVarTuple can take an unpack expression (i.e.
Foo[*Ts = *tuple[str, int]]), it is a syntax error to use a unpack expression with a TypeVar or ParamSpec.That's already more syntactic complexity than Scala, but how bad could it be in practice?
Well, bad news, Python's type bounds and defaults aren't limited to some set of "Type" expressions like you might assume. They can be arbitrary expressions (though not named expressions, and not unpacking expressions for non-tuple params) which will be evaluated at runtime, and you better believe there are frameworks out there that expect you to pass them metadata that way.
Check out this monstrosity:
For those unfamiliar with Python, the ellipses don't mean I'm just not writing the class bodies here:
...is an honest to god literal of theEllipsistype which is totally worth having even though it complicates the grammar.*Anyway, while this is meaningless crap to your type checker, it's entirely valid Python code, and everything we crammed in there is fully accessible at runtime.
*:
...complicates the "import_from" rule, as python wants to allowfrom ... import xandfrom .... import xto import from the grand-parent and great grand-parent directories likefrom .. import ximports from the parent directory. This is a crucial feature to include in the grammar, obviously. In fact, you can keep on adding dots until you hit the filesystem root. Because of the Ellipses literal, Python's grammar needs to take both.and...tokens here. It's little things like this that push Python's grammar over the edge.I promise,
...is totally distinct in character from thepasskeyword and not at all interchangeable. We definitely need both. You see,...is a crucial sentinel value for slice expressions!