Stories
Slash Boxes
Comments
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

use Perl Log In

Log In

[ Create a new account ]

Journal of jjore (6662)

Saturday July 11, 2009
12:08 AM

You'll miss Carp in Ruby

In Perl, you have a nice built in library called Carp which gives you stack traces including the parameters on the stack. If you desire, you can dump the entire contents of any variable in any argument in your backtrace. If you really desire, you can modify your caller's variables.

This isn't possible in ruby-1.8.x due to mistakes or oversights in the design.

In perl, here's a sample of what you can do easily:

use Carp qw( cluck );
sub a { cluck('Message') }
sub b { a( 1 .. 2 ) }
sub c { b( 'a' .. 'c' ) }
c();

which prints your stack:

Message at - line 2
    main::a(1, 2) called at - line 3
    main::b('a', 'b', 'c') called at - line 4
    main::c() called at - line 5

There's other options like Carp::confess() to throw an exception with a stack trace, Carp::longmess() to make the string you see above, the module Carp::Always (http://search.cpan.org/dist/Carp-Always) to make Carp be your default behavior.

Carp is based on the caller() function which returns many pieces of information: class, filename, line, function, has args?, context, eval() text, is require?, compilation/pragma info. If you read perldebguts, you learn to also get the arguments:

sub b {
    package DB;
    () = caller 1;
    say "caller's args=@DB::args";
    $DB::args[0] = 'Zappo';
    return;
}
sub a {
    say "args=@_";
    b();
    say "args=@_";
}
a( 'flash' );
 
# args=flash
# caller's args=flash
# args=Zappo

I tried, I really tried to add this into Ruby-1.8.6. The problem is that for each ruby function, it uses actual C recursion to go deeper and it passes the arguments as an Array. For something like this:

def c(x);      end
def b(x); c(3); end
def a(x); b(2); end
a(1)

something like this happens in C:

rb_call(a,[1]) {
  rb_call(b,[2]) {
    rb_call(c,[3]) {
    }
  }
}

The problem being... how do you access the arguments without a pointer? You don't. Perl works because it is "stackless" in the sense of nested perl functions don't usually make the C stack go deeper and "stack based" in the sense that all arguments are pushed onto an application level stack.

Ruby's caller() function is like a particularly stupid perl version. You get the filenames, line numbers, and method names but that's it.

As is, it is nearly impossible to implement a useful stack trace in ruby-1.8.6. I've got a vague idea I might go learn how gdb extracts the backtrace, then walk that to find the argument arrays but OMG, that is such an ugly idea. I've got some x86 assembly books I might drag out to help with this.

Thursday July 09, 2009
01:00 AM

You'll miss search.cpan.org

Today I'm trying to read some documentation for ruby gems I haven't installed. In perl, you can just go to http://search.cpan.org/ and read documentation for all kinds of things you haven't installed and evaluate whether you want to read more or download or install.

Have you used the perl introspection module Devel::Spy before? No? Probably not. You can trivially go read the documentation for this thing you've never heard of at http://search.cpan.org/dist/Devel-Spy.

Not so with RubyForge. It's missing the batteries, you see.

Tuesday July 07, 2009
07:10 PM

Perl's compile time check is greater than Ruby

At work, I just rewrote a bunch of ruby code, moved piles of things around. It's changing some ordinary synchronous code to use EventMachine, something that's kind of like POE.

I just found out writing in ruby is like perl, but with

no strict 'vars';

on all the time.. This major time saver isn't available at all!

Even worse, whenever I typo a variable or forget to introduce it properly it's automatically turned into a method call.

W

T

F

Perl works to save my bacon and would never let me get away with typoing a variable or forget to introduce it. It's giganto times more efficient to program in Perl than Ruby.

Sunday July 05, 2009
12:48 PM

My first Perl 6 program

I tried to write the program from http://use.perl.org/~jjore/journal/39223 in Perl 6 but failed. It's written but there an error being thrown from within the regexp engine that I'm going to have to debug. Anyway, this was instructive to me about what worked and what didn't.

I tried reading some of the S* documentation but found it hard going. I ended up just browsing around in the Rakudo and Parrot implementations and test suites to figure out how to write this.

I get the following errors depending on what files I give to this program. My next steps are to go to #perl6 or #parrot and see how I debug the regexp. (but plz, don't reply here w/ help. This blog post is not a bug report).

Null PMC access in get_string()
in regex PGE::Grammar::_block51 (tab-width.p6:9)
called from Main (tab-width.p6:31)

Malformed UTF-8 string
in method IO::slurp (src/gen_setting.pm:3279)
called from method IO::slurp (src/gen_setting.pm:596)
called from Main (tab-width.p6:14)

The code:

#!/home/josh/src/rakudo/perl6
for @*ARGS -> $ifn {
    next if $ifn ~~ m{'/.git'};
 
    # TODO: open( ..., :rw ) not implemented. Open a second file in :w
    # as a workaround.
 
    my $ifh = open $ifn, :r;
    # TODO: not implemented $fh.binmode;
    my $isrc = $ifh.slurp;
    $ifh.close;
 
    # TODO: s/// not implemented, try .subst as workaround
    # in Main (src/gen_setting.pm:3279)
    my $osrc = $isrc.subst(
        /   :i
            ^^
            $<variables> = (
                $<indent> = (\N*)
                    Local\ Variables\:\N*\n
                [ \N* \n ]*
            )
            $<end> = (
                \N* End\: \N* \n
            )
        /,
        {
            # TODO: "$<variables>$<indent>tab-width: 8\n$<end>";
            "{$0}{$0[0]}tab-width: 8\n{$1}"
        }
    );
 
    next if $osrc eq $isrc;
 
    # TODO: lack of builtin rename() means I have to
    # write to a temp file
    my $ofn = "$ifn.tmp";
    my $ofh = open( $ofn, :w );
    $ofh.print( $osrc );
    $ofh.close;
 
    # TODO: rename() builtin not implemented
    # rename $ofn, $ifn;
    run "mv $ofn $ifn";
}

Friday July 03, 2009
04:00 PM

Perl 5.10.0, (not-so) giaganto-times faster than Ruby 1.8.6

Earlier today I wanted to edit a lot of source code to add some Emacs hints about the tab stop. I originally wrote it in perl and it works fine, takes two seconds to edit 150MB of text across 4851 files.

time find . -type f -print0 | xargs -0 /opt/perl-5.10.0/bin/perl tab-width
 
real        0m1.966s
user        0m1.340s
sys         0m0.354s

Here's the Perl 5:

undef $/;
my $RX = qr/
    (?<start>
        ^(?<indent>.*)Local\ variables:.*\n
    )
    (?<variables>
        (?:
            \k<indent>.*\n
        )*
    )
    (?<end>
        \k<indent>End:
    )
/mix;
 
for my $fn ( @ARGV ) {
    next if $fn =~ m{/.git};
 
    open my $fh, '+<', $fn
        or die "Can't open $fn: $!";
    binmode $fh
        or die $!;
 
    my $src = <$fh>;
    next unless $src =~ s{$RX}{$+{start}$+{variables}$+{indent}tab-width: 8\n$+{end}};
 
    seek $fh, 0, 0
        or die $!;
    truncate $fh, 0
        or die $!;
    print { $fh } $src
        or die $!;
    close $fh
        or die "Can't close $fh: $!";
}

I need to know Ruby better so I wrote a Ruby version of the same program. I don't know how long it takes to run. I started it awhile ago. In the time it's taking Ruby to run this, I got up to have some Pizza and Beer, then wrote this blog post.

time find . -type f -print0 | xargs -0 /opt/ruby-1.8.6/bin/ruby tab-width.rb
 
real    31m19.763s
user    18m7.957s
sys    12m5.596s

Here's the Ruby:

RX = Regexp.new(
    "
    (
        ^(.*)Local\\ variables:.*\\n
    )
    (
        (
            \\2.*\\n
        )*
    )
    (
        \\2End:
    )",
    Regexp::EXTENDED | Regexp::MULTILINE
)
 
ARGV.each do |fn|
    next if fn =~ %r{/\.git}
 
    open( fn, 'r+' ) do |fh|
        fh.binmode
 
        src = fh.read
        next unless src.sub!( RX ) {|m| "#{$1}#{$3}#{$2}tab-width: 8\n#{$5}" }
 
        fh.seek 0, IO::SEEK_SET
        fh.truncate 0
        fh.puts src
    end
end

Update: It's been over half an hour now.
Update: aha, done now
Update: got the .sub!() wrong. Fixed. Presumably I'm waiting another 30m. Going for a bike ride instead of waiting.
Update: didn't go biking. Asked #ruby-lang for help. (?>) and (?!) to control the ruby regexp engine seem to just trigger stack overflows
Update: this next big chunk.

So I talked to helpful people on #ruby-lang like larsch, rpag, and Aria. It turns out one major mistake was mis-using Regexp::MULTILINE. It's equivalent to perl's /s, not perl's /m. The docs don't actually talk about this so I had to guess. I guessed wrong.

Now I find Ruby 1.8.6 is only 3x slower while 1.9 is equivalent to Perl 5.10.0

Friday June 26, 2009
12:37 PM

Search your perl documentation w/ perldoc-search

With the perldoc-search program, you can easily search all your perl documentation to find where that elusive "add_build_element" method is documented.

When I say this:

perldoc-search add_build_element

I get this:

perltoc - perl documentation table of contents
Module::Build::API - API Reference for Module Authors
Module::Build::Cookbook - Examples of Module::Build Usage

Now I know where to find documentation and examples of this method. Anyone who wants to extend this, it is available in github at http://github.com/jbenjore/App-Perldoc-Search/tree/master and CPAN at http://search.cpan.org/dist/App-Perldoc-Search.

I wrote this on the flight back from YAPC10. Just landed in Seattle.

Update: Aaaannnd, it appears Mike Schilli already wrote something similar. Somehow I missed it when I looked before. Dunno how, Perldoc::Search is such an easy name to find: http://search.cpan.org/dist/Perldoc-Search.

Friday May 29, 2009
05:08 PM

Sigh

I'm going to be writing a lot of ruby now. :-/ I'm sad to be giving up the awesome tools available in perl. :-/

*sigh*

# Sigh. Automatic semicolons are a disease.
foo =\
  bar\
  .select { |e| e.yah? }\
  .collect { | e| e.noooo! }\
  .select { |e| e.ok? }

Monday May 18, 2009
03:06 PM

Sharing conference video?

I still have 324GB of conference video from the Perl Programming conference YAPC::NA 2008 which I have found too large to do much of anything with. I tried uploading one video to google video at http://video.google.com/videoplay?docid=7054401183589794595 but the slides turned out much blurrier than my original.

I'd like to be able to share all of this but it's too much to just make available for upload from my cable modem.

Til then, go watch rjbs talk about email in Email Hates the Living at http://video.google.com/videoplay?docid=7054401183589794595. Even if you can't read it all, it's enlightening, terrifying and hilarious.

josh@lik:/mnt/home/josh/Videos$ du -h YAPC\:\:NA\ 2008/
6M     YAPC::NA 2008/cog/Media
16M     YAPC::NA 2008/cog
9.9G    YAPC::NA 2008/yapc-2008-firstday/yapc-signes-barbie/Media
9.9G    YAPC::NA 2008/yapc-2008-firstday/yapc-signes-barbie
48G     YAPC::NA 2008/yapc-2008-firstday/yapc-2008/Media
48G     YAPC::NA 2008/yapc-2008-firstday/yapc-2008
58G     YAPC::NA 2008/yapc-2008-firstday
45G     YAPC::NA 2008/yapc-2008-secondday/yapc-schwern-morning/Media
45G     YAPC::NA 2008/yapc-2008-secondday/yapc-schwern-morning
42G     YAPC::NA 2008/yapc-2008-secondday/yapc-nathan-afternoon/Media
42G     YAPC::NA 2008/yapc-2008-secondday/yapc-nathan-afternoon
87G     YAPC::NA 2008/yapc-2008-secondday
24G     YAPC::NA 2008/pre-hackathon/prehack-yapc-2008/Media
24G     YAPC::NA 2008/pre-hackathon/prehack-yapc-2008
24G     YAPC::NA 2008/pre-hackathon
34G     YAPC::NA 2008/yapc-jbj/yapc-jbj-tapes/Media
34G     YAPC::NA 2008/yapc-jbj/yapc-jbj-tapes
38G     YAPC::NA 2008/yapc-jbj/yapc-jjore-tapes-two/Media
38G     YAPC::NA 2008/yapc-jbj/yapc-jjore-tapes-two
71G     YAPC::NA 2008/yapc-jbj
86G     YAPC::NA 2008/yapc-2008-thirdday/yapc-morning-smith/yapc-morning-smith-chromatic/Media
8 6G     YAPC::NA 2008/yapc-2008-thirdday/yapc-morning-smith/yapc-morning-smith-chromatic
86G     YAPC::NA 2008/yapc-2008-thirdday/yapc-morning-smith
86G     YAPC::NA 2008/yapc-2008-thirdday
324G    YAPC::NA 2008/

Sunday May 03, 2009
06:04 PM

Beginning to administer perl on Ubuntu

Inspired by some traffic on module-authors@ and similar, I'm trying to use cpan2dist to create debian packages of CPAN modules, with easy and no fuss.

It's... a slog. Apparently CPANPLUS::Dist::Deb assumes you'd only ever want to use the system perl. I'm working through the issues but it's an unhappy place to be right now. I figure I'm a pile more hours out from being able to use this. :-( Don't want to spend more of my weekend on this.

BTW, http://rassie.org/archives/tag/cpan2dist is nifty to give the right 90 seconds worth of info that the manual doesn't.

Thursday April 23, 2009
10:00 AM

Cursing perl 5

I can't create a nil-class object. Argh! I am utterly prevented from doing a complete proxy/spy in Devel::Spy because of this. I can "fix" all use of defined() just like UNIVERSAL::ref but I can't fix all the uses of SvOK in C or XS code.