What does `my' do?!

E

Eric Pozharski

That's what I thought too.

Not actually that the shell was strange, but that it was strange
for a programmer of Ilya's cluefulness to be using Windows (which
was my erroneous guess as to why it was double quoted).

I asked him, and he explained else-thread.

Yes, that came in next feed. But I still puzled: I suppose most of
answering party, has run that one-liner. And I suppose they seemlesly
replaced double-quotes with single-quotes. That must be some kind of
I am fearless!

I am unmanageable! (and so is my hair)

after 5years of unmanageble hair, then 10years of pony-tail, I've got
used to plait (for 5years already). However, since I'm insane, you can
skip this consideration.
 
X

Xho Jingleheimerschmidt

Ben said:
No. People seem to keep making this mistake. Named subs are *not*
closures in Perl 5, they simply keep a ref to all the variables they
reference.

Isn't that what a closure is?

Xho
 
T

Tad J McClellan

Eric Pozharski said:
Yes, that came in next feed. But I still puzled: I suppose most of
answering party, has run that one-liner. And I suppose they seemlesly
replaced double-quotes with single-quotes. That must be some kind of
Perl-specific mental disorder


Translating to the particular shell that you are using is
common even among those that do not share your affliction.

However, since I'm insane,


I've noticed.
 
I

Ilya Zakharevich

perl -wle "eval shift; delayed()" "my $x; $x=12; sub delayed {print $x}"
12
*After* `eval' is executed, the scope of $ARGV[0] is exited. But as
you see (and this is *very expected*), $x is not cleared on scope
exit.
Yor code example represents a closure wherein the value of a lexical

Wrong - already discussed.
variable declared outside of its scope gets captured. As usual, $x is
cleared at the end of the scope of $ARGV[0]

As my example shows, it's value is 12. So it is not "cleared".

Hope this helps,
Ilya
 
I

Ilya Zakharevich

Why it is not completely correct:

perl -wle "eval shift; delayed()" "my $x; $x=12; sub delayed {print $x}"
12

*After* `eval' is executed, the scope of $ARGV[0] is exited. But as
you see (and this is *very expected*), $x is not cleared on scope
exit.

I remembered the "meta-explanation of what happens" I made for myself
when I was fixing/developing this stuff...

The variable is "renewed" at the end of scope, not "cleared".

A new, completely fresh copy of the variable is made, which has no
relationship to "the old copy". (As if Perl accesses a variable
through a reference, and now stores at this location a reference to
another variable.)

After this (and until end-of-scope is reached again), this new copy is
accessed through $x in this scope.

BUT: embedded subroutines maintain their own "references to
variables"; since they "do not own" $x, no "renewing" is made in
their end-of-scope. So they always access the reference to the
"first" $x:

perl -wle "for (0..1) { my $x; $x=12 unless $_; sub p{print $x}; p; p; print $x }"
12
12
12
12
12
Use of uninitialized value in print at -e line 1.

(Of course, closures behave in yet slightly different ways... Sigh,
I did not want to document it yet, and STILL do not know how to
express it short-clear-not-ambiguously-and-correct...)

Ilya

P.S. Of course, when one creates a reference to a completely new
variable, there is no guaranties that anything changes! *IF*
somebody else was keeping a reference to the old variable, then
one MUST get something distinct. However, if it was only you
who referenced the variable, you can get back the same "slot".

This is similar to doing free()+malloc(): you can get back the
same buffer; the difference is that Perl guaranties that *new*
values are undef. (As if malloc() in C would always reset
memory buffers to 0...)
 
I

Ilya Zakharevich

We appear to be in vehement agreement: anything that looks like
"initialization" in a "my" is not special, but is merely a standard
run-time assignment like any other. (My use of "initial value" may
have been inapt, especially in this example, where it's assigned in
the BEGIN block.)

Another sigh... *If* the things were this simple...

perl -wle "my $x = 12, $x = 13; print $x"
Name "main::x" used only once: possible typo at -e line 1.
12

So `my $x' has a runtime effect too: it puts the "new" $x on
stack - as different from plain `$x', which puts the "current" $x on
stack. And to muddy things yet more, the switch of the "current" $x
to the new value happens at time of `;' - which I consider a very
brain-damaged decision...

Yours,
Ilya
 
I

Ilya Zakharevich

Besides this unusual initialization/assignment thing, the docs specify
BEGIN is wrapped in an eval when it is run, which I thought odd.

That's just for symmetry with END...

Hope this helps,
Ilya
 
I

Ilya Zakharevich

WOOS2 - Windows on OS/2

No, I never got to installing and patching Windows3 [so that it would
become a subsystem of OS/2]. (And, IIRC, this would be called WinOS2.)

Yours,
Ilya
 
N

Nathan Keel

Ilya said:
Another sigh...  *If* the things were this simple...

perl -wle "my $x = 12, $x = 13; print $x"
Name "main::x" used only once: possible typo at -e line 1.
12

Things are *nearly* that simple. While your points are valid in that
there's more to it, who in the world would write code like that? You
write weird or bad code, you get a weird or bad result. I get the
topic of interest and that you wouldn't write code like that, but I
wouldn't approach the topic like you would. All of the results are
predictable here, I don't see the problem.
 
D

derykus

Wrong - already discussed.
variable declared outside of its scope gets captured. As usual, $x is
cleared at the end of the scope of $ARGV[0]

As my example shows, it's value is 12.  So it is not "cleared".

Just to be clear in this rather complicated thread, Ilya is responding
to Ferry B's post
rather than Ben's.
 
X

Xho Jingleheimerschmidt

Ben said:
Not quite. Named subs are compiled once at compile time, and only keep a
ref to the outer lexicals as they existed then. This means that code
like

use warnings;

sub mkfoo {
my ($x) = @_;

sub foo { $x }

return \&foo;
}

You could change the named sub def to:

eval q{sub foo {$x}};
say mkfoo($_)->() for 1..2;

gives

Variable "$x" will not stay shared at clos line 6.
1
1

whereas if you use an anon sub you get a fresh clone of the sub with
refs to the *current* set of outer lexicals, so code like

sub mkfoo {
my ($x) = @_;
return sub { $x };
}

You could put the anonymous sub def in a begin block, to prevent it from
being compiled. It can't be done as elegantly as the string eval
above, because you need to somewhere to stash value, but it can be done.
say mkfoo($_)->() for 1..2;

gives

1
2

as expected. This is obviously important when using closures as
callbacks and such.

Sure, anonymous subs are more useful in such situations, but I think
that what triggers recompilation is an accident of the language, and not
the essence of a closure. I think the essence of a closure is what it
does with lexical variables at the time it is compiled. So I think a
named sub is still a closure, it is just one that has an implicit BEGIN
block around it, and so only compiles once unless you take steps to
change that.

Xho
 
D

derykus

Quoth Ilya Zakharevich <[email protected]>:






Even weirder:

    ~% perl -le'$x = ($x = 5) + 1; print $x'
    6
    ~% perl -le'my $x = (my $x = 5) + 1; print $x'
    5
~%

:)

Hm,

perl -wle 'my $x = (my $x = 5) + 1; print $x'
"my" variable $x masks earlier declaration in same statement at -e
line 1.

But I see your smiley ... punchline ?
 
I

Ilya Zakharevich

Things are *nearly* that simple. While your points are valid in that
there's more to it, who in the world would write code like that?

I would do all the time, if it were possible...

defined (my $foo = bar) and some_call($foo).

Thanks for your praises,
Ilya
 
I

Ilya Zakharevich

for my $x (1..2) {
push @cvs, sub { $x };
}

and

for my $x (1..2) {
eval "sub foo { \$x }";
push @cvs = \&foo;
}

is that in the first case the anon sub is only compiled at compile time,
and both copies get the same optree, whereas in the second they are
(separately) compiled at runtime and each gets a different optree (that
happen to do the same thing). I would say that the first gives multiple
instances of a single closure, whereas the second gives multiple subrefs
that happen to do similar things to different variables. When I put it
like that it's hard not to say the distinction is purely academic :).

Now try this with 1..1e7 ... Or with -w...

Ilya
 
I

Ilya Zakharevich

The question of memory usage is important in some cases, but not really
relevant to the semantics.

To the contrary. If you ignore the memory usage and speed, there is
absolutely no point in having closures (for languages with eval()).
But you already noticed this...
For one thing, a CvCLONED CV uses some memory itself, so running out
of memory for cloned anon subs is just a matter of tweaking the
numbers a little higher...

If this were relevant, we would all run with 64K of memory, and would
satisfy the rest from swap. 1/2 ;-) [I assume that implement-swapping
code fits in 64K; I would not be surprised if with contemporary
Winlixes this is not true ;-]

Yours,
Ilya
 
X

Xho Jingleheimerschmidt

Ilya said:
To the contrary. If you ignore the memory usage and speed, there is
absolutely no point in having closures (for languages with eval()).
But you already noticed this...

It seems to me that there are plenty of reasons, other than memory usage
and speed, to avoid string evals. And other languages that have
something like eval() might do it in ways such that it can't be used to
replace anonymous subroutine closures. For that matter, I think Perl
would be entitled to change eval in ways that break this. The eval docs
say that subroutine defined inside eval are visible after the eval, but
doesn't say what the behavior of outer scoped lexical variable would be
in that case.

My point was to explore the essence of what a closure is, not to propose
practical alternatives to anonymous subrefs.

Xho
 
I

Ilya Zakharevich

Ilya Zakharevich wrote:
replace anonymous subroutine closures. For that matter, I think Perl
would be entitled to change eval in ways that break this. The eval docs
say that subroutine defined inside eval are visible after the eval, but
doesn't say what the behavior of outer scoped lexical variable would be
in that case.

The state of Perl docs is a sad matter...

*The intent* is to have eval""s behaving exactly as literal code
inserted into the scope. I do not know how far this is implemented
now. When I was watching Perl development, some hints, IIRC, were not
propagated into eval""s...
My point was to explore the essence of what a closure is, not to propose
practical alternatives to anonymous subrefs.

This is a very sound approach.
Ilya
 
T

Tim McDaniel

Another sigh... *If* the things were this simple...

perl -wle "my $x = 12, $x = 13; print $x"
Name "main::x" used only once: possible typo at -e line 1.
12

So `my $x' has a runtime effect too: it puts the "new" $x on
stack - as different from plain `$x', which puts the "current" $x on
stack. And to muddy things yet more, the switch of the "current" $x
to the new value happens at time of `;' - which I consider a very
brain-damaged decision...

That looks to me more like a scope compile-time effect. "my $x"
creates a variable that doesn't come into rvalue scope until after the
end of the statement, except that it can be assigned to in the
statement itself. (It has two different scopes? Uglier and uglier.)
 
W

Willem

Tim McDaniel wrote:
) That looks to me more like a scope compile-time effect. "my $x"
) creates a variable that doesn't come into rvalue scope until after the
) end of the statement, except that it can be assigned to in the
) statement itself. (It has two different scopes? Uglier and uglier.)

Indeed. Very annoying if you want to do something like:

my $widget = $main->SomeWidget(-command => sub {
...
$widget->insert($text);
...
});

Which doesn't work (obviously, after reading the above).


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,214
Messages
2,571,110
Members
47,703
Latest member
robert.marryson

Latest Threads

Top