Perl Scope Confusion with Format / Write












7















Why is $var unavailable (out of scope ?) to write when declared with my, if its scope is pretty much package-level ?



package ASDF;
use warnings;
use strict;
use feature 'say';

my $var = 'foo';

format =
@<<<<< @>>>>>
'test : ', $var
.


sub test {
say $var;
write;
}


1;


Called with :



perl -wE 'use ASDF; ASDF::test();'


Produces :



foo
Variable "$var" is not available at ASDF.pm line 16.
Use of uninitialized value $var in formline at ASDF.pm line 10.
test :


It appears otherwise available to say in the same scope ...



Replacing my with our fixes it :



foo
test : foo


Why can't write pick-up on $var correctly ?

Is it a scope issue, or an issue with how Perl's write or format is implemented ?










share|improve this question


















  • 3





    Seems like formats don't properly close over lexical variables. This is the sort of error message I'd expect from eval('$x') where $x is a variable from some surrounding lexical scope that isn't used in the subroutine otherwise.

    – melpomene
    Jan 2 at 18:37











  • Did you try our $var?

    – toolic
    Jan 2 at 18:41






  • 2





    @toolic "Replacing my with our fixes it :"

    – melpomene
    Jan 2 at 18:43






  • 2





    I repeat: Perl6::Form is a module for Perl5

    – ikegami
    Jan 3 at 3:00






  • 3





    Formats are an ancient feature of Perl (older than local variables). My guess is no one has touched their code in 20 years. It looks like a bug to me.

    – melpomene
    Jan 3 at 12:25
















7















Why is $var unavailable (out of scope ?) to write when declared with my, if its scope is pretty much package-level ?



package ASDF;
use warnings;
use strict;
use feature 'say';

my $var = 'foo';

format =
@<<<<< @>>>>>
'test : ', $var
.


sub test {
say $var;
write;
}


1;


Called with :



perl -wE 'use ASDF; ASDF::test();'


Produces :



foo
Variable "$var" is not available at ASDF.pm line 16.
Use of uninitialized value $var in formline at ASDF.pm line 10.
test :


It appears otherwise available to say in the same scope ...



Replacing my with our fixes it :



foo
test : foo


Why can't write pick-up on $var correctly ?

Is it a scope issue, or an issue with how Perl's write or format is implemented ?










share|improve this question


















  • 3





    Seems like formats don't properly close over lexical variables. This is the sort of error message I'd expect from eval('$x') where $x is a variable from some surrounding lexical scope that isn't used in the subroutine otherwise.

    – melpomene
    Jan 2 at 18:37











  • Did you try our $var?

    – toolic
    Jan 2 at 18:41






  • 2





    @toolic "Replacing my with our fixes it :"

    – melpomene
    Jan 2 at 18:43






  • 2





    I repeat: Perl6::Form is a module for Perl5

    – ikegami
    Jan 3 at 3:00






  • 3





    Formats are an ancient feature of Perl (older than local variables). My guess is no one has touched their code in 20 years. It looks like a bug to me.

    – melpomene
    Jan 3 at 12:25














7












7








7


1






Why is $var unavailable (out of scope ?) to write when declared with my, if its scope is pretty much package-level ?



package ASDF;
use warnings;
use strict;
use feature 'say';

my $var = 'foo';

format =
@<<<<< @>>>>>
'test : ', $var
.


sub test {
say $var;
write;
}


1;


Called with :



perl -wE 'use ASDF; ASDF::test();'


Produces :



foo
Variable "$var" is not available at ASDF.pm line 16.
Use of uninitialized value $var in formline at ASDF.pm line 10.
test :


It appears otherwise available to say in the same scope ...



Replacing my with our fixes it :



foo
test : foo


Why can't write pick-up on $var correctly ?

Is it a scope issue, or an issue with how Perl's write or format is implemented ?










share|improve this question














Why is $var unavailable (out of scope ?) to write when declared with my, if its scope is pretty much package-level ?



package ASDF;
use warnings;
use strict;
use feature 'say';

my $var = 'foo';

format =
@<<<<< @>>>>>
'test : ', $var
.


sub test {
say $var;
write;
}


1;


Called with :



perl -wE 'use ASDF; ASDF::test();'


Produces :



foo
Variable "$var" is not available at ASDF.pm line 16.
Use of uninitialized value $var in formline at ASDF.pm line 10.
test :


It appears otherwise available to say in the same scope ...



Replacing my with our fixes it :



foo
test : foo


Why can't write pick-up on $var correctly ?

Is it a scope issue, or an issue with how Perl's write or format is implemented ?







perl scope built-in






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Jan 2 at 18:23









robutrobut

427




427








  • 3





    Seems like formats don't properly close over lexical variables. This is the sort of error message I'd expect from eval('$x') where $x is a variable from some surrounding lexical scope that isn't used in the subroutine otherwise.

    – melpomene
    Jan 2 at 18:37











  • Did you try our $var?

    – toolic
    Jan 2 at 18:41






  • 2





    @toolic "Replacing my with our fixes it :"

    – melpomene
    Jan 2 at 18:43






  • 2





    I repeat: Perl6::Form is a module for Perl5

    – ikegami
    Jan 3 at 3:00






  • 3





    Formats are an ancient feature of Perl (older than local variables). My guess is no one has touched their code in 20 years. It looks like a bug to me.

    – melpomene
    Jan 3 at 12:25














  • 3





    Seems like formats don't properly close over lexical variables. This is the sort of error message I'd expect from eval('$x') where $x is a variable from some surrounding lexical scope that isn't used in the subroutine otherwise.

    – melpomene
    Jan 2 at 18:37











  • Did you try our $var?

    – toolic
    Jan 2 at 18:41






  • 2





    @toolic "Replacing my with our fixes it :"

    – melpomene
    Jan 2 at 18:43






  • 2





    I repeat: Perl6::Form is a module for Perl5

    – ikegami
    Jan 3 at 3:00






  • 3





    Formats are an ancient feature of Perl (older than local variables). My guess is no one has touched their code in 20 years. It looks like a bug to me.

    – melpomene
    Jan 3 at 12:25








3




3





Seems like formats don't properly close over lexical variables. This is the sort of error message I'd expect from eval('$x') where $x is a variable from some surrounding lexical scope that isn't used in the subroutine otherwise.

– melpomene
Jan 2 at 18:37





Seems like formats don't properly close over lexical variables. This is the sort of error message I'd expect from eval('$x') where $x is a variable from some surrounding lexical scope that isn't used in the subroutine otherwise.

– melpomene
Jan 2 at 18:37













Did you try our $var?

– toolic
Jan 2 at 18:41





Did you try our $var?

– toolic
Jan 2 at 18:41




2




2





@toolic "Replacing my with our fixes it :"

– melpomene
Jan 2 at 18:43





@toolic "Replacing my with our fixes it :"

– melpomene
Jan 2 at 18:43




2




2





I repeat: Perl6::Form is a module for Perl5

– ikegami
Jan 3 at 3:00





I repeat: Perl6::Form is a module for Perl5

– ikegami
Jan 3 at 3:00




3




3





Formats are an ancient feature of Perl (older than local variables). My guess is no one has touched their code in 20 years. It looks like a bug to me.

– melpomene
Jan 3 at 12:25





Formats are an ancient feature of Perl (older than local variables). My guess is no one has touched their code in 20 years. It looks like a bug to me.

– melpomene
Jan 3 at 12:25












1 Answer
1






active

oldest

votes


















2














At the bottom of the Perl format documentation it says:




Lexical variables (declared with "my") are not visible within a format unless the format is declared within the scope of the lexical variable.




Reading that would imply that what you are trying would work, but apparently lexically scoped variables work differently for format and write when called from outside of the package they where declared in. Also, all of the examples in the article use global variables...



This more modern tutorial about format repeats that you might run into trouble if you use lexically scoped variables (variables declared with my) because write picks the variables from the current package and, as stated in the comments of your question, was written in a time when Perl did not have the my keyword or lexical scoping.



The solutions the article offers:




When you are ready to output some data, you use write. This design shows the age of formats since write doesn't take arguments to fill in the pictures. It uses the variables that are in scope.




our( $id, $name, $food, $amount ) = qw( 12 Buster Tuna 1.0 );
write();



Formats are also a bit crufty because you don't pass arguments to write to fill in the pictures. Perl relies on variables with the specified names being in scope. You can use lexical variables, but they have to be in the same scope as the format definition, and they have to be in scope when you call write. It's impractical to do that with lexicals, so the most agile way involves localized package variables:




foreach my $record ( @cats ) {
local( $id, $name, $food ) = @$record;
write( $fh );
}


And also this advice in the wrap-up:





  • Use localized package variables to set data for the format




So, our and local seem to be the way to go if you want to keep using format and write in modern Perl.






share|improve this answer


























    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54011306%2fperl-scope-confusion-with-format-write%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    2














    At the bottom of the Perl format documentation it says:




    Lexical variables (declared with "my") are not visible within a format unless the format is declared within the scope of the lexical variable.




    Reading that would imply that what you are trying would work, but apparently lexically scoped variables work differently for format and write when called from outside of the package they where declared in. Also, all of the examples in the article use global variables...



    This more modern tutorial about format repeats that you might run into trouble if you use lexically scoped variables (variables declared with my) because write picks the variables from the current package and, as stated in the comments of your question, was written in a time when Perl did not have the my keyword or lexical scoping.



    The solutions the article offers:




    When you are ready to output some data, you use write. This design shows the age of formats since write doesn't take arguments to fill in the pictures. It uses the variables that are in scope.




    our( $id, $name, $food, $amount ) = qw( 12 Buster Tuna 1.0 );
    write();



    Formats are also a bit crufty because you don't pass arguments to write to fill in the pictures. Perl relies on variables with the specified names being in scope. You can use lexical variables, but they have to be in the same scope as the format definition, and they have to be in scope when you call write. It's impractical to do that with lexicals, so the most agile way involves localized package variables:




    foreach my $record ( @cats ) {
    local( $id, $name, $food ) = @$record;
    write( $fh );
    }


    And also this advice in the wrap-up:





    • Use localized package variables to set data for the format




    So, our and local seem to be the way to go if you want to keep using format and write in modern Perl.






    share|improve this answer






























      2














      At the bottom of the Perl format documentation it says:




      Lexical variables (declared with "my") are not visible within a format unless the format is declared within the scope of the lexical variable.




      Reading that would imply that what you are trying would work, but apparently lexically scoped variables work differently for format and write when called from outside of the package they where declared in. Also, all of the examples in the article use global variables...



      This more modern tutorial about format repeats that you might run into trouble if you use lexically scoped variables (variables declared with my) because write picks the variables from the current package and, as stated in the comments of your question, was written in a time when Perl did not have the my keyword or lexical scoping.



      The solutions the article offers:




      When you are ready to output some data, you use write. This design shows the age of formats since write doesn't take arguments to fill in the pictures. It uses the variables that are in scope.




      our( $id, $name, $food, $amount ) = qw( 12 Buster Tuna 1.0 );
      write();



      Formats are also a bit crufty because you don't pass arguments to write to fill in the pictures. Perl relies on variables with the specified names being in scope. You can use lexical variables, but they have to be in the same scope as the format definition, and they have to be in scope when you call write. It's impractical to do that with lexicals, so the most agile way involves localized package variables:




      foreach my $record ( @cats ) {
      local( $id, $name, $food ) = @$record;
      write( $fh );
      }


      And also this advice in the wrap-up:





      • Use localized package variables to set data for the format




      So, our and local seem to be the way to go if you want to keep using format and write in modern Perl.






      share|improve this answer




























        2












        2








        2







        At the bottom of the Perl format documentation it says:




        Lexical variables (declared with "my") are not visible within a format unless the format is declared within the scope of the lexical variable.




        Reading that would imply that what you are trying would work, but apparently lexically scoped variables work differently for format and write when called from outside of the package they where declared in. Also, all of the examples in the article use global variables...



        This more modern tutorial about format repeats that you might run into trouble if you use lexically scoped variables (variables declared with my) because write picks the variables from the current package and, as stated in the comments of your question, was written in a time when Perl did not have the my keyword or lexical scoping.



        The solutions the article offers:




        When you are ready to output some data, you use write. This design shows the age of formats since write doesn't take arguments to fill in the pictures. It uses the variables that are in scope.




        our( $id, $name, $food, $amount ) = qw( 12 Buster Tuna 1.0 );
        write();



        Formats are also a bit crufty because you don't pass arguments to write to fill in the pictures. Perl relies on variables with the specified names being in scope. You can use lexical variables, but they have to be in the same scope as the format definition, and they have to be in scope when you call write. It's impractical to do that with lexicals, so the most agile way involves localized package variables:




        foreach my $record ( @cats ) {
        local( $id, $name, $food ) = @$record;
        write( $fh );
        }


        And also this advice in the wrap-up:





        • Use localized package variables to set data for the format




        So, our and local seem to be the way to go if you want to keep using format and write in modern Perl.






        share|improve this answer















        At the bottom of the Perl format documentation it says:




        Lexical variables (declared with "my") are not visible within a format unless the format is declared within the scope of the lexical variable.




        Reading that would imply that what you are trying would work, but apparently lexically scoped variables work differently for format and write when called from outside of the package they where declared in. Also, all of the examples in the article use global variables...



        This more modern tutorial about format repeats that you might run into trouble if you use lexically scoped variables (variables declared with my) because write picks the variables from the current package and, as stated in the comments of your question, was written in a time when Perl did not have the my keyword or lexical scoping.



        The solutions the article offers:




        When you are ready to output some data, you use write. This design shows the age of formats since write doesn't take arguments to fill in the pictures. It uses the variables that are in scope.




        our( $id, $name, $food, $amount ) = qw( 12 Buster Tuna 1.0 );
        write();



        Formats are also a bit crufty because you don't pass arguments to write to fill in the pictures. Perl relies on variables with the specified names being in scope. You can use lexical variables, but they have to be in the same scope as the format definition, and they have to be in scope when you call write. It's impractical to do that with lexicals, so the most agile way involves localized package variables:




        foreach my $record ( @cats ) {
        local( $id, $name, $food ) = @$record;
        write( $fh );
        }


        And also this advice in the wrap-up:





        • Use localized package variables to set data for the format




        So, our and local seem to be the way to go if you want to keep using format and write in modern Perl.







        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Jan 30 at 7:59

























        answered Jan 30 at 7:46









        PowertiekePowertieke

        1,92011118




        1,92011118
































            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54011306%2fperl-scope-confusion-with-format-write%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            MongoDB - Not Authorized To Execute Command

            How to fix TextFormField cause rebuild widget in Flutter

            in spring boot 2.1 many test slices are not allowed anymore due to multiple @BootstrapWith