That's pretty much Pascal's qualifier-focused "CONST MaxStars = 5, MinStars = 0;" Not sure what beauty you see there: perhaps you find the curves of those parentheses sexy?
I've recently arrived at a mixed declaration, which "distributes the information" across the line, I think in a way which allows it to grow without being overhwelming, (which i take to be a holy grail...)
fn calc :: (x: int) => x
fn calc :: tidy (x: str)
open(str).read()
fn calc :: tidy heap (x: int)
let data: api many(int) = new array.fill(x)(x)
repeat d <- data
print(d)
fn compiletime($i, $T) :: temp (xs: $T*$i)
let data: api many(int) = new array.from(xs)
let sum = xs.reduce(op(+))
sum
fn lotsofparam($i, $T) :: pure (
num: f32,
xs: $T*$i,
ys: api many(str),
zs: api numeric
)
let sum = xs.reduce(op(+))
return sum
`tidy` is similar to python context managers, or an automatic `defer`. So any resources within the function have their `.close`s run.
`heap` is a semantics of `new`: allocate to the global heap
`temp` likewise means allocate to a smaller temporary arena
`pure` means no allocations and no resources
$vars are compile-time where $lowercase are integers, $UPPERCASE are types.
The type int*10 is a static array, so $T*$i is a compile-time variable but run-time static array.
The `api` keyword is for interface types, it's a syntax transform to a compile-time variable, ie., `fn($T) generic(x: $T)` with a compile-time constraint on $T
In most languages the type language is a different language to the executable language. In cases where this is so, I prefer the type declaration to be on a separate line to the executable definition rather than having them intermixed. I think Haskell has the right approach here.
I think philosophically this article should clarify the semantics of the languages, what needs to be specified in the declarations. Then talk about the syntax if there is any further need to. Languages are all about semantics; in principle there is no reason languages couldn't offer each user his own choice of syntax.
If it was absolutely completely convertible to different syntaxes, then yes, choice of syntax would be awesome. But everything has to be accurately representable in every supported syntax, which is a high bar.
I was going to protest about maintainability - if nobody can read your syntax, they can't maintain your code. But if they can just convert it to their syntax, then they can maintain it.
Even better, certain things may be easier to represent in one syntax than in another. You could write each part in the syntax that works best for it, if that simplifies things, and then convert them into any of the other syntaxes.
One thing that would be essential, though, is that the syntax A -> syntax B -> syntax A round trip gives you back the original code in syntax A (or better - but it can't be worse). If you get back, say, twice as much code when you do the round trip, then you can't convert back and forth for different people and still maintain a workable code base.