Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling
 
PerlMonks  

When CGI->new doesn't return a CGI object

by Juerd (Abbot)
on Jan 07, 2003 at 00:48 UTC ( #224805=perlmeditation: print w/ replies, xml ) Need Help??

Note: All variables used or mentioned here are package global variables, not lexicals.

*foo is a typeglob. Using it, you can access @foo, $foo, %foo and &foo. You probably know that. You can get a reference to @foo by using \@foo, but also by using *foo{ARRAY}.

\$foo == *foo{SCALAR} \@foo == *foo{ARRAY} \%foo == *foo{HASH} \&foo == *foo{CODE} \*foo == *foo{GLOB} *foo{IO}

So far, so good. If you want to throw away our old global variable and replace it with another, you assign a reference to *foo. Perl will use the appropriate slot, *foo{THING} itself is read only.

*foo = \"Scalar" # Note: constants are read-only *foo = [ 'Array' ] *foo = { foo => 'Hash' } *foo = sub { print 'Subroutine' } *foo = Symbol::gensym # GLOB *foo = Symbol::geniosym # IO

References are being assigned. Nothing special. Note that no data is copied. If you have $foo, that is a reference to an array, and assign it to *foo, both @$foo and @foo are the same array. And $foo and \@foo are references to that array.

References can be blessed. And because the slots in a typeglob are references, they can be blessed too. Just like you would bless anything else. And because if you reference something that is dereferenced, you get the same reference you dereferenced, the reference would still blessed, if it was originally.

sub method { print "\@_ is: @_\n" } *foo = bless [ 'Array' ], 'main'; *foo{ARRAY}->method("It's an object now");

As you can see, no scalar variable is needed to store an object in. You can use the slots of a typeglob as well. Remember how \@foo == *foo{ARRAY}? This means \@foo can be an object!

sub method { print "\@_ is: @_\n" } *foo = bless [ 'Array' ], 'main'; (\@foo)->method("It's an object now");

The parens are needed because \ has lower precedence than ->.

Perhaps you think this is nice and all, and think you will never use objects that aren't stored in normal scalar variables. Well, think again. File and directory handles, found in the IO slot, are blessed references. That's right, filehandles are objects. Blessed to IO::Handle. Even if you're not using that module.

use IO::Handle; STDOUT->autoflush(1);

What's going on here, why doesn't Perl look for an autoflush method in a class named STDOUT? *STDOUT{IO} is a blessed IO reference. When a string is used in an OO manner (the left hand side of the arrow operator), it's used as a filehandle if the IO slot is used. If it there's no IO slot, the bareword is supposed to be a class.

With foo->method(), IO::Handle::method is used if foo is a filehandle, but foo::method is used if it is not. "foo"->method() is no different. Consider the following code:

use IO::Handle; use CGI; open CGI, 'somefile' or die $!; my $cgi = CGI->new;

What is $cgi here? Is it a CGI object, as the guy I was helping expected? No. Is it an IO::Handle object, as I expected? No. It is a GLOB reference, blessed to GLOB. I'd like to know why, because even *CGI{IO}->new would have returned an IO::Handle. Can anyone explain please what happens in CGI->new here?

Things I learned so far:

  • ref(\@foo) doesn't have to be ARRAY
  • Filehandles are objects, even if IO::Handle isn't loaded yet (i.e. they are objects without methods)
  • Once some string is used as a file handle, you can no longer use it as a class name with the arrow operator
  • *foo{FILEHANDLE} is a synonym for *foo{IO}, to be backwards compatible
  • Even though *foo{FILEHANDLE} is a synonym for *foo{IO}, they return a different reference
  • You can use other classes than IO::Handle for filehandle objects. Simply re-bless.
  • I need sleep. Good night everyone.

- Yes, I reinvent wheels.
- Spam: Visit eurotraQ.

Comment on When CGI->new doesn't return a CGI object
Select or Download Code
Re: When CGI->new doesn't return a CGI object
by grinder (Bishop) on Jan 07, 2003 at 08:29 UTC

    As far as "Once some string is used as a file handle, you can no longer use it as a class name with the arrow operator" is concerned, this is known behaviour. tye summed the situation up succintly in the thread Filehandles vs. Packages: And the winner is..., (and also suggests a patch).

    Apart from that, ++ for the detective work :)


    print@_{sort keys %_},$/if%_=split//,'= & *a?b:e\f/h^h!j+n,o@o;r$s-t%t#u'
Re: When CGI->new doesn't return a CGI object
by adrianh (Chancellor) on Jan 07, 2003 at 17:28 UTC

    At the risk of being niggly...

    References can be blessed. And because the slots in a typeglob are references, they can be blessed too. Just like you would bless anything else. And because if you reference something that is dereferenced, you get the same reference you dereferenced, the reference would still blessed, if it was originally.

    It's the referent that is blessed into a package, not the reference. When you do:

    my @foo = (1,2,3); bless \@foo, 'Bar'; my $x = \@foo; my $y = \@foo;

    Then $x and $y are different references that refer to the same array, which has been blessed into the Bar package.

    Chapter 3 of TheDamian's Object Oriented Perl covers this topic well for those who are as pedantic as I am :-)

      While we are being niggly and pedantic i'd like to correct you where you said

      Then $x and $y are different references that refer to the same array, which has been blessed into the Bar package.

      This is a common misunderstanding (even by the serious pros. Data::Dumper has a flaw that IMO can be traced back to this subtle mistake) In reality you should have said

      Then $x and $y are different scalar variables holding a reference to the same array, which has been blessed into the Bar package.

      This is a crucial distinction. Consider how many distinct variables are present in the two following snippets:

      my ($z,$x,$y); $x=\$y; $y=\$x; $z=[$x,$y];
      and
      my $z=[]; $z->[0]=\$z->[1]; $z->[1]=\$z->[0];
      Note that dumping $z in both cases will result in the same output when using Data::Dumper.

      Pedantic can be fun and useful sometimes... :-)

      Oh yes, the correct answer to my question can be found in the source of the node.

      --- demerphq
      my friends call me, usually because I'm late....

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlmeditation [id://224805]
Approved by diotalevi
Front-paged by demerphq
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others meditating upon the Monastery: (10)
As of 2014-08-22 18:41 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The best computer themed movie is:











    Results (163 votes), past polls