agianni has asked for the wisdom of the Perl Monks concerning the following question:

Following up on my previous post, which took care of the specific question I asked, I am now faced with another problem:
#!perl use strict; use warnings; use Test::More qw( no_plan ); my $obj = GlobTest->new(); isa_ok( $obj, 'GlobTest' ); for my $method ( 0..9 ) { can_ok( $obj, $method ); } package GlobTest; BEGIN{ for my $method ( 0..9 ) { no strict 'refs'; *$method = sub { return $_ }; } } sub new { bless {}, shift }

Why can't I call those manufactured methods on the object? Shouldn't those typeglobs be in the GlobTest package space and therefor available as methods of a GlobType object?

perl -e 'split//,q{john hurl, pest caretaker}and(map{print @_[$_]}(joi +n(q{},map{sprintf(qq{%010u},$_)}(2**2*307*4993,5*101*641*5261,7*59*79 +*36997,13*17*71*45131,3**2*67*89*167*181))=~/\d{2}/g));'

Replies are listed 'Best First'.
Re: Calling locally manufactured (typeglob) methods
by rhesa (Vicar) on Apr 05, 2007 at 15:55 UTC
    0..9 aren't valid identifiers, so you can't use them as glob names just like that (and you really shouldn't).

    A trick is to make $method contain the package name explicitly:

    package GlobTest; BEGIN{ for my $method ( map { __PACKAGE__ . '::' . $_ } 0..9 ) { no strict 'refs'; *$method = sub { return $_ }; } } sub new { bless {}, shift }
    That makes all tests pass. But again, I don't think numerical method names are a good idea.
      0..9 aren't valid identifiers, so you can't use them as glob names just like that (and you really shouldn't).
      They are valid identifiers (e.g. $^O = ~ /(.*)/; print "os: $1\n";), just special ones. As perlvar says:
      Perl identifiers that begin with digits, control characters, or punctuation characters are exempt from the effects of the package declaration and are always forced to be in package main
        Sure, sure. They're valid enough in that respect. But it also says:
        Perl variable names may also be a sequence of digits or a single punctuation or control character. These names are all reserved for special uses by Perl;
        That means you're not supposed to use them outside their intended, reserved, special contexts.

        What's more:

        % perl -e 'my $14' Can't use global $14 in "my" at -e line 1, at end of line % perl -e '$1 = q/foo/' Modification of a read-only value attempted at -e line 1. % perl -e 'sub 14 { 14 }' Illegal declaration of anonymous subroutine at -e line 1.
        Doesn't look very valid on the face of it, does it?

        So in order to (ab)use them like ordinary identifiers at all, you have to jump through hoops. And you'll get pummeled to death by your coworkers or future maintenance programmers. That's why I said "invalid". It may not be technically precise, but in practice it's accurate enough.

Re: Calling locally manufactured (typeglob) methods
by agianni (Hermit) on Apr 05, 2007 at 15:51 UTC
    Never mind, this example doesn't seem to adequately express the problem I'm having. It looks like manufacturing the methods with just numbers as names is causing the problem for me in this case.
    perl -e 'split//,q{john hurl, pest caretaker}and(map{print @_[$_]}(joi +n(q{},map{sprintf(qq{%010u},$_)}(2**2*307*4993,5*101*641*5261,7*59*79 +*36997,13*17*71*45131,3**2*67*89*167*181))=~/\d{2}/g));'

      I can only imagine what the problem is since you didn't describe it but I am guessing that perhaps you goofed by returning $_ instead of $method. $_ is a global and when you call it will have values unrelated to the 0..9 you named your methods after.

      I would like to offer you a bit of hope in your method names. In theory, you can name your methods just about anything. Your calling syntax may not be pleasant or usual but it does not become impossible just because your identifers no longer match /^[_[:alpha:]]\w*\z/ or /^\p{IdStart}\p{IdContin}*\z/.

      $method = '1'; $obj->$method; # Works! $obj->1; # Doesn't work!

      ⠤⠤ ⠙⠊⠕⠞⠁⠇⠑⠧⠊