<?xml version="1.0" encoding="utf-8"?>
<!-- If you are running a bot please visit this policy page outlining rules you must respect. http://www.livejournal.com/bots/ -->
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:lj="http://www.livejournal.com">
  <id>urn:lj:livejournal.com:atom1:kyle_burton</id>
  <title>Asymmetrical</title>
  <subtitle>Non Standard</subtitle>
  <author>
    <name>kyle_burton</name>
  </author>
  <link rel="alternate" type="text/html" href="http://kyle-burton.livejournal.com/"/>
  <link rel="self" type="text/xml" href="http://kyle-burton.livejournal.com/data/atom"/>
  <updated>2008-11-19T03:06:29Z</updated>
  <lj:journal userid="7841083" username="kyle_burton" type="personal"/>
  <link rel="service.feed" type="application/x.atom+xml" href="http://kyle-burton.livejournal.com/data/atom" title="Asymmetrical"/>
  <link rel="hub" href="http://pubsubhubbub.appspot.com/"/>
  <entry>
    <id>urn:lj:livejournal.com:atom1:kyle_burton:14970</id>
    <link rel="alternate" type="text/html" href="http://kyle-burton.livejournal.com/14970.html"/>
    <link rel="self" type="text/xml" href="http://kyle-burton.livejournal.com/data/atom/?itemid=14970"/>
    <title>List Comprehensions in Clojure</title>
    <published>2008-11-19T03:06:29Z</published>
    <updated>2008-11-19T03:06:29Z</updated>
    <category term="lisp clojure list-comprehensions jvm"/>
    <content type="html">&lt;p&gt;Just a quick example of list comprehensions in &lt;a href="http://clojure.org/"&gt;Clojure&lt;/a&gt;.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;
;; generate all the positions on a chess board:
(for [file "ABCDEFGH"
      rank (range 1 9)]
  (format "%c%d" file rank))
;; ("A1" "A2" "A3" "A4" "A5" "A6" "A7" "A8" 
;;  "B1" "B2" "B3" "B4" "B5" "B6" "B7" "B8" 
;;  "C1" "C2" "C3" "C4" "C5" "C6" "C7" "C8" 
;;  "D1" "D2" "D3" "D4" "D5" "D6" "D7" "D8" 
;;  "E1" "E2" "E3" "E4" "E5" "E6" "E7" "E8" 
;;  "F1" "F2" "F3" "F4" "F5" "F6" "F7" "F8" 
;;  "G1" "G2" "G3" "G4" "G5" "G6" "G7" "G8" 
;;  "H1" "H2" "H3" "H4" "H5" "H6" "H7" "H8")

(count  (for [file "ABCDEFGH"
              rank (range 1 9)]
          (format "%c%d" file rank)))
;;64

;; the pythagorean triples example:
(for [aa (range 1 10)
      bb (range 1 10)
      cc (range 1 10)
      :when (= (* cc cc)
               (+ (* aa aa)
                  (* bb bb)))]
  (list aa bb cc))
;; ((3 4 5) (4 3 5))

;; all permutations?
(defn all-permutations [things]
  (if (= 1 (count things))
    (list things)
    (for [head things
          tail (all-permutations (disj (set things) head))]
      (do
        (cons head tail)))))

(all-permutations '(a b c))
;; ((a c b) (a b c) (b a c) (b c a) (c a b) (c b a))

&lt;/pre&gt;</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:kyle_burton:14679</id>
    <link rel="alternate" type="text/html" href="http://kyle-burton.livejournal.com/14679.html"/>
    <link rel="self" type="text/xml" href="http://kyle-burton.livejournal.com/data/atom/?itemid=14679"/>
    <title>Cloud Con East Notes</title>
    <published>2008-10-21T15:30:25Z</published>
    <updated>2008-10-21T15:30:25Z</updated>
    <content type="html">Overall Computing Among The Clouds was a good conference.  &lt;br /&gt;&lt;br /&gt;The main theme I took away from it was that it is a continuing trend&lt;br /&gt;and services will continue to appear and be developed that will make&lt;br /&gt;taking advantage of these resource pools even easier.&lt;br /&gt;&lt;br /&gt;The trend for physical data centers will continue to become more and&lt;br /&gt;more outsourced to organizations that can provide those services with&lt;br /&gt;greater economy of scale.  Currently Amazon's offerings are slightly&lt;br /&gt;more expensive than a hosted system that you own.  More guidelines&lt;br /&gt;came out about when the trade off is appropriate.  Keep in mind that as&lt;br /&gt;a trend, cloud computing is still new - it is likely that these trade&lt;br /&gt;offs will shift - even as soon as over the next year or two (eg: it is&lt;br /&gt;likely, in my opinion, that the raw cost of 24x7 allocation will fall&lt;br /&gt;below the cost of ownership due to economies of scale - and I think&lt;br /&gt;this will happen by no longer than 3 years).&lt;br /&gt;&lt;br /&gt;Own your own:&lt;br /&gt;&lt;br /&gt; - you have a steady load&lt;br /&gt;&lt;br /&gt;   - AWS, used 24x7x365 is more expensive than owning and hosting&lt;br /&gt;     physical machine - though this does not include administrative&lt;br /&gt;     costs&lt;br /&gt;&lt;br /&gt; - you have hard SLA's&lt;br /&gt;&lt;br /&gt;   - you can not anticipate peak loads but must have spare capacity to&lt;br /&gt;     handle peaks&lt;br /&gt;&lt;br /&gt; - you have sensitive data that requires more certainty about where the&lt;br /&gt;   data gets stored, etc&lt;br /&gt;&lt;br /&gt;   - though there are cloud computing platforms that are working&lt;br /&gt;     towards security data data protection certifications&lt;br /&gt;&lt;br /&gt;Use an AWS style platform:&lt;br /&gt;&lt;br /&gt; - your needs scale up and then can scale back down&lt;br /&gt;&lt;br /&gt; - you can plan for these needs such that you have time to provision&lt;br /&gt;   the&lt;br /&gt;&lt;br /&gt; - you have no capitol budget&lt;br /&gt;&lt;br /&gt; - you have a service where you can charge in direct proportion to&lt;br /&gt;   utilization rather than based on capacity.&lt;br /&gt;&lt;br /&gt;Higher Level Application Stacks, like Google App Engine:&lt;br /&gt;&lt;br /&gt; - keep in mind these are new and the space is still being explored,&lt;br /&gt;   more will appear, a model will develop around these, more languages&lt;br /&gt;   and frameworks will be supported - though it mostly will be based&lt;br /&gt;   on those that can be easily hosted/sandboxed, which is why you're&lt;br /&gt;   seeing Python first and Java following along&lt;br /&gt;&lt;br /&gt; - all of the provisioning is hidden from you - Google's offering&lt;br /&gt;   dynamically scales your application up and down based on&lt;br /&gt;   utilization - this is a significant reduction in your design and&lt;br /&gt;   administrative workload&lt;br /&gt;&lt;br /&gt; - simplicity of application development _and_ scalability are rarely&lt;br /&gt;   found in existing technologies, this is one of the most compelling&lt;br /&gt;   aspects of these kinds of application stacks&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Organizations and individuals are starting to learn how they need to&lt;br /&gt;change the design of their services and applications to take better&lt;br /&gt;advantage of the Cloud.  It takes a bit of a change in mind-set - the&lt;br /&gt;phrase was dropped "Machine Instances are the new processes" and I&lt;br /&gt;think that's an appropriate framing of one of the changes in mindset&lt;br /&gt;you should have to take advantage of the sea of resources that is&lt;br /&gt;becoming available.&lt;br /&gt;&lt;br /&gt;Changing your software to be more easily bootstrapped, eliminate the&lt;br /&gt;assumption that you have access to local, disk based services -&lt;br /&gt;everything is pulled remotely, use URLs, and services - don't assume&lt;br /&gt;local interfaces, assume remote.  Design to come up / boot faster -&lt;br /&gt;scaling up / down quickly you don't get the same amortization over&lt;br /&gt;time for start up costs.  Design with the crash fast mentality - as&lt;br /&gt;robust as these systems are, you should still design with the idea in&lt;br /&gt;mind that the system could go away at a moment's notice -- in addition&lt;br /&gt;to the benefit to unexpected outages, this allows you to scale _down_&lt;br /&gt;faster.  Keep your persistent data in the provided data stores and&lt;br /&gt;use the provided queuing systems to distribute work.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;What these offerings need to do to gain wider acceptance and the the&lt;br /&gt;value-adds to come:&lt;br /&gt;--------------------------------------------------------&lt;br /&gt;&lt;br /&gt;I think that harder SLAs will develop as there is more competition.&lt;br /&gt;Higher level tools will develop on top of the instance-based cloud&lt;br /&gt;offerings (EC2) to allow for more automated provisioning - this will&lt;br /&gt;make it easier for you, but not so easy as for full restricted stacks&lt;br /&gt;like GAE.&lt;br /&gt;&lt;br /&gt;I think we'll see tools and offerings develop that will come down&lt;br /&gt;towards traditional data centers to allow a simpler mixing of a&lt;br /&gt;traditional service with bleed over to the cloud as resources need to&lt;br /&gt;be scaled up but also so that you can have control over the processing&lt;br /&gt;or data (sensitive data?) in your own protected environment but push&lt;br /&gt;generic activity up into the cloud as necessary.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Other notable happenings from the conference or that were recently&lt;br /&gt;announced:&lt;br /&gt;------------------------------------------------------------------&lt;br /&gt;&lt;br /&gt;- Microsoft is creating AMIs for Windows on EC2.&lt;br /&gt;&lt;br /&gt;- Google just announced that Java will be a supported App Engine&lt;br /&gt;  development language - previously only Python was supported.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Haskell in the corporate environment&lt;br /&gt;----------------------------------------&lt;br /&gt;&lt;br /&gt;Seemed out of place for the event - not really cloud-ish.  Though I&lt;br /&gt;personally see Functional Programming being a larger industry trend.&lt;br /&gt;It follows from structured -&amp;gt; procedural -&amp;gt; object oriented -&amp;gt;&lt;br /&gt;functional - with respect to the time line of coming out of academia at&lt;br /&gt;least, not necessarily the pejorative idea of one being 'higher level'&lt;br /&gt;than the other - though so far, time has implied that with the other&lt;br /&gt;patterns.&lt;br /&gt;&lt;br /&gt;The presenter (Jeff Polakow) is using it extensively at his current&lt;br /&gt;employer.&lt;br /&gt;&lt;br /&gt;Those kinds of firms (wall st) allow a lot of latitude to the&lt;br /&gt;technical staff, so its easier to experiment (R&amp;D) with new&lt;br /&gt;technologies.  It's much harder for a company like HMS to decide to&lt;br /&gt;take on something like this - it's hard to find developers, how to&lt;br /&gt;develop, deploy, monitor and design with these technologies is&lt;br /&gt;undetermined for companies like HMS.  &lt;br /&gt;&lt;br /&gt;I think the FP trend is being pushed into industry by the shift to&lt;br /&gt;multi-core, the past difficulties of developing concurrent,&lt;br /&gt;parallel/distributed applications (its hard and giving developers&lt;br /&gt;access to create threads directly has proven to be a difficult road&lt;br /&gt;to travel), the need for infrastructural level automatic scaling, and&lt;br /&gt;the easier path to robustness that languages like Erlang offer.&lt;br /&gt;&lt;br /&gt;In languages like Java, you have to take into consideration all the&lt;br /&gt;libraries you're using with respect to their referential transparency&lt;br /&gt;- it's not the default.  In the FP languages referential transparency&lt;br /&gt;is the _default_ case, so you can, in general, make that assumption.&lt;br /&gt;The underlying stack can also make that assumption about your code as&lt;br /&gt;well - which is why the concurrency / distribution model is less&lt;br /&gt;coupled to the implementation than it is in the more imperative&lt;br /&gt;languages.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Horizontal Scaling with HiveDB&lt;br /&gt;----------------------------------------&lt;br /&gt;&lt;br /&gt;CafePress has a _large_ catalog.  I was kind of shocked to hear that&lt;br /&gt;they have 265 million products.  They have a low margin based on the&lt;br /&gt;aggregate amount of data they have to store and serve up, so solutions&lt;br /&gt;like Oracle were just not an option for them simply from a cost basis.&lt;br /&gt;&lt;br /&gt;They spent time analyzing their options and didn't find anything that&lt;br /&gt;fit their needs (cost, performance, no off-line resharding), and&lt;br /&gt;created a more scalable data storage architecture.&lt;br /&gt;&lt;br /&gt;The solution they created performs better, scales better, is more&lt;br /&gt;robust and has a better SLA than many of the other commercial&lt;br /&gt;solutions.&lt;br /&gt;&lt;br /&gt;It is effectively a hibernate extension that uses MySQL and does data&lt;br /&gt;partitioning (pseudo-automatically) by using a set of replicated MySQL&lt;br /&gt;databases as a catalog to map to where the data is stored for your&lt;br /&gt;shard (replicated 3x).  The system supports dynamic repartitioning -&lt;br /&gt;migration of shards away from a shard-host to get less busy data away&lt;br /&gt;from data that is more 'hot' - the busiest data sets end up on their&lt;br /&gt;own shard-node with everything else having been pushed away from them.&lt;br /&gt;&lt;br /&gt;They only need to 'lock' the data for a single user's data when&lt;br /&gt;migrating it.  The system as a whole doesn't go down.  The MySQL&lt;br /&gt;catalogs are replicated (3 machines, master-master, writing to 1) and&lt;br /&gt;can be upgraded by taking 1 of the 3 out of the cluster.  The same&lt;br /&gt;kind of approach goes for the other sharing servers.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Panel Discussion&lt;br /&gt;----------------------------------------&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Hive and Hadoop&lt;br /&gt;----------------------------------------&lt;br /&gt;&lt;br /&gt;Hive is a data storage system built on top of Hadoop with its own&lt;br /&gt;query language (HiveQL), built by Facebook.  The goals are a bit&lt;br /&gt;different from HiveDB - HiveDB is more for OLTP, while Hive is more&lt;br /&gt;for large-scale analytics.  Being built on top of Hadoop, HiveDB is&lt;br /&gt;much more batch oriented.  Facebook uses it for doing analytics /&lt;br /&gt;data-mining / machine-learning of their user and transactional data&lt;br /&gt;sets (logs, user activities, etc.) to mine out aggregate and trending&lt;br /&gt;intelligence from the large data set.&lt;br /&gt;&lt;br /&gt;Surprising facts: 2Tb of growth _per_ _day_.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Building Scalable Web Applications with Google App Engine&lt;br /&gt;---------------------------------------------------------&lt;br /&gt;&lt;br /&gt;Stacks like GAE take a more managed environment approach than the more&lt;br /&gt;raw / primitive services provided by Amazon.  The two fit into&lt;br /&gt;different use cases though and, IMO, one will not necessarily supplant&lt;br /&gt;the other.&lt;br /&gt;&lt;br /&gt;GAE takes away from you all the concerns about deployment, production&lt;br /&gt;architecture, system management or administration.  It gives you a data&lt;br /&gt;store with an OO API, and a web-app development environment that you&lt;br /&gt;develop your application within.  There are things you can't do, for&lt;br /&gt;example, you can't run arbitrary software or services on GAE like you&lt;br /&gt;can on the more machine-image based cloud services (AWS EC2).&lt;br /&gt;&lt;br /&gt;What you gain from giving up those capabilities is: Google's&lt;br /&gt;infrastructure for scaling is _your_ infrastructure for scaling.  Your&lt;br /&gt;app is designed in a psuedo-functional way - the stack encourages you&lt;br /&gt;to design your app to perform all dynamism on put/post time and to&lt;br /&gt;just render/display at get time.  This approach helps with the scaling&lt;br /&gt;of the system.  Storage location transparency helps with spooling up&lt;br /&gt;other instances of the app in disparate data centers, etc.&lt;br /&gt;&lt;br /&gt;This kind of stack really makes it easy to develop the most common&lt;br /&gt;case of web applications - it is both easy to do and it scales.  This&lt;br /&gt;is a combination that almost _never_ get together.&lt;br /&gt;&lt;br /&gt;I see these kinds of stacks as becoming more established and a large&lt;br /&gt;part of Internet based application development - I think that more&lt;br /&gt;organizations will offer these kind of stacks across more&lt;br /&gt;technologies.&lt;br /&gt;&lt;br /&gt;You really should sign up and at least try GAE out.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Developing and Deploying Java applications on the Amazon Elastic Compute Cloud&lt;br /&gt;------------------------------------------------------------------------------&lt;br /&gt;&lt;br /&gt;Chris Richardson has created cloud-tools, a package of utilities (and&lt;br /&gt;a maven plug-in) for provisioning EC2 instances, pushing your&lt;br /&gt;application up and executing tasks across your cluster of instances.</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:kyle_burton:14446</id>
    <link rel="alternate" type="text/html" href="http://kyle-burton.livejournal.com/14446.html"/>
    <link rel="self" type="text/xml" href="http://kyle-burton.livejournal.com/data/atom/?itemid=14446"/>
    <title>destructuring-bind</title>
    <published>2008-09-18T12:29:34Z</published>
    <updated>2008-09-18T12:29:34Z</updated>
    <category term="lisp"/>
    <content type="html">&lt;pre&gt;
;; This is a typical usage, for pulling apart a list                                                                         
(destructuring-bind
      (first second)
    '(1 2)
  (format t "~%~%;;; =&amp;gt; first:~a second:~a~&amp;" first second))

;;; =&amp;gt; first:1 second:2                                                                                                      

;; You can also pull apart improper lists:                                                                                   
(destructuring-bind
      (first . second)
    '(1 . 2)
  (format t "~%~%;;; =&amp;gt; first:~a second:~a~&amp;" first second))

;;; =&amp;gt; first:1 second:2                                                                                                      

;; The first argument to destructuring-bind is a lambda list, but you                                                        
;; can grab the remainder by either using a dotted list:                                                                     

(destructuring-bind
      (first second . stuff)
    '(1 2 3 4 5)
  (format t "~%~%;;; =&amp;gt; first:~a second:~a rest:~a~&amp;" first second stuff))

;;; =&amp;gt; first:1 second:2 rest:(3 4 5)                                                                                         

;; or you can grab the remainder with &amp;rest, just like you do for                                                            
;; functions that take a variable number of arguments:                                                                       
(destructuring-bind
      (first second &amp;rest stuff)
    '(1 2 3 4 5)
  (format t "~%~%;;; =&amp;gt; first:~a second:~a rest:~a~&amp;" first second stuff))

;;; =&amp;gt; first:1 second:2 rest:(3 4 5)                                                                                         

;; It really is a lambda list, you can use default parameters:                                                               
(destructuring-bind
      (first second &amp;optional (third 'default))
    '(1 2)
  (format t "~%~%;;; =&amp;gt; first:~a second:~a third:~a~&amp;" first second third))

;;; =&amp;gt; first:1 second:2 third:DEFAULT                                                                                        

(destructuring-bind
      (first second &amp;optional (third 'default))
    '(1 2 3)
  (format t "~%~%;;; =&amp;gt; first:~a second:~a third:~a~&amp;" first second third))

;;; =&amp;gt; first:1 second:2 third:3                                                                                              


;; And you can use keyword parameters:                                                                                       
(destructuring-bind
      (first second &amp;key third)
    '(1 2 :third 3)
  (format t "~%~%;;; =&amp;gt; first:~a second:~a third:~a~&amp;" first second third))

;;; =&amp;gt; first:1 second:2 third:3                                                                                              




;; Finally, you can use it to 'unparse' trees as well, which is a                                                            
;; really great feature, since your variable declaration matches the                                                         
;; 'shape' of the data strucutre you're pulling apart.  This technique                                                       
;; is really handy for dealing with XML after it's been converted to                                                         
;; s-expressions.                                                                                                            
(destructuring-bind
      (a (b (c d e (f g) h i j)) &amp;rest remainder)
    '(1 (2 (3 4 5 (6 7) 8 9 10)) 11 12 13 14 15)
  (format t
          "~%~%;;; =&amp;gt; a:~a b:~a c:~a d:~a e:~a f:~a g:~a h:~a i:~a j:~a remainder:~a ~&amp;"
          a b c d e f g h i j remainder))

;;; =&amp;gt; a:1 b:2 c:3 d:4 e:5 f:6 g:7 h:8 i:9 j:10 remainder:(11 12 13 14 15)                                                   



&lt;/pre&gt;</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:kyle_burton:14202</id>
    <link rel="alternate" type="text/html" href="http://kyle-burton.livejournal.com/14202.html"/>
    <link rel="self" type="text/xml" href="http://kyle-burton.livejournal.com/data/atom/?itemid=14202"/>
    <title>Bring me Data!  Landmark Parsing in CL</title>
    <published>2008-08-16T05:02:11Z</published>
    <updated>2008-08-16T05:02:25Z</updated>
    <category term="lisp common-lisp"/>
    <content type="html">&lt;pre&gt;
(require :drakma)
(require :landmark-parser)

(use-package :landmark-parser)

(defvar *doc* (drakma:http-request "http://www.loc.gov/standards/iso639-2/php/code_list.php"))

(defun get-main-table (doc)
  (extract-between
   (new-parser doc)
   '((forward-past "&amp;lt;table ")
     (forward-past "&amp;lt;table ")
     (forward-past "&amp;lt;tr")
     (forward-to "&amp;lt;tr"))
   '((forward-to "&amp;lt;/table"))))
                      
(defun get-rows (block)
    (extract-all (new-parser block)
                 '((forward-to "&amp;lt;tr"))
                 '((forward-past "&amp;lt;/tr&amp;gt;"))))
                                   
(defun row-&amp;gt;cells (row)                                                                                                   
  (extract-all (new-parser row)    
               '((forward-past "&amp;lt;td")
                 (forward-past "&amp;gt;"))
               '((forward-to "&amp;lt;/td&amp;gt;"))))

(with-open-file (out "/home/mortis/iso.tab"
                     :direction :output
                     :if-exists :supersede)
  (loop for row in (mapcar #'row-&amp;gt;cells (get-rows (get-main-table *doc*)))                                                
     do
       (format out "~{~a~^      ~}~&amp;" row)))

&lt;/pre&gt;

&lt;p&gt;
I just uploaded the &lt;a href="http://asymmetrical-view.com/personal/code/lisp/landmark-parser/src/cl/landmark-parser.lisp"&gt;Landmark Parser&lt;/a&gt; tonight.
&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:kyle_burton:13937</id>
    <link rel="alternate" type="text/html" href="http://kyle-burton.livejournal.com/13937.html"/>
    <link rel="self" type="text/xml" href="http://kyle-burton.livejournal.com/data/atom/?itemid=13937"/>
    <title>OSCon Day 1</title>
    <published>2008-07-22T05:57:53Z</published>
    <updated>2008-07-22T05:57:53Z</updated>
    <content type="html">Andrew and I arrived for registration and took advantage of the&lt;br /&gt;continental breakfast before heading up to the Intro to Python.&lt;br /&gt;&lt;br /&gt;O'Reilly had the registration process pretty streamlined.  They had a&lt;br /&gt;long bank of laptops wich you needed only enter your registration&lt;br /&gt;code, or your email address (if you registered on the oscon conference&lt;br /&gt;web site).  Register, then walk up to the materials station and pick&lt;br /&gt;up your ID and badge card.&lt;br /&gt;&lt;br /&gt;There were plenty of juices, coffee, fruit and pastries.  There was&lt;br /&gt;also plenty of seating.  To either O'Reilly's or the Oregon Conference&lt;br /&gt;Center's credit, things were very well organized.&lt;br /&gt;&lt;br /&gt;The conference room we were must have had seating for a few hundred&lt;br /&gt;people and it was effectively full.  There was limited space for each&lt;br /&gt;attendee and their items (it was at least cramped for me) - though&lt;br /&gt;they expected a laptop per attendee - there were plenty of power&lt;br /&gt;strips, laid along every other row of tables, within easy reach of&lt;br /&gt;every single seat.  It was well planned and laid out.&lt;br /&gt;&lt;br /&gt;The intro to Python got underway at 8:30 and although it was geared&lt;br /&gt;toward an audience with some programming experience, it assumed (as&lt;br /&gt;the title suggested) no python experience.  Steve Holden was a great&lt;br /&gt;speaker, filling in twice with anecdotes while technical issues were&lt;br /&gt;worked out with equipment (once was a mis configuration of his laptop,&lt;br /&gt;the other was a power interruption).&lt;br /&gt;&lt;br /&gt;Python is a very capable language.  It is more consistent about its&lt;br /&gt;OO and syntax when compared to Perl.  It is also a lot bigger on&lt;br /&gt;conventions, broadly adopted by the community.  This is mostly focused&lt;br /&gt;on formatting (one expression per line), in-line documentation and&lt;br /&gt;coding stle in general.&lt;br /&gt;&lt;br /&gt;Functions are first class types, you can take a function into a&lt;br /&gt;variable, you can implement the equivalent of funcall and apply in&lt;br /&gt;python.  Functions can be passed as arguments.  Python supports&lt;br /&gt;positional parameters, default values for function params and calling&lt;br /&gt;functions, any function, with positional arguments, named arguments, a&lt;br /&gt;tuple of arguments (similar to funcall), or a dictionary (an indirect&lt;br /&gt;way of using named arguments).&lt;br /&gt;&lt;br /&gt;Python actually has a lot of features which were inspired by&lt;br /&gt;functional programming (including list comprehensions).&lt;br /&gt;&lt;br /&gt;Python is byte-compiled, like Java.  You write code in a .py file, and&lt;br /&gt;the first time it is loaded as a module (import), python compiles the&lt;br /&gt;code for you.  The time stamp check fo the .pyc vs the .py file is&lt;br /&gt;transparent, it's automatically handled.&lt;br /&gt;&lt;br /&gt;Strings are immutable, which is something that helps Jython be a&lt;br /&gt;natural fit in the JVM.&lt;br /&gt;&lt;br /&gt;Python supports some destructuring constructs, based in what it calls&lt;br /&gt;tuples.  It's easier to show an example:&lt;br /&gt;&lt;br /&gt;  a, (b, c) = (1, (2, 3))&lt;br /&gt;&lt;br /&gt;  print a,b,c =&amp;gt; 1, 2, 3&lt;br /&gt;&lt;br /&gt;Tuples, and this kind of binding syntax, is widely used in processing&lt;br /&gt;things like lists, and maps.&lt;br /&gt;&lt;br /&gt;An interesting feature of the language is the pair of functions,&lt;br /&gt;local() and gobal().  local() returns a dictionary (Python's name for&lt;br /&gt;a Map), of all of the variable bindings (and values) that are visible&lt;br /&gt;in the current scope (exclusive of global variables).  globals()&lt;br /&gt;returns the variables in the entire module's scope (not local, lexical&lt;br /&gt;or class scope, and not global in the sense of a Perl global - not&lt;br /&gt;universally global).&lt;br /&gt;&lt;br /&gt;Other highlights:&lt;br /&gt;&lt;br /&gt; - the yield() form, which is like a weak kind of continuation&lt;br /&gt; - for, and while loops can have an else clause, which is executed&lt;br /&gt;    when the form terminates normally (as opposed to breaking out&lt;br /&gt;    of the loop)&lt;br /&gt; - the Python try/catch form (try/except/finally) can have an else&lt;br /&gt;    form, again, which is executed if no exception was thrown in&lt;br /&gt;    the try block&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;After a break for lunch, both Andrew and I attended the Introduction&lt;br /&gt;to Django, presented by Jacob Kaplan-Moss.&lt;br /&gt;&lt;br /&gt;Django is an MVC framework for Python for rapid development of&lt;br /&gt;interactive web sites.  It is an MVC framework very much in the spirit&lt;br /&gt;of Ruby on Rails - I've done a small site in Rails and the parallels&lt;br /&gt;were very close between the two frameworks.&lt;br /&gt;&lt;br /&gt;Django has a code generation framework, an ORM layer (which is very&lt;br /&gt;similar to Rails' ActiveRecord), an html template system (with a&lt;br /&gt;default syntax based on PHPs smarty template system), and integrated&lt;br /&gt;support for testing.  &lt;br /&gt;&lt;br /&gt;Django has an interesting testing feature called doctests.  If you've&lt;br /&gt;worked with an interactive language with a REPL, you have probably&lt;br /&gt;used it to explore the behavior of code and to informally test the&lt;br /&gt;code.  Doctests are a way of (almost literally) taking a cut and paste&lt;br /&gt;of the interactive session and vivifying the transcript as a&lt;br /&gt;regression test.  I like the idea of a recorded test, but as Andrew&lt;br /&gt;and I talked about it, he convinced me that the literal representation&lt;br /&gt;wasn't all that great a choice for implementing those kinds of tests.&lt;br /&gt;I do like the reduction of effort that comes with that kind of&lt;br /&gt;testing, and recognize the inherent informality of it.&lt;br /&gt;&lt;br /&gt;All that said, Django (like Rails) is big on doing test driven&lt;br /&gt;development.  &lt;br /&gt;&lt;br /&gt;I looked up the status of Django on Jython and apparently it's close&lt;br /&gt;to being a 1.0 release (nothing I'd recommend for use at HMS at the&lt;br /&gt;moment, but Sun has hired people to work on Jython and Django is one&lt;br /&gt;of the frameworks they are concerned with making work).&lt;br /&gt;&lt;br /&gt;I'm looking forward to tomorrow.</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:kyle_burton:13706</id>
    <link rel="alternate" type="text/html" href="http://kyle-burton.livejournal.com/13706.html"/>
    <link rel="self" type="text/xml" href="http://kyle-burton.livejournal.com/data/atom/?itemid=13706"/>
    <title>Sending a signal...</title>
    <published>2008-07-20T15:27:09Z</published>
    <updated>2008-07-20T15:27:09Z</updated>
    <category term="introspection"/>
    <content type="html">Something has come up recently that has forced me to think about and&lt;br /&gt;articulate the difference in how I perceive occasional cigar smoking&lt;br /&gt;and the habit of cigarette smoking.&lt;br /&gt;&lt;br /&gt;This is within the context of having kids and having to be in the&lt;br /&gt;position of having to be the arbitrator of what they're exposed to.&lt;br /&gt;Capable or not I am one of the people who must lead them though&lt;br /&gt;experiencing the world.  The end goals being to get them to be able to&lt;br /&gt;operate independently, handle whatever the world throws at them and be&lt;br /&gt;able to help others.&lt;br /&gt;&lt;br /&gt;The difference, I've recently come to realize is: it's the signal that&lt;br /&gt;each one sends.&lt;br /&gt;&lt;br /&gt;Seeing a person decide to smoke a cigar at the end of the day, after&lt;br /&gt;most activity is over sends a certain signal.  It is something which&lt;br /&gt;is done out of the context of normal daily activity.  It is something&lt;br /&gt;that can wait, it can be delayed, it is optional.&lt;br /&gt;&lt;br /&gt;Seeing a person stop all activity to step outside to take themselves&lt;br /&gt;away to smoke a cigarette sends a signal.  A kid will see this adult&lt;br /&gt;decide that what they are about to do is more important than playing&lt;br /&gt;another game, more important than starting on desert, than watching&lt;br /&gt;the movie, than being with the kid for those five minutes.&lt;br /&gt;&lt;br /&gt;The cigarette smoker is compelled to smoke, while the (typical) cigar&lt;br /&gt;smoker is not.&lt;br /&gt;&lt;br /&gt;Kids pick up on what is important to the adults in their lives, its a&lt;br /&gt;necessary part of how they learn about the world.  The compulsory&lt;br /&gt;behavioral traits that I exhibit in front of my kids seem to be the&lt;br /&gt;things which are most influential.  I can tell them that brushing&lt;br /&gt;their teeth is good for them, but unless they see me do it,&lt;br /&gt;consistently, no amount of saying it to them causes the value to&lt;br /&gt;transfer.  At least not at about 5 years of age.&lt;br /&gt;&lt;br /&gt;I've become more and more aware of the signal that I send in a lot of&lt;br /&gt;contexts.  Having children has made many of these signals much more&lt;br /&gt;apparent.</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:kyle_burton:13524</id>
    <link rel="alternate" type="text/html" href="http://kyle-burton.livejournal.com/13524.html"/>
    <link rel="self" type="text/xml" href="http://kyle-burton.livejournal.com/data/atom/?itemid=13524"/>
    <title>Idempotency or Singleton Memoization</title>
    <published>2008-06-18T13:17:46Z</published>
    <updated>2008-06-18T13:17:46Z</updated>
    <category term="perl programming functional-programming"/>
    <content type="html">&lt;pre&gt;
sub makeDoOnce {
  my($sub) = @_;
  my $alreadyDone = undef;
  my @result      = undef;
  my $exception   = undef;
  return sub {
    die $exception if $exception;
    if ($alreadyDone) {return wantarray ? @result : $result[0];}

    eval {
      my $w = wantarray;
      if (not defined $w) {             $sub-&amp;gt;(@_)}
      if ($w)             {@result    = $sub-&amp;gt;(@_)}
      else                {$result[0] = $sub-&amp;gt;(@_)}
    };
    $exception = $@ if $@;
    die $exception if $exception;
    $alreadyDone = 1;
    return wantarray ? @result : $result[0];
  };
}
&lt;/pre&gt;</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:kyle_burton:13308</id>
    <link rel="alternate" type="text/html" href="http://kyle-burton.livejournal.com/13308.html"/>
    <link rel="self" type="text/xml" href="http://kyle-burton.livejournal.com/data/atom/?itemid=13308"/>
    <title>The same and yet different</title>
    <published>2008-06-07T13:39:06Z</published>
    <updated>2008-06-07T13:39:06Z</updated>
    <category term="perl python programming"/>
    <content type="html">&lt;p&gt; I've just opened the book &lt;a href="http://www.diveintopython.org/"&gt;Dive into Python by Mark
Pilgrim&lt;/a&gt;.  The first example is a function that creates a
(database?) connection string.  Knowing &lt;a href="http://www.perl.org/"&gt;Perl&lt;/a&gt;, I wrote a close equivalent so I
could look at the differences.  &lt;/p&gt;

&lt;p&gt;
First, the Python:&lt;/p&gt;

&lt;pre&gt;
def buildConnectionString(params):
    """Build a connection string from a dictionary of parameters.

    Returns string."""

    return ";".join(["%s=%s" % (k,v) for k,v in params.items()])

if "__main__" == __name__:
    print buildConnectionString({
            "server":"localhost",
            "database":"master",
            "uid":"sa",
            "pwd":"sekret"
            })
&lt;/pre&gt;

&lt;p&gt; Ok, defines a function of one parameter (buildConnectionString) -
and that parameter is called out in the signature.  This leads me to
suspect that &lt;a href="http://python.org/"&gt;Python&lt;/a&gt; may actually know
that the function takes a single argument (though not it's type), and
that information may be available to the runtime (this is the kind of
thing that helps IDEs and other software tools). &lt;/p&gt;

&lt;p&gt; Within that function we can provide a &lt;a href="http://en.wikipedia.org/wiki/Docstring"&gt;docstring&lt;/a&gt;.  This is
something I'm familiar with from &lt;a href="http://common-lisp.net/"&gt;Common Lisp&lt;/a&gt; and it's a feature that
I like.  I suspect that I'll find that this is available in the Python
runtime later on...&lt;/p&gt;

&lt;p&gt; Then Mr. Pilgrim immediately indoctrinates us to Python's &lt;a href="http://en.wikipedia.org/wiki/List_comprehension"&gt;list
comprehensions&lt;/a&gt;.  Good.  We can see that literal strings have
methods (we're calling .join on the literal ";"), so they're an object
(in Perl strings are not).  I'm not sure what params.items() returns
yet - a flat list?  A set of pairs?  I'm sure this is waiting for me
on the next few pages.&lt;/p&gt;

&lt;p&gt; Ok, this is a simple enough task, and the code is nice and
succinct.  The list comprehension makes the task clear (at least to
me).  What does the equivalent Perl look like? (well, my equivalent
Perl, this is _my_ way of doing it, &lt;a href="http://en.wikipedia.org/wiki/There&amp;#39;s_more_than_one_way_to_do_it"&gt;TIMTOWTDI&lt;/a&gt;
after all).&lt;/p&gt;

&lt;pre&gt;
use strict;
use warnings;

=head2 buildConnectionString                                                                                                 
                                                                                                                             
Build a connection string from a dictionary of parameters.                                                                   
                                                                                                                             
Returns string.                                                                                                              
                                                                                                                             
=cut                                                                                                                         
                                                                                                                             
sub buildConnectionString {
    my($params) = @_;
    return join(";",map { "$_=$params-&amp;gt;{$_}" } keys %$params);
}

if (__PACKAGE__ eq "main") {
    print buildConnectionString({
        "server"   =&amp;gt; "localhost",
        "database" =&amp;gt; "master",
        "uid"      =&amp;gt; "sa",
        "pwd"      =&amp;gt; "sekret"
        }),"\n";
}
&lt;/pre&gt;

&lt;p&gt; Ok, right off, I won't write Perl without the &lt;a href="http://perldoc.perl.org/strict.html"&gt;'use strict;'&lt;/a&gt; and &lt;a href="http://perldoc.perl.org/warnings.html"&gt;'use warnings;'&lt;/a&gt; &lt;a href="http://perldoc.perl.org/index-pragmas.html"&gt;pragmas&lt;/a&gt; since
they are big time savers.  The first way in which they save time is
that they help identify errors at compile-time that would otherwise be
caught at run-time, and they point out conditions that you likely
weren't handling (like using the contents of a variable before
assigning to it).&lt;/p&gt;

&lt;p&gt; Then there is the external documentation.  My team has adopted the
javadoc-like habit of making the api documentation in-line with the
code.  The difference here though is that there is no formal
relationship between the &lt;a href="http://perldoc.perl.org/perlpod.html"&gt;POD&lt;/a&gt; and the function
itself - unlike in the Python docstring (and in Javadoc, where
adjacency is an implicit relationship).  This means that the Perl
documentation can't be (easily) the same kind of runtime value-add as
the Python docstring (go Lisp).&lt;/p&gt;

&lt;p&gt; The next thing is the function signature, or rather lack of, in
the Perl function.  Again, my team has adopted the convention of using
a single line to do function argument destructuring - that way the
first line of our functions is at least representationally equivalent
to a signature.  This makes our Perl applications a lot easier to read
and maintain.  Of course there are some cases (at least in Perl) when
it can be useful to slightly modify the argument list, replace your
function call with some other and pretend like the first never
happened, though I'm not going into that right now.  The main
difference is that our convention isn't a formal part of the language,
while in Python it is - and may additionally be a value-add at runtime
(I'm sure I'll find out later, again, this is the kind of thing that
helps IDEs and tools).&lt;/p&gt;

&lt;p&gt; As far as the actual implementation, there is little logical or
semantic difference between Perl's join/map and Python's
join/list-comprehension.  Perl's join is not a method.  Neither uses
an iterator off of the collection (as &lt;a href="http://www.ruby-lang.org/en/"&gt;Ruby&lt;/a&gt; would), but both apply an
operation to every (logical) item in a set (in the Python case it's a
pair, though as I said I'm not sure how the &lt;a href="http://www.lisp.org/HyperSpec/Body/mac_destructuring-bind.html"&gt;destructuring&lt;/a&gt;
happens yet).&lt;/p&gt;

&lt;p&gt; There are other smallish differences too, I could have used Perl's
sprintf, which would have more closely aligned with Python's implicit formatter:&lt;/p&gt;

&lt;pre&gt;
sub buildConnectionString {
    my($params) = @_;
    return join(";",map { sprintf "%s=%s", $_, $params-&amp;gt;{$_} } keys %$params);
}
&lt;/pre&gt;

&lt;p&gt; But either language is more than capable.  With the overloading of
curly braces, even with my 10+ years of Perl experience, it's still a
bit fuzzy to my eyes where the break is between the end of the
hash-table (which is a map) and the code-block for the map.  It's not
that I can't read that code, or read it quickly, the dual meaning of
the curly braces means that I have to use grammatical cues rather than
just syntactic ones.&lt;/p&gt;

&lt;p&gt; This is less than a first impression mind you.  I'm trying hard to
stay out of the &lt;a href="http://en.wikipedia.org/wiki/Turing_tarpit"&gt;Turing Tar pit&lt;/a&gt;.
I like the list comprehensions and I like that Mr. Pilgrim introduced
them right away in the book.  I'm looking forward to the rest of
it.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:kyle_burton:12968</id>
    <link rel="alternate" type="text/html" href="http://kyle-burton.livejournal.com/12968.html"/>
    <link rel="self" type="text/xml" href="http://kyle-burton.livejournal.com/data/atom/?itemid=12968"/>
    <title>The difference between requirements and code.</title>
    <published>2008-05-19T02:14:59Z</published>
    <updated>2008-05-19T02:14:59Z</updated>
    <content type="html">&lt;p&gt;
Programmers tend to know this without questioning it and often without
being able to describe why: you can't reverse engineer requirements
from code.  This idea seems to be irresistibly seductive to
non-developers though.  
&lt;/p&gt;

&lt;p&gt;
Requirements are, at their heart, declarative.  Code is imperative.
Well I suppose that depends and I'll come back to this topic later.  A
program is one possible solution to the requirement, one possible
implementation.  It is not the requirement.
&lt;/p&gt;

&lt;p&gt;
Requirements declare "clean the car".  Code says "Get a bucket.  Get
the car wash soap.  Get rags.  Get the hose.  Turn on the hose.  Fill
the bucket." and so on.  It could also have said "Drive to the car
wash".  Of course those instructions aren't necessary if the car isn't
dirty (but you can't tell that from the instructions).  They also
could have meant "Wash the dog" or "Make lots of bubbles".  If you
didn't already have it in your head that the intent was to wash a car
you'd probably be lost.  Worse, you'd be lucky to figure out what it
meant.
&lt;/p&gt;

&lt;p&gt;
And what are the chances that there is a bug in the code?  That bug
would leave you with an error in your requirement.  What if the
instructions in the code are working around limitations in the
programming language?  What about the OS?  The network?  The database?
What if....what if the program is working around errors in the data,
which were introduced by some other application?  What if it's a
legacy version of the program itself?
&lt;/p&gt;

&lt;p&gt;
You can use code as a clue though, as a guide.  If you know what the
goal probably was you can use the code as a way to try to disprove
your hunch.
&lt;/p&gt;

&lt;p&gt;
You can't reverse engineer requirements from code - you'll never hit
the spirit or the meaning of the original requirements.  You can
certainly use the existing code to produce requirements for a system
that re-implements the code itself (including workarounds, bugs and
all), but you'll never produce the intent or core need that caused the
application to be created in the first place.  Not from looking at the
code alone.
&lt;/p&gt;

&lt;p&gt;
So, what about the earlier supposition?  When you use non-imperative
approaches to implement requirements what you end up with is a
declarative (or functional) statement of...the requirements.  They are
stated in a more formal manner certainly, but they will be a statement
of the requirements nonetheless.  
&lt;/p&gt;

&lt;p&gt;
This a core reason DSLs and XML configurations are often good
solutions.  SQL is successful because it allows you to say what you
want, not how to get it from some internal, vendor specific, database
API.
&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:kyle_burton:12613</id>
    <link rel="alternate" type="text/html" href="http://kyle-burton.livejournal.com/12613.html"/>
    <link rel="self" type="text/xml" href="http://kyle-burton.livejournal.com/data/atom/?itemid=12613"/>
    <title>Compile Time Evaluation, w/o Macros</title>
    <published>2008-04-28T21:58:15Z</published>
    <updated>2008-04-28T21:58:15Z</updated>
    <category term="lisp"/>
    <content type="html">&lt;p&gt; We all have constants in our applications, sometimes we have&lt;br /&gt;numeric values that are only used once and are clearer if they're left&lt;br /&gt;as an expression (like the number of seconds in a day, well these&lt;br /&gt;things are better off as constants in many cases, though I'm only&lt;br /&gt;using it as an example). &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;
(defun days-&amp;gt;seconds (days)
  (* days (* 24 60 60)))

(format t "seconds in ~a days:~a~&amp;" 1 (days-&amp;gt;seconds 1))

(time (loop repeat 1000000
	    do (days-&amp;gt;seconds 10)))
 =&amp;gt; 2.093 sec.
&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt; In common lisp there is a reader macro you can use to have these&lt;br /&gt;kinds of expressions executed at compile time - and thus use no CPU&lt;br /&gt;time during your running application (or even within the compiled&lt;br /&gt;executable): &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;
(defun compile-time-days-&amp;gt;seconds (days)
  (* days #.(* 24 60 60)))

(time (loop repeat 1000000
	    do (compile-time-days-&amp;gt;seconds 10)))
 =&amp;gt; 1.87s
&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt; Admittedly in this case it's not a worthwhile improvement in&lt;br /&gt;performance - but these are the kinds of things many technologies&lt;br /&gt;represent as build processes.  When you're configuring a build to be&lt;br /&gt;specialized for a locale, or particular production environment, you&lt;br /&gt;either factor those parts of the application into a configuration&lt;br /&gt;file, or you generate code (almost certainly with some tool set which is&lt;br /&gt;not your programming language). &lt;/p&gt;</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:kyle_burton:12440</id>
    <link rel="alternate" type="text/html" href="http://kyle-burton.livejournal.com/12440.html"/>
    <link rel="self" type="text/xml" href="http://kyle-burton.livejournal.com/data/atom/?itemid=12440"/>
    <title>Updated Lisp Presentation Slides</title>
    <published>2008-04-28T17:59:40Z</published>
    <updated>2008-04-28T17:59:40Z</updated>
    <category term="lisp"/>
    <content type="html">&lt;p&gt;I took the "make the title of your presentation confrontational" advice and changed the title from "Introduction to Lisp" to &lt;a href="http://asymmetrical-view.com/talks/lisp-presentation/lisp-presentation.pdf"&gt;"Why Won't Lisp Just Go Away?"&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It went much more smoothly the second time around.  I also got some good feedback from &lt;a href="http://www.innovationontherun.com/"&gt;Rob DiMarco&lt;/a&gt; and &lt;a href="http://www.jpsdomain.org/"&gt;JP Vossen&lt;/a&gt; (author of the &lt;a href="http://www.oreilly.com/catalog/9780596526788/"&gt;Bash Cookbook&lt;/a&gt;).  It has been difficult to come up with a 60-90 minute talk, keeping it short enough, while still talking up the strong points.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:kyle_burton:12071</id>
    <link rel="alternate" type="text/html" href="http://kyle-burton.livejournal.com/12071.html"/>
    <link rel="self" type="text/xml" href="http://kyle-burton.livejournal.com/data/atom/?itemid=12071"/>
    <title>Data Analysis in the [Unix] shell</title>
    <published>2008-04-28T15:52:50Z</published>
    <updated>2008-04-28T15:52:50Z</updated>
    <content type="html">&lt;p&gt;I often prefer the shell and Unix utilities to having to wait to
load data into a relational database or MS Access (unless a lot of
what I'm doing requires complex joins).  It's often possible to not
even have to transform the encoding of the files before analyzing
them.  There are a couple of recipes for doing SQL equivalents with
the shell utilities.  There are a bunch of them, these are a few that
I just used this morning.  Most of the time all it takes is a bit of
imagination about how to create a simple data-flow by composing a
small handful of ubiquitous Unix utilities.&lt;/p&gt;

&lt;p&gt;All these examples will also work within
the &lt;a href="http://www.cygwin.com/"&gt;Cygwin&lt;/a&gt; environment for
Windows, or at a Terminal in OS X (especially when combined with the
additional software available
via &lt;a href="http://www.finkproject.org/"&gt;Fink&lt;/a&gt;
or &lt;a href="http://www.macports.org/"&gt;Mac Ports&lt;/a&gt; projects..
&lt;/p&gt;

&lt;b&gt;"SELECT COUNT(*) FROM TABLE"&lt;/b&gt;

&lt;p&gt;
Just selecting the count of records from an input file is one of the
easiest things to accomplish (if your file is already line-oriented).
The &lt;tt&gt;wc&lt;/tt&gt;, or word count utility can do this easily.  By
default it counts characters, words and lines.  With '-l' it will emit
only the count of lines.&lt;/p&gt;

&lt;pre&gt;
user@host:~/data$ wc -l table.tab
10
&lt;/pre&gt;

&lt;p&gt;If you want to ignore the header, start with the second line (see
the next example for a more thorough explanation):&lt;/p&gt;

&lt;pre&gt;
user@host:~/data$ tail -n +2 | table.tab
9
&lt;/pre&gt;

&lt;b&gt;"SELECT COUNT(DISTINCT(FIELD1)) FROM TABLE"&lt;/b&gt;

&lt;p&gt;For getting a distinct count of values in a column :&lt;/p&gt;

&lt;pre&gt;
user@host:~/data$ cut -f1 table.tab | tail -n +2 | sort | uniq -c
&lt;/pre&gt;

&lt;p&gt; The first part &lt;tt&gt;cut&lt;/tt&gt; is a utility that allows you to take
particular columns from a tab-delimited file, or character ranges from
a fixed-width file.  &lt;tt&gt;cut&lt;/tt&gt; also allows you to specify the
delimiter - but be warned that the commonly encountered CSV format
requires more complexity in parsing than just using a comma as a
delimiter.  So this takes the first column out of the input file.
&lt;/p&gt;

&lt;p&gt; The next part of that is the &lt;tt&gt;tail&lt;/tt&gt; command.  &lt;tt&gt;tail&lt;/tt&gt;
is a command that outputs the end or 'tail' of a file.  The '-n'
option says what line number to start at (counted from the end of the
file) - in this case the '+' tells &lt;tt&gt;tail&lt;/tt&gt; to start at the
second line from the beginning.  This effectively tosses out the
header line.&lt;/p&gt;

&lt;p&gt; Next the values themselves are sorted.  This is necessary for the
&lt;tt&gt;uniq&lt;/tt&gt; command, which will only collapse or count duplicate
lines when they are adjacent.&lt;/p&gt;

&lt;p&gt;Finally we reduce duplicate lines with &lt;tt&gt;uniq&lt;/tt&gt;.  The '-c'
tells it to emit the count of duplicates when collapsing them.&lt;/p&gt;


&lt;h3&gt;Dealing with varoius file archive types&lt;/h3&gt;

&lt;p&gt;I often work with files in zip archives and tar (unix tape archive)
archives, sometimes with additional compression applied to them (.Z,
unix compress; .gz, gzip; and .bz2 bzip).  It is possible to work with
these files without having to unarchive or decompress them permanently
if all you need is a simple count of lines or to only process them
once.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Pulling a file from a Zip Archive&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;To pull one or more files from within a zip archive, and send them
to another command (as part of a pipeline):&lt;/p&gt;

&lt;pre&gt;
user@host:~/data$ unzip -l archive.zip
Archive: archive.zip
  Length    Date   Time   Name
 --------   ----   ----   ----
      34  04-28-08 11:01  table1.tab
      56  04-28-08 11:01  table1.tab
user@host:~/data$ unzip -c archive.zip table1.tab table2.tab | wc -l
36
&lt;/pre&gt;

&lt;p&gt;That example uses the &lt;tt&gt;unzip&lt;/tt&gt; command to pull 2 files out
and send them to standard output - to either the screen or the next
command in the pipeline.  In this case that is &lt;tt&gt;wc&lt;/tt&gt; to get the
combined record count for the two files.  We don't have to worry about
cleaning up the two files when we're done either.&lt;/p&gt;

&lt;p&gt;
&lt;tt&gt;unzip -l&lt;/tt&gt; lists the files in a zip archive.  If we left off
the '-c' (and the '| wc -l') unzip would have extracted just those two
files from the archive (in case there were more and you only wanted a
small handful).&lt;/p&gt;

&lt;h3&gt;Dealing with various file encodings&lt;/h3&gt;

&lt;p&gt;The first barrier to using most of these readily available utilities
is often the file formats themselves.  The utilities are line-oriented
for the records and tab-oriented for the fields.  So the first step is
often figuring out how to even get your data into a tab-delimited
format.&lt;/p&gt;

&lt;p&gt;There is more to that than I have time to write right now.  I'll
work at following up with examples for another posting.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:kyle_burton:11817</id>
    <link rel="alternate" type="text/html" href="http://kyle-burton.livejournal.com/11817.html"/>
    <link rel="self" type="text/xml" href="http://kyle-burton.livejournal.com/data/atom/?itemid=11817"/>
    <title>Some Reflection in CLOS</title>
    <published>2008-04-25T14:23:57Z</published>
    <updated>2008-04-25T14:30:14Z</updated>
    <category term="lisp"/>
    <content type="html">&lt;p&gt;CLOS and slot (member) lookup recently came across &lt;a href="http://groups.google.com/group/comp.lang.lisp/browse_thread/thread/adc8793b7f4b858a?hl=en"&gt;c.l.l&lt;/a&gt;.  &lt;br /&gt;&lt;br /&gt;&lt;pre&gt;
;; some reflection in clos

(defclass test-class
  ()
  ((s1 :reader :slot1
       :writer :set-slot1)
   (s2 :reader :slot2
       :writer :set-slot2)
   (s3 :reader :third-slot
       :writer :update-three)))


(defvar x nil)
(setf x (make-instance 'test-class))

(use-package :clos)

(class-direct-slots (class-of x))
;; =&amp;lt; 
;; (#&amp;lt;standard-direct-slot-definition s1="S1" #x19f471c9="#x19F471C9"&amp;gt;
;;  #&amp;lt;standard-direct-slot-definition s2="S2" #x19f471f5="#x19F471F5"&amp;gt;
;;  #&amp;lt;standard-direct-slot-definition s3="S3" #x19f47221="#x19F47221"&amp;gt;)


(class-direct-superclasses (class-of x))

;; =&amp;gt; 
;; (#&amp;lt;standard-class standard-object="STANDARD-OBJECT"&amp;gt;)

(mapcar #'slot-definition-readers (class-direct-slots (class-of x)))
;; =&amp;gt; ((:SLOT1) (:SLOT2) (:THIRD-SLOT))

(mapcar #'slot-definition-writers (class-direct-slots (class-of x)))
;; =&amp;gt; ((:SET-SLOT1) (:SET-SLOT2) (:UPDATE-THREE))

&lt;/pre&gt;</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:kyle_burton:11531</id>
    <link rel="alternate" type="text/html" href="http://kyle-burton.livejournal.com/11531.html"/>
    <link rel="self" type="text/xml" href="http://kyle-burton.livejournal.com/data/atom/?itemid=11531"/>
    <title>IRC in Emacs with ERC</title>
    <published>2008-04-14T15:23:05Z</published>
    <updated>2008-04-14T15:23:05Z</updated>
    <category term="irc emacs"/>
    <content type="html">&lt;p&gt; &lt;a href="http://neverlight.com/wordpress/"&gt;Jason Stelzer&lt;/a&gt; just turned me on to &lt;a href="http://delysid.org/emacs/erc.html"&gt;ERC&lt;/a&gt;, an IRC mode for Emacs.  It even just works with Windows, and comes with recent versions of Emacs (as of April 2008). &lt;/p&gt;  &lt;p&gt; There are even easy ways to automatically start a session and connect to a channel - wrapping that up helped make it more automatic: &lt;/p&gt;   &lt;br /&gt;&lt;br /&gt;&lt;pre&gt;
(defun krb-start-erc ()
  (interactive)
  (erc-open
   "irc-server-name-or-ip"
   6667
   "your-username"
   "your-full-name"
   t ;; connect
   "your-passwd")
  (erc-join-channel "datapump"))
&lt;/pre&gt;</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:kyle_burton:11348</id>
    <link rel="alternate" type="text/html" href="http://kyle-burton.livejournal.com/11348.html"/>
    <link rel="self" type="text/xml" href="http://kyle-burton.livejournal.com/data/atom/?itemid=11348"/>
    <title>Keyword symbols vs non-keyword symbols</title>
    <published>2008-03-11T01:54:03Z</published>
    <updated>2008-03-11T01:54:03Z</updated>
    <category term="lisp"/>
    <content type="html">&lt;p&gt; It took too long for it to really click so while I'm thinking about this 
again I'm writing it down.  There are good
reasons why you should avoid using symbols of the form &lt;code&gt;'foo&lt;/code&gt; in
preference to &lt;code&gt;:foo&lt;/code&gt;.  The main semantic difference is that the one
preceded with a single quote is tied to the package where it occurrs, while the
one preceded by the colon is placed within the keyword package.  &lt;/p&gt;

&lt;p&gt; What this means to you and your code may vary.  One immediate reason to use
keyword symbols (the ones that start with a colon) is that they are the same
everywhere - they are &lt;code&gt;equal&lt;/code&gt; (&lt;code&gt;eq&lt;/code&gt; even).  This means
that they're shared - if you take symbols as arguments, or return symbols as
values, then the keyword symbols will be easier to use.  You won't have to
export them from your package for them to be accessible (except in very rare,
unhygenic, cases, eg: &lt;code&gt;aif&lt;/code&gt;).  &lt;/p&gt;

&lt;pre&gt;
CL-USER&amp;gt; (defpackage :foo                                                                                                    
           (:use :common-lisp)                                                                                                        
           (:export :qux))
#&amp;lt;PACKAGE "FOO"&amp;gt;
CL-USER&amp;gt; (in-package :foo)
#&amp;lt;PACKAGE "FOO"&amp;gt;
FOO&amp;gt; (defun qux ()                                                                                                           
       'bar)
QUX
FOO&amp;gt; (equal 'bar (qux))
T
FOO&amp;gt; (in-package :cl-user)
#&amp;lt;PACKAGE "COMMON-LISP"&amp;gt;
CL-USER&amp;gt; (equal 'bar (foo:qux))
NIL
CL-USER&amp;gt; 
&lt;/pre&gt;

&lt;p&gt; That last one there was somehow confusing to me for a long time.  Using
keyword symbols solves that issue neatly: &lt;/p&gt;

&lt;pre&gt;
CL-USER&amp;gt; (defpackage :foo                                                                                                         
  (:use :common-lisp)                                                                                                        
  (:export :qux))
#&amp;lt;PACKAGE "FOO"&amp;gt;
CL-USER&amp;gt; (in-package :foo)
#&amp;lt;PACKAGE "FOO"&amp;gt;
FOO&amp;gt; (defun qux ()                                                                                                           
  :bar)
STYLE-WARNING: redefining QUX in DEFUN                                                                                       
QUX
FOO&amp;gt; (equal :bar (qux))
T
FOO&amp;gt; (in-package :cl-user)
#&amp;lt;PACKAGE "COMMON-LISP"&amp;gt;
CL-USER&amp;gt; (equal :bar (foo:qux))
T
CL-USER&amp;gt; 
&lt;/pre&gt;

&lt;p&gt; The other reason to use them is that they're not just interned for the
package they were defined in, but &lt;b&gt;all&lt;/b&gt; keyword symbols are interned in
the keyword package - saving memory in your running instance.  &lt;/p&gt;

&lt;p&gt; This point was lost on me until I started using packages seriously.  I had
no context for understanding it until I started using packages to organize my
code.  &lt;/p&gt;

&lt;p&gt;
In general you should probably be using keyword symbols as your default.
&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:kyle_burton:11248</id>
    <link rel="alternate" type="text/html" href="http://kyle-burton.livejournal.com/11248.html"/>
    <link rel="self" type="text/xml" href="http://kyle-burton.livejournal.com/data/atom/?itemid=11248"/>
    <title>Landmark Parsing</title>
    <published>2008-02-29T05:22:06Z</published>
    <updated>2008-02-29T05:22:06Z</updated>
    <category term="perl parsing html"/>
    <content type="html">&lt;p&gt;
Someone asked for an example so I dug up my &lt;a href="http://asymmetrical-view.com/personal/code/perl/jspwiki"&gt;jspwiki&lt;/a&gt; tool.  Here is the guts of the parser:
&lt;/p&gt;

&lt;pre&gt;

sub makeParser {
  my($data) = @_;
  my $pos = 0;
  my $setData = sub { $data = $_[0]; $pos = 0; };
  my $start   = sub { $pos = 0 };
  my $fwd     = sub { return -1 if $pos == -1; $pos += $_[0]; $pos = -1 if $pos &amp;gt;= length($data); $pos };
  my $bck     = sub { return -1 if $pos == -1; $pos -= $_[0]; $pos = -1 if $pos &amp;lt; 0;              $pos };
  my $bckTo   = sub { return -1 if $pos == -1; $pos = rindex $data, $_[0], $pos; };
  my $fwdTo   = sub { return -1 if $pos == -1; $pos =  index $data, $_[0], $pos; };
  my $fwdPast = sub {
    return $pos if $pos == -1;
    $pos = index $data, $_[0], $pos;
    return $pos if $pos == -1;
    $pos += length($_[0]);
    $pos &amp;gt;= length($data) ? $pos = -1 : $pos;
  };
  my $btwn = sub {
    return -1 if $pos == -1;
    my $s = $fwdPast-&amp;gt;($_[0]);
    return undef if $s == -1;
    my $e = $fwdTo-&amp;gt;($_[1]);
    return undef if $e == -1;
    my $item = substr $data, $s, $e - $s;
    return $item;
  };

  my $all = sub {
    my @all;
    while (-1 != $pos) {
      my $item = $btwn-&amp;gt;(@_);
      last unless $item;
      push @all, $item;
    }
    return @all;
  };

  return ($setData,$start,$fwd,$bck,$fwdTo,$fwdPast,$bckTo,$btwn,$all);
}
&lt;/pre&gt;

&lt;p&gt;and here is how it gets used:&lt;/p&gt;

&lt;pre&gt;
sub getPageInfo {
  my($topic) = @_;
  my $data = $UserAgent-&amp;gt;get("$BaseURL/PageInfo.jsp?page=$topic")-&amp;gt;content;
  print "$data\n";
  my($setData,$start,$fwd,$bck,$fwdTo,$fwdPast,$bckTo,$btwn,$all) = makeParser($data);
  my $table = $btwn-&amp;gt;('Version','&amp;lt;/table&amp;gt;');

  ($setData,$start,$fwd,$bck,$fwdTo,$fwdPast,$bckTo,$btwn,$all) = makeParser($table);
  print join("\t",qw(Version Date Author Size Changes from Previous)),"\n";
  dumpRow($_) for $all-&amp;gt;('&amp;lt;tr&amp;gt;','&amp;lt;/tr&amp;gt;');
}

sub dumpRow {
  my($row) = @_;
  my($setData,$start,$fwd,$bck,$fwdTo,$fwdPast,$bckTo,$btwn,$all) = makeParser($row);
    print join("\t",map { simpleStrip($_) } $all-&amp;gt;('&amp;lt;td&amp;gt;','&amp;lt;/td&amp;gt;')),"\n";
}

&lt;/pre&gt;</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:kyle_burton:10847</id>
    <link rel="alternate" type="text/html" href="http://kyle-burton.livejournal.com/10847.html"/>
    <link rel="self" type="text/xml" href="http://kyle-burton.livejournal.com/data/atom/?itemid=10847"/>
    <title>Automating Invitations to Mailman Lists</title>
    <published>2008-02-28T21:12:34Z</published>
    <updated>2008-02-28T21:14:29Z</updated>
    <category term="lisp drakma mailman"/>
    <content type="html">&lt;p&gt;&lt;br /&gt;This is just a code example - I had a new mailing list created at work and needed a large-ish list of people to get onto it.  To save a bit of effort (admittedly a small amount) I scripted it.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;; (require 'asdf-install)
; (asdf-install:install :drakma)

(require :drakma)
(use-package :drakma)

;; (http-request "http://mailman/mailman/listinfo/code-reviews")

;; &amp;lt;FORM Method=POST ACTION=\"http://mailman/mailman/subscribe/code-reviews\"&amp;gt;
;; &amp;lt;INPUT type=\"Text\" name=\"email\" size=\"30\" value=\"\"&amp;gt;
;; &amp;lt;INPUT type=\"Text\" name=\"fullname\" size=\"30\" value=\"\"&amp;gt;
;; &amp;lt;INPUT type=\"Password\" name=\"pw\" size=\"15\"&amp;gt;
;; &amp;lt;INPUT type=\"Password\" name=\"pw-conf\" size=\"15\"&amp;gt;
;; &amp;lt;input type=radio name=\"digest\" value=\"0\" CHECKED&amp;gt; No
;; &amp;lt;INPUT type=\"Submit\" name=\"email-button\" value=\"Subscribe\"&amp;gt;

(defun subscribe-user-to-code-reviews (email full-name pass)
  (drakma:http-request "http://mailman/mailman/subscribe/code-reviews"
                       :method :post
                       :parameters
                       `(("email"        . ,email)
                         ("fullname"     . ,full-name)
                         ("pw"           . ,pass)
                         ("pw-conf"      . ,pass)
                         ("digest"       . "0")
                         ("email-button" . "Subscribe"))))

; (subscribe-user-to-code-reviews "kburton@some-domain.com" "Kyle Burton" "some-password")

;; I went into outlook, opened the shared public contact list, did
;; CTRL-A, CTRL-C, went to excel and pasted, then saved as addrs.csv, then
;; do a bit of vi-magic to format the lines as expected below
(defun get-lines ()
  (with-open-file (in "/home/kburton/foo.txt" :direction :input)
    (loop for line = (read-line in nil nil)  then (read-line in nil nil)
       while line
       collect line)))

; (get-lines)

(require :cl-ppcre)
(use-package :cl-ppcre)

(defun split-line (line)
  (multiple-value-bind
        (string matches)
      (cl-ppcre:scan-to-strings "\"([^\"]+)\".*E-mail: (.+)$" line)
    (list (aref matches 0)
          (aref matches 1))))

;(split-line "\"Smith, John\" E-mail: jsmith@some-domain.com")

(loop for line in (get-lines)
     while line
     do
     (destructuring-bind
           (name email)
         (split-line line)
       (format t "name:~a email:~a~&amp;amp;" name email)
       (subscribe-user-to-code-reviews email "" "")))
&lt;/pre&gt;</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:kyle_burton:10643</id>
    <link rel="alternate" type="text/html" href="http://kyle-burton.livejournal.com/10643.html"/>
    <link rel="self" type="text/xml" href="http://kyle-burton.livejournal.com/data/atom/?itemid=10643"/>
    <title>Developer to Engineer</title>
    <published>2008-02-28T01:02:59Z</published>
    <updated>2008-02-28T01:02:59Z</updated>
    <category term="perl testing tdd"/>
    <content type="html">&lt;p&gt;Kudos to you Josh [Crean].  He stepped up and gave a tech-talk today at work
on using unit testing and &lt;code&gt;Devel::Cover&lt;/code&gt;.  Not only did he
give the talk, but he did it as a live interactive session - creating
a module and its test, fielding questions and taking input from the
other developers.&lt;/p&gt;

&lt;p&gt; Actually he followed test driven development.  This was based on
comments by the audience -- he switched tack during the session.&lt;/p&gt;

&lt;p&gt; Josh responded well to the "should we shoot for 100% coverage",
and even showed an example (by coding it up as part of the live
performance) where unit tests can drive software to 100% coverage and
still contain bugs (100% coverage based on unit tests doesn't
&lt;i&gt;prove&lt;/i&gt; the code is correct in any way).&lt;/p&gt;

&lt;p&gt; If you haven't checked out Test::Unit or Devel::Cover on CPAN, you
should take a look.  They can really improve the software you're
developing.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:kyle_burton:10455</id>
    <link rel="alternate" type="text/html" href="http://kyle-burton.livejournal.com/10455.html"/>
    <link rel="self" type="text/xml" href="http://kyle-burton.livejournal.com/data/atom/?itemid=10455"/>
    <title>Yahoo as a takeover target for Microsoft</title>
    <published>2008-02-04T13:24:35Z</published>
    <updated>2008-02-04T13:24:35Z</updated>
    <content type="html">&lt;p&gt;
Something interesting is going on that is a rare event: large tech firms are looking to merge.  Microsoft has offered to merge (buy) Yahoo.  This appears to be in an attempt to strengthen its on-line business units.
&lt;/p&gt;

&lt;p&gt;
Some bloggers are taking this as Microsoft effectively admitting that they can't catch up in search or on-line advertising (not necessarily technologically, but definitely with respect to market share).
&lt;/p&gt;

&lt;p&gt;
&lt;ul&gt;
  &lt;li&gt;Mark Cuban: &lt;a href="http://www.blogmaverick.com/2008/02/03/why-yahoo-should-say-yes-to-microsoft/"&gt;Why Yahoo should say Yes to MicroSoft&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://www.reuters.com/article/ousiv/idUSN0362915520080204"&gt;Yahoo may consider Google alliance, source says&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://googleblog.blogspot.com/2008/02/yahoo-and-future-of-internet.html"&gt;Yahoo! and the future of the Internet&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://online.wsj.com/article/SB120206856800138831.html?mod=hpp_us_whats_news"&gt;Google Offers to Help Yahoo
Fight Off Microsoft&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/p&gt;


&lt;p&gt;
A lot of people have a lot to say...regardless of all the ideas that are flouted, the effects will ripple out for a long time.  If MS succeeds, it will cause issues for Yahoo's current employees (there is rumor that many don't want to work for MS), if Google steps in and somehow scuttles the deal, it may be seen as some kind of evidence of weakness in MS and strength in Google.
&lt;/p&gt;

&lt;p&gt;
Regardless, Microsoft seems to have some serious issues to work out - it seems to be in the process of finding itself again.  How are they going to brand their on-line presence after this kind of merger?  What are they going to do with Yahoo from a technology perspective?  Yahoo is  definitely not an MS shop (unix, PHP, Java).  I wonder about this in context of what happened with the Hotmail acquisition of old...
&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:kyle_burton:10233</id>
    <link rel="alternate" type="text/html" href="http://kyle-burton.livejournal.com/10233.html"/>
    <link rel="self" type="text/xml" href="http://kyle-burton.livejournal.com/data/atom/?itemid=10233"/>
    <title>Scheme's let loop form</title>
    <published>2008-01-31T03:09:12Z</published>
    <updated>2008-01-31T03:09:12Z</updated>
    <category term="lisp macro"/>
    <content type="html">&lt;p&gt;
I particularly like Scheme's let loop form:
&lt;/p&gt;
&lt;pre&gt;

(let loop ((x 1) (y 2))
     (write "x=") (write x)
     (write ", y=") (write y)
     (newline)
     (cond ((= x y)
            #t)
           (else
            (loop (+ 1 x) y)))) 
&lt;/pre&gt;
&lt;p&gt;
It allows you to define a locally scoped recursive function, with arguments and initial values, that is immediately called.  It is clean and private - the name &lt;i&gt;loop&lt;/i&gt; only exists within the let declaration - it is not available in any other scope.
&lt;/p&gt;

&lt;p&gt;
I wanted the same form for programming in CL.  There are two unfortunate things about this, the first is that &lt;i&gt;loop&lt;/i&gt; is already defined (a public symbol in the CL-USER package).  Although this is analogous to a reserved word in many programming languages, I could 'steal' the meaning of &lt;i&gt;loop&lt;/i&gt; for just this scope, I just choose not to use the symbol &lt;i&gt;loop&lt;/i&gt; when using this macro.  The other unfortunate thing is that you can't 'extend' the &lt;tt&gt;let&lt;/tt&gt; form (at least I don't know if it supports the same kind of run-time extension that &lt;tt&gt;setf&lt;/tt&gt; supports).  Regardless, if I chose a sensible name, it can be done:
&lt;/p&gt;

&lt;pre&gt;
(defmacro llet (name bindings &amp;body body)
  (let ((args (mapcar #'first bindings))
        (initial-values (mapcar #'second bindings)))
  `(labels ((,name ,args
              ,@body))
     (,name ,@initial-values))))

(macroexpand-1
 '(llet lp ((x 1) (y 2))
   (format t "x:~a y:~a~&amp;" x y)
   (cond ((= x y)
          t)
         (t 
          (lp (1+ x) y)))))

(llet lp ((x 1) (y 2))
   (format t "x:~a y:~a~&amp;" x y)
   (cond ((= x y)
          t)
         (t 
          (lp (1+ x) y))))  

(llet recur ((x 1) (y 2))
  (format t "x:~a y:~a~&amp;" x y)
  (cond ((= x y)
         t)
        (t
         (recur (1+ x) y))))
&lt;/pre&gt;

&lt;p&gt;
Not exactly the same, but just as useful and clean.
&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:kyle_burton:9961</id>
    <link rel="alternate" type="text/html" href="http://kyle-burton.livejournal.com/9961.html"/>
    <link rel="self" type="text/xml" href="http://kyle-burton.livejournal.com/data/atom/?itemid=9961"/>
    <title>More with Macros: cut to rcut to pcut and finally to kcut</title>
    <published>2008-01-31T02:53:19Z</published>
    <updated>2008-01-31T02:53:19Z</updated>
    <category term="lisp macro"/>
    <content type="html">&lt;p&gt;
&lt;a href="http://kyle-burton.livejournal.com/9543.html"&gt;Last time&lt;/a&gt; I worked through &lt;tt&gt;cut&lt;/tt&gt;, to &lt;tt&gt;rcut&lt;/tt&gt; (recursive cut) to a &lt;tt&gt;pcut&lt;/tt&gt; (pattern cut).  When talking that over with Josh today over lunch, I said a way to think about &lt;tt&gt;cut&lt;/tt&gt; is that you first write out a literal version of the form you want, then replace (or cut) out the parts you want to vary and &lt;tt&gt;cut&lt;/tt&gt; gives you back a function that takes as many arguments as cut points you supplied.
&lt;/p&gt;

&lt;p&gt;
Another way to think about it was that we created a new way to define a function (a lambda) without having to formally specify the arguments to the function - and that we could even go one step further and make a &lt;tt&gt;pdefine&lt;/tt&gt; that was a defun with the same semantics.  So we banged one out on the projector:
&lt;/p&gt;

&lt;pre&gt;
(defmacro pdefine (name &amp;rest body)
  `(setf (symbol-function ',name)
         (pcut ,@body)))

(pdefine myfunc
         (cond ((&amp;gt; ?fst 1)
                (format t "first arg (~a) was &amp;gt;1, x is: ~a~&amp;" ?fst ?x))
               (t
                (format t "first arg (~a) was &amp;lt;1, x is: ~a, y is:~a~&amp;" ?fst ?x ?y))))


(myfunc 1/2 'a 'b)
(myfunc 2/1 'a 'b)

&lt;/pre&gt;

&lt;p&gt;
We left off the session (back to our day jobs) with the idea that you could do it with named parameters (keywords) rather than just by using positional arguments.  Turned out to be an easy extension:
&lt;/p&gt;

&lt;pre&gt;
(defmacro kcut (&amp;rest body)
  (let* ((formals (list))
         (fml-hash (make-hash-table :test #'equal))
         (new-body
          (map-tree #'(lambda (elt)
                        (if (starts-with-? elt)
                            (aprog1
                             (or (gethash elt fml-hash)
                                 (aprog1
                                  (read-from-string (subseq (format nil "~a" elt) 1))
                                  (push it formals)
                                  (setf (gethash elt fml-hash) it)))
                             it)
                            elt))
                    body)))
    `#'(lambda (&amp;key ,@(reverse formals))
         ,@new-body)))

(macroexpand-1
 '(kcut
   (cond ((&amp;gt; ?fst 1)
          (format t "first arg (~a) was &amp;gt;1, x is: ~a~&amp;" ?fst ?x))
         (t
          (format t "first arg (~a) was &amp;lt;1, x is: ~a, y is:~a~&amp;" ?fst ?x ?y)))))

(let ((fn (kcut
           (cond ((&amp;gt; ?fst 1)
                  (format t "first arg (~a) was &amp;gt;1, x is: ~a~&amp;" ?fst ?x))
                 (t
                  (format t "first arg (~a) was &amp;lt;1, x is: ~a, y is:~a~&amp;" ?fst ?x ?y))))))
  (funcall fn :fst 1/2 :x 'a :y 'b)
  (funcall fn :fst 2/1 :x 'a :y 'b))


(defmacro kdefine (name &amp;rest body)
  `(setf (symbol-function ',name)
         (kcut ,@body)))

(kdefine mykfunc
         (cond ((&amp;gt; ?fst 1)
                (format t "first arg (~a) was &amp;gt;1, x is: ~a~&amp;" ?fst ?x))
               (t
                (format t "first arg (~a) was &amp;lt;1, x is: ~a, y is:~a~&amp;" ?fst ?x ?y))))

(mykfunc :fst 1/2 :x 'a :y 'b)
(mykfunc :fst 2/1 :x 'a :y 'b)
(mykfunc :fst 1/2 :x 'a)
(mykfunc :fst 2/1 :x 'a)
(mykfunc :fst 1/2)
(mykfunc :fst 2/1)
&lt;/pre&gt;

&lt;p&gt;
I think I'm going to use these as examples for the presentation...
&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:kyle_burton:9543</id>
    <link rel="alternate" type="text/html" href="http://kyle-burton.livejournal.com/9543.html"/>
    <link rel="self" type="text/xml" href="http://kyle-burton.livejournal.com/data/atom/?itemid=9543"/>
    <title>SRFI-26's cut macro...</title>
    <published>2008-01-30T12:55:54Z</published>
    <updated>2008-01-30T13:01:43Z</updated>
    <content type="html">&lt;p&gt;I'm working on an &lt;a href="http://asymmetrical-view.com/lisp-presentation/"&gt;introduction to lisp presentation&lt;/a&gt; for &lt;a href="http://www.phillylinux.org/west.html"&gt;PLUG West&lt;/a&gt;.  I'm trying to think through examples of macros which are a good demonstration of what macros are and are for.  Towards that end, I picked Scheme's srfi-26's cut macro, which allows for specialization of argument and then extend it in a couple of ways.  Below is the example code, including a simplified cut, a recursive (or tree) cut, and a pattern cut (which allows the cut points to be named).&lt;/p&gt;

&lt;pre&gt;
;; the scheme cut macro...srfi-26                                                                                            

;;  (cut #'format "~a~&amp;" &amp;lt;&amp;gt;)                                                                                                 
;; =&amp;gt;                                                                                                                        
;;  #'(lambda (x) (format "~a~&amp;" x))                                                                                         
;;                                                                                                                           
;; It's 'flat' though, it'd be nice to have something which could work                                                       
;; on any form...a recursive cut.                                                                                            

(defmacro aprog1 (it &amp;rest body)
  "Anaphoric prog1, returns the value of the first expression,                                                               
executing all subsequent expressions for their side effects.  It binds                                                       
the symbol 'it' to the result of the first expression.                                                                       
                                                                                                                             
  (aprog1                                                                                                                    
    (make-hash-table :test #'equal)                                                                                          
    (setf (gethash \"a\" it) 1)                                                                                              
    (setf (gethash \"b\" it) 2)                                                                                              
    (setf (gethash \"c\" it) 3))                                                                                             
  =&amp;gt; #&amp;lt;HASH-TABLE :TEST EQUAL :COUNT 3 {BE49831}&amp;gt;                                                                     
                                                                                                                             
"
  `(let ((it ,it))
     ,@body
     it))

(defmacro cut (fn &amp;rest body)
  "                                                                                                                          
(cut #'cons (+ a 1) &amp;lt;&amp;gt;) is the same as (lambda (x2) (cons (+ a 1) x2))                                                       
(cut #'list 1 &amp;lt;&amp;gt; 3 &amp;lt;&amp;gt; 5) is the same as (lambda (x2 x4) (list 1 x2 3 x4 5))                                                  
(cut #'list) is the same as (lambda () (list))                                                                               
(cut #'list 1 &amp;lt;&amp;gt; 3 &amp;lt;...&amp;gt;) is the same as (lambda (x2 . xs) (apply list 1 x2 3 xs))                                           
                                                                                                                             
The following form is not supported in this version:                                                                         
  (cut &amp;lt;&amp;gt; a b) is the same as (lambda (f) (f a b))                                                                           
"
  (let* ((formals (list))
         (new-body
          (mapcar #'(lambda (item)
                      (if (equal '&amp;lt;&amp;gt; item)
                          (aprog1
                           (gensym)
                           (push it formals)
                           it)
                          item))
                  body)))
    `#'(lambda ,(reverse formals)
         (funcall ,fn ,@new-body))))

;; (macroexpand-1 '(cut #'format t "~a: ~a~&amp;" "thing" &amp;lt;&amp;gt;))                                                                   
;; (funcall (cut #'format t "~a: ~a~&amp;" "thing" &amp;lt;&amp;gt;) 10)                                                                       
;; (funcall (cut #'format t "~a: ~a~&amp;" &amp;lt;&amp;gt; &amp;lt;&amp;gt;) "thing" 10)                                                                    

(defun map-tree (fn tree)
  (cond ((null tree)
         tree)
        ((not (listp tree))
         (funcall fn tree))
        (t
         (mapcar #'(lambda (elt) (map-tree fn elt)) tree))))

;; (map-tree #'(lambda (elt) (format t "x:~a~&amp;" elt) (1+ elt)) '(1 2 (3 4 (5 6 (7)))))                                       

(defmacro rcut (&amp;rest body)
  (let* ((formals (list))
         (new-body
          (map-tree #'(lambda (elt)
                        (if (equalp '&amp;lt;&amp;gt; elt)
                            (aprog1
                             (gensym)
                             (push it formals)
                             it)
                            elt))
                    body)))
    `#'(lambda ,(reverse formals)
         ,@new-body)))

(macroexpand-1
 '(rcut
   (cond ((&amp;gt; &amp;lt;&amp;gt; 1)
          (format t "first arg was &amp;gt;1, second arg is: ~a~&amp;" &amp;lt;&amp;gt;))
         (t
          (format t "first arg was &amp;lt;1, third arg is: ~a~&amp;" &amp;lt;&amp;gt;)))))


(let ((fn
       (rcut
        (cond ((&amp;gt; &amp;lt;&amp;gt; 1)
               (format t "first arg was &amp;gt;1, second arg is: ~a~&amp;" &amp;lt;&amp;gt;))
              (t
               (format t "first arg was &amp;lt;1, third arg is: ~a~&amp;" &amp;lt;&amp;gt;))))))
  (funcall fn 1/2 'a 'b)
  (funcall fn 2/1 'a 'b))




;; that's all well and good, but what we probably really want is pcut (pattern cut):                                         
;;                                                                                                                           
;;    (pcut                                                                                                                  
;;      (cond ((&amp;gt; ?fst 1)                                                                                                    
;;             (format t "first arg (~a) was &amp;gt;1, x is: ~a~&amp;" ?fst ?x))                                                       
;;            (t                                                                                                             
;;             (format t "first arg (~a) was &amp;lt;1, x is: ~a, y is:~a~&amp;" ?fst ?x ?y)))                                          
;;                                                                                                                           

(defun starts-with-? (sym)
  (equal "?"  (subseq (format nil "~a" sym) 0 1)))


(defmacro pcut (&amp;rest body)
  (let* ((formals (list))
         (fml-hash (make-hash-table :test #'equal))
         (new-body
          (map-tree #'(lambda (elt)
                        (if (starts-with-? elt)
                            (aprog1
                             (or (gethash elt fml-hash)
                                 (aprog1
                                  (gensym)
                                  (push it formals)
                                  (setf (gethash elt fml-hash) it)
                                  it))
                             it)
                            elt))
                    body)))
    `#'(lambda ,(reverse formals)
         ,@new-body)))

(macroexpand-1
 '(pcut
        (cond ((&amp;gt; ?fst 1)
               (format t "first arg (~a) was &amp;gt;1, x is: ~a~&amp;" ?fst ?x))
              (t
               (format t "first arg (~a) was &amp;lt;1, x is: ~a, y is:~a~&amp;" ?fst ?x ?y)))))





(let ((fn (pcut
           (cond ((&amp;gt; ?fst 1)
                  (format t "first arg (~a) was &amp;gt;1, x is: ~a~&amp;" ?fst ?x))
                 (t
                  (format t "first arg (~a) was &amp;lt;1, x is: ~a, y is:~a~&amp;" ?fst ?x ?y))))))
  (funcall fn 1/2 'a 'b)
  (funcall fn 2/1 'a 'b))
&lt;/pre&gt;</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:kyle_burton:9467</id>
    <link rel="alternate" type="text/html" href="http://kyle-burton.livejournal.com/9467.html"/>
    <link rel="self" type="text/xml" href="http://kyle-burton.livejournal.com/data/atom/?itemid=9467"/>
    <title>Arc has been released...</title>
    <published>2008-01-30T03:04:14Z</published>
    <updated>2008-01-30T03:04:14Z</updated>
    <category term="arc lisp"/>
    <lj:music>Massive Attack - Teardrop</lj:music>
    <content type="html">&lt;p&gt;&lt;br /&gt;&lt;a href="http://paulgraham.com"&gt;Paul Graham&lt;/a&gt; and Robert Morris just announced that &lt;a href="http://arclanguage.org/"&gt;Arc&lt;/a&gt; has been released.&lt;br /&gt;&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:kyle_burton:9102</id>
    <link rel="alternate" type="text/html" href="http://kyle-burton.livejournal.com/9102.html"/>
    <link rel="self" type="text/xml" href="http://kyle-burton.livejournal.com/data/atom/?itemid=9102"/>
    <title>n-choose-k</title>
    <published>2008-01-29T04:51:45Z</published>
    <updated>2008-01-29T04:51:45Z</updated>
    <category term="lisp combinatorics"/>
    <content type="html">&lt;p&gt;
We have an application that performs matching over multiple data sets.  We can estimate the run-time based on the number of record pairings it executes.  This is the n-choose-k of the number of records in the match (n-choose-2).  The computation of which is well documented: &lt;a href="http://en.wikipedia.org/wiki/Combination"&gt;Wikipedia: Combination&lt;/a&gt;, though for the degenerate case of &lt;code&gt;k=2&lt;/code&gt;, you can just add the previous number of entries as you iterate up:
&lt;/p&gt;

&lt;pre&gt;
(defun n-choose-2 (n)                                                                                                        
  (loop                                                                                                                      
     for ii from 1 upto n                                                                                                    
     for total = 0 then (+ total (- ii 1))                                                                                   
     finally (return total)))                                                                                                
                                                                                                                             
(n-choose-2 100)                                                                                                             
;; =&amp;gt; 4950                                                                                                                   
                                                                                                                            &lt;/pre&gt;

&lt;p&gt;
Of course since Common Lisp has built-in bignum support, you can implement the formula as described in the Wikipedia article, without regard (well mostly) to the magnitude of the numbers involved:
&lt;/p&gt;

&lt;pre&gt;
(defun fact (n)                                                                                                              
  (when (= 0 n)                                                                                                              
    (return-from fact 1))                                                                                                    
   (loop                                                                                                                     
    for ii from 1 to n                                                                                                       
    for ff = ii then (* ff ii)                                                                                               
    finally (return ff)))                                                                                                    
                                                                                                                             
                                                                                                                             
(defun n-choose-k (n k)                                                                                                      
  (/                                                                                                                         
   (fact n)                                                                                                                  
   (* (fact k)                                                                                                               
      (fact (- n k)))))                                                                                                      
                                                                                                                             
(n-choose-k 100 2)                                                                                                           
(n-choose-k 100 50)                                                                                                          
                                                                                                                             
;; won't run in any reasonable time on my hardware                                                                           
;; (n-choose-k 5123456 2)                                                                                                    
;; but this will:                                                                                                            
(n-choose-2 5123456)  
&lt;/pre&gt;</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:kyle_burton:8867</id>
    <link rel="alternate" type="text/html" href="http://kyle-burton.livejournal.com/8867.html"/>
    <link rel="self" type="text/xml" href="http://kyle-burton.livejournal.com/data/atom/?itemid=8867"/>
    <title>Simplistic Currency Formatting</title>
    <published>2008-01-27T18:35:50Z</published>
    <updated>2008-01-27T18:37:03Z</updated>
    <category term="ruby rails formatting"/>
    <content type="html">&lt;p&gt;I'm only just taking Rails for a spin, creating a simple website for coordinating volunteer work for a small local charity event (UMLY Alphabet Auction), and needed a currency formatter.  I couldn't find one that exactly fit my needs (most likely because I'm new to Rails) so I adapted one from what I was able to find.
&lt;/p&gt;
&lt;pre&gt;
class ApplicationController &amp;lt; ActionController::Base
  ...

  # adapted from: http://snippets.dzone.com/posts/show/2581                                                                  
  def ApplicationController.number_to_currency (number, options = {})
    separator = options.delete(:separator) { '.'}
    delimiter = options.delete(:delimiter) { ','}
    unit      = options.delete(:unit) { '$' }
    num = sprintf "#{unit}%.2f", number
    num.sub!(/\./,separator)
    while num.sub!(/(\d)(\d\d\d)([\.,])/,"\\1#{delimiter}\\2\\3")
      true
    end
    num
  end

  def number_to_currency  (number, options = {})
    ApplicationController.number_to_currency number, options
  end
&lt;/pre&gt;

&lt;p&gt;Adding it in to the ApplicationController made it available everywhere I needed it.  Also, I'm uneasy about defining it as both a method and a class method - otherwise I couldn't call it from both contexts (as either a method or directly off of the class)...something I'll have to look into further.&lt;/p&gt;</content>
  </entry>
</feed>
