It's a bit subjective, but I'm hoping to get a clearer understanding of what factors make an operator clear to use vs obtuse and difficult. I've been considering language designs recently, and one issue that I always circle back around on is when to make some key operation in the language an operator, and when to use a keyword or function.
Haskell is somewhat notorious for this, as custom operators are easy to create and often a new data type will come packaged with several operators for use on it. The Parsec library, for example, comes with a ton of operators for combining parsers together, with gems like >.
and .>
I can't even recall what they mean right now, but I do remember them being very easy to work with once I had memorized what they actually mean. Would a function call such as leftCompose(parser1, parser2)
have been better? Certainly more verbose, but clearer in some ways.
Operator overloads in C-like languages are a similar issue, but conflated by the additional problem of overloading the meaning of familiar operators like +
with unusual new meanings.
In any new language, this would seem like a pretty tough issue. In F#, for example, casting uses a mathematically derived type-casting operator, instead of the C# style cast syntax or the verbose VB style. C#: (int32) x
VB: CType(x, int32)
F#: x :> int32
In theory a new language could have operators for most built-in functionality. Instead of def
or dec
or var
for variable declaration, why not ! name
or @ name
or something similar. It certainly shortens up declaration followed by binding: @x := 5
instead of declare x = 5
or let x = 5
Most code is going to require a lot of variable definitions, so why not?
When is an operator clear and useful, and when is it obscuring?
+
for string concatenation or<<
for streams). With Haskell, on the other hand, an operator is either just a function with a custom name (that is, not overloaded) or part of a type class which means that while it's polymorphic, it does the same logical thing for every type, and even has the same type signature. So>>
is>>
for every type and is never going to be a bit shift.