The Power of Scheme — GNUcode.me

The Power of Scheme

by Joshua Branson — January 22, 2021

I am currently building a sway service for GNU Guix. Some of the videos for that are here.

The following blog post is going to show one recent mental goof I had recently. Please bear in mind, that I am still learning scheme, and what I am saying is an attempt to think out loud (thought-vomit) and may not reflect reality. This is an attempt to clarify my thoughts and better understand scheme, particularly GNU Guile.

Consider this simplified scheme function (the original used match-lambda).

(define (proc x)
   (lambda (x)
      (display x)))

A beginner scheme programmer (like me), would look at this procedure and assume that there is no correct way to call this procedure. For example:

(proc "Hello World\n") ;; compiles and runs but does not display Hello World.

(proc)  ;; This creates a compile error

((proc "Hello World"))  ;; This create a compile error

So I decided to try to be helpful. If Guile compiles the first line of code, but it cannot run correctly, then why compile it? So I filed a bug report with GNU Guile developers. (The GNU Guile devs are fantastic people by the way. We actually had a pretty cool exchange back and forth). Well, it turns out that the correct way to call the above procedure is this:

((proc <whatever value you want here>) "Hello World")

Essentially the above proc is the same thing as this:

(define proc
  (lambda (x)
    (lambda (x)
      x)))

So proc is a procedure that takes one argument, and returns a procedure that takes one argument. The two xs there are not related. One should probably write the above procedure as:

(define proc
  (lambda (x)
    (lambda (y)
      y)))

This hopefully shows that x and y are two different values.

Occasionally as I am writing GNU Guile code, Guile will tell me that an error occurred, but fail to report the error line number. I suspect that has to do with macro shenanigans. Just today I discovered such an error and made a commit with it here, so that later I can simplify that file down to its bare essentials, and submit another guile report or talk to some guile people about it.

Here is the error in a simplified form:

(use-modules (guix records))

(define-record-type* <sway-bindsym>
  sway-bindsym make-sway-bindsym
  sway-bindsym?
  (key-combo sway-bindsym-key-combo
             (default "")))

(display sway-bindsym)  ;; compile error at unknown location

Here is the compile error output:

;;; note: source file /home/joshua/prog/guile/test.scm
;;;       newer than compiled /home/joshua/.cache/guile/ccache/3.0-LE-8-4.4/home/joshua/prog/guile/test.scm.go
;;; note: auto-compilation is enabled, set GUILE_AUTO_COMPILE=0
;;;       or pass the --no-auto-compile argument to disable.
;;; compiling /home/joshua/prog/guile/test.scm
;;; WARNING: compilation of /home/joshua/prog/guile/test.scm failed:
;;; Syntax error:
;;; unknown location: source expression failed to match any pattern in form sway-bindsym
ice-9/psyntax.scm:2800:12: In procedure syntax-violation:
Syntax error:
unknown location: source expression failed to match any pattern in form sway-bindsym

What I needed to type at that last line was:

(display (sway-bindsym)) ;; correct

(sway-bindsym) is a macro that I believe calls the macro define-record-type*. So I imagine that it is hard for guile to pinpoint, where the error is.

Anyway, I am really liking coding in GNU Guile. It is super fun and awesome. I just recently discovered match-lambda, and it's a fantastic GNU Guile macro to deal with pass around records.