fREWdiculous!
3 Mar
Apparently Patrick Michaud, pumpking of rakudo, read my post yesterday and he came up with an even better solition!
I’d read his post if I were you, but here was the code he got it down to (after adding the R meta op
):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | my %op_dispatch_table = { '+' => { .push(.pop + .pop) }, '-' => { .push(.pop R- .pop) }, '*' => { .push(.pop * .pop) }, '/' => { .push(.pop R/ .pop) }, 'sqrt' => { .push(.pop.sqrt) }, }; sub evaluate (%odt, $expr) { my @stack; my @tokens = $expr.split(/\s+/); for @tokens { when /\d+/ { @stack.push($_); } when ?%odt{$_} { %odt{$_}(@stack); } default { die "Unrecognized token '$_'; aborting"; } } @stack.pop; } say "Result: { evaluate(%op_dispatch_table, @*ARGS[0]) }"; |
Brilliant!
3 Mar
Jeff Atwood claims that comments are a required ingredient for a blog. How true! There have been some comments recently on my original post about an interactive perl shell. My post mostly centered around writing one liners with your regular shell.
Well, brunov replied and mentioned Devel::REPL, which is excellent! It has all kinds of great features and really does everything that you would expect a modern language shell to do. It’s a surprising hassle to get to work with ActiveState perl in windows, but in Linux it works like a charm!
G briefly mentioned perl -de0, which is alright, if you want something out of the box, but if given a choice between perl -de0 and perl -E, I’d choose the latter, as at the very least I get the latest 5.10 features that way. Unless I missed something you can’t even do things on multiple lines in perl -de0. But I’m sure plenty of people dig it.
Anyway, hope that helps someone!
28 Feb
This doesn’t really make rakudo interactive, it just gives you history, but that’s pretty nice!
1 | ledit ./perl6 |
ledit is in apt, so if you have ubuntu you can just install it with sudo aptitude install ledit. Very nice!
28 Feb
“For what it’s worth, ± does happen to be in Latin-1, and therefore officially fair game for Standard Perl.” –Larry Wall, on adding ± as some form of operator to perl6.
27 Feb
I did this because of the excellent Higher-Order Perl.
Here is the Perl 5 code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | #!/usr/bin/perl use strict; use warnings; my $op_dispatch_table = { '+' => sub { my ($stack) = @_; push @$stack, pop(@$stack) + pop(@$stack); }, '-' => sub { my ($stack) = @_; my $s = pop(@$stack); push @$stack, pop(@$stack) - $s; }, '*' => sub { my ($stack) = @_; push @$stack, pop(@$stack) * pop(@$stack); }, '/' => sub { my ($stack) = @_; my $s = pop(@$stack); push @$stack, pop(@$stack) / $s; }, 'sqrt' => sub { my $stack = shift; push @$stack, sqrt(pop(@$stack)); }, }; my $result = evaluate($op_dispatch_table, $ARGV[0]); print "Result: $result\n"; sub evaluate { my $odt = shift; my @stack; my ($expr) = @_; my @tokens = split /\s+/, $expr; for my $token (@tokens) { if ($token =~ /\d+$/) { push @stack, $token; } else { if (my $fn = $odt->{$token}) { $fn->(\@stack); } else { die "Unrecognized token '$token'; aborting"; } } } return pop(@stack); } |
And here is the Perl 6:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | #!/home/frew/personal/rakudo/perl6 my %op_dispatch_table = { '+' => sub (@stack) { @stack.push(@stack.pop + @stack.pop); }, '-' => sub (@stack) { # this should probably be: # @stack.push(@stack.pop R- @stack.pop); my $s = @stack.pop; @stack.push(@stack.pop - $s); }, '*' => sub (@stack) { @stack.push(@stack.pop * @stack.pop); }, '/' => sub (@stack) { # this should probably be: # @stack.push(@stack.pop R/ @stack.pop); my $s = @stack.pop; @stack.push(@stack.pop / $s); }, 'sqrt' => sub (@stack) { @stack.push(@stack.pop.sqrt); }, }; sub evaluate (%odt, $expr) { my @stack; my @tokens = $expr.split(/\s+/); for @tokens -> $token { if $token ~~ /^\d+$/ { @stack.push($token); } else { if my &fn = %odt{$token} { &fn(@stack); } else { die "Unrecognized token '$token'; aborting"; } } } return @stack.pop; } say "Result: { evaluate(%op_dispatch_table, @*ARGS[0]) }"; |
Usage: ./calc.pl “5 6 +”
The main differences to notice are sigil invariance, subroutine signatures, and method instead of function syntax.
27 Feb
A coworker called me and asked me what it meant that when vim opened a file there were a bunch of ^@’s in it. I didn’t know off hand, but I did know that vim had some feature to print out the ascii value of the character that the cursor is over. So without further ado:
:as or ga
Enjoy!
26 Feb
1 | noglob zmv -W **/^*.flac **/*.flac |
I just ripped a bunch of music into flac and I forgot to add .flac to the end of the files until I was mostly done. If you are using zsh (and you load the zmv module) the above line will rename all files that do not end in .flac to whatever they used to be, but with .flac at the end.
excellent.
26 Feb
One of my least favorite things about javascript is scope management. In most languages scope is quite clear; if you defined a variable previously and “higher up” in some kind of scope stack, you can access it. And furthermore, this always refers to the current object. That’s not quite true for javascript, because javascript is different than (almost) any other programming language you have ever used.
You don’t like monkeypatching? Bummer. That’s how objects are created in javascript…more or less. But more on that later. Right now: scope.
Here is a base form that I wrote for work. We use ExtJS for all of our UI, which lets us do cool things like this. Feel free to read it like a story; I just want to point out lines 18-37. Take a look at those and then read on.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | Ext.ns('ACDRI.ui'); ACDRI.ui.BaseForm = Ext.extend(Ext.FormPanel, { generateUrl: function() { return '/devcgi/init.plx/controller_' + this.controller + '/' + this.action; }, validateRole: function(form, action) { console.error(action); }, initComponent: function() { var config = { bodyStyle:'padding:5px 5px 0', width: 350, defaults: {width: 230}, buttons: [{ text: 'Save', handler: function() { this.getForm().submit({ url: this.url, baseParams: this.baseParams, waitMsg:'Saving...', success:function(form, action){ this.closeFunction(); console.log(this); if (this.successFunction) { this.successFunction(); } }, failure:function(form, action){ this.validateRole(form, action); }, scope: this }); }, scope: this },{ scope: this, text: 'Cancel', handler: function() { this.closeFunction(); } }] }; Ext.apply(this, config); ACDRI.ui.BaseForm.superclass. initComponent.apply(this, arguments); } }); |
Note the “scope: this” directives sprinkled throughout the code. The reason for the usage of the directives is that we have some functions (success, etc) that have the keyword this in them. By default this is supposed to refer to the object from which the method is called (the invocant), but with a language like javascript where you can add methods and variables to objects (kinda like monkeypatching, but only for instances of objects) on the fly, you start to realize that sometimes you don’t want this to be the invocant, but something else. You probably want this to be the object that adds the method to the other object. Well, in ExtJS the scope config option allows you to set the invocant.
In the above example we have to set the invocant because otherwise the validateRole method will be called from the button, and not the form. The same follows for the this.getForm() etc.
That’s pretty common in Ext. People run into this kind of thing all the time because they assume that what they are configuring is the current object but it usually isn’t.
But that’s chump change to what I had to do below. Read (17-19):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | Ext.ns('ACDRI.ui'); ACDRI.ui.CustomerContacts = Ext.extend( ACDRI.ui.Grid, { addFunction: function() { var win; win = new ACDRI.ui.FormWindow({ title: 'Create New ' + this.itemName, height: 250, items: [{ url: this.generateCreationUrl(), baseParams: { customer_id: this.customer_id }, xtype: 'customer_contact_form', // \/ Look here \/ successFunction: function() { this.getStore().load(); }.createDelegate(this), closeFunction: function() { win.close(); } }] }); win.show(); }, initComponent: function() { this.record = Ext.data.Record.create([ {name: 'id', type: 'string'}, {name: 'first_name', type: 'string'}, {name: 'last_name', type: 'string'}, {name: 'phone', type: 'string'}, {name: 'fax', type: 'string'}, {name: 'email', type: 'string'} ]); var config = { controller: 'WorkOrderEntry', action: 'customer_contacts', title: 'Contacts', itemName: 'Contact', baseParams: { customer_id: this.customer_id }, columns: [{ header: 'Name', renderer: function(value, metadata, record) { var t = new Ext.XTemplate([ '<tpl if="email">', '<a href="mailto:{email}">', '{first_name} {last_name}</a>', '</tpl>', '<tpl if="!email">', '{first_name} {last_name}', '</tpl>' ]); return t.applyTemplate({ email: record.get('email'), first_name: record.get('first_name'), last_name: record.get('last_name') }); }, sortable: true, width: 110 },{ header: 'Phone', dataIndex: 'phone', sortable: true, width: 110 },{ header: 'Fax', dataIndex: 'fax', sortable: true, width: 110 }] }; Ext.apply(this, config); ACDRI.ui.CustomerContacts.superclass. initComponent.apply(this, arguments); } }); Ext.reg('customer_contacts', ACDRI.ui.CustomerContacts); |
See, the scope option is Ext specific. When you start doing your own stuff (like I am) you have to deal with scope yourself. createDelegate (bind in Prototype) helps us set the scope in a function. It gives us a new anonymous function with the scope set to whatever we passed it.
The issue above is that we want the window to reload the grid after a successful save. The window doesn’t know anything about the grid, so we have to explicitly tell it that the this is the grid. That’s what createDelegate does.
Crazy huh?
23 Feb
This week’s AOTW is To Watch the Storms by Steve Hackett. I first heard of Steve Hackett (and also this album) in a sampler from InsideOut. I remember listening to the sampler and being blown away by both the Hackett song and the Flower Kings song. I later ordered this album and have consistently been impressed by the quality of the album.
But quality is not all that it takes to make a great album. This album has an amazing variety of music. For example, The Devil is an Englishman is an unusual techno-rock song, Frozen Statues is an extremely sparse song (I count 2 instruments,) and The Silk Road is a powerful, almost acoustic drum based song. I consider this album prog in the purest sense in that it does very unusual things with music and pulls them off quite nicely.
I would say the best listening conditions for this album are when you are on a dark beach with a storm coming in so the wind is blowing gently. It may sound like the album name is the reason, but imagine listening to it in those conditions and I think you will see what I mean.
This is another one of those albums that is hard to pick songs for, but I can try: Brand New, Rebecca, The Silk Road, and Serpentine Song.
Colors: Blue, White, and Brown.
22 Feb
One thing that I love about reading good programming books (maybe even good Perl programming books) is the humor instilled in them. Tonight I decided to start reading Higher Order Perl (which you can get free here!) Here is a selection from the frontispiece:
… Hardly anyone wants to listen to Lisp programmers. Perl folks have a deep suspicion of Lisp, as demonstrated by Larry Wall’s famous remark that Lisp has all the visual appeal of oatmeal with fingernail clippings mixed in. Lisp programmers go around making funny noises like ‘cons’ and ‘cooder,’ and they talk about things like the PC loser-ing problem, whatever that is. They believe that Lisp is better than other programming languages, and they say so, which is irritating. But now it is all okay, because now you do not have to listen to the Lisp folks. You can listen to me instead. I will make soothing noises about hashes and stashes and globs, and talk about the familiar and comforting soft reference and variable suicide problems. Instead of telling you how wonderful Lisp is, I will tell you how wonderful Perl is, and at the end you will not have to know any Lisp…
I am looking forward to reading this one