Hopefully you'll remember our messy example from yesterday (here it is again just incase you don't):
{ H{ { "api_key" "YOUR_API_KEY_GOES_HERE" } { "per_page" 1 } } } "flickr.interestingness.getList" "http://www.flickr.com/services/xmlrpc/" invoke-method rpc-response-params 0 over nth nip string>xml "photo" tag-named* "http://farm" swap "farm" over at swap ".static.flickr.com/" swap "server" over at swap "/" swap "id" over at swap "_" swap "secret" over at swap ".jpg" swap drop append append append append append append append append
While this code actually works, it's near impossible to understand (unless you're a true genius like me!).
In reality this code is not doing that much, but there's a lot of flip flopping of things with the data stack, and trying to do it all in one line like this becomes something of a master SUDOKU puzzle. Sure it works, but good luck trying to debug it or expand it down the road!
So now let's take a look at my factored out version. Since we are going to define a number of words that we might want to reuse down the road, we'll now save the code in a file called "flickr.factor" (I'm putting mine directly in my Factor folder, but you can save your to whatever location you prefer).
USING: arrays kernel sequences xml xml.utilities xml-rpc namespaces assocs ;
: getsecret ( tag -- string )
"secret" over at swap drop ;
: getid ( tag -- string )
"id" over at swap drop ;
: getserver ( tag -- string )
"server" over at swap drop ;
: getfarm ( tag -- string )
"farm" over at swap drop ;
: buildurl ( tag -- string )
"http://farm" swap dup getfarm swap >r append r>
".static.flickr.com/" swap dup getserver swap >r append r>
"/" swap dup getid swap >r append r>
"_" swap getsecret append
".jpg" append 4array concat ;
: getphoto ( xml -- tag )
"photo" tag-named* ;
: interestingness-getlist ( per_page api_key -- string )
[ "api_key" set "api_key" get drop "per_page" set "per_page" get drop ]
H{ } make-assoc 1array
"flickr.interestingness.getList" "http://www.flickr.com/services/xmlrpc/" invoke-method
rpc-response-params 0 over nth nip string>xml ;
Once we've got that file created, we can now go back into our Listener, load it, and then use it with the following commands (keep in mind my path is where I saved flickr.factor, yours might be different - and yes today I'm working on a MAC):
"/Applications/Factor/flickr.factor" run-file
1 "MY_API_KEY" interestingness-getlist getphoto buildurl
Assuming you copied everything correctly (and you used a valid API_KEY) you should now have a URL on your stack that you can copy/past into a browser (just like our initial messy example!).
Best of all, this new version is a lot more simple to understand all the steps that are going on (and therefore it will be easier to maintain, upgrade, and reuse down the road if need be). Sure it was a little more typing, but the benefits of being readable and usable GREATLY outweighs the extra few keystrokes it took!
So now that it's a little easier to follow, let me go ahead and break down some of the more interesting things that are happening here.
1. The actual xml-rpc call to the flickr service is done in the interestingness-getlist word. Here we take our per_page and api_key values off the data stack and create an array which contains a Hash. Once we've built up the proper parameter details (in the proper structure) we use them along with the method and URL to invoke the XML-RPC service. Doing this returns a Tuple to us, hopefully with a rpc-response-params value (I need to update this to deal with rpc-faults). Then we simply pull out the xml from that Tuple as a string and convert it to proper xml.
2. We use the getphoto word to simply pull out the first child photo tag and we return it as an XML tag (if we wanted to get more than one photo at a time we could simply step through our rpc-response-params calling this word as many times as we needed)
3. Finally we call the buildurl word which simply pushes strings onto the datastack and calls various attributes of the photo tag as needed. In the end, we append all the strings on the stack into one larger string and we have our URL.
Simple, simple, right? OK it's true, I'm not doing anything too complex here and really getting the URL of an 'interesting' photo is next to worthless by itself. Still, as a small example it really seems to dive into a lot of the more subtle tips and tricks of working in Factor. I hope it reveals some of the core ideas of 'thinking in Factor', at least from a newbies point of view...
But I'll leave it to you to let me know what you think (and what we can do next to improve on this as a group of newbies)!



