This is a read-only archive!

75 Posts Tagged 'Lisp' RSS

Keyword Arguments: Ruby, Clojure, Common Lisp

And suddenly I return to blogging, rising from the ashes like some kind of zombie phoenix. Turns out writing a book is a good absorber of time, like some sort of heavy-duty temporal paper towel. Now that I've gotten the terrible similes out of my system, let's talk about keyword arguments, one of my favorite features in any language that supports them.

Ruby, Clojure, and Common Lisp are all languages I enjoy to some degree, and they all have keyword arguments. Let's explore how keyword args differ in those languages.

June 24, 2011 @ 10:22 AM PDT
Cateogory: Programming
Tags: Lisp, Ruby, Clojure

I'm turning into a Lisp snob

Reddit and StackOverflow and other websites I frequent are filled to the brim with discussion of Google's Go. The code snippet on the front page is:

package main

import "fmt"

func main() {
  fmt.Printf("Hello, 世界\n")

First thoughts that ran through my head as I looked over the site:

  • Ugh, look at all that syntax.
  • Nice(r) type system (than C++ and Java). I'll stick with multimethods though.
  • Concurrency semantics, hmmm... Shared mutable memory between threads? I think I'll stick with Clojure for now thanks.
  • Where are the macros?
  • It has anonymous functions and closures and sort-of first-class functions? Good. Welcome to the 1960's.
  • len is a special operator? Sigh. (Programming language quality is usually inversely proportional to the number of special forms.)
  • Cool that they used Japanese in the example though. (That word is sekai, "world", obviously.)

Compared to a Lisp, this language looks indistinguishable to C, Perl, Python, Java etc. It looks like such a small incremental improvement (if it even is an improvement). Yet another imperative, for-loop-wielding, curly-brace-using, pointer-mangling, state-mutating, OOP language.

In fact via Reddit today I read this awesome post to a mailing list which compares Go with ALGOL68, and it gave me a would-you-look-at-that moment. Once you learn a few languages that are significantly different from ALGOL derivatives, all ALGOLish languages start to look eerily similar. Are we really stuck with ALGOL-derived languages being the only viable mainstream languages for all time? How much polish can we possibly apply to the same turd?

Then I realized, I'm turning into a Lisp snob. : ( Learning a Lisp apparently does spoil you for the rest of time. I am without a basis to judge whether this language will be a successful replacement of anything. All I know is I probably won't use it. Honestly I'm much more excited about new things on the horizon in Clojure. And I still have getting better at Haskell on my TODO list.

November 13, 2009 @ 2:38 PM PST
Cateogory: Programming
Tags: Lisp, Go, Clojure

Emacs Clojure colors

In yet another step along the path of trying to forcibly morph Emacs into Vim, I started a port of my Vim color scheme Gentooish to an Emacs color-theme.

Then I threw a few lines at the bottom of .emacs to highlight a few more Clojure-specific things when in clojure-mode. Result:


This is inspired partly by parenface.el which dims parens so they don't stand out as much. Lispers have this silly meme where they pretend they can't see parens at all, but being a mere human I want Emacs to help blend them into the background a bit.

I want to dim parens but also make braces and brackets pop out a bit more. Coloring braces, brackets and parens slightly differently helps make a few things easier to read in my opinion, especially in ))]}])) kinds of situations (like at the end of the function above).

This is pretty brute-force and I really wish I could figure out how to highlight #{} (sets) differently than {} (hash-maps). Highlighting (), '(), `(), and #() differently would be awesome too. But that is well beyond my elisp skills at the present. Certain areas of Emacs are all but impenetrable, no matter how much documentation I read and how much banging on the keyboard I do. The morass that is font-lock is one of those areas.

p.s. I find an easy way to keep your dotfiles in git is to make a folder (called dotfiles or something) and symlink your dotfiles from there to your home directory. I also put * in .gitignore so git doesn't slurp up anything sensitive by accident.

October 30, 2009 @ 12:02 PM PDT
Cateogory: Programming

Sort a Clojure map by two or more keys

Note to self. Given this:

user> (def x [{:foo 2 :bar 11}
              {:bar 99 :foo 1}
              {:bar 55 :foo 2}
              {:foo 1 :bar 77}])


How do you sort by :foo, and where :foo is equal, sort by :bar?

Obviously not like this:

user> (sort x)
; Evaluation aborted.
;; java.lang.ClassCastException: clojure.lang.PersistentArrayMap cannot be cast to java.lang.Comparable

Also not like this:

user> (sort-by #(map % [:foo :bar]) x)
; Evaluation aborted.
;; java.lang.RuntimeException: java.lang.ClassCastException: clojure.lang.LazySeq cannot be cast to java.lang.Comparable

What's a guy got to do to find something Comparable? Well, vectors are Comparable, so we can do this:

user> (sort-by #(vec (map % [:foo :bar])) x)
({:foo 1, :bar 77} {:bar 99, :foo 1} {:foo 2, :bar 11} {:bar 55, :foo 2})
October 20, 2009 @ 7:23 PM PDT
Cateogory: Programming

Now I have two problems

I'm converting one of my websites from Ruby on Rails to Clojure in my spare time. I stupidly put a bunch of RoR-style links inline into certain bits of plaintext content, so in my DB there are a bunch of text fields with <%= link_to ... %> in the middle.

It was easy to fix with a regex though:

(defn clean [txt]
  (re-gsub #"<%=\s*link_to\s+(\"[^\"]+\"|'[^']+')\s*(?:,\s*'([^']+)'\s*)?(?:,\s*image_path\(['\"]([^'\"]+)['\"]\)\s*)?(?:,\s*:controller\s*=>\s*(?::(\S+)|['\"]([^\"']+)['\"])\s*)?(?:,\s*:action\s*=>\s*(?::(\S+)|['\"]([^\"']+)['\"])\s*)?(?:,\s*:id\s*=>\s*(?:(\d+)|:(\S+)|['\"]([^\"']+)['\"])\s*)?\s*%>"
           (fn [[_ s & parts]] (let [href (str-join "/" (filter identity parts))]
                           (str "<a href=\"/" href "\">" (re-gsub #"^[\"']|[\"']$" "" s) "</a>")))

And by easy, I mean not easy.

Note to self, try something other than a regex next time.

Note to self, don't bury some framework's funky-syntax DSL in the middle of plaintext content. Next time use HTML or do the conversion from DSL to HTML early rather than late.

Silly how two years ago I thought I'd be using Ruby for that site forever.

September 25, 2009 @ 4:02 PM PDT
Cateogory: Programming

Church Numerals in Clojure

Church Numerals are a way of encoding natural numbers using lambda expressions. A number n is represented by a function that composes another function f around its argument x, n times. So:

0 ≡ λf.λx. x
1 ≡ λf.λx. f x
2 ≡ λf.λx. f (f x)

These can be implemented very easily in Lisps and other languages with first-class functions. In Clojure, this would be:

0 ≡ (fn [f] (fn [x] x))
1 ≡ (fn [f] (fn [x] (f x)))
2 ≡ (fn [f] (fn [x] (f (f x))))

The insane thing is that you can do arithmetic on these things using nothing but more anonymous functions. It's lambdas all the way down.

Once you understand this, your brain will explode, and hopefully little bits of it will land next to the remnants of my own brain to keep it company.

So based on the Wikipedia article, here are some functions that convert numbers to and from Church encoding, and then some functions to do basic arithmetic on Church numerals. I understand this down to exp (via lots of pencil and paper expansions) but I gave up understanding at pred.

(defn church
  "Convert a natural number to a Church numeral."
  (loop [n n, acc (fn [f] (fn [x] x))]
    (if (zero? n)
      (recur (dec n)
             (fn [f]
               (fn [x]
                 (f ((acc f) x))))))))

(defn unchurch
  "Convert a Church numeral to a plain integer."
  ((n inc) 0))

(def plus
     (fn [m]
       (fn [n]
         (fn [f]
           (fn [x]
             ((m f) ((n f) x)))))))

(def mult 
     (fn [m]
       (fn [n]
         (fn [f]
          (n (m f))))))

(def exp
     (fn [m]
       (fn [n]
         (n m))))

(defn pred [n]
  (fn [f]
    (fn [x]
      (((n (fn [g]
             (fn [h]
               (h (g f)))))
        (fn [u] x))
       (fn [u] u)))))

(def sub
     (fn [m]
       (fn [n]
         ((n pred) m))))

(def is-zero?
     (fn [n]
       ((n (fn [x] 'FALSE)) 'TRUE)))

And this somehow actually works:

user> (unchurch (fn [f] (fn [x] (f (f (f (f (f (f (f x))))))))))
user> (unchurch (church 7))
user> (unchurch ((plus (church 2)) (church 3)))
user> (unchurch ((mult (church 2)) (church 3)))
user> (unchurch ((exp (church 2)) (church 3)))
user> (unchurch ((sub (church 7)) (church 3)))
user> (is-zero? (church 0))
user> (is-zero? (church 7))

This is the kind of thing I wish I'd studied more in college. I covered some cool stuff, some small amount of theory of computation and whatnot, but not nearly enough of this. Not enough functional programming, not enough Lispy goodness.

A lot of people say all programmers should learn assembler language so you understand what's happening at a low level. But shouldn't it be just as important to learn lambda calculus? It's another kind of low level, a very important one at that.

September 15, 2009 @ 7:14 PM PDT
Cateogory: Programming

Adventures in blogging

So my newest site is about pareidolia which I think is an interesting subject. It's still in its early stages, using a data import from yet another of my old sites that I ran with a friend of mine. This makes three websites I'm running out of the same JVM on my server now. It'll be interesting to see how many more I can cram in there before my VPS explodes. CPU and RAM utilization are still supposedly minimal. I actually plan to redo my old faltering FF1 site entirely in Clojure too, which is probably the largest Clojure project I plan to undertake in the foreseeable future.

I'm still trying to come up with some kind of "how to make a blog in Clojure" tutorial once I nail down a good way to do it. The code for my blog has "grown organically" (i.e. become a mess) beyond the point where I'd inflict it upon the world without substantial cleanup. Probably easier to start over from scratch with something that's more demonstrative.

I'm also not too savvy on many of the "right ways" to do things in Compojure, as per this discussion. That's the good and bad thing about using a Lisp. You can pull off almost anything. There is no underlying structure to the code other than structure you impose. It's easy to write a mess.

August 03, 2009 @ 5:24 PM PDT
Cateogory: Programming

Making image thumbnails in Clojure

I'm making a new website (in Clojure of course) and I have a need to resize uploaded images to make thumbnails. At first I tried to use JMagick because I'm familiar with ImageMagick already and it seemed like an OK library. But on the crusty old OS my VPS uses, I had a really hard time getting it to build, and even once it built it started segfaulting like mad.

Should've gone with something simpler first. Java has built-in libraries for this. It only took a few seconds to adapt this code on Stack Overflow into Clojure code.

(use '
(defn make-thumbnail [filename new-filename width]
  (let [img (javax.imageio.ImageIO/read (as-file filename))
        imgtype (java.awt.image.BufferedImage/TYPE_INT_ARGB)
        width (min (.getWidth img) width)
        height (* (/ width (.getWidth img)) (.getHeight img))
        simg (java.awt.image.BufferedImage. width height imgtype)
        g (.createGraphics simg)]
    (.drawImage g img 0 0 width height nil)
    (.dispose g)
    (javax.imageio.ImageIO/write simg "png" (as-file new-filename))))
August 02, 2009 @ 4:32 PM PDT
Cateogory: Programming
Tags: Lisp, Java, Clojure

Tokyo Cabinet, Engage

I posted recently about being dissatisfied with how my blog was playing with MySQL. I was going to try for some kind of file-based storage, but in the end I decided to go with Tokyo Cabinet, which is a very lightweight key/value store.

This simplifies a lot of code, because a blog is pretty much one list of objects (posts) with a bunch of sub-objects (tags, categories, comments). An SQL DB is made for independent objects that are related to each other via keys. So storing a post means deconstructing it into its parts and stuffing all the parts into their own tables, and fetching a post means fetching all the parts and putting it back together. A bit of a bother.

With a key/value store, a post is a hashmap, and it has sub-lists of comments and tags etc., and you serialize the whole thing and stuff it into the DB; when fetching you un-serialize it and you're good. Clojure being a Lisp, there's already a nice serialization format (s-expressions), so there's hardly any work to be done.

I'll give it a few days and if everything actually works, I'll push the code to github. The code is still pretty nasty and ad-hoc; I did this rewrite in the matter of a couple of hours on a weekend. But parts of it may be useful to someone.

I also plan to do some kind of simplified "How to make a blog in Clojure" tutorial in the near future. The code for this blog is bloated with a lot of functionality that is pretty specific to my site and that most people don't need. A more to-the-point tutorial would probably be more helpful.

This post is related to Who needs a DB?
July 05, 2009 @ 1:50 PM PDT
Cateogory: Programming

Clojure, SLIME, ODBC, SQL Server

I had a lot of trouble connecting to an MS SQL Server at work via Clojure. Java 6 comes with a JDBC-ODBC bridge which worked fine from a Clojure REPL at a command prompt, or from inferior-lisp in Emacs, but in SLIME it would hang every time I tried to connect and I'd have to kill Java. Couldn't for the life of me figure out why.

I got it to work eventually by using Microsoft's own JDBC driver, which you can download here.

Once you put the downloaded .jar file on your CLASSPATH (in my case, sqljdbc4.jar) you can connect like this:

user> (def db {:classname ""
               :subprotocol "sqlserver"
               :subname "//server_hostname;database=SomeDatabase;user=SomeUser;password=SomePassword"})
user> (use 'clojure.contrib.sql)
user> (with-connection db 
        (with-query-results rs ["SELECT * FROM whatever"] (prn rs)))
... results ...

Posted for the sake of Googlebot and for my own future sanity.

June 26, 2009 @ 4:27 AM PDT
Cateogory: Programming