comp.lang.ada
 help / color / mirror / Atom feed
From: Dmitry A. Kazakov <mailbox@dmitry-kazakov.de>
Subject: Re: Modes (was unbounded_string)
Date: Fri, 10 Oct 2003 11:15:27 +0200
Date: 2003-10-10T11:15:27+02:00	[thread overview]
Message-ID: <htqcov8rj5v1ii4aiad48sso0dhj0glcan@4ax.com> (raw)
In-Reply-To: mailman.60.1065773352.25614.comp.lang.ada@ada-france.org

On Fri, 10 Oct 2003 02:27:19 -0600, "Andrew Carroll"
<andrew@carroll-tech.net> wrote:

>>>For all other types, the compiler chooses the parameter 
>>>mode best suited to the type. 
>Great!!!  SIGN ME UP!!!  But...is it possible that the compiler 
>doesn't get it right?  What would I need to do if I found that
>the compiler didn't get it right in my testing?  I'm guessing
>that you will say, "specify the mode".

You cannot directly specify the by-value vs. by-reference mode.

>package x is
>type x;
>type xptr is access x;
>type x is tagged limited record
> head: nodeptr; 
> something: unbounded_string;
>end record;
>
>--creates a new node to put into the 'head' list.
>--new node is created from information in token.
>--token has nothing to do with the 'something' variable
>--declared in the record above.
>procedure add(this: xptr; token: unbounded_string); 
>
>end x;
>
>So, with the above code "example", xptr is passed as an 'in'
>or 'in out' mode at the add procedure?  

It depends only on whether the value of the pointer This has to be
modified by Add. If yes, then the mode is "in out". If not, then the
mode is "in". If it is a garbage and has to be set in Add, then the
mode has to be "out". Note that all this has nothing to do with the
object the value of This points to. It is This, an access type object,
which is passed to Add, not the object which it accidentally points
(or not) to.

>Are you saying that I should use just x and not xptr as the
>parameter so that the compiler will choose the correct mode?

The rule of thumb is: newer use pointers if there is an alternative.
So:

   procedure Add (This: in out X; Token: Unbounded_String); 

Note that X is tagged limited, so it will be passed by reference as
expected. There is nothing to choose for the compiler. Observe also
subtle pitfalls caused by pointers: your Add is not a primitive
subprogram of X. So it cannot be overridden by descendant types! Thus
another rule: if a pointer, then when possible anonymous:

   procedure Add (This: access X; Token: Unbounded_String); 
      -- This will be a primitive subprogram of X

>If so, you recommend it because of deallocation issues?

Irrelevant. In 90% cases, just forget that there is any difference
between by-reference vs. by-value.

>On to strings...
>>> Basically, you have reinvented the wheel. What you have is 
>>> Unbounded_String, but with its guts hanging out all over the place, 
>>> instead of using information hiding as a software engineer should, and 
>>> as Ada.Strings.Unbounded does.
>[snip]
>>> The "Ada Way" / "Ada idiom"
>
>Is there something in the code below that I missed about information 
>hiding?  
>
>Temp: gnat.os_lib.String_Access;
>...
>Temp := gnat.os_lib.getenv("QUERY_STRING");
>...
>---------------------------------------
>-- ready to use Temp for something else
>---------------------------------------
>Temp := gnat.os_lib.getenv("SOME_OTHER_VARIABLE");
>
>Considering the code above, what is the "Ada idiom" to "resize" a String
>without pointers and dynamic allocation?  In other words; what "Ada 
>idiom" code would you write to do the same thing I did, without pointers
>and dynamic allocation?  You don't have to write the code, a good 
>reading reference would be okay.

with Ada.Strings.Unbounded;  use Ada.Strings.Unbounded;
with GNAT.OS_Lib; use GNAT.OS_Lib;
...
Temp : Unbounded_String;
...
Temp := To_Unbounded_String (Getenv ("QUERY_STRING").all);
   -- Note that Temp is a copy of the env-string. So you can
   -- modify it.
...
Temp := To_Unbounded_String (Getenv ("SOME_OTHER_VARIABLE").all);

BUT FORGET IT AT ONCE! The Ada way is not to create objects you do not
need. The right way:

with GNAT.OS_Lib; use GNAT.OS_Lib;
...
declare  -- I need the value of QUERY_STRING here
   Temp : String renames Getenv ("QUERY_STRING").all;
      -- Temp is an alias to the env-string. You cannot modify it.
      -- Yet it is not a pointer. An analogue would be C++ reference
begin
   ... -- Doing with Temp everything I can to do to
       -- a constant String
end; -- I don't need it anymore

for example:

function Query_Variable_Name return String is ...;
--
-- Print all queried env-strings, which values start with 'A':
--
loop
   declare
      Name : constant String := Query_Variable_Name;
   begin
      exit when Name'Length = 0;
      declare
         Value : String renames Getenv (Name).all;
      begin
         if Value'Length > 0 and then Value (Value'First) = 'A' then
            Put_Line (Name & "=" & Value);
         end if;
      end;
   end;
end loop;

---
Regards,
Dmitry Kazakov
www.dmitry-kazakov.de



  reply	other threads:[~2003-10-10  9:15 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <20031010074015.761204C40C1@lovelace.ada-france.org>
2003-10-10  8:27 ` Modes (was unbounded_string) Andrew Carroll
2003-10-10  9:15   ` Dmitry A. Kazakov [this message]
2003-10-11  7:16     ` Simon Wright
2003-10-13  9:28       ` Dmitry A. Kazakov
2003-10-10 15:18   ` Stephen Leake
2003-10-10 16:21     ` Martin Dowie
2003-10-14 18:47     ` Craig Carey
2003-10-10 19:06   ` Jeffrey Carter
2003-10-13  9:33     ` Dmitry A. Kazakov
2003-10-13  9:40       ` Stephane Richard
2003-10-13 10:12         ` Dmitry A. Kazakov
2003-10-15  2:16         ` Warren W. Gay VE3WWG
2003-10-15  3:36           ` Jeff C,
2003-10-16 16:45             ` Warren W. Gay VE3WWG
     [not found] <20031010094017.680474C40C1@lovelace.ada-france.org>
2003-10-10 10:58 ` Andrew Carroll
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox