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 ]

rjbs (4671)

rjbs
  (email not shown publicly)
http://rjbs.manxome.org/
AOL IM: RicardoJBSignes (Add Buddy, Send Message)
Yahoo! ID: RicardoSignes (Add User, Send Message)

I'm a Perl coder living in Bethlehem, PA and working Philadelphia. I'm a philosopher and theologan by training, but I was shocked to learn upon my graduation that these skills don't have many associated careers. Now I write code.

Journal of rjbs (4671)

Wednesday October 08, 2008
07:33 AM

our text editors, our secret masters

Ever wonder how much of our programming style is dictated by our desire to see the right pretty colors? In Perl, I think it's a good bit.

For example, I know that the person who wrote this line wasn't using Vim's default Perl syntax:

Account->q(accountid => $self->{accountid});

...because it would interpret q(...) as a non-interpolative string. Meanwhile, the guy who wrote this was:

$logger->("setting account information to \%info");

...because syntax highlighting told him that %info was a variable, even though Perl doesn't interpolate hashes.

I always put spaces around my range operators, because otherwise in 1..2 the dots are different colors.

Other examples welcome.

Tuesday October 07, 2008
08:13 PM

hearts were entertaining june

I feel like I'm living in Brazil. No, not the nation, the film.

Two lamps in my house have failed, and both are so old and poorly wired that repairing them has been a real pain (and they're both still broken as I type this). My EVDO modem has been really flaky for the past three or four weeks and it's been a crap shoot, each day, as to whether I could get online.

Today I did a lot of uninstall/reinstall of the modem drivers, but it didn't help. I've been suspecting that it's a problem with the hardware. A few minutes ago, trying to remove and reseat the modem's USB connector, I pulled the device gently from my laptop, only to have the modem come out but not the connector. Has it been failing due to some kind of physical defect? Maybe, but now I'll never know. I doubt my vendor is going to accept a return on something that looks like it was physically mistreated.

So, I called work to say I was going to have to order a replacement and then started to bring up 3GStore on my iPhone. While I typed, the keyboard froze and my music started to skip. I tried and tried to power down, but nothing happened. I thought, "I'll have to call a friend and ask how to turn it off in this situation!" but of course then I remembered that I can't call someone when my phone is locked up. Fortunately, I had the iPhone User Guide on my laptop which (knock on wood!) has not been failing. Once I reset the phone, it announced that its battery was in the red. What?!

I really hope that the next thing to break down isn't the bus or, worse, the car right in front of the bus.

At least I don't have a pacemaker.

Sunday October 05, 2008
11:00 PM

just what the cpan was missing

I work for Pobox. We provide identity management. For the most part, it's about email. You register an email address with us and we handle the mail for you. We send it to an IMAP store, or your current ISP, or some flash in the pan webmail provider like Google. We do other things, though, like web and URL redirection. It's about managing services that relate to your identity.

Now, in internet years, we're ancient. We've been operating since 1995, which basically means that we've been providing internet services to real world end users for just about as long as there have been end users in the real world. (Inhabitants of .edu and .mil don't count; I said real world!)

That means that we used to offer some identity services that aren't really relevant anymore. For example, sometimes when sifting through data in the customer configuration datastores, I come across the plan configuration. Who here rememberes the .plan file? It's the precursor to twitter. You put what you were doing in your plan file and then when you got fingered, that file was served up.

Yeah, don't ask me about the unfortunate name "finger." I didn't name it.

Anyway, the long-gone support for finger at Pobox came up recently at a planning meeting. I said that I'd be focusing my time on re-enabling it during some planned service updates. The sysadmins groaned, and it encourated me. I wrote "finger server?" in my meeting notes.

This weekend, I made another crack about it, and got more worried noises from a sysadmin. I pulled up the RFC, realized how incredibly simple it would be to implement, realized that the CPAN didn't have a finger daemon, and did wrote one. Net::Finger::Server is available for installation.

Just to show that it isn't entirely useless, I threw together a little finger daemon:

~$ finger @git.codesimply.com | head
[zodiac.codesimply.com]
Repository                          Description
Acme-Canadian                       Canooks in your code, eh?
Acme-Lingua-EN-Inflect-Modern       modernize Lingua::EN::Inflect rule's
Acme-ProgressBar                    a simple progress bar for the patient
Acme-Studly                         convertBetween various_well_known Ide...
Amce-CNA                            a moer tolernat verison of mehtod loc...

...and then...

~$ finger Amce-CNA@git.codesimply.com | head
[zodiac.codesimply.com]
Project  : Amce-CNA
Desc.    : a moer tolernat verison of mehtod location
Clone URL: git://git.codesimply.com/Amce-CNA.git

I don't really think that we'll be bringing back finger support at Pobox. That's fine, we have better things to do. Finally, though, the CPAN has a server for the only protocol whose RFCs have sections on integrating with vending machines.

Friday October 03, 2008
06:48 AM

email::messageid 1.400

I've uploaded a new Email::MessageID, version 1.400. It has two major improvements. First, the result of its new method is now an Email::MessageID object, where it was previously an Email::Address object(!). This means that it can now have its own message-id-specific methods. It has one: in_brackets. This is a very common mistake:

my $email = Email::Simple->create(
  body   => ...,
  header => [
    ...
    'Message-Id' => Email::MessageID->new->as_string,
  ],
);

This would produce a bogus message. Message-Ids must be in angle brackets. Rather than fix as_string and break the code of everyone who was already dealing with this, I've added in_brackets. Use it!

Monday September 15, 2008
07:30 AM

new app cmd interface finally released

One of the earliest libraries I wrote for Pobox is ICG::CLI. It makes it easy to write CLI programs by tying together Getopt::Long::Descriptive with some common options (like help and verbose) and a few bits of code to make them work. So, you got three routines, whisper, say, and yell, which were like printf, but respected the verbose and quiet flags. (This got refactored into Log::Speak, which I don't think was ever released. Oh well.)

Later, I pulled out Rubric's subcommand dispatch code out into App::Cmd, and that was a big success, and used GLD, but didn't get you the printing builtins for verbose operation. Also, building them in wasn't going to be easy, because App::Cmd was OO instead of just a few imported routines. I finally decided on a way to make it happen, about six months ago, and it was a lot of fun to implement. It makes writing App::Cmd programs even easier, introduces fun uses for Sub::Exporter and lets you write plugins that provide exported functions into all your commands magically. That means that this is now possible:

package MyApp::Command::purge;   use MyApp -command;

sub run {     my ($self, $opt, $args) = @_;

  debug for $args->flatten;   }

1;

...because you can have (for example) a debug routine and autobox imported into every command automatically. I have a number of plugins to write to make this possible, and I've basically been putting off the release for months, waiting to get them written, but I had enough people saying, "Seriously, can you release what's in your git repo?" that I finally broke down and did it.

Hopefully I'll get some cool plugins written, real soon now.

Friday September 12, 2008
09:02 AM

more stupid headlines

Only a few weeks after reading in the Sunday Times that The Castle and the Trial were "Kafkaesque," today, CNN has this headline:

Warning: Ike may bring 'certain death'

I think I would've phrased it, "Possibility of death is certain" but there's no accounting for taste.

Monday September 08, 2008
06:27 PM

salt and vinegar goldfish crackers

Wow. I was looking at Wikipedia's article on Goldfish crackers recently (don't ask) and I saw an amazing fact. In "some regions of Canada" one can acquire salt and vinegar goldfish crackers.

I must try these! Are they delicious? Can you get me some? Help!

Sunday September 07, 2008
11:04 PM

rx, json schema, and uri templates

I got to feeling like maybe JSON Schema was not yet firm enough to give up on, and that maybe I could help improve it in the areas where Rx's design made more sense. I made one or two very minor suggestions that were accepted, but the most important area was not addressed. You can read more about it at the Google Groups thread.

I moved on to looking at other parts of my project, and realized that I was going to need a way to templatize a URI. Maybe it was time to look at URI Templates again. When I'd first seen them, they didn't seem like they provided much. You'd say:

http://gallery.example.com/user/{username}/photo/{photoid}

...and then fill it in with:

{ username => "rjbs", photoid => 1234 }

That was it. Still, that's more or less everything I'd need. I thought I'd have another look and see if there was some reason not to use it.

Well, in the time since I first saw it, there have been a few revisions to the spec, adding features like list-value variables and operators. So you can say:

http://x.com/?valid={-opt|true|valid}&{-join|&|foo,bar}&baz={-list|&baz=|baz}

{ valid => 1, foo => 'x', bar => 'y', baz => [ 1, 3, 5 ] }

...to get:

http://x.com/?valid=true&foo=x&bar=y&baz=1&baz=3&baz=5

That -opt operation says "if the value for 'valid' is not empty, then evaluate to the string 'true' and otherwise the empty string." There's also an inverted form called -neg. The behavior of -join should be clear. Unfortunately you're not allowed to pass list-value items to it, so it's not very useful for building a query string that would contain multiple entries for a given name. That's a shame, since it seems to be intended for use in building query strings. Meanwhile, -list (once called -listjoin) doesn't act like -join. It doesn't include the name of the variable (or equals sign) with each entry, so I have to include it in the join string and before the expansion.

Here's another way to do it:

http://x.com/?valid={-opt|true|valid}&{-join|&|foo,bar}{-prefix|&baz=|baz}

-prefix (along with -suffix and -list) are actually shown in examples forming paths, letting you turn our baz value above into 1/2/3/ or /1/2/3.

The first thing I wonder is this: why do we need a template system for query strings, anyway? They're easy, they've been around since forever, and the existing tools already handle all the crap like multiple values for one named parameter. The more interesting problem is in the path and maybe, sometimes, the domain. The most important feature is probably just dropping in a named value.

Another useful feature mentioned (and according to the archives at least briefly implemented) but not in the spec is the ability to deal with substrings. The system described looked like this:

http://cpan.org/{-sub|0,1|author}/{-sub|0,2|author}/{author}

I think that stinks. In most cases that I've seen this kind of thing, you're just making a simple path, and it looks like one of these:

R/J/BS
R/J/RJBS
R/RJ/RJBS
S/B/RJBS

I sure don't want to have to give every substring that I need, with those slashes. Why not:

http://cpan.org/{buildup:author,3,cumulative}

...or something more along those lines.

I think I need to look through the APIs that I'd use this on and see what features I'd want, and whether URI Templates address those well. If not, I'm not going to settle on something that gives me features I don't need but none that I do. I just don't relish trying to compete with yet another somewhat successful system.

Saturday September 06, 2008
09:58 PM

code simply now migrated to gitosis

For a few days now I've felt really unproductive, but also unenthused about any of the work I had in front of me. Today, I managed to get one thing done, though: I reconfigured Code Simply's git setup to use gitosis.

Among other things, it means I can hand out the equivalent of "commit bits" to projects at git.codesimply.com without handing out system users. Now other people can be productive for me!

Thursday September 04, 2008
07:11 PM

why sigils are great

Last night at ABE.pm, I was talking a little bit with The Gang about some of the things I came to believe while doing the same thing in multiple languages. In explaining some of the issues I have with Ruby, both the scope of variables and the resolution of methods, this example came to me:

class X
  def x; return 10; end

  def y
    if false
      x = 100
    end

    return x
  end

  def z
    return x
  end
end

obj = X.new

puts "result of obj.y: #{obj.y.inspect}"
puts "result of obj.z: #{obj.z.inspect}"

This will print:

result of obj.y: nil
result of obj.z: 10

When obj.y is called, a variable called x is not assigned to, because the assignment happens in a conditional branch that is not entered. Nonetheless, the assignment to the variable creates the variable, because variables are not block scoped and because variables need not be explicitly declared. This means that when return x is reached, x is a local variable with no assigned value. That variable, which is nil, is returned.

When obj.z is called, nothing has defined x in the method's scope, so Ruby resolves it as a method call on the current target, obj. In other words, the x in the method z is the same as self.x.

Of course, good method and variable names goes a long way to making this less of an issue, but "Can't we just agree to not introduce bugs?" isn't a great safety net.

In Perl 6, the y method would be something like:

method y {
  if false { my $x = 100 }
  return $x;
}

...but that's a syntax error, because Perl has block scope. To return the variable you'd say:

method y {
  my $x;
  if $bool { $x = 100 }
  return $x;
}

To return the result of a method on self, you'd say:

method y {
  if $bool { my $x = 100 }
  $self.x;
}

...and if you have a lot of stuff operating on $self and want to avoid a bunch of that typing, you could write:

method y {
  if $bool { my $x = 100 }

  given $self {
    # (pretend we have lots of code here that we save typing on)
    return .x;
  }
}

It's always clear whether we're dealing with a variable (there's a $ or other variable-marking sigil) or a method (there's an invocant or a lone dot, which acts something like a method-call sigil).

I think that Ruby's use of sigils is great. Its sigil-for-scope makes much more sense given Ruby's "everything is an object" variables. I just wish that they had a sigil for local scope variables.

This would actually be a huge improvement on a current problem. See, Ruby 1.9 is going to have block-level scope. Unfortunately, this will sometimes change how code worked.

value = 10;
array.each { |value| do_something }

This code (in Ruby) will clobber value, because the value in the proc is not created in a distinct scope from the value to which 10 was assigned. When Ruby 1.9 is adopted, this code will change. The two value variables will be distinct, and the first value will not be clobbered.

If block scope had been introduced with a new sigil this would have been avoided. Your old code would be:

*value = 10;
array.each { |*value| do_something }

Well, of course it's clear that these would be the same! They both have the (hypothetical) function-scope sigil. Ruby 1.9 wouldn't break this, because instead of changing the way sigil-free local variables worked, it would let you have a block-local variable if you asked for it:

%value = 10;
array.each { |%value| do_something }

That first variable could use a star, too. The important thing is that the smaller-scoped variable would be marked as only existing in its block-local scope. Of course, running out of sigils is a risk, but I'd rather see Ruby 3.0 require twigils than have backcompat issues like this.