<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-11347242</id><updated>2011-11-04T19:39:08.716-07:00</updated><title type='text'>/dev/code</title><subtitle type='html'>Share the Love&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;And the Code</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://devcode.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11347242/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://devcode.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Mark Wutka</name><uri>http://www.blogger.com/profile/01735952904584567390</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/-FBR1bumy7EM/TrShvjZulMI/AAAAAAAAATQ/c7nnkgqSTLg/s220/mark_arabia_mtn.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>18</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-11347242.post-5536259349846627182</id><published>2008-05-22T13:30:00.000-07:00</published><updated>2008-05-22T14:03:01.780-07:00</updated><title type='text'>Adding 1 to a binary number in sed</title><content type='html'>I have an odd fascination with binary clocks. I just recently built my own, based on an AVR microcontroller, which I will post more about soon. I also have a binary watch that was a present from Ceal a few years ago. During a particular boring meeting yesterday, I was watching it count the seconds, and I realized that to increment a binary number by 1, you are really looking for the pattern: 01*$ (the last part of the number consisting of 0 followed by only 1s to the end of the line). When you find that pattern, you just invert the bits.&lt;br /&gt;&lt;br /&gt;For example, to add 1 to 10011 (19 decimal), you are only interested in the 011 at the end. You invert that part and get 10100 (20 decimal). The only time the 01*$ pattern doesn't work is when the number is all 1s. In that case, you can insert a leading 0 and again just invert the bits. For example, 1111 (15 decimal) first becomes 01111, then inverted becomes 10000 (16 decimal).&lt;br /&gt;&lt;br /&gt;So, after that little epiphany, I began to wonder if I could write a sed script that functioned as a binary adder. At first I didn't think it could be done, because I was thinking purely in terms of doing substitutions. I have since learned much more about the capabilities of sed and found it was possible. Here is the script, along with an explanation of what each line does:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;s/^1*$/0&amp;/&lt;br /&gt;h&lt;br /&gt;s/\(.*\)01*$/\1/&lt;br /&gt;x&lt;br /&gt;s/^.*\(01*\)$/\1/&lt;br /&gt;y/01/10/&lt;br /&gt;x&lt;br /&gt;G&lt;br /&gt;s/\n//&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;table width="70%"&gt;&lt;br /&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;s/^1*$/0&amp;amp;/&lt;/code&gt;&lt;/td&gt;&lt;td&gt;If the number is all 1s, insert a leading 0&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;h&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Copy the current line to the hold buffer&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;s/\(.*\)01*$/\1/&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Strip off the 01*$ pattern from the end&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;x&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Exchange the current pattern with the hold buffer&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;s/^.*\(01*\)$/\1/&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Strip off everything but the 01*$ pattern&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;y/01/10/&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Invert the bits in the current line&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;x&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Exchange the current pattern with the hold buffer (go back to the prefix bits)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;G&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Join the hold buffer (the end bits that were just inverted) to the current pattern (sed puts it on a separate line)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;s/\n//&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Join the two lines&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;To test this, I wrote a little script that starts with 0, runs it through the adder, prints the result, and the runs the result through the adder. This is the script (caution, it loops forever):&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;#!/bin/sh&lt;br /&gt;NUM=0&lt;br /&gt;while true; do&lt;br /&gt;   NUM=`echo $NUM | sed -f adder.sed`&lt;br /&gt;   echo $NUM&lt;br /&gt;done&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;And here is a snippet of the results:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;1&lt;br /&gt;10&lt;br /&gt;11&lt;br /&gt;100&lt;br /&gt;101&lt;br /&gt;110&lt;br /&gt;111&lt;br /&gt;1000&lt;br /&gt;1001&lt;br /&gt;1010&lt;br /&gt;1011&lt;br /&gt;1100&lt;br /&gt;1101&lt;br /&gt;1110&lt;br /&gt;1111&lt;br /&gt;10000&lt;br /&gt;10001&lt;br /&gt;10010&lt;br /&gt;10011&lt;br /&gt;10100&lt;br /&gt;&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11347242-5536259349846627182?l=devcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://devcode.blogspot.com/feeds/5536259349846627182/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11347242&amp;postID=5536259349846627182' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11347242/posts/default/5536259349846627182'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11347242/posts/default/5536259349846627182'/><link rel='alternate' type='text/html' href='http://devcode.blogspot.com/2008/05/adding-1-to-binary-number-in-sed.html' title='Adding 1 to a binary number in sed'/><author><name>Mark Wutka</name><uri>http://www.blogger.com/profile/01735952904584567390</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/-FBR1bumy7EM/TrShvjZulMI/AAAAAAAAATQ/c7nnkgqSTLg/s220/mark_arabia_mtn.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11347242.post-114194180610839281</id><published>2006-03-09T13:15:00.000-08:00</published><updated>2006-11-12T17:26:07.824-08:00</updated><title type='text'>Beyond XML, part 2</title><content type='html'>I have come to the realization that the thing I was trying to describe in my previous post is fairly close to ASN.1 (Abstract Syntax Notation 1). The thing about ASN.1 that I never really grasped was that you can have different encoding rules. Thus, you can have an encoding that encodes as XML, or another one that has a more efficient binary protocol. I came to this realization while reading about Sun's Fast Infoset for SOAP requests, during my desperate search for a production-ready Java SOAP implementation that was reasonably fast. Still looking, though..&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11347242-114194180610839281?l=devcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://devcode.blogspot.com/feeds/114194180610839281/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11347242&amp;postID=114194180610839281' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11347242/posts/default/114194180610839281'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11347242/posts/default/114194180610839281'/><link rel='alternate' type='text/html' href='http://devcode.blogspot.com/2006/03/beyond-xml-part-2.html' title='Beyond XML, part 2'/><author><name>Mark Wutka</name><uri>http://www.blogger.com/profile/01735952904584567390</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/-FBR1bumy7EM/TrShvjZulMI/AAAAAAAAATQ/c7nnkgqSTLg/s220/mark_arabia_mtn.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11347242.post-112404685310290208</id><published>2005-08-14T11:57:00.000-07:00</published><updated>2006-11-12T17:26:07.751-08:00</updated><title type='text'>Beyond XML</title><content type='html'>Most people I have worked with will tell you that I am not a fan of XML. It has its places, but people seem to try to use it everywhere they can just because it is popular. I was reflecting this morning on XML Schemas and how ugly they are. It is difficult to look at a schema and visualize the data layout.&lt;br /&gt;&lt;br /&gt;At first, I wondered why this is so, and why you can look at a data definition in other languages and get a good idea how everything fits. Some of this is probably the noise of XML -- all those tags just give your brain more information to process. I think another part of it, though, is that XML is so explicit about things. In other languages, you can define things more positionally. That is, you can define a variable declaration as "type varname". In XML, you can do the same thing in your schema, but you still need tags for the type and varname.&lt;br /&gt;&lt;br /&gt;As I thought about this, it occurred to me that maybe all we need is a really super schema language. One where we define mappings to and from an abstract data notation. Instead of just mapping to/from XML, it would be great if you could map to/from all kinds of formats -- property files, flat files, comma-delimited, etc. You could couple this with some kind of interface definition language that expresses an interface in terms of the abstract data notation and then you could have something like SOAP but with support for multiple syntactic forms.&lt;br /&gt;&lt;br /&gt;For example, suppose I define a remote-call interface in an abstract notation that looks something like this:&lt;br /&gt;remote_call_request = string call_name, any params[];&lt;br /&gt;remote_call_response = any result;&lt;br /&gt;&lt;br /&gt;Then I could define multiple syntaxes for the remote call. One might looks like a SOAP request, one might be pipe-delimited text. It seems like the syntax definition might be pretty complicated to write, but it also seems like it could solve some headaches. It would be more friendly to legacy systems, you could get closer to a binary XML kind of format, you could convert easily from one format to another (like you do with XSLT, but with better support for non-XML formats).&lt;br /&gt;&lt;br /&gt;I don't know if anyone is working on something like this, or if it is even possible, but it is interesting to think about.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11347242-112404685310290208?l=devcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://devcode.blogspot.com/feeds/112404685310290208/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11347242&amp;postID=112404685310290208' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11347242/posts/default/112404685310290208'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11347242/posts/default/112404685310290208'/><link rel='alternate' type='text/html' href='http://devcode.blogspot.com/2005/08/beyond-xml.html' title='Beyond XML'/><author><name>Mark Wutka</name><uri>http://www.blogger.com/profile/01735952904584567390</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/-FBR1bumy7EM/TrShvjZulMI/AAAAAAAAATQ/c7nnkgqSTLg/s220/mark_arabia_mtn.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11347242.post-112137058768484804</id><published>2005-07-14T12:24:00.000-07:00</published><updated>2006-11-12T17:26:07.677-08:00</updated><title type='text'>Lispy or not?</title><content type='html'>I just started making Lisp versions my cop and robber entries from the ICFP contest. I am aware that because other languages I use don't have anything like Lisp's macros, I tend not to use macros in Lisp. I am trying to change that.&lt;br /&gt;&lt;br /&gt;When I was coding my parser in ocaml, I thought it was cool to use the match statement to parse the various lines, like this:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;let parse_line line =&lt;br /&gt;  match Str.split (Str.regexp "[ \t]+") line with&lt;br /&gt;      "wsk\\" :: [] -&gt; handle_wsk_start()&lt;br /&gt;    | "name:" :: name :: [] -&gt; handle_name name&lt;br /&gt;    | "robber:" :: name :: [] -&gt; handle_robber name&lt;br /&gt;    | "cop:" :: name :: [] -&gt; handle_cop name&lt;br /&gt;    | "nod\\" :: [] -&gt; handle_nodes_start()&lt;br /&gt;    | "nod:" :: name :: tag :: x :: y :: [] -&gt; handle_node name (node_tag_of_string tag)&lt;br /&gt;                                            (int_of_string x) (int_of_string y)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Since I don't have match in Lisp, I wondered what would be a good way to do this in Lisp. I decided to do it with a macro. I keep a global hash table that maps keywords like "wsk\\" and "name:" to functions that handle the data for those keywords. I use a macro named defparse to create a function where instead of the name of the function, I supply the keyword name. Here is how I handle the "nod:" line for example:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(defparse "nod:" (name tag x# y#)&lt;br /&gt;  (push (make-instance 'node :name name :tag tag :x x# :y y#) *build-node-list*))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;One of the interesting things here is that you are seeing the function that handles the line, not just my definition of what is on the "nod:" line. In the ocaml version, I had all the keywords in one big match statement and made them call separate functions. I could have implemented the functions in the match statements but I thought it might look ugly. I like the Lisp solution here because I define the line contents and the function in one place, but it isn't all cluttered with other line definitions.&lt;br /&gt;&lt;br /&gt;There are a couple of things going on in defparse. First, it turns the function body into a lambda expression that is mapped in the global keyword hash table. Next, it looks for parameters whose names end in # and automatically converts them from string to integer. This is what the expansion of my (defparse "nod:" ...) looks like:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(SETF (GETHASH "nod:" *COMMAND-HANDLERS*)&lt;br /&gt;        (LAMBDA (NAME TAG #:G4171 #:G4172)&lt;br /&gt;          (LET ((|X#| (PARSE-INTEGER #:G4171)) (|Y#| (PARSE-INTEGER #:G4172)))&lt;br /&gt;            (PUSH (MAKE-INSTANCE 'NODE :NAME NAME :TAG TAG :X |X#| :Y |Y#|)&lt;br /&gt;                  *BUILD-NODE-LIST*))))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Those #:G4171 and #:G4172 names are unique symbol names generated by the gensym function. A macro in Lisp is basically a function whose return value is code that will be compiled. This means that it blends in well with the language - there are a few syntactic differences having to do with quoting, but otherwise, you don't learn a separate macro language. One of the difficulties is that the macros run at compile time, so you can make use of all the functions you have defined (as far as I can tell, at least).&lt;br /&gt;&lt;br /&gt;For the curious, here is my defparse macro:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(defmacro defparse (command param-list &amp;body body)&lt;br /&gt;  (let* ((int-params (remove-if-not&lt;br /&gt;                     #'(lambda (param)&lt;br /&gt;                         (let ((ps (symbol-name param)))&lt;br /&gt;                         (char= (elt ps (1- (length ps))) #\#))) param-list))&lt;br /&gt;         (param-map (mapcar #'(lambda (x) (cons x (gensym))) int-params))&lt;br /&gt;         (param-list-with-syms (mapcar&lt;br /&gt;                      #'(lambda (param) (if (assoc param param-map) (cdr (assoc param param-map)) param))&lt;br /&gt;                      param-list))&lt;br /&gt;         (let-list (mapcar #'(lambda (pg) (list (car pg) (list 'parse-integer (cdr pg)))) param-map)))&lt;br /&gt;    `(setf (gethash ,command *command-handlers*)&lt;br /&gt;           (lambda ,param-list-with-syms&lt;br /&gt;             (let ,let-list ,@body)))))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The thing I am a bit curious about is whether this is a Lispy way to approach the problem. Would a Lisp pro nod his or her head at this, or start to gag?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11347242-112137058768484804?l=devcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://devcode.blogspot.com/feeds/112137058768484804/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11347242&amp;postID=112137058768484804' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11347242/posts/default/112137058768484804'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11347242/posts/default/112137058768484804'/><link rel='alternate' type='text/html' href='http://devcode.blogspot.com/2005/07/lispy-or-not.html' title='Lispy or not?'/><author><name>Mark Wutka</name><uri>http://www.blogger.com/profile/01735952904584567390</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/-FBR1bumy7EM/TrShvjZulMI/AAAAAAAAATQ/c7nnkgqSTLg/s220/mark_arabia_mtn.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11347242.post-112101497197293150</id><published>2005-07-10T13:02:00.000-07:00</published><updated>2006-11-12T17:26:07.601-08:00</updated><title type='text'>My 2005 ICFPC Submission</title><content type='html'>My Ocaml code for the 2005 ICFP Programming Contest is now available at &lt;a href="http://www.wutka.com/download/markwutka_icfpc.tgz"&gt;http://www.wutka.com/download/markwutka_icfpc.tgz&lt;/a&gt;&lt;br /&gt;I'm sorry to say that there is only one barely informative comment. The only other comments are code that has been commented out.&lt;br /&gt;&lt;br /&gt;One of the things I learned last night on IRC was that I can optimize some of my match statements. The parser (parser.ml) has lines like this in its match:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;    | "nod:" :: name :: tag :: x :: y :: [] -&gt; handle_node name (node_tag_of_string tag)&lt;br /&gt;                                                  (int_of_string x) (int_of_string y)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Apparently, I can make this a little shorter with:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;    | ["nod:";name;tag;x;y] -&gt; handle_node name (node_tag_of_string tag)&lt;br /&gt;                                                  (int_of_string x) (int_of_string y)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Although I am happy with my choice of Ocaml for doing this project, I am not happy with my usage of Ocaml. I didn't use the "O" part of it at all - no objects. I did things as modules and it was a little cumbersome. I should have made a generic Bot class and then derived the cop and robber from that. I ended up copying too much code back and forth.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11347242-112101497197293150?l=devcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://devcode.blogspot.com/feeds/112101497197293150/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11347242&amp;postID=112101497197293150' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11347242/posts/default/112101497197293150'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11347242/posts/default/112101497197293150'/><link rel='alternate' type='text/html' href='http://devcode.blogspot.com/2005/07/my-2005-icfpc-submission.html' title='My 2005 ICFPC Submission'/><author><name>Mark Wutka</name><uri>http://www.blogger.com/profile/01735952904584567390</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/-FBR1bumy7EM/TrShvjZulMI/AAAAAAAAATQ/c7nnkgqSTLg/s220/mark_arabia_mtn.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11347242.post-112101364000244496</id><published>2005-07-10T00:25:00.000-07:00</published><updated>2006-11-12T17:26:07.478-08:00</updated><title type='text'>36+7 hours of coding</title><content type='html'>I submitted my final entry for the &lt;a href="http://icfpc.plt-scheme.org/"&gt;2005 ICFP Programming Contest&lt;/a&gt; and the deadline has passed, so now I feel free to share the mini diary I kept while working on the project.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;June 24-27, 2005 - It Begins&lt;br /&gt;&lt;br /&gt;Friday, 7:08 PM&lt;/span&gt;&lt;br /&gt;I'm finally home and eating supper. The contest started 9 hours ago. I had to work today, so the best I have been able to manage is to look through the rules. I am excited to get going. Last night, I did a few tests with Chicken Scheme since I suspected I might have to do some socket code. The LiveCD the contest people put out mentioned something about game servers. Now that I see that I just read from stdin and write to stdout, I am back to Ocaml. The other thing that leads me back to Ocaml is that I will have 5 seconds to make a move each turn, I might need all the speed I can get.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Friday, 7:28 PM&lt;/span&gt;&lt;br /&gt;I'm starting on the parser now. I will make a callback interface similar to the way SAX works to handle each message event. For nested messages like wsk, I will have callbacks for each sub-message. The callback interface will allow me to simulate the server in code later without actually having to do the full protocol.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Friday, 9:24 PM&lt;/span&gt;&lt;br /&gt;It has been a little bumpy with Ocaml, but the problem is a disconnect between the chair and the keyboard. I am getting the parser written now. I have code to dump out the wsk structure, am trying to get it running now.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Friday, 9:54 PM&lt;/span&gt;&lt;br /&gt;Got the basic parser running a little while ago. Now I am adding in support for all the commands the server can send. I have been on #icfpc on freenode for a while now (I am mr_pengy) and it is a blast chatting with these folks. It makes me wish we were all in one big lab.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Friday, 11:48 PM&lt;/span&gt;&lt;br /&gt;All the parsing is coded, now I am trying to build the graphs for foot and car paths. After that I think I may go to bed.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Saturday, 12:14 AM&lt;/span&gt;&lt;br /&gt;I decided to keep a list of foot edges and car edges in each node, so I essentially have two trees. I am going to bring in my old fibheap code and add dijkstra's algorithm so I can do shortest path computations. I want to see if I can compute the shortest path between all points in each tree. There are &amp;lt; 300 nodes in the graph, so that's just a few hundred thousand distances to compute. I'll have to see how long it takes. If the size of the world increases substantially, though, this will be a bad idea. Time for bed now.&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;Saturday, 10:02 AM&lt;/span&gt;&lt;br /&gt;I probably slept a lot later than I should have. I finally got caught up with the ICFPC mailing list – lots of rule clarifications. Time to code.&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;Saturday, 11:57 AM&lt;/span&gt;&lt;br /&gt;If I were to quit now, it wouldn't be a total loss. I was wrestling with trying to squeeze my fibheap code into this project without making it become really ugly. Then I started thinking about alternate ways to compute the distances. I worked out a way to do Dijkstra's shortest path algorithm without a priority queue. Basically, I start with distance D=0 and I iterate through each node N looking for node Nadj with distance=D. Then, I look at each node Nadj' that is an edge node of Nadj. If the distance from N to Nadj' is greater than D+1, I update the distance from N to Nadj' to be D. When I have done that for all nodes, I then repeat the procedure for all nodes with D=1 and so forth, until I do not find a node to update. On my machine, doing this calculation for all 229 nodes takes about 0.03 seconds. The max distance on foot is 29, the max distance by car is 17. This isn't bad considering the map is roughly a 15x15 grid. This is pretty exciting, even though I have yet to write a complete bot, so I am going to get started on a robber bot.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Saturday, 1:15 PM&lt;/span&gt;&lt;br /&gt;Still reorganizing the code and making a bot interface. Still no bot, but this should make it easier to write one. There was a mention on #icfpc to look up the Floyd-Warshall shortest path algorithm, I think that's essentially what I came up with. I am pretty sure mine is O(n^3) like Floyd.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Saturday, 4:16 PM&lt;/span&gt;&lt;br /&gt;I'm working on a robber bot. As a first try, I am having it look for banks that it can get to before the cops do, with a certain margin for error. If it can't find one, it picks another place to go. I'm writing lots of functions that should make it easier to add other behavior.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Saturday, 8:53 PM&lt;/span&gt;&lt;br /&gt;I have a pretty dumb robber bot. He got caught after robbing one bank. It's not that my cop is smart, the robber ran right into him. The robber targeted banks that were farthest away from the cops, but didn't know how to avoid cops in its path. I have been thinking for a while about what to do about that, and my current thinking is that I need to make a new shortest path algorithm that avoids cops. Basically, before traversing an edge, see if the destination falls within some constraints (no cop within 2 spaces, for example). That would allow me to plot a short path around a cop.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Saturday, 10:13 PM&lt;/span&gt;&lt;br /&gt;My robber just made all the way through without getting caught, and having robbed several banks. The cops are still very dumb, and the robber needs some work. His choice of banks is still determined by how far away the cops are, but not how close he is. Also, I need to make some adjustments to make sure it picks valid moves. I had a problem with that and I need to make absolutely sure it validates the move. Still, I feel good about my progress.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Saturday, 10:43 PM&lt;/span&gt;&lt;br /&gt;I figured out where the invalid moves were coming from and made several adjustments there. I also changed the algorithm to go for the closest bank now that the distances take cop proximity into account. If it were to get surrounded right now, it wouldn't be able to pick a path because it wouldn't find nodes that are “safe”. In that case, I will make an emergency flee function. I may let it go for a “less safe” path first, then any path where there is no cop. Otherwise, stay put.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Saturday, 11:45 PM&lt;/span&gt;&lt;br /&gt;I added the emergency flee function, so it should be able to get out of a jam. Tomorrow I have to make a better cop. I submitted an entry already just in case my machine crashes. Can't be too careful.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Sunday, 9 AM&lt;/span&gt;&lt;br /&gt;Over breakfast, I modified the robber's calculations for cop distances to account for cops changing from foot to car. I'm leaving for Meeting for Worship shortly, won't be able to get going again until after noon.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Sunday, 4:04 PM&lt;/span&gt;&lt;br /&gt;I have been working on the cop for a while. I tried assigning the cops a beat where they walked from bank to bank. My robber still got a ton of money. Now I am trying to compute the vicinity where the robber should be.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Sunday, 5:29 PM&lt;/span&gt;&lt;br /&gt;I have been working on smartening up my cop. The contest rules state that in the initial tournament, your cop must win – not just come in the top 3. Because of the way the evidence collection works, that means if the other cops stumble on evidence and you aren't the one to capture the robber, you lose. This seems a little too random for me. My cop now directs the other cops to the general vicinity of the last known location of the robber, adjusting for time (“Our fugitive has been on the run for 90 minutes...”), but also within a certain minimum distance away. The idea is that my cop comes in to the actual area and snoops around. It doesn't quite work that way, but it isn't too bad. Whenever my cop smells the robber, it computes the possible locations of the robber (based on last-known location) and joins that with the locations that are exactly the smell distance away. Then it picks a random one if there are any. My cop can now occasionally beat my robber. I'm going to see what the ratio is.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Sunday, 5:42 PM&lt;/span&gt;&lt;br /&gt;Oops! In computing how far a robber could have moved, I forgot that the robber only moves on every other turn, so the area was much too wide.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Sunday, 5:55 PM&lt;/span&gt;&lt;br /&gt;In 20 games, the robber won 12 and my cop won 8. Also, my cop lost to the other cops in 1 out of those 8.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Sunday, 7:12 PM&lt;/span&gt;&lt;br /&gt;I am really starting to feel tired. This has been a tough project and I am sure I won't win. I would like to be able to get through the regular season part of it, at least. I have modified the robber a little bit. Before, when it couldn't find a regular move, it would look for a “safe” move, which was a move that maximized the distance from the cops. Now, it looks at the set of those moves and tries to maximize the safe moves from that move as well. I could probably play with the logic there a little, but I will first see if that improves its performance against my current cop.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Sunday, 7:27 PM&lt;/span&gt;&lt;br /&gt;The robber won 14 out of 20 this time. It might be just a tiny bit better than before. I started logging its searches and I have seen it get out of a jam when it has picked an emergency move, but usually when it has to do that, it gets caught.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Sunday, 10:03 PM&lt;/span&gt;&lt;br /&gt;I submitted my updated cop &amp; robber. My team name is “O Caml, My Caml”. I just recently put in code to look at the informs from the Mcgruff bots again and now I am starting to see how I might use Bayes theorem to predict user location. Someone mentioned Bayes on #icfpc yesterday, but I didn't know what he was getting at. I googled and found a paper on predicting customer location on a wireless network and now I am beginning to understand. Unfortunately, there are less than 12 hours left, and I know I won't be able to last all night. I don't know if I can create a smarter cop in the next few hours or not. I'll give it a try.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Sunday, 11:07 PM&lt;/span&gt;&lt;br /&gt;I tried a few other things with probabilities, trying to incorporate Bayes theorem, but it seemed to be a little worse than my previous algorithm. Perhaps the Mcgruff bots aren't so good at estimating probabilities. It looks like I'll be sticking with what I have.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Sunday, 11:32 PM&lt;/span&gt;&lt;br /&gt;I just sent in my final submission for the first part of the contest. Time for bed.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Monday, 2:24 AM&lt;/span&gt;&lt;br /&gt;I was in bed with the light off when I realized that if a robber never hit a bank, my cop wouldn't find him. I switched the cop to start off in beat mode. Now I am doing some analysis on what bank a robber hits last before getting caught. So far, "60-and-blackstone" and "53-and-the-other-lake-park" lead by far. I tried eliminating 60&amp;B already and cops won 17 out of 30 times. I am trying again with all banks allowed. Then I will try with 60&amp;amp;B and 53&amp;OLP removed.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Monday, 3:44 AM&lt;/span&gt;&lt;br /&gt;I tried a number of combinations, including picking random banks, the farthest bank, sticking with a bank until it was robbed. In the end, the best strategy was still to aim for the closest bank, but don't rob the bank at 60-and-blackstone. That should be enough right there to disqualify me from the Judge's Prize. NOW I'm going to bed.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;July 9-10, 2005 - And now, The Twist&lt;/span&gt;&lt;br /&gt;The interesting thing about this contest was that after the initial 72-hour period, there was almost a two-week lull, then they announced a change in the rules that we had 24 hours to respond to. I can't say that my response was great, but at least I submitted something.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Saturday, 10:10 AM&lt;/span&gt;&lt;br /&gt;I am in Blacksburg, VA getting ready to come home after a week at the Friends General Conference Gathering. My dorm room at Va. Tech has an internet connection so I have just logged in to start reading the "twist" in the problem specification. UGH! Cops can be bribed! I don't know how I am going to do this. I spend the next 20 minutes looking over the requirements.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Saturday, 3:20 PM&lt;/span&gt;&lt;br /&gt;Ceal is driving right now as I work on my program. I have just adapted my original cop and robber to the new protocol. The robber doesn't offer any bribes and the cop doesn't accept them. At least I have something.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Sunday, 12:45 AM&lt;/span&gt;&lt;br /&gt;I have just submitted my final code. I am really tired after waking up at 6, packing the van and driving about 4 of the 7 hours of the return trip. My robber tried to bribe cops, but my cop does not take bribes. I decided to leave the cop alone. This will probably cost me the judges prize, even though I don't think I had a realistic shot at it to begin with. This has been a fun project and I hope to go back and try to add better strategy to my programs later.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11347242-112101364000244496?l=devcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://devcode.blogspot.com/feeds/112101364000244496/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11347242&amp;postID=112101364000244496' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11347242/posts/default/112101364000244496'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11347242/posts/default/112101364000244496'/><link rel='alternate' type='text/html' href='http://devcode.blogspot.com/2005/07/367-hours-of-coding.html' title='36+7 hours of coding'/><author><name>Mark Wutka</name><uri>http://www.blogger.com/profile/01735952904584567390</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/-FBR1bumy7EM/TrShvjZulMI/AAAAAAAAATQ/c7nnkgqSTLg/s220/mark_arabia_mtn.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11347242.post-111984143561468282</id><published>2005-06-26T19:46:00.000-07:00</published><updated>2006-11-12T17:26:07.406-08:00</updated><title type='text'>Coding my head off</title><content type='html'>It has been a really long time since I posted anything here. This weekend I have been participating in &lt;a href="http://icfpc.plt-scheme.org/"&gt;The Eighth Annual ICFP Programming Contest&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;There were a few accidental clues given before the contest started. The LiveCD they distributed mentioned something about game servers, and the submission instructions mentioned a cop and a robber executable. Thinking that the contest might require some socket programming, I looked at the languages available to see which ones would be best for that. I always had Python and Java to fall back on, but Chicken Scheme seemed like a possibility.&lt;br /&gt;&lt;br /&gt;When the contest was announced on friday, however, the cop and robber executables just had use stdin and stdout for all communication, which left the choice of language pretty wide open. I decided to go with OCaml. There are things about OCaml that really annoy me. I get syntax errors in odd places and I have to put parens in places I wouldn't expect. It is probably just because I don't know the language well enough. When the contest is over, I'd love to have someone who knows the language well to look over my code and tell me what stupid things I do.&lt;br /&gt;&lt;br /&gt;Despite the minor annoyances, I am really happy that I picked OCaml. Toby Reyelts was arguing with me here about static vs. dynamic typing when I first started this blog. I think that OCaml's static type checking really saved me many times on this project. When I changed something significant, the compiler dutifully told me when I broke an interface.&lt;br /&gt;&lt;br /&gt;There will be more about the contest in a future blog entry. I have been keeping a little log during the contest, just updating what I am working with, along with the time, so you get some idea what it might be like. I just don't want to say anything until the contest is over (in 2 weeks, after the requirements change) because I don't want to give away anything to my opponents.&lt;br /&gt;&lt;br /&gt;I submitted a cop &amp; robber a little while ago and I think they may end up being my final entries. It is almost 11pm EDT, so there are only 11 hours left in the contest and I'm really tired. Realistically, I don't think I have any shot at winning. I think that my bots have a good chance of making it out of the regular season round, but I expect them to be trounced in the playoffs.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11347242-111984143561468282?l=devcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://devcode.blogspot.com/feeds/111984143561468282/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11347242&amp;postID=111984143561468282' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11347242/posts/default/111984143561468282'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11347242/posts/default/111984143561468282'/><link rel='alternate' type='text/html' href='http://devcode.blogspot.com/2005/06/coding-my-head-off.html' title='Coding my head off'/><author><name>Mark Wutka</name><uri>http://www.blogger.com/profile/01735952904584567390</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/-FBR1bumy7EM/TrShvjZulMI/AAAAAAAAATQ/c7nnkgqSTLg/s220/mark_arabia_mtn.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11347242.post-111460714223271629</id><published>2005-04-27T05:53:00.000-07:00</published><updated>2006-11-12T17:26:07.341-08:00</updated><title type='text'>The Steele Fortress</title><content type='html'>There has been some discussion on &lt;a href="http://lambda-the-ultimate.org/"&gt;Lambda the Ultimate&lt;/a&gt; about a new language that Guy Steele (of Scheme fame, among other things) has been working on at Sun Labs. It is called Fortress and is targeted towards the same application domain as Fortran. This is *not* Fortran, however. Take a look at this list of features (shamelessly cut&amp;pasted from LtU):&lt;br /&gt;&lt;bl&gt;&lt;br /&gt;&lt;li&gt;an advanced component and linking architecture&lt;/li&gt;&lt;br /&gt;&lt;li&gt;objects and traits (which look similar to Moby and Scala)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;multiple dispatch&lt;/li&gt;&lt;br /&gt;&lt;li&gt;type inference&lt;/li&gt;&lt;br /&gt;&lt;li&gt;parameterized types&lt;/li&gt;&lt;br /&gt;&lt;li&gt;extensible syntax&lt;/li&gt;&lt;br /&gt;&lt;li&gt;first-class functions&lt;/li&gt;&lt;br /&gt;&lt;li&gt;proper tail calls&lt;/li&gt;&lt;br /&gt;&lt;li&gt;labelled jumps, exceptions&lt;/li&gt;&lt;br /&gt;&lt;li&gt;contracts&lt;/li&gt;&lt;br /&gt;&lt;li&gt;some interesting parallelism features (including futures, parallel loops, atomicity primitives, transactions)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;matrices&lt;/li&gt;&lt;br /&gt;&lt;li&gt;comprehensions&lt;/li&gt;&lt;br /&gt;&lt;li&gt;bignums, fixnums (signed and unsigned), floating-point, imaginary and complex numbers&lt;/li&gt;&lt;br /&gt;&lt;li&gt;dimensions&lt;/li&gt;&lt;br /&gt;&lt;/bl&gt;&lt;br /&gt;&lt;br /&gt;It is nice to see type inference popping up again, as well as proper tail calls, parameterized types and contracts (kinda sounds like Nice except for the tail calls).  I have only glanced at the &lt;a href="http://research.sun.com/projects/plrg/fortress0618.pdf"&gt;spec&lt;/a&gt; but one of the interesting things that popped out is that do-loops are assumed to execute in parallel by default. It will be interesting to see what happens with this language.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11347242-111460714223271629?l=devcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://devcode.blogspot.com/feeds/111460714223271629/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11347242&amp;postID=111460714223271629' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11347242/posts/default/111460714223271629'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11347242/posts/default/111460714223271629'/><link rel='alternate' type='text/html' href='http://devcode.blogspot.com/2005/04/steele-fortress.html' title='The Steele Fortress'/><author><name>Mark Wutka</name><uri>http://www.blogger.com/profile/01735952904584567390</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/-FBR1bumy7EM/TrShvjZulMI/AAAAAAAAATQ/c7nnkgqSTLg/s220/mark_arabia_mtn.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11347242.post-111315351405999319</id><published>2005-04-10T09:56:00.000-07:00</published><updated>2006-11-12T17:26:07.272-08:00</updated><title type='text'>On second thought..</title><content type='html'>Well, I was doing pretty well with the lambda-calculus-in-ocaml thing until I tried to define XOR for Church booleans. I defined it as:&lt;br /&gt;&amp;lambda;a.&amp;lambda;b.a (not b) b&lt;br /&gt;&lt;br /&gt;I worked this out on paper and it seems to be correct. It fails when I define it in OCAML as:&lt;br /&gt;let xorx = fun a b -&gt; a (notx b) b;;&lt;br /&gt;&lt;br /&gt;When I say it fails, I mean that I get a type error when I try something like this:&lt;br /&gt;(xorx fls tru) "true" "false"&lt;br /&gt;(or if I just call my print_cbool function). It works if I define xorx as:&lt;br /&gt;let xorx = fun a b -&gt; a (notx b) (b tru fls);;&lt;br /&gt;Since b is supposed to be a boolean, (b tru fls) should be redundant.&lt;br /&gt;&lt;br /&gt;A patient gentleman on the #ocaml channel tried to explain to me why OCAML wasn't good for doing Church booleans, but when I started hearing terms like "predicative polymorphism" and "prenex normal form" I realized that I wasn't going to understand the explanation. I hope I will understand some of these terms better by the time I finish Types and Programming Languages.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11347242-111315351405999319?l=devcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://devcode.blogspot.com/feeds/111315351405999319/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11347242&amp;postID=111315351405999319' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11347242/posts/default/111315351405999319'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11347242/posts/default/111315351405999319'/><link rel='alternate' type='text/html' href='http://devcode.blogspot.com/2005/04/on-second-thought.html' title='On second thought..'/><author><name>Mark Wutka</name><uri>http://www.blogger.com/profile/01735952904584567390</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/-FBR1bumy7EM/TrShvjZulMI/AAAAAAAAATQ/c7nnkgqSTLg/s220/mark_arabia_mtn.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11347242.post-111296696901055534</id><published>2005-04-08T06:21:00.000-07:00</published><updated>2006-11-12T17:26:07.197-08:00</updated><title type='text'>Lambda Calculus and OCAML</title><content type='html'>I've been working my way through &lt;a href="http://www.cis.upenn.edu/%7Ebcpierce/tapl/"&gt;Types and Programming Languages (TAPL)&lt;/a&gt;. Chapter 5 discusses the untyped lambda calculus, which is a theoretical representation of computation that predates computers.&lt;br /&gt;&lt;br /&gt;There are a number of lambda calculus tutorials out on the web, including &lt;a href="http://www.inf.fu-berlin.de/lehre/WS03/alpi/lambda.pdf"&gt;this one (PDF)&lt;/a&gt;. Basically, lambda calculus lets you define functions like this:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&amp;lambda;x.x&lt;/b&gt;&lt;br /&gt;This is a function that takes a single argument x and returns x. A function can only take a single argument, but you can nest functions to handle multiple arguments, like this:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&amp;lambda;x.&amp;lambda;y.x*y&lt;/b&gt;&lt;br /&gt;In this case, the outermost function's return value is a function that multiplies its argument by x.So &lt;b&gt;(&amp;lambda;x.&amp;lambda;y.x*y) 5 3&lt;/b&gt; becomes &lt;b&gt;(&amp;lambda;y.5*y) 3&lt;/b&gt; which becomes 15. This method of converting multiple arguments into nested functions is called &lt;a href="http://en.wikipedia.org/wiki/Currying"&gt;currying&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The thing I find really interesting is that it is very easy to translate basic lambda calculus expressions into OCAML and try them out. For example, I'll start with Church Booleans.&lt;br /&gt;&lt;br /&gt;A Church Boolean is a method of defining true and false as functions. Both functions take two arguments (using the nested notation). True returns its first argument, while false returns its second:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;true = &amp;lambda;t.&amp;lambda;f.t&lt;br /&gt;false = &amp;lambda;t.&amp;lambda;f.f&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;This translates very easily into OCAML (I am using an older form of function declaration because it matches more closely with the lambda calculus form):&lt;pre&gt;&lt;br /&gt;let tru = fun t f -&gt; t;;&lt;br /&gt;let fls = fun t f -&gt; f;;&lt;br /&gt;&lt;/pre&gt;Now, tru and fls are not static values, but functions. This function prints Church booleans  as "true" or "false":&lt;pre&gt;&lt;br /&gt;let print_cbool = fun b -&gt; print_string (b "true" "false");;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;You can define boolean &lt;b&gt;and&lt;/b&gt; in lambda calculus as:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;and = &amp;lambda;a.&amp;lambda;b.a b fls&lt;/b&gt;&lt;br /&gt;Each argument to this function is a boolean function like tru or fls. If a is tru, then it returns its first argument, which is b, otherwise it returns fls. If b is tru, then the result of a and b is tru, otherwise it is fls.&lt;br /&gt;In a similar manner, you can define &lt;b&gt;or&lt;/b&gt; and &lt;b&gt;not&lt;/b&gt; as:&lt;br /&gt;&lt;b&gt;or = &amp;lambda;a.&amp;lambda;b.a tru b&lt;br /&gt;not = &amp;lambda;a.a fls tru&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;In OCAML, these can be defined as:&lt;pre&gt;&lt;br /&gt;let andx = fun a b -&gt; a b tru;;&lt;br /&gt;let orx = fun a b -&gt; a tru b;;&lt;br /&gt;let notx = fun a -&gt; a fls tru;;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;You can then play around with various expressions like:&lt;pre&gt;&lt;br /&gt;print_cbool (andx tru tru);;&lt;br /&gt;print_cbool (andx tru fls);;&lt;br /&gt;print_cbool (andx (notx fls) tru);;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Booleans are fun, but it gets much more interesting when you get into numbers. Church numerals are formed by a combination of two functions s and z. The s function is the "successor" function and z is the zero function. The first few church numerals are defined as:&lt;br /&gt;&lt;b&gt;C(0) = &amp;lambda;s.&amp;lambda;z.z&lt;br /&gt;C(1) = &amp;lambda;s.&amp;lambda;z.s z&lt;br /&gt;C(2) = &amp;lambda;s.&amp;lambda;z.s (s z)&lt;br /&gt;C(3) = &amp;lambda;s.&amp;lambda;z.s (s (s z))&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;If you think of s as "1+" and z as 0, then C(0) = 0, C(1) = 1+ 0, C(2) = 1+ (1+ 0), etc.&lt;br /&gt;I defined a function p1 as shorthand for adding 1, and created a print_church function to display an integer version of a Church numeral:&lt;pre&gt;&lt;br /&gt;let p1 = (+) 1;;&lt;br /&gt;let print_church = fun c -&gt; print_int (c p1 0);;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;In this case, p1 is a partial function, the (+) operator takes two arguments, but since I only supplied 1, p1 actually returns a function that adds 1 to its argument.&lt;br /&gt;&lt;br /&gt;Now, since I don't want to manually define each Church numeral, I defined a simple function that generates Church numerals:&lt;pre&gt;&lt;br /&gt;let rec church = fun n s z-&gt;&lt;br /&gt;  if n = 0 then z&lt;br /&gt;  else s (church (n-1) s z);;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;If you call &lt;b&gt;print_church (church 55)&lt;/b&gt; you'll see &lt;b&gt;55&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;It is also possible to define the addition operation. Since a Church numeral is essentially defined by adding 1 over and over starting from 0, addition can just be defined as adding 1 over and over starting from another number, like this:&lt;br /&gt;&lt;b&gt;plus=&amp;lambda;a.&amp;lambda;b.&amp;lambda;s.&amp;lambda;z.a s (b s z)&lt;/b&gt;&lt;br /&gt;That is, instead of the usual z function, let a's z function be the evaluation of b (instead of counting from 0, a is calculated by starting from b). In OCAML, this can be defined as:&lt;pre&gt;&lt;br /&gt;let plus = fun a b s z -&gt; a s (b s z)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;If you call &lt;b&gt;print_church (plus (church 12) (church 34))&lt;/b&gt; you should see a result of &lt;b&gt;46&lt;/b&gt;.&lt;br /&gt;Multiplication can be defined in a similar way. Instead of adding 1 every time, you add b, like this:&lt;br /&gt;&lt;b&gt;mult=&amp;lambda;a.&amp;lambda;b.&amp;lambda;s.&amp;lambda;z.a (b s) z&lt;/b&gt;&lt;br /&gt;In OCAML, this is:&lt;pre&gt;&lt;br /&gt;let mult = fun a b s z -&gt; a (b s) z;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Again, using print_church, you can test the mult function. If you call &lt;b&gt;print_church (mult (church 12) (church 34))&lt;/b&gt; you should see &lt;b&gt;408&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;You can get a little closer to the lambda calculus notation by using only single arguments in function definitions:&lt;pre&gt;&lt;br /&gt;let tru = fun t -&gt; fun f -&gt; t;;&lt;br /&gt;let fls = fun t -&gt; fun f -&gt; f;;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11347242-111296696901055534?l=devcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://devcode.blogspot.com/feeds/111296696901055534/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11347242&amp;postID=111296696901055534' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11347242/posts/default/111296696901055534'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11347242/posts/default/111296696901055534'/><link rel='alternate' type='text/html' href='http://devcode.blogspot.com/2005/04/lambda-calculus-and-ocaml.html' title='Lambda Calculus and OCAML'/><author><name>Mark Wutka</name><uri>http://www.blogger.com/profile/01735952904584567390</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/-FBR1bumy7EM/TrShvjZulMI/AAAAAAAAATQ/c7nnkgqSTLg/s220/mark_arabia_mtn.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11347242.post-111255756754537978</id><published>2005-04-03T12:05:00.000-07:00</published><updated>2006-11-12T17:26:07.118-08:00</updated><title type='text'>OCAML oddity</title><content type='html'>I kept getting this message from OCAML saying:&lt;br /&gt;&lt;b&gt;This expression has type map_path but is here used with type 'a&lt;br /&gt;The type constructor map_path would escape its scope.&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;The error was occurring when I was trying to add a record to a Hashtbl. Here is a shorter piece of code that will generate the same error:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;let ht=Hashtbl.create 100;;&lt;br /&gt;type footype={foo1:int;foo2:int};;&lt;br /&gt;Hashtbl.add ht "foo" {foo1=5;foo2=10};;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;You'll get an error that the constructor footype would escape its scope. The thing that seems odd to me is that this error occurs because the hash table was created before the type was known, even though the hash table hasn't really been bound to a specific type yet. If you just reverse the order of the first two statements, everything works:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;type footype={foo1:int;foo2:int};;&lt;br /&gt;let ht=Hashtbl.create 100;;&lt;br /&gt;Hashtbl.add ht "foo" {foo1=5;foo2=10};;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Although the error message is a bit confusing, the error itself makes sense when you think about it. The reason it is an error is that if you had to explicitly declare the type of the hash table when you created it, you wouldn't be able to because footype hasn't been declared yet. Once you realize that, even the error message makes sense. The type is declared after the hash table, so it was not "in scope" when the table was created. This makes more sense if you think of the statements as really being nested inside successive lets, although this isn't valid OCAML syntax:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;let ht=Hashtbl.create 100 in&lt;br /&gt;   let type footype={foo1:int;foo2:int} in&lt;br /&gt;      Hashtbl.add ht "foo" {foo1=5; foo2=10};&lt;br /&gt;      ht;;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Written like this, you see that the scope of footype would really be within the scope of "let ht=".. and you shouldn't be able to see footype outside of the let. Since the let returns the table, though, you would be violating the scoping rules. Again, that's not exactly how OCAML does it, but it makes sense when you think of it this way.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11347242-111255756754537978?l=devcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://devcode.blogspot.com/feeds/111255756754537978/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11347242&amp;postID=111255756754537978' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11347242/posts/default/111255756754537978'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11347242/posts/default/111255756754537978'/><link rel='alternate' type='text/html' href='http://devcode.blogspot.com/2005/04/ocaml-oddity.html' title='OCAML oddity'/><author><name>Mark Wutka</name><uri>http://www.blogger.com/profile/01735952904584567390</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/-FBR1bumy7EM/TrShvjZulMI/AAAAAAAAATQ/c7nnkgqSTLg/s220/mark_arabia_mtn.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11347242.post-111202560805474387</id><published>2005-03-31T09:26:00.000-08:00</published><updated>2006-11-12T17:26:07.050-08:00</updated><title type='text'>Fibonacci heap consolidate function</title><content type='html'>While redoing my fib heap code in OCAML, I figured out a nice tail-recursive way to do part of the heap consolidation function. The pseudo-code of the algorithm, as specified in &lt;a href="http://highered.mcgraw-hill.com/sites/0070131511/information_center_view0/"&gt;CLRS&lt;/a&gt; is:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;CONSOLIDATE(H)&lt;br /&gt;  for i := 0 to d(n[H])&lt;br /&gt;    fo A[i] := NIL&lt;br /&gt;&lt;br /&gt;  for each node w in the root list of H&lt;br /&gt;    do x &lt;= w&lt;br /&gt;       d := degree[x]&lt;br /&gt;       while A[d] != NIL&lt;br /&gt;         do y := A[d]&lt;br /&gt;           if key[x] &gt; key[y]&lt;br /&gt;             then exchange x &lt;-&gt; y&lt;br /&gt;           FIB-HEAP-LINK (H,y,x)&lt;br /&gt;           A[d] := nil&lt;br /&gt;           d := d + 1&lt;br /&gt;       A[d] := x&lt;br /&gt;  min[H] := nil&lt;br /&gt;  for i := 0 to D(n[H])&lt;br /&gt;    do if A[i] != NIL&lt;br /&gt;         then add A[i] to the root list of H&lt;br /&gt;              if min[H] = nil or key[A[i]] &lt; key[min[H]]&lt;br /&gt;                then min[H] := A[i]&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I tend to split this into two pieces. The first part (the "for each node w ...") creates an array of root-level nodes, each with a different degree (number of children). If two nodes have the same degree, one becomes the child of the other - the one with the lower key being the parent. Once this array has been created, the second part wipes out the old root list and re-inserts the new nodes, adjusting the min pointer to point to the node with the lowest key.&lt;br /&gt;&lt;br /&gt;The second part, in OCAML, looks like this:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;let fh_consolidate2 heap node =&lt;br /&gt;  match node with&lt;br /&gt;      Empty -&gt; ()&lt;br /&gt;    | Node(n) -&gt;&lt;br /&gt;        if is_empty heap.min then&lt;br /&gt;          heap.min &lt;- node&lt;br /&gt;        else&lt;br /&gt;          (fh_splice_nodes heap.min node;&lt;br /&gt;           if (heap.compare_func n.data (as_fh_node_rec heap.min).data) then&lt;br /&gt;             heap.min &lt;- node);;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;I call fh_consolidate2 using an iterator (see my earlier blog on partial functions if you don't understand how I can pass (fh_consolidate2 heap) this way):&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Array.iter (fh_consolidate2 heap) a;;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The first part is more interesting because it is a pain to write in OCAML. The LISP version looks like this:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;    (do* ((num-roots (fib-heap-node-list-length (fib-heap-min heap)) (decf num-roots))&lt;br /&gt;      (x (fib-heap-min heap) next)&lt;br /&gt;      (d (fib-heap-node-degree x) (fib-heap-node-degree x))&lt;br /&gt;      (next (fib-heap-node-right x) (fib-heap-node-right x)))&lt;br /&gt;     ((&lt;= num-roots 0))&lt;br /&gt;      (do ((y (aref a d) (aref a d)))&lt;br /&gt;      ((null y))&lt;br /&gt;    (when (funcall (fib-heap-compare-func heap)&lt;br /&gt;               (fib-heap-node-data y) (fib-heap-node-data x))&lt;br /&gt;      (let ((temp x))&lt;br /&gt;        (setf x y)&lt;br /&gt;        (setf y temp)))&lt;br /&gt;    (fib-heap-link x y)&lt;br /&gt;    (setf (aref a d) nil)&lt;br /&gt;    (incf d))&lt;br /&gt;      (setf (aref a d) x))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;As you can see, this is pretty much an imperitive Lisp version of the pseudo-code. &lt;br /&gt;One observation I made was that since I am clearing out the root level of the heap, I can go ahead and do that as I iterate through the heap. I created a destructive foreach that removes nodes from the heap as it goes through. Since the list is circular, the loop is done when a node's right pointer points to itself (meaning it is the last one):&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;let destructive_foreach f node =&lt;br /&gt;  match node with&lt;br /&gt;      Empty -&gt; ()&lt;br /&gt;    | Node(n) -&gt;&lt;br /&gt;        let rec foreach_iter curr next =&lt;br /&gt;          fh_remove_from_list curr;&lt;br /&gt;          (f curr);&lt;br /&gt;          if next != curr then&lt;br /&gt;            (foreach_iter next next.right)&lt;br /&gt;        in&lt;br /&gt;          foreach_iter n n.right;;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now that destructive_foreach handles the "for each node w in the root list of H", I just need a better way to store the nodes in the A array. The "while A[d] != NIL" loop is really just a loop that looks for an empty slot in A. I rewrote the loop as a tail recursive procedure like this:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  let rec put_in_slot x =&lt;br /&gt;    let d = x.degree in&lt;br /&gt;      if is_empty a.(d) then&lt;br /&gt;        a.(d) &lt;- Node(x)&lt;br /&gt;      else&lt;br /&gt;        (let y = (as_fh_node_rec a.(d)) in&lt;br /&gt;           a.(d) &lt;- Empty;&lt;br /&gt;           if heap.compare_func x.data y.data then&lt;br /&gt;             (fh_link x y; put_in_slot x)&lt;br /&gt;           else&lt;br /&gt;             (fh_link y x; put_in_slot y))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Basically, look at the degree of x, if a[d] is empty, put x in there. Otherwise, pull the item out of a[d] and call it y. Link x and y together and then look for a slot to put the new joined-together nodes. Now, the guts of the consolidate routine just look like this:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;    destructive_foreach put_in_slot heap.min;&lt;br /&gt;    heap.min &lt;- Empty;&lt;br /&gt;    Array.iter (fh_consolidate2 heap) a;;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11347242-111202560805474387?l=devcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://devcode.blogspot.com/feeds/111202560805474387/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11347242&amp;postID=111202560805474387' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11347242/posts/default/111202560805474387'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11347242/posts/default/111202560805474387'/><link rel='alternate' type='text/html' href='http://devcode.blogspot.com/2005/03/fibonacci-heap-consolidate-function.html' title='Fibonacci heap consolidate function'/><author><name>Mark Wutka</name><uri>http://www.blogger.com/profile/01735952904584567390</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/-FBR1bumy7EM/TrShvjZulMI/AAAAAAAAATQ/c7nnkgqSTLg/s220/mark_arabia_mtn.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11347242.post-111195317597960716</id><published>2005-03-27T11:43:00.001-08:00</published><updated>2006-11-12T17:26:06.977-08:00</updated><title type='text'>Followup on "Duh!"</title><content type='html'>One of the things that has been bothering me about my "Duh!" moment is that it seems like a bit of a cop-out. I shouldn't have to use a list to represent a null reference - I &lt;i&gt;should&lt;/i&gt; be able to represent it using the Empty | Node of 'a fh_node_rec. I decided to go back and make the code work the way I originally thought it should, and except for a few lingering bugs with decreasing a key value, I have the heap working with Empty representing null.&lt;br /&gt;&lt;br /&gt;Two things that helped me a lot were the definition of an is_empty function:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;let is_empty node =&lt;br /&gt;    match node with&lt;br /&gt;        Empty -&gt; true&lt;br /&gt;     | x -&gt; false;;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;and as as_fh_node_rec that is essentially like a cast (there may be a built-in way to do this in OCaml, I just don't know about it):&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;let as_fh_node_rec node =&lt;br /&gt;    match node with&lt;br /&gt;        Empty -&gt; failwith "Expected fh_node_rec, found empty"&lt;br /&gt;       | Node(n) -&gt; n;;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;When I need to refer to an fh_node_rec as a Node, I can just do Node(x). The combination of these things made the solution a little more palatable, but it is still a bit of an annoyance.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11347242-111195317597960716?l=devcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://devcode.blogspot.com/feeds/111195317597960716/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11347242&amp;postID=111195317597960716' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11347242/posts/default/111195317597960716'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11347242/posts/default/111195317597960716'/><link rel='alternate' type='text/html' href='http://devcode.blogspot.com/2005/03/followup-on-duh.html' title='Followup on &quot;Duh!&quot;'/><author><name>Mark Wutka</name><uri>http://www.blogger.com/profile/01735952904584567390</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/-FBR1bumy7EM/TrShvjZulMI/AAAAAAAAATQ/c7nnkgqSTLg/s220/mark_arabia_mtn.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11347242.post-111163746433346148</id><published>2005-03-23T19:57:00.000-08:00</published><updated>2006-11-12T17:26:06.820-08:00</updated><title type='text'>DUH!</title><content type='html'>I had a "Duh!" moment this evening. A "Duh!" moment is an "Aha!" moment where you say "Aha! I am an idiot!". I have been translating my Fibonacci Heap code from Lisp to OCAML. In my implementation, a heap node has left and right pointers for storing nodes in a circular list, and also parent and child pointers. Since a pointer could be null, I defined a type that could be either Empty or an fh_node_rec object, like this:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;type 'a fh_node_rec = {&lt;br /&gt;    mutable data : 'a;&lt;br /&gt;    mutable parent : 'a fh_node;&lt;br /&gt;    mutable left : 'a fh_node_rec;&lt;br /&gt;    mutable right : 'a fh_node_rec;&lt;br /&gt;    mutable child : 'a fh_node;&lt;br /&gt;    mutable degree : int;&lt;br /&gt;    mutable mark : bool;&lt;br /&gt;} and 'a fh_node = Empty | Node of 'a fh_node_rec;;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;So, mistake number one was that the left and right pointers were a different type from the parent and child. This got really complicated when I started processing the lists. When handling the left and right nodes, I could work directly with fh_node_rec types, but for parent and child, I had to use match, like:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;match x with&lt;br /&gt;    Empty -&gt; ()&lt;br /&gt;  | Node(xn) -&gt; (* do something with xh as an fh_node_rec *)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;I ended up defining multiple functions, some that worked with fh_node and others that worked with fh_node_rec. I started to have trouble keeping track of whether something was an fh_node or an fh_node_rec. I really had trouble when writing the consolidate function. In fact, I never could get it right.&lt;br /&gt;&lt;br /&gt;I came across a paper called &lt;a href="http://sdg.csail.mit.edu/~dnj/teaching/6898/projects/vicente-wagner.pdf"&gt;Design Patterns in OCaml&lt;/a&gt; by Antonio Vicente and Earl Wagner that suggested using a list to represent items that may be null, using [] to represent null. That's when I just wanted to slap my forehead for not thinking of it before. I was able to define a single record type:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;type 'a fh_node = {&lt;br /&gt;    mutable data : 'a;&lt;br /&gt;    mutable parent : 'a fh_node list;&lt;br /&gt;    mutable left : 'a fh_node;&lt;br /&gt;    mutable right : 'a fh_node;&lt;br /&gt;    mutable child : 'a fh_node list;&lt;br /&gt;    mutable degree : int;&lt;br /&gt;    mutable mark : bool;&lt;br /&gt;};;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;I was able to eliminate all the duplicate functions and I got the consolidate function written. It was much easier to see if a node was equal to [] than it was to see if it was either an Empty type or an fh_node. Once I get the rest of the code finished and working, I'll post it on my web site.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11347242-111163746433346148?l=devcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://devcode.blogspot.com/feeds/111163746433346148/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11347242&amp;postID=111163746433346148' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11347242/posts/default/111163746433346148'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11347242/posts/default/111163746433346148'/><link rel='alternate' type='text/html' href='http://devcode.blogspot.com/2005/03/duh.html' title='DUH!'/><author><name>Mark Wutka</name><uri>http://www.blogger.com/profile/01735952904584567390</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/-FBR1bumy7EM/TrShvjZulMI/AAAAAAAAATQ/c7nnkgqSTLg/s220/mark_arabia_mtn.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11347242.post-111158799844818051</id><published>2005-03-23T06:04:00.000-08:00</published><updated>2006-11-12T17:26:06.740-08:00</updated><title type='text'>Partial functions in OCAML</title><content type='html'>OCAML supports something called "partial functions". Suppose you define a function that takes two arguments and adds them together:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;let adder x y = x + y;;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;You can obviously call &lt;b&gt;adder 2 3&lt;/b&gt; and expect to get back 5. OCAML lets you call &lt;b&gt;adder 2&lt;/b&gt; and get back a function that adds 2 to whatever argument you pass it. For example:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;let add2 = adder 2;;&lt;br /&gt;let add3 = adder 3;;&lt;br /&gt;Printf.print "%d %d\n" (add2 5) (add3 7);;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;You would see "7 10" printed out.&lt;br /&gt;&lt;br /&gt;I must admit, my first reaction to this was "Neat. So what?" I am starting to see the usefulness of it, however. In Scheme, if I want to loop through a list and add 5 to every member of the list, I can do something like this:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(map (lambda (x) (+ x 5)) '(1 2 3 4 5 6))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;In OCAML, you &lt;i&gt;could&lt;/i&gt; do this:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;List.map (function x -&gt; (x + 5)) [1;2;3;4;5];;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Since I have defined my adder function, though, I can do this instead:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;List.map (adder 5) [1;2;3;4;5];;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;I think the trick to taking advantage of partial functions may be to determine which arguments are likely to change and place those last. For example, if I have a function called heap_consolidate, I can define it as:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;let heap_consolidate x heap = (* do something with x and the heap *)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;or I can do:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;let heap_consolidate heap x = (* do something with x and the heap *)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;If I am going to be passing a lot of different x values for the same heap, especially if I want to iterate through a list or an array, I might want to make heap the first parameter so I can do something like this:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;List.map (heap_consolidate myheap) myheap.root;;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;If heap is the second argument, I would have to do:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;List.map (function x -&gt; heap_consolidate x myheap) myheap.root;;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;While partial functions may seem error-prone, I don't think that is the case. If you accidentally omit a function argument, OCAML's type checker will notice that you are using a function type where it is expecting you to use something else. Without type checking, partial functions seem pretty dangerous.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11347242-111158799844818051?l=devcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://devcode.blogspot.com/feeds/111158799844818051/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11347242&amp;postID=111158799844818051' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11347242/posts/default/111158799844818051'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11347242/posts/default/111158799844818051'/><link rel='alternate' type='text/html' href='http://devcode.blogspot.com/2005/03/partial-functions-in-ocaml.html' title='Partial functions in OCAML'/><author><name>Mark Wutka</name><uri>http://www.blogger.com/profile/01735952904584567390</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/-FBR1bumy7EM/TrShvjZulMI/AAAAAAAAATQ/c7nnkgqSTLg/s220/mark_arabia_mtn.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11347242.post-111115781034913246</id><published>2005-03-18T06:20:00.000-08:00</published><updated>2006-11-12T17:26:06.676-08:00</updated><title type='text'>OCAML and Type inference</title><content type='html'>I have been playing around with OCAML a bit. I was amazed at how well it did in the &lt;a href="http://shootout.alioth.debian.org/great/benchmark.php?test=all&amp;lang=all&amp;sort=fullcpu"&gt;Great Computer Language Shootout&lt;/a&gt;, so I decided to see what it was like.&lt;br /&gt;&lt;br /&gt;After working with Scheme and Lisp for a while, OCAML is really not that different. Where you might do (let ((x 1) (y 2)) (something)) in Lisp, you do:&lt;br /&gt;let x=1 and y=2 in something;;&lt;br /&gt;&lt;br /&gt;I really haven't gotten into the meat of the language yet - I've really just been playing with the CAML part and not the O. Any way, OCAML was my first encounter with type inference (that I can recall, at least). OCAML is strictly typed, but you don't usually have to indicate the type of a variable. The OCAML compiler figures it out. If a function can accept different types of variables, that's okay, too.&lt;br /&gt;&lt;br /&gt;For example, here is a simple recursive function that removes all occurrences of x from a list:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;let rec remove x l =&lt;br /&gt;    match l with&lt;br /&gt;        [] -&gt; []&lt;br /&gt;    | h::t -&gt; if x == h then remove x t else h::(remove x t)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Because of the usage, l must be a list. If I try to pass anything else as the second parameter to remove, I will get an error at compile time. The x parameter can be any type, but it must match the type of elements in l. So, I can do this:&lt;br /&gt;&lt;b&gt;remove 3 [1;2;3;4;5];;&lt;/b&gt;&lt;br /&gt;or&lt;br /&gt;&lt;b&gt;remove 'B' ['A','B','C','D'];;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;I can't do:&lt;br /&gt;&lt;b&gt;remove 'A' [1;2;3;4;5];;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;The interesting thing is that these errors get caught at compile time. I don't declare any types in my definition of remove, the compiler just figures out the type restrictions at compile time. Now, if I add a print statement to print out x as an integer value, I am now constraining x to be only an integer (and l to be only a list of integers):&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;let rec remove2 x l =&lt;br /&gt;    match l with&lt;br /&gt;        [] -&gt; []&lt;br /&gt;    | h::t -&gt; if x == h then ((Printf.printf "Removed %d\n" x);remove2 x t)&lt;br /&gt;        else h::(remove2 x t)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now I can still do:&lt;br /&gt;&lt;b&gt;remove2 3 [1;2;3;4;5];;&lt;/b&gt;&lt;br /&gt;but I now get an error if I try to do:&lt;br /&gt;&lt;b&gt;remove2 'B' ['A','B','C','D'];;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Last night I took a little Chicken Scheme program that I had written to solve the puzzle USA+USSR=PEACE and rewrote it in OCAML. It is a brute force program and isn't the most efficient way to do it, but it only took a few minutes to write:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(require-extension srfi-1 srfi-13 format)&lt;br /&gt;(define usa "USA")&lt;br /&gt;(define ussr "USSR")&lt;br /&gt;(define peace "PEACE")&lt;br /&gt; &lt;br /&gt;(define digit-pool '(0 1 2 3 4 5 6 7 8 9))&lt;br /&gt;(define letter-pool '(#\U #\S #\A #\R #\P #\E #\C))&lt;br /&gt; &lt;br /&gt;(define (word-to-number word letter-table)&lt;br /&gt;  (let ((sum 0))&lt;br /&gt;    (string-for-each&lt;br /&gt;      (lambda (x) (set! sum (+ (* 10 sum) (cdr (assoc x letter-table))))) word)&lt;br /&gt;    sum))&lt;br /&gt; &lt;br /&gt;(define print-solution (lambda (letter-table)&lt;br /&gt;  (format #t "~A + ~A = ~A~%"&lt;br /&gt;          (word-to-number usa letter-table)&lt;br /&gt;          (word-to-number ussr letter-table)&lt;br /&gt;          (word-to-number peace letter-table))))&lt;br /&gt; &lt;br /&gt;(define test-solution (lambda (letter-table)&lt;br /&gt;  (when (= (+ (word-to-number usa letter-table)&lt;br /&gt;              (word-to-number ussr letter-table))&lt;br /&gt;           (word-to-number peace letter-table))&lt;br /&gt;    (print-solution letter-table))))&lt;br /&gt; &lt;br /&gt;(define try-letter (lambda (letters digits letter-table)&lt;br /&gt;  (cond ((null? letters) (test-solution letter-table))&lt;br /&gt;        (#t&lt;br /&gt;         (let ((curr-letter (first letters))&lt;br /&gt;               (curr-letter-pool (cdr letters)))&lt;br /&gt;          (for-each (lambda (digit)&lt;br /&gt;            (try-letter curr-letter-pool&lt;br /&gt;                        (delete digit digits)&lt;br /&gt;                        (alist-cons curr-letter digit letter-table)))&lt;br /&gt;        digits))))))&lt;br /&gt;   &lt;br /&gt;(try-letter letter-pool digit-pool '())&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I was able to just about translate the program without any major rewriting:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;let usa = "USA";;&lt;br /&gt;let ussr = "USSR";;&lt;br /&gt;let peace = "PEACE";;&lt;br /&gt; &lt;br /&gt;let digit_pool = [0;1;2;3;4;5;6;7;8;9];;&lt;br /&gt;let letter_pool = ['U';'S';'A';'R';'P';'E';'C'];;&lt;br /&gt; &lt;br /&gt;let word_to_number word letter_table =&lt;br /&gt;    let rec rec_word_to_number pos num =&lt;br /&gt;        if pos &gt;= (String.length word) then num&lt;br /&gt;            else rec_word_to_number (pos + 1) (num * 10 +&lt;br /&gt;                (List.assoc word.[pos] letter_table)) in&lt;br /&gt;    rec_word_to_number 0 0;;&lt;br /&gt; &lt;br /&gt;let print_solution letter_table =&lt;br /&gt;    Printf.printf "%d + %d = %d\n" (word_to_number usa letter_table)&lt;br /&gt;        (word_to_number ussr letter_table)&lt;br /&gt;        (word_to_number peace letter_table);;&lt;br /&gt; &lt;br /&gt;let test_solution letter_table =&lt;br /&gt;    if (word_to_number usa letter_table) + (word_to_number ussr letter_table)&lt;br /&gt;        = (word_to_number peace letter_table) then&lt;br /&gt;            print_solution letter_table;;&lt;br /&gt; &lt;br /&gt;let rec remove x l =&lt;br /&gt;    match l with&lt;br /&gt;        [] -&gt; []&lt;br /&gt;    | h::t -&gt; if x == h then remove x t else h::(remove x t)&lt;br /&gt; &lt;br /&gt;let rec try_letter letters digits letter_table =&lt;br /&gt;    match letters with&lt;br /&gt;        [] -&gt; (test_solution letter_table)&lt;br /&gt;    | curr_letter::curr_letter_pool -&gt;&lt;br /&gt;            List.iter (function digit -&gt;&lt;br /&gt;                (try_letter curr_letter_pool (remove digit digits)&lt;br /&gt;                    ((curr_letter,digit)::letter_table))) digits;;&lt;br /&gt; &lt;br /&gt;try_letter letter_pool digit_pool [];;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Although the code is pretty similar, the OCAML version runs more than twice as fast as the Chicken Scheme version. I think that a lot of the speed difference is due to the fact that OCAML knows the type of everything ahead of time. The cool thing, though, is that I didn't have to tell OCAML about the types, it figured them out on its own.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11347242-111115781034913246?l=devcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://devcode.blogspot.com/feeds/111115781034913246/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11347242&amp;postID=111115781034913246' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11347242/posts/default/111115781034913246'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11347242/posts/default/111115781034913246'/><link rel='alternate' type='text/html' href='http://devcode.blogspot.com/2005/03/ocaml-and-type-inference.html' title='OCAML and Type inference'/><author><name>Mark Wutka</name><uri>http://www.blogger.com/profile/01735952904584567390</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/-FBR1bumy7EM/TrShvjZulMI/AAAAAAAAATQ/c7nnkgqSTLg/s220/mark_arabia_mtn.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11347242.post-111050638351995771</id><published>2005-03-10T17:30:00.000-08:00</published><updated>2006-11-12T17:26:06.601-08:00</updated><title type='text'>Communicating with the outside world</title><content type='html'>Many languages provide something a mechanism to call into external libraries. I thought I'd mention two ways this is done, one in Lisp and another in Python. The example I am using for Python uses the dynamic libraries package. There is also an excellent package called &lt;a href="http://starship.python.net/crew/theller/ctypes/"&gt;ctypes&lt;/a&gt; that works well under Windows, Linux and MacOS X.&lt;br /&gt;&lt;br /&gt;I have a C library that works with &lt;a href="http://www.wutka.com/dawg.html"&gt;Directed Acyclic Word Graphs&lt;/a&gt;, specifically, the type of file used to store words for the Hasbro Scrabble game. I use the DAWG for automated cryptogram solvers as well. The C library is available at &lt;a href="http://www.wutka.com/download/dawg.c"&gt;http://www.wutka.com/download/dawg.c&lt;/a&gt;. If you want to play with this, the dictionary file is available at &lt;a href="http://www.wutka.com/download/twl98.daw"&gt;http://www.wutka.com/download/twl98.daw&lt;/a&gt;. The 3 functions that you would care about are:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;int load_dawg(char *filename); // Load the DAWG into memory&lt;br /&gt;int match(char *word); // Returns non-zero if WORD is a valid word in the dawg&lt;br /&gt;int longest_match(char *word); // Returns the length of the longest word found at the beginning&lt;br /&gt;                               // of the string passed in. (MARKFOOBAR would return 4, &lt;br /&gt;                               // since MARK is valid, but MARKF isn't)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Under Linux, I compiled this into a shared library with the following commands:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;gcc -fPIC -c dawg.c&lt;br /&gt;gcc -shared -Wl,-soname,libdawg.so.1 -o libdawg.so.1 dawg.o&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now, from Python, I can use dl.open and dl.call to invoke these functions:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;import dl&lt;br /&gt;&lt;br /&gt;dawglib=dl.open("libdawg.so.1")&lt;br /&gt;&lt;br /&gt;def dawg_open(filename):&lt;br /&gt;    return dawglib.call("load_dawg", filename)&lt;br /&gt;&lt;br /&gt;def dawg_match(word):&lt;br /&gt;    return dawglib.call("match", word)&lt;br /&gt;&lt;br /&gt;def dawg_longest_match(word):&lt;br /&gt;    return dawglib.call("longest_match", word)&lt;br /&gt;&lt;br /&gt;dawg_open("twl98.daw")&lt;br /&gt;&lt;br /&gt;print "FOO=%d" % (dawg_match("FOO"))&lt;br /&gt;print "AA=%d" % (dawg_match("AA"))&lt;br /&gt;print "A=%d" % (dawg_match("A"))&lt;br /&gt;print "MARK=%d" % (dawg_match("MARK"))&lt;br /&gt;print "longest PRINTFOOBAR=%d" % (dawg_longest_match("PRINTFOOBAR"))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;As you can see, I wrapped these calls with convenience methods. I do the same thing in the Lisp code below, which uses the &lt;a href="http://uffi.b9.com/"&gt;Universal Foreign Function Interface&lt;/a&gt;.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(uffi:load-foreign-library #p"libdawg.so.1" :module "dawg" :supporting-libraries '("c"))&lt;br /&gt;&lt;br /&gt;(uffi:def-function ("load_dawg" dawg-load-c) ((name :cstring)) :module "dawg" :returning :int)&lt;br /&gt;(uffi:def-function ("match" dawg-match-c) ((word :cstring)) :module "dawg" :returning :int)&lt;br /&gt;(uffi:def-function ("longest_match" dawg-longest-match-c) ((word :cstring))&lt;br /&gt;  :module "dawg" :returning :int)&lt;br /&gt;&lt;br /&gt;(defun dawg-load (filename)&lt;br /&gt;  (let* ((c-filename (uffi:convert-to-cstring filename))&lt;br /&gt;        (result (dawg-load-c c-filename)))&lt;br /&gt;    (uffi:free-cstring c-filename)&lt;br /&gt;    result))&lt;br /&gt;&lt;br /&gt;(defun dawg-match (word)&lt;br /&gt;  (let* ((c-word (uffi:convert-to-cstring word))&lt;br /&gt;        (result (dawg-match-c c-word)))&lt;br /&gt;    (uffi:free-cstring c-word)&lt;br /&gt;    result))&lt;br /&gt;&lt;br /&gt;(defun dawg-longest-match (word)&lt;br /&gt;  (let* ((c-word (uffi:convert-to-cstring word))&lt;br /&gt;        (result (dawg-longest-match-c c-word)))&lt;br /&gt;    (uffi:free-cstring c-word)&lt;br /&gt;    result))&lt;br /&gt;&lt;br /&gt;(defun run-test ()&lt;br /&gt;  (dawg-load "twl98.daw")&lt;br /&gt;  (format t "FOO=~A~%" (dawg-match "FOO"))&lt;br /&gt;  (format t "AA=~A~%" (dawg-match "AA"))&lt;br /&gt;  (format t "A=~A~%" (dawg-match "A"))&lt;br /&gt;  (format t "MARK=~A~%" (dawg-match "MARK"))&lt;br /&gt;  (format t "longest PRINTFOOBAR=~A~%" (dawg-longest-match "PRINTFOOBAR")))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Again, I defined convenience methods, mostly because I needed to allocate and free the C strings. It's really nice when a language lets you use external library without having to write any glue code in C or some other language.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11347242-111050638351995771?l=devcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://devcode.blogspot.com/feeds/111050638351995771/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11347242&amp;postID=111050638351995771' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11347242/posts/default/111050638351995771'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11347242/posts/default/111050638351995771'/><link rel='alternate' type='text/html' href='http://devcode.blogspot.com/2005/03/communicating-with-outside-world.html' title='Communicating with the outside world'/><author><name>Mark Wutka</name><uri>http://www.blogger.com/profile/01735952904584567390</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/-FBR1bumy7EM/TrShvjZulMI/AAAAAAAAATQ/c7nnkgqSTLg/s220/mark_arabia_mtn.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11347242.post-111042476285343363</id><published>2005-03-09T18:48:00.000-08:00</published><updated>2006-11-12T17:26:06.505-08:00</updated><title type='text'>Fun With Lisp</title><content type='html'>I have occasionally played with Lisp and Scheme in the past, but never long enough to get a good feel for the language. Lately, however, I have spent a significant amount of time working with Lisp and I am really beginning to appreciate the beauty of the language.&lt;br /&gt;&lt;br /&gt;I have started a &lt;a href="http://www.wutka.com/lisp.html"&gt;web page for Lisp stuff&lt;/a&gt; where I will put some of the interesting things I come up with. So far, it has an implementation of the Fibonacci Heap, which I can tell you is a bear to implement. I also have an implementation of Dijkstra's Shortest Path algorithm and some code to parse Tiger/Line files.&lt;br /&gt;&lt;br /&gt;Why do I think Lisp is cool?&lt;br /&gt;&lt;br /&gt;First of all, the syntax is extremely simple. Yes, there are a lot of parentheses, but I think the reason that they stand out so much is that, apart from quotes, there's not a lot of punctuation required. You don't have to end statements with a semi-colon, or put commas between list items, or put curly braces around statements. It is simple and direct.&lt;br /&gt;&lt;br /&gt;First class functions are really cool, as well. Although they are not unique to Lisp, first class functions are not found in Java, which is my current day-job-language. By saying a function is "first class", it means that a function has the same status as other data items. You can pass a function as a parameter to another function. You can store functions in other data structures. You could, for example, iterate over a list and apply each function in the list to a particular piece of data. This would make it easier to apply business rules, for example. You can do this in Java with Interfaces, it's just a bit easier in Lisp.&lt;br /&gt;&lt;br /&gt;There are lots of functions for dealing with data structures. For all the different containers that Java has, it really falls down on the job when it comes to actually using them. One of the things that always impressed me about Smalltalk was the things you could do with containers (Ruby has this as well, and Python's list comprehensions are close enough). In Lisp, for example, there is the (map) function, which in its simple form is just like iterating through a list with a for loop.&lt;br /&gt;For example:&lt;br&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;b&gt;(mapc #'print '(1 2 3 4 5 6 7))&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;loops through a list and calls the (print) function for each item in the list. There are numerous (map) functions, some return no result, some return a list of the result of applying the function. Where the (map) functions excel beyond a simple loop, however, is that it can use multiple lists and invoke functions that take more than one argument. A simple example would be adding together corresponding elements in two lists:&lt;br&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;b&gt;(mapcar #'+ '(1 2 3 4 5) '(6 7 8 9 10))&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;which returns the list &lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;b&gt;(7 9 11 13 15).&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;There are other cool things, one last one I'd like to mention is that a Lisp environment tends to be highly interactive. You can write some functions and immediately interact with them from a Lisp prompt.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11347242-111042476285343363?l=devcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://devcode.blogspot.com/feeds/111042476285343363/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=11347242&amp;postID=111042476285343363' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11347242/posts/default/111042476285343363'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11347242/posts/default/111042476285343363'/><link rel='alternate' type='text/html' href='http://devcode.blogspot.com/2005/03/fun-with-lisp.html' title='Fun With Lisp'/><author><name>Mark Wutka</name><uri>http://www.blogger.com/profile/01735952904584567390</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://3.bp.blogspot.com/-FBR1bumy7EM/TrShvjZulMI/AAAAAAAAATQ/c7nnkgqSTLg/s220/mark_arabia_mtn.jpg'/></author><thr:total>7</thr:total></entry></feed>
