Request for comments on simple Ada program
flag
Messages 11 - 20 of 112 - Collapse all
/groups/adfetch?hl=en&adid=7xvxixEAAABrZDfYUzbUGqox1JYt5tDsFSRgCP-avRN4YT0eROC0jw
The group you are posting to is a Usenet group. Messages posted to this group will make your email address visible to anyone on the Internet.
Your reply message has not been sent.
Your post was successful
 
From:
To:
Cc:
Followup To:
Add Cc | Add Followup-to | Edit Subject
Subject:
Validation:
For verification purposes please type the characters you see in the picture below or the numbers you hear by clicking the accessibility icon. Listen and type the numbers you hear
 
1.  Maciej Sobczak  
View profile  
 More options Nov 15 2005, 11:03 am
Newsgroups: comp.lang.ada
From: Maciej Sobczak <no.s...@no.spam.com>
Date: Tue, 15 Nov 2005 17:03:50 +0100
Local: Tues, Nov 15 2005 11:03 am
Subject: Request for comments on simple Ada program
Hi,

While playing with Ada and exercising its constructs, I have written the
following classic Sieve of Eratosthenes:

with Ada.Text_IO;
with Ada.Integer_Text_IO;
use Ada.Text_IO;
use Ada.Integer_Text_IO;

procedure Primes is

    -- classic sieve
    procedure Print_Primes(Upper : in Positive) is
       Prime_Numbers : array(2..Upper) of Boolean := (others => True);
    begin
       for N in Prime_Numbers'Range loop
          if Prime_Numbers(N) then
             Put(N);
             New_Line;

             declare
                I : Positive := 2 * N;
             begin
                while I <= Prime_Numbers'Last loop
                   Prime_Numbers(I) := False;
                   I := I + N;
                end loop;
             end;
          end if;
       end loop;
    end Print_Primes;

    Upper_Limit : Positive;

begin
    Put("Enter the upper limit: ");
    Get(Upper_Limit);

    Print_Primes(Upper_Limit);
end Primes;

Now my question is: What would do do to make this code "better"?

Would you add comments? Loop labels? Change names? Is one-character name
for the loop control variable considered OK?
Would you put the "sieving" part in a separate function? Maybe even more
nested? Or maybe would you remove the separate function and put
everything in the main function altogether?
Would you define a separate type for the array or is the anonymous type
considered harmless?
Would you add more vertical whitespace? Or maybe it's already too much
of them?
Would you use different scopes for variable declarations?

The question is not whether this program is correct, but rather what
kind of pedantic touches would you apply to make it "better" (for your
definition of "better", like more readable, etc.)?

I'm interested in style and what do you consider to be a *good* Ada
code. Please do not hesitate to be as picky as you want - that's exactly
the point of this post.

Note: This is not a homework, I'm a self-learner.

--
Maciej Sobczak : http://www.msobczak.com/
Programming    : http://www.msobczak.com/prog/


    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
2.  Samuel Tardieu  
View profile  
 More options Nov 15 2005, 12:43 pm
Newsgroups: comp.lang.ada
From: Samuel Tardieu <s...@rfc1149.net>
Date: 15 Nov 2005 18:43:39 +0100
Local: Tues, Nov 15 2005 12:43 pm
Subject: Re: Request for comments on simple Ada program

>>>>> "Maciej" == Maciej Sobczak <no.s...@no.spam.com> writes:

Maciej> I'm interested in style and what do you consider to be a
Maciej> *good* Ada code. Please do not hesitate to be as picky as you
Maciej> want - that's exactly the point of this post.

Ok, you want some nitpicking, here is some :)

After my signature, you can find the way I would have coded it. I
would have separated the prime numbers *computation* from the prime
number *display*. The computation may be reused in many contexts. What
if you now need to compute the primes in another part of your program
and store them in a file? It doesn't seem logical to have to modify
any part involved in prime numbers computation, especially if you want
to be able to test it in isolation.

My example is much more verbose than yours. However, it is also much
more reusable. I've also included an example of unit testing for the
Check_Primes procedure.

Of course, all that is a question of taste.

  Sam

with Ada.Text_IO;         use Ada.Text_IO;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
with Primes;              use Primes;

procedure Primes_Printer is

   procedure Print_Primes (Primes : Candidates_Array);
   --  Print all indices for which the value is True

   procedure Print_Primes_Up_To (Upper_Bound : Potential_Prime);
   --  Print all primes between 2 and Potential_Prime

   ------------------
   -- Print_Primes --
   ------------------

   procedure Print_Primes (Primes : Candidates_Array) is
   begin
      for N in Primes'Range loop
         if Primes (N) then
            Put (N); New_Line;
         end if;
      end loop;
   end Print_Primes;

   ------------------------
   -- Print_Primes_Up_To --
   ------------------------

   procedure Print_Primes_Up_To (Upper_Bound : Potential_Prime) is
      Primes : Candidates_Array (2 .. Upper_Bound) := (others => True);
   begin
      Check_Primes (Primes);
      Print_Primes (Primes);
   end Print_Primes_Up_To;

   Upper_Limit : Potential_Prime;

begin
   Put ("Enter the upper limit: ");
   Get (Upper_Limit);

   Print_Primes_Up_To (Upper_Limit);
end Primes_Printer;

package Primes is

   subtype Potential_Prime is Positive range 2 .. Positive'Last;

   type Candidates_Array is array (Potential_Prime range <>) of Boolean;
   pragma Pack (Candidates_Array);

   procedure Check_Primes (Candidates : in out Candidates_Array);
   --  Mark non prime numbers in Candidates by setting their entry
   --  to False. Entries must be previously set to True. The only
   --  exception is when Candidates'First is greater than 2: in this
   --  case, multiples of numbers between 2 and Candidates'First+1
   --  must contain False and will not be checked again.

end Primes;

package body Primes is

   ------------------
   -- Check_Primes --
   ------------------

   procedure Check_Primes (Candidates : in out Candidates_Array) is

      procedure Mark_Multiples (Multiplier : in Potential_Prime);
      --  Mark all multiples of Multiplier (not including itself) as
      --  being non primes.

      --------------------
      -- Mark_Multiples --
      --------------------

      procedure Mark_Multiples (Multiplier : in Potential_Prime)
      is
         M : Potential_Prime := 2 * Multiplier;
      begin
         while M <= Candidates'Last loop
            Candidates (M) := False;
            M := M + Multiplier;
         end loop;
      end Mark_Multiples;

   begin
      for N in 2 .. Candidates'Last loop
         if Candidates (N) then
            Mark_Multiples (N);
         end if;
      end loop;
   end Check_Primes;

end Primes;

with Ada.Text_IO; use Ada.Text_IO;
with Primes;      use Primes;

--  Test correctness of the Check_Primes function for primes up to 10_000

procedure Test_Primes is

   function Is_Prime (N : Potential_Prime) return Boolean;
   --  Check whether N can be divided by any number between 1 and N
   --  (exclusive).

   -------------
   -- Is_Prime --
   --------------

   function Is_Prime (N : Potential_Prime) return Boolean is
   begin
      for I in 2 .. N-1 loop
         if N rem I = 0 then
            return False;
         end if;
      end loop;
      return True;
   end Is_Prime;

   Primes : Candidates_Array (2 .. 10_000) := (others => True);

begin
   Check_Primes (Primes);
   for N in Primes'Range loop
      if Is_Prime (N) /= Primes (N) then
         Put_Line ("Error -- result for" & Potential_Prime'Image (N) &
                   " doesn't match");
         return;
      end if;
   end loop;
   Put_Line ("OK");
end Test_Primes;


    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
3.  Samuel Tardieu  
View profile  
 More options Nov 15 2005, 12:47 pm
Newsgroups: comp.lang.ada
From: Samuel Tardieu <s...@rfc1149.net>
Date: 15 Nov 2005 18:47:09 +0100
Local: Tues, Nov 15 2005 12:47 pm
Subject: Re: Request for comments on simple Ada program

>>>>> "Sam" == Samuel Tardieu <s...@rfc1149.net> writes:

Sam> It doesn't seem logical to have to modify any part involved in
Sam> prime numbers computation, especially if you want to be able to
Sam> test it in isolation.

Moreover (I forgot this point), you can now change the Check_Primes
procedure (in the Primes package body) without affecting the main
program, for example to use something else than Erathostene's
sieves. And the unit test will still be usable (and then becomes also
a regression test, which checks that you haven't broken anything).

  Sam
--
Samuel Tardieu -- s...@rfc1149.net -- http://www.rfc1149.net/sam


    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
4.  Jacob Sparre Andersen  
View profile  
 More options Nov 15 2005, 4:28 pm
Newsgroups: comp.lang.ada
From: Jacob Sparre Andersen <spa...@nbi.dk>
Date: Tue, 15 Nov 2005 22:28:05 +0100
Local: Tues, Nov 15 2005 4:28 pm
Subject: Re: Request for comments on simple Ada program

Samuel Tardieu wrote:

Overall I like Samuel's version, but since we're picking nits, I'll
pick some in the comments (the code is as good as it gets) ...

>    procedure Print_Primes_Up_To (Upper_Bound : Potential_Prime);
>    --  Print all primes between 2 and Potential_Prime

... between 2 and Upper_Bound.

>    ------------------
>    -- Print_Primes --
>    ------------------

>    procedure Print_Primes (Primes : Candidates_Array) is

I use similar comments to separate/introduce procedures, but what do
we add by repeating the name of the procedure in the comment?  Except
for something which later can be different from the actual name of the
procedure?

Writing the function of the procedure in a comment is OK, although I
would like to keep all the non-checkable stuff outside the source
file.

Jacob (who believes that the optimal comment/code ratio is zero)
--
"I'm going as a barrel of toxic waste!"


    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
5.  Samuel Tardieu  
View profile  
 More options Nov 15 2005, 4:53 pm
Newsgroups: comp.lang.ada
From: Samuel Tardieu <s...@rfc1149.net>
Date: 15 Nov 2005 22:53:34 +0100
Local: Tues, Nov 15 2005 4:53 pm
Subject: Re: Request for comments on simple Ada program

>>>>> "Jacob" == Jacob Sparre Andersen <spa...@nbi.dk> writes:

Jacob> Jacob (who believes that the optimal comment/code ratio is
Jacob> zero)

It depends. Sometimes (particularily when doing embedded stuff), you
do have to comment the tricks you resort to. When I do some low-level
Ada or Forth programming for microcontrollers, some of the words (that
I need to optimize for performance) really need comments. If not for
me (the author of the code), at least for others.

What I do in general is reread every code I write one week later. Each
time I ask myself "why did I do this?", even for one second, I add a
comment. My experience shows that even when I go through the code one
year later, I have no question that are not already answered in the
comments.

  Sam
--
Samuel Tardieu -- s...@rfc1149.net -- http://www.rfc1149.net/sam


    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
6.  Anders Wirzenius  
View profile  
 More options Nov 16 2005, 4:10 am
Newsgroups: comp.lang.ada
From: Anders Wirzenius <and...@no.email.thanks.invalid>
Date: Wed, 16 Nov 2005 09:10:44 GMT
Local: Wed, Nov 16 2005 4:10 am
Subject: Re: Request for comments on simple Ada program

Samuel Tardieu <s...@rfc1149.net> writes:
> What I do in general is reread every code I write one week later. Each
> time I ask myself "why did I do this?", even for one second, I add a
> comment. My experience shows that even when I go through the code one
> year later, I have no question that are not already answered in the
> comments.

Excellent way of working!

Once upon a time (early eighties) when I was a Fortran programmer, my
colleague and I used to start coding by writing a pseudo code. The
syntax for the pseudo code was Ada. Much of the Ada code was left in the
Fortran code as comments.

--
Anders


    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
7.  Samuel Tardieu  
View profile  
 More options Nov 15 2005, 4:55 pm
Newsgroups: comp.lang.ada
From: Samuel Tardieu <s...@rfc1149.net>
Date: 15 Nov 2005 22:55:41 +0100
Local: Tues, Nov 15 2005 4:55 pm
Subject: Re: Request for comments on simple Ada program

>>>>> "Jacob" == Jacob Sparre Andersen <spa...@nbi.dk> writes:
>> Print all primes between 2 and Potential_Prime

Jacob> ... between 2 and Upper_Bound.

Yeah, typo while coming up with an educative example :)

Jacob> I use similar comments to separate/introduce procedures, but
Jacob> what do we add by repeating the name of the procedure in the
Jacob> comment?

Visual effect. If you have an editor which emphasizes subprogram names
a lot, they might not be needed. However, putting them let anyone
browsing the code (even in plain text only) see the subprogram names
immediately.

  Sam
--
Samuel Tardieu -- s...@rfc1149.net -- http://www.rfc1149.net/sam


    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
8.  Niklas Holsti  
View profile  
 More options Nov 16 2005, 4:03 am
Newsgroups: comp.lang.ada
From: Niklas Holsti <nob...@nowhere.fi>
Date: Wed, 16 Nov 2005 11:03:12 +0200
Local: Wed, Nov 16 2005 4:03 am
Subject: Re: Request for comments on simple Ada program

Jacob Sparre Andersen wrote:
> Writing the function of the procedure in a comment is OK, although I
> would like to keep all the non-checkable stuff outside the source
> file.

> Jacob (who believes that the optimal comment/code ratio is zero)

People differ. In my Ada code, the "comments" average 33% of
non-blank lines (59% for package specs, 23% for package bodies,
and note that I never repeat comments from specs in bodies). I
still occasionally find it hard to *fully* understand code from a
couple of years back. It's not the details -- I know what
N := N + 1 means by itself -- but the background assumptions,
intentions, limitations, usage rules, interactions.

I put "comments" in quotes above, because I think that this is a
bad case of mis-naming in programming language terminology. The
word "comment" implies something skimpy, an addition, a note; in
my view, what is needed is a rationale, description or motivation
that is mainly written *before* the code itself.

As for keeping such text in separate design documents, I would do
it if a customer demanded it, but I think it would be much harder
to manage changes, versions and configurations accurately. Still,
some very high-level descriptions are nice to keep apart from the
source-code, if they are not outdated by day-to-day code changes.

--
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
       .      @       .


    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
9.  Jacob Sparre Andersen  
View profile  
 More options Nov 16 2005, 9:21 am
Newsgroups: comp.lang.ada
From: Jacob Sparre Andersen <spa...@nbi.dk>
Date: Wed, 16 Nov 2005 15:21:06 +0100
Local: Wed, Nov 16 2005 9:21 am
Subject: Re: Request for comments on simple Ada program

Niklas Holsti wrote:
> Jacob Sparre Andersen wrote:
>> Writing the function of the procedure in a comment is OK, although
>> I would like to keep all the non-checkable stuff outside the source
>> file.
>> Jacob (who believes that the optimal comment/code ratio is zero)

> In my Ada code, the "comments" average 33% of non-blank lines (59%
> for package specs, 23% for package bodies, and note that I never
> repeat comments from specs in bodies).

My numbers are 33% in specs and 18% in bodies (22% in total), but I
consider them to be too high.

My reason for mentioning what I believe is the optimal comment/code
ratio, is actually due to an article in ACM Queue, where the authors
used a code quality metric, which equalled more comments with higher
code quality.

> I still occasionally find it hard to *fully* understand code from a
> couple of years back. It's not the details -- I know what N := N + 1
> means by itself -- but the background assumptions, intentions,
> limitations, usage rules, interactions.

That can happen to me too - and to almost any other programmer too, I
suppose.

> I put "comments" in quotes above, because I think that this is a bad
> case of mis-naming in programming language terminology. The word
> "comment" implies something skimpy, an addition, a note; in my view,
> what is needed is a rationale, description or motivation that is
> mainly written *before* the code itself.

But I don't put the rationale in the source code.  The rationale is
kept in a separate file.  What I still do put in the source code - and
don't like putting there - is the abstracts for the subprograms and
packages.  But how can I easily cross-link the documentation (with the
abstracts) and the code (with the implementations)?  Should I cite the
package name/full subprogram specification in the documentation to
create the cross-link?  Or can somebody come up with a more elegant
solution?

> As for keeping such text in separate design documents, I would do it
> if a customer demanded it, but I think it would be much harder to
> manage changes, versions and configurations accurately. Still, some
> very high-level descriptions are nice to keep apart from the
> source-code, if they are not outdated by day-to-day code changes.

I always keep the design documents separate (when they exist ;-), but
I must admit that programming for research purposes is a bit different
from commercial software development.

Jacob
--
"Human beings just can't not communicate."


    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
10.  Niklas Holsti  
View profile  
 More options Nov 16 2005, 12:08 pm
Newsgroups: comp.lang.ada
From: Niklas Holsti <nob...@nowhere.fi>
Date: Wed, 16 Nov 2005 19:08:50 +0200
Local: Wed, Nov 16 2005 12:08 pm
Subject: Re: Request for comments on simple Ada program

Jacob Sparre Andersen wrote:
> Niklas Holsti wrote:

>>...

>>>Jacob (who believes that the optimal comment/code ratio is zero)

On a philosophical level, I agree with you -- writing "comments"
is an extra burden, and one risks contradictions between the
comments and the code (I recall an article long ago in SIGPLAN
Notices with the title "Comments considered harmful" :-)

An ideal language should be expressive and readable enough to
stand on its own. Unfortunately, Ada -- or, to be fair, the way I
use Ada -- is still too low-level for that. Perhaps some future
aspect-oriented language...

> My reason for mentioning what I believe is the optimal comment/code
> ratio, is actually due to an article in ACM Queue, where the authors
> used a code quality metric, which equalled more comments with higher
> code quality.

I agree that such a metric can be very misleading, because then
you should measure the quality of the comments, too, which is
impossible to automate. But I think anyone who has tried to reuse
two code packages, one with (good) comments and the other without,
must feel that there is *some* truth in the metric.

> But I don't put the rationale in the source code.  The rationale is
> kept in a separate file.  What I still do put in the source code - and
> don't like putting there - is the abstracts for the subprograms and
> packages.  But how can I easily cross-link the documentation (with the
> abstracts) and the code (with the implementations)?  Should I cite the
> package name/full subprogram specification in the documentation to
> create the cross-link?  Or can somebody come up with a more elegant
> solution?

There are some IDE-like commercial tools -- if memory serves, some
sort of souped-up requirements databases + design tools + code
generatorts with "automatic" document generation functions -- that
claim to keep these cross-links for you. But burying my code in
that sort of a monster machine makes me very nervous, and they
aren't cheap either.

The conversation seems to be drifting towards Knuth's "literate
programming". I think it is or was a good idea, but gave more
benefit for Pascal than it would give for Ada, which can be more
literate in itself. Perhaps the time is ripe for something like
"checkable literate programming", modelled on SPARK, where the
annotations/comments are readable and informative but also checkable?

--
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
       .      @       .


    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.

Create a group - Google Groups - Google Home - Terms of Service - Privacy Policy
©2010 Google