Inject fresh variable in scope

Discussion in 'Perl Misc' started by Andrei Alexandrescu (See Website For Email), Nov 12, 2005.

  1. Hello,


    I set out to write a useful OnScopeExit feature that's supposed to
    execute some code when the current scope is exited. What I came up with is:

    package OnScopeExit;
    my $todo = sub {};
    sub new { shift; $todo = shift; bless {}; }
    sub DESTROY {
    &$todo;
    }
    package main;
    sub OnScopeExit(&) {
    return new OnExit(shift);
    }

    Now I can say in any scope I please:

    {
    ... code ...
    my $tempFile = "/tmp/temp.txt";
    my $cookie1 = OnScopeExit { unlink($tempFile); };
    ... code ...
    }

    Sure enough, when the current scope exits, the local $cookie1 will have
    its reference count go to zero, the DESTROY sub gets called, and the
    code that deletes the temporary file is invoked. Very nice.

    The only annoying part is that I need to define some "my" variable with
    a unique name for each OnScopeExit action I want to perform. Ideally,
    I'd only need to write:

    {
    ... code ...
    my $tempFile = "/tmp/temp.txt";
    OnScopeExit { unlink($tempFile); }
    ... code ...
    }

    that is, the creation of a lexically-scoped anonymous variable that will
    go out of scope should be somehow automated.

    I looked through symbol tables, scratchpads, and the ilk, for a couple
    of hours, to no avail. Is there a way?


    Thanks,

    Andrei
    Andrei Alexandrescu (See Website For Email), Nov 12, 2005
    #1
    1. Advertising

  2. "Andrei Alexandrescu (See Website For Email)"
    <> wrote in
    news::

    > I set out to write a useful OnScopeExit feature that's supposed to
    > execute some code when the current scope is exited.


    ....

    > Sure enough, when the current scope exits, the local $cookie1 will
    > have its reference count go to zero, the DESTROY sub gets called, and
    > the code that deletes the temporary file is invoked. Very nice.
    >
    > The only annoying part is that I need to define some "my" variable
    > with a unique name for each OnScopeExit action I want to perform.


    If you are willing to live with the necessity of creating only one
    lexically scoped AtExit object, you might find:

    http://search.cpan.org/~bradapp/AtExit-2.01/AtExit.pm

    useful.

    Sinan

    --
    A. Sinan Unur <>
    (reverse each component and remove .invalid for email address)

    comp.lang.perl.misc guidelines on the WWW:
    http://mail.augustmail.com/~tadmc/clpmisc/clpmisc_guidelines.html
    A. Sinan Unur, Nov 13, 2005
    #2
    1. Advertising

  3. "Andrei Alexandrescu (See Website For Email)"
    <> wrote in
    news::

    > Hello,
    >
    >
    > I set out to write a useful OnScopeExit feature that's supposed to
    > execute some code when the current scope is exited. What I came up
    > with is:
    >
    > package OnScopeExit;
    > my $todo = sub {};
    > sub new { shift; $todo = shift; bless {}; }
    > sub DESTROY {
    > &$todo;
    > }
    > package main;
    > sub OnScopeExit(&) {
    > return new OnExit(shift);
    > }
    >
    > Now I can say in any scope I please:
    >
    > {
    > ... code ...
    > my $tempFile = "/tmp/temp.txt";
    > my $cookie1 = OnScopeExit { unlink($tempFile); };
    > ... code ...
    > }
    >
    > Sure enough, when the current scope exits, the local $cookie1 will
    > have its reference count go to zero, the DESTROY sub gets called, and
    > the code that deletes the temporary file is invoked. Very nice.
    >
    > The only annoying part is that I need to define some "my" variable
    > with a unique name for each OnScopeExit action I want to perform.
    > Ideally, I'd only need to write:
    >
    > {
    > ... code ...
    > my $tempFile = "/tmp/temp.txt";
    > OnScopeExit { unlink($tempFile); }
    > ... code ...
    > }
    >
    > that is, the creation of a lexically-scoped anonymous variable that
    > will go out of scope should be somehow automated.
    >
    > I looked through symbol tables, scratchpads, and the ilk, for a couple
    > of hours, to no avail. Is there a way?


    I don't believe so. I tried this same sort of thing a while back,
    and I couldn't think of any way.

    Two things about your object class, above. One, you should not use
    a package variable ($todo) to store your action. What if someone needed
    to do this?

    {
    my $one = OnScopeExit {...};
    {
    my $two = OnScopeExit {...};
    }
    }

    For each object, store the to-do action *in* the object itself.
    Instead of:
    > sub new { shift; $todo = shift; bless {}; }

    do
    sub new { shift; bless { todo => shift }; }

    Second: Don't hardcode OnScopeExit to be in package main. What if
    you need an end-of-scope action in a module you're developing, a
    module that exists in a different namespace than "main"? Export it
    properly, via the Exporter module.

    HTH.

    --
    Eric
    `$=`;$_=\%!;($_)=/(.)/;$==++$|;($.,$/,$,,$\,$",$;,$^,$#,$~,$*,$:,@%)=(
    $!=~/(.)(.).(.)(.)(.)(.)..(.)(.)(.)..(.)......(.)/,$"),$=++;$.++;$.++;
    $_++;$_++;($_,$\,$,)=($~.$"."$;$/$%[$?]$_$\$,$:$%[$?]",$"&$~,$#,);$,++
    ;$,++;$^|=$";`$_$\$,$/$:$;$~$*$%[$?]$.$~$*${#}$%[$?]$;$\$"$^$~$*.>&$=`
    Eric J. Roode, Nov 13, 2005
    #3
  4. Andrei Alexandrescu (See Website For Email)

    Guest

    "Eric J. Roode" <> writes:

    > "Andrei Alexandrescu (See Website For Email)"
    > <> wrote in
    > news::
    >
    >> Hello,
    >>
    >>
    >> I set out to write a useful OnScopeExit feature that's supposed to
    >> execute some code when the current scope is exited. What I came up
    >> with is:
    >>
    >> package OnScopeExit;
    >> my $todo = sub {};
    >> sub new { shift; $todo = shift; bless {}; }
    >> sub DESTROY {
    >> &$todo;
    >> }
    >> package main;
    >> sub OnScopeExit(&) {
    >> return new OnExit(shift);
    >> }
    >>
    >> Now I can say in any scope I please:
    >>
    >> {
    >> ... code ...
    >> my $tempFile = "/tmp/temp.txt";
    >> my $cookie1 = OnScopeExit { unlink($tempFile); };
    >> ... code ...
    >> }
    >>
    >> Sure enough, when the current scope exits, the local $cookie1 will
    >> have its reference count go to zero, the DESTROY sub gets called, and
    >> the code that deletes the temporary file is invoked. Very nice.
    >>
    >> The only annoying part is that I need to define some "my" variable
    >> with a unique name for each OnScopeExit action I want to perform.
    >> Ideally, I'd only need to write:
    >>
    >> {
    >> ... code ...
    >> my $tempFile = "/tmp/temp.txt";
    >> OnScopeExit { unlink($tempFile); }
    >> ... code ...
    >> }
    >>
    >> that is, the creation of a lexically-scoped anonymous variable that
    >> will go out of scope should be somehow automated.
    >>
    >> I looked through symbol tables, scratchpads, and the ilk, for a couple
    >> of hours, to no avail. Is there a way?

    >
    > I don't believe so. I tried this same sort of thing a while back,
    > and I couldn't think of any way.
    >
    > Two things about your object class, above. One, you should not use
    > a package variable ($todo) to store your action. What if someone needed
    > to do this?
    >
    > {
    > my $one = OnScopeExit {...};
    > {
    > my $two = OnScopeExit {...};
    > }
    > }
    >
    > For each object, store the to-do action *in* the object itself.
    > Instead of:
    >> sub new { shift; $todo = shift; bless {}; }

    > do
    > sub new { shift; bless { todo => shift }; }
    >
    > Second: Don't hardcode OnScopeExit to be in package main. What if
    > you need an end-of-scope action in a module you're developing, a
    > module that exists in a different namespace than "main"? Export it
    > properly, via the Exporter module.


    ISTM that it could be done with a source filter e.g.

    use strict;
    use warnings;

    package OnScopeExitHelper;

    sub new ($&) {
    shift;
    return bless {code => shift};
    }

    sub DESTROY {
    &{$_[0]->{code}};
    }

    package UniqueVarName;

    require Tie::Scalar;
    our @ISA = qw /Tie::StdScalar/;

    our $base_var = "aaaaaaaaa";

    sub FETCH {
    return $base_var++;
    }

    package OnScopeExit;

    use Filter::Simple;
    use Regexp::Common qw /balanced/;

    our $var;
    tie $var, 'UniqueVarName';

    FILTER_ONLY code => sub { s{\b OnScopeExit \b
    \s+
    ( $RE{balanced}{-parens=>'{}'} )
    }
    {my \$$var = OnScopeExitHelper->new(sub $1)
    }gsx
    };

    1;

    Seems to work, but I expect that it could be improved.

    HTH

    --
    Brian Raven
    That should probably be written:
    no !@#$%^&*:mad:!semicolon
    -- Larry Wall in <>
    , Nov 14, 2005
    #4
  5. wrote in news::

    > ISTM that it could be done with a source filter
    >
    >


    Hmmm, that's not a bad idea. I must explore that.

    --
    Eric
    `$=`;$_=\%!;($_)=/(.)/;$==++$|;($.,$/,$,,$\,$",$;,$^,$#,$~,$*,$:,@%)=(
    $!=~/(.)(.).(.)(.)(.)(.)..(.)(.)(.)..(.)......(.)/,$"),$=++;$.++;$.++;
    $_++;$_++;($_,$\,$,)=($~.$"."$;$/$%[$?]$_$\$,$:$%[$?]",$"&$~,$#,);$,++
    ;$,++;$^|=$";`$_$\$,$/$:$;$~$*$%[$?]$.$~$*${#}$%[$?]$;$\$"$^$~$*.>&$=`
    Eric J. Roode, Nov 14, 2005
    #5
  6. wrote:
    > ISTM that it could be done with a source filter e.g.


    (snip)

    Thanks! Interesting idea; I got it to work, but then I noticed someone
    has written something along the same lines:

    http://search.cpan.org/~abergman/Hook-Scope-0.04/Scope.pm

    Now, I tried to install that, and found out it depends on a zillion
    other modules. Now, the question is: is there a simple way to manage
    dependencies in Perl - i.e., download a package and all of its
    dependents from somewhere? Thanks!


    Andrei
    Andrei Alexandrescu (See Website For Email), Nov 15, 2005
    #6
  7. Andrei Alexandrescu (See Website For Email) <> wrote:

    > Now, the question is: is there a simple way to manage
    > dependencies in Perl - i.e., download a package and all of its
    > dependents from somewhere?



    perldoc CPAN


    --
    Tad McClellan SGML consulting
    Perl programming
    Fort Worth, Texas
    Tad McClellan, Nov 15, 2005
    #7
    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. Steve C. Orr [MVP, MCSD]

    Fresh Starter

    Steve C. Orr [MVP, MCSD], Apr 2, 2004, in forum: ASP .Net
    Replies:
    4
    Views:
    405
    Abul Hasan
    Apr 3, 2004
  2. peshrad
    Replies:
    1
    Views:
    396
    Peter Blum
    Apr 9, 2004
  3. Peña, Botp

    inject does not inject last value

    Peña, Botp, Aug 7, 2006, in forum: Ruby
    Replies:
    4
    Views:
    178
    Peña, Botp
    Aug 7, 2006
  4. David Filmer
    Replies:
    19
    Views:
    238
    Kevin Collins
    May 21, 2004
  5. Andrew Falanga
    Replies:
    2
    Views:
    198
    Andrew Falanga
    Nov 22, 2008
Loading...

Share This Page