How to define a sub on the fly?

Discussion in 'Perl Misc' started by kj, Apr 30, 2004.

  1. kj

    kj Guest

    Can someone please show me how to define a sub Foo::Bar::baz on
    the fly (i.e. when the module is loaded)?

    Thanks!

    kj

    --
    NOTE: In my address everything before the period is backwards.
    kj, Apr 30, 2004
    #1
    1. Advertising

  2. In article <c6uipi$inb$>, kj <> wrote:
    :Can someone please show me how to define a sub Foo::Bar::baz on
    :the fly (i.e. when the module is loaded)?

    Try constructing it inside a BEGIN block. BEGIN blocks are executed
    as the module is loaded.
    --
    Disobey all self-referential sentences!
    Walter Roberson, Apr 30, 2004
    #2
    1. Advertising

  3. kj

    Uri Guttman Guest

    >>>>> "WR" == Walter Roberson <-cnrc.gc.ca> writes:

    WR> In article <c6uipi$inb$>, kj <> wrote:
    WR> :Can someone please show me how to define a sub Foo::Bar::baz on
    WR> :the fly (i.e. when the module is loaded)?

    WR> Try constructing it inside a BEGIN block. BEGIN blocks are executed
    WR> as the module is loaded.

    that won't help much. the module itself is executed at compile time when
    it is loaded by the use statement so the BEGIN block gains little there.

    but i would ask the OP what they mean by creating a sub on the fly and
    why does he think it is needed? it isn't hard to do but i won't help if
    it is not even needed.

    uri

    --
    Uri Guttman ------ -------- http://www.stemsystems.com
    --Perl Consulting, Stem Development, Systems Architecture, Design and Coding-
    Search or Offer Perl Jobs ---------------------------- http://jobs.perl.org
    Uri Guttman, May 1, 2004
    #3
  4. kj () wrote:
    : Can someone please show me how to define a sub Foo::Bar::baz on
    : the fly (i.e. when the module is loaded)?

    Since that's the normal case, I'll assume you mean you want to define it
    in an unusual manner. The following probably defines two subs called baz
    and boz, though I can't test it while using this computer.


    foreach $baz (qw(baz boz))
    { eval qq{
    sub Foo::Bar::$baz
    { print "This is sub Foo Bar $baz\n";
    }
    };
    }


    (oh dear, ATARI sm125 appears to be toasting, bye bye to an old faithful
    companion. I wonder if this will make sense. Better stop typing
    Malcolm Dew-Jones, May 1, 2004
    #4
  5. kj

    kj Guest

    In <> Uri Guttman <> writes:

    >>>>>> "WR" == Walter Roberson <-cnrc.gc.ca> writes:


    > WR> In article <c6uipi$inb$>, kj <> wrote:
    > WR> :Can someone please show me how to define a sub Foo::Bar::baz on
    > WR> :the fly (i.e. when the module is loaded)?


    >but i would ask the OP what they mean by creating a sub on the fly and
    >why does he think it is needed? it isn't hard to do but i won't help if
    >it is not even needed.


    OK, here's the situation. The module in question has the simple
    task of serving information contained in a *variable* collection
    of data flat-files (data/A, data/B, ..., data/X, etc.). For me,
    the most natural way to code this would be to have a sub/method
    that took a filename as argument (e.g. get_data("$path/data/B")),
    but for reasons that have to do with the software framework in
    which this module will operate, it is necessary, instead, to have
    several separate subroutines named after the data files (e.g. sub
    A { ... }, etc., which could simply call get_data("$path/data/A").
    And since the names of these files cannot be known until runtime,
    these subroutines can only be defined then.

    Thanks,

    kj
    --
    NOTE: In my address everything before the period is backwards.
    kj, May 1, 2004
    #5
  6. kj

    Uri Guttman Guest

    >>>>> "k" == kj <> writes:

    k> In <> Uri Guttman
    k> <> writes:

    >> but i would ask the OP what they mean by creating a sub on the fly and
    >> why does he think it is needed? it isn't hard to do but i won't help if
    >> it is not even needed.


    k> OK, here's the situation. The module in question has the simple
    k> task of serving information contained in a *variable* collection of
    k> data flat-files (data/A, data/B, ..., data/X, etc.). For me, the
    k> most natural way to code this would be to have a sub/method that
    k> took a filename as argument (e.g. get_data("$path/data/B")), but
    k> for reasons that have to do with the software framework in which
    k> this module will operate, it is necessary, instead, to have several
    k> separate subroutines named after the data files (e.g. sub A { ...
    k> }, etc., which could simply call get_data("$path/data/A"). And
    k> since the names of these files cannot be known until runtime, these
    k> subroutines can only be defined then.

    then how do you determine which method to call? i mean how does the
    driving code select the method? is based on the filename itself? what is
    the class this object is in? could it have an attribute that is the
    filename? one way to solve this is via polymophism. you create a set of
    classes named for the file (e.g. MyData::A) which all implement the
    get_data method. the framework then builds a class name based on the
    file name and uses that to create a new object. then it calls get_data
    (remember, the same method name in all the classes) and voila, you have
    your data. but it all sounds like too much work in any case. what kind
    of framework can't handle simple args or a dispatch table.

    uri

    --
    Uri Guttman ------ -------- http://www.stemsystems.com
    --Perl Consulting, Stem Development, Systems Architecture, Design and Coding-
    Search or Offer Perl Jobs ---------------------------- http://jobs.perl.org
    Uri Guttman, May 1, 2004
    #6
  7. kj

    Anno Siegel Guest

    Uri Guttman <> wrote in comp.lang.perl.misc:
    > >>>>> "k" == kj <> writes:

    >
    > k> In <> Uri Guttman
    > k> <> writes:
    >
    > >> but i would ask the OP what they mean by creating a sub on the fly and
    > >> why does he think it is needed? it isn't hard to do but i won't help if
    > >> it is not even needed.

    >
    > k> OK, here's the situation. The module in question has the simple
    > k> task of serving information contained in a *variable* collection of
    > k> data flat-files (data/A, data/B, ..., data/X, etc.). For me, the
    > k> most natural way to code this would be to have a sub/method that
    > k> took a filename as argument (e.g. get_data("$path/data/B")), but
    > k> for reasons that have to do with the software framework in which
    > k> this module will operate, it is necessary, instead, to have several
    > k> separate subroutines named after the data files (e.g. sub A { ...
    > k> }, etc., which could simply call get_data("$path/data/A"). And
    > k> since the names of these files cannot be known until runtime, these
    > k> subroutines can only be defined then.
    >
    > then how do you determine which method to call? i mean how does the


    I'm not sure the OP's framework is OO at all.

    > driving code select the method? is based on the filename itself?


    That's the question, whether OO or not. Making the names of subroutines
    dependent on exterior filenames breaks the program/data separation.
    Making the sub calls later may break it again.

    > the class this object is in? could it have an attribute that is the
    > filename? one way to solve this is via polymophism. you create a set of
    > classes named for the file (e.g. MyData::A) which all implement the
    > get_data method. the framework then builds a class name based on the
    > file name and uses that to create a new object.


    What is the object for? The get_data method doesn't need one, it might
    as well be a class method and be called as such. You would need to call
    a class method to create the object in any case, it might as well do
    the actual job. IOW, instead of doing

    my $class = 'MyData::' . $filename;
    my $obj = $class->new;
    my $data = $obj->get_data;

    say

    my $class = 'MyData::' . $filename;
    my $data = $class->get_data;

    > then it calls get_data
    > (remember, the same method name in all the classes) and voila, you have
    > your data. but it all sounds like too much work in any case. what kind
    > of framework can't handle simple args or a dispatch table.


    I'm wondering that too...

    Anno
    Anno Siegel, May 1, 2004
    #7
  8. Walter Roberson wrote:
    > In article <c6uipi$inb$>, kj <> wrote:
    > :Can someone please show me how to define a sub Foo::Bar::baz on
    > :the fly (i.e. when the module is loaded)?
    >
    > Try constructing it inside a BEGIN block. BEGIN blocks are executed
    > as the module is loaded.

    Sidestepping the rest of the thread (ie the validity of doing this), you
    can use the autoloader and/or eval. Creation of subs (or any code on the
    fly) can be done with eval $definition.

    eg
    eval<<EOF;
    sub newsub(){
    return "from newsub";
    };
    EOF

    You may well want to take this step within a BEGIN block. Bear in mind
    prototypes are meaningless when a sub is called as a class or object method.

    There are many examples of using the autoloader available so I won't
    give one here, but you probably want to use it to intercept calls to eg
    get_filename1(), get_filename2() and take it from there.

    Mark
    Mark Clements, May 1, 2004
    #8
  9. kj

    Anno Siegel Guest

    Mark Clements <> wrote in comp.lang.perl.misc:
    > Walter Roberson wrote:
    > > In article <c6uipi$inb$>, kj <> wrote:
    > > :Can someone please show me how to define a sub Foo::Bar::baz on
    > > :the fly (i.e. when the module is loaded)?
    > >
    > > Try constructing it inside a BEGIN block. BEGIN blocks are executed
    > > as the module is loaded.

    > Sidestepping the rest of the thread (ie the validity of doing this), you
    > can use the autoloader and/or eval. Creation of subs (or any code on the
    > fly) can be done with eval $definition.


    ....it can, granted, but there's no real need for "eval".

    > eg
    > eval<<EOF;
    > sub newsub(){


    Why the prototype? They are the exception with sub definitions, not
    the rule.

    > return "from newsub";
    > };
    > EOF


    *newsub = sub { return "from newsub" };

    has the same effect, but is clearer and simpler.

    Anno
    Anno Siegel, May 1, 2004
    #9
  10. kj

    Anno Siegel Guest

    Mark Clements <> wrote in comp.lang.perl.misc:
    > Walter Roberson wrote:
    > > In article <c6uipi$inb$>, kj <> wrote:
    > > :Can someone please show me how to define a sub Foo::Bar::baz on
    > > :the fly (i.e. when the module is loaded)?
    > >
    > > Try constructing it inside a BEGIN block. BEGIN blocks are executed
    > > as the module is loaded.

    > Sidestepping the rest of the thread (ie the validity of doing this), you
    > can use the autoloader and/or eval. Creation of subs (or any code on the
    > fly) can be done with eval $definition.


    ....it can, granted, but there's no real need for "eval".

    > eg
    > eval<<EOF;
    > sub newsub(){


    Why the prototype? They are the exception with sub definitions, not
    the rule.

    > return "from newsub";
    > };
    > EOF


    *newsub = sub { return "from newsub" };

    has the same effect, but is clearer and simpler.

    Anno
    Anno Siegel, May 1, 2004
    #10
  11. Anno Siegel wrote:

    >>eval<<EOF;
    >> sub newsub(){

    >
    >
    > Why the prototype? They are the exception with sub definitions, not
    > the rule.

    I tend to use them because if used correctly they enable the compiler to
    catch attempts to call subs with the wrong number of arguments, though
    obviously here they'll have no effect as the compiler can't see the
    definition of the new sub. It was therefore misleading of me to use it here.


    >
    > *newsub = sub { return "from newsub" };

    In this case, yes, but I don't see how this enables you to build
    subroutines on the fly. eval STRING is relatively inefficient but
    extremely powerful (and therefore dangerous).

    Mark
    Mark Clements, May 1, 2004
    #11
  12. kj

    Peter Scott Guest

    In article <4093882c$>,
    Mark Clements <> writes:
    >Anno Siegel wrote:


    >> *newsub = sub { return "from newsub" };

    >In this case, yes, but I don't see how this enables you to build
    >subroutines on the fly.


    Closures.

    {
    my $thing = "foo";
    my $method = "${thing}_method";
    no strict 'refs';
    *$method = sub { ... do something with $thing ... };
    }

    --
    Peter Scott
    http://www.perldebugged.com/
    *** NEW *** http://www.perlmedic.com/
    Peter Scott, May 1, 2004
    #12
  13. kj

    Anno Siegel Guest

    Mark Clements <> wrote in comp.lang.perl.misc:
    > Anno Siegel wrote:
    >
    > >>eval<<EOF;
    > >> sub newsub(){

    > >
    > >
    > > Why the prototype? They are the exception with sub definitions, not
    > > the rule.

    > I tend to use them because if used correctly they enable the compiler to
    > catch attempts to call subs with the wrong number of arguments,


    True, but it also makes your subs behave weirdly, supplying unexpected
    context to arguments or even silently taking references. In my view,
    prototypes can (sparingly) be used in interface-type functions to
    help the user deal with them, or to allow suggestive syntax. The
    non-standard behavior must be clearly documented. Few Perl programmers
    use prototypes routinely with all subs.

    > though
    > obviously here they'll have no effect as the compiler can't see the
    > definition of the new sub. It was therefore misleading of me to use it here.
    >
    >
    > >
    > > *newsub = sub { return "from newsub" };

    > In this case, yes, but I don't see how this enables you to build
    > subroutines on the fly. eval STRING is relatively inefficient but
    > extremely powerful (and therefore dangerous).


    If you actually need to compile a string of code for the new sub, there
    is no way around "eval".

    Often a closure gives enough flexibility. If the sub needs to read a
    particular file, this would do (simplified, untested):

    sub create_sub {
    my $name = shift;
    my $sub = sub {
    open( my $f, $name) or die "Can't read file '$name': $!";
    # ...
    };
    no strict 'refs';
    *{ 'read_' . $name} = $sub;
    }

    That creates one named closure per call, each reading the file it is
    named after. No need for "eval" here.

    Anno
    Anno Siegel, May 1, 2004
    #13
  14. kj

    kj Guest

    In <> Uri Guttman <> writes:

    >>>>>> "WR" == Walter Roberson <-cnrc.gc.ca> writes:


    > WR> In article <c6uipi$inb$>, kj <> wrote:
    > WR> :Can someone please show me how to define a sub Foo::Bar::baz on
    > WR> :the fly (i.e. when the module is loaded)?


    > WR> Try constructing it inside a BEGIN block. BEGIN blocks are executed
    > WR> as the module is loaded.


    >that won't help much. the module itself is executed at compile time when
    >it is loaded by the use statement so the BEGIN block gains little there.


    >but i would ask the OP what they mean by creating a sub on the fly and
    >why does he think it is needed? it isn't hard to do but i won't help if
    >it is not even needed.


    The framework I was referring to is a Web services one, in which
    clients discover and call a server's available services at runtime.
    (I should add that this framework is horribly designed, and even
    worse implemented--all out of my hands.) As it turns out, at our
    site the menu of services that fit this model is one that is
    dynamically changing (the sources of available data, each corresponding
    to a different data file, will change from one day to the next,
    both in number and in content). In this case, clients "discover"
    desired services typically by requesting desired input and output
    signatures. The input signature for all these possible services
    has no room for a filename, or any other parameter that could be
    used to select among all the services provided at our site at any
    given time. Likewise, the service dispatching protocol (which I
    don't control) matches service names to methods in a 1-to-1 way
    (in fact the service names are expected to be identical to the
    names of the corresponding methods that the dispatcher calls). I
    don't see any way to match this API other than by providing separate
    methods for each data source file available at our site on a given
    day, even if these methods all end up calling the same core method
    with an additional argument (the source file to use). (The
    meta-service that describes all the services available at our site
    to interested clients would also need to determine these methods
    dynamically.)

    kj
    --
    To s&e^n]d me m~a}i]l r%e*m?o\v[e bit from my a|d)d:r{e:s]s.
    kj, May 1, 2004
    #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. THY
    Replies:
    1
    Views:
    394
    Steve C. Orr, MCSD
    Aug 19, 2003
  2. Lee Sander
    Replies:
    7
    Views:
    302
  3. Ben
    Replies:
    2
    Views:
    882
  4. Lawrence D'Oliveiro

    Death To Sub-Sub-Sub-Directories!

    Lawrence D'Oliveiro, May 5, 2011, in forum: Java
    Replies:
    92
    Views:
    2,019
    Lawrence D'Oliveiro
    May 20, 2011
  5. Brian

    Fly outmenu on the fly

    Brian, Apr 8, 2005, in forum: Javascript
    Replies:
    0
    Views:
    103
    Brian
    Apr 8, 2005
Loading...

Share This Page