RFC strict::can

2005-12-04 Thread Ovid
strict::can is a module which, if used, imports a can method into
your namespace.  This version of can() will not report imported helper
functions or private methods.  Full docs below.

Comments and suggestions welcome.

Cheers,
Ovid

--

NAME
strict::can - Make can() ignore private methods and imported
subroutines

VERSION
Version 0.01

SYNOPSIS
 package Foo;
 use strict::can;
 use HTML::Entities qw(encode_entities); # imported into Foo::
 
 sub new { bless {}, shift }
 sub _private { 'some private function' }

 # later
 Foo-can('new');  # true
 Foo-can('encode_entities');  # false (because it's an imported
function)
 Foo-can('_private'); # false (because it's a private
function, even
   #though we can still call
it)

EXPORT
This module exports a can() method into your namespace.

DESCRIPTION
This module gives your classes a can() method which overrides
(not
replaces) UNIVERSAL::can. In most respects it behaves like you
expect
it should, but does not report private methods (see below) or
imported
functions.

  Imported functions
Frequently we import helper functions into our namespace.
Ordinarily
can() will return the code reference for these functions even
though
this is probably not what we want. strict::can will return false
for
any imported functions/methods. If you want to expose them, write
wrapper methods for them.

 {
 package Foo;
 use strict::can;
 use HTML::Entities qw/encode_entities/; # import into Foo::
 ...
 sub encode {
 my ($self, @args) = @_;
 return encode_entities(@args);
 }
 }
 
 # later
 if (Foo-can('encode_entities')) {
 # never gets to here
 }

  Private methods
Methods which begin with an underscore are, by convention,
considered
private and should not be relied on. Unfortunately, can()
succeeds
with those, too. strict::can will return false for private
methods
unless the class checking can() is a *subclass* of the class or
instance it is checking. This is because we're allowing a little
more
trust for subclasses as private methods are often protected
methods
which subclasses should be allowed to use.

 {
 package Foo;
 use strict::can;
 ...
 sub _private {
 return 'Top Sekret!';
 }
 }
 
 # later
 {
 package main;
 if (Foo-can('_private')) {
 # never gets to here
 }
 }
 {
 package Foo::Bar;
 our @ISA = qw(Foo);
 if (Foo-can('_private')) {
 # success at last!
 }
 }

AUTHOR
Curtis Ovid Poe, [EMAIL PROTECTED]

BUGS
Please report any bugs or feature requests to
[EMAIL PROTECTED], or through the web interface at
http://rt.cpan.org/NoAuth/ReportBug.html?Queue=strict-can. I will
be
notified, and then you'll automatically be notified of progress on
your
bug as I make changes.

SEE ALSO
The B::svref_2object function.

COPYRIGHT  LICENSE
Copyright 2005 Curtis Ovid Poe, all rights reserved.

This program is free software; you can redistribute it and/or
modify it
under the same terms as Perl itself.

-- 
If this message is a response to a question on a mailing list, please send
follow up questions to the list.

Web Programming with Perl -- http://users.easystreet.com/ovid/cgi_course/


Re: Perl editing support in Vim (was: FF:: namespace)

2005-12-04 Thread Smylers
A. Pagaltzis writes:

 * Smylers [EMAIL PROTECTED] [2005-12-04 03:35]:
 
  That's because the default ftplugin/perl.vim sets iskeyword to
  include the colon, so that all gets treated as a single word.
  Until now I hadn't seen a disadvantage of removing that colon,
  but now you've pointed that out I'm going to have to choose
  between putting up with that bug in syntax highlighting or
  making namespaces more awkward to complete ...
 
 Another disadvantage, and a reason I could never live without
 that colon: move the cursor on top of a module name, then hit
 [Ctrl-W][f] or [g][f].

That's the colon in isfname (which I do have), rather than the one in
iskeyword (which I don't, but perhaps I should).

 Neat, no?

Indeed (though there's an irritating bug where if I have something like
~/lib/perl/ early in my path and CGI::Lite is installed there then when
Perl searches for CGI will find the _directory_ ~/lib/perl/CGI/
(necessary for CGI::Lite), rather than CGI.pm (which is later in the
path).  There's some magic which says also check for this filename with
'.pm' on the end, but we really want that to be only rather than
also.

The last time I looked at that I couldn't see a way of fixing it.

 It could be smarter yet (it only works relative to @INC or the current
 directory; hmm, now that I think about it I may have an idea for to
 fix that?)

I have this in ~/.vim/after/ftplugin/perl.vim:

  let l:path = system('perl -I, -Ilib -I../lib -e print join q[,], @INC')

That adds in ./lib/ and ../lib/.  But it'd be good to look for use lib
statements and similar in the code and add those in too.

Smylers
-- 
May God bless us with enough foolishness to believe that we can make a
difference in this world, so that we can do what others claim cannot be done.



Re: RFC strict::can

2005-12-04 Thread Kurt Starsinic
On 12/4/05, Ovid [EMAIL PROTECTED] wrote:
 strict::can is a module which, if used, imports a can method into
 your namespace.  This version of can() will not report imported helper
 functions or private methods.  Full docs below.

 Comments and suggestions welcome.

I think that the ignore private feature is less than useful.  If
one agrees with the convention of prepending private methods with an
underscore (which I personally do find useful), then one won't *call*
can() on such a method.  But since that convention is not enforced by
the language, what is the value of codifying it in a module?

As to the imported-subroutines feature, that could break a lot of
code.  Here's a simple example:

   package Foo;
   use Exporter;
   use strict::can;
   if (Foo-can('import')); # BOOM

I can provide other examples from my own code, but I think you get
the point.

The module is clever, but it's not clear to me that it's
practically useful.  Could you provide a real-world example where this
would help to prevent or detect a programming error?

- Kurt


 Cheers,
 Ovid

 --

 NAME
 strict::can - Make can() ignore private methods and imported
 subroutines

 VERSION
 Version 0.01

 SYNOPSIS
  package Foo;
  use strict::can;
  use HTML::Entities qw(encode_entities); # imported into Foo::

  sub new { bless {}, shift }
  sub _private { 'some private function' }

  # later
  Foo-can('new');  # true
  Foo-can('encode_entities');  # false (because it's an imported
 function)
  Foo-can('_private'); # false (because it's a private
 function, even
#though we can still call
 it)

 EXPORT
 This module exports a can() method into your namespace.

 DESCRIPTION
 This module gives your classes a can() method which overrides
 (not
 replaces) UNIVERSAL::can. In most respects it behaves like you
 expect
 it should, but does not report private methods (see below) or
 imported
 functions.

   Imported functions
 Frequently we import helper functions into our namespace.
 Ordinarily
 can() will return the code reference for these functions even
 though
 this is probably not what we want. strict::can will return false
 for
 any imported functions/methods. If you want to expose them, write
 wrapper methods for them.

  {
  package Foo;
  use strict::can;
  use HTML::Entities qw/encode_entities/; # import into Foo::
  ...
  sub encode {
  my ($self, @args) = @_;
  return encode_entities(@args);
  }
  }

  # later
  if (Foo-can('encode_entities')) {
  # never gets to here
  }

   Private methods
 Methods which begin with an underscore are, by convention,
 considered
 private and should not be relied on. Unfortunately, can()
 succeeds
 with those, too. strict::can will return false for private
 methods
 unless the class checking can() is a *subclass* of the class or
 instance it is checking. This is because we're allowing a little
 more
 trust for subclasses as private methods are often protected
 methods
 which subclasses should be allowed to use.

  {
  package Foo;
  use strict::can;
  ...
  sub _private {
  return 'Top Sekret!';
  }
  }

  # later
  {
  package main;
  if (Foo-can('_private')) {
  # never gets to here
  }
  }
  {
  package Foo::Bar;
  our @ISA = qw(Foo);
  if (Foo-can('_private')) {
  # success at last!
  }
  }

 AUTHOR
 Curtis Ovid Poe, [EMAIL PROTECTED]

 BUGS
 Please report any bugs or feature requests to
 [EMAIL PROTECTED], or through the web interface at
 http://rt.cpan.org/NoAuth/ReportBug.html?Queue=strict-can. I will
 be
 notified, and then you'll automatically be notified of progress on
 your
 bug as I make changes.

 SEE ALSO
 The B::svref_2object function.

 COPYRIGHT  LICENSE
 Copyright 2005 Curtis Ovid Poe, all rights reserved.

 This program is free software; you can redistribute it and/or
 modify it
 under the same terms as Perl itself.

 --
 If this message is a response to a question on a mailing list, please send
 follow up questions to the list.

 Web Programming with Perl -- http://users.easystreet.com/ovid/cgi_course/



Re: RFC strict::can

2005-12-04 Thread Ovid
--- Kurt Starsinic [EMAIL PROTECTED] wrote:

package Foo;
use Exporter;
use strict::can;
if (Foo-can('import')); # BOOM

 I can provide other examples from my own code, but I
 think you get the point.

The current version on my hard drive allows for import.

 The module is clever, but it's not clear to me that it's
 practically useful.  Could you provide a real-world example 
 where this
 would help to prevent or detect a programming error?

Your world and my world can be considerably different.  Using code very
similar to this solved a problem I had with Class::Trait whereby I was
exporting methods which should not have been exported.  Also, if one is
routinely in the habit of checking class capabilities rather than class
types, this can be quite useful.

Cheers,
Ovid

-- 
If this message is a response to a question on a mailing list, please send
follow up questions to the list.

Web Programming with Perl -- http://users.easystreet.com/ovid/cgi_course/


Re: RFC strict::can

2005-12-04 Thread Johan Vromans
Kurt Starsinic [EMAIL PROTECTED] writes:

 The module is clever, but it's not clear to me that it's
 practically useful.

I think it could be useful if the new 'can' would only succeed on
public methods (note: not private ones, and also not on non-methods).
This would require a way to tag subroutines as being private a/o methods. 

-- Johan


Re: RFC strict::can

2005-12-04 Thread Kurt Starsinic
On 12/4/05, Ovid [EMAIL PROTECTED] wrote:
 --- Kurt Starsinic [EMAIL PROTECTED] wrote:

 package Foo;
 use Exporter;
 use strict::can;
 if (Foo-can('import')); # BOOM

  I can provide other examples from my own code, but I
  think you get the point.

 The current version on my hard drive allows for import.

  The module is clever, but it's not clear to me that it's
  practically useful.  Could you provide a real-world example
  where this
  would help to prevent or detect a programming error?

 Your world and my world can be considerably different.  Using code very
 similar to this solved a problem I had with Class::Trait whereby I was
 exporting methods which should not have been exported.

Do you mean calling methods which should not have been called? 
It's not clear to me what, exactly, exporting methods means.

 Also, if one is
 routinely in the habit of checking class capabilities rather than class
 types, this can be quite useful.

It's clear that you're interested in addressing issues with
checking class capabilities.  What I'm not quite following is the
basis of your premise, as I understand it:  that imported functions
are, in general, not meant to called as methods (with an undocumented
exception made for import).  What I'm asking for, if you're
interested in feedback, is an example of a situation where youvre
imported a function into a class, from other code you've called can()
on said class before invoking a method call, it did The Wrong Thing,
and you posit that all of the above doesn't reflect a bug in the class
that did the importing.

You *are* suggesting making this a pragma under the very
well-known strict namespace and putting it on CPAN, so I'm
expressing my personal concern that it may not be as generally useful
and safe as the nomenclature might suggest.

- Kurt