Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Perl > Perl Misc > Creator named like class

Reply
Thread Tools

Creator named like class

 
 
Anno Siegel
Guest
Posts: n/a
 
      07-16-2004
It is possible to use the name of a class also as the name of a subroutine,
which may create objects of that class. To fix the ideas, assume a class

package Race::Horse;

sub new {
my $class = shift;
bless {
name => shift,
# ...
}, $class;
}

# more methods...

It is now possible to define

sub Race::Horse {
Race::Horse->new( @_);
}

Instead of the always slightly cumbersome

my $horse = Race::Horse->new( 'Stewball');

we can now say

my $horse = Race::Horse( 'Stewball');

I find this creator intuitive, and I'm thinking of equipping two or
three CPAN modules of mine that way.

Of course, there are problems. Aren't there always?

First off, it's thin ice that it works at all (if you know what I mean).
In sub Race::Hose, "Race::Horse->new..." is ambiguous syntax. What is
left of the arrow can be any expression, so Perl would be in its rights
to read it as "Race::Horse()->new..." and plunge into deep recursion.
It Does What I Mean, but I don't think the feature is documented.
I don't think it is likely to go away. That would break old code.

Another problem is name space violation. Race::Horse defines a sub
in package Race, where it has no business defining things. Of course,
there is no rule that explicitly forbids it, but it might be considered
poor (even rude) style. Actual collisions are improbable, however.
If package Race contains subs, their names are likely to be lower case.

A favorable point is that the additional creator doesn't interfere with
the traditional ->new (or any other creator that might be used). One
can replace the other anywhere, and no-one is forced to use the new
style.

Anno
 
Reply With Quote
 
 
 
 
Jaap Karssenberg
Guest
Posts: n/a
 
      07-16-2004
On 16 Jul 2004 16:57:21 GMT Anno Siegel wrote:
: First off, it's thin ice that it works at all (if you know what I
: mean). In sub Race::Hose, "Race::Horse->new..." is ambiguous syntax.
: What is left of the arrow can be any expression, so Perl would be in
: its rights to read it as "Race::Horse()->new..." and plunge into deep
: recursion. It Does What I Mean, but I don't think the feature is
: documented. I don't think it is likely to go away. That would break
: old code.

I think you can be pretty sure that in the "Race::Horse->new" syntax
"Race::Horse" is considered a class name in any current and future
version of perl5. It is not documented explicitly AFAIK but it is used
as in example code in several perl manpages.

: Another problem is name space violation. Race::Horse defines a sub
: in package Race, where it has no business defining things. Of course,
: there is no rule that explicitly forbids it, but it might be
: considered poor (even rude) style. Actual collisions are improbable,
: however. If package Race contains subs, their names are likely to be
: lower case.

For this reason I would advise against using this construct in modules
that are intended for CPAN. At the very least check the existence of the
sub before defining you own. But thats no real insurance.

*Race::Horse = sub { # define constructor if sub doesn't allready exist
... code ...
} unless *Race::Horse{CODE} ;

--
) ( Jaap Karssenberg || Pardus [Larus] | |0| |
: : http://pardus-larus.student.utwente.nl/~pardus | | |0|
) \ / ( |0|0|0|
",.*'*.," Proud owner of "Perl6 Essentials" 1st edition wannabe
 
Reply With Quote
 
 
 
 
Anno Siegel
Guest
Posts: n/a
 
      07-17-2004
Jaap Karssenberg <(E-Mail Removed)> wrote in comp.lang.perl.misc:
> On 16 Jul 2004 16:57:21 GMT Anno Siegel wrote:
> : First off, it's thin ice that it works at all (if you know what I
> : mean). In sub Race::Hose, "Race::Horse->new..." is ambiguous syntax.
> : What is left of the arrow can be any expression, so Perl would be in
> : its rights to read it as "Race::Horse()->new..." and plunge into deep
> : recursion. It Does What I Mean, but I don't think the feature is
> : documented. I don't think it is likely to go away. That would break
> : old code.
>
> I think you can be pretty sure that in the "Race::Horse->new" syntax
> "Race::Horse" is considered a class name in any current and future
> version of perl5. It is not documented explicitly AFAIK but it is used
> as in example code in several perl manpages.


It is also not true, if, at compile-time, Race::Horse is defined as
a sub. Example:

package Race::Horse;
sub new { bless {}, shift }

package Mickey::Mouse;
sub new { bless {}, shift }

my $x = Race::Horse->new; # swap
sub Race::Horse { 'Mickey::Mouse' } # swap

print ref $x, "\n";

This prints "Race::Horse", so the bare Race::Horse has been parsed as
Race::Horse a class name, as you say. But swap the indicated lines,
and it prints "Mickey::Mouse", so now it has been parsed as Race::Horse().

So the sub takes precedence, if defined at compile time. In

sub Race::Horse { Race::Horse->new( @_) }

the sub Race::Horse comes uncomfortably close to being defined at
compile time. Other ways of using a sub name inside a sub do result
in recursion, and that's the point I'm slightly worried about.

> : Another problem is name space violation. Race::Horse defines a sub
> : in package Race, where it has no business defining things. Of course,
> : there is no rule that explicitly forbids it, but it might be
> : considered poor (even rude) style. Actual collisions are improbable,
> : however. If package Race contains subs, their names are likely to be
> : lower case.
>
> For this reason I would advise against using this construct in modules
> that are intended for CPAN. At the very least check the existence of the
> sub before defining you own. But thats no real insurance.
>
> *Race::Horse = sub { # define constructor if sub doesn't allready exist
> ... code ...
> } unless *Race::Horse{CODE} ;


Ohh... much too clever for its own good, I think It has quite some
surprise potential. If needed, I'd add a use-time option to switch it
off explicitly.

On the other hand, there is an ill-defined, but distinct, notion of
public and private name space on CPAN. As long as I'm in "my" name
space, I'll feel free to define what I please. Then again, I *am*
thinking of things like Music::Wurlitzer, where Music is an established
piece of public name space. I guess it should be optional in such
cases.

Anno
 
Reply With Quote
 
Brian McCauley
Guest
Posts: n/a
 
      07-17-2004
Jaap Karssenberg <(E-Mail Removed)> writes:

> On 16 Jul 2004 16:57:21 GMT Anno Siegel wrote:
> : Another problem is name space violation. Race::Horse defines a sub
> : in package Race, where it has no business defining things. Of course,
> : there is no rule that explicitly forbids it, but it might be
> : considered poor (even rude) style. Actual collisions are improbable,
> : however. If package Race contains subs, their names are likely to be
> : lower case.
>
> For this reason I would advise against using this construct in modules
> that are intended for CPAN.


But the glob that coresponds to the Race::Horse package if not
*Race::Horse but *Race::Horse::. Hence, logically, if you want a
subroutine with the same name as the package this is &Race::Horse::
not &Race::Horse. This way there is no namespace polution. On the
other hand I prefer the model where constructors are classs methods in
the first place.

--
\\ ( )
. _\\__[oo
.__/ \\ /\@
. l___\\
# ll l\\
###LL LL\\
 
Reply With Quote
 
Anno Siegel
Guest
Posts: n/a
 
      07-17-2004
Brian McCauley <(E-Mail Removed)> wrote in comp.lang.perl.misc:
> Jaap Karssenberg <(E-Mail Removed)> writes:
>
> > On 16 Jul 2004 16:57:21 GMT Anno Siegel wrote:
> > : Another problem is name space violation. Race::Horse defines a sub
> > : in package Race, where it has no business defining things. Of course,
> > : there is no rule that explicitly forbids it, but it might be
> > : considered poor (even rude) style. Actual collisions are improbable,
> > : however. If package Race contains subs, their names are likely to be
> > : lower case.
> >
> > For this reason I would advise against using this construct in modules
> > that are intended for CPAN.

>
> But the glob that coresponds to the Race::Horse package if not
> *Race::Horse but *Race::Horse::. Hence, logically, if you want a
> subroutine with the same name as the package this is &Race::Horse::
> not &Race::Horse. This way there is no namespace polution.


....but also no way of calling the sub. Or is there?

> On the
> other hand I prefer the model where constructors are classs methods in
> the first place.


I'm afraid the whole plan is what we call a "Schnapsidee" in German
(though no booze was involved in bringing it up). I overlooked the
simple fact that after defining "sub Race::Horse" the class name
Race::Horse cannot be used as a barewword anymore. That means that
any class method in Race::Horse, including ->new, must now be called
through a string literal:

my $x = 'Race::Horse'->new( ...);

That's not a price I want to pay for a mere esthetical improvement.
I'd say sorry for bringing it up, but the discussion has helped me
realize the idea isn't worth much, so I won't.

Anno
 
Reply With Quote
 
Brian McCauley
Guest
Posts: n/a
 
      07-17-2004
http://www.velocityreviews.com/forums/(E-Mail Removed)-berlin.de (Anno Siegel) writes:

> Brian McCauley <(E-Mail Removed)> wrote in comp.lang.perl.misc:
> > [...] logically, if you want a
> > subroutine with the same name as the package this is &Race::Horse::
> > not &Race::Horse. This way there is no namespace polution.

>
> ...but also no way of calling the sub. Or is there?


Actually you can say 'Race::Horse::'->().

You can even do this under strict, although arguably you shouldn't be
able to. Strict refs doesn't seem to apply to symrefs that are
resolved (or optomised away) at compile time but this is no something
I'd want to rely on.

> I'm afraid the whole plan is what we call a "Schnapsidee" in German
> (though no booze was involved in bringing it up).


> I'd say sorry for bringing it up, but the discussion has helped me
> realize the idea isn't worth much, so I won't.


Still, it was fun wasn't it?

--
\\ ( )
. _\\__[oo
.__/ \\ /\@
. l___\\
# ll l\\
###LL LL\\
 
Reply With Quote
 
Lukas Mai
Guest
Posts: n/a
 
      07-17-2004
Brian McCauley schrob:
[...]
> Actually you can say 'Race::Horse::'->().


> You can even do this under strict, although arguably you shouldn't be
> able to. Strict refs doesn't seem to apply to symrefs that are
> resolved (or optomised away) at compile time but this is no something
> I'd want to rely on.


It gets weirder:

$ perl -Mstrict -e '"foo"->{bar} = 42'
Global symbol "%foo" requires explicit package name at -e line 1.

$ perl -Mstrict -e 'our %foo; "foo"->{bar} = 42'
Variable "%foo" is not imported at -e line 1.
Global symbol "%foo" requires explicit package name at -e line 1.

What?

$ perl -Mstrict -le '"::foo"->{bar} = 42; print "::foo"->{bar}'
42

$ perl -MO=Deparse -Mstrict -e '"::foo"->{bar} = 42;\
print "::foo"->{bar}'
use strict 'refs';
$foo{'bar'} = 42;
print $foo{'bar'};
-e syntax OK

$ perl -Mstrict -e '${"::foo"}{bar} = 42;'
Can't use string ("::foo") as a HASH ref while "strict refs" in use at
-e line 1.

I don't understand what's going on here. Apparently string literals are
exempt from use strict "refs", but only when using -> to dereference
them. And use strict "vars" doesn't let me declare them with our(), but
an explicit package name works.

Confused, Lukas
--
main(int v,char**c){c?main(atoi(c[--v]),0),
puts("")utchar((v/2&&main(v/2,0),48|v&1));}
 
Reply With Quote
 
Tassilo v. Parseval
Guest
Posts: n/a
 
      07-17-2004
Also sprach Lukas Mai:

> Brian McCauley schrob:
> [...]
>> Actually you can say 'Race::Horse::'->().

>
>> You can even do this under strict, although arguably you shouldn't be
>> able to. Strict refs doesn't seem to apply to symrefs that are
>> resolved (or optomised away) at compile time but this is no something
>> I'd want to rely on.

>
> It gets weirder:
>
> $ perl -Mstrict -e '"foo"->{bar} = 42'
> Global symbol "%foo" requires explicit package name at -e line 1.


It looks as though perl treats

"foo"->{bar}

as

*foo->{bar}

which follows the ordinary logic of accessing the HASH slot of a
typeglob in a similar way to doing

*foo = \%hash;

> $ perl -Mstrict -e 'our %foo; "foo"->{bar} = 42'
> Variable "%foo" is not imported at -e line 1.
> Global symbol "%foo" requires explicit package name at -e line 1.
>
> What?


This I don't understand either. There seems to be a minor but important
difference in the optree of the above two:

our %foo; "foo"->{bar}

gives:

...
SVOP (0x8149470) gv GV (0x82161a4) *<none>::foo
^^^^^^^^^^^^ !!

compared to

our %foo; *foo->{bar};

# or

our %foo; "::foo"->{bar};

resulting in

...
SVOP (0x814946 gv GV (0x814809 *foo
^^^^
> $ perl -Mstrict -le '"::foo"->{bar} = 42; print "::foo"->{bar}'
> 42
>
> $ perl -MO=Deparse -Mstrict -e '"::foo"->{bar} = 42;\
> print "::foo"->{bar}'
> use strict 'refs';
> $foo{'bar'} = 42;
> print $foo{'bar'};
> -e syntax OK
>
> $ perl -Mstrict -e '${"::foo"}{bar} = 42;'
> Can't use string ("::foo") as a HASH ref while "strict refs" in use at
> -e line 1.
>
> I don't understand what's going on here. Apparently string literals are
> exempt from use strict "refs", but only when using -> to dereference
> them. And use strict "vars" doesn't let me declare them with our(), but
> an explicit package name works.


It looks as though perl can be confused enough to get the package of a
global variable wrong. A cursory scan through the source suggests that
thus bug occurs somewhere in Perl_gv_fetchpv which doesn't try hard
enough to figure out the namespace of a global under certain rare
circumstances.

Tassilo
--
$_=q#",}])!JAPH!qq(tsuJ[{@"tnirp}3..0}_$;//::niam/s~=)]3[))_$-3(rellac(=_$({
pam{rekcahbus})(rekcah{lrePbus})(lreP{rehtonabus}) !JAPH!qq(rehtona{tsuJbus#;
$_=reverse,s+(?<=sub).+q#q!'"qq.\t$&."'!#+sexisexi ixesixeseg;y~\n~~dddd;eval
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
object-like macro used like function-like macro Patrick Kowalzick C++ 5 03-14-2006 03:30 PM
Nested Class, Member Class, Inner Class, Local Class, Anonymous Class E11 Java 1 10-12-2005 03:34 PM
Anyone know anything named DX? (was Re: Announcing PyCs) (was:Announcing PyCs, a new Python-like language on .Net) Mark Hahn Python 22 09-09-2004 12:14 PM
any pure HTML creator like SmartStore ? Henrik HTML 5 01-18-2004 01:52 AM
access creator of class Max-Ph. Blickenstorfer ASP .Net 0 01-07-2004 03:31 PM



Advertisments