* how to import a package @ 2006-12-06 2:14 markww 2006-12-06 3:06 ` Adam Beneschan 2006-12-06 19:47 ` Jeffrey R. Carter 0 siblings, 2 replies; 25+ messages in thread From: markww @ 2006-12-06 2:14 UTC (permalink / raw) Hi, I have this snippet of code (from members here) which defines a generic type: generic type T is private; package P is type Node; type Node_Ptr is access Node; type Node is record Data : T; Prev_Rec : access Node; -- points to the next record or null if none exists. Next_Rec : access Node; -- points to the previous record or null if none exists. end record; end P; Now my compiler (gnat) complains that Node, and Node_Ptr are not seen by the rest of the application. Is this because they are scoped within package P? If so, how do I 'import' the package? Right now I just stuck this at the start of my main procedure: procedure my_project is generic type T is private; package P is type Node; type Node_Ptr is access Node; type Node is record Data : T; Prev_Rec : access Node; -- points to the next record or null if none exists. Next_Rec : access Node; -- points to the previous record or null if none exists. end record; end P; type PERSON_REC; type PERSON_REC_POINT is access PERSON_REC; type PERSON_REC is record m_strName : UNBOUNDED_STRING; m_strPhone : UNBOUNDED_STRING; m_strAddress : UNBOUNDED_STRING; end record; so I thought it would have been visible by the rest of the application. Thanks, Mark -- etc... ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: how to import a package 2006-12-06 2:14 how to import a package markww @ 2006-12-06 3:06 ` Adam Beneschan 2006-12-06 3:34 ` markww 2006-12-06 19:47 ` Jeffrey R. Carter 1 sibling, 1 reply; 25+ messages in thread From: Adam Beneschan @ 2006-12-06 3:06 UTC (permalink / raw) markww wrote: > Hi, > > I have this snippet of code (from members here) which defines a generic > type: > > generic > type T is private; > package P is > type Node; > type Node_Ptr is access Node; > type Node is record > Data : T; > Prev_Rec : access Node; -- points to the next record or > null if none exists. > Next_Rec : access Node; -- points to the previous record or > null if none exists. > end record; > end P; > > Now my compiler (gnat) complains that Node, and Node_Ptr are not seen > by the rest of the application. Is this because they are scoped within > package P? > > If so, how do I 'import' the package? Right now I just stuck this at > the start of my main procedure: P is a generic package so you have to instantiate it. Something like: package Person_List is new P (T => Person_Rec); Now, Node and Node_Ptr are visible within Person_List, and the "Data" field in Person_List.Node will have type Person_Rec. There's no such thing as a "generic type" in Ada. -- Adam ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: how to import a package 2006-12-06 3:06 ` Adam Beneschan @ 2006-12-06 3:34 ` markww 2006-12-06 9:18 ` Simon Wright 0 siblings, 1 reply; 25+ messages in thread From: markww @ 2006-12-06 3:34 UTC (permalink / raw) Hi Adam, Thanks for your help. Now I've instantiated a list of my ppl records. Right underneath the generic package definition I had: Start : Node_Ptr; Last : Node_Ptr; but Node_Ptr is not visible. Is it no longer possible to have those two variables declared like that? Thanks, Mark Adam Beneschan wrote: > markww wrote: > > Hi, > > > > I have this snippet of code (from members here) which defines a generic > > type: > > > > generic > > type T is private; > > package P is > > type Node; > > type Node_Ptr is access Node; > > type Node is record > > Data : T; > > Prev_Rec : access Node; -- points to the next record or > > null if none exists. > > Next_Rec : access Node; -- points to the previous record or > > null if none exists. > > end record; > > end P; > > > > Now my compiler (gnat) complains that Node, and Node_Ptr are not seen > > by the rest of the application. Is this because they are scoped within > > package P? > > > > If so, how do I 'import' the package? Right now I just stuck this at > > the start of my main procedure: > > P is a generic package so you have to instantiate it. Something like: > > package Person_List is new P (T => Person_Rec); > > Now, Node and Node_Ptr are visible within Person_List, and the "Data" > field in Person_List.Node will have type Person_Rec. > > There's no such thing as a "generic type" in Ada. > > -- Adam ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: how to import a package 2006-12-06 3:34 ` markww @ 2006-12-06 9:18 ` Simon Wright 0 siblings, 0 replies; 25+ messages in thread From: Simon Wright @ 2006-12-06 9:18 UTC (permalink / raw) "markww" <markww@gmail.com> writes: (it would be easier to comment on this if you didn't top-post! I've re-organised ...) > Adam Beneschan wrote: >> P is a generic package so you have to instantiate it. Something like: >> >> package Person_List is new P (T => Person_Rec); >> >> Now, Node and Node_Ptr are visible within Person_List, and the "Data" >> field in Person_List.Node will have type Person_Rec. > Thanks for your help. Now I've instantiated a list of my ppl records. > Right underneath the generic package definition I had: > > Start : Node_Ptr; > Last : Node_Ptr; > > but Node_Ptr is not visible. Is it no longer possible to have those two > variables declared like that? Either say Start : Person_List.Node_Ptr; (assuming Adam's instantiation) or 'use' the instantiation: package Person_List is new P (T => Person_Rec); use Person_List; --S ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: how to import a package 2006-12-06 2:14 how to import a package markww 2006-12-06 3:06 ` Adam Beneschan @ 2006-12-06 19:47 ` Jeffrey R. Carter 2006-12-06 23:56 ` markww 1 sibling, 1 reply; 25+ messages in thread From: Jeffrey R. Carter @ 2006-12-06 19:47 UTC (permalink / raw) markww wrote: > Hi, > > I have this snippet of code (from members here) which defines a generic > type: > > generic > type T is private; > package P is > type Node; > type Node_Ptr is access Node; > type Node is record > Data : T; > Prev_Rec : access Node; -- points to the next record or > null if none exists. > Next_Rec : access Node; -- points to the previous record or > null if none exists. > end record; > end P; > > Now my compiler (gnat) complains that Node, and Node_Ptr are not seen > by the rest of the application. Is this because they are scoped within > package P? Package are very basic to Ada. 1st you must know how to make use of a package. If you don't know that, you're not ready to do anything useful with Ada. In general, if you have a library-level package P, you make it visible to another compilation unit through a context clause: with P; package Q is ... In this case, you have a generic package, which is not a package but a way to create a package tailored to your needs. You can only mention a generic package in a context clause or instantiation. You still have to mention it in a context clause: with P; procedure My_Project is then you have to use it to make a new package (instantiation): package X is new P (T => Person_Rec); Now the things declared in P are available in X. You have to use a qualified name to access them: X. Node. (Since you're a beginner, I'd recommend avoiding the use clause until you have a better idea how these things work.) The above is for the most common case that P is a library-level generic package. In your case it appears your generic package is declared in your main procedure (which is not very useful), so it is not library-level and is directly visible; you neither need nor can use a context clause for P. But all this is very basic. You should work through a tutorial or text and understand packages and generic packages before trying this; both are available at adapower.com or adaworld.com. It would also help if you used basic Ada indentation standards: generic type T is private; package P is type Node; ... end P; Again, by the time you've worked through a tutorial or text you should have been exposed to a bunch of examples, and will hopefully have seen the logic behind the common indentation approach. If you've already been through a tutorial or text, including generics, then there's something you didn't understand. In that case, I'm not sure which part you didn't understand. -- Jeff Carter "People called Romanes, they go the house?" Monty Python's Life of Brian 79 ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: how to import a package 2006-12-06 19:47 ` Jeffrey R. Carter @ 2006-12-06 23:56 ` markww 2006-12-07 1:18 ` Björn Persson ` (2 more replies) 0 siblings, 3 replies; 25+ messages in thread From: markww @ 2006-12-06 23:56 UTC (permalink / raw) Yes I'm still confused - sorry - I'm coming from C++ / java and the ada syntax / scoping is a bit strange to me. So I thought a package is equivalent to a structure/class. I thought that the following line: package Person_List in new P (T => PERSON_REC) is just instantiating one instance of the package called Person_List. So the line: Start : Person_List.Node_Ptr; doesn't make sense to me since it looks like 'Start' is being defined as pointing to Person_List.Node_Ptr, when I thought the right side of the colon must be a data type. In any event, I can't event get past adding the following line under the package: package Person_List is new P (T => PERSON_REC); my compiler (gnat) gives an error saying: operator for type "Node_Ptr" defined at line 23, nstance at line 39 is not directly visible use clause would make operation legal line 39 is the line I just listed above. Line 23 is where Node_Ptr is defined in the package. So ok, I stick the line: use Person_List; underneath 'package Person_List is new P (T => PERSON_REC); ' but the compiler still throws the same error. Thanks, Mark Jeffrey R. Carter wrote: > markww wrote: > > Hi, > > > > I have this snippet of code (from members here) which defines a generic > > type: > > > > generic > > type T is private; > > package P is > > type Node; > > type Node_Ptr is access Node; > > type Node is record > > Data : T; > > Prev_Rec : access Node; -- points to the next record or > > null if none exists. > > Next_Rec : access Node; -- points to the previous record or > > null if none exists. > > end record; > > end P; > > > > Now my compiler (gnat) complains that Node, and Node_Ptr are not seen > > by the rest of the application. Is this because they are scoped within > > package P? > > Package are very basic to Ada. 1st you must know how to make use of a > package. If you don't know that, you're not ready to do anything useful > with Ada. In general, if you have a library-level package P, you make it > visible to another compilation unit through a context clause: > > with P; > package Q is > ... > > In this case, you have a generic package, which is not a package but a > way to create a package tailored to your needs. You can only mention a > generic package in a context clause or instantiation. You still have to > mention it in a context clause: > > with P; > procedure My_Project is > > then you have to use it to make a new package (instantiation): > > package X is new P (T => Person_Rec); > > Now the things declared in P are available in X. You have to use a > qualified name to access them: X. Node. (Since you're a beginner, I'd > recommend avoiding the use clause until you have a better idea how these > things work.) > > The above is for the most common case that P is a library-level generic > package. In your case it appears your generic package is declared in > your main procedure (which is not very useful), so it is not > library-level and is directly visible; you neither need nor can use a > context clause for P. > > But all this is very basic. You should work through a tutorial or text > and understand packages and generic packages before trying this; both > are available at adapower.com or adaworld.com. > > It would also help if you used basic Ada indentation standards: > > generic > type T is private; > package P is > type Node; > ... > end P; > > Again, by the time you've worked through a tutorial or text you should > have been exposed to a bunch of examples, and will hopefully have seen > the logic behind the common indentation approach. > > If you've already been through a tutorial or text, including generics, > then there's something you didn't understand. In that case, I'm not sure > which part you didn't understand. > > -- > Jeff Carter > "People called Romanes, they go the house?" > Monty Python's Life of Brian > 79 ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: how to import a package 2006-12-06 23:56 ` markww @ 2006-12-07 1:18 ` Björn Persson 2006-12-07 1:26 ` Brian May 2006-12-07 4:06 ` Jeffrey R. Carter 2 siblings, 0 replies; 25+ messages in thread From: Björn Persson @ 2006-12-07 1:18 UTC (permalink / raw) markww wrote: > Yes I'm still confused - sorry - I'm coming from C++ / java and the ada > syntax / scoping is a bit strange to me. So I thought a package is > equivalent to a structure/class. No, a struct in C would be a record in Ada. A class in C++ corresponds to a tagged record type in Ada. C++ doesn't have anything quite like a package; I'd say the closest you get is a namespace. In Java, the classes serve as both data types and packages. Not so in Ada. An Ada package isn't a data type any more than a C++ namespace is. What you have is a generic package. Generics in Ada fill the same role as templates in C++, but they're not quite the same thing. When you instantiate a C++ template you get a class ? a data type. When you instantiate a generic package in Ada you get a package, which can in turn contain data types, subprograms and other things. (Ada also has generic subprograms, but no generic data types.) > So the line: > > Start : Person_List.Node_Ptr; > > doesn't make sense to me since it looks like 'Start' is being defined > as pointing to Person_List.Node_Ptr, when I thought the right side of > the colon must be a data type. Right. Node_Ptr is a data type, and its declaration is to be found in the package Person_List. Start is an object (a variable) of this type. -- Bj�rn Persson PGP key A88682FD omb jor ers @sv ge. r o.b n.p son eri nu ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: how to import a package 2006-12-06 23:56 ` markww 2006-12-07 1:18 ` Björn Persson @ 2006-12-07 1:26 ` Brian May 2006-12-07 4:14 ` markww 2006-12-07 4:06 ` Jeffrey R. Carter 2 siblings, 1 reply; 25+ messages in thread From: Brian May @ 2006-12-07 1:26 UTC (permalink / raw) >>>>> "markww" == markww <markww@gmail.com> writes: markww> I thought that the following line: markww> package Person_List in new P (T => PERSON_REC) markww> is just instantiating one instance of the package called markww> Person_List. So the line: markww> Start : Person_List.Node_Ptr; In Ada, a package is not a type (unlike in, say Java where a class is a type and a package). So the above defines Start to of type Node_Ptr as found in the Person_List package. markww> doesn't make sense to me since it looks like 'Start' is markww> being defined as pointing to Person_List.Node_Ptr, when I markww> thought the right side of the colon must be a data type. Correct. -- Brian May <bam@snoopy.apana.org.au> ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: how to import a package 2006-12-07 1:26 ` Brian May @ 2006-12-07 4:14 ` markww 2006-12-07 4:40 ` Brian May 0 siblings, 1 reply; 25+ messages in thread From: markww @ 2006-12-07 4:14 UTC (permalink / raw) Ok so I moved the package into another file, compiled it separately, and it seems to import now. Looks like: package Node is new GenericNode(T => PERSON_REC); use Node; and now I can declare variables like: Start : Node.Node_Ptr; which is very excellent. Thanks for your help with that. I thought it would be smooth sailing now but I ran into one other minor problem related to this which I think is just a syntax problem. I've defined a function to count the # of nodes I have like: function GetRecordCount(Starting_Point : Node.Node_Ptr) return INTEGER is Temp : Node.Node_Ptr; nCount : INTEGER := 0; begin Temp := Starting_Point; if Temp = null then return 0; else loop nCount := nCount + 1; Temp := Temp.Next_Rec; // PROBLEM if Temp = null then return nCount; end if; end loop; end if; end GetRecordCount; but I get an error at line: Temp := Temp.Next_Rec; expected type "Node_Ptr" defined at genericnode.ads:9, instance at line 29 do I need to use some special syntax to do that assignment? Next_Rec is of type Node_Ptr so I don't see why it's causing an error. Thanks, Mark Brian May wrote: > >>>>> "markww" == markww <markww@gmail.com> writes: > > markww> I thought that the following line: > > markww> package Person_List in new P (T => PERSON_REC) > > markww> is just instantiating one instance of the package called > markww> Person_List. So the line: > > markww> Start : Person_List.Node_Ptr; > > In Ada, a package is not a type (unlike in, say Java where a class is > a type and a package). > > So the above defines Start to of type Node_Ptr as found in the > Person_List package. > > markww> doesn't make sense to me since it looks like 'Start' is > markww> being defined as pointing to Person_List.Node_Ptr, when I > markww> thought the right side of the colon must be a data type. > > Correct. > -- > Brian May <bam@snoopy.apana.org.au> ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: how to import a package 2006-12-07 4:14 ` markww @ 2006-12-07 4:40 ` Brian May 2006-12-07 9:32 ` Stuart 0 siblings, 1 reply; 25+ messages in thread From: Brian May @ 2006-12-07 4:40 UTC (permalink / raw) >>>>> "markww" == markww <markww@gmail.com> writes: markww> Ok so I moved the package into another file, compiled it separately, markww> and it seems to import now. Looks like: markww> package Node is new GenericNode(T => PERSON_REC); markww> use Node; markww> and now I can declare variables like: markww> Start : Node.Node_Ptr; markww> which is very excellent. Thanks for your help with that. I thought it markww> would be smooth sailing now but I ran into one other minor problem markww> related to this which I think is just a syntax problem. I've defined a markww> function to count the # of nodes I have like: markww> function GetRecordCount(Starting_Point : Node.Node_Ptr) return markww> INTEGER is markww> Temp : Node.Node_Ptr; markww> nCount : INTEGER := 0; markww> begin markww> Temp := Starting_Point; markww> if Temp = null then markww> return 0; markww> else markww> loop markww> nCount := nCount + 1; markww> Temp := Temp.Next_Rec; // PROBLEM markww> if Temp = null then markww> return nCount; markww> end if; markww> end loop; markww> end if; markww> end GetRecordCount; markww> but I get an error at line: markww> Temp := Temp.Next_Rec; markww> expected type "Node_Ptr" defined at genericnode.ads:9, instance at markww> line 29 markww> do I need to use some special syntax to do that assignment? Next_Rec is markww> of type Node_Ptr so I don't see why it's causing an error. Going back in time, you said you defined Next_Rec as: type Node; type Node_Ptr is access Node; type Node is record Data : T; Prev_Rec : access Node; Next_Rec : access Node; end record; Note that "access Node" is not the same thing as "Node_Ptr". From memory the first is an "anonymous access type", but my memory is a bit rusty on this topic right now (Ada 2005 feature when used in a record?). I think you want to replace "access Node" with "Node_Ptr". -- Brian May <bam@snoopy.apana.org.au> ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: how to import a package 2006-12-07 4:40 ` Brian May @ 2006-12-07 9:32 ` Stuart 2006-12-07 11:21 ` Jean-Pierre Rosen 0 siblings, 1 reply; 25+ messages in thread From: Stuart @ 2006-12-07 9:32 UTC (permalink / raw) "Brian May" <bam@snoopy.apana.org.au> wrote in message news:sa4veko5ndy.fsf@margay.local... >>>>>> "markww" == markww <markww@gmail.com> writes: > Going back in time, you said you defined Next_Rec as: > > type Node; > type Node_Ptr is access Node; > type Node is record > Data : T; > Prev_Rec : access Node; > Next_Rec : access Node; > end record; > > Note that "access Node" is not the same thing as "Node_Ptr". > > From memory the first is an "anonymous access type", but my memory is > a bit rusty on this topic right now (Ada 2005 feature when used in a > record?). Ada is very particular about type matching and this can lead to some consequences that, at first, appear very odd. If you look at this example: package P is pragma Elaborate_Body(P); -- Allow a package body to exist! end P; package body P is type T is array(0..5) of integer; A, B : array(0..5) of integer; C, D : T; begin A := B; -- Not allowed because types don't match! C := D; -- Types match! end P; Even though A and B appear in the same statement, they are of different anonymous types. This is because A, B : array(0..5) of integer; is equivalent to A : array(0..5) of integer; B : array(0..5) of integer; and, as you may already have realized, homographs are not treated as being the same in Ada. However, both C and D are of the same named type - even though the type T has an anonymous type as an index range. I think it is better to avoid anonymous types - so the declaration of T might be better written as: type T_index is range 0..5; type T is array(T_index) of integer; -- Stuart ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: how to import a package 2006-12-07 9:32 ` Stuart @ 2006-12-07 11:21 ` Jean-Pierre Rosen 2006-12-11 6:16 ` markww 0 siblings, 1 reply; 25+ messages in thread From: Jean-Pierre Rosen @ 2006-12-07 11:21 UTC (permalink / raw) Stuart a �crit : > package body P is > type T is array(0..5) of integer; > A, B : array(0..5) of integer; > C, D : T; > begin > A := B; > -- Not allowed because types don't match! > C := D; > -- Types match! > end P; > > [...] > However, both C and D are of the same named type - even though the type T > has an anonymous type as an index range. I think it is better to avoid > anonymous types - so the declaration of T might be better written as: > type T_index is range 0..5; > type T is array(T_index) of integer; > Just nit-picking, the index type of T is not anonymous, it is Standard.Integer by default, therefore the aboved declaration is not equivalent. Agreed, it is best to avoid hidden use of Standard.Integer. If you need Integer as the index type, better use: type T is array (Integer range 0..5) of Integer; Note that this remark is also applicable to loops. Rather than: for I in 1..10 loop write: for I in Integer range 1..10 loop (small plug: there is a rule in AdaControl to check the above) -- --------------------------------------------------------- J-P. Rosen (rosen@adalog.fr) Visit Adalog's web site at http://www.adalog.fr ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: how to import a package 2006-12-07 11:21 ` Jean-Pierre Rosen @ 2006-12-11 6:16 ` markww 2006-12-11 6:50 ` markww 2006-12-11 7:00 ` Simon Wright 0 siblings, 2 replies; 25+ messages in thread From: markww @ 2006-12-11 6:16 UTC (permalink / raw) Ok I still don't understand why this assignment is illegal though - here's a test I have: generic type T is private; package GenericNode is type Node; type Node_Ptr is access Node; type Node is record Data : T; -- the generic data we want to store in a node. Prev_Rec : access Node_Ptr; -- points to the next record or null if none exists. Next_Rec : access Node_Ptr; -- points to the previous record or null if none exists. end record; end GenericNode; now later... package gNode is new GenericNode(T => PERSON_REC); use gNode; function Test(whatever : INTEGER) return INTEGER is Temp : gNode.Node_Ptr; begin Temp := Temp.Next_Rec; -- no!!!!!!!!!!!!!!!! return 0; end Test; Why is the Temp assignment not possible? The compiler says: expected type Node_Ptr defined in genericnode.ads. But I have defined it as type Node_Ptr. Thanks, Mark Jean-Pierre Rosen wrote: > Stuart a écrit : > > package body P is > > type T is array(0..5) of integer; > > A, B : array(0..5) of integer; > > C, D : T; > > begin > > A := B; > > -- Not allowed because types don't match! > > C := D; > > -- Types match! > > end P; > > > > [...] > > However, both C and D are of the same named type - even though the type T > > has an anonymous type as an index range. I think it is better to avoid > > anonymous types - so the declaration of T might be better written as: > > type T_index is range 0..5; > > type T is array(T_index) of integer; > > > Just nit-picking, the index type of T is not anonymous, it is > Standard.Integer by default, therefore the aboved declaration is not > equivalent. > > Agreed, it is best to avoid hidden use of Standard.Integer. If you need > Integer as the index type, better use: > type T is array (Integer range 0..5) of Integer; > > Note that this remark is also applicable to loops. Rather than: > for I in 1..10 loop > > write: > for I in Integer range 1..10 loop > > (small plug: there is a rule in AdaControl to check the above) > -- > --------------------------------------------------------- > J-P. Rosen (rosen@adalog.fr) > Visit Adalog's web site at http://www.adalog.fr ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: how to import a package 2006-12-11 6:16 ` markww @ 2006-12-11 6:50 ` markww 2006-12-11 9:40 ` Georg Bauhaus 2006-12-11 7:00 ` Simon Wright 1 sibling, 1 reply; 25+ messages in thread From: markww @ 2006-12-11 6:50 UTC (permalink / raw) Ok I removed the 'access' keyword for the Next_Rec/Prev_Rec definitions and that seems to have cleared that issue up. I hope this is the last problem I run into , the rest of the app is compiling ok. I used to have a procedure that would add a person_rec to my linked list. I'm trying to update it so it takes a generic type and gets added to the linked list instead. So I made a test function like: procedure Add_Record(GenericData : gNode.T) is Temp : gNode.Node_Ptr; begin Temp := new gNode.Node; Temp.Data := GenericData; end Add_Record; now the compiler is saying that my generic type T is not visible to the rest of the application. It's in the imported package though and all the rest of the parts are visible. How do I make it visible? Also, is this procedure definition correct? In C++ it's easy to do this after defining a type it would be just: bool Add_Record (T t); template<typename T> bool CLinkedList<T>::Add_Record(T t) { // ... } I'm guessing it must be similar. Thanks, Mark markww wrote: > Ok I still don't understand why this assignment is illegal though - > here's a test I have: > > generic > type T is private; > package GenericNode is > type Node; > type Node_Ptr is access Node; > type Node is record > Data : T; -- the generic data we want to > store in a node. > Prev_Rec : access Node_Ptr; -- points to the next record or > null if none exists. > Next_Rec : access Node_Ptr; -- points to the previous > record or null if none exists. > end record; > end GenericNode; > > now later... > > package gNode is new GenericNode(T => PERSON_REC); > use gNode; > > function Test(whatever : INTEGER) return INTEGER is > Temp : gNode.Node_Ptr; > begin > Temp := Temp.Next_Rec; -- no!!!!!!!!!!!!!!!! > return 0; > end Test; > > Why is the Temp assignment not possible? The compiler says: expected > type Node_Ptr defined in genericnode.ads. But I have defined it as type > Node_Ptr. > > Thanks, > Mark > > > > Jean-Pierre Rosen wrote: > > Stuart a écrit : > > > package body P is > > > type T is array(0..5) of integer; > > > A, B : array(0..5) of integer; > > > C, D : T; > > > begin > > > A := B; > > > -- Not allowed because types don't match! > > > C := D; > > > -- Types match! > > > end P; > > > > > > [...] > > > However, both C and D are of the same named type - even though the type T > > > has an anonymous type as an index range. I think it is better to avoid > > > anonymous types - so the declaration of T might be better written as: > > > type T_index is range 0..5; > > > type T is array(T_index) of integer; > > > > > Just nit-picking, the index type of T is not anonymous, it is > > Standard.Integer by default, therefore the aboved declaration is not > > equivalent. > > > > Agreed, it is best to avoid hidden use of Standard.Integer. If you need > > Integer as the index type, better use: > > type T is array (Integer range 0..5) of Integer; > > > > Note that this remark is also applicable to loops. Rather than: > > for I in 1..10 loop > > > > write: > > for I in Integer range 1..10 loop > > > > (small plug: there is a rule in AdaControl to check the above) > > -- > > --------------------------------------------------------- > > J-P. Rosen (rosen@adalog.fr) > > Visit Adalog's web site at http://www.adalog.fr ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: how to import a package 2006-12-11 6:50 ` markww @ 2006-12-11 9:40 ` Georg Bauhaus 2006-12-11 14:19 ` markww 0 siblings, 1 reply; 25+ messages in thread From: Georg Bauhaus @ 2006-12-11 9:40 UTC (permalink / raw) On Sun, 2006-12-10 at 22:50 -0800, markww wrote: > So I made a test function like: > > procedure Add_Record(GenericData : gNode.T) is > Temp : gNode.Node_Ptr; > begin > Temp := new gNode.Node; > Temp.Data := GenericData; > end Add_Record; > > now the compiler is saying that my generic type T is not visible to the > rest of the application. The type T is in the formal part of the package, not in the package proper. So either you are explicit about T (you have made an instance of the package using Some_Type for T, so you can use Some_Type instead of gNode.T there, too) or you make your generic package have a type Gen_T by using "subtype Gen_T is T" or similar. > Also, is this procedure definition correct? In C++ it's easy to do this > after defining a type it would be just: > > bool Add_Record (T t); > template<typename T> > bool CLinkedList<T>::Add_Record(T t) > { > // ... > } But here, you have one specific T and one generic T. ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: how to import a package 2006-12-11 9:40 ` Georg Bauhaus @ 2006-12-11 14:19 ` markww 2006-12-11 15:03 ` Dmitry A. Kazakov ` (2 more replies) 0 siblings, 3 replies; 25+ messages in thread From: markww @ 2006-12-11 14:19 UTC (permalink / raw) Ok I just broke down and wrote the test function to take a specific PERSON_REC type to add into a new node. The program compiles and runs as expected, but I just lost my generics support by doing this, I think: procedure Add_Record(GenericData : PERSON_REC) is Temp : gNode.Node_Ptr; begin Temp := new gNode.Node; Temp.Data := GenericData; end Add_Record; So yes now it runs ok and I can print the contents of the linked list and see that a person record was added into the Data member. But now I can't use this Add_Record function to store some other type of user defined data, it will only work with PERSON_RECs. I'm sorry, I still don't understand how to just pass a generic through as a parameter! Thanks, Mark Georg Bauhaus wrote: > On Sun, 2006-12-10 at 22:50 -0800, markww wrote: > > So I made a test function like: > > > > procedure Add_Record(GenericData : gNode.T) is > > Temp : gNode.Node_Ptr; > > begin > > Temp := new gNode.Node; > > Temp.Data := GenericData; > > end Add_Record; > > > > now the compiler is saying that my generic type T is not visible to the > > rest of the application. > > The type T is in the formal part of the package, not in the package > proper. So either you are explicit about T (you have made an > instance of the package using Some_Type for T, so you can use > Some_Type instead of gNode.T there, too) or you make your generic > package have a type Gen_T by using "subtype Gen_T is T" or similar. > > > > Also, is this procedure definition correct? In C++ it's easy to do this > > after defining a type it would be just: > > > > bool Add_Record (T t); > > template<typename T> > > bool CLinkedList<T>::Add_Record(T t) > > { > > // ... > > } > > But here, you have one specific T and one generic T. ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: how to import a package 2006-12-11 14:19 ` markww @ 2006-12-11 15:03 ` Dmitry A. Kazakov 2006-12-11 16:22 ` Adam Beneschan 2006-12-11 20:28 ` Jeffrey R. Carter 2 siblings, 0 replies; 25+ messages in thread From: Dmitry A. Kazakov @ 2006-12-11 15:03 UTC (permalink / raw) On 11 Dec 2006 06:19:37 -0800, markww wrote: > I'm sorry, I still don't understand how to just pass a generic through > as a parameter! No way. It is incorrect in either C++ or Ada. A generic is never a [normal] parameter. It can only be a *generic* parameter of another generic thing. Answering less formally, what you want to achieve is probably this: generic type T is private; package Generic_List is type Node; type Node_Ptr is access Node; type Node is limited record -- We don't copy nodes Data : T; -- The data in the node Prev : Node_Ptr; -- Previous node, else null Next : Node_Ptr; -- Next node, else null end record; -- Operations defined on the nodes follow: -- -- Add a new node to the list after the node indicated by -- the parameter After. -- procedure Add (After : Node_Ptr; Data : T); end Generic_List; ---------------------------------------------- package body Generic_List is procedure Add (After : Node_Ptr; Data : T) is New_Node : Node_Ptr := new Node; begin New_Node.Data := Data; New_Node.Prev := After; New_Node.Next := After.Next; if After.Next /= null then After.Next.Prev := New_Node; end if; After.Next := New_Node; end Add; end Generic_List; ------------------------------------------- 1. T is a generic formal parameter of the package Generic_List. 2. Data is normal parameter of a procedure Add. 3. The procedure Add is not generic 4. When Generic_List is instantiated this instance will be a normal package with a normal procedure Add in it. 5. This Add will be defined on the actual type specified for T during the instantiation. For example: package List_Of_Integers is new Generic_List (T=>Integer); -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: how to import a package 2006-12-11 14:19 ` markww 2006-12-11 15:03 ` Dmitry A. Kazakov @ 2006-12-11 16:22 ` Adam Beneschan 2006-12-11 20:28 ` Jeffrey R. Carter 2 siblings, 0 replies; 25+ messages in thread From: Adam Beneschan @ 2006-12-11 16:22 UTC (permalink / raw) markww wrote: > Ok I just broke down and wrote the test function to take a specific > PERSON_REC type to add into a new node. The program compiles and runs > as expected, but I just lost my generics support by doing this, I > think: > > procedure Add_Record(GenericData : PERSON_REC) is > Temp : gNode.Node_Ptr; > begin > > Temp := new gNode.Node; > Temp.Data := GenericData; > end Add_Record; > So yes now it runs ok and I can print the contents of the linked list > and see that a person record was added into the Data member. > > But now I can't use this Add_Record function to store some other type > of user defined data, it will only work with PERSON_RECs. > > I'm sorry, I still don't understand how to just pass a generic through > as a parameter! If I understand what you're trying to do, then I think you want to put Add_Record inside the generic. You can add this to the GenericNode package: procedure Add_Record (GenericData: T); and then set up a package body for GenericNode that contains the body of Add_Record. The effect is that when GenericNode is instantiated (package <whatever> is new GenericNode...) with type PERSON_REC or ANOTHER_REC or whatever, you will also get a new Add_Record, inside gNode, to add records of that type. You'll probably have to do something additional. The way you've written Add_Record above, it assigns Temp to be a pointer to a new node, but then Temp isn't stored anywhere else, so that the new node you've just created is abandoned and no one can ever access it again. How you solve this depends on your particular design, but you may need to turn Add_Record into a function that returns a Node_Ptr, or add an OUT parameter whose type is Node_Ptr. Hope this helps, -- Adam ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: how to import a package 2006-12-11 14:19 ` markww 2006-12-11 15:03 ` Dmitry A. Kazakov 2006-12-11 16:22 ` Adam Beneschan @ 2006-12-11 20:28 ` Jeffrey R. Carter 2006-12-12 3:19 ` markww 2 siblings, 1 reply; 25+ messages in thread From: Jeffrey R. Carter @ 2006-12-11 20:28 UTC (permalink / raw) markww wrote: > > procedure Add_Record(GenericData : PERSON_REC) is > Temp : gNode.Node_Ptr; > begin > > Temp := new gNode.Node; > Temp.Data := GenericData; > end Add_Record; This leaks memory. Others have discussed the solution to your specific problem, but I think what you're missing is the general mind-set that a type definition and the operations on that type should be encapsulated in a package. So far, you only have 1 operation (Add_Record), but in a generally useful linked-list package you'd probably have a lot more. Those operations should be in the package; then, whenever you instantiate the package, you get the operations. This concept, encapsulation of data and their operations (usually with hiding of the data's structure), is called "object orientedness". In many languages, this design concept is mixed up with the implementation concept of programming by extension (incorrectly called OOP); for example, in C++, you get both from the "class" construct. In Ada, the 2 are separate. At this point, you might find it instructive to look at some existing linked-list packages, such as the one in the Ada-0X container library, or the ones in the PragmAda Reusable Components http://pragmada.home.mchsi.com/ or many of the component libraries you can find at adapower.com or adaworld.com. -- Jeff Carter "Blessed is just about anyone with a vested interest in the status quo." Monty Python's Life of Brian 73 ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: how to import a package 2006-12-11 20:28 ` Jeffrey R. Carter @ 2006-12-12 3:19 ` markww 2006-12-12 3:31 ` Jeffrey R. Carter ` (2 more replies) 0 siblings, 3 replies; 25+ messages in thread From: markww @ 2006-12-12 3:19 UTC (permalink / raw) Thanks all I think I got it now. Dmitry A. Kazakov, Adam Beneschan, your posts really showed me how to set it up. Now I have all the list functions as part of that package and it's working as expected for a generic list. I'm wondering still if it's possible to have a data member in the package definition that serve as my start and end nodes. In C++ I'd do something like: struct List { AddNode(...); DeleteNode(...); ... Node *pStart, *pEnd; // keeps track of start and end nodes for a single list instance. } am I allowed to do the same in my package definition? Then things would be a lot neater. Right now I have the start and end pointers as variables external to the package, so everytime I call AddNode() etc I have to pass them through which is pretty sloppy. It looks like: generic type T is private; package Generic_List is type Node; type Node_Ptr is access Node; type Node is limited record -- We don't copy nodes Data : T; -- The data in the node Prev : Node_Ptr; -- Previous node, else null Next : Node_Ptr; -- Next node, else null end record; procedure Add(Start : in out Node_Ptr; Last : in out Node_Ptr; Data : T); procedure Delete(Start : in out Node_Ptr; Last : in out Node_Ptr; nIndex : INTEGER); function GetNodeCount (Start : Node_Ptr) return INTEGER; function GetNode(Start : Node_Ptr; nIndex : INTEGER) return Node_Ptr; function GetNodePosition(Start : Node_Ptr; MatchData : T) return INTEGER; -- Something like: m_Start : Node_Ptr; m_Last : Node_Ptr; end Generic_List; then externally I'd hope to use it like: GenericList.Add(T); instead of what I'm doing now: GenericList.Add(Start, Last, T); Thanks, Mark Jeffrey R. Carter wrote: > markww wrote: > > > > procedure Add_Record(GenericData : PERSON_REC) is > > Temp : gNode.Node_Ptr; > > begin > > > > Temp := new gNode.Node; > > Temp.Data := GenericData; > > end Add_Record; > > This leaks memory. > > Others have discussed the solution to your specific problem, but I think > what you're missing is the general mind-set that a type definition and > the operations on that type should be encapsulated in a package. So far, > you only have 1 operation (Add_Record), but in a generally useful > linked-list package you'd probably have a lot more. Those operations > should be in the package; then, whenever you instantiate the package, > you get the operations. > > This concept, encapsulation of data and their operations (usually with > hiding of the data's structure), is called "object orientedness". In > many languages, this design concept is mixed up with the implementation > concept of programming by extension (incorrectly called OOP); for > example, in C++, you get both from the "class" construct. In Ada, the 2 > are separate. > > At this point, you might find it instructive to look at some existing > linked-list packages, such as the one in the Ada-0X container library, > or the ones in the PragmAda Reusable Components > > http://pragmada.home.mchsi.com/ > > or many of the component libraries you can find at adapower.com or > adaworld.com. > > -- > Jeff Carter > "Blessed is just about anyone with a vested interest in the status quo." > Monty Python's Life of Brian > 73 ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: how to import a package 2006-12-12 3:19 ` markww @ 2006-12-12 3:31 ` Jeffrey R. Carter 2006-12-12 9:03 ` Stuart 2006-12-12 10:56 ` Georg Bauhaus 2 siblings, 0 replies; 25+ messages in thread From: Jeffrey R. Carter @ 2006-12-12 3:31 UTC (permalink / raw) markww wrote: > > generic > type T is private; > package Generic_List is > ... > -- Something like: > m_Start : Node_Ptr; > m_Last : Node_Ptr; > > end Generic_List; You can do that, but then your package can only be a single list. If that's what you want, you should consider moving the type and data declarations to the body, and only having the operations in the spec. Perhaps what you really want is something like type List is record First : Node_Ptr; Last : Node_Ptr; end record; procedure Add (To : in out List; Item : in T); -- Jeff Carter "Blessed is just about anyone with a vested interest in the status quo." Monty Python's Life of Brian 73 ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: how to import a package 2006-12-12 3:19 ` markww 2006-12-12 3:31 ` Jeffrey R. Carter @ 2006-12-12 9:03 ` Stuart 2006-12-12 10:56 ` Georg Bauhaus 2 siblings, 0 replies; 25+ messages in thread From: Stuart @ 2006-12-12 9:03 UTC (permalink / raw) "markww" <markww@gmail.com> wrote in message news:1165893584.829025.235440@l12g2000cwl.googlegroups.com... > I'm wondering still if it's possible to have a data member in the > package definition that serve as my start and end nodes. In C++ I'd do > something like: <snip C> > am I allowed to do the same in my package definition? Then things would > be a lot neater. As Jeff Carter explained - yes you can. The approach you currently have is often referred to as an Abstract Data Type (ADT), whereas what you are considering is an Abstract State Machine (ASM). The topic is worth researching. It is a very important program design consideration as to whether to make something an ADT or an ASM as it controls the location of state and the nature of the interface. This is a lesson that is emphasized in the design of SPARK (see www.sparkada.com) programs. Given an ADT it is quite straightforward to create an ASM; you simply create a package that contains the state variable and replicates each of the ADT operations, omitting the Object parameter from their own parameter list and using the state variable when calling the ADT operation to provide the functionality. package ADT is type T is private; procedure Add(Item : in integer; To : in out T); function Initialize(Initial : in integer) return T; private type T is integer; -- Just a demo! end ADT; with ADT; package ASM is procedure Add(Item : in integer); private State : ADT.T := ADT.Initialize(0); end ASM; package body ASM is procedure Add(Item : in integer) is begin ADT.Add(Item => Item, To => State); end Add; end ASM; > Right now I have the start and end pointers as variables external to > the package, so everytime I call AddNode() etc I have to pass > them through which is pretty sloppy. It looks like: Why do you have them as separate variables? You could create a type (call it, say, List) that has both these components. Having 'cracked' generics you might want to go back and think very carefully about what the 'visible' parts of your ADT/ASM are, and what are 'private' details. Generally the more you make private the less chance there is of things getting messed up, and the easier it is to make changes to the underlying type to develop/extend/improve your design. Jeff's suggestion of looking at the design of packages like Containers is a good one. Regards -- Stuart ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: how to import a package 2006-12-12 3:19 ` markww 2006-12-12 3:31 ` Jeffrey R. Carter 2006-12-12 9:03 ` Stuart @ 2006-12-12 10:56 ` Georg Bauhaus 2 siblings, 0 replies; 25+ messages in thread From: Georg Bauhaus @ 2006-12-12 10:56 UTC (permalink / raw) On Mon, 2006-12-11 at 19:19 -0800, markww wrote: > I'm wondering still if it's possible to have a data member in the > package definition that serve as my start and end nodes. As Jeffrey and Stuart have explained, you are still led astray by a misconception: A C++ struct/class here corresponds to an Ada type, not to an Ada package. Although you need a package to associate the "methods" with the tagged type, all data members must become the record components in the type definition. C++: From a struct or class, you create objects. Ada: From a type, you create objects. C++: Operations of a type are declared within the struct/class Ada: Operations of a type are declared after the type within a surrounding package. Compare the following definitions: namespace Geo { struct Any { int x, y; virtual void move(int a, int b) = 0; }; struct Point : public Any { virtual void move(int a, int b); }; struct Circle : public Any { int r; virtual void move(int a, int b); }; } package Geo is type Any is abstract tagged record x, y: Integer; -- data members of any geometric object end record; procedure move(thing: in out Any; a, b: Integer) is abstract; -- abstract method of Any type Point is new Any with record null; -- no additional data members end record; --overriding procedure move(thing: in out Point; a, b: Integer); type Circle is new Any with record r: Integer; -- Circle objects with radius end record; --overriding procedure move(thing: in out Circle; a, b: Integer); end Geo; HTH, -- Georg ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: how to import a package 2006-12-11 6:16 ` markww 2006-12-11 6:50 ` markww @ 2006-12-11 7:00 ` Simon Wright 1 sibling, 0 replies; 25+ messages in thread From: Simon Wright @ 2006-12-11 7:00 UTC (permalink / raw) "markww" <markww@gmail.com> writes: > Ok I still don't understand why this assignment is illegal though - > here's a test I have: > > generic > type T is private; > package GenericNode is > type Node; > type Node_Ptr is access Node; > type Node is record > Data : T; -- the generic data we want to > store in a node. > Prev_Rec : access Node_Ptr; -- points to the next record or > null if none exists. > Next_Rec : access Node_Ptr; -- points to the previous > record or null if none exists. > end record; > end GenericNode; > > now later... > > package gNode is new GenericNode(T => PERSON_REC); > use gNode; > > function Test(whatever : INTEGER) return INTEGER is > Temp : gNode.Node_Ptr; > begin > Temp := Temp.Next_Rec; -- no!!!!!!!!!!!!!!!! > return 0; > end Test; > > Why is the Temp assignment not possible? The compiler says: expected > type Node_Ptr defined in genericnode.ads. But I have defined it as type > Node_Ptr. You've declared Next_Rec as *access* Note_Ptr. I think you meant to declare it as just Node_Ptr. struct node { T data; node** prev_rec; /* should be just node* ? */ node** next_rec; }; Also, look at the way you've commented on Prev_Rec and Next_Rec. Aside from the comments being the wrong way round, you say 'points to the ... record'. As written, it points to *a pointer to* the .. record. ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: how to import a package 2006-12-06 23:56 ` markww 2006-12-07 1:18 ` Björn Persson 2006-12-07 1:26 ` Brian May @ 2006-12-07 4:06 ` Jeffrey R. Carter 2 siblings, 0 replies; 25+ messages in thread From: Jeffrey R. Carter @ 2006-12-07 4:06 UTC (permalink / raw) markww wrote: > Yes I'm still confused - sorry - I'm coming from C++ / java and the ada > syntax / scoping is a bit strange to me. So I thought a package is > equivalent to a structure/class. A package provides modularity, encapsulation, information hiding, and namespace control. A C++ struct is the equivalent of an Ada record type. A C++ class provides encapsulation and information hiding. C++ namespaces provide namespace control. Nothing in C++ provides modularity, although header files and preprocessor textual inclusion provide an imitation. > I thought that the following line: > > package Person_List in new P (T => PERSON_REC) > > is just instantiating one instance of the package called Person_List. Right. P is a generic package, and this creates an instantiation of it, a package named Person_List. > So the line: > > Start : Person_List.Node_Ptr; > > doesn't make sense to me since it looks like 'Start' is being defined > as pointing to Person_List.Node_Ptr, when I thought the right side of > the colon must be a data type. Start is a variable object, of type Person_List.Node_Ptr. The type's simple name is Node_Ptr, but that's not visible. The expanded name (Person_List.Node_Ptr) means it's Node_Ptr in Person_List. > In any event, I can't event get past adding the following line under > the package: > > package Person_List is new P (T => PERSON_REC); > > my compiler (gnat) gives an error saying: > > operator for type "Node_Ptr" defined at line 23, nstance at line 39 > is not directly visible > use clause would make operation legal That's an odd msg; without more context I don't know what it's trying to tell you. This line has to come after the declaration of Person_Rec. -- Jeff Carter "People called Romanes, they go the house?" Monty Python's Life of Brian 79 ^ permalink raw reply [flat|nested] 25+ messages in thread
end of thread, other threads:[~2006-12-12 10:56 UTC | newest] Thread overview: 25+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2006-12-06 2:14 how to import a package markww 2006-12-06 3:06 ` Adam Beneschan 2006-12-06 3:34 ` markww 2006-12-06 9:18 ` Simon Wright 2006-12-06 19:47 ` Jeffrey R. Carter 2006-12-06 23:56 ` markww 2006-12-07 1:18 ` Björn Persson 2006-12-07 1:26 ` Brian May 2006-12-07 4:14 ` markww 2006-12-07 4:40 ` Brian May 2006-12-07 9:32 ` Stuart 2006-12-07 11:21 ` Jean-Pierre Rosen 2006-12-11 6:16 ` markww 2006-12-11 6:50 ` markww 2006-12-11 9:40 ` Georg Bauhaus 2006-12-11 14:19 ` markww 2006-12-11 15:03 ` Dmitry A. Kazakov 2006-12-11 16:22 ` Adam Beneschan 2006-12-11 20:28 ` Jeffrey R. Carter 2006-12-12 3:19 ` markww 2006-12-12 3:31 ` Jeffrey R. Carter 2006-12-12 9:03 ` Stuart 2006-12-12 10:56 ` Georg Bauhaus 2006-12-11 7:00 ` Simon Wright 2006-12-07 4:06 ` Jeffrey R. Carter
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox