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

Discussion in 'Perl Misc' started by Jaap Karssenberg, Jun 30, 2004.

  1. Re: Getting to variables contained in a typeglob referenced by ascalar.

    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.

    --
    ) ( Jaap Karssenberg || Pardus [Larus] | |0| |
    : : http://pardus-larus.student.utwente.nl/~pardus | | |0|
    ) \ / ( |0|0|0|
    ",.*'*.," Proud owner of "Perl6 Essentials" 1st edition :) wannabe
     
    Jaap Karssenberg, Jun 30, 2004
    #1
    1. Advertising

  2. Jaap Karssenberg

    ddtl Guest

    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.
     
    ddtl, Jun 30, 2004
    #2
    1. Advertising

  3. Jaap Karssenberg

    ddtl Guest

    On Wed, 30 Jun 2004 19:28:59 +0200, Jaap Karssenberg
    <> wrote:

    >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.
     
    ddtl, Jun 30, 2004
    #3
  4. Jaap Karssenberg

    ddtl Guest


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

    >
    >$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.
     
    ddtl, Jun 30, 2004
    #4
  5. Jaap Karssenberg

    Steven Kuo Guest

    Re: Getting to variables contained in a typeglob referenced by ascalar.

    On Wed, 30 Jun 2004, ddtl wrote:

    >
    > 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";

    --
    Hope this helps,
    Steven
     
    Steven Kuo, Jun 30, 2004
    #5
  6. Jaap Karssenberg

    ddtl Guest


    >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.
     
    ddtl, Jun 30, 2004
    #6
  7. Jaap Karssenberg

    Anno Siegel Guest

    ddtl <this.is@invalid> wrote in comp.lang.perl.misc:
    >
    > 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
     
    Anno Siegel, Jun 30, 2004
    #7
  8. In article <>,
    ddtl <this.is@invalid> wrote:

    > 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
     
    Richard Morse, Jun 30, 2004
    #8
  9. Jaap Karssenberg

    ddtl Guest


    >> When i run that script, it prints:

    >
    >> *main::10

    >
    >
    >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.
     
    ddtl, Jun 30, 2004
    #9
  10. Jaap Karssenberg

    Steven Kuo Guest

    Re: Getting to variables contained in a typeglob referenced by ascalar.

    On Thu, 1 Jul 2004, ddtl wrote:

    >
    > >$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?
    >



    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.


    --
    Hope this helps,
    Steven
     
    Steven Kuo, Jun 30, 2004
    #10
  11. Purl Gurl <> wrote:

    > ddtl wrote:
    >
    > > you could not use "my" for global - becaise if variable is
    > > declared with "my", it is not a global.

    >
    > 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

    --
    #!/local/bin/perl5 -wp -*- mode: cperl; coding: iso-8859-1; -*-
    # matlab comment stripper (strips comments from Matlab m-files)
    s/^((?:(?:[])}\w.]'+|[^'%])+|'[^'\n]*(?:''[^'\n]*)*')*).*/$1/x;
     
    Peter J. Acklam, Jun 30, 2004
    #11
  12. Jaap Karssenberg

    ddtl Guest


    >$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?
     
    ddtl, Jun 30, 2004
    #12
  13. Jaap Karssenberg

    ddtl Guest


    >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.
     
    ddtl, Jun 30, 2004
    #13
  14. Jaap Karssenberg

    ddtl Guest

    On Wed, 30 Jun 2004 13:54:48 -0700, Purl Gurl <> wrote:

    >ddtl wrote:
    >
    >> >> When i run that script, it prints:

    >
    >> >> *main::10

    >
    >> >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.

    >
    >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.
    >
    >
    >> > Use of a "my" lexical declaration for a global serves no purpose
    >> > just as use of a "our" declaration for globals, serves no purpose.

    >
    >> you could not use "my" for global - becaise if variable is declared
    >> with "my", it is not a global.

    >
    >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:
    --------------------------
    my $variable = "global";
    print "$main::variable\n";
    --------------------------

    It won't print anything - because the global variable $::global
    is not set.
     
    ddtl, Jun 30, 2004
    #14
  15. Purl Gurl <> wrote:

    > Peter J. Acklam wrote:
    >
    > > It is private to the file, so in a way the file acts as the
    > > "block" you are referring to.

    >
    > 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

    --
    #!/local/bin/perl5 -wp -*- mode: cperl; coding: iso-8859-1; -*-
    # matlab comment stripper (strips comments from Matlab m-files)
    s/^((?:(?:[])}\w.]'+|[^'%])+|'[^'\n]*(?:''[^'\n]*)*')*).*/$1/x;
     
    Peter J. Acklam, Jul 1, 2004
    #15
  16. Jaap Karssenberg

    ddtl Guest


    >
    >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?

    >'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.
     
    ddtl, Jul 1, 2004
    #16
  17. Purl Gurl <> wrote:

    > 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

    --
    #!/local/bin/perl5 -wp -*- mode: cperl; coding: iso-8859-1; -*-
    # matlab comment stripper (strips comments from Matlab m-files)
    s/^((?:(?:[])}\w.]'+|[^'%])+|'[^'\n]*(?:''[^'\n]*)*')*).*/$1/x;
     
    Peter J. Acklam, Jul 1, 2004
    #17
  18. Jaap Karssenberg

    Ala Qumsieh Guest

    Re: Getting to variables contained in a typeglob referenced by ascalar.

    Purl Gurl wrote:

    > 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 Gurl wrote:
    > 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
     
    Ala Qumsieh, Jul 1, 2004
    #18
  19. Jaap Karssenberg

    Anno Siegel Guest

    ddtl <this.is@invalid> wrote in comp.lang.perl.misc:
    >
    > >$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.


    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
     
    Anno Siegel, Jul 1, 2004
    #19
  20. Jaap Karssenberg

    John Bokma Guest

    Re: Getting to variables contained in a typeglob referenced by ascalar.

    ddtl wrote:

    >>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:


    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.

    --
    John MexIT: http://johnbokma.com/mexit/
    personal page: http://johnbokma.com/
    Experienced Perl programmer available: http://castleamber.com/
    Happy Customers: http://castleamber.com/testimonials.html
     
    John Bokma, Jul 1, 2004
    #20
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Jeff Wagner
    Replies:
    11
    Views:
    561
    Francis Avila
    Nov 30, 2003
  2. ThomasW
    Replies:
    11
    Views:
    287
    ThomasW
    Sep 28, 2009
  3. Clint Olsen
    Replies:
    6
    Views:
    364
    Jeff 'japhy' Pinyan
    Nov 13, 2003
  4. Mark

    Replace scalar in another scalar

    Mark, Jan 27, 2005, in forum: Perl Misc
    Replies:
    4
    Views:
    168
    Arndt Jonasson
    Jan 27, 2005
  5. kj

    Typeglob Qs

    kj, Jun 28, 2005, in forum: Perl Misc
    Replies:
    2
    Views:
    66
    Sisyphus
    Jun 28, 2005
Loading...

Share This Page