May 09, 2008
On Thu, 08 May 2008 18:28:23 +0100, Michael Neumann <mneumann@ntecs.de> wrote:

> Nick Sabalausky wrote:
>  > "Michael Neumann" <mneumann@ntecs.de> wrote in message
>  > news:48231B20.1080009@ntecs.de...
>  >> Actually, IMHO any C-style syntax has much more sever problems leading
>  >> to hard to find bugs:
>  >>
>  >>     if (a)
>  >>       s1;
>  >>     s2;
>  >>
>  >
>  > I can't say I've ever found that to be a problem. But maybe that's just me.
>
> Me neither. But it's annoying to have at least 3 different style guidelines for C-style syntaxes.
>
>    if (a) b;
>
>    if (a)
>      b;
>
>    if (a) {
>      b;
>    }
>
>    if (a)
>    {
>      b;
>    }
>
>    if (a)
>      {
>      b;
>      }
>
>    if (a)
>      {
>        b;
>      }
>
> And so on :).
>
> Compare that with how many choices you have when using "if ... end"!
>
> Regards,
>
>    Michael

I thought D had dropped single statement if's for this very reason. I must be mistaken. Many a (C) coding
style guide strongly encourages embracing even single statements in constructs like this.

You can go further with the idea. After all you can casuse ambiguity between e.g nested loops as well.

if (a) {
  while(b) {c}
}

versus

if (a)
   while(b)
      c
   wend
fi

or whatever.
You can mess around with this stuff forever without increasing programmer productivity signficantly.
The real gains are when you hit on improvements to semantic expressiveness. I'd much rather have the next
foreach than waste time worrying about } versus fi, endif etc.

Regards,

Bruce.










May 09, 2008
On Thu, 08 May 2008 19:19:23 +0100, Nick Sabalausky <a@a.a> wrote:

> "Michael Neumann" <mneumann@ntecs.de> wrote in message
> news:fvvd1a$7p3$1@digitalmars.com...
>> terranium wrote:
>> > Michael Neumann Wrote:
>> >
>> >> Another example which leads to hard to read code and potential
>> >> bugs is (ignoring compiler warnings):
>> >>
>> >>      class A
>> >>      {
>> >>        int i;
>> >>
>> >>        //
>> >>        // add some 25 lines of code here
>> >>        //
>> >>
>> >>        void foo(int i)
>> >>        {
>> >>          // what is "i" here?
>> >>        }
>> >>      }
>> >>
>> >> This is solved in Ruby by using a separate namespace for instance
>> >> variables ("@i" for instance variable "i", and "i" for local variable
>> >> "i").
>> >
>> > In C family languages this is ruled out by naming convention.
>>
>> Which in the case of using a m_ prefix leads to hard(er) to read code.
>> And then there is no standard naming convention, and who actually uses
>> such a naming convention? Without that, you can't easily distinguish a
>> local variable from an instance variable from a global variable.
>>
>
> In "good" C family languages, the instance variable is referred to by
> prefixing it with something like "this.". I think there are some that do it
> differently (ECMAScript, IIRC), but I'd argue those ones are making a big
> mistake.
>
A interesting take on this comes from the IDE crowd. You always know the type/context
of a variable because of tool-tips and syntax highlighting.
Its just us old-timers stuck in a world of ASCII editing.
May 09, 2008
On Thu, 08 May 2008 18:24:54 +0100, Michael Neumann <mneumann@ntecs.de> wrote:

> terranium wrote:
>  > Michael Neumann Wrote:
>  >
>  >> Another example which leads to hard to read code and potential
>  >> bugs is (ignoring compiler warnings):
>  >>
>  >>      class A
>  >>      {
>  >>        int i;
>  >>
>  >>        //
>  >>        // add some 25 lines of code here
>  >>        //
>  >>
>  >>        void foo(int i)
>  >>        {
>  >>          // what is "i" here?
>  >>        }
>  >>      }
>  >>
>  >> This is solved in Ruby by using a separate namespace for instance
>  >> variables ("@i" for instance variable "i", and "i" for local variable
>  >> "i").
>  >
>  > In C family languages this is ruled out by naming convention.
>
Another take (which I prefer) comes from compiler warnings about variables
being shadowed. gcc is good like that.
May 09, 2008
On Thu, 08 May 2008 21:43:49 +0100, Michael Neumann <mneumann@ntecs.de> wrote:

>
> Yeah, you are right. It is inconsitent to define the instance variable
> with "i" while accessing it with "@i":
>
>    class A {
>      int i;
>
>      void foo(int i) { @i = i; }
>    };
>
> But, then it's no less inconsistent than using "this.i".
>
Perhaps we should insist on using a dollar sign to indicate getting the value from a variable?
;-> <cue evil laughter />
May 09, 2008
On Fri, 09 May 2008 21:20:30 +0100, Nick Sabalausky <a@a.a> wrote:

> "Michael Neumann" <mneumann@ntecs.de> wrote in message
> news:g01mtk$1nvj$1@digitalmars.com...
>> Nick Sabalausky wrote:
>> > // Note: untested
>> > class A {
>> >   int i=0;
>> >
>> >   void foo() {
>> >     // Accidentially clobbers "this.i" aka "@i"
>> >     for(i=0; i<77; i++)
>> >       {/* Do stuff */}
>> >   }
>> >
>> >   invariant() {
>> >     assert(this.i==0); // Fails after foo() is called
>> >   }
>> > }
>> >
>> > I still like the @ thing, though.
>>
>> Very good example!
>>
>> A solution could be to force the programmer to use the "this." notation
>> or at least issuing a compiler warning if not done.  The latter could be
>> implemented in the compiler without any changes to the syntax/language.
>>
I believe Walter disapproves of compiler warnings on principle. Its either an error or it isn't.
I tend to disagree but on the otherhand I always code with -Werror and frown at any warnings
emitted by anything so I guess deep down I really agree with him.
May 09, 2008
On Fri, 09 May 2008 15:45:47 +0100, terranium <spam@here.lot> wrote:

> Michael Neumann Wrote:
>
>> But hey, it's C!
>
> It's not an excuse for writing junk. The excuse is this was written by one man.

That's no excuse either. Code for yourself as you would for others, if not better.
May 09, 2008
Nick Sabalausky:
> How are dynamic languages are considered to be easier/faster to spot/fix bugs?

Well:
- here I talk about Python, because I usually talk about the things I know.
- They often have a faster write code-test code loop because there's no compilation phase.
- Python has an interactive shell, you usually use that to build and try and test little complex pieces of code, for example to be sure complex slices are correct, etc. You can use that to test the code (a little piece, one line of code, a function, a class, a module, the whole program) interactively (with the debugger too, if you want).
- When you have done some tests of the method/function/class/module in the shell, you can just copy the text of that interactive session and paste it into a docstring of that function/class (and you may want to clean it a bit), that's a doctest already (adding two lines in the "main" too). Then you can add more tests like that very quickly. It's not easy to find a faster and simpler way to test code. With that you can avoid most little bugs from your code. I miss doctests in D.
- There are lints for Python too, you may want to use them too if you are developing a large code, etc. I generally don't use them for small programs.
- Python code is very readable and it has very little noise/clutter. And its formatting is very uniform across different developers. That helps you spot/avoid bugs. It helps you focus on the algorithm instead on the syntax/noise.
- Python has good builtins, and their API is very well designed, with easy short names, and it's easy to remember even if you don't use an IDE. And they are designed to often warn you if you use them in the wrong way (try using sum() to sum strings). So using them you can write code faster, and put less bugs in. D phobos std.string API shows some examples where its API can be improved, like the string cropping that's confusing between two very similarly named functions. Those things may increase your bug count.
- Like D python has many fail-safe, for example there is no ++ or while b=a+12:
etch, those details (and other parts of the Python syntax) are designed specifically to avoid you the most common bugs, even if that may cost you few extra chars of code.
- Unlike C, lot things are safe(r), there are no pointers, etc.
- Python has some higher-order functions and tools (like itertools, map, list comprehensions, apply, keyword arguments, zip, generator, iterators, decorators, etc) that help you write less code, write it in a higher level, avoiding bugs, making code more readable, etc. I have tried to put some of those things into my D libs I show here now and then, and I think I have partially succeed.
- It has a very uniform syntax and semantics, everything is managed by reference, classes and functions are objects of some metaclass, so you have much less things to think about, and you program faster putting less bugs in. Corner cases (C++ is *full* of them) slow you down and make you put *tons* of bugs into your code. Python is slower at running time than compiled languages, but it's simpler. This allows faster coding and give you less things to think of while you code or while you debug, so you have more free brainpower to think about writing the good/correct algorithm or avoiding more logical/higher-order bugs.
- having shorter names and methods everywhere allows you to write Python code with a bigger font, so your eyes can read code better, and you can spot syntax/typo bugs better. I use a smaller font when I use languages that burn a lot of horizontal space.
- Python is very well debugged (I have found only two bugs in Python so far, while I have found about 15 in DMD, and I have used D for much less time) and it has a large std lib, full of many useful things you can use quickly in simple ways to do most common things, that are almost bug-free, usually with a simple and logical API. All this speeds up your coding, because you use those things instead of re-writing them yourself, avoids you bugs, allows you to use algorithms by Knuth, etc. When you spot a bug it's nearly always yours.
- Python module system avoids you TONS of compilation/linking problems you may find in C++. D module system looks like a partially copy of the Python module system, but it has some bugs/missing parts/bad designed things that I have discussed in a nearly ignored post of mine in this newsgroup. Such module system keeps things tidy, and avoids you many bugs. (Import is dynamic, that helps for other things).
- Probably there are other things I have missed. Each of those things can be found in other languages (and D copies some of them), but when you sum them all you may find your coding speed rather high and your bug count low enough to allow you to write systems like Zope (I think it's about 1e5 - 2e5 lines long).

Now back to D!

Bye,
bearophile
May 10, 2008
Bruce Adams wrote:
> I thought D had dropped single statement if's for this very reason. I
> must be mistaken. Many a (C) coding
> style guide strongly encourages embracing even single statements in
> constructs like this.
>
> You can go further with the idea. After all you can casuse ambiguity
> between e.g nested loops as well.
>
> if (a) {
>   while(b) {c}
> }
>
> versus
>
> if (a)
>    while(b)
>       c
>    wend
> fi
>
> or whatever.
> You can mess around with this stuff forever without increasing
> programmer productivity signficantly.

It's not about programm productivity, but about redundancy :)

But then there is still Ada for those that need that redundancy to
prevent bugs. Or just don't write too deeply nested code ;-)

Regards,

  Michael
May 10, 2008
Bruce Adams wrote:
> On Fri, 09 May 2008 15:45:47 +0100, terranium <spam@here.lot> wrote:
>
>> Michael Neumann Wrote:
>>
>>> But hey, it's C!
>>
>> It's not an excuse for writing junk. The excuse is this was written by
>> one man.
>
> That's no excuse either. Code for yourself as you would for others, if
> not better.

Okay, it's not junk, definitvely not. It's just that some parts like
eval.c are not commented at all and for a newbie very hard to
understand. Another reason might be, because it origins from Japan, so
we wouldn't be able to read the comments anyway :).

To clarify: I'd actually call Ruby one of the best commented projects
I've ever seen, with the highest code/comment ratio. But only for the
parts that the programmer uses, not the very low-level implementation.

See this as just one example:

http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/object.c?revision=15758&view=markup

Btw, I'd like to see this style of documentation in languages like Java.
Java has a lot of documentation, but actually very little (if any)
examples in the documentation, so you have to figure out yourself how to
use it, which costs a lot of time. "An example is worth a 1000 words."

Regards,

  Michael
May 10, 2008
On Sat, 10 May 2008 11:58:41 +0100, Michael Neumann <mneumann@ntecs.de> wrote:

> Bruce Adams wrote:
>  > I thought D had dropped single statement if's for this very reason. I
>  > must be mistaken. Many a (C) coding
>  > style guide strongly encourages embracing even single statements in
>  > constructs like this.
>  >
>  > You can go further with the idea. After all you can casuse ambiguity
>  > between e.g nested loops as well.
>  >
>  > if (a) {
>  >   while(b) {c}
>  > }
>  >
>  > versus
>  >
>  > if (a)
>  >    while(b)
>  >       c
>  >    wend
>  > fi
>  >
>  > or whatever.
>  > You can mess around with this stuff forever without increasing
>  > programmer productivity signficantly.
>
> It's not about programm productivity, but about redundancy :)
>
> But then there is still Ada for those that need that redundancy to
> prevent bugs. Or just don't write too deeply nested code ;-)
>
> Regards,
>
>    Michael

Reducing bugs from syntax errors is one of several ways to improve
programmer productivity. Its much less important than good semantics though.