Re^3: A short whishlist of Perl5 improvements leaping to Perl7
by tobyink (Canon) on Nov 27, 2020 at 11:45 UTC
|
{
my $x = 123;
}
say $x;
| [reply] [d/l] |
|
|
wouldn't compile, because the second $x is not declared - there was no prior assignment on file-scope - and automine implied strict
| [reply] [d/l] [select] |
Re^3: A short whishlist of Perl5 improvements leaping to Perl7
by LanX (Saint) on Nov 27, 2020 at 12:19 UTC
|
> Under the OP's "proposal", you would still be able to do
I can't see that the OP made a proposal just a fuzzy wish and linking to a thread where I coined the term automine and already highlighted the problems.
> $x = 123;
{
my $x = 456;
}
Your example is redundant, cause the obvious rule is that any assignment in a new scope equals a declaration.
So what's the proposal now?
Python has IMHO
- rather complicated rules, (which changed again in Py2.2 for enclosed )
- no block-scope, no loop-scope, just (nested) function-scopes ( def )
- no my to support, but the inverse nonlocal for Py3
- it's hoisting declarations to scopes start
These rules only look easy on simple cases, but closures are rather fuzzy. Given that most Pythonistas have a rather simple worldview, they don't miss closures.
This model is very hard to transfer to Perl.
Where would we steal? Ruby? Javascript?
JS is a mess, a var is
- like our outside a function
- like my inside a function
- is hoisting
JS had to introduce let to have a proper my plus an optional strict
So again WHAT is the proposal???
For the records: I'd love to be able to have an automine pragma which makes easy cases easy and complicated cases feasible.
| [reply] [d/l] [select] |
|
|
my $x;
if (f()) {
...
$x = ...;
} else {
...
$x = ...;
}
And this one:
my $found;
for (...) {
if (...) {
$found = ...
}
}
And this one:
my @a;
while (...)
...
push @a, ...;
}
I don't think any program I've ever written would work!
| [reply] [d/l] [select] |
|
|
| [reply] |
|
|
|
|
|
|
|
let's try a proposal as thought experiment and discuss it
short version:*
- basically only file and function scope are automatic.
- all deeper nested scopes need to be explicit. Implicit effects there - if allowed - belong to the surrounding file/function scope.
- nested subs are tricky
1. Any assignment to an undeclared new variable implies a "implicit" my when in
- file-scope (outside any sub)
$x = 1 ==> my $x =1
- function-scope
sub foo { $x = 1; ... } ==> sub foo { my $x =1; ... }
- loop-header but NOT body
for $x (@a) {...} ==> for my $x (@a) {...}
- some commands like open *
open $fh, ... ==> open my $fh, ...
2. explicit my are still optionally allowed, our and state keep their semantics
3. No hoisting, a variable accessed before an implicit my still belongs to the upper scope and needs to be declared there
4. loop-bodies and naked blocks (technically the same) follow the old rules
5. ( ??? ) nested/anonymous subs are tricky, when it comes to closed over vars
- if they follow rule 1, than we need a declaration alike Py's nonlocal ... maybe its or over to mark vars avoiding implicit my
- if they are exempt from rule 1 and rather act like 4, we get a break in symmetry
- another solution would be a new keyword fun to create a sub with auto-mine while keeping sub explicit.
6. ( ??? ) functional blocks like in map {BLOCK} are technically anonymous subs °
7. ( ??? ) class-variables are a current issue in proposed new OOP models.
8. special global vars are exempt from implicit my.
9. Last but not least automine activates strict
So ...
- Did I forget a case?
- Do you need examples?
- Please inform yourself about closures before judging.
°) actually not in the case of map and grep but for all of List::Util , try return to see the difference
*) updated
| [reply] [d/l] [select] |
|
|
While the former thought experiment was closer to Python's behavior - all vars belong (mostly) to function scope - there is another possible approach.
1. any assignment to a new variable leads to an implicit my but only if their was no previous explicit declaration in a surrounding scope. This will replace former rules 1,4 and 5 all others still apply
Hence we get the following 4 cases for explicit declarations with my or our
| automine | effect | comment |
{
$x = 1;
{
$x = 2;
}
}
|
{
my $x = 1;
{
my $x = 2;
}
}
|
not strict w/o automine
|
{
$x = 1;
{
my $x = 2;
}
}
|
{
my $x = 1;
{
my $x = 2;
}
}
|
not strict w/o automine
|
{
my $x = 1;
{
$x = 2;
}
}
|
{
my $x = 1;
{
$x = 2;
}
}
|
backwards compatible
|
{
my $x = 1;
{
my $x = 2;
}
}
|
{
my $x = 1;
{
my $x = 2;
}
}
|
backwards compatible
|
Surprises and pitfalls:
| automine | effect | comment |
sub foo {
if (1) {
$x = 2;
}
print $x;
}
|
sub foo {
if (1) {
my $x = 2;
}
print $x; # undeclared
}
|
Doesn't compile Surprising for Pythonistas
|
sub add {
$x = 0;
for (1..9) {
$x = $x + $_;
}
print $x;
}
|
sub add {
my $x = 0;
for (1..9) {
my $x = $x + $_;
}
print $x; # prints 0
}
|
Unexpected result!
Needs an explicit my $x = 0 at init to avoid implicit my
|
This is a very Perlish approach and avoids many edge cases.
Of course this laziness comes with a price, introducing a new explicit declaration on file scope has an effect at the distance and could silently break subroutines
use automine
# our $var;
...
sub foo {
$var = shift; # not 'my $var' if explicit 'our $var' exists
...
}
That's why this theoretical pragma must be optional. (Of course scoping the our inside a tight block would also prevent this.)
| [reply] [d/l] [select] |
Re^3: A short whishlist of Perl5 improvements leaping to Perl7
by kcott (Archbishop) on Nov 27, 2020 at 02:14 UTC
|
OK, that's a fair point; one could differentiate between the two $x variables.
I still dislike it.
Given the OP has indicated "I think my idea isn't good",
I don't think further discussion is necessary.
| [reply] [d/l] |
|
|
| [reply] |
|
|
| [reply] |