Array slices and types

This is a discussion on Array slices and types within the ADA forums in Programming Languages category; Consider this: type Name is new String (1 .. 10); N : Name; Some_String : String := "abc"; How can I assign Some_String to the beginning slice (ie. to the first three characters) of N? Everything that I can think of (short of copying characters individually) hits the type compatibility problem. -- Maciej Sobczak * www.msobczak.com * www.inspirel.com Database Access Library for Ada: www.inspirel.com/soci-ada...

Go Back   Application Development Forum > Programming Languages > ADA

Object Mix

Register FAQ Calendar Search Today's Posts Mark Forums Read
  #1  
Old 08-20-2008, 10:51 AM
Maciej Sobczak
Guest
 
Default Array slices and types

Consider this:

type Name is new String (1 .. 10);

N : Name;

Some_String : String := "abc";

How can I assign Some_String to the beginning slice (ie. to the first
three characters) of N?
Everything that I can think of (short of copying characters
individually) hits the type compatibility problem.

--
Maciej Sobczak * www.msobczak.com * www.inspirel.com

Database Access Library for Ada: www.inspirel.com/soci-ada
Reply With Quote
  #2  
Old 08-20-2008, 11:26 AM
Niklas Holsti
Guest
 
Default Re: Array slices and types

Maciej Sobczak wrote:
> Consider this:
>
> type Name is new String (1 .. 10);
>
> N : Name;
>
> Some_String : String := "abc";
>
> How can I assign Some_String to the beginning slice (ie. to the first
> three characters) of N?
> Everything that I can think of (short of copying characters
> individually) hits the type compatibility problem.


One way is to assign all of N:

N := Name (Some_String(1..3) & String (N(4..10)));

Another way is to use a helpful procedure:

procedure Set (Target : out String; Source : in String)
is
begin
Target := Source;
end Set;

and use type "conversion" on the output parameter:

Set (Target => String (N(1..3)), Source => Some_String(1..3));

That is equivalent to the (forbidden):

String (N(1..3)) := Some_String(1..3); -- Not Ada!


--
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
. @ .
Reply With Quote
  #3  
Old 08-20-2008, 11:46 AM
Dmitry A. Kazakov
Guest
 
Default Re: Array slices and types

On Wed, 20 Aug 2008 07:51:02 -0700 (PDT), Maciej Sobczak wrote:

> Consider this:
>
> type Name is new String (1 .. 10);
>
> N : Name;
>
> Some_String : String := "abc";
>
> How can I assign Some_String to the beginning slice (ie. to the first
> three characters) of N?
> Everything that I can think of (short of copying characters
> individually) hits the type compatibility problem.


You need an unconstrained base type for this. In your case the base is
anonymous. So name it:

type Name_Base is new String; -- The base type is now named
subtype Name is Name_Base (1..10);
N : Name;
Some_String : String := "abc";
begin
N (1..3) := Name_Base (Some_String);

--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de
Reply With Quote
  #4  
Old 08-20-2008, 01:47 PM
stefan-lucks@see-the.signature
Guest
 
Default Re: Array slices and types

On Wed, 20 Aug 2008, Maciej Sobczak wrote:

> Consider this:
>
> type Name is new String (1 .. 10);
>
> N : Name;
>
> Some_String : String := "abc";
>
> How can I assign Some_String to the beginning slice (ie. to the first
> three characters) of N?


Some_String does always contain exactly ten characters, no more, no less.

But you can assign the first three characters of Some_String to name:

N(1 .. 3) := Some_String;

> Everything that I can think of (short of copying characters
> individually) hits the type compatibility problem.


Here is a completely compilable example:

with Ada.Text_IO;

procedure Slice is
S: String(1 .. 3);
T: String(1 .. 5) := (others => '*');
U: String(1 .. 9) := (others => '-');
begin
S := T(1 .. 3);
U(1 .. 5) := T;
Ada.Text_IO.Put_Line(S & "|" & T & "|" & U);
end Slice;

As expected, the output is a line with the string "***|*****|*****----".



--
------ Stefan Lucks -- Bauhaus-University Weimar -- Germany ------
Stefan dot Lucks at uni minus weimar dot de
------ I love the taste of Cryptanalysis in the morning! ------

Reply With Quote
  #5  
Old 08-20-2008, 01:51 PM
stefan-lucks@see-the.signature
Guest
 
Default Re: Array slices and types

> > type Name is new String (1 .. 10);
> >
> > N : Name;
> >
> > Some_String : String := "abc";
> >
> > How can I assign Some_String to the beginning slice (ie. to the first
> > three characters) of N?

>
> Some_String does always contain exactly ten characters, no more, no less.


Sorry, Some_String always contains exactly three characters, name contains
ten.


--
------ Stefan Lucks -- Bauhaus-University Weimar -- Germany ------
Stefan dot Lucks at uni minus weimar dot de
------ I love the taste of Cryptanalysis in the morning! ------

Reply With Quote
  #6  
Old 08-20-2008, 02:52 PM
Niklas Holsti
Guest
 
Default Re: Array slices and types

Dmitry A. Kazakov wrote:
> On Wed, 20 Aug 2008 07:51:02 -0700 (PDT), Maciej Sobczak wrote:
>
>
>>Consider this:
>>
>> type Name is new String (1 .. 10);
>>
>> N : Name;
>>
>> Some_String : String := "abc";
>>
>>How can I assign Some_String to the beginning slice (ie. to the first
>>three characters) of N?
>>Everything that I can think of (short of copying characters
>>individually) hits the type compatibility problem.

>
>
> You need an unconstrained base type for this. In your case the base is
> anonymous. So name it:
>
> type Name_Base is new String; -- The base type is now named
> subtype Name is Name_Base (1..10);
> N : Name;
> Some_String : String := "abc";
> begin
> N (1..3) := Name_Base (Some_String);


Or you can use the 'Base attribute:

N(1..3) := Name'Base (Some_String(1..3));

--
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
. @ .
Reply With Quote
  #7  
Old 08-20-2008, 04:01 PM
Simon Wright
Guest
 
Default Re: Array slices and types

Niklas Holsti <niklas.holsti@tidorum.invalid> writes:

> Or you can use the 'Base attribute:
>
> N(1..3) := Name'Base (Some_String(1..3));


Only for scalar types, says GNAT.
Reply With Quote
  #8  
Old 08-20-2008, 04:45 PM
Adam Beneschan
Guest
 
Default Re: Array slices and types

On Aug 20, 7:51 am, Maciej Sobczak <see.my.homep...@gmail.com> wrote:
> Consider this:
>
> type Name is new String (1 .. 10);
>
> N : Name;
>
> Some_String : String := "abc";
>
> How can I assign Some_String to the beginning slice (ie. to the first
> three characters) of N?
> Everything that I can think of (short of copying characters
> individually) hits the type compatibility problem.


Do you really need a new *type*, as opposed to:

subtype Name is String (1 .. 10);

???

(The answer may be yes. But I would not declare Name to be a new
*type*, rather than a subtype, unless there's a reason for this---such
as Name being declared earlier as a private type. I just wanted to
make sure that you were aware that declaring a subtype is a
possibility.)

-- Adam


Reply With Quote
  #9  
Old 08-21-2008, 01:26 AM
Niklas Holsti
Guest
 
Default Re: Array slices and types

Simon Wright wrote:
> Niklas Holsti <niklas.holsti@tidorum.invalid> writes:
>
>
>>Or you can use the 'Base attribute:
>>
>> N(1..3) := Name'Base (Some_String(1..3));

>
>
> Only for scalar types, says GNAT.


Oops... GNAT 3.15p accepted 'Base for the array type. But the LRM
indeed allows it only for scalar types, so this is a bug (or
"extension" :-) in 3.15p. Sorry for my misinformation (and I know I
should use a newer GNAT).

But doesn't this example show that it would be useful to have 'Base
also for array types? Any strong reasons against it?

--
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
. @ .
Reply With Quote
  #10  
Old 08-21-2008, 04:53 AM
Dmitry A. Kazakov
Guest
 
Default Re: Array slices and types

On Thu, 21 Aug 2008 08:26:26 +0300, Niklas Holsti wrote:

> But doesn't this example show that it would be useful to have 'Base
> also for array types?


For any type, actually.

Consider this language design fault:

procedure Initialize (X : in out S) is
begin
Initialize (T (X));
... -- My stuff
end Initialize;

A call to Initialize should be done automatically, but it is not. So the
parent of S must be explicitly specified and known to all descendant. This
is a really *bad* thing:

package Foo is
type S is new T with private;
private
type S is new Private_Decendant_Of_T with ...;
end Foo;

What would happen if Private_Decendant_Of_T overrode Initialize of T? The
result would be an inability to publicly derive from S any new types if
Initialize should be extended!

S'Base could mend it:

procedure Initialize (X : in out S) is
begin
(S"Base (X)).Initialize; -- Call to parent whatever it be
... -- My stuff
end Initialize;

Presently the only way is to override Initialize, Finalize and Adjust
everywhere, even if you actually don't want to extend them:

package Foo is
type S is new T with private;
overriding procedure Initialize (X : in out S); -- Have to do this!
private
type S is new Private_Decendant_Of_T with ...;
end Foo;

--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de
Reply With Quote
Reply


Thread Tools
Display Modes


All times are GMT -5. The time now is 05:58 AM.


Powered by vBulletin® Version 3.7.2
Copyright ©2000 - 2009, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.2.0
vB Ad Management by =RedTyger=

In an effort to better serve ads to our visitors, cookies are used on objectmix.com. For more information, check out our Privacy Policy.