Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Locked thread
Mario Incandenza
Aug 24, 2000

Tell me, small fry, have you ever heard of the golden Triumph Forks?
Classes and method names can be strings or subrefs, you don't need to result to ugly poo poo like eval or disabling strict.

code:
sub callMethod {
  my ($self) = @_;

  # instance method
  my $method = "method";
  my $result1 = $self->$method;

  # class method
  my $class = ref($self);
  my $result2 = $class->$method;

  # You can also...
  my $sub1 = sub { "hay $_[0]" };
  my $sub2 = \&method2;

  my $hay = $self->$sub1;
  my $itsa = $self->$sub2;
}

sub method2 {
  "it's a $_[0]";
}

Adbot
ADBOT LOVES YOU

Mario Incandenza
Aug 24, 2000

Tell me, small fry, have you ever heard of the golden Triumph Forks?
I've found CGI::Application is a good midway point between CGI.pm and Catalyst. Plus the tools like CAP::ValidateRM and CAP::FillInForm make easy work of boring, important things like input validation. It's even super easy to AJAXify the application if you bolt in CGI::Ajax or use a toolkit like Prototype or Ext.

Mario Incandenza
Aug 24, 2000

Tell me, small fry, have you ever heard of the golden Triumph Forks?
Yeah, sounds like you need to reinstall Net::SSLeay so that the XS components are properly linked.

Mario Incandenza
Aug 24, 2000

Tell me, small fry, have you ever heard of the golden Triumph Forks?
If you can read its output, try strace perl -c failing_script.pl and see where Perl is loading its libraries from (look for stat and open calls in particular). That will probably give you an idea of why it's failing, at the very least you can try blasting the mismatched versions and installing them again.

Mario Incandenza
Aug 24, 2000

Tell me, small fry, have you ever heard of the golden Triumph Forks?
It might also be a symbolic reference:

code:
> $foo = "bar";
> $var = "foo";
> print $$var;
bar
This is pretty horrible programming practice and shouldn't be used on a widespread basis, if at all.

Mario Incandenza
Aug 24, 2000

Tell me, small fry, have you ever heard of the golden Triumph Forks?
I have drunk deeply of the Catalyst + DBIx::Class koolaid and am looking forward to overhauling the 80,000 lines of garbage I get paid to nurse.

Mario Incandenza fucked around with this message at 14:27 on Feb 7, 2008

Mario Incandenza
Aug 24, 2000

Tell me, small fry, have you ever heard of the golden Triumph Forks?

Triple Tech posted:

Oh good, good you can tell me about how Catalyst works then. When I access a URL of a website that's running on Catalyst, what is the server actually hitting? Do all the URLs get submitted as an argument to a dispatcher, or are there individual .cgi files laying around?

I'd like to move my company's site to a framework but I'm not sure how this fancy stuff works.
Since it's based around fast-runtime at the expense of slow compilation, you're better off using Catalyst in conjunction with FastCGI or mod_perl - otherwise you'll be adding a second or two onto your response time. It ships with a HTTP::Server engine for use during development.

The controllers contain actions, which are just methods that have subroutine attributes defining the URLs they can handle. There's plenty of syntactic sugar for interacting with the models and views, and I'm really impressed with how easy it was to plug in authentication and other stuff, generally it was a simple case of installing a CPAN module and adding a couple of lines to the YAML config file.

jrockway's book is okay but it's really just an intro, you'll get just as much out of the POD as you will from the book (except for maybe the REST and Jemplate stuff which are pretty snazzy).

Here's a controller that handles AJAX-style logins:
code:
package MyApp::Controller::Login;
use base "Catalyst::Controller';

# matches http://dev.blah.com/login, optional trailing slash
sub login :Path {
  my ( $self, $c ) = @_;

  if ($c->user) {
    $c->res->redirect($c->uri_for('/home'));
  } else {
    $c->stash->{template} = 'login.tt2';
  }
}

# matches http://dev.blah.com/login/submit
sub submit :Local {
  my ($self, $c) = @_;

  my $q = $c->req->params;

  if ($c->login(@$q{qw/username password/})) {
    $c->stash->{success} = 1;
  }
  else {
    $c->stash->{success} = undef;
    $c->stash->{errors} = { username => 'bad login details.', password => 'bad login details.' };
  }

  $c->detach('View::JSON');
}

Mario Incandenza fucked around with this message at 04:01 on Feb 8, 2008

Mario Incandenza
Aug 24, 2000

Tell me, small fry, have you ever heard of the golden Triumph Forks?
COBOL programmers can write greate COBOL in any language :q:
code:
if ((( $SessionType == 1 && $LoginData{'AccountType'} eq "Pre-paid" &&
( ( ($LoginData{'Balance'} * 100) < ($VAR{'OrderPrice'} * 100) &&
$EnableModules{'Domains'} == 0 ||
( ($LoginData{'TestBalance'} * 100) < ($VAR{'OrderTotal'} * 100) &&
$EnableModules{'Domains'} == 1 ) ) )
 || ($SessionType == 3 && $VAR{'OrderTotal'} > 0)) && $ENV{'HTTPS'} ne "on" ) {
    $VAR{'s'} = "https://$ENV{'HTTP_HOST'}$LoginData{'SSLPort'}$ENV{'SCRIPT_NAME'}?SID=$FORM{'SID'}&Step=$FORM{'Step'}";
    $Page = $Pages[0];
}

Triple Tech posted:

Untested.

This works a bit better:

code:
# don't use tr to transform case
$data = lc($data);

...

my $i = 0;
while (1) {
  my ($double, $triple) = ($i + 1, $i + 2);

  $double < @words and push @doubles, [ @words[$i .. $double] ];
  $triple < @words and push @triples, [ @words[$i .. $triple] ];

  last if ++$i > @words;
}
It would be possible in one regex but you'd need to get pretty stoned first.

Mario Incandenza fucked around with this message at 05:32 on Feb 9, 2008

Mario Incandenza
Aug 24, 2000

Tell me, small fry, have you ever heard of the golden Triumph Forks?
I've found CDBI to be the slowest of the three major ORM packages (Class::DBI, DBIx::Class, Rose::DB::Object), and this benchmark seems to support that. RDBO may be the fastest but in the end I decided to stick with DBIC since it's the one most often used in conjunction with Catalyst and all the documentation reflects that, plus it was closer in usage to CDBI which I had previous experience with.

Mario Incandenza fucked around with this message at 00:03 on Apr 17, 2008

Mario Incandenza
Aug 24, 2000

Tell me, small fry, have you ever heard of the golden Triumph Forks?

Triple Tech posted:

Actually, there is a difference... And it's a terrible one. And I never use it. But in this particular scenario and use, you are correct.
code:
ABSTRACT: Balls considered harmful
Also, it's time to start using Vim macros so I can stop hand-typing:
code:
use 5.010;
use strict;
use warnings;

Mario Incandenza fucked around with this message at 15:33 on Apr 28, 2008

Mario Incandenza
Aug 24, 2000

Tell me, small fry, have you ever heard of the golden Triumph Forks?

Sartak posted:

In case anyone was curious: using & means the function call ignores the function's prototype, and passes in a plain list. As Triple Tech mentioned, it's pretty terrible.

Don't forget goto &subname - a magic goto useful mostly in AUTOLOAD subs, so you can replace the top frame of the call stack and cover your tracks.

Ninja Rope posted:

It's also useful when you want to make sure the parser knows you want to reference a function, like when using constants as hash keys:

Don't really like constant.pm... the lack of (easy) interpolation and all the edge-cases requiring &s or ()s make the cure worse than the disease.

Instead, why not:
code:
# create $PI as an immutable scalar
*PI = \3.141592;

# or
use Readonly;
Readonly my $PI => 3.141592;

Mario Incandenza fucked around with this message at 09:56 on Apr 29, 2008

Mario Incandenza
Aug 24, 2000

Tell me, small fry, have you ever heard of the golden Triumph Forks?

genericadmin posted:

Because that Readonly module is going to be really slow. The whole point of constant.pm is that the compiler will inline the data (because it is a sub) and creates no symbol table entry. It's more like a pre-processor constant the way C constants are. The syntax is retarded, I agree, but it's a very important module.
Yeah, I'm not debating any of that - I'm saying that 95% of the time I've seen it in use, it has not been inside scripts that need that level of performance. constant.pm shouldn't be the first choice for everyday code, not when using regular variables, made read-only in whatever method you choose, makes for a code base that's easier to read and easier to maintain. I don't like the special treatment they require when they could Just Be A Variable.

Mario Incandenza
Aug 24, 2000

Tell me, small fry, have you ever heard of the golden Triumph Forks?
The angle brackets read until they find $/, which is usually set to \n. Your best bet is to keep calling getc and passing it to ord() so you can see what the printer is returning (untested):
code:
# disable output buffering on STDOUT
use IO::Handle;
*STDOUT->autoflush;

while (1) {
  my $char = $socket->getc();
  printf '%s (%d) ', $char, ord($char);
}
That'll give you a better idea of how the printer answers queries and should point you in the right direction...

Mario Incandenza
Aug 24, 2000

Tell me, small fry, have you ever heard of the golden Triumph Forks?
Net::IMAP::Simple makes IMAP access really easy, if your mail server speaks it. To parse the emails once you've gotten them, install MIME::Tools, and then:

code:
use MIME::Parser;
my $parser = MIME::Parser->new;
my $email = $parser->parse_data($email_text);

for my $part ($email->parts) {
  my $filename = $part->head->recommended_filename;
  my $mime_type = $part->head->mime_type;

  do_something($filename, $mime_type, $part->bodyhandle->as_string)
  if wanted($filename) or interesting($mime_type);
}

Mario Incandenza fucked around with this message at 08:24 on May 24, 2008

Mario Incandenza
Aug 24, 2000

Tell me, small fry, have you ever heard of the golden Triumph Forks?
Wow, that looks awesome. Make sure you go see Adam Kennedy, his talks at YAPC::AU are entertaining and informative.

Mario Incandenza
Aug 24, 2000

Tell me, small fry, have you ever heard of the golden Triumph Forks?

LightI3ulb posted:

I'm really confused as to why my script keeps giving me the errors
Replace your C-style for-loop with until ($counter++ == 1) or something like that. Move my $sth0 and the rest of the $sth handles into the loop's scope. Replace undef in your DBI->connect line with {RaiseErrors => 1}. Inspect all the return values from ->execute calls, keeping in mind DBI may return '0E0' which is true in a boolean context but zero when evaluated numerically. A result with zero rows shouldn't cause DBI to complain about a missing execute statement, but whatever.

Also, use placeholders: my $rows = $dbh->prepare("INSERT INTO foo (bar) VALUES (?)")->execute("this replaces the question mark");

Mario Incandenza
Aug 24, 2000

Tell me, small fry, have you ever heard of the golden Triumph Forks?
This doesn't work?
code:
$self->run_modes({
  start => \&start,
  lol => 'hey',
})

Mario Incandenza
Aug 24, 2000

Tell me, small fry, have you ever heard of the golden Triumph Forks?
Thanks to strict.pm's 33% stacking combo against skeletons you're better off loading it first, then warnings. But hey, whatever works for you.

In the meantime the horrible code I'm paid to stop spontaneously combusting all the time is driving me insane, how do you guys mentally cope when dealing with really bad code all day, every day?

Mario Incandenza fucked around with this message at 15:14 on Jul 23, 2008

Mario Incandenza
Aug 24, 2000

Tell me, small fry, have you ever heard of the golden Triumph Forks?
perl -w enables warnings globally, which you might not want. use warnings is lexical, and only affects the current file/sub/block.

Mario Incandenza
Aug 24, 2000

Tell me, small fry, have you ever heard of the golden Triumph Forks?

Sartak posted:

I'll of course answer any Moose questions you guys have (and if I can't, I'll forward them to the guy who started the project).

Want to see more code? Should I explain a MooseX module? I could rewrite a CPAN module using Moose to see just how much less code is required.
I've used it for a few small things, seriously considering it for a large overhaul. I'm familiar with the basics (classes/roles/method modifiers etc), what useful stuff in Moose/MooseX:: wouldn't be immediately obvious from the docs/CPAN? I imagine piecing it together with Catamoose and DBIC would be rewarding.

Triple Tech posted:

I like things stock and low inertia... Even the syntax is not familiar looking.
But the syntax is just regular Perl...

Mario Incandenza
Aug 24, 2000

Tell me, small fry, have you ever heard of the golden Triumph Forks?
Intriguing. I like what I see in t/002_basic_array.t!

Mario Incandenza
Aug 24, 2000

Tell me, small fry, have you ever heard of the golden Triumph Forks?
Well, you could swap to HTML::Template::Plugin::Dot, which fakes up TT-style syntax and lets you write stuff like:
code:
<tmpl_loop rows>
  <a href="<tmpl_var this.url>"><tmpl_var this.name></a>
</tmpl_loop>
So you just pass in a arbitrarily nested structure (this can be a hashref or a fully fledged object) and walk through it from inside the template. Of course, at this point, you might as well consider swapping to TT.

Mario Incandenza
Aug 24, 2000

Tell me, small fry, have you ever heard of the golden Triumph Forks?
A naive implementation for your example:
code:
sub get_opts {
  my ($key, %opts);
  while (my $arg = shift @ARGV) {
    $arg =~ /^-/ and $key = $arg and $opts{$key} ||= [];
    $key and $arg !~ /^-/ and push @{ $opts{$key} }, $arg;
  }

  return \%opts;
}

Mario Incandenza
Aug 24, 2000

Tell me, small fry, have you ever heard of the golden Triumph Forks?
Yeah, they're LIFO:
code:
[matt@potato perl] for m in Foo Bar Baz; do echo -e "package $m; BEGIN { warn qq{BEGIN $m} }; END { warn qq{END $m} }; 1" > $m.pm; done
[matt@potato perl] perl -MFoo -MBar -MBaz -e '1'
BEGIN Foo at Foo.pm line 1.
BEGIN Bar at Bar.pm line 1.
BEGIN Baz at Baz.pm line 1.
END Baz at Baz.pm line 1.
END Bar at Bar.pm line 1.
END Foo at Foo.pm line 1.
END blocks are useful when aggregating the results of perl -ne (contrived example):
code:
$ ps auxww | perl -ne '$found{$_}++ if /wanted/; END { print for keys %found }'

Mario Incandenza
Aug 24, 2000

Tell me, small fry, have you ever heard of the golden Triumph Forks?

yaoi prophet posted:

Just an obscure word of warning (since this somewhat unlikely to crop up for most people) but man did it ruin my day once: "list context" can crop up when you aren't always thinking about it, and due to perl flattening lists when you're not looking this can have interesting results.

[...]

So, just be careful with wantarray.
Agreed. In my opinion, contexts in Perl are too implicit to modify the behaviour of a function - a more explicit method should be used (like parameters). To be honest I can't really see any reasonable use for wantarray().

Update: Actually, I can see how checking for void context would be useful. List-vs-scalar is still too messy though.

Mario Incandenza fucked around with this message at 08:38 on Aug 27, 2008

Mario Incandenza
Aug 24, 2000

Tell me, small fry, have you ever heard of the golden Triumph Forks?

heeen posted:

code:
sub getStuff()
{
my @foo;
.
.
.
return wantarray? @foo : \@foo;
}
Yes, I'm saying it's cleaner to always return an arrayref and deref it yourself if needed, so that you don't get bitten by list flattening with assigning to a hash. @$arrayref isn't that big a deal.
code:
return generateHugeListOf10_000_000elements() if wantarray;
return $numberof10_000_000elements;
If you're returning a 10 million element list as an actual list you have greater problems than wantarray.

Triple Tech posted:

My objective is to have a module consume this handle without knowing where it comes from. Also, without manually typing out an if-else branch.
I don't think it's a valid use. As Sartak recommended, make a dbh method, and that way if you pass in a full class name you don't need symbolic references, as Perl's OO system will happily accept strings.
code:
my $class = "Company::Database::Smoke";
my $dbh = $class->dbh;

# or even
my $method = "get_dbh";
my $dbh2 = $class->$method;

Mario Incandenza
Aug 24, 2000

Tell me, small fry, have you ever heard of the golden Triumph Forks?
You can subclass ResultSets too. This allows me to call $db->rs('domains.domain_names')->search_by_domain('foo.com') and still use indexes/joins properly.

It's nice to encapsulate larger, reusable queries into one callable name, instead of copy and pasting the same SQL query in 13 different files :(

code:
package DBIx::domains::ResultSet::domain_names;
use base 'DBIx::Class::ResultSet';

sub search_by_domain {
  my ( $self, $domain ) = @_;

  my ($domain_name, @extension) = split /[.]/ => $domain;
  my $extension = "." . join('.' => @extension);

  my $constraint = {
    domainname  => $domain_name,
    extension   => $extension,
  };

  my $options = {
    join => [qw/extension/],
  };

  return $self->search( $constraint, $options );
}

Mario Incandenza fucked around with this message at 11:28 on Sep 9, 2008

Mario Incandenza
Aug 24, 2000

Tell me, small fry, have you ever heard of the golden Triumph Forks?
Are you putting them inside your DBIC Schema, (e.g. MyDB/Schema/Table.pm), or MyApp/Model/MyDB/Table.pm? The model is just a wrapper around the schema, you'll need to place your custom methods in the schema if you want to reuse them properly outside of Catalyst.

Mario Incandenza
Aug 24, 2000

Tell me, small fry, have you ever heard of the golden Triumph Forks?
Yup, that works just fine, in fact I believe that's the recommended place, as it sits nicely alongside your relationship definitions (you mean resultset_class('Game::DB::ResultSet::Table'), yeah?).

Also, I know it's in the docs, but it's useful enough to bear repeating... if you ever need a plain hashref, you can do this (though keep in mind the keys still will be lowercased):

code:
my $rs = MyDB::Schema::Database->resultset('Table');
my $inflator = 'DBIx::ResultClass::HashRefInflator';

eval "require $inflator";
$rs->result_class($inflator);

while (my $hashref = $rs->next) {
}

Mario Incandenza
Aug 24, 2000

Tell me, small fry, have you ever heard of the golden Triumph Forks?
Inflation happens at the very end of the process, so as long as you define your join conditions by chaining calls to the resultset (as opposed to calling relations like $row->relation), your choice of inflator shouldn't impact the data you get back - just the form you receive it in.

The HashRefInflator doesn't do much more than pass through a hashref after fiddling with its values a little - ordinarily it will be blessed into DBIx::Class::Row and packed inside an object's private _column_data attribute. The class is really small, just two subs.

Mario Incandenza fucked around with this message at 10:50 on Sep 11, 2008

Mario Incandenza
Aug 24, 2000

Tell me, small fry, have you ever heard of the golden Triumph Forks?

Puck42 posted:

I have, same thing happens.
It's related to how Apache::Registry caches its code, see here for more info. Asterisk's res_perl works similarly to mod_perl and exhibits the same behaviour. I'd make absolutely sure your modules are cleanly designed and contain no syntax errors or anything that may prevent correct parsing. If you delete a subroutine from a package's symbol table and then fail to replace it before calling it you should see similar errors:
code:
perl> sub foo { my $x = 2 * rand(1) }
perl> $hash = \%main::
perl> $hash->{foo}       
-> *main::foo;
perl> delete $hash->{foo}
-> *main::foo;
perl> foo()
-x> Undefined subroutine &main::foo called at (eval 94) line 1.                                                                                                                                                                                              

uG posted:

Then again maybe my idea is flawed to begin with, as ultimately I just want to get the Resources of all the nations that share a trade with x-nation.
Since you can't use a many-to-many relationship to perform a search, you just need to make a "left" and "right" column and join across them with something like this (untested):
code:
package Game::DB::Schema::Nations;

__PACKAGE__->belongs_to(
  trade_links => 'Game::DB::Schema::TradeLinks', [
   'foreign.left' => 'self.id',
   'foreign.right' => 'self.id',
  ],
);

package Game::DB::Schema::trade_links;

__PACKAGE__->belongs_to(
  nation => 'Game::DB::Schema::Nations', [
   'foreign.id' => 'self.left',
   'foreign.id' => 'self.right',
  ],
);

package main;
my $resource_rs = $nation->trade_links->search_related('nation')->search_related('resources');
And if you wanted to place a restriction at any point along the chain, just add a constraint like so:
code:
->search_related(resources => {
  price => \\'< 100',
  -or => [
    resource => 'corn',
    resource => 'bitches',
  ]
});

Mario Incandenza fucked around with this message at 17:33 on Sep 12, 2008

Mario Incandenza
Aug 24, 2000

Tell me, small fry, have you ever heard of the golden Triumph Forks?
I don't see what's wrong with providing hooks into the end of an iteration? Providing it's not abused.

Mario Incandenza
Aug 24, 2000

Tell me, small fry, have you ever heard of the golden Triumph Forks?
Depends on the error. If it doesn't require an exception then using it like a try/catch isn't too :wtf:. It'd would be a useful place to call rollback(), now I think about it, if you wanted to have one transaction per iteration.

Mario Incandenza fucked around with this message at 10:44 on Sep 26, 2008

Mario Incandenza
Aug 24, 2000

Tell me, small fry, have you ever heard of the golden Triumph Forks?
Method::Signatures looks promising. It relies on Devel::Declare, which seems to do some semi-evil poo poo that kerplodes the debugger; however it's still pretty cool to write this:

code:
method new ($class: %args) {
  bless {%args}, $class;
}

Mario Incandenza
Aug 24, 2000

Tell me, small fry, have you ever heard of the golden Triumph Forks?
Interesting talk. I didn't know Devel::DProf was so useless.

Eurgh, so I need to get Crypt::OpenPGP installed on a fresh Etch box but it looks like the module hasn't been touched for nearly 6 years and the test suite is blowing up like a motherfucker. In theory I should be able to drop in Crypt::GPG if I mock the interface, yes?

Mario Incandenza fucked around with this message at 08:46 on Oct 7, 2008

Mario Incandenza
Aug 24, 2000

Tell me, small fry, have you ever heard of the golden Triumph Forks?

TiMBuS posted:

Maybe you can get it running, someone left a rating on the module telling you how to make it work:
Turns out it was actually this bug. Digests come out differently so Crypt::RIPEMD160 apparently installed, but Crypt::OpenPGP's t/07-digest.t blew up. Math::Pari's author fixed it for 5.10 in March, so as long as you build Pari from source it's relatively pain-free (for now).

Mario Incandenza
Aug 24, 2000

Tell me, small fry, have you ever heard of the golden Triumph Forks?
If you can install Text::CSV_XS off CPAN (run su, then cpan Text::CSV_XS), it's fairly easy. I'm not sure about the $SD/$ST references so I've left them in there.
code:

use Text::CSV_XS;

if (my $filename = $fields{outputfile1}) { 
  my @output = ( @fields{@sortlist}, "$SD\|$ST\|" );
  append_line($filename, \@output);
  $msgtext .= join("\n", map { "$_ = $fields{$_}" } @sortlist);
}

sub append_line {
  my ($filename, $fields) = @_;

  my $csv = Text::CSV_XS->new({
    always_quote => 1,
    eol => "\r\n",
  });

  open my $filehandle, '>>', $filename or die "couldn't open $filename: $!";
  $csv->print($filehandle => $fields);
}

Mario Incandenza fucked around with this message at 01:17 on Oct 9, 2008

Mario Incandenza
Aug 24, 2000

Tell me, small fry, have you ever heard of the golden Triumph Forks?
It's possible, though only under Linux/Unix. According to this Perlmonks thread, Windows will exhibit the blocking you describe, so you must use a two-socket solution.

Mario Incandenza
Aug 24, 2000

Tell me, small fry, have you ever heard of the golden Triumph Forks?
If they can be convinced of a trip to OSDC, now is probably the best time to pay - the Aussie dollar has tanked in the last few months relative to the USD.

Adbot
ADBOT LOVES YOU

Mario Incandenza
Aug 24, 2000

Tell me, small fry, have you ever heard of the golden Triumph Forks?

quote:

map { s/\/[^\/]+$// }
This is kinda ugly. Use File::Basename, it's a core module and all:
code:
use File::Basename qw/dirname/;

map { dirname($_) }

  • Locked thread