Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister
 
PerlMonks  

Probably an easy one - store command in variable.

by rementis (Beadle)
on Sep 15, 2005 at 16:35 UTC ( [id://492319]=perlquestion: print w/replies, xml ) Need Help??

rementis has asked for the wisdom of the Perl Monks concerning the following question:

OK, I've tried to do this just now using an anonymous subroutine, but I'm getting strange error messages. Here is my code:

my $command = sub { \@returnstring = \$d->checklist( text => $text, li +st => [ @list ] ) }; &$command;

Here is the error:

Can't modify reference constructor in scalar assignment at ./cdialog.p +l line 43, near ") }" Execution of ./cdialog.pl aborted due to compilation errors (#1) (F) You aren't allowed to assign to the item indicated, or otherwi +se try to change it, such as with an auto-increment. Uncaught exception from user code: Can't modify reference constructor in scalar assignment at ./c +dialog.pl line 43, near ") }" Execution of ./cdialog.pl aborted due to compilation errors.

Here's an update:

Here's the code I'm running now:

my $command = sub { $d->checklist( text => $text, list => [ @list ] ); }; my @returnlist = $command->();

And here's the error:

Can't use string (",") as an ARRAY ref while "strict refs" in use at /usr/local/lib/perl5/site_perl/5.8.3/UI/Dialog/Backend/CDialog +.pm line 581 (#1) (F) Only hard references are allowed by "strict refs". Symbolic references are disallowed. See perlref.

Also, in case it matters, list contains exactly this:

'1' , [ 'item1' , 0 ] , '2' , [ 'item2' , 0 ] , '3' , [ 'item3' , 0 ] , '4' , [ 'item4' , 0 ] , '5' , [ 'item5' , 0 ] , '6' , [ 'item6' , 0 ]

Janitor note: Original content follows:

Hello All-Knowing Monks,

I need to execute a command that I have built in a variable, like this:

my $command = "my \@returnstring = \$d->checklist( text => $text, list + => [ @list ] );";
If I print out the contents of $command I get exactly the line I want to execute, which looks like this:
my @returnstring = $d->checklist( text => Text, list => [ '1' , [ 'ite +m1' , 0 ] , '2' , [ 'item2' , 0 ] , '3' , [ 'item3' , 0 ] , '4' , [ ' +item4' , 0 ] , '5' , [ 'item5' , 0 ] , '6' , [ 'item6' , 0 ] ] );
But if I put $command; on a line by itself, the contents of $command are not executed as a statement. Is there any way to make the contents of $command execute as a statement?

Thanks in advance for any help!

Replies are listed 'Best First'.
Re: Probably an easy one - store command in variable.
by nobull (Friar) on Sep 15, 2005 at 16:50 UTC
    The simple (and wrong) answer is, of course, eval.

    Any variable declared within and eval(STRING) will go out of scope at the end of the eval().

    Perhaps you should take a step back and say why you think that you want to do this.

    I suspect the thing you are really looking for is the anonymous subroutine.

      expanding on the anonymous subroutine: you'd need something similar to this:
      my @list = qw(some random values); my $text = "bla bla bla"; my $command = sub { $d->checklist( text => $text, list => \@list ); }; my @returnlist = $command->();
      In this example $command is a closure - it "captures" the $text and @list variables. Depending on your problem that might or might not be the most elegant solution - without any context, it looks like you could also make a "normal" subroutine and pass those variables to it. YMMV.

Re: Probably an easy one - store command in variable.
by socketdave (Curate) on Sep 15, 2005 at 16:40 UTC
    This should do what you're looking for:
    eval $command;

    By the way, eval traps otherwise fatal errors, so pay attention to what's happening with the code being eval'd.

    Update:Thanks to everyone for pointing out the scoping and performance problems with eval. It just 'popped in there' like the Stay-Puffed marshmallow man.
      Just know that string eval can be costly (starts a new Perl interpreter) and potentially dangerous (you aren't using tainted user input to build this string are you?; run this with perl -T to find out for sure).

      Are you running this under use strict;? If so, then you will have some problems with my @returnsting. Specifically, you will need to have @returnstring declared before your eval to use it later. That means when you eval "my @returnstring = ...", you will create lexical variable within the scope of the eval that will mask the @returnstring that you declared outside of the eval scope. To solve this, simply remove the my from the string that you build.

      Ivan Heffner
      Sr. Software Engineer, DAS Lead
      WhitePages.com, Inc.
        Just a nit-pick; string eval does not start a new perl interpreter, although it does need to compile the $string every time the eval statement is executed, which usually makes it slow compared to alternative strategies.

        There are also some subtle issues and bugs with eval $string and scoping, but you're unlikely to run into them if you use eval $string sparingly. update: as nobull states: in this particular case, you've ran into one such issue: a lexical variable declared inside a string eval is not available outside of the eval statement :-)

Re: Probably an easy one - store command in variable.
by blazar (Canon) on Sep 15, 2005 at 16:49 UTC
    As socketdave told you, eval strictly answers your question. But there are good resons to discouraging one to use it, if possible. So I strongly recommend considering some alternative strategy, e.g. putting into $command a coderef. However without knowing what it is that you really want to accomplish it may be hard to give a suitable example...
Re: Probably an easy one - store command in variable.
by Roy Johnson (Monsignor) on Sep 15, 2005 at 17:16 UTC
    What do you want it to do? I suspect the backslashes shouldn't be there.

    Caution: Contents may have been coded under pressure.
Re: Probably an easy one - store command in variable.
by ikegami (Patriarch) on Sep 15, 2005 at 17:37 UTC

    Concerning your second update (Can't use string (",") as an ARRAY ref), It sounds like @list doesn't contain what you said it does. Could you use Data::Dumper on @list?

      @list contains commas and brackets, which are not showing up on this web page for some reason.
      It's like '1' comma left-bracket 'item1' comma 0 right bracket and so on.
        Put your code inside of <code> tags for it to show properly. Anyway, I took that into consideration when I wrote my post. My request stands.
Re: Probably an easy one - store command in variable.
by injunjoel (Priest) on Sep 15, 2005 at 19:36 UTC
    Greetings all,
    I agree with Roy Johnson about the slashes. you are trying to make @results a reference on the left hand side, which is why you are getting the error.
    Here are my suggestions for modifying your code.
    my $command = sub { my @returnstring = $d->checklist( text => $text, list => [ @list ] + ); return \@returnstring; }; my $some_ref = &$command;
    Now if you wanted the array from $d->checklist() to return as a reference itself you might try.
    my $command = sub { my $returnstring = \($d->checklist( text => $text, list => [ @list + ] )); return $returnstring; }; my $some_ref = &$command;
    However if you already have declared @returnstring outside of the scope of your anonymous sub and you wish to use this sub to modify it then you could simply do something like this...
    my @returnstring; my $command = sub { @returnstring = $d->checklist( text => $text, list => [ @list ] ); };
    again assuming that $d->checklist() returns an array.
    A simple way to think of it is that references get assigned to something. So the \ is allowed on the right hand side only.
    At least thats what works for me. :)
    These examples are untested but I think, as Roy Johnson pointed out, that your slashes are the problem.

    -InjunJoel
    "I do not feel obliged to believe that the same God who endowed us with sense, reason and intellect has intended us to forego their use." -Galileo

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others exploiting the Monastery: (6)
As of 2024-04-25 11:04 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found