Back 10 entriesOctober 29, 2005 to November 28, 2007Forward 10 entries

Cool cl-ppcre reader macros November 28, 2007

I've long been a fan of cl-ppcre, the common lisp perl regular expression library. I've hated constructing the expressions, though - regular expressions tend to use backslashes, which must be escaped when including in strings. Backslash escaping can quickly get out of hand.

Lisp is whatever language you want, right? So I used the reader macro functionality to make regular-expression generating syntax.


(eval-when (:compile-toplevel :load-toplevel :execute)
  (defparameter *regex-macro-character* #\/)

  (defun read-regex-string (stream)
    (let ((eof (gensym "EOF")))
      (with-output-to-string (str)
        (loop for prev-char = nil then cur-char
           for cur-char = (read-char stream nil eof)
           until (or (eql cur-char eof)
                     (and (not (eql prev-char #\\))
                          (eql cur-char *regex-macro-character*)))
           do (write-char cur-char str)

           finally (when (eql cur-char eof)
                     (error "Unexpected end-of-file while reading regex"))))))

  (defun read-regex-options (stream)
    (let ((eof (gensym "EOF")))
      (loop for char = (read-char stream nil eof)
         until (or (eql char eof)
                   (not (alphanumericp char)))
         collect char)))

  (defun read-regex (stream char arg)
    (declare (ignore char arg))
    (let ((pattern (read-regex-string stream))
          (options (read-regex-options stream)))
      `(eval-when (:compile-toplevel :load-toplevel :execute)
         (cl-ppcre:create-scanner ,pattern
                                  :case-insensitive-mode ,(member #\i options)
                                  :multi-line-mode ,(member #\m options)
                                  :single-line-mode ,(member #\s options)
                                  :extended-mode ,(member #\x options)))))

  (defun %enable-regex-reader-syntax ()
    (set-dispatch-macro-character #\# *regex-macro-character* #'read-regex)
    (values)))

(defmacro enable-regex-reader-syntax ()
  `(eval-when (:compile-toplevel :load-toplevel :execute)
    (%enable-regex-reader-syntax)))

;; This allows syntax such as #/foo/im

I also wrote a function called SCAN which takes a regular expression and returns a regexp-result object, which can then be used by REGREF to acquire the register strings. This is far less clumsy, I think, than the variable binding macros that come with cl-ppcre..


(defclass regex-result ()
  ((target :accessor target-of :initarg :target)
   (pattern :accessor pattern-of :initarg :pattern)
   (match-start :accessor match-start-of :initarg :match-start)
   (match-end :accessor match-end-of :initarg :match-end)
   (reg-starts :accessor reg-starts-of :initarg :reg-starts)
   (reg-ends :accessor reg-ends-of :initarg :reg-ends)))

(defun regref (result idx)
  (assert result (result) "NIL regex-result passed to regref")
  (cond
    ((zerop idx)
      (subseq (target-of result)
              (match-start-of result)
              (match-end-of result)))
    ((null (aref (reg-starts-of result) (1- idx)))
     nil)
    (t
      (subseq (target-of result)
              (aref (reg-starts-of result) (1- idx))
              (aref (reg-ends-of result) (1- idx))))))

(defun scan (regex target &key start end)
  (assert target nil "Target for SCAN is NIL")
  (multiple-value-bind (match-start match-end reg-starts reg-ends)
      (cl-ppcre:scan regex target :start (or start 0) :end (or end (length target)))
    (when match-start
      (make-instance 'regex-result
                     :target target
                     :pattern regex
                     :match-start match-start
                     :match-end match-end
                     :reg-starts reg-starts
                     :reg-ends reg-ends))))

;; Use like:
;;  (scan #/foo(o+)/i "Foooo") => #<REGEX-RESULT>
;;  (regref * 0) => Foooo
;;  (regref ** 1) => oo

Hopefully this snippet will be useful to others.


No comments posted. Post a comment!

Answer in a Python forum August 22, 2006

> What is a closure? I keep reading this word in programming, but never got a good explanation.

People always come up with the generator case, and I think that's the worst way of all to show off closures. Where they really come in handy is introducing lexical scoping.

Lexical scoping just means that the environment is defined by the context in the code, not in runtime. An example in Common Lisp:

(defun add-to-list (list number)
  (map 'list
       (lamba (x)
         (+ x number))
       list)))

This is a function called ADD-TO-LIST that takes a list and adds a number to each of its elements. DEFUN defines a function, MAP applies a function to each element of a list, and LAMBDA defines an anonymous function.

Now consider the anonymous function - it references both X, a parameter to the function, and NUMBER, which is a parameter to add-to-list. It must have access to NUMBER regardless of the context in which it's called. So it's placed into a closure, where all the variables in its environment are available. In that way, MAP doesn't have to worry about providing access to variables.

This is the primary advantage closures have over other function-variable patterns, like function pointers or functors. Anonymous functions declared in-place "just work."


No comments posted. Post a comment!

More lispyness July 11, 2006

I saw a blog entry comparing languages in terms of terseness. I agree that the ruby version maximizes both terseness and readability, but I couldn't help but make my own contribution in common lisp:


(loop for flipcount = 0 then (read)
      for numbers = (sort (loop for i from 1 upto 9 collect i)
                          (lambda (a b) (zerop (random 2))))
      then (nconc (reverse (subseq numbers 0 flipcount))
                  (subseq numbers flipcount))
      as steps from 0
      until (apply #'< numbers) do
      (format t "~{~a~^ ~}~%Reverse how many? " numbers)
      (force-output)
      finally (format t "~{~a~^ ~}~%Done!  That took you ~a steps.~%" numbers steps))

Muhahaha.


1 comment posted. Post a comment!

07/15/2006 - Ozone: Very nice solution, I really like the "sort by random".


Car wreck May 10, 2006

Ow.

It was a dark and stormy night. Around 7:00, Haplo, Asha and I were coming home from take out Chinese. The rain was beating down on the car, making it difficult to see even with the windshield wipers oscillating as fiercely as they could. We stopped to turn onto our street.

Wham! We get hit from behind!

So we were both a lot fuzzy and not sure at all what the proper thing to do was. I got out (in the pouring rain), and went down to the other car. Other people had already stopped and were calling 911. I didn't see the driver of the other car, but one of the people calling had gotten in her car. I got back in our own car and waited for the police.

When the police came, I sat in the back of the police car while he got the other driver. She was Mexican and spoke about as much English as I did Spanish. We got the paperwork out of the way, I kicked the rest of the obliterated bumper off my car, and we went home.

We dropped off the dog, got into some dry clothes, and left in her car to go to the emergency room of the hospital. My shoulder was hurting pretty badly, and she said her neck hurt. I suspected a fracture, and we were worried about soft tissue injuries. By the time we got there, it was around 8pm. We ate our chinese in the emergency room and waited.

By the time we got treated, it was 10pm. In their defense, we were probably just getting bumped by more severe problems. One of the staff told me while I was making my way to the emergency room that she had seen a bad wreck with four ambulances. It seems likely that they were having bigger problems than we were.

We got X-rays, a clean bill of health, and a prescription for pain killers. We went home at 11pm. Asha was supposed to be working on her finals tonight, and helping give an exam early next morning, but both of those have been blown. I've got a business trip tomorrow, but I don't think it'll be that strenuous, so I'm probably going to go. Suckage.

We hurt all over, but I feel like we got out lucky. I'm profoundly grateful for my little Celica, which took a rear-end hit at about 45 mph and left us without a scratch. The other car was completely totalled - the hood was crumpled up almost to the windshield. The material in our bumper was strewn about 50 feet down the road.

Haplo is entirely unharmed, and very put out about not getting his evening walk.

Beat up Celica


1 comment posted. Post a comment!

05/12/2006 - BLake: Ouch, glad to hear you all are ok.


Germany trip May 01, 2006

Only took a couple of months, but I finally have pictures of my Germany trip for everyone to see. I wanted to add more description to the pictures, but the styling wouldn't really go with that. I might change the style pretty soon to be more like Flickr's.


No comments posted. Post a comment!

The Wii...TF? April 27, 2006

I've been excited about the new Nintendo console system for a very long time. The one codenamed "Revolution." Nintendo officially named it today: It's now the "Wii."

Now what was the problem with "Revolution" as a name? And why the hell did they decide that "Wii" was a good idea. There are some marketing people in there that seriously need to be fired.

So, in all fun and seriousness, I set up a petition at iPetition to have them change the name back. I'll send it to Nintendo's feedback page in a few days.

I also posted it to Digg and SlashDot. That will ensure that only enlightened, thoughtful comments end up in the petition.


1 comment posted. Post a comment!

05/01/2006 - Ida: Like I said in your petiton, good luck with it! Seriously, though, I hate the name. If Nintendo doesn't change it, I'm giving up gaming. Yes, I've signed.


Interesting new website February 21, 2006

The good: I managed to get an mpg of my TV debut as a "data storage expert." The bad: it's 80 megabytes - I'm looking for a way to shrink it. The ugly: Me on TV. The camera really does add ten pounds and ten years.

I found an interesting website today called LinkedIn. It's essentially a social networking website, like Orkut or Sixdegrees. What makes it different (and interesting) is that it's focused on business and jobs. So if you're looking for sales contacts, services, or new employment, you can check to see if friends of friends have something.

In a job market where you have to know people to get anywhere, it seems like it could be quite useful.

Update: I was able to shrink the movie to 9MB. Enjoy.


I'm a TV expert! February 01, 2006

Just thought I'd pop in to tell people that I did an interview today on WVTM Channel 13 in Birmingham on how to keep data from rotting away. I discussed ways CD-Rs could fail, how to pick a good one, making a backup and hardware replacement policy, and keeping your stuff in a "Cool, Dry, and Dark" place for maximum lifespan.

Great stuff. I'll post when I find out the date and time of the showing, and perhaps I'll be able to through my clip up on the intarweb.


No comments posted. Post a comment!

Because all the cool kids are doing it... December 05, 2005

These are the Top 20 Geek Novels with the ones I've read in bold

  1. The HitchHiker's Guide to the Galaxy -- Douglas Adams
  2. 1984 -- George Orwell
  3. Brave New World -- Aldous Huxley
  4. Do Androids Dream of Electric Sheep? -- Philip Dick
  5. Neuromancer -- William Gibson
  6. Dune -- Frank Herbert
  7. I, Robot -- Isaac Asimov
  8. Foundation -- Isaac Asimov
  9. The Colour of Magic -- Terry Pratchett
  10. Microserfs -- Douglas Coupland
  11. Snow Crash -- Neal Stephenson
  12. Watchmen -- Alan Moore & Dave Gibbons
  13. Cryptonomicon -- Neal Stephenson
  14. Consider Phlebas -- Iain M Banks
  15. Stranger in a Strange Land -- Robert Heinlein
  16. The Man in the High Castle -- Philip K Dick
  17. American Gods -- Neil Gaiman
  18. The Diamond Age -- Neal Stephenson
  19. The Illuminatus! Trilogy -- Robert Shea & Robert Anton Wilson
  20. Trouble with Lichen - John Wyndham

While I'm very satisfied with my level of geeky acumen, I'm glad to see I still have some reading to do.


Car pic October 29, 2005

It struck me today that I hadn't put up pictures of the new car. I know, I know. It's been a year. Here it is.

Celica pic

Back 10 entriesOctober 29, 2005 to November 28, 2007Forward 10 entries