Re: each considered harmful?

2003-06-16 Thread Marcin Kasperski
 Calling keys() (or values()) in void context is quite efficient.

Nice to now. So it seems the correct idiom for using each is:

   keys %hash;
   while( my($k,$v) = each %hash ) {
...
   }

 p.s. I've shown an example, so we can have this issue documented
 together with other mod_perl gotchas. It's interesting that I don't
 remember this issue being reported earlier.

Maybe it could be of some interest where I happened to get this
problem. I got it in my custom TransHandler implemented to reduce stat
calls and to obtain 'select from multiple directories' effect.

... (config file) 

our %STATIC_FILES = (
'/img' = [ '/alternative/img', '/myapp/install/img' ],
'/css' = [ '/alternative/css', '/myapp/install/css' ],
...
)

... (transhandler file, simplified of course) ...

sub handler {
my $r = shift;
my $uri = $r-uri;
... detecting dynamic handlers ...
while( my($url, $dirs) = each %STATIC_FILES ) {
if( $uri =~ m{$url/(.*)$} ) {
foreach my $d (@$dirs) {
my $file = $d/$1;
if( -f $file ) {
   $r-filename($file);
   return OK;
}
}
}
}
}


Re: each considered harmful?

2003-06-16 Thread Stas Bekman
Marcin Kasperski wrote:
Calling keys() (or values()) in void context is quite efficient.


Nice to now. So it seems the correct idiom for using each is:

   keys %hash;
   while( my($k,$v) = each %hash ) {
...
   }
Looks like it. probably with a comment so you (or other readers) won't forget 
why you did that.

p.s. I've shown an example, so we can have this issue documented
together with other mod_perl gotchas. It's interesting that I don't
remember this issue being reported earlier.


Maybe it could be of some interest where I happened to get this
problem. I got it in my custom TransHandler implemented to reduce stat
calls and to obtain 'select from multiple directories' effect.
... (config file) 

our %STATIC_FILES = (
'/img' = [ '/alternative/img', '/myapp/install/img' ],
'/css' = [ '/alternative/css', '/myapp/install/css' ],
...
)
... (transhandler file, simplified of course) ...

sub handler {
my $r = shift;
my $uri = $r-uri;
... detecting dynamic handlers ...
while( my($url, $dirs) = each %STATIC_FILES ) {
if( $uri =~ m{$url/(.*)$} ) {
foreach my $d (@$dirs) {
my $file = $d/$1;
if( -f $file ) {
   $r-filename($file);
   return OK;
}
}
}
}
}
ah, a real-world example. Just what we need. Care to write a short pod section 
using this example, explaining the problem and the solution? plain text or pod 
will do. we will add it to the coding chapter.

Thanks.

__
Stas BekmanJAm_pH -- Just Another mod_perl Hacker
http://stason.org/ mod_perl Guide --- http://perl.apache.org
mailto:[EMAIL PROTECTED] http://use.perl.org http://apacheweek.com
http://modperlbook.org http://apache.org   http://ticketmaster.com


Re: each considered harmful?

2003-06-16 Thread Ged Haywood
Hi guys,

On Mon, 16 Jun 2003, Stas Bekman wrote:

[snip,snip]
 keys %hash;
 
 does the trick
 
 interesting that I don't remember this issue being reported earlier.

Probably because we all read the Camel Book, section 5.4.3, the bit
about FIRSTKEY.  All except Randal that is... :)

Most people when iterating over a hash will say something like

  foreach $scalar_name ( keys %hash_name ) { ... }

which automatically resets the iterator and is safe in a perisitent
Perl environment like mod_perl.  I hope.

73,
Ged.



Re: each considered harmful?

2003-06-16 Thread Stas Bekman
Ged Haywood wrote:
[...]
Most people when iterating over a hash will say something like

  foreach $scalar_name ( keys %hash_name ) { ... }

which automatically resets the iterator and is safe in a perisitent
Perl environment like mod_perl.  I hope.
That's a good point, Ged. Marcin, please include this preferred solution in 
the possible solutions section (assuming that you are going to write it ;).

__
Stas BekmanJAm_pH -- Just Another mod_perl Hacker
http://stason.org/ mod_perl Guide --- http://perl.apache.org
mailto:[EMAIL PROTECTED] http://use.perl.org http://apacheweek.com
http://modperlbook.org http://apache.org   http://ticketmaster.com


Re: each considered harmful?

2003-06-16 Thread Randal L. Schwartz
 Marcin == Marcin Kasperski [EMAIL PROTECTED] writes:

Marcin Maybe it could be of some interest where I happened to get this
Marcin problem. I got it in my custom TransHandler implemented to reduce stat
Marcin calls and to obtain 'select from multiple directories' effect.

Marcin ... (config file) 

Marcin our %STATIC_FILES = (
Marcin '/img' = [ '/alternative/img', '/myapp/install/img' ],
Marcin '/css' = [ '/alternative/css', '/myapp/install/css' ],
Marcin ...
Marcin )

Marcin ... (transhandler file, simplified of course) ...

Marcin sub handler {
Marcin my $r = shift;
Marcin my $uri = $r-uri;
Marcin ... detecting dynamic handlers ...
Marcin while( my($url, $dirs) = each %STATIC_FILES ) {
Marcin if( $uri =~ m{$url/(.*)$} ) {
Marcin foreach my $d (@$dirs) {
Marcin my $file = $d/$1;
Marcin if( -f $file ) {
Marcin$r-filename($file);
Marcinreturn OK;
Marcin }
Marcin }
Marcin }
Marcin }
Marcin }

That's actually the wrong data structure then.  What you want
if you're only ever accessing it as a list, is a list!

And, you're needlessly recompiling the regex each time.  Here's
a much better way to do that...

our @STATIC_FILES = (
  [ qr{^/img/(.*)$} = [ qw(/alternative/img /myapp/install/img) ],
  [ qr{^/css/(.*)$} = [ qw(/alternative/css /myapp/install/css) ],
  ...
);

sub handler {
  my $r = shift;
  my $uri = $r-uri;
  for (@STATIC_FILES) {
my ($pat, @dirs) = @$_;
if ($uri =~ $pat) {
  my $tail = $1;
  foreach my $dir (@dirs) {
my $file = $dir/$tail;
if (-f $file) {
  $r-filename($file);
  return OK;
}
  }
}
  }
  return DECLINED;
}

-- 
Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095
[EMAIL PROTECTED] URL:http://www.stonehenge.com/merlyn/
Perl/Unix/security consulting, Technical writing, Comedy, etc. etc.
See PerlTraining.Stonehenge.com for onsite and open-enrollment Perl training!


Re: each considered harmful?

2003-06-16 Thread Randal L. Schwartz
 Randal == Randal L Schwartz [EMAIL PROTECTED] writes:

Randal our @STATIC_FILES = (
Randal   [ qr{^/img/(.*)$} = [ qw(/alternative/img /myapp/install/img) ],
Randal   [ qr{^/css/(.*)$} = [ qw(/alternative/css /myapp/install/css) ],

Argh.  extra left bracket snuck in.

   [ qr{^/img/(.*)$} = qw(/alternative/img /myapp/install/img) ],
   [ qr{^/css/(.*)$} = qw(/alternative/css /myapp/install/css) ],

Randal   ...
Randal );

Randal sub handler {
Randal   my $r = shift;
Randal   my $uri = $r-uri;
Randal   for (@STATIC_FILES) {
Randal my ($pat, @dirs) = @$_;
Randal if ($uri =~ $pat) {
Randal   my $tail = $1;
Randal   foreach my $dir (@dirs) {
Randal my $file = $dir/$tail;
Randal if (-f $file) {
Randal   $r-filename($file);
Randal   return OK;
Randal }
Randal   }
Randal }
Randal   }
Randal   return DECLINED;
Randal }

Randal -- 
Randal Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095
Randal [EMAIL PROTECTED] URL:http://www.stonehenge.com/merlyn/
Randal Perl/Unix/security consulting, Technical writing, Comedy, etc. etc.
Randal See PerlTraining.Stonehenge.com for onsite and open-enrollment Perl training!

-- 
Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095
[EMAIL PROTECTED] URL:http://www.stonehenge.com/merlyn/
Perl/Unix/security consulting, Technical writing, Comedy, etc. etc.
See PerlTraining.Stonehenge.com for onsite and open-enrollment Perl training!


Re: each considered harmful?

2003-06-16 Thread Marcin Kasperski
  sub handler {
 
  my $r = shift;
  my $uri = $r-uri;
  ... detecting dynamic handlers ...
  while( my($url, $dirs) = each %STATIC_FILES ) {
  if( $uri =~ m{$url/(.*)$} ) {
  foreach my $d (@$dirs) {
  my $file = $d/$1;
  if( -f $file ) {
 $r-filename($file);
 return OK;
  }
  }
  }
  }
  }
 
 ah, a real-world example. Just what we need. Care to write a short pod
 section using this example, explaining the problem and the solution?
 plain text or pod will do. we will add it to the coding chapter.

Hmm, let's use my english-like language...

The problem:
- the application static files are installed in /myapp/img,
  /myapp/css, ...
- local site customization can be made by installing customized files
  in /custom/img, /custom/css...
- in both cases they are accessed via /img/..., /css/... urls

The solution - we use custom transhandler to check whether the
customized version exists and use it if so.


-- 
( Marcin Kasperski   | Working overtime sucks the spirit and motivation  )
( http://www.mk.w.pl |   out of a team. (Wells)  )
()
( O CVS i zarzdzaniu wersjami: http://www.mk.w.pl/narzedzia/narzedzia_cvs   )


Re: each considered harmful?

2003-06-16 Thread Stas Bekman
Marcin Kasperski wrote:
sub handler {

   my $r = shift;
   my $uri = $r-uri;
   ... detecting dynamic handlers ...
   while( my($url, $dirs) = each %STATIC_FILES ) {
   if( $uri =~ m{$url/(.*)$} ) {
   foreach my $d (@$dirs) {
   my $file = $d/$1;
   if( -f $file ) {
  $r-filename($file);
  return OK;
   }
   }
   }
   }
}
ah, a real-world example. Just what we need. Care to write a short pod
section using this example, explaining the problem and the solution?
plain text or pod will do. we will add it to the coding chapter.


Hmm, let's use my english-like language...

The problem:
- the application static files are installed in /myapp/img,
  /myapp/css, ...
- local site customization can be made by installing customized files
  in /custom/img, /custom/css...
- in both cases they are accessed via /img/..., /css/... urls
The solution - we use custom transhandler to check whether the
customized version exists and use it if so.
Yes, but can you write a section to be added to the documentation, explaining 
the problem, providing an example and a solution. Something that you'd have 
loved to find in the docs, when you first discovered it? Of course digesting 
all the helpful comments from others in this thread.

Good docs don't grow on the trees, someone has to put them together.

__
Stas BekmanJAm_pH -- Just Another mod_perl Hacker
http://stason.org/ mod_perl Guide --- http://perl.apache.org
mailto:[EMAIL PROTECTED] http://use.perl.org http://apacheweek.com
http://modperlbook.org http://apache.org   http://ticketmaster.com


Re[2]: each considered harmful?

2003-06-16 Thread Mike P. Mikhailov
Hello Marcin Kasperski,

Tuesday, June 17, 2003, 3:13:23 AM, you wrote:

  sub handler {
 
  my $r = shift;
  my $uri = $r-uri;
  ... detecting dynamic handlers ...
  while( my($url, $dirs) = each %STATIC_FILES ) {
  if( $uri =~ m{$url/(.*)$} ) {
  foreach my $d (@$dirs) {
  my $file = $d/$1;
  if( -f $file ) {
 $r-filename($file);
 return OK;
  }
  }
  }
  }
  }
 
 ah, a real-world example. Just what we need. Care to write a short pod
 section using this example, explaining the problem and the solution?
 plain text or pod will do. we will add it to the coding chapter.

MK Hmm, let's use my english-like language...

MK The problem:
MK - the application static files are installed in /myapp/img,
MK   /myapp/css, ...
MK - local site customization can be made by installing customized files
MK   in /custom/img, /custom/css...
MK - in both cases they are accessed via /img/..., /css/... urls

MK The solution - we use custom transhandler to check whether the
MK customized version exists and use it if so.


In our setup we use mod_rewrite for things like that. It checks for
static resources in the few places and if there is no custom version
finally looks in the some standard location (images, css, javascripts,
any static resources etc ...). In the dual frontend/backend setup I
think this approach is better -- requests for static resources
may still be served by light frontend server.


-- 
WBR, Mike P. Mikhailov

mailto: [EMAIL PROTECTED]
ICQ:280990142

Who is General Failure, and what is he doing reading my hard disk ?



Re: each considered harmful?

2003-06-15 Thread Randal L. Schwartz
 Marcin == Marcin Kasperski [EMAIL PROTECTED] writes:

Marcin You probably see the problem - when this code is re-executed (next
Marcin request), the loop iterates just over 'the rest' of the hash.

This is similar to the problem that shows up when you use glob in a
scalar context... it also has lexically-attached state.

And now that I think about it, so does the flip-flop scalar dot-dot
operator.

These are all examples of where it is non-trivial to take a CGI-based
script and just drop it in as Apache::Registry.  There's really
nothing A::R can do about it.  You must still use your Branes.
-- 
Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095
[EMAIL PROTECTED] URL:http://www.stonehenge.com/merlyn/
Perl/Unix/security consulting, Technical writing, Comedy, etc. etc.
See PerlTraining.Stonehenge.com for onsite and open-enrollment Perl training!


Re: each considered harmful?

2003-06-15 Thread Marcin Kasperski
  Does there exist some way to protect before this problem (some kind of
  auto-destructor, finally, whatever which would automatically rewind
  the hash internal iterator while leaving the context)?
 
 Not really a mod_perl problem, but you can read about the solution in
 the docs for each.
 
 There is a single iterator for each hash, shared by all each,
 keys, and values function calls in the program; it can be reset
 by reading all the elements from the hash, or by evaluating keys
 HASH or values HASH.

I found this note before asking, believe me... 
But it seems to me that this solution is not satisfactory - calling
'keys' or 'values' is inefficient and destroys most gains from
iterating over the hash using each...

-- 
( Marcin Kasperski   | Communication takes place between people, documents   )
( http://www.mk.w.pl |are secondary. (Booch) )
()
( Porady dla twrcw serwisw WWW: http://www.mk.w.pl/porady/porady_www  )


Re: each considered harmful?

2003-06-15 Thread Paul Johnson
On Sun, Jun 15, 2003 at 09:35:38PM +0200, Marcin Kasperski wrote:
   Does there exist some way to protect before this problem (some kind of
   auto-destructor, finally, whatever which would automatically rewind
   the hash internal iterator while leaving the context)?
  
  Not really a mod_perl problem, but you can read about the solution in
  the docs for each.
  
  There is a single iterator for each hash, shared by all each,
  keys, and values function calls in the program; it can be reset
  by reading all the elements from the hash, or by evaluating keys
  HASH or values HASH.
 
 I found this note before asking, believe me... 
 But it seems to me that this solution is not satisfactory - calling
 'keys' or 'values' is inefficient and destroys most gains from
 iterating over the hash using each...

Calling keys() (or values()) in void context is quite efficient.

Whether or not you appreciate the aesthetics is perhaps quite another
matter.

-- 
Paul Johnson - [EMAIL PROTECTED]
http://www.pjcj.net


Re: each considered harmful?

2003-06-15 Thread Stas Bekman
Paul Johnson wrote:
On Sun, Jun 15, 2003 at 09:35:38PM +0200, Marcin Kasperski wrote:

Does there exist some way to protect before this problem (some kind of
auto-destructor, finally, whatever which would automatically rewind
the hash internal iterator while leaving the context)?
Not really a mod_perl problem, but you can read about the solution in
the docs for each.
   There is a single iterator for each hash, shared by all each,
   keys, and values function calls in the program; it can be reset
   by reading all the elements from the hash, or by evaluating keys
   HASH or values HASH.
I found this note before asking, believe me... 
But it seems to me that this solution is not satisfactory - calling
'keys' or 'values' is inefficient and destroys most gains from
iterating over the hash using each...


Calling keys() (or values()) in void context is quite efficient.

Whether or not you appreciate the aesthetics is perhaps quite another
matter.
I think the point that Marcin is trying to make is that under normal 
circumstances (a script is run once) this problem doesn't occur. However under 
mod_perl the code persists and therefore doesn't DWIM, till you start thinking 
in mod_perl terms and not one-time run script terms.

The problem can be classified into the global variables usage under mod_perl 
category.

Consider:

#!/usr/bin/perl -T

our %hash;
%hash = map {$_ = 1 } 'a'..'c' unless %hash;
print Content-type: text/plain\n\n;

for (my ($k, $v) = each %hash) {
print $k $v\n;
last;
}
that script prints different values on the first 3 invocations and prints 
nothing on the 4th, and then repeats the loop. (when you run with httpd -X). 
there are 3 hash key/value pairs in that example.

As Paul has suggested you need to reset the iterator as documented for the 
operator each(). So adding:

keys %has;

does the trick for the above example.

p.s. I've shown an example, so we can have this issue documented together with 
other mod_perl gotchas. It's interesting that I don't remember this issue 
being reported earlier.

__
Stas BekmanJAm_pH -- Just Another mod_perl Hacker
http://stason.org/ mod_perl Guide --- http://perl.apache.org
mailto:[EMAIL PROTECTED] http://use.perl.org http://apacheweek.com
http://modperlbook.org http://apache.org   http://ticketmaster.com


each considered harmful?

2003-06-14 Thread Marcin Kasperski
Hmm, probably well known but ... I have not met any direct warning of
this problem so far.

 our %SOME_CONFIG = (
a = 1,
b = 2,
c = 3,
 );  

...
 while (my($k,$v) = each %SOME_CONFIG) {
 if( ... ) {
  return; # or last, or throw exception
 }
 }

You probably see the problem - when this code is re-executed (next
request), the loop iterates just over 'the rest' of the hash.

Does there exist some way to protect before this problem (some kind of
auto-destructor, finally, whatever which would automatically rewind
the hash internal iterator while leaving the context)?


Re: each considered harmful?

2003-06-14 Thread Paul Johnson
On Sat, Jun 14, 2003 at 11:33:17PM +0200, Marcin Kasperski wrote:
 Hmm, probably well known but ... I have not met any direct warning of
 this problem so far.
 
  our %SOME_CONFIG = (
 a = 1,
 b = 2,
 c = 3,
  );  
 
 ...
  while (my($k,$v) = each %SOME_CONFIG) {
  if( ... ) {
   return; # or last, or throw exception
  }
  }
 
 You probably see the problem - when this code is re-executed (next
 request), the loop iterates just over 'the rest' of the hash.
 
 Does there exist some way to protect before this problem (some kind of
 auto-destructor, finally, whatever which would automatically rewind
 the hash internal iterator while leaving the context)?

Not really a mod_perl problem, but you can read about the solution in
the docs for each.

There is a single iterator for each hash, shared by all each,
keys, and values function calls in the program; it can be reset
by reading all the elements from the hash, or by evaluating keys
HASH or values HASH.

perldoc -f each

-- 
Paul Johnson - [EMAIL PROTECTED]
http://www.pjcj.net