Ovid/moosex-extended

Use Feature::Compat::Try by default rather than include Syntax::Keyword::Try?

Closed this issue · 6 comments

gmbow commented

Syntax::Keyword::Try is great, and making it available as an include is a nice feature in MooseX::Extended.


After the try syntax made is way to the Perl core (which was one of the purpose of the Syntax::Keyword experiment I believe), Paul Evans came up with Feature::Compat::Try, which transparently chooses the best option (perl core or the keyword module - with a config that makes it functionally equivalent to the core).

The last point is the key thing ; with the set of options that the Compat module passes to the Keyword module, you get exactly the same behavior as in the latest Perl core. That's not the case when you just use Syntax::Keyword::Try, because the Keyword module may have more features by default than the core.

In the end, the Compat module makes the syntax available in older Perls in a way that makes it transparent to later on transition to perl 5.34 - the author keeps updating the module as the core syntax develops.


Few ideas that derive from this :

  • why not load the Compat module instead of the Keyword module in the try include ?
use MooseX::Extended includes => [qw/try/];
# loads Feature::Compat::Try 
  • even more radically, why not enable the try feature by default, rather than on demand?
use MooseX::Extended;
# loads Feature::Compat::Try 

use MooseX::Extended excludes => [qw/try/];
# doesn't load Feature::Compat::Try 

I understand that's (a) a design decision (b) a possibly breaking change -- so let me try describe some motivations :

  • the core try is not experimental anymore, and seems to be here to stay
  • the Compat module makes client code available "core try"-ready from the start
  • the change probably only breaks code that use experimental features of the Keyword module (such as the typed catch)
  • ... in a very far future where the whole world is running perl >= 5.34, you can internally drop the dependency to the Compat module without a any possible glitch !
Ovid commented

With the latest release, if you have a single argument to an import option, you no longer need an array ref:

use MooseX::Extended includes => 'try';

As for switching to Feature::Compat::Try, that's tempting. Let me look into that. As for making it the default, that's also tempting, but I'm trying to be conservative (too conservative?). If I make it the default, it implies that anyone currently using try via includes would break, so I'd have to ensure that includes would silently ignore try (and it would have to be documented carefully) at first, and later warn, before finally being removed from the includes list entirely.

Definitely need to think about that. More arguments in favor of your position welcome :)

Ovid commented

I'll need to play some more, but it breaks backwards-compatibility. Inside, we have this:

      Syntax::Keyword::Try->import(qw( try -require_catch -require_var ));

And that causes this test failure:

t/try.t .. Expected (VAR) for catch at t/try.t line 19.

So it will break code.

That being said, I can modify my imports to handle this correctly, but it speaks to a larger issue that's been bugging me for a while: we import modules and we don't allow arguments to be passed to those modules to customize their behavior. You get the default or nothing. I really need to fix that.

Ovid commented

I've taken the core of Feature::Compat::Try and added it directly into MooseX::Extended. You can also now pass import lists to the various features in includes. This on version 0.33 on its way to the CPAN now.

gmbow commented

I've taken the core of Feature::Compat::Try and added it directly into MooseX::Extended.

That’s a good thing already, thank you for that.

But now if someone is transitioning to a newer Perl version their code may break.

I understand that’s a trade off and you are taking the conservative root ; if someone is upgrading their perl version they should carefully check for breakage anyway.

Ovid commented

But now if someone is transitioning to a newer Perl version their code may break.

Yes, that is a potentially an issue. I should document this.

gmbow commented

But now if someone is transitioning to a newer Perl version their code may break.

Yes, that is a potentially an issue. I should document this.

As far as I understand, the gap is not that wide, since there are just a few features that are provided by the Keyword and not by the core try. That would be :

  • typed catch - that’s an experimental feature in the Keyword module
  • try without catch
  • catch without assigning the error to a lexical variable

Here is how the Compat module loads the Keyword module, here :

Syntax::Keyword::Try->import(qw( try -require_catch -require_var ));

As I understand : this imports the keyword, and configures the module such that a try block must be followed by a catch block, and that a variable is required whom the error should be assigned to in the catch block.

I am speculating that the impact is not that big (but who really knows what the code that uses MooseX::Extended looks like?)… and here comes again the argument in favor of pushing the Compat module up front (you mentioned you were interested reading more about that…)