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
uG
Apr 23, 2003

by Ralp

xobofni posted:

Here ya go.


Might add some more specific character set matching for the "number" and "filename," but not really necessary.
Wowzers! I'm afraid I made it seem a tad more complicated than it really is... what you posted is great, but folder/ doesnt need to be captured, just matched to see if its at the start of the string.

Valid
folder/(17)/(some text)/
folder/(17)/(some text)
folder/(34)/
folder/(34)
folder/

(parenthesis above not part of valid match syntax, but used to represent which values i want to capture)

Not Valid
anything not ^folder

I hope that makes sense haha. I tried to modify what you posted but im not picking up on regex very quickly :(

Adbot
ADBOT LOVES YOU

checkeredshawn
Jul 16, 2007

Does anyone know how I can get the name of an array passed to a subfunction? For example, if I have the subfunction foo, &foo(@somearray), can I get that subfunction to return the string "somearray"?

Triple Tech
Jul 28, 2006

So what, are you quitting to join Homo Explosion?
Why would you ever want to do that? It already sounds like a bad idea.

checkeredshawn
Jul 16, 2007

Triple Tech posted:

Why would you ever want to do that? It already sounds like a bad idea.

Well, this isn't why I want to do it, but imagine I'd like to do something like printing "[array name] has contents: [array contents]". Why I really want to do it has something to do with the GetOpt::Long, I'll explain in more detail later if you want.

German Joey
Dec 18, 2004

checkeredshawn posted:

Well, this isn't why I want to do it, but imagine I'd like to do something like printing "[array name] has contents: [array contents]". Why I really want to do it has something to do with the GetOpt::Long, I'll explain in more detail later if you want.

you should be able to do something like what you want with a combination of Padwalker (http://search.cpan.org/dist/PadWalker/PadWalker.pm) and caller. just promise me you won't do something retarded with this! padwalker and the B modules are the perl equivalent of nuclear weapons. watch where you tread.

German Joey
Dec 18, 2004

German Joey posted:

you should be able to do something like what you want with a combination of Padwalker (http://search.cpan.org/dist/PadWalker/PadWalker.pm) and caller. just promise me you won't do something retarded with this! padwalker and the B modules are the perl equivalent of nuclear weapons. watch where you tread.

actually, looks like there's a new module that does EXACTLY what you want already called Devel::Caller (http://search.cpan.org/~rclamp/Devel-Caller-2.03/lib/Devel/Caller.pm) that uses Padwalker. how convenient. also, Padwalker has a new function called closed_over since i last saw it and i think those chumps borrowed from code that i wrote without giving me credit!!

Filburt Shellbach
Nov 6, 2007

Apni tackat say tujay aaj mitta juu gaa!
PadWalker is an excellent piece of software. My only complaint is that you can't add new variables to a pad with it, you can only read or update.

Oh the evil I could do..

Anaconda Rifle
Mar 23, 2007

Yam Slacker

uG posted:

Wowzers! I'm afraid I made it seem a tad more complicated than it really is... what you posted is great, but folder/ doesnt need to be captured, just matched to see if its at the start of the string.

Valid
folder/(17)/(some text)/
folder/(17)/(some text)
folder/(34)/
folder/(34)
folder/

(parenthesis above not part of valid match syntax, but used to represent which values i want to capture)

Not Valid
anything not ^folder

I hope that makes sense haha. I tried to modify what you posted but im not picking up on regex very quickly :(

Edit: never mind. My regex had all sort of problems. m!^folder/([^/]*)/?(?<=/)([^/]*)/?$!

Try a modified one from xobofni:
/^folder\/([^\/]*)[\/]*([^/]*)\/?$/ if you don't want the leading slash and
/^\/folder\/([^\/]*)[\/]*([^/]*)\/?$/ if you do.

Anaconda Rifle fucked around with this message at 16:00 on Aug 1, 2008

Filburt Shellbach
Nov 6, 2007

Apni tackat say tujay aaj mitta juu gaa!
Any Moose users in the crowd? Just curious! (disclosure: I'm on the devteam)

In case you haven't heard of it: it's a really nice way to do OO. Moose itself is very declarative. For example:

code:
package Forum::User;
use Moose; # also turns on strict and warnings for you

# "has" creates a new attribute
has post_count => (
    # the attribute is read/write, so we get a r/w accessor:
    # $self->post_count and $self->post_count($new_count)
    is => 'rw',

    # isa sets up a type constraint. post_count must be an integer
    isa => 'Int',

    # every user starts with 0 posts
    # (though we could create a user who starts with more)
    default => 0,
);

has regtime => (
    # read-only, so $self->regtime($today) throws an error
    # (SA's 9-11 regdate upgrade could still work, just not through this accessor)
    is => 'ro',

    # classes are type constraints too
    isa => 'DateTime',

    # default values can be arbitrarily complex
    default => sub { DateTime->now },

    # delegation: make a regdate method that calls $self->regtime->ymd
    handles => {
       regdate => 'ymd',
    },
);

# "post" method is up to your imagination
sub post { ... }

# "after" method modifiers are run after the original method is done
after post => sub {
    my $self = shift;

    # this could be written more concisely with MooseX::AttributeHelpers
    $self->post_count($self->post_count + 1);
};
Give it a try! I bet you'll like it, especially if you're using something like Class::Accessor already.

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.

Ninja Rope
Oct 22, 2005

Wee.
How does using Moose affect performance (eg, run speed, memory usage)?

Filburt Shellbach
Nov 6, 2007

Apni tackat say tujay aaj mitta juu gaa!
Moose's major performance hit is in startup speed. Moose has to instantiate objects for all of your classes, attributes, methods, etc. We're always working on improving that; it is much better than it used to be. There's also a MooseX-Compile project that aims to perform this compilation only once, and after that load your classes from a Storable blob on disk. I should probably lend a hand to this project. I'd really like to see it get off the ground.

There's also a runtime cost. Using "make_immutable" (described in the docs for Moose.pm) will eliminate a lot of the cost. make_immutable memoizes some meta-level methods and inlines others.

I don't know about memory usage, because I've never cared about that. (I should)

I personally think Moose is worth all of these costs.

Triple Tech
Jul 28, 2006

So what, are you quitting to join Homo Explosion?
Maybe I'm too scared of using things that are different. All this Fields, Class Std, and of course Moose stuff is way over my head. I guess I'm just really used to blessed hashes, even if they can't DO much.

I like things stock and low inertia... Even the syntax is not familiar looking.

S133460
Mar 17, 2008
hello

Sartak posted:

Any Moose users in the crowd? Just curious! (disclosure: I'm on the devteam)

Nice work! I'm a big fan of Moose. We nearly used it for a lot of SA code, but our anti-dependency-ism won out. :(

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...

Triple Tech
Jul 28, 2006

So what, are you quitting to join Homo Explosion?
"SA stuff"? Who are you?

It's not "just regular Perl". It's trying to make has look like a regular keyword. I'm not even sure how it does that. :psyduck: (I wanted to say prototypes but on a shallow glance I can't seem to find where it implements it)

Regular Perl would a constructor named new that returns a blessed hash and has a bunch of subroutines attached to it.

Filburt Shellbach
Nov 6, 2007

Apni tackat say tujay aaj mitta juu gaa!

SpeedFrog posted:

what useful stuff in Moose/MooseX:: wouldn't be immediately obvious from the docs/CPAN?

Check out MooseX::AttributeHelpers.

You have an array attribute. But if you want to push elements onto it, you have to write something like this:

code:
sub add_rules {
    my $self = shift;
    my @rules = @_;

    push @{ $self->rules }, @rules;
}
But then @rules won't be type checked. MooseX::AttributeHelpers lets you write the following, which will have new rules be type-checked. It provides a bunch of helper methods for Perl's builtin types.

code:
has rules => (
    [b]metaclass => 'Collection::Array',[/b]
    is => 'ro',
    isa => 'ArrayRef[MyRule]',
    default => sub { [] },
    [b]provides => {
        push => 'add_rules',
    },[/b]
);

Triple Tech posted:

It's not "just regular Perl". It's trying to make has look like a regular keyword. I'm not even sure how it does that. :psyduck: (I wanted to say prototypes but on a shallow glance I can't seem to find where it implements it)

Here's what has looks like:
code:
sub has {
    my $name = shift;
    my %args = @_;
    ...
}
There's no magic or prototype. The parentheses are not required and => is a "fat" comma that quotes the word to its left. You can use this syntax anywhere.

edit: It's implemented in Moose.pm. The first instance of the word has is defining the keyword. It's only a little more complicated than what I've got, because you can pass in an array reference of names to define a bunch of attributes with the same options at once. We have a prototype, but it's only so passing in an odd number of arguments will explode sooner rather than later.

quote:

Regular Perl would a constructor named new that returns a blessed hash and has a bunch of subroutines attached to it.

Like Moose, you mean? :) Moose does use blessed hashrefs. Your class inherits "new" from Moose::Object. You still define methods as subroutines in a package.

Filburt Shellbach fucked around with this message at 16:49 on Aug 4, 2008

Triple Tech
Jul 28, 2006

So what, are you quitting to join Homo Explosion?
I thought all user defined subroutines required parenthesis. Am I mistaken? I guess it sounds like it but I don't know why I would think this unless I ran into a case where this was a problem.

S133460
Mar 17, 2008
hello

Triple Tech posted:

I thought all user defined subroutines required parenthesis. Am I mistaken? I guess it sounds like it but I don't know why I would think this unless I ran into a case where this was a problem.

When you use Moose, it exports has into the caller's namespace. It's no different than using other modules. You can later call no Moose to have it clean up after itself a bit.

(edit: and calling user-defined subs does not require parentheses, although doing so is good practice [even for built-ins])

S133460 fucked around with this message at 17:26 on Aug 4, 2008

Triple Tech
Jul 28, 2006

So what, are you quitting to join Homo Explosion?
Using parenthesis for built-ins is not good practice. In fact, the PBP is to not use parenthesis for built-ins.

Subotai
Jan 24, 2004

Triple Tech posted:

Using parenthesis for built-ins is not good practice. In fact, the PBP is to not use parenthesis for built-ins.

Where are you getting this??

Filburt Shellbach
Nov 6, 2007

Apni tackat say tujay aaj mitta juu gaa!

Subotai posted:

Where are you getting this??

I assume Perl Best Practices:

PBP p 13 posted:

Don't use unnecessary parentheses for builtins and "honorary" builtins.

In my opinion it doesn't really matter. But there are some cases where you need use parentheses (to avoid indirect method call syntax :argh: ), though probably not for builtins.

Filburt Shellbach fucked around with this message at 18:09 on Aug 4, 2008

S133460
Mar 17, 2008
hello

Subotai posted:

Where are you getting this??

I think he is talking about the Damian Conway book?

I always parenthesize builtins, because it avoids precedence bugs. Here's an example:

code:
$ perl -e '$theta = 1; print(sin $theta / cos $theta, "\n");'
0.961050079349205
$ perl -e '$theta = 1; print(sin($theta) / cos($theta), "\n");'
1.5574077246549
$ perl -e 'use Math::Trig; $theta = 1; print(tan($theta), "\n");'
1.5574077246549
If not using parentheses on builtins is a good practice, I guess that's one I'll have to skip. ;)

Triple Tech
Jul 28, 2006

So what, are you quitting to join Homo Explosion?
Well it's getting rid of unneeded parenthesis. Of course you need them for some things. I just don't like reading this, ever:

code:
open(my($fh), shift(@ARGV)) or die("oh noes, gonna die");

Subotai
Jan 24, 2004

Yeah I have never heard of anyone saying you should never use them. You should listen to Randal Schwartz over Damian Conway any day. *shakes fist at Damian Conway*

Subotai
Jan 24, 2004

Triple Tech posted:

Well it's getting rid of unneeded parenthesis. Of course you need them for some things. I just don't like reading this, ever:

code:
open(my($fh), shift(@ARGV)) or die("oh noes, gonna die");


You should use them where it makes sense to. To say "never use them" is dumb.

I personally would write that as:
open(FILE, shift) or die "blah";

But to each his own.

Filburt Shellbach
Nov 6, 2007

Apni tackat say tujay aaj mitta juu gaa!

Subotai posted:

You should listen to Randal Schwartz over Damian Conway any day. *shakes fist at Damian Conway*

So why are you posting here and not in the Smalltalk thread? ;)

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!

uG
Apr 23, 2003

by Ralp
code:
sub nation {
my @nations = Modules::DB::Nation->search(owner => $self->session->param('uid'));
return $self->html_generate("view_nation.html", {NATIONS => \@nations});
}

...later in the template file view_nation.html

<!-- TMPL_IF NATIONS -->
    <!-- TMPL_LOOP NAME=NATIONS --> 	
    	<p>Nation id: <TMPL_VAR ID></p>
    <!-- /TMPL_LOOP -->	
<!-- TMPL_ELSE -->
In the code above, @nations is array of class::dbi objects.

Now usually in the code above I would use regular DBI, and interate through a selectrow_hashref putting them into an array (for an array of dbi hashrefs). I'd pass it as the second argument in the code below, which would then run a TMPL_LOOP NAME=NATIONS for each hashref in the array inside the template.

But now that i'm switching to class::dbi, I can't figure out how to populate the template params like I want. I seem to have a problem grasping what type of data im working with with perl usually :( Any ideas?

EDIT: I could just iterate through the objects and create an actual hash myself, but I was hoping there would be a more elegant way.

code:
sub html_generate {
  my $self = shift;
  my $page = shift;
  my $params = shift;
  my $template = $self->load_tmpl($page,die_on_bad_params=>0);

  if(defined $params) {
    $template->param(%{$params});
  }

  $template->param({
             MYURL  => $self->query->url,
             USER   => $self->authen->username,
             UID    => $self->session->param('uid'),
  });

  return $template->output();
}

uG fucked around with this message at 07:34 on Aug 5, 2008

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.

S133460
Mar 17, 2008
hello

uG posted:

But now that i'm switching to class::dbi, I can't figure out how to populate the template params like I want. I seem to have a problem grasping what type of data im working with with perl usually :( Any ideas?


You're working with an object. Class::DBI expects you to access data through accessor methods it provides, rather than directly as you would with an unblessed hash.

code:
# via selectrow_hashref()
$nation->{owner};

# via Class::DBI result
$nation->owner();
Like SpeedFrog said, you usually would expose the object to the template and use the object accessors in the template.

uG
Apr 23, 2003

by Ralp

SpeedFrog posted:

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.
I must have missed Dot! I had read up on HTDot, but that seemed to give the template designer too much control with the application.

checkeredshawn
Jul 16, 2007

I'm having a problem with parameters to subroutines. I know I'm not allowed to pass a hash to a subroutine, it must be a reference. I still can't seem to figure this out though. I've got a text file with multiple similar blocks of text like so:

field = "Architecture:"
alias = "arch"
description = "The kernel architecture"

And I want to extract alias and field into a hash, so that $hash{"arch"} is equal to "Architecture". I've got a subroutine that takes an array (a block of lines like above), and it should take a hash as well, and when it finds alias and field in the block of text, it adds it to the hash using $hash{$key} = $value; So the subroutine looks like this:

code:
sub getstuff { 
  my (@array, %config) = @_; 
  my ($field, $alias, $fieldstring, $aliasstring);
  foreach my $line (@array) { 
    chomp($line);
    if ($line =~ /^field/) {
      ($fieldstring, $field) = split /=/, $line;
    } 
    if ($line =~ /^alias/) {
      ($aliasstring, $alias) = split /=/, $line;
    } 
  } 
  $config{$alias} = $field;
} 
But because of the whole hash reference thing, it doesn't work. I've tried changing it to \%config as well, but I got an error with that too. Eventually there's another piece of code that looks like this:

code:
foreach my $arrayref (@blocks) {
  my @array = @$arrayref;
  &getstuff(@array, %config);
}
Where @blocks contains arrays of lines which are the different blocks of text that I previously separated. Any help is appreciated, thanks.

Edit: the %config passed to the subroutine getstuff is just a hash that is declared earlier in the code with "my %config;"

checkeredshawn fucked around with this message at 21:09 on Aug 5, 2008

Triple Tech
Jul 28, 2006

So what, are you quitting to join Homo Explosion?
Holy christ, where to begin. The array should be passed in as a reference as well. When you're cutting up @_, see where you try to see it to the array and the hash? The array is slurping that entire stack up and there's nothing left for the hash to have. You need to do something like

my $return = getstuff(\@given_array, \%given_config)

checkeredshawn
Jul 16, 2007

Triple Tech posted:

Holy christ, where to begin. The array should be passed in as a reference as well. When you're cutting up @_, see where you try to see it to the array and the hash? The array is slurping that entire stack up and there's nothing left for the hash to have. You need to do something like

my $return = getstuff(\@given_array, \%given_config)

All right, I passed the array in as a reference as well by doing this in the first block of code:

code:
 
my ($array, $config) = @_;
.
.
.
foreach my $line ( @{$array} ) {

And then I'm giving the subroutine references by doing this in the second block of code:

code:
foreach my $arrayref (@blocks) {
  &getstuff($arrayref, \%config);
} 
The hash part of the problem is still screwed up, though. How can I saw $config{$alias} = $field in the first block without getting an error?


Edit: I've tried $config->{$alias} = $field as well as $config{$alias} = $field in the first block of code to try to assign to the passed in hash, but those gave errors.

checkeredshawn fucked around with this message at 21:33 on Aug 5, 2008

Triple Tech
Jul 28, 2006

So what, are you quitting to join Homo Explosion?
Judicious use of Data::Dumper should help.

$config{$alias} as written accesses a real hash called %config. What you want now is hash key access to a hash ref, which should be written as $config->{$alias}. In hash access form, it looks like %$config or %{ $config }, see the difference?

checkeredshawn
Jul 16, 2007

Triple Tech posted:

Judicious use of Data::Dumper should help.

$config{$alias} as written accesses a real hash called %config. What you want now is hash key access to a hash ref, which should be written as $config->{$alias}. In hash access form, it looks like %$config or %{ $config }, see the difference?

Hmm, I tried $config->{$alias} = $field and I get this error:

Use of uninitialized value in hash element at config.pl line 47.

Ninja Rope
Oct 22, 2005

Wee.

checkeredshawn posted:

code:
foreach my $arrayref (@blocks) {
  &getstuff($arrayref, \%config);
} 

It's also worth noting that using the ampersand (&) prefix on subroutines is generally not used any more.

Edit:

checkeredshawn posted:

Hmm, I tried $config->{$alias} = $field and I get this error:

Use of uninitialized value in hash element at config.pl line 47.

This error implies that $alias is undefined.

checkeredshawn
Jul 16, 2007

Ninja Rope posted:

It's also worth noting that using the ampersand (&) prefix on subroutines is generally not used any more.

Edit:


This error implies that $alias is undefined.

Ah, thanks for the ampersand tip, I was unsure about that also. The undefined value error message confuses me because I definitely declare it in the first block of code with

code:
my ($field, $alias, $fieldstring, $aliasstring);
Might it have something to do with the fact that I'm assigning it with split /=/, $line?

Edit: Odd, though, if I throw in a

code:
print "$alias\n";


At the end of the subroutine, it gives me the error once, but then prints off the rest of the information I need.

checkeredshawn fucked around with this message at 21:48 on Aug 5, 2008

Triple Tech
Jul 28, 2006

So what, are you quitting to join Homo Explosion?
Yeah, you just need to get into the flow of debugging and making sure variables are actually getting populated with what you think they should have. If you're really printing the alias you should see a blank string and an error saying it's undef.

Adbot
ADBOT LOVES YOU

checkeredshawn
Jul 16, 2007

Triple Tech posted:

Yeah, you just need to get into the flow of debugging and making sure variables are actually getting populated with what you think they should have. If you're really printing the alias you should see a blank string and an error saying it's undef.

How might I fix this error? Is it related to the scope of the subroutine?

  • Locked thread