Last update: Feb 06, 2012 at 05:00 UTC
Comments on the tutorial itself:
- All of the material currently in your "introduction" is footnote material. I'd move it into an actual footnote. And write a real introduction explaining what the tutorial is about! Don't just jump straight into code, expecting the reader to deduce what he's learning about.
- Make your code look good at standard wrapping widths, e.g. as Anonymous Monk would see the node. As it is, the "Comment" comments wrap; it looks really bad. I think I'd put the "Comments" on their own lines, either above or below the associated code line.
- Consider giving each comment a meaningful ID (like a variable name?) rather than just a number. But this is minor.
If we are going to convert this meditation directly into a tutorial, rather than having you repost:
- Delete the paragraph at the top, in which you provide context on the origin of the post. It's way too old for anyone to care now.
- Delete the last two paragraphs (after your signature). Again - no one cares about the edits you made back then. It would be one thing if we needed to maintain context for any comments on the post... but there aren't any!
All that being said - I'm not sure this is Tutorials-quality, in the sense that you're really just showing a very specific technique for accomplishing a very arcane task. I'd say it's a better fit for the Cool Uses for Perl section, frankly.
It's certainly very cool; I don't mean to take that away from it at all.
As for your other -- RFC Tutorial - Deleting Excel Rows, Columns and Sheets -- It looks really good to me. I'd post it in Cool Uses for Perl ASAP! (Or in Meditations. If you post it in CUFP, modify the title appropriately.)
my $total_population = $generations{$_};
$total_population += $generations{$_ - 1} if $generations{$_ - 1};
$total_population += $generations{$_ - 2} if $generations{$_ - 2};
store this in a .vbs file, e.g. eject_drives.vbs.
run directly as a command. windows knows how to execute .vbs files.
dim sh, f, i, v
set sh = CreateObject("Shell.Application")
set f = sh.NameSpace(17) 'My Computer'
for each i in f.Items
' MsgBox i.Name & "=" & i.Type
if (i.Type = "CD Drive") then
for each v in i.Verbs
if (v.Name = "E&ject") then
v.DoIt()
end if
next
end if
next
use List::Util qw( shuffle );
use strict;
use warnings;
my @upper = 'A'..'Z';
my @lower = 'a'..'z';
$_ = "What That April With His Shoures Soote
The Drought Of Marche Hath Perced To The Roote
";
$" = '';
eval "y/@upper@lower/@{[shuffle @upper]}@{[shuffle @lower]}/";
print
This code appears in the Perl Cookbook, 2nd Ed., and was allegedly taken from Mastering Regular Expressions.
It alleges properly to parse quoted CSV fields with embedded commas and double-quotes, but my test of this utterly fails.
sub parse_csv1 {
my $text = shift; # record containing comma-separated values
my @fields = ( );
while ($text =~ m{
# Either some non-quote/non-comma text:
( [^"',] + )
# ...or...
|
# ...a double-quoted field: (with "" allowed inside)
" # field's opening quote; don't save this
( now a field is either
(?: [^"] # non-quotes or
|
"" # adjacent quote pairs
) * # any number
)
" # field's closing quote; unsaved
}gx)
{
if (defined $1) {
$field = $1;
} else {
($field = $2) =~ s/""/"/g;
}
push @fields, $field;
}
return @fields;
}
Test:
my @f = parse_csv1('first,"second","thi,rd","fou""rth"');
print "$_\n" for @f;
Output:
first
second
thi
rd
fou
rth
WTF?
Solution:
The problem is on line 15:
( now a field is either
Because the /x switch is in effect, the programmer can, and did, embed comments within the regex.
But there is no way for the compiler to check when a # has been accidentally omitted!
Change the line to:
( # now a field is either
IIRC, credit for finding this bug goes to ikegami, and possibly ambrus as well. Thanks, guys!
A couple ideas for styling threads when the
"Lay out threads as <div> instead of <table>" setting is enabled:
/* a basic one: */
div.header { background-color: #EEE; padding: 3px; border-bottom: 1px
+solid blue; }
ul.replies:before { content: url(http://perlmonks.org/images/bubbles.p
+ng) }
ul.replies { list-style-type: none; padding-left: 40px; }
li.reply { border: 1px solid blue; }
/* a fun one: */
div.header { background-color: #DFB; padding: 3px; }
ul.replies:before { content: url(http://perlmonks.org/images/bubbles.p
+ng) }
ul.replies { border-left: 2px solid red; padding: 3px; list-style-type
+: none; padding-left: 20px; }
li.reply { border-top: 2px solid blue; padding: 3px; }
/* both will need something like this: */
div.comment-on { text-align: center; font-size: larger; background-col
+or: #DFB; }
<jcw> Jebus, I can't type.
<jcw> Perhaps a typing exercise would help.
*<* zdog has been kicked off channel #perlmonks by jcw (The quick brow
+n fox kicked over the whining dog)
<jcw> Yea, that worked.
*<* Signoff: castaway (Ping timeout)
*<* Signoff: theorbtwo (Ping timeout)
<jcw> 3 for the price of 1!
{
package Foo;
use overload '""' => \&as_string;
sub as_string { "Foo!" }
}
$_ = bless {}, 'Foo';
/(.*)/ and print "$1\n";
# does this print "Foo!" or "Foo=HASH(0xdeaded)"?
Special Characters in Unicode
Source: Mapping of Unicode characters
Character Name | Code point (hex) | Character between two Zeroes |
Word Joiner | ⁠ | 00 |
Zero-width joiner | ‍ | 00 |
Zero-width non-joiner | ‌ | 00 |
Zero-width space | ​ | 00 |
Zero-width no-break space |  | 00 |
Combining Grapheme Joiner | ͏ | 0͏0 |
Invisible Separator | ⁣ | 00 |
Invisible Times | ⁢ | 00 |
Function Application | ⁡ | 00 |
Space |   | 0 0 |
En Quad |   | 0 0 |
Em Quad |   | 0 0 |
En Space |   | 0 0 |
Em Space |   | 0 0 |
Three-Per-Em Space |   | 0 0 |
Four-Per-Em Space |   | 0 0 |
Six-Per-Em Space |   | 0 0 |
Figure Space |   | 0 0 |
Punctuation Space |   | 0 0 |
Thin Space |   | 0 0 |
Hair Space |   | 0 0 |
Left-to-Right Mark | ‎ | 00 |
Mathematical Space |   | 0 0 |
Soft Hyphen | ­ | 00 |
Non-breaking Hyphen | ‑ | 0‑0 |
No-break Space |   | 0 0 |
Narrow No-break Space |   | 0 0 |
Zero-width space | ​ | 00 |
Line separator | 
 | 0
0 |
Paragraph separator | 
 | 0
0 |
horizontal tab | 	 | 0 0 |
linefeed | 
 | 0
0 |
carriage return | 
 | 0
0 |
newline | … | 0
0 |
Gvim commands for using folds to browse Perl
data structures generated by Data::Dumper, given that
$Data::Dumper::Indent=1;
:set shiftwidth=2
:set foldcolumn=8 (not important)
:set foldmethod=indent
:1,$foldopen! (to open all folds)
use Tk::FileSelect;
use Data::Dumper;
use strict; use warnings;
my $mw = new MainWindow;
my $fs = $mw->FileSelect( -directory => '.' );
$fs->configure(-verify => ['-d'] );
print "$_: ",$fs->Subwidget($_),"\n" for
'dir_entry', # LabEntry
'file_entry', # LabEntry
'dir_list', # ScrlListbox
'file_list', # ScrlListbox
'dialog' # Dialog
;
my %ch;
$ch{$_} = $_ for $fs->children;
delete $ch{$_} for $fs->Subwidget;
my( $fr ) = @ch{ grep /Frame/, keys %ch };
my $b = $fr->Button( -text => "New Dir", -command => \&new_dir, );
$b->pack( -side => 'top', -fill => 'x', -expand => 1, );
my $file = $fs->Show;
die "> $file\n";
sub new_dir
{
$fs->Subwidget('dir_entry')->validate;
# note that this is the current "accepted" directory name from the
# dir entry. It may not be the name of an existing directory!
# but it will NOT have a trailing /* even if displayed.
# it's possible to wangle the direntry into a state where it
# has two slashes before the * and/or letters between
# the / and * for example: /x//* /x/y* /x//y*
# In all cases, the slash (both slashes, if present) up
# through the star are excluded from the value of -directory.
my $dir = $fs->cget('-directory');
print "Make a new dir under $dir !\n";
my $new_dirname = Prompt("Enter new folder name:"); # wave hands
my $new_dir = "$dir/$new_dirname";
mkdir $new_dir;
$fs->Accept_dir($new_dir);
}
Mysterious Posts
Mysterious
Mysteriously
Mystery
Mystify
Wall of Shame: Plagiarists In Residence
The sad, unfortunate fact is that not all of the registered users
of this site are playing with a full deck, scruples-wise.
In particular, two monks — jesuashok and madtoperl —
have routinely posted material by other authors stolen from other sites;
in each case, proper attribution of authorship was studiously avoided; and in many
cases the plagiarist explicitly claimed the work was original.
I'm not trying to single out these folks. They are simply a couple known, currently active plagiarists.
If you discover any other recent or new plagiarisms, please notify me, liverpole, planetscape, chargrill, or shmem (the Plagiarism Posse).
Keep in mind that usernames are not important; people can always create new user accounts to hide behind.
Rather, we want to educate any offenders — the people behind the usernames — that plagiarism is not cool and not acceptable.
Advice to moderators:
- Do not approve posts which are known to be plagiarisms.
In the case of posts by known habitual plagiarists such as madtoperl and jesuashok, err on the side of caution. Don't approve until the question has been settled. At this point, we have little reason to believe that jesuashok knows anything about how to program in perl, nor that madtoperl could write an original poem. For example.
- If possible, unapprove any plagiaristic posts which have already been approved.
Advice to monks:
- Down-vote plagiaristic posts. It's a shame that these liars have gotten beaucoups XP for posts that they did not put any original work into, nor (in the case of perl code) even understand.
Relevant PMD: How should Perlmonks deal with Plagiarism?
Some relevant discussion followed 571926, including accusations of plagiarism, followed by protestations of innocence.
Responses to questions in the Chatterbox
package SNMPfu;
# pass an object which is either a Net::SNMP object
# (as returned by Net::SNMP->session) or an SNMP::Session
# object (as in the SNMP module/dist).
sub wrap
{
my $obj = shift;
bless $obj, __PACKAGE__ . '::' . ref $obj; # rebless
}
package SNMPfu::Net::SNMP; # wrapper for Net::SNMP
use base 'Net::SNMP';
sub get # wraps Net::SNMP::get_request
{
my( $self, $var_id ) = @_;
my $r = $self->get_request( -varbindlist => [$var_id] );
defined $r or die $self->error;
$r->{$var_id}
}
package SNMPfu::SNMP::Session; # wrapper for SNMP::Session
use base 'SNMP::Session';
sub get # wraps SNMP::Session::get
{
my( $self, $var_id ) = @_;
$self->get($var_id) # but I'm not sure this correct. Illustration
+only.
}
1;
In user code:
my $sess = Net::SNMP->session( ... );
# or:
my $sess = SNMP::Session->new( ... );
SNMPfu::wrap( $sess );
my $val = $sess->get('sysDescr.0');
By reblessing, we divert all method calls on the object into
one of the wrapper classes we've written.
By making those wrapper classes inherit from the original
class of the object, the user can call "native" methods of
the object if she chooses. If we wish to disallow that, just
take out the 'use base' lines.
my $sh = new Win32::OLE 'Shell.Application' or die;
my $folder = $sh->NameSpace( $directory_path ) or die;
my $item = $folder->ParseName( $unqualified_filename ) or die;
$item->InvokeVerb('Edit');
Put the following code in a file named cdrom_drives.js
Execute it with the command
cscript /nologo cdrom_drives.js
/*
* cdrom_drives.js
* by jdporter
*/
var sh = WScript.CreateObject('Shell.Application');
var a = new Array();
var i;
for ( i = 65; i < 75; i++ ) { // test the first 10 drive letters
var p = String.fromCharCode(i,58,92); // letter + colon + backslas
+h
try {
var fi = sh.NameSpace(p).Self; // will throw if bad path
if ( fi.IsFileSystem && fi.Type == 'Compact Disc' ) a.push(p);
}
catch(e) {
}
}
WScript.Echo(a.join("\n"));
Odds and Ends
Get the total reputation of all your nodes.
use LWP::Simple;
use XML::Simple;
use strict;
my( $username, $password );
print "Username: "; chomp( $username = <> );
print "Password: "; chomp( $password = <> );
$username && $password or die "Abort.\n";
my $t = XMLin get "http://perlmonks.org/?node_id=32704;op=login;user=$
+username;passwd=$password;ticker=yes";
my $total;
my $n;
while ( my( $id, $hr ) = each %{ $t->{'NODE'} } )
{
$total += $hr->{'reputation'};
$n++;
}
print "$total rep in $n nodes\n";
Get a list of "other users" currently active in the Monastery, and their XP
use LWP::Simple;
use strict;
*a = \"http://perlmonks.org/?node_id";
printf qq
m%2d %7d %s\nm,m
leve.="(\d+)"l,m
exp="(\d+)"e,m
foruser="([^"]+)"ffor map get qq
m$a=16046;for_userid=$_m,map m
user_id="(\d+)"ug,get qq
m$a=15851m;
What's with all the "buddha" usernames?
Wacky. And then there's
HTML for a form with which someone (such as yourself) can send you a msg
This snippet can be put anyplace on PerlMonks where HTML forms are allowed, including
your homenode or in your Free Nodelet.
You must replace "jdporter" with your username, and 170442 with your user id (which is your homenode's node_id).
<form method="post" action="?" enctype="application/x-www-form-urlenco
+ded">
<input type="hidden" name="node_id" value="170442">
<input type="hidden" name="op" value="message">
<input type="hidden" name="replyto" value="user">
<input type="hidden" name="sendto" value="jdporter">
<input type="text" name="replytotext" size=60 maxlength=255>
<input type="hidden" name="sexisgood" value="submit">
</form>
How to using folds in Vim to browse Data::Dumper output
$Data::Dumper::Indent=1 is a prerequisite.
- :set shiftwidth=2
- :set foldcolumn=8 (actual value not critical)
- :set foldmethod=indent
- :1,$foldopen! to open all folds, since they're initially closed.
One of the patterns I see frequently goes like this:
- you say something that strongly and clearly implies X;
- other monk disagrees with you about X;
- you claim you never said X.
It's weasely, and intellectually dishonest. I don't care so much that you do that (you and I are strangers, after all), but I do care about the fact that it invariably and unnecessarily raises the noise level here by a significant amount. Sometimes I think you do it just for the joy of the fray.
Now, of course, you may -- and I fully expect you to -- say I'm mistaken about any or all of the above. But you have to ask yourself: Why do people so routinely misunderstand me? If you truly believe people aren't understanding your true opinion on something, I'd suggest (1) stating clearly and unambiguously -- and that means (among other things) without sarcasm, since that is so easily missed in this medium; and (2) maintaining your position with as much consistency as possible.
Below is the list of node links collected by clicking "Add to public pad" in my Personal Nodelet:
Help for User Settings
Aristotle
For Beginners: Basic Information Resources (or, Where to Look Things Up)
On finding the Perl Wisdom
ybiC
Nodelet types, uses, and (relative) usefulness
Welcome to the Monastery! Make yourself at home.
Spirit of the Monastery
Louis_Wu
Being a monk: why you'll love it, why you'll hate it
Site Comments.
PerlMonks for the Absolute Beginner
Forum or Knowledge-Base ?
A reflection or two on PM life
Perl $^O values for various operating systems
The Threading Dilemma
Are "PM Discussions" only to be technical?
About Perlmonks: How would you describe PM?
Why does PerlMonks work?
Where and how to start learning Perl
fast, flexible, stable sort
Keyword Nodelet / Tagging documentation
Re: Humorous Module Ideas
Real DJs Code Live (from Wired)
turnstep
PerlMonks as Ambassadors
The next step
How to get the most of your question from the monks
Help for new monks
New Monks
New Monks Info Page
broquaint
Add Entries to vroom's Book List
Re: Rethrowing with die $@ considered harmful (local $_ buggy)
Re: Name Space
Pumpkins are best used for...
Re^2: Unused accounts zombified
Re: How can I create an UTF8 encoded txt file contains strings like "aaaa"?
Conversion from UTF-8 to windows-1256 encoding
Re: Restrictions of the Anonymous Monk
Free Nodelet Settings
Making Perl Monks a better place for newbies (and others)
Ignored Users
Wow, stuff got inserted above, not below!
|