To the old Perl programmers out there looking for a new language to learn, I suggest giving Julia a serious look. I haven't had a language bring me this much joy since when I first discovered Perl a long time ago. If Perl is the grandpa, Julia is the granddaughter, and she's a really smart girl. She hangs out with scientists all day helping them make sense of their data, and she does it with a unique style.
To be continued...
(There's so much I want to say, but I don't want to commit the time to write it all down right now.)
xe.com is a well known site for calculating the exchange value between the currencies of the world. However, there are times I’d prefer to query it from the command line. They have an API, but it’s not free, so I ended up writing a quick and dirty script that scrapes the web page and uses regexps to extract the data.
I know you’re not supposed to parse HTML with regexps, but sometimes, you can get away with it for a while. Also, this script is not that serious, so it can fail without hurting anything.
#!perl
use strict;
use warnings;
use feature 'say';
use WWW::Mechanize;
use Data::Dump qw(pp);
sub url {
my ($from, $to, $amount) = @_;
my $tmpl = "https://www.xe.com/currencyconverter/convert/?Amount=%f&From=%s&To=%s";
sprintf($tmpl, $amount, $from, $to);
}
sub get_xe_page {
my ($from, $to, $amount) = @_;
my $mech = WWW::Mechanize->new();
my $url = url($from, $to, $amount);
$mech->get($url);
$mech->content;
}
sub extract_price {
my $html = shift;
my $r = qr|([\d,.]+)<span class="faded-digits">(\.?\d+)|;
my @p = ($html =~ $r);
my $price = join('', @p);
$price =~ s/,//;
$price;
}
sub main {
my ($from, $to, $amount) = @_;
my $c = get_xe_page($from, $to, $amount);
my $p = extract_price($c);
say "$amount $from = $p $to";
}
unless (caller) {
main(@ARGV);
}
I have not been able to figure out how to run an async thread in the background while using a REPL like reply. The moment I run the main loop, it takes over the input from the REPL. Here's what a typical failed REPL session might look like.
❯ rlwrap reply
use AnyEvent
use Coro
use Coro::AnyEvent
my ($i, $loop)
$res[0] = [
undef,
undef
]
$i = 0
$res[1] = 0
$loop = async { while ($i < 10) { say $i++; sleep 1 } }
$res[2] = bless( {}, 'Coro' )
AE::cv->recv
0
1
2
3
4
5
6
7
8
9
^C
I don't know how to get back to the REPL, so I hit ^C but that exits the REPL.
Solution
A workaround I discovered is vividsnow/perl-live which is a combination of perl + elisp that provides an interactive Perl environment that is running an event loop. However, instead of a REPL, you get an emacs buffer in cperl-mode from where you can send lines of perl to a running perl process.
It's not quite what I was looking for, but I can work with this. It does solve the problem of letting me interact with async threads in a running perl process.