Montag, 12. Juli 2010

Features of a language I would design

If I had the choice and time to define a programming language (what i would never do) which features would I include? This is not just a theoretical question, but also a way to find out which language I would seem as "best-designed".

References vs. Values
Java introduced the "Objects are Refs" concepts most of the modern languages seem to follow.Combined with the concept that all params are given "by value", most newbies tend to be a bit confused when using this paragidm.
I would take another, yet very compatible approach:
ALL VARIABLES ARE REFS.
As long as all "value" types (like int) do not allow an "inplace"-change on the first level (lower levels are not my problem), there is no difference between immutable ref types and values. None of them can be changed inplace!
Thats the idea upon which C# and Scala are built: You cannot change they values, you must assign new values.
Advantage of this scenario: The difference between refs and values does not exist from the design standpoint. Easier for the programmier!

Types
I would seem the following decisions to be indisputable concerning types:
static typing for maintainability and a good compiler
type inference so that types are only ever given in method signatures (where they are needed anyway to for maintenance reasons)
implicit conversions, the anti-element of strong typing are, as in scala, user-defineable, so that this powerful, yet dangerous approach to integrate libaries simple is fully accessable.

Generics
No types without generics! Typecasts should be tried to be avoided by clean generics-syntaxes at all costs. If possible, generics should be reified.

No checked Exceptions
Do it the go-lang way! Checked exceptions do not exist, but if a method can have errors, it must return a value which determines the type of error or an sucessful result. Exceptions are NOT USED for recoverable situations, UNLIKE in java. If it were, they MUST be checked (as java did correctly). But using return values in these situations is usually the much much better way.

Objectorientation, but less emphasis on inheritance
Object orientation is "good", but not inheritance. I do not know which kind of modeling concept I would prefer: Explicit interfaces, or the go-lang way with explicit duck-typing interfaces? Also, i am not quite sure if inheritance should not be in the language after all. However, i would never push it as the first solution (as java did).

Simple tuples and Closures
Tuples and Closures do two very important things: Tuples are mulittype arrays and are mainly used for multiple method return values. They are always designed as value-types (immutable). Closures are an integral part of any good language, so I will not discuss they advantages here.

No reflection
I would try to avoid all concepts of reflection in my language, simply because it defeats good design and most concepts and live without it. I would not do this for a language like a jvm-one, but I would do it if I were designing a machine-language.

Pattern matching
I am not sure if it would be as possible as in scala, but pattern matching should be a core element of the language as well, since its needed so often! unlike in scala, however, i would not define "case" classes but "val" classes, which in fact does nearly the same..

Functional approach
Like scala, the approaches would be very functional with only few keywords available, to make it easier to define your own keywords. For the same reason, the rules about brackets should be rather relaxed - but this is not for sure. Lisp shows that a concise, always identical approach has also advantages.

System language
If possible, the language should be powerful, but still good enough for a language for systems programming. Much like google go, but with less special rules which make this language seem a bit quirky in my opinion (pointers are not for maps/arrays i.e.).

Garbage collection
I need this one. The problem is that without a gc, memory management blends into the language. And thats bad, since it beats the entire concept and a lot of performance optimizations into the dust. With a gc, a lot of trivial objects could be allocated on the stack (if for a system language), since the language does not need to make clear where the objects are allocated. In general, the strategy would be to create small structs on the stack, but this rule is not in the influence of the programmer (unlike i.e. in c#). the compiler may try to find the best strategy here!

Method and operator overloading
Operator overloading must in general be allowed, since it must be the theoretical foundation of the basic data types. Method overloading, on the other hand, is hard to judge. I would not want if i really to wanted to make the language needlessly more complicated.