www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Good complexity

reply bearophile <bearophileHUGS lycos.com> writes:
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
Nov 21 2008
parent reply Tom S <h3r3tic remove.mat.uni.torun.pl> writes:
bearophile wrote:
 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.
Static if and static asserts in C? Good joke.
 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.
Captain Obvious saves the day once more :D -- Tomasz Stachowiak http://h3.team0xf.com/ h3/h3r3tic on #D freenode
Nov 21 2008
parent reply "Denis Koroskin" <2korden gmail.com> writes:
On Fri, 21 Nov 2008 19:19:58 +0300, Tom S  
<h3r3tic remove.mat.uni.torun.pl> wrote:

 bearophile wrote:
 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.
Static if and static asserts in C? Good joke.
No kidding: #define STATIC_ASSERT(expr) typedef char __staticAssert[ (expr) ]
 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.
Captain Obvious saves the day once more :D
Nov 21 2008
parent Tom S <h3r3tic remove.mat.uni.torun.pl> writes:
Denis Koroskin wrote:
 On Fri, 21 Nov 2008 19:19:58 +0300, Tom S 
 <h3r3tic remove.mat.uni.torun.pl> wrote:
 
 bearophile wrote:
 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.
Static if and static asserts in C? Good joke.
No kidding: #define STATIC_ASSERT(expr) typedef char __staticAssert[ (expr) ]
My point exactly *g* This one doesn't work. Arrays of 0 length are valid... You could subtract 1, but then, "STATIC_ASSERT(1); STATIC_ASSERT(2);" will fail anyway. Turns out one has to resort to a different _trick_. Then one compiler doesn't like it and you end up adding special cases. There goes "a little more complex that the ways to do similar things in C". Oh wait a sec, similar? I think he meant similar to the D stuff... How much of the D compile-time checking can you do in C then? :D And try a nice, formatted error message for the static assertion :P -- Tomasz Stachowiak http://h3.team0xf.com/ h3/h3r3tic on #D freenode
Nov 21 2008