Lexical scoping question.

Discussion in 'Perl Misc' started by Louis., Feb 10, 2005.

  1. Louis.

    Louis. Guest

    Hi,

    The below script will print "var is apple". I find this weird, because
    in textbooks you are taught to pass variable to subroutines as
    parameters. What is the point of doing this, if the variable is
    visible anyway?

    How can I make the variable exist in main and yet be invisible to the
    subroutine? I know I can create another variable with "my" and with
    the same name in the subroutine. This will block the subroutine from
    seeing variable in main, but is this really the way to do it, it seems
    very cumbersom.

    TIA,
    Louis.

    my $var = "apple";
    routine();

    sub routine {
    print "var is $var.\n";
    }




    Solution???

    {
    my $var = "apple";
    routine($var);
    }

    sub routine {
    my $var = $_[0];
    print "var is $var.\n";
    }
     
    Louis., Feb 10, 2005
    #1
    1. Advertising

  2. Louis.

    Larry Guest

    Louis. wrote:
    > Hi,
    >
    > The below script will print "var is apple". I find this weird,

    because
    > in textbooks you are taught to pass variable to subroutines as
    > parameters. What is the point of doing this, if the variable is
    > visible anyway?
    >
    > How can I make the variable exist in main and yet be invisible to the
    > subroutine? I know I can create another variable with "my" and with
    > the same name in the subroutine. This will block the subroutine from
    > seeing variable in main, but is this really the way to do it, it

    seems
    > very cumbersom.
    >
    > TIA,
    > Louis.
    >
    > my $var = "apple";
    > routine();
    >
    > sub routine {
    > print "var is $var.\n";
    > }
    >
    >
    >
    >
    > Solution???
    >
    > {
    > my $var = "apple";
    > routine($var);
    > }
    >
    > sub routine {
    > my $var = $_[0];
    > print "var is $var.\n";
    > }


    #include <stdio.h>

    int print_a();
    int a = 5;
    int main()
    {
    print_a();
    }
    int print_a()
    {
    printf("%d\n",a);
    }

    looks like you can mess it up in C too.
     
    Larry, Feb 10, 2005
    #2
    1. Advertising


  3. > The below script will print "var is apple". I find this weird, because
    > in textbooks you are taught to pass variable to subroutines as
    > parameters. What is the point of doing this, if the variable is
    > visible anyway?
    >
    > How can I make the variable exist in main and yet be invisible to the
    > subroutine? I know I can create another variable with "my" and with
    > the same name in the subroutine. This will block the subroutine from
    > seeing variable in main, but is this really the way to do it, it seems
    > very cumbersom.
    >
    > my $var = "apple";
    > routine();
    >
    > sub routine {
    > print "var is $var.\n";
    > }


    You can declare the function before the variable:

    sub routine {
    print "var is $var.\n";
    }

    my $var = "apple";
    routine();
     
    Arndt Jonasson, Feb 10, 2005
    #3
  4. Louis. wrote:

    > Hi,
    >
    > The below script will print "var is apple". I find this weird, because
    > in textbooks you are taught to pass variable to subroutines as
    > parameters. What is the point of doing this, if the variable is
    > visible anyway?


    You avoid using global effects because it's good programming practice
    and significantly improves the maintainability of your scripts, not
    because the language makes you do it.
    >
    > How can I make the variable exist in main and yet be invisible to the
    > subroutine?


    Lexical variables don't exist in main; they don't exist in *any*
    package. That's why they're lexical. Lexical variables are
    statically scoped to the block that contains them. If they're
    not contained in a block, they're scoped to the file they're in.

    > I know I can create another variable with "my" and with
    > the same name in the subroutine. This will block the subroutine from
    > seeing variable in main, but is this really the way to do it, it seems
    > very cumbersom.


    Really? Doesn't seem that way to me. YMMV, I guess.
    >
    > TIA,
    > Louis.
    >
    > my $var = "apple";
    > routine();
    >
    > sub routine {
    > print "var is $var.\n";
    > }
    >
    >
    >
    >
    > Solution???
    >
    > {
    > my $var = "apple";
    > routine($var);
    > }
    >
    > sub routine {
    > my $var = $_[0];
    > print "var is $var.\n";
    > }


    Yes, that's how you do it. You should *always* define lexicals in the
    smallest possible block. A good way to help you do this is to get in
    the habit of not declaring variables until you need them.
    --
    Christopher Mattern

    "Which one you figure tracked us?"
    "The ugly one, sir."
    "...Could you be more specific?"
     
    Chris Mattern, Feb 10, 2005
    #4
  5. Louis. <> wrote:

    > The below script will print "var is apple". I find this weird,
    > because in textbooks you are taught to pass variable to
    > subroutines as parameters. What is the point of doing this, if the
    > variable is visible anyway?


    I think the point is that you have a choice. If you want to use a
    variable from a larger scope inside a subroutine you're free to do so.
    Perl itself doesn't pass judgement on it; Perl *programmers*, on the
    other hand....

    > my $var = "apple";
    > routine();
    >
    > sub routine {
    > print "var is $var.\n";
    >}


    --
    David Wall
     
    David K. Wall, Feb 10, 2005
    #5
  6. David K. Wall wrote:
    > I think the point is that you have a choice. If you want to use a
    > variable from a larger scope inside a subroutine you're free to do so.
    > Perl itself doesn't pass judgement on it;


    That's not always true.

    sub outer {
    my $var = 'apple';
    sub inner {
    ".. but \$var is still '$var' acc. to inner().\n"
    }
    if (shift) {
    $var =~ s/apple/banana/;
    print "\$var is now '$var' ..\n";
    print inner();
    return;
    }
    print "\$var is '$var'.\n";
    }

    outer();
    outer(1);

    Outputs:
    $var is 'apple'.
    $var is now 'banana' ..
    ... but $var is still 'apple' acc. to inner().

    (plus the warning: Variable "$var" will not stay shared)

    When running a program under mod_perl, this phenomenon may occur also
    when non-nested subroutines use file scoped variables.

    > Perl *programmers*, on the other hand....


    Making passing of variables a habit is not only a matter of style.

    --
    Gunnar Hjalmarsson
    Email: http://www.gunnar.cc/cgi-bin/contact.pl
     
    Gunnar Hjalmarsson, Feb 10, 2005
    #6
  7. Gunnar Hjalmarsson <> wrote:

    > David K. Wall wrote:
    >> I think the point is that you have a choice. If you want to use
    >> a variable from a larger scope inside a subroutine you're free to
    >> do so. Perl itself doesn't pass judgement on it;

    >
    > That's not always true.
    >
    > sub outer {
    > my $var = 'apple';
    > sub inner {
    > ".. but \$var is still '$var' acc. to inner().\n"
    > }
    > if (shift) {
    > $var =~ s/apple/banana/;
    > print "\$var is now '$var' ..\n";
    > print inner();
    > return;
    > }
    > print "\$var is '$var'.\n";
    > }
    >
    > outer();
    > outer(1);
    >
    > Outputs:
    > $var is 'apple'.
    > $var is now 'banana' ..
    > .. but $var is still 'apple' acc. to inner().
    >
    > (plus the warning: Variable "$var" will not stay shared)
    >
    > When running a program under mod_perl, this phenomenon may occur
    > also when non-nested subroutines use file scoped variables.


    I don't see a problem there. The results might not be what you
    expect, but perl will still let you use a variable from a larger
    scope inside a subroutine, and even warn you when it sees what it
    "thinks" are possibly unintended consequences. Doesn't seem very
    judgemental to me.


    >> Perl *programmers*, on the other hand....

    >
    > Making passing of variables a habit is not only a matter of style.


    I certainly never intended to say that, but since you're on about it,
    how about expanding on that comment? Offhand I can think of two
    situations where you HAVE to pass parameters to a sub: recursive
    functions and OOP.

    (For some truly tangled code that uses global variables for
    everything, take a look at the Greymatter blogging code. Urgh...)

    --
    David Wall
     
    David K. Wall, Feb 10, 2005
    #7
  8. David K. Wall wrote:
    > Gunnar Hjalmarsson <> wrote:
    >> David K. Wall wrote:
    >>> I think the point is that you have a choice. If you want to use
    >>> a variable from a larger scope inside a subroutine you're free to
    >>> do so. Perl itself doesn't pass judgement on it;

    >>
    >> That's not always true.


    <"Variable ... will not stay shared" example snipped>

    > I don't see a problem there. The results might not be what you
    > expect, but perl will still let you use a variable from a larger
    > scope inside a subroutine, and even warn you when it sees what it
    > "thinks" are possibly unintended consequences. Doesn't seem very
    > judgemental to me.


    Potentially unintended consequences is a strong reason to not do it,
    whether "judgemental" is the accurate term or not. ;-)

    >> Making passing of variables a habit is not only a matter of style.

    >
    > I certainly never intended to say that, but since you're on about it,
    > how about expanding on that comment?


    I was simply referring to my example. The principal reason for passing
    variables to subs, AFAIU, is that it makes the code easier to maintain.
    The point I was trying to make was that, besides its making the code
    less maintainable, there are situations where using lexical variables in
    a sub, when they are scoped outside, may directly affect the expected
    result.

    --
    Gunnar Hjalmarsson
    Email: http://www.gunnar.cc/cgi-bin/contact.pl
     
    Gunnar Hjalmarsson, Feb 10, 2005
    #8
  9. Louis.

    Michael Powe Guest

    >>>>> "Louis" == Louis <> writes:

    Louis> Hi, The below script will print "var is apple". I find this
    Louis> weird, because in textbooks you are taught to pass variable
    Louis> to subroutines as parameters. What is the point of doing
    Louis> this, if the variable is visible anyway?

    Louis> How can I make the variable exist in main and yet be
    Louis> invisible to the subroutine? I know I can create another

    Use 'anonymous' blocks. Any variable declared with 'my' outside a
    block has file scope. To permit the variable only a local scope, put
    it in a block like this:

    c:\src>type test.pl
    type test.pl
    #!perl

    use strict;

    {
    my $var = "string";

    }

    print $var;

    c:\src>test.pl
    test.pl
    Global symbol "$var" requires explicit package name at C:\src\test.pl line 10.
    Execution of C:\src\test.pl aborted due to compilation errors.

    I use these blocks for encapsulating variables all the time. Helps
    protect me from myself. ;-)

    In python, btw, it is a common idiom to define a main() function in
    your script, which serves the same purpose of maintenance of scope.

    mp

    --
    Michael Powe Waterbury CT
    ENOSIG: signature file is empty
     
    Michael Powe, Feb 11, 2005
    #9
    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. Matt Barnicle
    Replies:
    10
    Views:
    648
    Bruno Desthuilliers
    Dec 2, 2007
  2. Khookie

    C closures & lexical scoping

    Khookie, Dec 12, 2007, in forum: C Programming
    Replies:
    28
    Views:
    1,415
    cr88192
    Dec 15, 2007
  3. walterbyrd
    Replies:
    16
    Views:
    482
    Steven D'Aprano
    Dec 18, 2008
  4. Aronaxis, the Sourceror

    (?{..}) and lexical scoping issues.

    Aronaxis, the Sourceror, Jun 20, 2004, in forum: Perl Misc
    Replies:
    3
    Views:
    218
    Anno Siegel
    Jun 21, 2004
  5. PerlFAQ Server
    Replies:
    0
    Views:
    375
    PerlFAQ Server
    Jan 6, 2011
Loading...

Share This Page