title:The Power of Scheme date: 2021-01-22 22:00 tags: guile scheme
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 x
s 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.