failing to apply eval to a string

Discussion in 'Perl Misc' started by Avner, Jan 9, 2006.

  1. Avner

    Avner Guest

    I want to create a parametrized check of the file type. Something like:
    return unless -f $_
    where the -f may be changed to -d in a different scenario. So I create
    a variabled string and apply eval to the string:

    e.g.
    $fileType = "-f";
    $cmdLine = "return unless $fileType $_";
    print "cmdLine: $cmdLine\n";
    eval $cmdLine;

    If I type the "return unless -f $_" the perl code acts correctly but if
    creating a variabled string and appling eval to it the code fails.
    Printing the cmdLine looks ok (it prints to the screen "cmdLine: return
    unless -f ." where . is the checked file
    but then I get the following error from the eval line
    Warning: Use of "-f" without parens is ambiguous at (eval 1) line 1.
    Error code: syntax error at (eval 1) line 2, at EOF

    What's wrong?

    Thanks,
    Avner
     
    Avner, Jan 9, 2006
    #1
    1. Advertising

  2. Avner

    Guest

    Avner wrote:
    > but then I get the following error from the eval line
    > Warning: Use of "-f" without parens is ambiguous at (eval 1) line 1.


    Maybe Perl is actually telling you what's wrong - maybe you ought to
    use parens (and quote your filename, since you're doing this as a
    string eval):

    my $cmdLine = "return unless $fileType ('$_')";

    FWIW, though, what you posted seems like a bit of a kludge...

    --
    http://DavidFilmer.com
     
    , Jan 9, 2006
    #2
    1. Advertising

  3. Avner

    Guest

    "Avner" <> wrote:
    > I want to create a parametrized check of the file type. Something like:
    > return unless -f $_
    > where the -f may be changed to -d in a different scenario. So I create
    > a variabled string and apply eval to the string:


    I wouldn't use eval in this context.

    if ($fileType eq "-f) {
    return unless -f $_;
    } elsif ($fileType eq "-d") {
    return unless -d $_;
    } else {
    die "Unsupported fileType $fileType"
    };

    >
    > e.g.
    > $fileType = "-f";
    > $cmdLine = "return unless $fileType $_";
    > print "cmdLine: $cmdLine\n";
    > eval $cmdLine;
    >
    > If I type the "return unless -f $_" the perl code acts correctly but if
    > creating a variabled string and appling eval to it the code fails.
    > Printing the cmdLine looks ok (it prints to the screen "cmdLine: return
    > unless -f ." where . is the checked file


    .. should be the quoted filename, or a variable. Not a bareword of the
    checked filename, which is what you probably have.

    Xho

    --
    -------------------- http://NewsReader.Com/ --------------------
    Usenet Newsgroup Service $9.95/Month 30GB
     
    , Jan 9, 2006
    #3
  4. Avner

    Avner Guest

    I tried it and it stll doesn't work
    Changing to
    $cmdLine1 = "return unless $fileType ('$_')";

    prints:
    cmdLine1: return unless -f ('.')

    and does nothing (does not return when checking the current directory
    file ".")
     
    Avner, Jan 9, 2006
    #4
  5. Avner

    Avner Guest

    Thanks Xho for your answer.

    I could do the if testing as you suggested but I don't want to limit
    the combinations of fileType parameter. I want to leave it open for any
    combination without having to update the code each time a new fileType
    comes.

    Also, next I planned on doing a check on the extention of the file.
    Something like

    $excludeFileExtFlag = "\.in\|\.h\$\|\.cpp\$\|\.c\$";
    return unless ($_ =~/$excludeFileExtFlag/);

    There as well I wouldn't want to introduce logic to my code and update
    the if block every time a new extention comes around.

    Could you explain why eval fails at the first place?
    Why won't it simply run the command as is? (the command prints out
    exactly as if it was typed into the code)

    Thanks,
    Avner
     
    Avner, Jan 9, 2006
    #5
  6. Avner

    Dr.Ruud Guest

    Dr.Ruud, Jan 9, 2006
    #6
  7. Avner <> wrote:

    > I want to create a parametrized check of the file type. Something like:
    > return unless -f $_
    > where the -f may be changed to -d in a different scenario. So I create
    > a variabled string and apply eval to the string:



    > If I type the "return unless -f $_" the perl code acts correctly but if
    > creating a variabled string and appling eval to it the code fails.
    > Printing the cmdLine looks ok (it prints to the screen "cmdLine: return
    > unless -f ." where . is the checked file



    That does NOT look ok to me...

    Compare:

    return unless -f . # dot is the concatenation operator here

    with

    return unless -f '.' # dot is a string here

    strings need quotes around them.


    > What's wrong?



    You have built the eval string incorrectly.


    --
    Tad McClellan SGML consulting
    Perl programming
    Fort Worth, Texas
     
    Tad McClellan, Jan 9, 2006
    #7
  8. Avner

    Avner Guest

    Tad McClellan wrote:
    > Avner <> wrote:
    >
    > > I want to create a parametrized check of the file type. Something like:
    > > return unless -f $_
    > > where the -f may be changed to -d in a different scenario. So I create
    > > a variabled string and apply eval to the string:

    >
    >
    > > If I type the "return unless -f $_" the perl code acts correctly but if
    > > creating a variabled string and appling eval to it the code fails.
    > > Printing the cmdLine looks ok (it prints to the screen "cmdLine: return
    > > unless -f ." where . is the checked file

    >
    >
    > That does NOT look ok to me...
    >
    > Compare:
    >
    > return unless -f . # dot is the concatenation operator here
    >
    > with
    >
    > return unless -f '.' # dot is a string here
    >
    > strings need quotes around them.
    >
    >
    > > What's wrong?

    >
    >
    > You have built the eval string incorrectly.
    >

    Your argument seems right to me but I don't know how to build the
    string correctly.
    How should I phrase the command line? I tried changing the fault
    command line from
    $cmdLine = "return unless $fileType $_";
    to (added quotes around $_)
    $cmdLine = "return unless $fileType '$_'";
    but it didn't help. The printed command is now
    return unless -f '.'
    and the code still does not catch the dot ('.') file.
    Besides, how do I generalize the code to deal with all sorts of file
    names?
    (the dot file is only one specific file name)

    Thanks,
    Avner





    >
    > --
    > Tad McClellan SGML consulting
    > Perl programming
    > Fort Worth, Texas
     
    Avner, Jan 9, 2006
    #8
  9. Avner

    Guest

    "Avner" <> wrote:
    > I tried it and it stll doesn't work
    > Changing to
    > $cmdLine1 = "return unless $fileType ('$_')";
    >
    > prints:
    > cmdLine1: return unless -f ('.')
    >
    > and does nothing (does not return when checking the current directory
    > file ".")


    eval statements are "returnable". So the "return" in your string is
    returning from the eval to the subrouting, rather than returning from the
    subroutine itself. I noticed that the first time, but then forgot to
    comment on it. Sorry about that.

    So you would want the eval statement to return a logical value, and
    have the test and the literal "return" be in the sub itself, not the eval:

    $cmdLine1 = "$fileType ('$_')";
    return unless eval $cmdLine;

    Xho

    --
    -------------------- http://NewsReader.Com/ --------------------
    Usenet Newsgroup Service $9.95/Month 30GB
     
    , Jan 9, 2006
    #9
  10. Avner

    Avner Guest

    wrote:
    > eval statements are "returnable". So the "return" in your string is
    > returning from the eval to the subrouting, rather than returning from the
    > subroutine itself. I noticed that the first time, but then forgot to
    > comment on it. Sorry about that.
    >
    > So you would want the eval statement to return a logical value, and
    > have the test and the literal "return" be in the sub itself, not the eval:
    >
    > $cmdLine1 = "$fileType ('$_')";
    > return unless eval $cmdLine;
    >
    > Xho


    Xho, that solved the problem and now I know better the nature of the
    eval command. You were really helpful. Thanks again.
    >
    > --
    > -------------------- http://NewsReader.Com/ --------------------
    > Usenet Newsgroup Service $9.95/Month 30GB
     
    Avner, Jan 9, 2006
    #10
  11. Avner

    Avner Guest

    Jim Gibson wrote:
    >
    > The return will return a value from the eval, not execute a return
    > statement in the context of the subroutine. However, you can capture
    > the outcome of the eval in a local variable and use that to test the
    > outcome of the file test operator:
    >
    > sub test_file
    > {
    > my( $file, $test ) = @_;
    > my $result;
    > my $cmd = "\$result = $test '$file'";
    > eval($cmd);
    > return unless $result;
    > ...
    > }
    >
    > ... which may be called as:
    >
    > test_file('-d',foo);


    Thanks for your advise Jim.

    >
    > Posted Via Usenet.com Premium Usenet Newsgroup Services
    > ----------------------------------------------------------
    > ** SPEED ** RETENTION ** COMPLETION ** ANONYMITY **
    > ----------------------------------------------------------
    > http://www.usenet.com
     
    Avner, Jan 9, 2006
    #11
  12. Avner <> wrote:
    >
    > wrote:
    >> eval statements are "returnable". So the "return" in your string is
    >> returning from the eval to the subrouting, rather than returning from the
    >> subroutine itself. I noticed that the first time, but then forgot to
    >> comment on it. Sorry about that.
    >>
    >> So you would want the eval statement to return a logical value, and
    >> have the test and the literal "return" be in the sub itself, not the eval:
    >>
    >> $cmdLine1 = "$fileType ('$_')";
    >> return unless eval $cmdLine;
    >>
    >> Xho

    >
    > Xho, that solved the problem



    Unless something "bad" finds its way into $fileType or $_ ...


    > and now I know better the nature of the
    > eval command.



    If it were my problem to solve, I would use a "dispatch table"
    instead, and not have to be worried about the evil string eval.

    my %tests = (
    f => sub { return -f $_[0] },
    d => sub { return -d $_[0] },
    );

    ...

    return unless $tests{$fileType}->($_);


    --
    Tad McClellan SGML consulting
    Perl programming
    Fort Worth, Texas
     
    Tad McClellan, Jan 9, 2006
    #12
  13. Avner

    Dave Weaver Guest

    Tad McClellan <> wrote:
    > If it were my problem to solve, I would use a "dispatch table"
    > instead, and not have to be worried about the evil string eval.
    >
    > my %tests = (
    > f => sub { return -f $_[0] },
    > d => sub { return -d $_[0] },
    > );
    >


    I would suggest adding a check along the lines of:

    die "test '$fileType' not defined" unless defined $tests{$fileType};

    > return unless $tests{$fileType}->($_);
     
    Dave Weaver, Jan 10, 2006
    #13
  14. Avner

    Anno Siegel Guest

    Tad McClellan <> wrote in comp.lang.perl.misc:
    > Avner <> wrote:
    > >
    > > wrote:
    > >> eval statements are "returnable". So the "return" in your string is
    > >> returning from the eval to the subrouting, rather than returning from the
    > >> subroutine itself. I noticed that the first time, but then forgot to
    > >> comment on it. Sorry about that.
    > >>
    > >> So you would want the eval statement to return a logical value, and
    > >> have the test and the literal "return" be in the sub itself, not the eval:
    > >>
    > >> $cmdLine1 = "$fileType ('$_')";
    > >> return unless eval $cmdLine;
    > >>
    > >> Xho

    > >
    > > Xho, that solved the problem

    >
    >
    > Unless something "bad" finds its way into $fileType or $_ ...
    >
    >
    > > and now I know better the nature of the
    > > eval command.

    >
    >
    > If it were my problem to solve, I would use a "dispatch table"
    > instead, and not have to be worried about the evil string eval.
    >
    > my %tests = (
    > f => sub { return -f $_[0] },
    > d => sub { return -d $_[0] },
    > );
    >
    > ...
    >
    > return unless $tests{$fileType}->($_);


    String eval may still have its place in building the table:

    my %tests;
    $tests{ $_} = eval "sub { return -$_ shift }" for qw( f d x M);

    Now the strings are under program control, there's nothing to be
    worried about.

    Anno
    --
    If you want to post a followup via groups.google.com, don't use
    the broken "Reply" link at the bottom of the article. Click on
    "show options" at the top of the article, then click on the
    "Reply" at the bottom of the article headers.
     
    Anno Siegel, Jan 10, 2006
    #14
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Eric Newton
    Replies:
    3
    Views:
    9,558
    Brock Allen
    Apr 4, 2005
  2. Stefan Siegl
    Replies:
    1
    Views:
    986
    Marrow
    Jul 18, 2003
  3. DataBinder.Eval and Eval.

    , Jun 16, 2006, in forum: ASP .Net
    Replies:
    1
    Views:
    573
    Karl Seguin [MVP]
    Jun 16, 2006
  4. Alex van der Spek

    eval('07') works, eval('08') fails, why?

    Alex van der Spek, Jan 8, 2009, in forum: Python
    Replies:
    6
    Views:
    1,529
    Bruno Desthuilliers
    Jan 8, 2009
  5. Raj Singh
    Replies:
    2
    Views:
    108
    Ken Bloom
    Jan 19, 2009
Loading...

Share This Page