Re: Tell me how it works!
by ikegami (Patriarch) on Jan 28, 2009 at 16:14 UTC
|
undef(@a) would give you want you want. undef isn't recursive. Undefining the glob doesn't undefine the values referenced by the glob.
Before glob assignment
----------------------
*main::a *main::b
| |
| +-------+ +-------+ |
+--> | Glob | | Glob | <--+
+-------+ +-------+ +-------+ +-------+
| GP ----> | GP | | GP | <---- GP |
+-------+ +-------+ +-------+ +-------+
+-- ARRAY | | ARRAY --+
+-------+ | +-------+ +-------+ |
| Array | <-+ +-> NULL
+-------+
| 1,2,3 |
+-------+
After glob assignment
---------------------
*main::a *main::b
| |
| +-------+ +-------+ |
+--> | Glob | | Glob | <--+
+-------+ +--------+ +-------+
| GP ---------> | GP | <--------- GP |
+-------+ +--------+ +-------+
| ARRAY --+
+--------+ | +-------+
+-> | Array |
+-------+
| 1,2,3 |
+-------+
After "undef *a"
(Gets a fresh GP,
undoing the glob
assignment)
-----------------
*main::a *main::b
| |
| +-------+ +-------+ |
+--> | Glob | | Glob | <--+
+-------+ +-------+ +-------+ +-------+
| GP ----> | GP | | GP | <---- GP |
+-------+ +-------+ +-------+ +-------+
+-- ARRAY | | ARRAY --+
| +-------+ +-------+ | +-------+
NULL <-+ +-> | Array |
+-------+
| 1,2,3 |
+-------+
If you had done "undef @a"
(Clears @a)
--------------------------
*main::a *main::b
| |
| +-------+ +-------+ |
+--> | Glob | | Glob | <--+
+-------+ +--------+ +-------+
| GP ---------> | GP | <--------- GP |
+-------+ +--------+ +-------+
| ARRAY --+
+--------+ | +-------+
+-> | Array |
+-------+
| () |
+-------+
Note that "@a=();" is usually better than "undef @a;" since it doesn't discard @a's buffer.
| [reply] [d/l] [select] |
|
| [reply] |
|
| [reply] |
|
|
|
Re: Tell me how it works!
by zentara (Cardinal) on Jan 28, 2009 at 14:58 UTC
|
Since no one else mentioned it, as a habit, avoid using $a and $b as variables....they are used in the sort function, and will cause trouble if you sort anywhere in your script.
| [reply] |
Re: Tell me how it works!
by citromatik (Curate) on Jan 28, 2009 at 15:31 UTC
|
Because undef *a undefines the typeglob *a, but not the underlying slots. Look at these 2 examples:
#1
$a = 10;
*b = *a;
$a = 4;
print $b; # <- prints 4
#2
$a = 10;
*b = *a;
undef *a;
$a = 4;
print $b; # <- prints 10!
| [reply] [d/l] [select] |
Re: Tell me how it works!
by gone2015 (Deacon) on Jan 28, 2009 at 14:49 UTC
|
Because *a is implicitly a collection of pointers to the various $a, @a, etc values. So *b = *a copies those pointers, and undef *a wipes out the original collection of pointers, but not the copy.
Update: my apologies, I omitted one level of indirection. I am grateful to brother citromatik for pointing out the error of my ways. (I will now go and mediate on the problem of hubris.)
Correcting my earlier explanation... What is happening is that *a implicitly refers to a structure which contains a collection of pointers to the various $a, @a, etc values. So *b = *a makes *b implicitly refer to the same structure as *a. The operation undef *a wipes out the implicit reference -- it does not affect *b, or the structure, or the values pointed to by that structure.
| [reply] [d/l] [select] |
|
$x = 10;
@x = qw(1 2 3);
*y = *x;
$x = 12;
print $y; # <- Prints 12
undef $x;
print $y; # <- Warns "Use of uninitialized value in..."
See perlmod
| [reply] [d/l] [select] |
|
*a=*b;
But, I read somewhere that assigning the typeglob(*a) will make both to point the same location(address/ memory).
So, When I undef the *a, how the *b remains the same?
Can you clear me in this? | [reply] [d/l] |
|
|
|
|
Re: Tell me how it works!
by jethro (Monsignor) on Jan 28, 2009 at 14:49 UTC
|
Use only on a scalar value, an entire array or hash, or a subroutine n
+ame.
...
The undef function will probably not do what you expect on most specia
+l variables
| [reply] [d/l] |
|
| [reply] |
Re: Tell me how it works!
by Bloodnok (Vicar) on Jan 28, 2009 at 17:14 UTC
|
| [reply] |
Re: Tell me how it works!
by Marshall (Canon) on Jan 28, 2009 at 17:47 UTC
|
Very wise Monks have covered the "how". I am curious as to the "why"?. What is the purpose and the real world application? | [reply] |
|
Why what? Why create an alias?
sub inplace_uc {
our $text; local *text = \$_[0];
$text =~ tr/a-z/A-Z/;
}
Update: Added missing "$text =~". | [reply] [d/l] [select] |
|
I was enquiring as to what the orginal poster wanted to
accomplish and why he thought he needed the typeglob
syntax. That's a different question than how it works.
You definately know how it works. We have a great
intellectual question, but maybe we should be answering a
different question? I'm just probing a bit to see if there is
some more fundamental application issue here.
I looked at this inplace_uc code and I did add "$text =~" in front of the
tr, which seemed appropriate.
Here, there is really no performance to be gained that I can see.
The inplace_uc() call passes the whole string on the stack and there is some
stuff to get the address of it. If we are doing an "inplace" replacement,
why not just pass the addresss of the string instead of the whole string?
My inplace_uc2() uses the address of the string in a very straightforward
way.
As a perfence of style, I would always expect an inplace modification to
to take place on an address or in Perl lingo a referece to something.
Ok, mileage varies as they say.
#!/usr/bin/perl -w
use strict;
my $lc_msg = 'message';
inplace_uc ($lc_msg);
print "$lc_msg\n";
sub inplace_uc
{
our $text;
local *text = \$_[0]; # equivalent to:
# local *text = \shift;
$text =~ tr/a-z/A-Z/; # added $text =~
}
my $lc_msg_y = 'another_message';
inplace_uc2 (\$lc_msg_y);
print "$lc_msg_y\n";
sub inplace_uc2
{
my $str_ref = shift;
$$str_ref =~ tr/a-z/A-Z/;
}
# prints:
#MESSAGE
#ANOTHER_MESSAGE
| [reply] [d/l] |
|