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
(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)))
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
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.