Difference between revisions of "Coding Gotchas"

From Dreamwidth Notes
Jump to: navigation, search
(Created page with "This page has a list of random weird Perl and DW gotchas == Gotchas == === use strict + my $foo if === <source lang="perl"> use strict; my $x = -1 if 0; # this condition is s...")
 
m (You can change the external value of non-reference scalars passed to a subroutine: Needs lang=text)
 
(17 intermediate revisions by 5 users not shown)
Line 1: Line 1:
This page has a list of random weird Perl and DW gotchas
+
This page documents coding "gotchas" where things might not turn out how you expect them to.
  
== Gotchas ==
+
== Dreamwidth specific gotchas ==
 +
 
 +
=== LJ::Entry->new always returns an LJ::Entry ===
 +
 
 +
You might expect that given an invalid <code>ditemid</code>, you might get an undefined value back--but that is not the case.  This is for efficiency's sake--entry and comment fetch requests are cached, and then when one of the entries is accessed (such as $entry->subject), all the entries or comments are requested all at once. Check the <code>$entry->valid</code> sub instead.
 +
 
 +
<source lang="perl">
 +
my $entry = LJ::Entry->new( $u, ditemid => $deleted_ditemid );
 +
print "Entry 1 is defined\n" if defined $entry;
 +
# use this instead of checking if the entry is defined
 +
print "Entry 1 is valid\n" if defined $entry->valid;
 +
 
 +
$entry = LJ::Entry->new( $u, ditemid => $valid_ditemid );
 +
print "Entry 2 is defined\n" if defined $entry;
 +
print "Entry 2 is valid\n" if defined $entry->valid;
 +
</source>
 +
 
 +
Returns
 +
 
 +
<source lang="text">
 +
Entry 1 is defined
 +
Entry 2 is defined
 +
Entry 2 is valid
 +
</source>
 +
 
 +
=== $r->OK is 0 ===
 +
 
 +
$r->OK is 0, not 200
 +
 
 +
=== $r->redirect is an 'error' page ===
 +
 
 +
For reasons that don't need exploring at this juncture, <tt>$r->redirect</tt>
 +
( and probably any other case when you return something besides <tt>$r->OK</tt> from a handler method ),
 +
the method is treated as an 'error' page.
 +
 
 +
If you want to set headers,
 +
you will have to use <tt>$r->err_header_out</tt> instead of <tt>$r->header_out</tt>.
 +
 
 +
=== Updating strings requires string names to be changed, too ===
 +
 
 +
See [[English-stripping]].
 +
 
 +
== General Perl gotchas ==
 +
 
 +
=== You can change the external value of non-reference scalars passed to a subroutine ===
 +
 
 +
<source lang="perl">
 +
use strict;
 +
 
 +
my $x;
 +
 
 +
print "x is '$x'\n";
 +
foo($x);
 +
print "x is now '$x'\n";
 +
 
 +
sub foo { $_[0] = "bar"; }
 +
</source>
 +
 
 +
Returns
 +
 
 +
<source lang="text">
 +
x is ''
 +
x is now 'bar'
 +
</source>
  
 
=== use strict + my $foo if ===
 
=== use strict + my $foo if ===
Line 8: Line 71:
 
use strict;
 
use strict;
  
my $x = -1 if 0; # this condition is supposed to fail.
+
my $x = -1 if 0; # intentional false, for example.
$x = 1; # This accesses a *global, persistant across requests* $x
+
$x = 1; # This accesses a *global, persistent across requests* $x
 
</source>
 
</source>
 +
 +
The condition can be anything, and this bug only happens if the "my $x" line does not execute because of the condition, if the condition is true then it will end up using the local as expected.
  
 
strict does '''not''' complain about this.
 
strict does '''not''' complain about this.
  
Do the following instead
+
Do the following instead:
  
 
<source lang="perl">
 
<source lang="perl">
Line 23: Line 88:
 
$x = 1;
 
$x = 1;
 
</source>
 
</source>
 +
 +
=== Useless use of private variable in void context ===
 +
 +
If you have code such as the following, you may get a totally nonsensical error:
 +
 +
<source lang="perl">
 +
my $foo = 0;
 +
my $bar = 1;
 +
 +
my @baz = $foo, $bar;
 +
</source>
 +
 +
Which causes an error of "Useless use of private variable in void context" -- you want to do the following instead:
 +
 +
<source lang="perl">
 +
my $foo = 0;
 +
my $bar = 1;
 +
 +
my @baz = ( $foo, $bar );
 +
</source>
 +
 +
[[Category:Development]]

Latest revision as of 23:29, 18 August 2014

This page documents coding "gotchas" where things might not turn out how you expect them to.

Dreamwidth specific gotchas

LJ::Entry->new always returns an LJ::Entry

You might expect that given an invalid ditemid, you might get an undefined value back--but that is not the case. This is for efficiency's sake--entry and comment fetch requests are cached, and then when one of the entries is accessed (such as $entry->subject), all the entries or comments are requested all at once. Check the $entry->valid sub instead.

my $entry = LJ::Entry->new( $u, ditemid => $deleted_ditemid );
print "Entry 1 is defined\n" if defined $entry;
# use this instead of checking if the entry is defined
print "Entry 1 is valid\n" if defined $entry->valid;
 
$entry = LJ::Entry->new( $u, ditemid => $valid_ditemid );
print "Entry 2 is defined\n" if defined $entry;
print "Entry 2 is valid\n" if defined $entry->valid;

Returns

Entry 1 is defined
Entry 2 is defined
Entry 2 is valid

$r->OK is 0

$r->OK is 0, not 200

$r->redirect is an 'error' page

For reasons that don't need exploring at this juncture, $r->redirect ( and probably any other case when you return something besides $r->OK from a handler method ), the method is treated as an 'error' page.

If you want to set headers, you will have to use $r->err_header_out instead of $r->header_out.

Updating strings requires string names to be changed, too

See English-stripping.

General Perl gotchas

You can change the external value of non-reference scalars passed to a subroutine

use strict;
 
my $x;
 
print "x is '$x'\n";
foo($x);
print "x is now '$x'\n";
 
sub foo { $_[0] = "bar"; }

Returns

x is ''
x is now 'bar'

use strict + my $foo if

use strict;
 
my $x = -1 if 0; # intentional false, for example.
$x = 1; # This accesses a *global, persistent across requests* $x

The condition can be anything, and this bug only happens if the "my $x" line does not execute because of the condition, if the condition is true then it will end up using the local as expected.

strict does not complain about this.

Do the following instead:

use strict;
 
my $x;
$x = -1 if 0;
$x = 1;

Useless use of private variable in void context

If you have code such as the following, you may get a totally nonsensical error:

my $foo = 0;
my $bar = 1;
 
my @baz = $foo, $bar;

Which causes an error of "Useless use of private variable in void context" -- you want to do the following instead:

my $foo = 0;
my $bar = 1;
 
my @baz = ( $foo, $bar );