moderated >> adding an attribute to a sub

by nadim » Sat, 02 Apr 2005 10:02:20 GMT


Hi,

I need to tag a sub in some way. had it been a variable I could have blessed
it but it's a sub (hold on, why couldn't I bless a sub ref?).

I also need to have it look nice. Using attributes sounds like a good idea but
I don't understand how to define new attributes to use with the attributes
module.

Using Attribute::Handlers is easy (mainly because the doc is much better) but
I can't get the list of attributes through attributes::get and I don't see
any other method.

I attach the example I wrote.

Cheers, Nadim.


moderated >> adding an attribute to a sub

by Brian McCauley » Sat, 02 Apr 2005 18:18:41 GMT



Dunno, why couldn't you? I can.


I knew nothing about non-bultin attributes until 10 minuites ago.

After a quick look at the source it appears that there is no builtin
mechanism for the storing of non-builtin attibutes. Your handlers (ether
defined though Attribute::Handlers or directly though the lower level
attributes mechanism) are responsible for recording the attribute in
some way.

If you want your new attributes to be fetchable with attributes::get
then you need to define a method FETCH_CODE_ATTRIBUTES (and so on for
SCALAR, HASH, ARRAY)

Attribute::Handlers does not define such a method.

Clearly you could define a method FETCH_CODE_ATTRIBUTES (and so)
reachable via UNIVERSAL but you'd have a problem if any other module did
so too.

My advice is go back to your originial suggestion and have your handler
bless the CODEref and when you want to find out if a subroutine has one
of your attributes examine the blessing.

moderated >> adding an attribute to a sub

by mjtg » Sat, 02 Apr 2005 20:33:37 GMT


You can bless a sub reference:

perl -wl
sub Foo::bar { print "Foo::bar" };
my $x = bless sub {}, 'Foo';
$x->bar;
__END__
Foo::bar


Mike Guy

moderated >> adding an attribute to a sub

by nadim » Sun, 03 Apr 2005 07:28:58 GMT

I did play with blessing a sub and it works fine but I still wanted to make it
look a bit nicer.

I used Attribute::Handlers to bless the sub ref. A::H can control that the
attribute is added to a sub ref so half the work is done.

This works:
use Attribute::Handlers ;

sub Creator : ATTR(CODE)
{
my ($package, $symbol, $referent, $attr, $data, $phase) = @_;

# some debug info
print STDERR
ref($referent), " '",
*{$symbol}{NAME}, "' ",
"($referent) ", "was just declared ",
"and ascribed the ${attr} attribute ",
#"with data ($data)\n",
"in phase $phase\n";

bless $referent, $attr ;
}

sub test : Creator
{
print "creator\n" ;
}

print "sub is a " . ref \&test ;
print "\n" ;

but when I move the attribute sub to its own module, it stops working though
the documentation says it should work.

use PBS::Attributes ;

sub test : Creator
{
print "creator\n" ;
}

print "sub is a " . ref \&test ;
print "\n" ;

Gives:
Invalid CODE attribute: Creator at attrib.pl line 6
BEGIN failed--compilation aborted at attrib.pl line 8.

moderated >> adding an attribute to a sub

by Brian McCauley » Sun, 03 Apr 2005 17:01:49 GMT

[ Please don't post TOFU ((new) Text Over, Fullquote Under) it is
considered rude. Rudeness corrected ]




>
>>My advice is go back to your originial suggestion
>>and have your handler bless the CODEref


I've had a look at how Attribute::Handlers' handlers are implemented.
Basically they are methods.

When you say in "sub test : Creator {....}" in package main perl will
effectively.

sub test; # Forward declaration
use attributes ('main',\&test,'Creator');
sub test {....};

The use statement, of course, expands to:

BEGIN {
require attributes;
attributes->import('main',\&test,'Creator');
}

Which in turn will resolve to a call to &attributes::import.

&attributes::import will then call main->MODIFY_CODE_ATTRIBUTES

Which in turn will resolve (via @UNIVERSAL::ISA) to a call to
&Attribute::Handlers::UNIVERSAL::MODIFY_CODE_ATTRIBUTES.

This will in turn will try to call main->_ATTR_CODE_Creator.

But this will not resolve to &PBS::Attributes::_ATTR_CODE_Creator
because @main::ISA does not inherit from PBS::Attributes.

Try

use base qw(PBS::Attributes);

As I say this is all new to me. One thing that seems odd is the fact
that your Creator hander actually exists as &PBS::Attributes::Creator as
well as existing &PBS::Attributes::_ATTR_CODE_Creator etc.

moderated >> adding an attribute to a sub

by nadim » Sun, 03 Apr 2005 23:13:02 GMT

Great detective work Brian.

FYI, I am using this to "tag" subs that are used in a build system. I need
syntactic sugar so people writtin makefiles (in perl) don't need to do it in
an OO fashion.

IE:

#stuff pushed magically in this space like "use base(..)

sub X : Creator {} ;
AddRule 'name' , [\&X, '*.X' => 'some_dependency] ;

instead for:

my $creator = new Creator( sub{..}) ;
my $rule = new Rule('name', $creator, ...=) ;
AddRule($rule) ;


De-OObjectifying something that should be is challenging and fun (and
wrong ;-)

Cheers, Nadim.

moderated >> adding an attribute to a sub

by nadim » Mon, 04 Apr 2005 06:38:07 GMT


That worked fine till I tried this:

1/ PBS::Attributes is unchanged

2/ In package PBS::Rules I have the following:

use base qw(PBS::Attributes) ;

sub GeneratelCreator
{
my $s = sub : Creator { $creator->(@args)} ;

return($s) ;
}

PBS::Rules is automatically loaded in "makefiles" so the user can write rules
and, this what I need to add, write subs that are "creators".

I get this error:

[nadim@khemir PIP]$ pbs -dpt
Can't locate auto/PBS/Rules/_ATTR_CODE_.al in @INC (@INC
contains: /usr/local/lib/perl5/5.8.5/i686-linux /usr/local/lib/perl5/5.8.5 /usr/local/lib/perl5/site_perl/5.8.5/i686-linux /usr/local/lib/perl5/site_perl/5.8.5 /usr/local/lib/perl5/site_perl .)
at /usr/local/lib/perl5/5.8.5/Attribute/Handlers.pm line 189
CHECK failed--call queue aborted.

This must happend before any "makefile" is loaded then I 'm lost!!!

Cheers, Nadim.

Similar Threads

1. cperl mode formatting of attributed subs

2. Idea: 'throws' attribute for subs

Greetings, colleagues!

I'm going to begin working on an extension, that would introduce an
attribute for subroutines, somewhat similar to Java's 'throws'.

It could like something like <<'__THE_FOLLOWING__':
use <TheModule>;
use Exception::Class (
    'Danger',
    'Danger::Avalanche' => { isa => 'Danger' },
    'Danger::Tornado' => { isa => 'Danger' },
);

sub dangerous : throws(Danger'Avalanche,Danger'Tornado) { }
__THE_FOLLOWING__

If 'dangerous' is called from somewhere else and Danger::Avalanche and
Danger::Tornado (or any ancestor exception class, i. e. Danger or
Exception::Class) are not being caught,
then an exception like <<'__THIS__' will be thrown:
Exceptions 'Danger::Avalanche', 'Danger::Tornado' are not being caught
at badcode.pl line 8
__THIS__

I've got a couple of questions:
1. Is there something like this already available?
2. What name for 'TheModule' can you suggest?
3. Any ideas how to make 'exception not being caught' exception be
thrown during the compilation phase, to make sure all thrown
exceptions are caught in the code, even if some subroutines are not
called afterwards during the execution? In other words, do you see a
way how to get the stack of subroutine calls during the compilation
phase, not waiting for subroutines are really executed?

Regards,
Ivan

3. Add attributes to Hyperlinks in HyperLinkColumn

4. control.Attributes.Add() not working properly

Hello,

I have a textbox in a datagrid row which has autopostback. When it posts 
back, it updates a prop on an object in a session variable.
In order to update the right object, in the ItemDataBound of the grid, i was 
adding the objects ID property as a
MyTextbox.Attributes.Add("recid",rowDataItemObj.RecID)
along with several other attributes.

For some reason these attributes are not being added the first time through. 
But when do a postback, then they get added properly. The code adding the 
attributes is not enclosed in any IsPostback checks.

anyone ever had this problem before, or can help?

Thanks in advance,
- ArthurDent 


5. properly adding multiple javascript attributes - Microsoft .NET Framework

6. adding attributes to a database handle

Two questions:

1. Is it possible to add/store "user defined" attributes in a database handle.

I'd like to do something like this:

my $dbh = DBI->connect(...);

$dbh->{important_info} = ...;

...

print "the important info was: ", $dbh->{important_info}, "\n";

2. Is there anything preventing the sub-classing of database handles
(i.e. reblessing into a sub-class after creation)?

7. Adding attributes to xml root element. - Perl

8. Net::LDAP - adding value to an existing attribute

Although the manpage for NET::LDAP::Entry states that using add method
would add to the values of an existing entry, LDAP server refuses to
add the entry on calling update method stating "Already exists"
(message code 68, ldap_error_text given below).  How do I overcome
this?

TIA

--------
Net::LDAP::Entry manpage excerpt:
--------

add ( ATTR => VALUE [, ATTR2 => VALUE2 ... ] )

    Add one or more new attributes to the entry. Each value must be a
scalar variable or a reference to an array. The values given will be
added to the values which already exist for the given attributes.

--------
ldap_error_text
--------

The client attempted to add an entry that already exists. This can
occur as
a result of

 * An add request was submitted with a DN that already exists

 * A modify DN requested was submitted, where the requested new DN
already exist
s

 * The request is adding an attribute to the schema and an attribute
with the
   given OID or name already exists