package Function::ReturnScalar ;
use strict ;
use warnings ;
use Attribute::Handlers ;
no warnings 'redefine' ;
my $function_code_ref ;
my %behavior_of ;
$behavior_of{first} = sub { $_[0] } ;
$behavior_of{last} = sub { $_[-1] } ;
$behavior_of{count} = sub { @_ } ;
sub UNIVERSAL::ScalarContext : ATTR {
my ( $package, $symbol, $referent, $attr, $behave_how_arg ) = @_ ;
my $symbol_name = *{$symbol}{NAME} ;
my $behavior = $behavior_of{ $behave_how_arg->[0] } ;
$function_code_ref->{ $package }->{ $symbol_name } = *{$symbol}{CODE} ;
*{ $symbol } = sub {
my $original =
$function_code_ref->{ $package }->{ $symbol_name } ;
return ( wantarray ? sub { @_ } : $behavior
)->( $original->( @_ ) ) ;
} ;
return ;
}
sub UNIVERSAL::Listify : ATTR {
my ( $package, $symbol, $referent, $attr, $behave_how_arg ) = @_ ;
my $symbol_name = *{$symbol}{NAME} ;
my $behavior = sub { @_[0..$#_] } ;
$function_code_ref->{ $package }->{ $symbol_name } = *{$symbol}{CODE} ;
*{ $symbol } = sub {
my $original =
$function_code_ref->{ $package }->{ $symbol_name } ;
return $behavior->( $original->( @_ ) ) ;
} ;
return ;
}
1 ;
This would be invoked exactly as you described.
As a gratuitous bonus, I added the Listify attribute in response to your comment about "not interested".
Still trying to figure out how to throw a compiler error if an illegal argument is passed, eg $data->[0] !~ /(?:first|last|count)/.
]]>Seems like you're making the same point as Aristotle did at 3:22am. But his response included a recommendation. Yours seems less gracious.
]]>I'm wrong because the code gives me the wrong answer? Well yeah. If this were truly a question in a tech forum, I'd hope most would avoid responding simply to confirm the OP.
I'm wrong because stylistically, the most verbose approach is the best? I'll entertain a different opinion. But I disagree with the fundamental premise that the right answer is always more code.
No- you're wrong. The example lowercase function performs a mutation of arbitrary complexity (not the trivial built in op in my example). Your solution requires that the complex mutation have a duplicate definition.
Although it's an elegant answer to your follow-up question, James's solution fails for the same reason. Although his could remedied by rewriting lowercase :List to invoke the Scalar version, my original question was "How do I avoid repeatedly using the same complicated idiom?" Depending on the interpretation of point 2, you probably think my problem is actually a desirable feature.
Most importantly, I wasn't asking this technical question to get an answer. I wanted comments on my proposed solution. Your alternative, which I didn't ask for, is wrong for the reason listed above and fails to meet the simple-for-repeatability objective explicit in my OP.
Aristotle- RTFM.
It's bad enough sloughing through speculative guesses in the tech support forums. I was really hoping one of the responders would be kind enough to comment on my solution.
]]>sub lowercase {
return map { lc } @_ ;
}
$jim = lowercase('jim') ;
print "$jim\n" ;
Naturally that this snippet of code prints 1. I understand the explanation of "an array in scalar context blah blah blah". But it's so counter-intuitive because many functions are intended to mutate each element in a list. Presumably one should define separate functions depending on whether an array is expected, but that's so non-perlish. There's no elegant way to throw the wantarray operator in that example function. And even if there was, it's awkward to use the same idiom repeatedly.
I'd prefer simply to use a pragma such as the following:
use Function::ReturnScalar qw( first ) ;
## use Function::ReturnScalar qw( last ) ; # optional alternative
## use Function::ReturnScalar qw( count ) ; # optional alternative
sub lowercase {
return map { lc } @_ ;
}
$jim = lowercase('Jim') ; # $jim == 'jim'
The pragmas in the above example don't exist. At least, even after posting on perlmonks, I can't find anything equivalent. But in a couple of hours, I wrote a rudimentary module that performs this function.
]]> So if in fact there isn't one already, and others are interested in this functionality, I'd be perfectly happy to press on. In that case, please comment as appropriate.Here's my prototype:
package Function::ReturnScalar ;
use strict ;
use warnings ;
my $originals_of_package_ref ;
my @callers ;
my %behavior_of ;
$behavior_of{first} = sub { $_[0] } ;
$behavior_of{last} = sub { $_[-1] } ;
$behavior_of{count} = sub { @_ } ;
INIT {
map { _replace_package_symbols( @$_ ) } @callers ;
}
##
# Accepts one of first|last|count
##
sub import {
my ( $package, $behave_how ) = @_ ;
push @callers, [ scalar caller, $behave_how ] ;
}
sub _replace_package_symbols {
my ( $package, $behave_how ) = @_ ;
no strict qw( refs ) ;
no warnings ;
my $scalar_code_ref = $behavior_of{ $behave_how } ;
return unless $scalar_code_ref ;
my %symbols = %{ "${package}::" } ;
my @subs = grep $_->[1],
map { [ $_ => *{ $symbols{$_} }{CODE} ] }
keys %symbols ;
map { $originals_of_package_ref->{ $package }->{ $_->[0] } = $_->[1] }
@subs ;
map { *{ "$symbols{ $_->[0] }" }
= _create_closure( $package, $_->[0],
$scalar_code_ref ) }
@subs ;
return ;
}
sub _create_closure {
my ( $package, $symbol_name, $scalar_code_ref ) = @_ ;
return sub {
my $original =
$originals_of_package_ref->{ $package }->{ $symbol_name } ;
return ( wantarray ? sub { @_ } : $scalar_code_ref
)->( $original->( @_ ) ) ;
} ;
}
1;
]]>
I understand that "modern perl" specifically refers to the MOP paradigm and generally means Moose. But results on a google search for "modern javascript" only show effective synonyms for "state-of-the-art javascript".
confuseAcat's response struck me as slightly ad hominem. My fundamental point is the challenge of separating the hype from the substance. The use of the term "modern" smacks of the former in that "modern" is not very descriptive and intends to imply that its detractors are trogolodytes. FWIW, "modern" can sometimes also mean "outdated" as in "modern architecture".
preaction's response about perl directories is contrary to my understanding: I've published XML::Parser::Nodes consistent with XML::Parser::Expat, XML::Parser::PerlSax, and XML::Parser::Lite. These are all separate distros independent of XML::Parser.
In conclusion: Both these responses demonstrate the same confusion and ambiguity that I've experienced.
Also, thanks nickl, I'll check out your recommendations.
]]>The context is that recruiters are pressuring older programmers to learn JQuery (read Community College class) and I'm also wondering whether to rewrite a few apps that I maintain.
Although I don't want to overstate these parallels to Moose, JavaScript implements OO exactly the same way as Perl5- without accessors. Consequently, I'm skeptical when I hear that Perl5's OO is archaic or discredited. I didn't encounter the argument that JQuery "fixes" JavaScript's flawed OO design. But that useless book might merely have lacked the technical sophistication. Others may have already drawn this parallel.
Granted, Perl5's vocabulary, such as the @ISA idiom for inheritance, should never have persisted beyond Perl5 beta. It seems very tentative, like a placeholder for a task that was never completed.
But I've been thinking about the talk in Austin demonstrating Moose roles and how essential its "partial inheritance" features are. And I started thinking about JQuery. Does this feature simply accomodate poor programming? And as such, is there a danger of institutionalizing poor practices? Nobody should be designing classes that provide functionality beyond the "role" expected in the Moose framework. If an application is capable of multiple roles, each should be split into separate class definitions. Classes are supposed to be specific and discrete.
This post may indicate my ignorance: My CPAN contributions always consist of multiple classes that reflect this programming practice. And it's frustrating that CPAN doesn't distinguish which classes are independent. In other words, CPAN's taxonomy doesn't separate classes from packages. I.e. in Java, a package represents a group of inter-related classes.
Back to Moose: Is the paradigm that what Java considers a package, Moose considers a class; and what Java considers a class, Moose considers a role? I'm sure I'm over-simplifying. But if this description is fundamentally accurate, then I'm inclined to express my reservations, however belatedly. Is Moose merely popular because everyone likes it?
-Jim
]]>In 2001, Arthur Andersen Business Consulting went out of business. And I lost the best job I ever had. Clearly Enron was a significant factor, but importantly, AABC ran out of money to fund their war with Andersen Consulting/Accenture. Almost immediately, I was contacted by a friend/colleague, Jeff: He was launching a startup and needed an IT Director. Essentially, my job was to develop the technology his company would resell.
My salary lasted as long as it took to set up a web server. Jeff was an instinctive entrepeneur. After receiving so many inquiries from web developers, he redefined his business model. He bought a nice suit, leased an expensive car, wiggled his way into the right offices, and got contracts to build websites. Then he resold those contracts and pocketed a 80-90% profit. In those days, a web developer was anyone who owned a copy of Dreamweaver. And everyone expected to become a millionaire: Web pages cost $50-$100 apiece. Revisions were similarly priced. Developers expected $25,000 to build out a retail website with 500 products. And revisions usually doubled the quoted contract. After a couple years, the business model was becoming unsustainable.
There were already lots of database backed CMS's, I'd homebrewed one myself. The economy was shit, I had a sick kid, and I managed to convince Jeff to rehire me and put me in charge of production. Afterwards, designers only got paid for designing (crazy huh?) instead of charging $60-$80 per hour for cutting and pasting content. But the resulting collaboration platform had to accomodate quite bit of hostility.
A few years after this startup failed trying to float too many juggling balls, I came accross the term MVC, and it immediately resonated- because I understood the challenge of a collaboration between designers (now called UI specialists), content aggregators, and programmers, each satisfying perfectly arbitrary requirements. Morever, the nature of the web-interface product sets very high expectations for malleability. In practice, a change request should only go to one of the 3 teams without affecting the other two.
I rolled my solution out 8 years ago, and still host a dozen or so legacy implementations.
Now I'm basically out of the website business. But as time allows, I'm applying new technologies to accomodate this fundamental objective that still seems relevant.
Am I the only skeptic? Any solution can be arbitrarily defined in terms of three haphazardly assigned designations- a fact not lost on marketers and hypesters. I'd prefer to convince potential employers that MVC is an objective and philosophy that needs to be applied in practice, not just a bullet point on a spec sheet.
Any other thoughts?
So far, the local response has been positive. As long as I don't step on any toes here. In so many ways, Perl and Detroit are the best of all possible worlds.
]]>