Getting to variables contained in a typeglob referenced by a scalar.

J

Jaap Karssenberg

The point is the nature of a typeglob, this entity is a namespace node
which refers to _any_ type with that name (hence "typeglob"). So you can
regard a typeglob reference as a reference to any type at the same time.

Using ->{SCALAR} is just a special syntax to force dereferencing as a
scalar type. Using $$fh does this implicitly.
 
D

ddtl

Hello,

After 'open' is called in the following way:

open my $fh, $file;

'$fh' contains a reference to a filehandle, i.e., somewhere in the 'open'
function there is probably a following assignment:

$fh = \*SOME_TYPEGLOB;

(and somehow that typeglob is anonymous (?), so the filehandle is
also anonymous).

If I understand correctly, it actually means that '$fh' contains
a reference to a typeglob, because wherever there is a filehandle,
it can be substituted for a typeglob.

Than, if we want to get to the variables inside that typeglob, we
have to do it in the following way:

*$fh - access the fileglob
*$fh->{SCALAR} - access a reference to a scalar (typeglob is also a special
hash)
${*$fh->{SCALAR}} - access the scalar itself.

But "Programming Perl" (14.4.1) mentions another, easier way -
just use $$$fh (or @$$fh or %$$fh, etc.).

I don't understand, though, how it works - what do we access when
$$fh is used - there is no scalar reference inside '$fh'?
The book doesn't mention it as some new way of using typeglobs/references,
which probably means that it should be clear from the previous chapters
why and how it works, and it seems that I missed the point.


The question is, then: how and why $$$fh etc. work, and where is an
explanation for it in the book (or just in the documentation)


ddtl.
 
D

ddtl

The point is the nature of a typeglob, this entity is a namespace node
which refers to _any_ type with that name (hence "typeglob"). So you can
regard a typeglob reference as a reference to any type at the same time.

Using ->{SCALAR} is just a special syntax to force dereferencing as a
scalar type. Using $$fh does this implicitly.

But if reference to a typeglob is equivalent to a reference to whatever type
with that name I want, it should be able to say:

$$fh = 10;
print "$$fh";

and it would print out "10", because '$fh contains a reference to a
typeglobe == a reference to a scalar (among other things), so
dereferencing '$fh' should get to the value, but the above prints:

*main::10

so it means that another level of indirection is needed, i.e. - '$fh' does not
contains a reference to a scalar (or it's equivalent)?

ddtl.
 
D

ddtl

$fh = 10;
$ref_fh = \$fh;
print $$ref_fh;

'$fh' already contains a typeglob reference (put there by a 'open' function),
see my first post in the thread - I am continuing the discussion.
(all the point is when a scalar contains a typeglob reference,
not a usual reference to a scalar).

ddtl.
 
S

Steven Kuo

Hello,

After 'open' is called in the following way:

open my $fh, $file;

'$fh' contains a reference to a filehandle, i.e., somewhere in the 'open'
function there is probably a following assignment:

$fh = \*SOME_TYPEGLOB;

(and somehow that typeglob is anonymous (?), so the filehandle is
also anonymous).

If I understand correctly, it actually means that '$fh' contains
a reference to a typeglob, because wherever there is a filehandle,
it can be substituted for a typeglob.

Than, if we want to get to the variables inside that typeglob, we
have to do it in the following way:

*$fh - access the fileglob
*$fh->{SCALAR} - access a reference to a scalar (typeglob is also a special
hash)
${*$fh->{SCALAR}} - access the scalar itself.

But "Programming Perl" (14.4.1) mentions another, easier way -
just use $$$fh (or @$$fh or %$$fh, etc.).

I don't understand, though, how it works - what do we access when
$$fh is used - there is no scalar reference inside '$fh'?
The book doesn't mention it as some new way of using typeglobs/references,
which probably means that it should be clear from the previous chapters
why and how it works, and it seems that I missed the point.



$fh is a reference to a GLOB
$$fh is the GLOB itself
$$$fh is the SCALAR inside the GLOB


The question is, then: how and why $$$fh etc. work, and where is an
explanation for it in the book (or just in the documentation)


Perhaps this makes it clearer:

use strict;
use warnings;
use Scalar::Util;
use Symbol;

$\ = $/;

my $foo = gensym;
$$$foo = 'bar';

open ($foo, '<', '/etc/services')
or die "Could not open file : $!";

if ( fileno($foo)
and fileno($foo) == fileno(*$foo{IO}) ) {
print "SAME FILE DESCRIPTOR\n";
}

print $$$foo;

# equivalently

print ${*$foo{SCALAR}};

print Scalar::Util::reftype($foo), "\n";
 
D

ddtl

That's fine. However, your displayed code is
trying to set a value for a referenced variable.
Your displayed code makes no reference to your
already set $fh variable.

If you did actually reference your $fh variable,

$fh = 10;
$$fh = 10;
print $$fh;

Modification of a read-only value attempted at test.pl line 4.

I don't really understand what do you mean. Here is a complete
listing of a test program:

---------------------------------------------
use strict;

open (my $fh, "C:\\a\\projects\\tests\\a.pl") or
die "Cannot open file: $!\n";
$$fh = 10;
print "$$fh\n";
---------------------------------------------

When i run that script, it prints:
---------------------------------------------
*main::10
---------------------------------------------

The reference contained in $fh was put there by a 'open' function
(there is an autovivification going on), the reference is to an
anonymous variable (typeglob, actually). Then begins a question
itself (see previous posts).

So there is no attempt to set a read-only value...

ddtl.
 
A

Anno Siegel

ddtl said:
Hello,

After 'open' is called in the following way:

open my $fh, $file;

'$fh' contains a reference to a filehandle, i.e., somewhere in the 'open'
function there is probably a following assignment:

$fh = \*SOME_TYPEGLOB;

(and somehow that typeglob is anonymous (?), so the filehandle is
also anonymous).

The module Symbol creates anonymous globs. It is used in the creation
of this kind of file handle.
If I understand correctly, it actually means that '$fh' contains
a reference to a typeglob, because wherever there is a filehandle,
it can be substituted for a typeglob.

I think you mean "...substituted *by* a typeglob".
Than, if we want to get to the variables inside that typeglob, we
have to do it in the following way:

*$fh - access the fileglob
*$fh->{SCALAR} - access a reference to a scalar (typeglob is also a special
hash)
${*$fh->{SCALAR}} - access the scalar itself.

But "Programming Perl" (14.4.1) mentions another, easier way -
just use $$$fh (or @$$fh or %$$fh, etc.).

I don't understand, though, how it works - what do we access when
$$fh is used - there is no scalar reference inside '$fh'?

It's the glob. You need older books (Perl 4 level) to find any that talk
about (type-)globs at any length. Their original purpose has entirely
been superseded by references.
The book doesn't mention it as some new way of using typeglobs/references,
which probably means that it should be clear from the previous chapters
why and how it works, and it seems that I missed the point.


The question is, then: how and why $$$fh etc. work, and where is an
explanation for it in the book (or just in the documentation)

The fact that $fh is created as a file handle is irrelevant, it's just
a behavior of globs. To see how globs work, observe this:

our ( $var, @var, %var);
$var = 123;
%var = ( aaa => 123, bbb => 456 );
@var = qw( boo hoo woo);

my $glob = *var;

print "$$glob\n";
print "@$glob\n";
print "$_=>$$glob{ $_} " for keys %$glob; print "\n";

....which prints

123
boo hoo woo
bbb=>456 aaa=>123

So $glob behaves like a universal reference in that can be de-referenced
as a scalar, an array, a hash, and a sub (not shown).

Adding a level of (ordinary) reference works just as it should, and
results in the same output:

my $fh = \ $glob; # same as $fh = \ *var;

print $$$fh, "\n";
print "@$$fh\n";
print "$_=>$$$fh{ $_} " for keys %$$fh; print "\n";

Anno
 
R

Richard Morse

ddtl said:
You are not supposed to use close() on indirect filehandles - in order
to close the file you either exit the scope, or use:

I'm sorry, but I don't see this in `perldoc perlopentut`, `perldoc -f
open`, or `perldoc -f close`.

I do see that you _may_ just let them be automatically closed on exiting
the surrounding scope. But nothing that forbids using close on them --
in fact, `perldoc -f close` states:

: FILEHANDLE may be an expression whose value can be used as an
: indirect filehandle, usually the real filehandle name.

And in the Camel book (version 3) it says:

: FILEHANDLE may be an expression whose value can be used as an
: indirect filehandle (either the real filehandle name or a
: reference to anything that can be interpreted as a filehandle
: object).

Where do you find that you are not supposed to close files?

Ricky
 
D

ddtl

Doesn't print anything on my system, Perl 5.6 version.

Checked both under Windows & under Linux (though I had to change
the path for a Linux version - everything else was left unchanged),
in both cases the output was "*main::10". I use Perl 5.8.4 on all
systems.
You really don't want to do that.

It was just an example, so that I would be able to ask a question.
Add this,

close ($fh) || die "$!";

You will learn why.

You are not supposed to use close() on indirect filehandles - in order
to close the file you either exit the scope, or use:

undef $f;

That is why you get an error, see perlopentut.
Use of strict is really not needed for a three line script
but is optional. Use it if you really need strict.

I use strict even for one-liners - this is a personal preference, and
it is certainly not wrong.
Use of a "my" lexical declaration for a global serves no purpose
just as use of a "our" declaration for globals, serves no purpose.

This is just an *example*. BTW, you could not use "my" for global -
becaise if variable is declared with "my", it is not a global.

ddtl.
 
S

Steven Kuo

But how do you get to the typeglob using a funny character used to
access scalars - glob is not scalar. I could understand why it works if
instead of '$' it had been possible to use other funny characters as
well, like '@$fh' or '%$fh' - then i would infer: because glob contains
everything, you can get to glob by dereferencing glob reference with
any funny character, but in fact only '$$f' gets you a glob, all the other
constructs generate an error. Then why it works?


If you want the array and hash in the GLOB, then you write:
@$$fh and %$$fh respectively (not @$fh and not %$fh);

It 'works' because the deference syntax is unambiguous. From

'perldoc perlref'

....

A typeglob may be dereferenced the same way a reference can, because
the dereference syntax always indicates the type of reference desired.
So "${*foo}" and "${\$foo}" both indicate the same scalar variable.
 
P

Peter J. Acklam

Purl Gurl said:
Yes it is. Unless inside a private block, it is global.

It is private to the file, so in a way the file acts as the
"block" you are referring to.
That is a global variable. It is visible everywhere and never
falls out of scope.

It goes out of scope when perl has executed the file.

Peter
 
D

ddtl

$fh is a reference to a GLOB
$$fh is the GLOB itself
$$$fh is the SCALAR inside the GLOB

But how do you get to the typeglob using a funny character used to
access scalars - glob is not scalar. I could understand why it works if
instead of '$' it had been possible to use other funny characters as
well, like '@$fh' or '%$fh' - then i would infer: because glob contains
everything, you can get to glob by dereferencing glob reference with
any funny character, but in fact only '$$f' gets you a glob, all the other
constructs generate an error. Then why it works?
 
D

ddtl

I'm sorry, but I don't see this in `perldoc perlopentut`, `perldoc -f
open`, or `perldoc -f close`.

I do see that you _may_ just let them be automatically closed on exiting
the surrounding scope. But nothing that forbids using close on them
...
...
Where do you find that you are not supposed to close files?

I certainly may be wrong - i infered that claim from what is written
in perlopentut:

"Another convenient behavior is that an indirect filehandle automatically closes
when it goes out of scope or when you undefine it"

and from the fact that using close() on indirect reference generated an error:
if using close() is perfectly legal, then why an error? Conclusion: it is
illegal to use close on indirect references, and an alternative way is
using undef.

Maybe there is another reason, and then the conclusion is wrong (rather,
it seems quite obviously wrong, because of your citations).

What is the real reason, then, that close($fh) doesn't succeed?

ddtl.
 
D

ddtl

Yes, there is some difference between Perl 5.6 and Perl 5.8 version.
I ran that under 5.8.0 version. Prints as like your example.

Odd behavior because that is not a valid reference, not in
a classic sense. It is true a reference is auto-generated
by the type glob, but I would expect a "read only" type
error to be generated when an attempt is made to change
the value of a direct reference to the original variable.




Yes it is. Unless inside a private block, it is global.

#!perl

my $variable = "global";

That is a global variable. It is visible everywhere and
never falls out of scope.

It wouldn't be visible everywhere - it is visible everywhere
in the file, because file is it's lexical scope. You won't
be able to access it from other files.

Try that:
 
P

Peter J. Acklam

Purl Gurl said:
His code only contains that unclosed block, followed by his odd
variable reference stuff.

I'm not sure what you mean by "unclosed block". All pieces of
code end somewhere. In this case the scope ends at the end of the
file.
That my declaration is globally visible and never falls out of
scope.

It does, at the end of the file.
However, you are correct and I would not argue, should that
block be closed, then that variable is lexically scoped to a
private block, or is it?

The file *is* a "private block".

Peter
 
D

ddtl

If you want the array and hash in the GLOB, then you write:
@$$fh and %$$fh respectively (not @$fh and not %$fh);

It 'works' because the deference syntax is unambiguous.

But why not use $@$fh or $%$fh - it shouldn't be ambiguous -
the first $ indicates that fh is a scalar. The second funny character
indicates that we dereference scalar and getting to the typeglob
(typeglob is either a scalar, or array or hash, so every funny
character should do - why give special privilege to $?). Then we
use another $, to show that we dereference typeglob and want
to get the scalar value. We always indicate the desired type
of a reference - first reference to a typeglob, then reference to
a scalar. Why not, then?
 
P

Peter J. Acklam

Purl Gurl said:
Your Perl program falls off the end of the paper. Nothing falls
out of scope, no memory is released for reuse. Your program
simply exits.

If "foo.pl" contains

--------------------------------
#!perl

my $var = 'hello';
require "bar.pl";
print $var;
--------------------------------

and "bar.pl" contains

--------------------------------
#!perl

my $var = 'world';
--------------------------------

and you execute "foo.pl", then "hello" will be printed, not
"world", because the variable $var in "bar.pl" fell out of scope
at the end of the file "bar.pl".

Peter
 
A

Ala Qumsieh

Purl said:
Something about syntax I used previously, which is now
gone being overwritten during testing. Clearly a type
of syntax error on my part. I have not discovered what
syntax error I used which prevented a print, most likely
I used the wrong variable name.

That's why no one should listen to your advice, not even you:

Purl said:
Use of strict is really not needed for a three line script
but is optional. Use it if you really need strict.

Even for a three line script, it pays to use strict.

--Ala
 
A

Anno Siegel

ddtl said:
But how do you get to the typeglob using a funny character used to
access scalars - glob is not scalar.

In most respects, globs *do* behave like scalars. In particular, you
can assign them to scalar variables and take references of those.
De-referencing gives you back the plain glob. That is what happens
in the code above.
I could understand why it works if
instead of '$' it had been possible to use other funny characters as
well, like '@$fh' or '%$fh' -

You are describing how globs behave. They are themselves a kind of
reference.

A ref to a glob is just that. You de-reference it with "$" to
retrieve the glob, then you add a "funny character" (a sigil) to
specify which part of the glob you want.
then i would infer: because glob contains
everything, you can get to glob by dereferencing glob reference with
any funny character, but in fact only '$$f' gets you a glob, all the other
constructs generate an error. Then why it works?

Because it is programmed to work that way. It doesn't make much
sense to ask why, it just is implemented that way.

Anno
 
J

John Bokma

ddtl said:
You are not supposed to use close() on indirect filehandles - in order
to close the file you either exit the scope, or use:

Weird, I always do

close $fh or die "Can't close '$filename' after ...: $!"

Works for me.

And yes, I check after close, and no, haven't seen it fail ever.
 

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

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,013
Latest member
KatriceSwa

Latest Threads

Top