The Hobbit Hole

In a hole there lived a hobbit. Not a nasty, dirty, wet hole, filled with the ends of worms and an oozy smell, nor yet a dry, bare, sandy hole with nothing in it to sit down on or to eat: it was a hobbit-hole, and that means comfort.

12/29/2006

Scheme Feature Expressions (cont…)

Filed under: Programming — bilbo @ 2:29 pm

This is just a little note for myself and anyone else who might have used the feature expressions and found them not working when within a module.  You need to define any features at the top level.

This means that to use feature expressions in a module you must do something like this:

(require (lib "feature-expressions.ss"))
(add-feature ':testing)

(module mymod mzscheme
  #+:testing (display "This is a test")
)

Hope the holidays found you happy and the new year finds you inspired to try something new.

12/12/2006

XNA Game Studio Express

Filed under: Programming — bilbo @ 9:26 am

XNA Game Express Studio is out!  I really like the idea behind this product.  The ability to write games for either Windows and the Xbox 360 is very appealing.  I’m just that kind of person.  I bought an HP48 because it could do graphs and I could write software for it.  I bought a PS2 because I could get PS2 Linux.  This is certainly one more reason to get a 360, besides Assassin’s Creed. :)

I can’t say I really have a plan for it.   I just like tinkering.

There are some things to not like about it for sure.  For one, and this is unsubstantiated, but I believe it only allows you to write C#, not C++ or other .NET languages even.  Still, C# is a decent language, if not my favorite.

12/1/2006

Scheme Feature Expressions

Filed under: Programming — bilbo @ 11:57 pm

So I’ve taken a small break from Lisp to play around with Scheme. I was intrigued by Bill Clementson’s claim that the best open source Lisp was PLT Scheme.

To just test things out, I played around with the FFI that I was using for porting Omega. It’s nice and clean and worked, at least on Windows. I did notice though that Scheme lacks feature expressions, or conditional compilation for Lisp. A few hours later scanning the docs, and PLT Scheme now supports them, thanks to its integrated reader macro support.

Here is the entire implementation:

(module feature-expressions mzscheme

(provide *features* enable-conditional-compile add-feature remove-feature)

  ;; Provides raise-read-error and raise-read-eof-error
(require (lib "readerr.ss" "syntax")
         (prefix ^ (lib "1.ss" "srfi")))

; this is the list of features that the feature expressions check against
; when compiling
(define *features* '(plt scheme))

(define add-feature
  (lambda (feature)
    (unless (member feature *features*)
      (set! *features* (cons feature *features*)))))

(define remove-feature
  (lambda (feature)
    (^remove! (lambda (f) (eq? f feature)) *features*)))

(define eval-feature-expression
  (lambda (fexp)
    (letrec ((in-feature
              (lambda (feature)
                ;(display feature)
                ;(newline)
                (cond
                  ((and (symbol? feature) (eq? feature 'and))
                   'and)
                  ((and (symbol? feature) (eq? feature 'or))
                   'or)
                  ; if it's a pair or list, then evaluate that sub expression
                  ((pair? feature)
                   (map in-feature feature))
                  ((symbol? feature)
                   (if (member feature *features*) #t #f))
                  ; #f evaluates to #f of course
                  ((eq? feature #f)
                   #f)
                  ; any object that isn't a symbol will evaluate to #t
                  (else
                   #t)))))
      (if (pair? fexp)
          (eval (map in-feature fexp))
          (in-feature fexp)))))

(define enable-conditional-compile
  (lambda ()
    (let ((cond-dispatch
             (case-lambda
               ((ch port)
                (let ((fexp (read port))) ; (read/recursive port #f (current-readtable)))
                  (cond ((eq? ch #\+)
                         (unless (eval-feature-expression fexp)
                           (begin (read port) (void))))
                        ((eq? ch #\-)
                         (when (eval-feature-expression fexp)
                           (begin (read port) (void))))
                        (else
                         (error 'feature-expressions "something bad happened.  Unknown char ~v" ch)))))
               ((ch port src line col pos)
                (let ((fexp (read port))) ; (read/recursive port #f (current-readtable)))
                  (cond ((eq? ch #\+)
                         (unless (eval-feature-expression fexp)
                           (begin (read port) (void))))
                        ((eq? ch #\-)
                         (when (eval-feature-expression fexp)
                           (begin (read port) (void))))
                        (else
                         (error 'feature-expressions "something bad happened.  Unknown char ~v" ch))))))))
      (current-readtable
       (make-readtable (current-readtable)
                       #\+ 'dispatch-macro cond-dispatch
                       #\- 'dispatch-macro cond-dispatch))
      (current-readtable))))

; set the feature expressions in the current readtable
(current-readtable (enable-conditional-compile))
)

I thought it was pretty straightforward. I really like case-lambda. Add support for constants and types in addition to parameters and you’d almost have Haskell like pattern invocations. Hmm….