home *** CD-ROM | disk | FTP | other *** search
- Path: sparky!uunet!gatech!destroyer!caen!nic.umass.edu!dime!graceland!srivasta
- From: srivasta@pilgrim.umass.edu (Manoj Srivastava)
- Newsgroups: comp.lang.perl
- Subject: [Question] Indirection
- Keywords: glob,pointer.star value
- Message-ID: <58235@dime.cs.umass.edu>
- Date: 4 Jan 93 19:05:42 GMT
- Sender: news@dime.cs.umass.edu
- Reply-To: srivasta@pilgrim.umass.edu
- Organization: University of Massachusetts at Amherst
- Lines: 154
-
-
- Hi,
-
- I have a question about the best way to do address the
- following problem. I am parsing a set of object specifications, where
- an object could have a number of tuples of the form (attribute value)
- which I'd like to place in an associative array, and it also has a
- list of other objects, which I place in an simple array.
-
- The actual parsing is done by an automatically generated
- subroutine, &yyparse, which modifies the global entities %Attribute,
- and @Object list. I'd like the outer level routine, parse_obj (),
- (which is recursively called on object list) to place these into a
- form which can beaccessed by the name of the object.
-
- The way I see it, I have two options, firstly (Shamelessly
- copied from Tom Christiansen's article of 24 Jul 91 01:56:10 GMT Re:
- possibly novice associative array query) of using an associative
- array of uniquely named packages, keyed by object name, and use eval
- to create the package. (I think I understand how this works, I'm
- appending the code from Tom's posting at the end of this article; I'm
- still hazy about what those type globs are doing). The second option
- is to set up uniquely named arrays and use type globbing; like so:
-
- sub parse_obj {
- local ($obj_name) = @_;
-
- ...
- undef %Attribute;
- undef @Object;
- &yyparse;
- local ($code)=<<EOF;
- foreach \$key (keys \%Attribute){
- \$$obj_name{\$key} = \$Attribute{\$key};
- }
- foreach \$key (\@Object){
- push (\@$obj_name, \$key);
- }
- \$Global_attrs{\$$obj_name} = *$obj_name;
- EOF
- eval $code;
- ...
- }
-
- And now I can set a pointer to reference the objects, as
-
- *ptr = $Global_attrs{$obj_name};
- print "@ptr";
- ....
-
- Is there any other way to do this? (Hah! this is perl. there
- _has _ to be one).
-
- Also, I'd appreciate an explanation of the lines like *'Current_Folder
- = *Current_Folder; in the code snippet below, like *'Current_Folder
- referes to the current package, right? and what would happen if the
- refered value changes? (I'm sorry, but to me these look like C's
- pointers, and if the referenced values change, the effect is noticed
- by any alias reference).
-
- In other words, if I type glob *new = *old, and then change $old, will
- $new change? If this is so, then any solution to my problem would
- require a copying step, since yyparse keeps modifying %Attribute and
- and @Object.
-
- manoj
-
- Quote feom tchrist@convex.COM (Tom Christiansen)'s article dated
- 24 Jul 91 01:56:10 GMT with
- Subject: Re: possibly novice associative array query
-
- Tom> Let me discuss in brief two other strategems for magaging complex
- Tom> data structures in perl.
-
- Tom> The first is employed by the &activate_folder routine in plum.
- Tom> Basically, I want to keep around an associative array of active
- Tom> folders (actually, active folder sequences). Each active folder
- Tom> has a bunch of properties of varying associated with it, such as
- Tom> its cache's last mtime, all the line from scan, the mappings
- Tom> between message ids to scan line indices, etc.
-
- Tom> In C, the natural thing to do would be to use an array of
- Tom> structures. In perl, we must be sneakier than that. What I've
- Tom> done is selected an associative array called %Active_Folders; the
- Tom> keys are the folder names, and the values are not pointers to
- Tom> individual variables, but rather the names of UNIQUELY NAMED
- Tom> PACKAGES in which all variables associated with the folder. When
- Tom> I activate one, I set the current pointers equal to the hidden
- Tom> ones, and then normal variable references continue to work.
- Tom> Since only one folder can be considered active (viewed) at any
- Tom> given moment, this works well.
-
- Tom> Here's the trimmed-down routine:
-
- Tom> $gensym = 'a';
-
- Tom> sub gensym { 'gensym_' . $gensym++; }
-
- Tom> sub activate_folder {
- Tom> local($folder) = @_;
-
- Tom> &assert('$folder',$folder);
-
- Tom> $Last_Seq = $Current_Seq;
-
- Tom> $Active_Folders{$folder} = &gensym
- Tom> unless defined $Active_Folders{$folder};
-
- Tom> local($package) = $Active_Folders{$folder};
-
- Tom> # warning: it is important that any of these aggregate vars
- Tom> # get clearedinstead of undeffed. otherwise you may get
- Tom> # a coredump.
-
- Tom> local($code)=<<"EOF";
- Tom> {
- Tom> package $package;
- Tom> *'Current_Folder = *Current_Folder;
- Tom> *'Current_Seq = *Current_Seq;
- Tom> *'Current_Line = *Current_Line;
- Tom> *'Top_Line = *Top_Line;
- Tom> *'Scan_Lines = *Scan_Lines;
- Tom> *'Scan_IDs = *Scan_IDs;
- Tom> *'Incomplete_Read = *Incomplete_Read;
- Tom> *'Folder_Cache_Time = *Folder_Cache_Time;
- Tom> *'Last_Typed = *Last_Typed;
- Tom> *'Deleted = *Deleted;
- Tom> }
- Tom> EOF
- Tom> eval $code;
- Tom> $Current_Seq = $folder;
-
- Tom> &panic("bad eval: $@\n$code\n") if $@;
- Tom> }
-
- Tom> The typed variables I use are:
-
- Tom> $Current_Folder
- Tom> $Current_Seq
- Tom> $Current_Line
- Tom> $Top_Line
- Tom> @Scan_Lines
- Tom> %Scan_IDs
- Tom> $Incomplete_Read
- Tom> $Folder_Cache_Time
- Tom> $Last_Typed
- Tom> %Deleted
- Tom> $Deleted
-
- Tom> In certain ways, the pseudo-anonymous packages provided by &gensym
- Tom> are the key to this entire scheme.
-
-
-
-