Using closures with "use strict"

Discussion in 'Perl Misc' started by Ben Morrow, Jun 23, 2004.

  1. Ben Morrow

    Ben Morrow Guest

    Quoth ddtl <this.is@invalid>:
    >
    > If I define a "use strict" and want to create a closure,
    > how can I refer to the anonymous functions defined in that
    > closure? Consider the following example:
    >
    > -------------------------------------------
    > use strict;
    >
    > {
    > our $f = sub {print "Hi\n";};
    > }
    >
    > &$f;
    > -------------------------------------------
    >
    > Here compiler complains, and reports an error:
    >
    > "Variable "$f" is not imported at ~/test line 7."


    The variable declared by 'our' is a lexically-scoped alias to the
    package global, so you need to put it in the same place as you would put
    an equivalent 'my' variable. What you want is

    use strict;

    our $f;
    {
    # presumably there is more code here?

    $f = sub {...};
    }

    # I prefer this style of indirect function call, as it matches the other
    # deref ops and doesn't lead to potential confusion about calling named
    # subs with &.

    $f->();

    or perhaps

    our $f = do {
    ...
    sub {...};
    };

    Ben

    --
    All persons, living or dead, are entirely coincidental.
    Kurt Vonnegut
    Ben Morrow, Jun 23, 2004
    #1
    1. Advertising

  2. ddtl <this.is@invalid> wrote in message
    <news:>:

    > If I define a "use strict" and want to create a closure,
    > how can I refer to the anonymous functions defined in that
    > closure? Consider the following example:
    >
    > -------------------------------------------
    > use strict;
    >
    > {
    > our $f = sub {print "Hi\n";};
    >}
    >
    > &$f;
    > -------------------------------------------


    That doesn't fit my idea of a closure. It's just a code reference.
    As you noted, the code above is broken because variables declared
    with our() are lexically scoped.

    A closure (as I understand it) is a subroutine that keeps track of
    lexical variables that are within scope when that subroutine is
    defined, so that later it can still access those variables even
    though they're out of the present scope.

    For example:

    use strict;

    my $f;
    {
    my $string = 'test';
    sub set_string { $string = $_[0] }
    sub get_string { $string }
    $f = \&get_string;
    }

    print get_string(), "\n";
    set_string('something else');
    print get_string(), "\n";

    # call get_string() using a code reference
    print $f->(), "\n";

    # this statement will generate an error, because $string is
    # now out of scope
    print "\$string = $string\n";


    set_string() and get_string() are closures. $f is just a code
    reference to what happens to be a closure.
    David K. Wall, Jun 23, 2004
    #2
    1. Advertising

  3. Ben Morrow

    ddtl Guest

    Hello,

    If I define a "use strict" and want to create a closure,
    how can I refer to the anonymous functions defined in that
    closure? Consider the following example:

    -------------------------------------------
    use strict;

    {
    our $f = sub {print "Hi\n";};
    }

    &$f;
    -------------------------------------------

    Here compiler complains, and reports an error:

    "Variable "$f" is not imported at ~/test line 7."

    Obviously, though 'f' is declared using 'our' modifier, as there
    is no such a global variable called 'f', using 'our $f;' creates
    some kind of restricted global variable (don't know even how to
    call it - that variable works like a global one, but it's "globalness"
    is restricted to the enclosing block).

    In order to rectify it (and still have the benefits of "use strict",
    there are two possibilities that I can see:

    1) Enclose closure and every call to anonymous function defined in
    the closure in "no strict":

    ------------------------------------
    use strict;

    {
    no strict;
    $f = sub {print "Hi\n";};
    use strict;

    }

    #...
    #...

    no strict;
    &$f;
    use strict;
    #...
    #...
    ------------------------------------

    2) Define all the references to anonymous functions in closure as
    "our $REF_NAME" somewhere outside the block:


    ------------------------------------
    use strict;

    {
    our $f = sub {print "Hi\n";};
    }
    our $f;

    &$f;
    ------------------------------------


    Another solution can maybe involve some tricks with package declarations,
    but I am only in the "Chapter 8" of "Programming Perl", so I can't
    be sure.


    The problem is, that all those solutions are looking very contrived
    and ugly.

    Is there is a better way to do that?


    ddtl.
    ddtl, Jun 23, 2004
    #3
  4. ddtl (this.is@invalid) wrote:

    : Hello,

    : If I define a "use strict" and want to create a closure,
    : how can I refer to the anonymous functions defined in that
    : closure? Consider the following example:

    : -------------------------------------------
    : use strict;

    : {
    : our $f = sub {print "Hi\n";};
    : }

    : &$f;
    : -------------------------------------------

    : Here compiler complains, and reports an error:

    : "Variable "$f" is not imported at ~/test line 7."

    : Obviously, though 'f' is declared using 'our' modifier, as there
    : is no such a global variable called 'f', using 'our $f;' creates
    : some kind of restricted global variable (don't know even how to
    : call it - that variable works like a global one, but it's "globalness"
    : is restricted to the enclosing block).
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

    Yes (sort of), that's what "our" does. It tells the compiler you intend
    to access the global variable $f, but only within the current scope.

    If you intend to access the same global variable within a different scope
    then it must also be defined within that different scope as well.

    There are various things you could do. (most examples untested)

    #1
    use strict;
    my $f;
    {
    $f = sub {print "Hi\n";};
    }
    &$f;

    #2
    use strict;
    our $f;
    {
    $f = sub {print "Hi\n";};
    }
    &$f;

    #3
    use strict;
    {
    our $f = sub {print "Hi\n";};
    }
    our $f;
    &$f;
    #4
    use strict;
    {
    our $f = sub {print "Hi\n";};
    }
    {
    our $f;
    &$f;
    }

    #5
    use strict;
    yse vars '$f';
    {
    $f = sub {print "Hi\n";};
    }
    &$f;

    and possibly others. Unless $f must be accessed by routines in different
    files then the #1 (my $f) is probably best. However, "our" does have the
    advantage that you can declare it within smaller blocks as needed (#4),
    which makes it available to less than the entire file (unlike my, where
    everything after the declaration must see the variable if any of the code
    is to see it).
    Malcolm Dew-Jones, Jun 23, 2004
    #4
  5. ddtl <this.is@invalid> wrote:

    > If I define a "use strict" and want to create a closure,


    > -------------------------------------------
    > use strict;
    >
    > {
    > our $f = sub {print "Hi\n";};
    > }
    >
    > &$f;
    > -------------------------------------------



    There is no closure there you know.

    Maybe your question is how to make a closure or what constitutes
    a "closure"?


    > Obviously, though 'f' is declared using 'our' modifier, as there
    > is no such a global variable called 'f', using 'our $f;' creates
    > some kind of restricted global variable (don't know even how to
    > call it - that variable works like a global one, but it's "globalness"
    > is restricted to the enclosing block).



    I think you are confusing the scope of the _name_ of the variable
    with being able to access the value of the variable.

    You can always access package variables (so they are "global").

    All our() does for you is give you temporary ('til end of block)
    permission to use short names instead of fully qualified names.

    with our($x):

    print $x;


    without our($x):

    print $main::x;

    or

    print $Cool::package::x;


    You can access the value at any place in the code, its value is global.

    You can access the value by the "short name" only in the our()'s scope.


    > Is there is a better way to do that?



    I think the other followups have already done that part.


    --
    Tad McClellan SGML consulting
    Perl programming
    Fort Worth, Texas
    Tad McClellan, Jun 24, 2004
    #5
  6. Ben Morrow

    ddtl Guest


    >> -------------------------------------------
    >> use strict;
    >>
    >> {
    >> our $f = sub {print "Hi\n";};
    >>}
    >>
    >> &$f;
    >> -------------------------------------------

    >
    >That doesn't fit my idea of a closure. It's just a code reference.
    >As you noted, the code above is broken because variables declared
    >with our() are lexically scoped.
    >
    >A closure (as I understand it) is a subroutine that keeps track of
    >lexical variables that are within scope when that subroutine is
    >defined, so that later it can still access those variables even
    >though they're out of the present scope.


    You are right of course - this is not actually a closure, but was just too
    lazy to type the whole ~10 more characters to provide anonymous sub
    with it's "personal" scoped variables :). Anyway, the question was clearly
    understood by everybody, despite of my lazyness.

    ddtl.
    ddtl, Jun 24, 2004
    #6
    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. H. Wade Minter
    Replies:
    8
    Views:
    286
    Robin
    Apr 25, 2004
  2. Martina

    why is important to use : use strict?

    Martina, Sep 19, 2005, in forum: Perl Misc
    Replies:
    6
    Views:
    98
    J├╝rgen Exner
    Sep 20, 2005
  3. Ting Wang
    Replies:
    5
    Views:
    172
    John Bokma
    Oct 6, 2005
  4. Peng Yu

    When to use "use strict;"?

    Peng Yu, Jan 25, 2010, in forum: Perl Misc
    Replies:
    14
    Views:
    176
    John Bokma
    Jan 27, 2010
  5. Marius Gavrilescu

    Re: use strict; use warnings;

    Marius Gavrilescu, Feb 24, 2014, in forum: Perl Misc
    Replies:
    152
    Views:
    484
    $Bill
    Mar 11, 2014
Loading...

Share This Page