First GNU Guile Patch and More Guix Packages

November 22, 2013

I have spent some of the last month working on contributing to GNU Guile and now I can finally say that I have contributed code to the project. Guile has several hash table implementations: a Guile native one, SRFI-69, and R6RS. SRFI-69 contains a handy procedure, alist->hash-table, which allows for a sort of hash literal-like syntax:

(alist->hash-table
 '((foo . 1)
   (bar . 2)
   (baz . 3)))

However, I prefer to use Guile’s native hash implementation, and SRFI-69 is incompatible with it, so I decided to port alist->hash-table. Unfortunately, it was not as simple as writing just one procedure. The native hash tables actually have 4 different ways of doing key comparisons: Using equal?, eq?, eqv?, and user-defined procedures. This is a design flaw because the user must make sure to use the right procedures at all times rather than simply set the hash and assoc procedures when creating the hash table instance.

Below is the final implementation. Since 3 of the 4 variations were essentially the same, I wrote a short macro to reduce code duplication.

;;;; Copyright (C) 2013 Free Software Foundation, Inc.
;;;;
;;;; This library is free software; you can redistribute it and/or
;;;; modify it under the terms of the GNU Lesser General Public
;;;; License as published by the Free Software Foundation; either
;;;; version 3 of the License, or (at your option) any later version.
;;;;
;;;; This library is distributed in the hope that it will be useful,
;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
;;;; Lesser General Public License for more details.
;;;;
;;;; You should have received a copy of the GNU Lesser General Public
;;;; License along with this library; if not, write to the Free Software
;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
;;;;

(define-syntax-rule (define-alist-converter name hash-set-proc)
  (define (name alist)
    "Convert ALIST into a hash table."
    (let ((table (make-hash-table)))
      (for-each (lambda (pair)
                  (hash-set-proc table (car pair) (cdr pair)))
                (reverse alist))
      table)))

(define-alist-converter alist->hash-table hash-set!)
(define-alist-converter alist->hashq-table hashq-set!)
(define-alist-converter alist->hashv-table hashv-set!)

(define (alist->hashx-table hash assoc alist)
  "Convert ALIST into a hash table with custom HASH and ASSOC
procedures."
  (let ((table (make-hash-table)))
    (for-each (lambda (pair)
                (hashx-set! hash assoc table (car pair) (cdr pair)))
              (reverse alist))
    table))

Not only did I manage to get my code into Guile, I was given commit access to GNU Guix by the lead developer, Ludovic Courtès. I have never had commit access to any free software project repositories besides my own. I feel quite honored, as cheesy as that may sound.

Packages for SDL and SDL2 have been merged into master, and packages for SDL_gfx, SDL_image, SDL_mixer, SDL_net, and SDL_ttf for SDL 1.2 are pending review.

I like to show off the elegance of Guix package recipes, so here’s some code:

;;; Copyright © 2013 David Thompson <dthompson2@worcester.edu>
;;;
;;; This file is part of GNU Guix.
;;;
;;; GNU Guix is free software; you can redistribute it and/or modify it
;;; under the terms of the GNU General Public License as published by
;;; the Free Software Foundation; either version 3 of the License, or (at
;;; your option) any later version.
;;;
;;; GNU Guix is distributed in the hope that it will be useful, but
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;;; GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with GNU Guix.  If not, see <http://www.gnu.org/licenses/>.

(define sdl
  (package
    (name "sdl")
    (version "1.2.15")
    (source (origin
             (method url-fetch)
             (uri
              (string-append "http://libsdl.org/release/SDL-"
                             version ".tar.gz"))
             (sha256
              (base32
               "005d993xcac8236fpvd1iawkz4wqjybkpn8dbwaliqz5jfkidlyn"))))
    (build-system gnu-build-system)
    (arguments '(#:tests? #f)) ; no check target
    (inputs `(("libx11" ,libx11)
              ("libxrandr" ,libxrandr)
              ("mesa" ,mesa)
              ("alsa-lib" ,alsa-lib)
              ("pkg-config" ,pkg-config)
              ("pulseaudio" ,pulseaudio)))
    (synopsis "Cross platform game development library")
    (description "Simple DirectMedia Layer is a cross-platform development
library designed to provide low level access to audio, keyboard, mouse,
joystick, and graphics hardware.")
    (home-page "http://libsdl.org/")
    (license lgpl2.1)))

(define sdl2
  (package (inherit sdl)
    (name "sdl2")
    (version "2.0.0")
    (source (origin
             (method url-fetch)
             (uri
              (string-append "http://libsdl.org/release/SDL2-"
                             version ".tar.gz"))
             (sha256
              (base32
               "0y3in99brki7vc2mb4c0w39v70mf4h341mblhh8nmq4h7lawhskg"))))
    (license bsd-3)))

Much help is needed to package the GNU system for Guix. If you are interested in helping, please drop by #guix on freenode, we are friendly. :)