in reply to Re^3: Nesting Functions in thread Nesting Functions
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.
Re^5: Nesting Functions
by LanX (Saint) on Jul 19, 2019 at 13:48 UTC
|
> 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)
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
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]
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
>>> fruits = ["apple", "banana", "cherry"]
>>> for x in fruits:
... print(x)
... if x == "banana":
... print(y)
... if x == "apple":
... y=1
...
apple
banana
1
cherry
Probably you don't like the "hoisting" of the binding of y?
Please note that JS is also doing hoisting even that it has a var statement°
°) and now even let which behaves (almost completely) like my in Perl | [reply] [Watch: Dir/Any] [d/l] [select] |
|
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?
| [reply] [Watch: Dir/Any] |
|
But definition are different between language aren't they?
Some are, and that's a pity because it only leads to confusion. I like standards and one of them is a standard jargon/lexicon. If some language decides that it's going to abandon that then it is to that language's detriment.
Like a closure can just be an anonymous function in some languages.
That's just plain nuts. If a function isn't closing over anything then it is not a closure - QED. :-)
Or do you consider that there is one true definition, and incorrect uses?
For some terms, absolutely. There are terms which are well defined within Comp Sci (pointer, array, function, etc.) which if used to mean something else would certainly be classed as an incorrect use.
I won't discuss much further, or at all, because who cares about python anyway?
Amen, brother. Our fellow monk betmatt does seem rather obsessed by it, though. Poor chap.
| [reply] [Watch: Dir/Any] |
|
|
yes there's hoisting happening in Python (though hoisting might be a JS term)
OK if you want to define "lexical" by the order of statements inside a scope, (our is a good example) than let's compromise on "private" .
Both Perl and Python have private variables.
- in Perl they are also called "lexical vars" and declared with my for the rest of the scope
- in Python they are called "local vars" and implicitly declared while assigning in a function scope or some obscure comprehensions for the full scope, even up-wards
OK?
| [reply] [Watch: Dir/Any] |
|
|
|
(let ((var1 init-form-1)
(var2 init-form-2)
...
(varm init-form-m))
form1
form2
...
formn)
Both Perl and Python avoid extra "blocks" for each declaration by coupling the declaration to the surrounding scope.
(To exactly simulate this behaviour we'd need a do block in Perl where all lexical vars are defined at the very beginning)
So yes Perl is a bit saner but with a more complex implementation than Python and JS which are pretending the declaration happened at the scopes start.
So using your arguments none of these languages are implementing lexical vars, because none is using a "let block" syntax.
My argument is that semantics matter not syntax.
AND you can easily transform Python and JS scoping to Perl's by moving the declaration at their scopes start and leaving the init parts at their respective place.
Replicating my former example
sub fun2 {
my $a;
print $a; # undef warning *
$a = 33;
}
I hope my POV is clearer now.
*) In order to have a fatal like in python just tie the declarations with a tied variable that croaks when fetched.
°) though I don't know the original notation in lambda calculus | [reply] [Watch: Dir/Any] [d/l] [select] |
|
|