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

I'd like to store routine as in t.yml:
--- - - 1 - sub { print "one" }
and use it as in t.pl:
use YAML; my $s = YAML::LoadFile( "t.yml" ); my $f = $s->[ 0 ]->[ 1 ]; $f->();
but...
perl t.pl Undefined subroutine &main::sub { print "one" } called at t.pl line 10 +.
Any advice to make this work? Thanks.

Replies are listed 'Best First'.
Re: code reference in YAML
by CountZero (Bishop) on Jan 27, 2011 at 07:21 UTC
    It is a bit more complicated than your code.

    First the YAML file looks like this:

    --- - - 1 - !!perl/code | { print "one"; }
    And to use code from a YAML file you must put the UseCode-switch on.

    use Modern::Perl; use YAML qw/LoadFile/; local $YAML::UseCode = 1; my $s = YAML::LoadFile( "code.yml" ); my $f = $s->[ 0 ]->[ 1 ]; $f->();

    Beware that using Perl code from a YAML file involves this code to be evaled, with all security risks that come with it. That is the reason why by default the UseCode-switch is 0 (off).

    CountZero

    A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

      Thank you CountZero! I would have never known !!perl/code... Your example worked perfectly with my Strawberry Perl, except for this warning message. I think it is from *use warnings* in Modern::Perl. We can live with that. :) Thanks again!
      perl t.pl Name "YAML::UseCode" used only once: possible typo at t.pl line 4. one
        Actually, in order to find out how to write the YAML file I reverse engineered the YAML file.

        I made the data-structure you wanted to have and then dumped it into a YAML file. Easy as pie!

        CountZero

        A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

        Update: Both solutions below are better. I didn't think of how ugly "local ... if ...;" was.


        If you want to make the warning go away without disabling warnings, you could reference the variable twice, like so:

        local $YAML::UseCode = 1 if ! defined $YAML::UseCode;

        ...roboticus

        When your only tool is a hammer, all problems look like your thumb.