Complexity in a programming language isn't created equal, there is good and bad 
one. So by itself it not necessary a bad thing.
(There is also the complexity of the implementation, that is a different matter 
and has a different set of advantages/disadvantages. I don't discuss about it 
here).

For example D is a language much more complex than C, but in practice I am able 
to write correct programs in *much* less time in D than in C. My D programs 
contain less bugs too.

How to tell the bad complexity from the good one? The good complexity is of 
features that allow to reduce code, avoid potential bugs, remove often the need 
of twiddling with pointers, to express a programmer meaning in a clear and 
standard way, etc. Adding to the language keywords that have a single and clean 
meaning seems an example of good complexity, while having keywords with 
multiple meanings looks like a bad form of complexity. Special cases are bad 
complexity. Adding simple standard ways to perform a common purpose may become 
good complexity if it's chosen wisely.

Here are few examples, mostly from D:

1) C doesn't have an array slicing syntax, so C is less complex. But D slicing 
syntax is handy, easy to read and understand, and equally efficient (or more, 
because such slices are lazy), so they are a good complexity. I like slices, 
but them being lazy has produced several bugs in my code, so I think I may like 
slices to be copying by default and lazy when required, that is the opposite of 
the current situation (so [a..b].dup becomes the standard default meaning and 
[a..b] becomes the special syntax. So it may become: [a..b] an eager copy, and 
[a..b].lazy the light slicing. This may reduce bugs).

2) D built-in dynamic arrays allow to manage matrixes and tensor is a way WAY 
simpler than C, so while they introduce complexity in the language (and its 
implementation), I think it's a good complexity. On the other hand I often find 
this syntax very confusing:
auto m = new int[][](n, m);
that is I confuse rows with columns, etc. In Python I use Numpy or a syntax 
with the native lists that can't be confusing to Python programmers:
m = [[None] * n for _ in xrange(m)]
So for me that's a little example of bad complexity in D.

3) Python has lazy and eager ways to define lists (lazy ones just define an 
iterable sequence), D lacks them, so Python is more complex here. But in 
practice they give:
- a short syntax that reduces code clutter, so they avoig bugs too
- avoid the usage of lambdas most of the times
- avoid the usage of many map() and filter() and related functions present in 
my libs and in std.algorithm of D2, this reduces complexity a lot and at the 
same time leads to faster (delegate-free) code as Andrei likes. This shows why 
using map() and filter() and related functions is bad, and I'd like a better 
solution, instead of seeing them added to the D stdlib.

4) Adding few associative arrays methods like a 'clear', to return a lazy view 
of its keys or values or pairs, and so on, increase its complexity, but in 
practice allow to write less code and to write smarter code, so they are good 
comlexity. The same may be true for a built-in set data structure, and part of 
the things that can be found in my dlibs.

5) The D module system is more complex than the basix import semantics of C, 
but in practice it leads to a simpler management of the parts of the programs, 
so it's a good complexity. The current module system has some holes, flling 
them may be a Good Thing [TM] (and probably it doesn't add much extra 
complexity).

6) Static if and static asserts seem a little more complex that the ways to do 
similar things in C, but they seem a good complexity.

My list can go on :-)

I think that most of the complexity of D is good, but there are many 
corners/things can be improved still, reducing the bad complexity of the 
language, adding more good complexity, reducing some corner cases, making D 
code both safer and faster to write and faster to run.

Bye,
bearophile

Reply via email to