in reply to Re^2: Nesting Functions
in thread Nesting Functions

> 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.

Replies are listed 'Best First'.
Re^4: Nesting Functions
by Eily (Monsignor) on Jul 19, 2019 at 13:32 UTC

    Implementation of semantic matters not syntax or naming.
    I'm not sure I understand what you mean. Are you saying the names of elements in a language must match their implementation and not their behaviour? I really don't agree with that, you shouldn't have to know which interpreter you are using to call things, if their behaviour is well defined.

    If you do call python's function variables lexical, I surely wouldn't call them "lexical my", as you can't limit a variable to a scope except function (so a variable in a loop can be used outside of that loop). And the condition for using a variable in perl is that it has been declared before lexically, while in python it must have been defined before chronologically. Also in perl one distinction is that non lexicals can be accessed by name (symref or symbols table) while lexicals can't. Python doesn't have that distinction.

    Python has closures, closures require lexicals.
    I'm tempted to argue that it could also be that Python has a different definition of closure, but I think that's a fair point. But Python variables behave so differently than lexicals from other languages (at least the ones I know), that I'd rather avoid calling them lexicals, and focus on the fact that closures keep a hold of variables beyond their expected lifespan, rather than talking about lexical scope.

    Edit: (after yours):

    the first assignment in a "scope" is an implicit declaration in Python.
    I'd rather consider that all possible variables are implicitly declared. Otherwise that would mean that you can access a variable above it's (implicit) declaration like in my example. This would also imply conditional declaration when I'd rather consider only the definition/initialization can be conditional. Although, after checking, exec (the equivalent of perl's eval) only sees globals by default. So that's a point for lexicals.

      > while in python it must have been defined before chronologically.

      not sure what you mean. Example?

      > Also in perl one distinction is that non lexicals can be accessed by name (symref or symbols table) while lexicals can't. Python doesn't have that distinction.

      AFAIK does Python have namespaces - well classes - like __BUILTINS__ or globals()['var'] to access such non-lexicals.

      > Are you saying the names of elements in a language must match their implementation and not their behaviour?

      I'm saying it has to match the semantic of the definition. From what I know have "lexical vars" been invented in lambda calculus.

      I suppose they where first implemented in lisp.

      > as you can't limit a variable to a scope except function (so a variable in a loop can be used outside of that loop)

      Scoping rules are different, but please keep in mind that you need an extra "form" in lisp to build a lexical scope. (at least in elisp). So scopes are language depended.

      But what matters here is the visibility of lexicals (or rather non-visibility outside a scope)

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

        > Example?

        fruits = ["apple", "banana", "cherry"] for x in fruits: print(x) if x == "banana": print(y) if x == "apple": y=1

        whips himself

        map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]

        I've edited my post after seeing your update FYI.

        > while in python it must have been defined before chronologically.

        not sure what you mean. Example?
        This was what my example above was meant to demonstrate. The print(a) is fine because a=x has been executed first chronologically, although it was done after lexically (ie, below).

        I'm saying it has to match the semantic of the definition
        But definition are different between language aren't they? Like a closure can just be an anonymous function in some languages. Or do you consider that there is one true definition, and incorrect uses? You say that "Scoping rules are different", but you might just consider that the definition of a scope is different between languages. I could then argue that python doesn't have a definition for lexical variables. But I see it's a very poor argument, as you can't say that a language doesn't have a feature simply because the feature has another name :).

        But what matters here is the visibility of lexicals
        That makes sense. And IMHO it's an argument for calling our variable lexical aliases rather than just package variables :D.

        I still don't think calling python variables lexical is really helpful, especially when comparing it to perl. But I see your points and accept them as valid. I won't discuss much further, or at all, because who cares about python anyway?

Re^4: Nesting Functions
by LanX (Saint) on Jul 19, 2019 at 14:15 UTC
    > 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.

    Another disturbing thing is that Python does hoisting like JS.

    if it encounters a (implicit) declaration of a var somewhere at the end of a function, it will bind all var to the same private storage.

    see demo of the mess in fun2()

    >>> a=666 # global >>> def fun1(): ... print a # global ... >>> def fun2(): ... print a # privat ... a = 33 # declaration ... >>> fun1() 666 >>> fun2() Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 2, in fun2 UnboundLocalError: local variable 'a' referenced before assignment >>>

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