MooseStyle: Self-made inline vs cpan-based inline


I have read the "Add-Moose-style-attribute-accessors-to-your-Perl-classes" article from David Farrell.


I understand his issue with "sans dependencies" but was uncomfortable with
his solution. To write this code-snippet everytime (or copy&past)
and maintain every file feels wrong.

I rememberd of Mo and Mo:Inline.
What turned out to be better than in my memory.

What are your opinions?

10 Comments

Mo::Inline is a cool idea, but the extreme golfing used by Mo for very little reason makes it something I'm no longer comfortable using in production code.

Hopefully David Golden will achieve his ambition for Class::Tiny to be added to core, then all such silliness can end.

What Mo does isn't really golfing in the way it's typically known, but mostly minimization in the same style as many JS minifiers do it. Unless you have specific complaints, you have no reason to worry about it.

Also, it is done for the very specific reason that this way it can be dropped into software with copy&paste without even changing the line numbers.

An inlining script could easily fiddle the line numbers.

Hey Matthias,

Thanks for considering the article even worth discussing :) I'll check out Mo::Inline.

One thing I wanted to clarify: generally I would advocate using Moo/Moose over vanilla Perl OO, but there seems to be a lot of interest in vanilla Perl OO articles (our most popular article is Old School OO Perl, hence the article.

With Moo/Moose you could achieve something similar with:
for (qw/x y/) { has $_ => ( is => 'rw') }

Either way it's a limiting pattern - especially for argument checking which would be a PITA to implement this way.

Thanks,

David

Or in Moose/Moo:

has [qw/x y/] => ( is => 'rw' );

An upgrade to Mo::Inline appears to be behind this issue for YAML:

https://rt.cpan.org/Ticket/Display.html?id=90817

and I think a similar issue was behind this:

https://rt.cpan.org/Ticket/Display.html?id=76664

It's not the most pleasant code to be debugging either.

It's an interesting idea, but I'm treating it as a warning sign in code in future, particularly anything that so many other modules depend on.

> Is your issue about Mo or about non-core dependencies?

Neither - it's about modules which use Mo::Inline. Mo itself seems fine, if a module uses it and works, that's great. Non-core dependencies... the more the merrier. I have no objections to a module depending on Mo itself. My specific complaint (as Mithaldu was asking) is that debugging something which has been through the Mo::Inline process is a headache I'd rather avoid.

Granted, YAML is perhaps an extreme case, several things depend on it so breakage is very visible, and it's mildly disheartening to open the RT queue and see that there's >100 open tickets to check.

Also, please note that ingy has already released a new version of YAML which so far seems to resolve the problem -

At least Mo::Inline can update all your scripts with one command.

That's a nice feature.

My main issue is that these aren't my scripts/modules: if something breaks in a dependency it's usually worth taking a look at the source to see if it's an easy fix.

In this case... apparently there was a bug somewhere in here:


no warnings;my$M=__PACKAGE__.'::';*{$M.Object::new}=sub{my$c=shift;my$s=bless{@_},$c;my%n=%{$c.::.':E'};map{$s->{$_}=$n{$_}->()if!exists$s->{$_}}keys%n;$s};*{$M.import}=sub{import warnings;$^H|=1538;my($P,%e,%o)=caller.'::';shift;eval"no Mo::$_",&{$M.$_.::e}($P,\%e,\%o,\@_)for@_;return if$e{M};%e=(extends,sub{eval"no $_[0]()";@{$P.ISA}=$_[0]},has,sub{my$n=shift;my$m=sub{$#_?$_[0]{$n}=$_[1]:$_[0]{$n}};@_=(default,@_)if!($#_%2);$m=$o{$_}->($m,$n,@_)for sort keys%o;*{$P.$n}=$m},%e,);*{$P.$_}=$e{$_}for keys%e;@{$P.ISA}=$M.Object};*{$M.'builder::e'}=sub{my($P,$e,$o)=@_;$o->{builder}=sub{my($m,$n,%a)=@_;my$b=$a{builder}or return$m;my$i=exists$a{lazy}?$a{lazy}:!${$P.':N'};$i or ${$P.':E'}{$n}=\&{$P.$b}and return$m;sub{$#_?$m->(@_):!exists$_[0]{$n}?$_[0]{$n}=$_[0]->$b:$m->(@_)}}};*{$M.'default::e'}=sub{my($P,$e,$o)=@_;$o->{default}=sub{my($m,$n,%a)=@_;exists$a{default}or return$m;my($d,$r)=$a{default};my$g='HASH'eq($r=ref$d)?sub{+{%$d}}:'ARRAY'eq$r?sub{[@$d]}:'CODE'eq$r?$d:sub{$d};my$i=exists$a{lazy}?$a{lazy}:!${$P.':N'};$i or ${$P.':E'}{$n}=$g and return$m;sub{$#_?$m->(@_):!exists$_[0]{$n}?$_[0]{$n}=$g->(@_):$m->(@_)}}};my$i=\&import;*{$M.import}=sub{(@_==2 and not$_[1])?pop@_:@_==1?push@_,grep!/import/,@f:();goto&$i};@f=qw[builder default import];use strict;use warnings;

at which point I close the editor and look for other options...

Leave a comment

About Matthias

user-pic I blog about Perl.