betmatt has asked for the wisdom of the Perl Monks concerning the following question:

Hello Monks,

In Python you would think that functions are the equivalent to subroutines in Perl. Then I realise that it is possible to have nested functions in Python, however not nested subroutines in Perl. What differences are there to consider here? Obviously the way variables are defined in critical. Is there really any difference between (1) having a call to a subroutine and then within a nested loop having a call to another subroutine. And (2) that we see in Python. It was this video that promoted my thinking on this. https://www.youtube.com/watch?v=QVdf0LgmICw

Python has Local, Enclosing, Global and Built-in variables.

2019-07-28 Athanasius linkified the URL

Replies are listed 'Best First'.
Re: Nesting Functions
by LanX (Cardinal) on Jul 19, 2019 at 11:48 UTC
    from my understanding is a nested def in Python equivalent to °

    sub outer { my $c_inner = sub { print "perl" }; $c_inner->(); }

    Please note that Python is implicitly preferring references while Perl prefers the "Explicit is better than implicit" approach (yes it's ironic)

    > Python has Local, Enclosing, Global and Built-in variables.

    More or less: *

    • Local and Enclosing correspond to lexical private vars similar³ to my
    • Global corresponds to an our in main:: namespace
    • Built-in is CORE:: namespace, (and pretty dangerous to play with)

    > It was this video that promoted my thinking on this. https://www.youtube.com/watch?v=QVdf0LgmICw

    Not linkified not watched.²

    Hint: Please provide code examples if you want better answers.

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

    update

    °) There was an experimental attempt to allow "private subs" in Perl, which was essentially syntactic sugar for the following IIRC. No idea if it's still available or deprecated.

    *) the py-docs are sparse and incomplete here. Variable declarations in class context become attributes. These are essentially package vars in Perl. (Python has no package and Perl has no class )

    ²) tried to, but won't watch a 20 min video to guess what your question is.

    ³) updated, see Re^7: Nesting Functions for details

      > No idea if it's still available or deprecated

      Upgrade! They are no longer experimental and they can be nested. Lexical Subroutines

      map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]
        The docs are (as usual) fuzzy, is it the same semantic like the code I've shown?

        I.e. will PadWalker show an entry inner for my sub inner {} ?

        Cheers Rolf
        (addicted to the Perl Programming Language :)
        Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

      Local and enclosing are lexical my
      Python doesn't have lexicals. All variables are rather some equivalent of package variables, where each function counts as a package that can't access variables of other function. So a variable can be used as long as it as been defined sometime before in the function, regardless of scope:
      >>> def scope(): ... for x in range(1,10): ... if x > 3: ... print(a) ... else: ... a=x ... >>> scope() 3 3 3 3 3 3 >>> print(a) Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name 'a' is not defined
      I had some difficulty understanding the meaning and use of with statements, until I realized it was just a mechanism to simulate lexical scope (with the possibility to do some clean up on a variable at the end of a defined scope). You might find some example when looking for variable declaration in python, but actually the (new) feature is just type enforcing, there is no equivalent to my in python.

      That's the thing I dislike the most about python, just above the lack of explicit block-ending tokens (curly brackets :P).

        > All variables are rather some equivalent of package variables, where each function counts as a package that can't access variables of other function.

        That's more or less how lexicals are realized in Perl.

        A Pad° is a hash like structure ("namespace") like a package. (with the difference that it doesn't have globs)

        Every scope has it's own pad, nesting scopes results in a chain of pads to be investigated.

        You may want to play a bit with PadWalker

        > Python doesn't have lexicals.

        Python has closures, closures require lexicals.

        > there is no equivalent to my in python.

        Implementation of semantic matters not syntax or naming.

        update

        the first assignment in a "scope" is an implicit declaration in Python.

        Sometimes it's a my sometimes an our .

        The mess starts because you can't use something like strict* to catch typos and Py3 needed to introduce nonlocal to mark assignments which are not declarations.

        "Explicit is better than implicit" ... LOL

        Cheers Rolf
        (addicted to the Perl Programming Language :)
        Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

        °) Pad: = short for perlguts#Scratchpads

        *) which JS successfully copied because it has var and even let now.