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
Triple Tech
Jul 28, 2006

So what, are you quitting to join Homo Explosion?
Nevermind what I said. Low reading comprehension. :colbert:

Adbot
ADBOT LOVES YOU

Kidane
Dec 15, 2004

DANGER TO MANIFOLD
Yes! Awesome, I've got a beginner's perl book which devotes one paragraph to getopt::long and doesn't mention the configure option. So basically anything extra will cause ARGV to have an option set, yes yes yes, thank you v. much.

Erasmus Darwin
Mar 6, 2001

Kidane posted:

Yes! Awesome, I've got a beginner's perl book which devotes one paragraph to getopt::long and doesn't mention the configure option. So basically anything extra will cause ARGV to have an option set, yes yes yes, thank you v. much.

Try running "perldoc Getopt::Long" in your shell, and you should get way more than you ever wanted to know about Getopt::Long. It'll work for any installed module, and you can also look up built-in functions with "perldoc -f functioname". "perldoc perldoc" gives you documentation on perldoc itself.

ProvostZak
Dec 31, 2000

it's a huge step
Okay, I've been trying to get the code Triple Tech and Speed Frog suggested to work but I just cannot get my head around it. I guess the main problem is I'm not entirely sure what I'm doing with the code that works. This is what I understand of the code I have:

code:
$filename = "samplefile.txt";
open ( FILE, $filename) or die "Cannot open file: $!";

 while ( $data = <FILE> ) {
This opens the file and creates a loop in which each line of the file is fed into $data

code:
$data =~ tr/A-Z/a-z/;
This puts everything into lowercase, but can be replaced with $data = lc($data); for the same effect.

code:
@values = split(/\s/, $data);
This takes the contents of $data and breaks it on each space, and then feeds these pieces into an array.

code:
foreach $val (@values)
 {
       open (OUTFILE, '>>testfile.txt');
       print OUTFILE "$val\n";
       close (OUTFILE);
 }
This line takes each element in the array @values and tags it as $val, before feeding it into the new testfile. It pastes in each element followed by a break.

Then the code loops again back to the start of the 'while' function, starting on the next row in the samplefile.

Okay, so the code you guys suggested is kind of swamping me. This is me trying to understand what is going on.

code:
my $i = 0;
while (1) {
This creates a loop and $i, setting it to zero.

code:
my ($double, $triple) = ($i + 1, $i + 2);
This creates two variables: $double and $triple and sets them to 1 and 2 to start with.

code:
$double < @words and push @doubles, [ @words[$i .. $double] ];
$triple < @words and push @triples, [ @words[$i .. $triple] ];
This does… the important bit. I think it checks if $double is less than the number assigned to the last element in the array @words and if it is then it adds the contents of the square brackets (which are the values in the array that have been assigned those numbers) onto the end of @doubles. In the case of $triple it takes the total of three values between $i and $triple.

code:
last if ++$i > @words;
}
This kicks us out of the while loop if incrementing $i would mean we had run out of elements in our array @words. If not it just increments $i (I think…)

So I tried the following code:

code:
$filename = "sample of no carriage returns and no blank entries.txt";
open (FILE, $filename) or die "Cannot open file: $!";

 while ($data = <FILE>)

{

 @words = split(/\s/, $data);

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

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

 last if ++$i > @words;
 }

 foreach $val (@doubles)

  {
       open (OUTFILE, '>>test6splitfile.txt');
       print OUTFILE "$val\n";
       close (OUTFILE);
  }

}

 exit 0;
This gives me output like this:

ARRAY(0x8f602c)
ARRAY(0x8f6050)
ARRAY(0x8f6080)
ARRAY(0x8f60b0)
ARRAY(0x8f60e0)
ARRAY(0x8f6110)
ARRAY(0x8f6140)
Etc. etc. etc.

I'm at a loss :(

Triple Tech
Jul 28, 2006

So what, are you quitting to join Homo Explosion?

ProvostZak posted:

code:
foreach $val (@values)
 {
       open (OUTFILE, '>>testfile.txt');
       print OUTFILE "$val\n";
       close (OUTFILE);
 }

By the way, this is pretty terrible. One, you should always be using warnings and strict. Two, doing file operations PER element, that's crazy. You should just buffer everything into a data structure, and then at the end of your script, dump/render it to a file.

ProvostZak posted:

code:
$double < @words and push @doubles, [ @words[$i .. $double] ];
$triple < @words and push @triples, [ @words[$i .. $triple] ];
This does… the important bit. I think it checks if $double is less than the number assigned to the last element in the array @words and if it is then it adds the contents of the square brackets (which are the values in the array that have been assigned those numbers) onto the end of @doubles. In the case of $triple it takes the total of three values between $i and $triple.

Close. Arrays in scalar context evaluate is the length of the array. So when we say double is less than array, we mean are there at least two elements in the array. Or three. Actually, the base for double and triple are moving targets, but since the words array isn't being modified, it's effectively the same thing... "Are there two or three elements still remaining from our current point of interest?"

ProvostZak posted:

code:
last if ++$i > @words;
This kicks us out of the while loop if incrementing $i would mean we had run out of elements in our array @words. If not it just increments $i (I think…)

Eh this is pretty rough to understand. It would be better to say $i++ on one line, and last if $i > @words on another. The plus one-ness happens first as a side effect. Then, you read the expression. "Stop the loop if we've exceeded the length of the array."

ProvostZak posted:

code:
$double < @words and push @doubles, [ @words[$i .. $double] ];
...

This gives me output like this:

ARRAY(0x8f602c)
ARRAY(0x8f6050)
ARRAY(0x8f6080)
ARRAY(0x8f60b0)
ARRAY(0x8f60e0)
ARRAY(0x8f6110)
ARRAY(0x8f6140)
Etc. etc. etc.

I'm at a loss :(

I guess you didn't get to references yet. We were giving you each set of doubles as one unit. You know how arrays store stuff, like a group of many individual things? And when we talk about a set of doubles, you can think about it as two individual numbers, or one package of two numbers. What we did was give you the doubles as single packages each. So... You have to unpackage them, technically, dereference them.

code:
for my $values (@values) {
  # dereference the package and copy it into doubles
  my @doubles = @$values;
  print "@doubles";
}

ashgromnies
Jun 19, 2004
I've been using Catalyst for an app at work recently and I really like the regular expression matching for Controller routines...

code:
sub focus : Regex('^report/focus/([^/]*)/([^/]*)/?([^/]*)?$') {
so cool!

Filburt Shellbach
Nov 6, 2007

Apni tackat say tujay aaj mitta juu gaa!
Here's a good example of why I shouldn't be allowed near Perl's inner workings: autobox::Closure::Attributes

Other than being a neat trick, it is a concise example of how to use really powerful tools you don't see every day:
  • autobox to let you add methods to ordinary scalars (in this case, coderefs)
  • PadWalker to inspect and change the variables captured by a closure
  • AUTOLOAD to catch all method calls
Are there any languages that have anything like this?

ashgromnies
Jun 19, 2004

Sartak posted:

Here's a good example of why I shouldn't be allowed near Perl's inner workings: autobox::Closure::Attributes

Other than being a neat trick, it is a concise example of how to use really powerful tools you don't see every day:
  • autobox to let you add methods to ordinary scalars (in this case, coderefs)
  • PadWalker to inspect and change the variables captured by a closure
  • AUTOLOAD to catch all method calls
Are there any languages that have anything like this?

What the hell is a closure? I read your example and didn't understand WTF was going on and I'm most of my way through a CS degree.

<deleted user>

ashgromnies posted:

What the hell is a closure? I read your example and didn't understand WTF was going on and I'm most of my way through a CS degree.

A reference to a subroutine that carries scoped data.

code:
package main;
use strict;
my $a = sub { my $thing = 'blue'; };
sub test { print $_[0]() };
&test($a);
This will print 'blue', because $thing persists in the scope of the closure.

Very powerful and useful concept. :)

Also, regarding the "closure as object" concept, don't forget that you can bless function references.

Filburt Shellbach
Nov 6, 2007

Apni tackat say tujay aaj mitta juu gaa!

genericadmin posted:

code:
package main;
use strict;
my $a = sub { my $thing = 'blue'; };
sub test { print $_[0]() };
&test($a);
This will print 'blue', because $thing persists in the scope of the closure.

It's even more than that. To have a closure, the variable has to be defined outside of the function. In CSey words, it needs to be a "free variable" in the scope of the function.

code:
package main;
use strict;

my $a = do {
    my $thing = 'blue';
    sub { "I am colored $thing" };
};
sub test { print $_[0]() };
&test($a);
This will print "I am colored blue". The sub "captures" the variable $thing. What autobox-Closure-Attributes does is let you get and set $thing directly.

code:
use autobox::Closure::Attributes;

print $a->thing; # "blue"
$a->thing("green");
print $a->thing; # "green"

test($a); # I am colored green

<deleted user>

Sartak posted:

It's even more than that. To have a closure, the variable has to be defined outside of the function. In CSey words, it needs to be a "free variable" in the scope of the function.

Interesting, I'd not realized a closure differed from an anonymous sub based on it encapsulating data from a higher scope.

quote:

code:
use autobox::Closure::Attributes;

print $a->thing; # "blue"
$a->thing("green");
print $a->thing; # "green"

test($a); # I am colored green

I'm curious why you chose to incur the overhead of AUTOLOAD and bring in PadWalker to accomplish this. Why not use a hash reference? If you really want accessors, you could define a simple object, or even bless the hash into Class::Accessor::Fast and attach some.

Filburt Shellbach
Nov 6, 2007

Apni tackat say tujay aaj mitta juu gaa!

genericadmin posted:

Interesting, I'd not realized a closure differed from an anonymous sub based on it encapsulating data from a higher scope.

Yep, that's what makes them so powerful. Take this example. Each instance of the function returned by create_counter gets its own $count.

code:
sub create_counter {
    my $count = shift;
    return sub {
        return ++$count;
    };
}

my $from_3 = create_counter(3);
my $from_9 = create_counter(9);

print $from_3->(); # 4
print $from_9->(); # 10
print $from_3->(); # 5
$from_3 and $from_9 are both references to functions, so you can pass them in anywhere that expects a function. Where would this be useful? Suppose you're using a module that expects you to provide a callback. You could see exactly how it's being called.

How about some imaginary function (delete_with_callback) that invokes your callback for a list of files, and you return true for files you want to delete, and false for files you want to keep.

However, the function returns the count of files that were deleted, but not the filenames. And you want to tell the user what you deleted. Here's how I'd do it:

code:
my @deleted;
my $callback = sub {
    my $file = shift;
    if ($file =~ m{\.py$}) {
        push @deleted, $file;
        return 1;
    }
    return 0;
};

delete_with_callback($callback);
print @files ? "Deleted @files" : "No files deleted";

genericadmin posted:

I'm curious why you chose to incur the overhead of AUTOLOAD and bring in PadWalker to accomplish this. Why not use a hash reference?

Oh, I totally wouldn't use this for regular objects. It's more a proof of concept than anything. However, on the very very small chance you need to get/set a closure's variables directly, this may be less painful than using PadWalker directly. For debugging, perhaps.

Puck42
Oct 7, 2005

Anyone familiar with DBIx::Class here?

I'm still trying to figure out how it all works, but I'm having an issue using update_or_create.

Every time I run it, I get an invalid syntax error from MySQL.

code:
my $sth = $schema->resultset('Users')->update_or_create({
                                              'username' => $username,
                                              'fullname' => $fullname,
                                              'guid' => $guid
                                                        }, { key =>'users_guid' });
SQL statement being created by DBIx
code:
SELECT me.index, me.username, me.fullname, me.guid FROM users me WHERE \
             ( ( me.guid = ? ) ): '5D65F46C-997A-41F4-BBA4-15494BC57885'
UPDATE users SET fullname = ? WHERE ( index = ? ): 'John Doe', '45'
I do have guid set as a unique constraint in the database and in the module. The statement works perfectly when it inserts a new entry, but fails on an update.

Any ideas?

Puck42 fucked around with this message at 21:45 on Feb 28, 2008

<deleted user>

Puck42 posted:

code:
UPDATE users SET fullname = ? WHERE ( index = ? )

The word 'index' is a MySQL reserved word, so:

code:
UPDATE users SET fullname = ? WHERE ( [b]`index`[/b] = ? );
-- or --
UPDATE users SET fullname = ? WHERE ( [b]users.index[/b] = ? );
Better yet, don't use reserved words as column names in your schema.

Puck42
Oct 7, 2005

yeah... that was the problem.


I feel like an idiot now. No idea how I forgot all about that.

codewarrior
Jan 6, 2003
edit: nm

ashgromnies
Jun 19, 2004
I need some help with Catalyst exception handling.

I have some error checking in my model that causes a die() to raise. I need to catch that somewhere else and depending on the view they have selected, give a different error page.

That is, I have two views - JSON view for AJAX stuff and TT2 view for regular HTML. If it's HTML, sure, show the default error page for now, if view == JSON then put an error message in the JSON output so it doesn't break their browser.


Here's my Root controller's end method:

code:
sub end : ActionClass('RenderView') {
    my ($self, $c) = @_;

    $c->log->debug("IN END METHOD");

    if ($c->req->param('output') && $c->req->param('output') eq 'json'){ # they requested JSON out
        $c->forward( 'MyApp::View::JSON' );
    } else {
        $c->forward( 'MyApp::View::TT' ) # else use TT
        unless ( $c->res->body || !$c->stash->{template} ); # unless they force the body...
    }
}
and when the die occurs, the "IN END METHOD" comes up, but it doesn't perform the JSON output on error even if ?output=json is set. The JSON output works everywhere else except when an exception is raised from die().

Log output:

code:
[debug] IN END METHOD
[error] Caught exception in MyApp::Controller::MyController->perform_roll "ERROR::: my error message at /lib/MyApp/Model/MyModel.pm line 184."
[info] Request took 4.181835s (0.239/s)
.----------------------------------------------------------------+-----------.
| Action                                                         | Time      |
+----------------------------------------------------------------+-----------+
| /auto                                                          | 0.003481s |
| /promotions/perform_roll                                       | 4.119870s |
| /end                                                           | 0.004715s |
|  -> MyApp::View::JSON->process                                 | 0.000783s |
'----------------------------------------------------------------+-----------'
It looks like it is calling the JSON view but the client's browser receives back an HTML error page from the AJAX request.


Ideas?

Kidane
Dec 15, 2004

DANGER TO MANIFOLD
Essentially, I'm trying to match one array against another. Here is what I've got:

code:
foreach(@php_available_modules) {
    @already_installed = grep $_, @php_installed_modules;
    @available_to_install = grep(/[^$_/], @php_installed_modules);
}
The first grep works perfectly, however I don't know how to say "grep for $_ in @php_installed_modules and if you DON'T find it, add $_ to some array". In fact given the syntax of grep in perl I'm not sure it's possible... I would write a regular expression which interpolates $_ but I don't think I'm allowed to do that either. :confused:

Intermediate Perl states:

"While the grep is running, it shadows any existing value in $_, which is to say that grep borrows the use of this variable but puts the original value back when it's done."

My interpretation is that I needn't worry about copying $_ into an intermediate variable, but I will probably try that just in case.

Kidane fucked around with this message at 12:10 on Mar 7, 2008

magimix
Dec 31, 2003

MY FAT WAIFU!!! :love:
She's fetish efficient :3:

Nap Ghost

Kidane posted:

Essentially, I'm trying to match one array against another. Here is what I've got:

code:
foreach(@php_available_modules) {
    @already_installed = grep $_, @php_installed_modules;
    @available_to_install = grep(/[^$_/], @php_installed_modules);
}

I found your description of the problem a bit confusing to be honest. So, assuming I haven't entirely misunderstood you, might the following do what you want?

code:
my @installed;
my @available;
my %installed = map {$_ => 1} @php_installed_modules;
foreach my $module (@php_available_modules)
{
	exists $installed{$module} ? 
		push @installed, $module :
		push @available, $module;
}
So @installed contains those php_available_modules that are in php_installed_modules, and @available contains those php_available_modules that are not in php_installed_modules.

magimix fucked around with this message at 12:27 on Mar 7, 2008

Kidane
Dec 15, 2004

DANGER TO MANIFOLD

magimix posted:

I found your description of the problem a bit confusing to be honest. So, assuming I haven't entirely misunderstood you, might the following do what you want?

my @installed;
my @available;
my %installed = map {$_ => 1} @php_installed_modules;
foreach my $module (@php_available_modules)
{
exists $installed{$module} ?
push @installed, $module :
push @available, $module;
}

So @installed contains those php_available_modules that are in php_installed_modules, and @available contains those php_available_modules that are not in php_installed_modules.
Yes, that's exactly what I'm trying to do.

I considered using a hash but the sub started swelling up and I'd like to keep this portion of my code to as few lines as possible.

magimix
Dec 31, 2003

MY FAT WAIFU!!! :love:
She's fetish efficient :3:

Nap Ghost

Kidane posted:

Yes, that's exactly what I'm trying to do.

I considered using a hash but the sub started swelling up and I'd like to keep this portion of my code to as few lines as possible.

I'd say worry about the functional aspect of your code for now, rather than its line-count. I created a hash of php_installed_modules so that I could iterate through php_available_modules once only, and do a single hash-lookup for each element therein.

Your original code has you iterating though php_installed_modules twice for every element in php_available_modules.

Kidane
Dec 15, 2004

DANGER TO MANIFOLD

magimix posted:

I'd say worry about the functional aspect of your code for now, rather than its line-count. I created a hash of php_installed_modules so that I could iterate through php_available_modules once only, and do a single hash-lookup for each element therein.

Your original code has you iterating though php_installed_modules twice for every element in php_available_modules.
You're right, of course. I've never used map before so I was shying away from it. My original code (before I tried using grep) looked like this
code:
foreach (@php_available_modules) {
    my $avail = $_;
    $installed = 0;
        foreach(@php_installed_modules) {
            if ($avail eq $_) {
                $installed = 1;
            }
        }
        if (not $installed) {
            push(@available_to_install, $avail);
        }
        else {
            push(@already_installed, $avail);
        }
}
Which is very awkward (I've only been doing this for a couple months). Your code worked perfectly so I am going to look in to what map does and add it to my toolbox.

Thanks a lot for your quick response! :D

magimix
Dec 31, 2003

MY FAT WAIFU!!! :love:
She's fetish efficient :3:

Nap Ghost

Kidane posted:

You're right, of course. I've never used map before so I was shying away from it. My original code (before I tried using grep) looked like this
code:
foreach (@php_available_modules) {
    my $avail = $_;
    $installed = 0;
        foreach(@php_installed_modules) {
            if ($avail eq $_) {
                $installed = 1;
            }
        }
        if (not $installed) {
            push(@available_to_install, $avail);
        }
        else {
            push(@already_installed, $avail);
        }
}
Which is very awkward (I've only been doing this for a couple months). Your code worked perfectly so I am going to look in to what map does and add it to my toolbox.

Thanks a lot for your quick response! :D


I'm still got a nagging doubt that I'm missing something. Anyway, would the following also do what you want?

code:
my %installed = map {$_ => 1} @php_installed_modules;
my @available = grep {!exists $installed{$_}} @php_available_modules;
In my test code, this produces the same @available as my previous code does. This is predicated around the fact that in the previous code @installed always had a one to one correlation with @php_installed_modules, so there was no sense duplicating that data. It also depends on the set of installed modules always being a subset of the available modules.

Kidane
Dec 15, 2004

DANGER TO MANIFOLD

magimix posted:

I'm still got a nagging doubt that I'm missing something. Anyway, would the following also do what you want?

code:
my %installed = map {$_ => 1} @php_installed_modules;
my @available = grep {!exists $installed{$_}} @php_available_modules;
In my test code, this produces the same @available as my previous code does. This is predicated around the fact that in the previous code @installed always had a one to one correlation with @php_installed_modules, so there was no sense duplicating that data. It also depends on the set of installed modules always being a subset of the available modules.
Ah, ok. This is part of the data I'm working with:

PHP modules already installed (from php -m):

code:
bcmath
bz2
calendar
ctype
curl
date
dbase
dom
exif
filter
ftp
gd
gettext
gmp
hash
iconv
imap
ionCube Loader
json
ldap
And these are the modules offered in the PHP source code:

code:
bcmath
calendar
dotnet
ctype
curl
date
dba
dbase
dom
exif
fbsql
fdf
filter
ftp
gd
gettext
gmp
hash
iconv
imap
interbase
json
ldap
I'm setting up a script to automate, for our users, a way to easily install PHP modules which we did not include on their server but can be easily compiled as module from the existing source. So I want to make sure they can only install modules which are already contained in the source, but aren't already installed. Pretty basic stuff.

Kidane fucked around with this message at 12:55 on Mar 7, 2008

<deleted user>

ashgromnies posted:

I need some help with Catalyst exception handling.
It looks like it is calling the JSON view but the client's browser receives back an HTML error page from the AJAX request.


Ideas?

Catalyst's error handling is horrible. Remember that if you are in a controller dispatch, exceptions get wrapped to Catalyst errors (which I absolutely hate).

By default Catalyst will check $c->error at the end of a request and show its goofy error page. To override the default error handler, you need to check $c->error yourself (usually in MyApp::end()).

code:
sub end {
   my ($self, $c) = @_;
   ...
   if(($c->req->header('X-Requested-With') || '') eq 'XMLHttpRequest') {
      # select a json view
   }
   
   if( scalar(@{$c->error}) ) {
      ...
      # handle the error however you'd like
      MyApp::View->set_error(...);
      ...
      # then, clear the errors so Catalyst won't handle them
      $c->{error} = [];
   }
}

ashgromnies
Jun 19, 2004

genericadmin posted:

By default Catalyst will check $c->error at the end of a request and show its goofy error page. To override the default error handler, you need to check $c->error yourself (usually in MyApp::end()).

I ended up throwing an eval{ }; around the call and got it working with my custom error handling.


Okay, another Catalyst question...


I have a method triggered that runs in the background(I enabled multi-threading on my Catalyst app) that takes a little bit of time to perform and has multiple actions it performs. I would like to inform the user of the current status of this method.


Here's the code that I have...

code:
    my $callback = sub {
        warn "logging status ".$_[0];
        $c->session->{'roll_status'} = $_[0];
    };

    if (eval { $somemodel->perform_action($params,
      $callback) }) {
        # action performed successfully
        $c->stash->{'json_status'} = SUCCESS;

    } else {
        # action failed
        $c->log->debug("error occured during perform_action");
        $c->stash->{'json_status'} = $@;
    }
$repo is a model object... then in perform_action, it looks something like this...

code:
sub perform_action {
    my $self = shift;
    my ($params, $status_callback) = @_;

    # some work is done here that takes a few seconds
    $status_callback('doing step 1');

    # other stuff that takes a few seconds
    $status_callback('doing step 2');

    # more more more stuff that takes a few seconds
    $status_callback('doing step 3');

    # last bit of work done...
    $status_callback('Done!');

    return 1;
}
So when I watch my logs, I see...

code:
logging status doing step 1
logging status doing step 2
logging status doing step 3
logging status Done!
occur one after another every few seconds as the code runs, as I would expect.

So then I have this method to check the status...

code:
sub get_roll_status : Regexp('^([^\/]+)\/get_roll_status$') {
    my $self = shift;
    my ($c) = @_;


    $c->stash->{'json_roll_status'} = $c->session->{'roll_status'};
    $c->stash->{'template'} = 'rolltool/roll_status.tt2';
}
and it ALWAYS returns "Done!" no matter what step is currently underway. From what I can tell, Catalyst waits to set the session variables until the entire request is complete, then does them all at once. The same behavior is exhibited if, instead of warn I use $c->log->debug(); statements... nothing appears while the work is being done, then once it is done it prints out all the statuses at once.


What would you do to get around this? I could write the status to a file locally and read from that but that seems to go against the Catalyst-way.

<deleted user>
What are you accomplishing by using threads? It seems like a job queue might be a better fit for what you are trying to do. Have the worker update the job status as it processes it, then just let your Catalyst action query the job status. This has the benefit of being asynchronous.

Also, in this statement:

code:
if (eval { $somemodel->perform_action($params, $callback) } ) {}
If you are going to catch exceptions, you may as well treat them as such:

code:
eval {
  $somemodel->perform_action($params, $callback)
  $c->stash->{'json_status'} = SUCCESS;
}

if($@) {
   $c->log->debug("error occured during perform_action: $@");
   $c->stash->{'json_status'} = ERROR;  # better than using a string
   $c->stash->{'error_msg'} = $@;
}

ashgromnies
Jun 19, 2004

genericadmin posted:

What are you accomplishing by using threads? It seems like a job queue might be a better fit for what you are trying to do. Have the worker update the job status as it processes it, then just let your Catalyst action query the job status. This has the benefit of being asynchronous.

We can't have a JobQueue because multiple people are allowed to trigger this action to happen at once and that is perfectly fine and expected. With a JobQueue, it is feasible that things might get out of order and new data could be stamped on with old data - the way it's set up now, it will throw an error if multiple people trigger actions that step on eachother, which is intended.

So I need to find a way of doing this without a slow Queue. It needs to allow multiple requests from different people at once...

ashgromnies
Jun 19, 2004
So no one knows how to get around the fact that Catalyst writes out session variables at the end of the request? I tried using a Cache, that didn't work either :(

<deleted user>

ashgromnies posted:

So no one knows how to get around the fact that Catalyst writes out session variables at the end of the request? I tried using a Cache, that didn't work either :(

Sessions are implemented as plugins (last I had seen anyway), so you are bound by the plugin implementation and the various Catalyst phases.

The intent of a "session" is to preserve state between HTTP messages, not within one request, so it should not be an issue when the session state is committed. I suspect you may be using the wrong tool for the job, but to be honest I'm not sure I'm correctly discerning exactly what you are wanting to do (maybe that's why others are not responding).

Adding threading to an application greatly affects how MVC should be applied.

ashgromnies
Jun 19, 2004

genericadmin posted:

Sessions are implemented as plugins (last I had seen anyway), so you are bound by the plugin implementation and the various Catalyst phases.

The intent of a "session" is to preserve state between HTTP messages, not within one request, so it should not be an issue when the session state is committed. I suspect you may be using the wrong tool for the job, but to be honest I'm not sure I'm correctly discerning exactly what you are wanting to do (maybe that's why others are not responding).

Adding threading to an application greatly affects how MVC should be applied.

For what it's worth, using Cache::FastMmap and $c->cache->get and set worked.

Kidane
Dec 15, 2004

DANGER TO MANIFOLD
Stupid question...

Is there a way to print to stdout without updating the cursor? For example if I wanted to display a percentage done indicator, or even just a spinning | to show that the program is thinking, is there a way to do this? My intuition tells me that it's not but I figured I might as well ask (Google was no help).

dagard
Mar 31, 2005

Kidane posted:

Stupid question...

Is there a way to print to stdout without updating the cursor? For example if I wanted to display a percentage done indicator, or even just a spinning | to show that the program is thinking, is there a way to do this? My intuition tells me that it's not but I figured I might as well ask (Google was no help).

This looks like what you want:
http://outflux.net/software/shorts/perl/Idle

Kidane
Dec 15, 2004

DANGER TO MANIFOLD

dagard posted:

This looks like what you want:
http://outflux.net/software/shorts/perl/Idle
Haha, of course, printing a carriage return will move the cursor back to the beginning of the line, why didn't I think of that? :doh:

Thanks!

syphon^2
Sep 22, 2004

dagard posted:

This looks like what you want:
http://outflux.net/software/shorts/perl/Idle
Hey that's really cool. How would one handle multiple-line "interactive" scripts then? The carriage return let's you re-draw the current line, but what if you need to re-draw the PREVIOUS line(s)?

Erasmus Darwin
Mar 6, 2001

syphon^2 posted:

Hey that's really cool. How would one handle multiple-line "interactive" scripts then? The carriage return let's you re-draw the current line, but what if you need to re-draw the PREVIOUS line(s)?

I think that's getting to the point where you need to start worrying about the terminal-specific means of moving the cursor around. (Or you can cheat and just hardcode the appropriate ANSI escape sequences, but that's bad.)

The low-level interface to the underlying terminal control sequences is handled by Term::Cap, which seems to be bundled with Perl:

http://www.perl.com/doc/manual/html/lib/Term/Cap.html

But you don't want to use that unless you're feeling adventurous and masochistic. It's a lot easier to use a nice wrapper like Term::Screen (which you'll have to grab off CPAN):

http://search.cpan.org/~jstowe/Term-Screen-1.03/Screen.pm

Term::Screen, Term::ReadKey, and Term::ANSIColor was enough for me to do an asteroid clone using ASCII characters. I can't remember why I skipped using Term::Screen's key handling code and instead went with Term::ReadKey.

Filburt Shellbach
Nov 6, 2007

Apni tackat say tujay aaj mitta juu gaa!
See also Curses, if (any of) you are interested in a "full-screen" terminal application like vim or NetHack.

ashgromnies
Jun 19, 2004
I'm trying to write a one liner to validate that all the *.yml files it finds can be properly parsed...

Here's what I came up with:

code:
find / -type f | grep ".yml" | xargs perl -e 'use YAML qw"LoadFile"; eval{ LoadFile("$_"); }; print "$_ : $@\n" if ($@);'
however it's not working.

It only gets two arguments, which I can check with:

code:
-bash-3.1$ find / -type f | grep ".yml" | xargs perl -e 'use YAML qw"LoadFile"; eval{ LoadFile("$_") if $_; }; print "$_ : $@\n";'
 :
 :
but that doesn't make sense. If I just run

code:
find / -type f | grep ".yml"
I get a huge list of files returned - what am I doing wrong?


edit: closer
code:
find / -type f | grep ".yml" | xargs perl -ne 'use YAML qw"LoadFile"; for(@ARGV){ eval{ LoadFile("$_"); }; print "$_ : $@\n" if ($@);}'
this one doesn't work, I get a lot of errors like:

code:
/path/to/._some_file_with_underscore_and_._.yml : YAML Error: Invalid characters in stream. This parser only supports printable ASCII
   Code: YAML_PARSE_ERR_BAD_CHARS
   Line: 0
   Document: 0
 at /opt/ActivePerl-5.8/site/lib/YAML.pm line 33
I'm pretty sure it's due to either the period or the underscore because files without those are parsing just fine.

perl one liners are fun but I write them like a regular script :(

ashgromnies fucked around with this message at 15:02 on Mar 14, 2008

<deleted user>
How about this?

code:
find . -regex '.*\.yml$' -type f -print0 |xargs -0 perl -mYAML -e 'eval { YAML::LoadFile($_); 1; } or warn "fail: $_\n\t$@" for(@ARGV);'

Adbot
ADBOT LOVES YOU

ashgromnies
Jun 19, 2004

genericadmin posted:

How about this?

code:
find . -regex '.*\.yml$' -type f -print0 |xargs -0 perl -mYAML -e 'eval { YAML::LoadFile($_); 1; } or warn "fail: $_\n\t$@" for(@ARGV);'

Awesome, thanks! How is it you know everything?

I went with this to exclude files that start with a "."... there were these "._.*.yml" files that seemed to be Mac OS X binary temp files that contained no valid YAML serialization:

code:
find / -regex '.*\/[^\.][^\/]*\.yml$' -type f -print0 |xargs -0 perl -mYAML -e 'eval { YAML::LoadFile($_); 1; } or warn "fail: $_\n\t$@" for(@ARGV);'

ashgromnies fucked around with this message at 20:19 on Mar 14, 2008

  • Locked thread