Wednesday, August 8, 2012

Interesting perl foreach behavior

My co-workers were surprised by this perl behavior and shared this problem so I thought it would be a fun post.
my %hash = (
   a => 1,
   b => 2,
);

foreach my $v (values %hash) {
    $v = 99;
}

warn Data::Dumper->Dump([\%hash], [qw(hash)]);

# This was the output:
$hash = {
  a => 99,
  b => 99
};


This code is trying to edit a hash, and normally, you would iterate over the keys and then change the looked up value somewhat like this:
foreach my $k (keys %hash) {
    $hash[$k] = 99;
}

You can also change an items value for an array as well:
my @test = qw(a b c);
foreach my $v (@test) {
  $v = 'zzz';
}
warn Data::Dumper->Dump([\@test], [qw(test)]);

# This was the output:
$test = [
  'zzz',
  'zzz',
  'zzz'
];


What is happening here is that the for-loop variable is an alias for each list item. Since its an alias, Perl does not copy the list item's value just to hand $v to you (it's efficient).

The modification of hash values happens in the example because values() itself returns a list of hash values. This below wouldn't work because it introduces an intermediate copy:
my %hash = (
  a => 1,
  b => 2,
);
my @hash_values = values %hash; # make copies of hash value aliases
foreach my $v (@hash_values) {
  $v = 99;
}

And the following example is also illegal because we are trying to modify read-only values:
foreach my $v (qw[ a b c ]) {
  $v = 'zzz';
}
So now you know the power of the foreach loop.

Saturday, June 16, 2012

SSH bookmarklet

When developing server software for a company, you might be troubleshooting an issue on a development server other than your own and you want to login to that server. Specifically I'm talking about when you are looking at say a QA person's issue in a web browser and you want to login to their box and see what's wrong.

I found out recently that my MacBook has the ssh protocol registerred already where if you click on a link with this scheme: ssh://user@host.name, then that executes ssh user@host.name. I wanted to figure out a way to utilize this in a bookmarklet. I also wanted it to be easy enough such that you could enter a different username, like root or the QA person's username if you have certain access restrictions on that server.

Here is my attempt to create that bookmarklet. Just drag it to your browser's toolbar:

Run SSH

Here is my breakdown of what happens:
// prompt for a user to ssh as, save that in the window for next time
window.sshuser = prompt('Login to ' + window.location.hostname + ' as', window.sshuser || '');

// construct the user@ string
user = (window.sshuser ? window.sshuser + '@' : '');

// construct the url and execute it
window.location = 'ssh://' + user + window.location.hostname


This works great, but I really want to figure out how to make multiple programs that register the ssh:// protocol for any operating system or browser. Something like this link explains: http://kb.mozillazine.org/Register_protocol

Windows is pretty easy to create a batch script that adds registry keys for an ssh protocol to run putty (or even cygwin ssh). I would like to know how to do the same on Ubuntu (or any Linux). I'm pretty stoked that the Macbook already has it. I don't know if its related to me installing mac developer tools, but I'm pretty satisfied.

Anyway, Hope this bookmarklet helps!

Weird jQuery bug

My software was recently upgraded from jQuery 1.5.2 to 1.7.2.

Luckily we had a bunch of automated tests for our ui code and we found a lot of issues with our code that toggles checkboxes or the disabled state of a tag.  Previously you could say
$('#my_checkbox').attr('checked', 'checked'); // check the checkbox
$('#my_checkbox').attr('checked', ''); // uncheck the checkbox

$('#my_input').attr('disabled', 'disabled'); // disable the input
$('#my_input').attr('disabled', ''); // enable the input
We had code all over the place that did this. But when we used empty string, attr didn't enable or uncheck the elements.

The fixes we found were to either use a boolean value instead of a string, or you could use the removeAttr function:
$('#my_checkbox').attr('checked', true); // check the checkbox
$('#my_checkbox').attr('checked', false); // uncheck the checkbox
$('#my_checkbox').removeAttr('checked'); // alternative to uncheck the checkbox

$('#my_input').attr('disabled', true); // disable the input
$('#my_input').attr('disabled', false); // enable the input
$('#my_input').removeAttr('disabled'); // alternative to enable the input
We needed to figure out the best way to change our code with little impact and it looked like using removeAttr would cause more code since you would have to litter your code with if/else statements to figure out whether to use the attr or the removeAttr case.

So because of this we tried to enforce using booleans. But you could run into issues where you didn't know the type of the second parameter to attr.
var checked = $('#my_checkbox').attr('checked'); // get the checkbox state:
//   'checked' or ''
//...
$('#other_checkbox').attr('checked', checked); // set another checkbox to the same state
// same thing appplies to disabled
I did some digging and found that jQuery 1.6.2 had a fix to change attr('checked') to return the actual html value of checked instead of a boolean value:
<input id="my_checkbox" type="checkbox" checked="checked" />
...
var checkState = $('#my_checkbox').attr('checked'); // returns 'checked' as of jQuery 1.6.2 instead of true.  When it is unchecked, you get undefined returned.
// See this link for a list of more quirks: 
//     http://blog.jquery.com/2011/06/30/jquery-162-released/#comment-526605
So, to remedy this, we decided to always ensure you pass a boolean to the attr function for disabled or checked. Don't use empty string to uncheck or enable your element. If you still want to rely on the return string of the attr function, you can booleanize it like this:

var check_state = $('#my_checkbox').attr('checked'); // get the checkbox state:
//    'checked' or undefined
//...
$('#other_checkbox').attr('checked', !!check_state); // set another checkbox to the same state using a boolean
// !!undefined yields false, 
// !!'checked' yields true
// same thing applies to disabled
Now you know, and knowing is half the battle.

<rant>
I have to say that I'm pretty unimpressed with jQuery since no one caught this.  Changing apis that are so important, like attr, is bad mojo and will cause many developers to curse your name late at night as they debug these unexpected api upgrade bugs.  jQuery is supposed to be so awesome because it is easy going and does what you expect.  This is a step backwards for all of us.
</ rant>

Wednesday, April 11, 2012

dev=1

Sometimes you want to be able to toggle dev=1 on a url. This can easily be done with javascript. You can create a link on a page with href="javascript:..." then right-click->save this link as a bookmark in your bookmark toolbar.

The following link is my attempt to write this, you can click it now, or bookmark it --> Toggle Dev

Let's read it line by line:
var alocation = window.location.search.toString(); // save the ?query string

// determine if when we add dev=1 if we need a ? or an &
var questoramp = alocation.indexOf('?') != -1 ? '&' : '?'; 

// if dev=1 exists, remove it, otherwise add it
var next = alocation.match(/[\?&]dev=1/) ? alocation.replace(/[\?&]dev=1/,'') : alocation + questoramp + 'dev=1'; 

// handle special case where dev=1 is at the beginning of the url
next = alocation.match(/\?dev=1&/) ? alocation.replace(/dev=1&/,'') : next; 

// update the window location
window.location.href=window.location.pathname + next + window.location.hash;

You have to make sure you don't forget the window.location.hash, or else you will get the dev=1 in the wrong part of the url.

=====================

I also wanted a way to toggle my web server from live apache(https) to a single threaded dev server (8080)

Here is my attempt: Toggle 8080

Again, here it is line by line
// save the whole url
var alocation = window.location.href.toString(); 

// if you see 8080 in the url, remove it and change the protocol to https, otherwise add it
var next = window.location.port == '8080' ? alocation.replace(/:8080/,'').replace(/http/,'https') : 'http://' + window.location.host + ':8080' + window.location.pathname + window.location.search + window.location.hash; 

// update the window location
window.location = next;

Hope this helps.

Friday, March 9, 2012

Logic chains in javascript and python

Let's talk about javascript.  What happens when you have a function like this:

function(x) {
    x = x || 'default'
    ...
}

This is useful when you want to have a function where x is optional.  When you don't pass a value to your function x is treated as undefined and the statement is read as x = undefined || 'default'.  Whenever you have:

somevariable = statement || statement || statement ... || statement

the variable will get assigned the first true value from left to right or the last false value.

But what happens when you do this?
x = [] || 'kittens'
you would think that [] evaluates as a false value, but in javascript an empty list is true so x becomes []

lets try this in python
x = [] or 'kittens'
This evaluates the way you think, x becomes 'kittens'.

Now, I'm not saying anyone would have statements like this, but I just wanted you to think about the little differences that languages have and how they can cause unforeseen bugs.

The same thing applies to empty objects:
in javascript:
x = {} || 'yarg' /* yields {} */
in python
x = {} or 'yarg' /* yields yarg */
Complimentary to the 'or' examples, 'and's behave the opposite.  If you have:
somevariable = statement && statement && ... && statement
your variable will get the first false statement or the last true statement.

This works pretty well in javascript/python

x = 'lol' and 'heh' and 'doh'
x = 'lol' && 'heh' && 'doh'
/* x has doh */
but again, try this:
// javascript
x = 'lol' && [] && 'doh' /* yields 'doh' */

# python
x = 'lol' and [] and 'doh' /* yields [] */
Now you know; and knowing is half the battle.


Thursday, March 1, 2012

Fun Emacs Prank

I noticed while using emacs you can use this handy program called emacsclient to perhaps open a file or run a command on emacs. I took this as an opportunity to have fun with my co-workers.

They like to run emacs with X-Forwarding on remote hosts that are the development hosts. Its easy to log into their remote host and do something like this:
emacsclient --no-wait ~/prank-file

This would open the file on their currently running emacs. Sounds great right? You could make some ascii picture of something nsfw and then just run good old emacsclient to turn their day around!

Anywho, this wasn't enough for me. I wanted to make it so the file would change and maybe scroll across the screen saying something like "LOL Kittens!". Or even you could try and make it invert the ascii art and then invert it back. Somewhat like you are flashing the text.

I first tried to get it so you could scroll the art across the screen (from left to right)
Example:
first iteration
LOL
CAT

second iteration
OL
AT

final iteration
L
T

I started out trying this:
columns=`head -n 1 /tmp/ascii-art-file | wc -c`; # get the number of columns in the text file

for x in seq 1 $columns; do
    cut -c $x-$columns /tmp/ascii-art-file > /tmp/scroll;
    emacsclient --no-wait /tmp/scroll; 
    sleep 5;
done;

This didn't work as expected. Emacs kept asking if I wanted to refresh the modified buffers.
I did some digging and it didn't seem like an easy solution. I wanted this to be something that would just appear on my co-worker's screen and cause mayhem.

After some more digging I found the handy emacs command: zone.
It does all fun stuff like scrolling your current buffer, or even dripping the text like the movie The Matrix.

I couldn't wait to find out that emacsclient came with --eval as an option. This allows you to run lisp on your emacs server. Checkmate.
I created this script:
/tmp/zone
#!/bin/sh

emacsclient --no-wait $1
emacsclient -e '(with-current-buffer "'`basename $1`'" (zone))'
sleep 5

This script ran fine. But sometimes emacsclient blocked when you ran zone. This wasn't ideal. So I added this to the beginning to kill the emacsclient every time you run zone:
ps -ef | grep emacsclient | grep -v grep | awk '{print $2}' | xargs --no-run-if-empty kill -9
Finally, to get this to run over and over, just put zone in a while loop:

while true; do /tmp/zone /tmp/ascii-art-file; done;
Happy pranking!

Friday, July 8, 2011

Code Review and Pair Programming

I was recently reading comments on Slashdot

While most developers agree that code reviews are a good thing, the people that don't like code review seem to think of it as a matter of the developer's skill level. If you write good code, then you don't need code reviews.

I don't believe this is right. At a big giant newspaper, or even for a book publisher, there are professionals that are really good writers. But this doesn't stop the publishers from hiring editors to review what they are writing. This is an example of feedback that ensures a high quality product. Even in school you can always agree that any paper you write is a better quality if you have at least one person proofread it first. I know I've gotten A's from papers that went through this process.

At my current job we do pair programming. I was skeptical at first, but this process ensures that every line of code checked in has been reviewed by a peer. I know this is not for everyone. It's an extreme diversion from the school of thought that programmers are best left alone in a cave.

Not only is code review built into pair programming, but it almost feels like an apprenticeship to new hires. It helps get them up to speed a lot faster than the old way where the new developer would bang their heads on code and then come ask a bunch of whiny questions to the more experienced developers. And usually the more experienced developers always give an indication that they don't have time to answer questions. When you pair, asking questions is part of your job and the more experienced person encourages you to stop them and explain what they are working on.

The final thing I like about pair programming is that it actually focuses you better. Let's say you are by yourself and feeling tired. You might want to goof off and go on Facebook or surf the web. When you are pairing, the other developer can help pick up slack, or you might help them. This is especially helpful during the after-lunch food coma.