• 201702.01

    Debug comments (or how to save your sanity using git)

    A lot of times when I’m programming, I need to write a few lines of code that test what I’m working on. This can be a top-level function call, a few log entries, etc. Much to my dismay, I tended to end up with this debug code committed to git.

    I decided I wasn’t going to take it anymore.

    Git’s pre-commit hook to the rescue

    Now, whenever I add one of these lines, I mark it with a special comment:

    console.log('the value is: ', val);     // gee, sure hope i don't commit this

    becomes

    // DEBUG: remove this log entry
    console.log('the value is: ', val);

    Then in my pre-commit hook, I symlink a script that checks for DEBUG comments in various languages for that repo:

    #!/bin/sh
    
    DEBUG=""
    function add_to_debug {
    	filetype=$1
    	comment=$2
    
    	next=$(
    		git diff \
    			--cached \
    			--name-only \
    			-G"${comment}[ ]*DEBUG" \
    			-- "*.${filetype}"
    	)
    	DEBUG="${DEBUG}${next}"
    }
    
    add_to_debug 'js' '//'
    add_to_debug 'rs' '//'
    add_to_debug 'html' '<!--'
    add_to_debug 'lisp' ';'
    add_to_debug 'sh' '#'
    add_to_debug 'hbs' '{{!--'
    
    if [ "${DEBUG}" != "" ]; then
    	echo
    	echo "Please address the DEBUG comments in following files before committing:"
    	echo
    	echo "${DEBUG}" | sed 's/^/  /'
    	exit 1
    fi

    Using this, trying to commit any code that has DEBUG comments will fail with the output:

    Please address the DEBUG comments in following files before committing:
    
      user.js
    

    This forces going back in and cleaning up your code before committing it. Wicked.

    Get it yourself

    Grab the pre-commit hook off my Github to END THE SUFFERING and stop committing your debug code.

    Comments
  • 201402.02

    Access your Firefox extension/add-on variables from the browser console

    It can be nice to access your FF extension's variables/functions from the browser console (ctrl+shift+j) if you need some insight into its state.

    It took me a while to figure this out, so I'm sharing it. Somewhere in your extension, do:

    var chromewin = win_util.getMostRecentBrowserWindow();
    chromewin.my_extension_state = ...;
    

    Now in the browser console, you can access whatever variables you set in the global variable my_extension_state. In my case, I used it to assign a function that lets me evaluate code in the addon's background page. This lets me gain insight into the background page's variables and state straight from the browser console.

    Note! This is a security hole. Only enable this when debugging your extension/addon. Disable it when you release it.

    Comments
  • 201207.07

    cl-mongo and multithreading

    We're building a queuing system for Musio written in common lisp. To be accurate, we already built a queuing system in common lisp, and I recently needed to add a worker to it that communicates with MongoDB via cl-mongo. Each worker spawns four worker threads, each thread grabbing jobs from beanstalkd via cl-beanstalk. During my testing, each worker was updating a Mongo collection with some values scraped from our site. However, after a few seconds of processing jobs, the worker threads begin to spit out USOCKET errors and eventually Clozure CL enters it's debugger of death (ie, lisp's version of a segfault). SBCL didn't fare too much better, either.

    The way cl-mongo's connections work is that it has a global hash table that holds connections: cl-mongo::*mongo-registry*. When the threads are all running and communicating with MongoDB, they are using the same hash table without any inherent locking or synchronization. There are a few options to fix this. You can implement a connection pool that supports access from multiple threads (complicated), you can give each thread its own connection and force the each thread to use its connection when communicating, or you can take advantage of special variables in lisp (the easiest, simplest, and most elegant IMO). Let's check out the last option.

    Although it's not in the CL spec, just about all implementations allow you to have global thread-local variables by using (defparameter) or (defvar), both of which create special variables (read: dynamic variables, as opposed to lexical). Luckily, cl-mongo uses defvar to create *mongo-registry*. This means in our worker, we can re-bind this variable above the top level loop using (let) and all subsequent calls to MongoDB will use our new thread-local version of *mongo-registry* instead of the global one that all the threads we're bumping into each other using:

    ;; Main worker loop, using global *mongo-registry* (broken)
    (defun start-worker ()
      (loop
        (let ((job (get-job)))
          (let ((results (process-job job)))
            ;; this uses the global registry. not good if running multiple threads.
            (with-mongo-connection (:db "musio")
              (db.save "scraped" results))))))

    New version:

    ;; Replace *mongo-registry* above worker loop, creating a local version of the
    ;; registry for this thread.
    (defun start-worker ()
      ;; setting to any value via let will re-create the variable as a local thread
      ;; variable. nil will do just fine.
      (let ((cl-mongo::*mongo-registry* nil))
        (loop
          (let ((job (get-job)))
            (let ((results (process-job job)))
              ;; with-mongo-connection now uses the local registry, which stops the
              ;; threads from touching each other.
              (with-mongo-connection (:db "musio")
                (db.save "scraped" results)))))))
    

    BOOM everything works great after this change, and it was only a one line change. It may not be as efficient as connection pooling, but that's a lot more prone to strange errors and synchronization issues than just segregating the connections from each other and calling it a day. One issue: *mongo-registry* is not exported by cl-mongo, which is why we access it via cl-mongo::*mongo-registry* (notice the double colon instead of single). This means in future versions, the variable name may change, breaking our above code. So, don't update cl-mongo without testing. Not hard.

    Hopefully this helps a few people out, let me know if you have better solutions to this issue!

    Comments
  • 201104.15

    PHP finally has anonymous functions??

    Wow, I can't believe I missed this...nobody seems to be talking about it at all. Ever since PHP 5.3, I can finally do non-generic callbacks.

    UPDATE: Check out this description of PHP lambdas (much better than what I've done in the following).

     2 function do_something($value)
     3 {
     4     // used &gt;= 2 times, but only in this function, so no need for a global
     5     $local_function = function($value) { ... };
     6 
     7     // use our wonderful anonymous function
     8     $result = $local_function($value);
     9     ...
    10     // and again
    11     $result = $local_function($result);
    12     return $result;
    13 }
    

    There's also some other great stuff you can do:

    2 $favorite_songs = array(
    3     array('name' => 'hit me baby one more time', 'artist' => 'britney'),
    4     array('name' => 'genie in a bottle', 'artist' => 'xtina'),
    5     array('name' => 'last resort', 'artist' => 'papa roach')
    6 );
    7 $song_names = array_map(function($item) { return $item['name']; }, $favorite_songs);
    

    GnArLy bra. If PHP was 20 miles behind Lisp, it just caught up by about 30 feet. This has wonderful implications because there are a lot of functions that take a callback, and the only way to use them was to define a global function and send in an array() callback. Terrible. Inexcusable. Vomit-inducing.

    Not only can you now use anonymous functions for things like array_map() and preg_replace_callback(), you can define your own functions that take functions as arguments:

     2 function do_something_binary($fn_success, $fn_failed)
     3 {
     4     $success = ...
     5     if($success)
     6     {
     7         return $fn_success();
     8     }
     9     return $fn_failed();
    10 }
    11 
    12 do_something_binary(
    13     function() { echo "I successfully fucked a goat!"; },
    14     function() { echo "The goat got away..."; }
    15 );
    

    Sure, you could just return $success and call whichever function you need after that, but this is just a simple example. It can be very useful to encapsulate code and send it somewhere, this is just a demonstration of the beautiful new world that just opened for PHP.

    So drop your crap shared host (unless it has >= 5.3.0), get a VPS, and start using this wonderful new feature.

    Comments
  • 201011.16

    Vim: I can't believe I ignored you all these years

    All these years, since the day I first turned on a linux distribution, I've ignored vi/vim. Sure, there are swarms of geeks covering you with saliva as they spew fact after fact about how superior vim is to everything else, but to me it's always been "that editor that is on every system that I eventually replace with pico anyway."

    Not anymore. Starting a few years back, I've done all of my development in Eclipse. It has wonderful plugins for PHP, C++, Javascript, etc. The past week or so I've been weening myself off of it and diving into vim. What actually got me started is I bought a Droid 2 off ebay for various hacking projects (I'm planning on reviewing it soon). Well, it was really easy to get vim working in it (sorry, lost the link already). I thought, well, shit, I've got vim, what the hell can I do with it? First things first, let's get a plugin for syntax coloring/indentation for a few of my favorite languages. What?! It has all of them already.

    Ok, now I'm interested. I installed vim for Windows (gvim), which was followed by a slow-but-steady growing period of "well, how do I do this" and "HA...I bet vim can't do THI...oh, it can." There are "marks" for saving your place in code, you can open the same file in multiple views (aka "windows"), you can bind just about any key combination to run any command or set of commands, etc. I even discovered tonight there's a "windows" mode for vim that mimics how any normal editor works. I hate to admit it, but I'll be using that a lot. One feature that blew my mind is the undo tree. Not stack, tree. Make a change, undo, make a new change, and the first change you did before your undo is still accessible (:undolist)!

    The nice thing about vim is that it saves none of its settings. Every change you make to it while inside the editor is lost after a restart. This sounds aggravating, but it actually makes playing with the editor really fun and easy. If I open 30 windows and don't know how to close them, just restart the editor. There are literally hundreds of trillions of instances when I was like "oh, shit" *restart*.

    Once you have a good idea of what you want your environment to be like, you put all your startup commands in .vimrc (_vimrc on Windows) and vim runs it before it loads. Your settings file uses the same syntax as the commands you run inline in the editor, which is awesome and makes it easy to remember how to actually use vim.

    So far I'm extremely impressed. The makers of vim have literally thought of everything you could possibly want to do when coding. And if they haven't thought of it, someone else has and has written a plugin you can drop into your plugins directory and it "just works." Speaking of plugins, vim.org's plugin list seems neverending. I was half expecting to see most plugins have a final mod date of 2002 or something, but a good portion have newer version released within the past two weeks. It seems the ones that are from 2002 never get updated because they're mostly perfect. Excellent.

    I do miss a few things though. First off, the project file list most editors have on the left side. I installed NERDTree to alleviate that pain, but honestly it's not the same as having my right click menus and pretty icons. I'm slowly getting used to it though. The nice thing about a text-only file tree is that in those instances where you only have shell access and need to do some coding, there isn't a dependency on a GUI.

    Tabs are another thing I miss. Gvim has tabs, but they aren't one tab == one file (aka "buffer") like most editors. You can hack it to do this, sort of, but it works really jenky. Instead I'm using MiniBufExplorer, which takes away some of the pain. I actually hacked it a bit because I didn't like the way it displays the tabs, which gave me a chance to look at some real vim script. It's mostly readable to someone who's never touched it before.

    That about does it for my rant. Vim is fast, free, customizable, extendable, scriptable, portable, wonderful, etc...and I've barely scratched the surface.

    Comments
  • 200911.27

    Arrays: Some PHP tricks I never knew

    This will be a short post, but pretty cool.

    You can add arrays together:

    	$test1	=	array('name' => 'andrew');
    	$test2	=	array('status' => 'totally gnar, dude');
    	print_r($test1 + $test2);
    	---------------------------
    	Array
    	(
    	    [name] => andrew
    	    [status] => totally gnar, dude
    	)

    Wow...who would have thought. And my most recent favorite, converting objects to events. It's a simple foreach($object as $key => $val) and putting each element into a separate array right? WRONG:

    	$array	=	(array)$object;

    No fucking way. Casting actually works in this case. Why does nobody tell me anything?! This is great for parsing XML because any parser normally returns an object, and quite honestly, I hate dealing with objects. All database data is by default returned as an array usually,  and it's a pain having some data sources being objects while others are arrays. Now it doesn't matter...if you like objects, cast an associative array as an (object), if you like arrays cast with (array). I love PHP...

    Comments