Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask
 
PerlMonks  

Symbolic Reference in Method Call

by EclecticScion (Novice)
on Jun 27, 2013 at 16:40 UTC ( #1041048=perlquestion: print w/ replies, xml ) Need Help??
EclecticScion has asked for the wisdom of the Perl Monks concerning the following question:

Greetings, O monks,

I am having difficulty using references in the context of a method call I am using. For example, this code (stolen from here) works perfectly:

use RTF::Writer; my $rtf = RTF::Writer->new_to_file("greetings.rtf"); $rtf->prolog(); $rtf->paragraph( "Hi there!" ); $rtf->close;

I would like to know how to use a reference in place of $rtf. Specifically, I would like to able to retrieve the string "rtf" from somewhere else, and then call $(insert string here)->... My best guess on how to do this, after consulting perlmod, would be something like this:

use RTF::Writer; my $rtf = RTF::Writer->new_to_file("greetings.rtf"); my $foo = "rtf"; ${$foo}->prolog(); ${$foo}->paragraph( "Hi there!" ); ${$foo}->close;

As it currently stands, the above returns an error. "use diagnostics;" reveals that the value of ${$foo} is undefined. Upon further research, I have determined that using symbolic references in this context is destined to fail. This page talks about using hashes as references for functions, but I haven't been able to find anything on method calls that are stored as scalars, as in the first example code above.

My short term goal is to figure out the correct code to replace ${$foo} in the second code block above. Any help would be greatly appreciated!

Comment on Symbolic Reference in Method Call
Select or Download Code
Re: Symbolic Reference in Method Call
by Loops (Hermit) on Jun 27, 2013 at 17:02 UTC

    $rtf isn't a string. It's a RTF::Writer object created by the call to RTF::Writer->new_to_file(). Your problem isn't with references, so your search is bound to end in frustration. Perhaps you could explain what you're really trying to accomplish? Is it that you don't want to write output to a file? If so you can look at the RTF::Writer documentation which provides a way for you to send the output to a string instead with RTF::Writer->new_to_string(). Afterward, you can do whatever you like with the string.

Re: Symbolic Reference in Method Call
by kennethk (Monsignor) on Jun 27, 2013 at 17:02 UTC
    The appropriate reference here is Symbolic references. Code might look similar to the above, though be aware that by declaring $rtf with my, you are creating a lexical variable, not a package variable. This means it will get garbage collected, and may no longer exist by the time you want to access it. Much better than symbolic references are normal ones, e.g.
    use RTF::Writer; my $rtf = RTF::Writer->new_to_file("greetings.rtf"); my $foo = \$rtf; ${$foo}->prolog(); ${$foo}->paragraph( "Hi there!" ); ${$foo}->close;

    See Why it's stupid to use a variable as a variable name for why you are opening yourself up for pain. The above also passes strict.

    In the end, however, these types of games generally raises the specter of an XY Problem. Why do you need a reference to the object? Is this a caching thing, which might be addressed with proper scoping?


    #11929 First ask yourself `How would I do this without a computer?' Then have the computer do it the same way.

      I agree with kennethk, if you want to use symbolic references, there's a high probability that you are doing it wrong, or do not have a clear idea of what you are trying to do. But, if you know that you are asking for trouble, here is something that might help you :

      our $value = "package var"; my $value = "lexical var"; my $ref = "value"; $, = ", "; print ${$ref}, $value, eval "\$$ref";
      package var, lexical var, lexical var

      You should see there that you can only access dynamix variables with symbolic references, not lexicals.

      Thanks for your reply! I've added a description of what I'm actually trying to accomplish below. I'm also going to spend more time reading some of the links you've suggested.

Re: Symbolic Reference in Method Call
by EclecticScion (Novice) on Jun 27, 2013 at 17:55 UTC

    Thanks for the replies! Since people have asked what I'm trying to do, I've included a copy of the actual code below.

    I have another program that regex-searches lengthy documents and tries to sort the paragraphs into categories based on keywords. The other program colours the text of the various paragraphs based on what category it thinks it fits into, and then human assistants go over the coloured document to check that the categorization is correct. If it isn't, the human assistants change the text colour to the appropriate value manually. The files are in RTF format.

    The purpose of the second program is to take the correctly-coloured document and split in into six new files (one for each category). The code I have written effectively (although inelegantly) identifies the text colour of each paragraph. I then want to write the text of the paragraph to the appropriate file, based on the text colour of the paragraph.

    use diagnostics; use File::Slurp; use RTF::Writer; my @destinations = ('IAs','Defs','Term','Payoffs','RWs','Boilerplate2' +); my $targetfolder = "contract/new2"; opendir(DIR, "$targetfolder"); my @files = readdir(DIR); closedir(DIR); my $count = 0; foreach $file (@files) { if ($file =~ /rtf/i) { my $IAs = RTF::Writer->new_to_file("contract/IAs/$file") +; my $Defs = RTF::Writer->new_to_file("contract/Defs/$file +"); my $Term = RTF::Writer->new_to_file("contract/Term/$file +"); my $Payoffs = RTF::Writer->new_to_file("contract/Payoffs +/$file"); my $RWs = RTF::Writer->new_to_file("contract/RWs/$file") +; my $Boilerplate2 = RTF::Writer->new_to_file("contract/Bo +ilerplate2/$file"); my $contract = read_file("$targetfolder/$file"); my @paragraphs = split('cf', $contract); foreach $clause (@paragraphs) { my @lines = split("\n", "$clause"); if ($lines[0] =~ /^\d$/){ my $colour = $lines[0]; my $goal = \${$destinations["$colour"]}; #P +ROBLEM CODE my $destinationfolder = ("contract/$goal"); foreach $line (@lines) { if ($line =~ /^\s*\w/ && $line !~ /^\d$ +/){ ${$goal}->paragraph ( "$line", ); } } } } } $count++; }

    Essentially, I want to fix the line marked "#PROBLEM CODE", above. I'm going to go over the replies and links above to see if I can figure out a solution. Thanks again!

      You are quite close to a clean (IMHO) solution here. Rather than using symbolic references, I would just use a hash to store the writer references:
      use diagnostics; use File::Slurp; use RTF::Writer; my @destinations = ('IAs','Defs','Term','Payoffs','RWs','Boilerplate2' +); my $targetfolder = "contract/new2"; opendir(DIR, "$targetfolder"); my @files = readdir(DIR); closedir(DIR); my $count = 0; foreach $file (@files) { if ($file =~ /rtf/i) { my %writer; for my $dest (@destinations) { $writer{$dest} = RTF::Writer->new_to_file("contract +/$dest/$file"); } my $contract = read_file("$targetfolder/$file"); my @paragraphs = split('cf', $contract); foreach $clause (@paragraphs) { my @lines = split("\n", "$clause"); if ($lines[0] =~ /^\d$/){ my $colour = $lines[0]; my $goal = $writer{$destinations[$colour]}; + #NO-LONGER-PROBLEMATIC CODE my $destinationfolder = ("contract/$destinations +[$colour]"); # Also changed this one foreach $line (@lines) { if ($line =~ /^\s*\w/ && $line !~ /^\d$ +/){ $goal->paragraph ( "$line", ); } } } } } $count++; }
      Untested, though it passes strict. I think there are some simplifications you could make in the logic in your @lines loop as well.

      Remember that objects are just a subclass of scalars; and consider perusing perlreftut and perllol.


      #11929 First ask yourself `How would I do this without a computer?' Then have the computer do it the same way.

        I had some trouble for a while with a bug relating to my first program, but I can now confirm that the above code works perfectly. Thanks very much!

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1041048]
Approved by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others studying the Monastery: (9)
As of 2014-07-30 03:09 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    My favorite superfluous repetitious redundant duplicative phrase is:









    Results (229 votes), past polls