Using a variant of that, we could let the undocumented 1.95 interface result when doing
use Text::Balanced; # or use Text::Balanced 1.95;
so that existing code will not be broken any more than it is. However, the new interface can result when doing
use Text::Balanced 2.00;
Further, both interfaces may be used simultaneously in the same program as such:
use Text::Balanced 2.00, qw(extract_quotelike);
package Two; use Text::Balanced 1.90, qw(extract_quotelike); my $res = (extract_quotelike('asdf'))[0]; print defined($res) ? "[$res]" : '(undef)'; # prints '[]'
package main; my $res = (extract_quotelike('asdf'))[0]; print defined($res) ? "[$res]" : '(undef)'; # prints '(undef)'
Here is the basic solution:
==========Text/Balanced.pm===========
use vars qw { $VERSION @ISA %EXPORT_TAGS %my_vers $caller}; $VERSION = '2.00'; @ISA = qw ( Exporter );
sub import { foreach (@_) { $my_vers{caller()} = $1 if(/^(\d+); } Text::Balanced->export_to_level(1, @_); }
sub VERSION { my $req_ver = $_[1]; $req_ver < 1.87 and croak "Text::Balanced $VERSION is incompatible with the requested " . "version $req_ver."; $req_ver > $VERSION and croak "Text::Balanced $VERSION is older than the requested " . "version $req_ver."; return $req_ver; }
sub _fail { ... return (undef,$$textref) if $my_vers{$caller} == 2; # new style return ('',$$textref,''); # old style (v. 1.xx) ... }
sub extract_quotelike (;$$) { ... $caller = caller() unless caller() eq 'Text::Balanced'; ... return _fail($wantarray, $textref) unless @match; ... };
sub extract_multiple (;$$$$) { $caller = caller() unless caller() eq 'Text::Balanced'; ... # this can call extract_quotelike() ... }
===========================
The complexity with using caller() is needed unfortunately since the module has a functional interface. I'll think this solution over some more since I have doubts that the added correctness with existing code is worth making new code potentially more brittle.
A simpler solution would be to just croak if a 1.95 or prior version is specified in "use" and possibly carp or croak (probably carp) if *no version* is specified. That comes with its own small issues of course.
-davidm
david wrote:
Vagn Johansen wrote:
How are interface changes handled on CPAN?
They're not. I'm trying to promote a pradigm of including a VERSION subroutine that
will croak (or at least die) when you ask for a non-forwards-compat. version.
In theory, you change the name when you change the itnerface, instead of merely
updating the version number.
How do you avoid breaking old programs when the interface changes?Issue a new module name with the new interface, and maintain both versions for bugs.