2023-12-03 18:57:36 +00:00
#+title : Programming in Scheme for SICP
#+author : Howard X. Abrams
#+date : 2022-03-01
#+tags : emacs scheme programming lisp
2022-03-03 23:13:48 +00:00
A literate programming file configuring Emacs.
2022-06-18 00:25:47 +00:00
#+begin_src emacs-lisp :exports none
2022-03-09 18:45:37 +00:00
;;; ha-programming-scheme --- Configuration for Scheme. -*- lexical-binding: t; -* -
2022-03-03 23:13:48 +00:00
;;
2023-02-23 17:35:36 +00:00
;; © 2022-2023 Howard X. Abrams
2022-06-18 00:25:47 +00:00
;; Licensed under a Creative Commons Attribution 4.0 International License.
2022-03-09 18:45:37 +00:00
;; See http://creativecommons.org/licenses/by/4.0/
2022-03-03 23:13:48 +00:00
;;
;; Author: Howard X. Abrams <http://gitlab.com/howardabrams >
;; Maintainer: Howard X. Abrams
;; Created: March 1, 2022
;;
;; This file is not part of GNU Emacs.
;;
;; *NB:* Do not edit this file. Instead, edit the original literate file at:
2024-10-19 20:34:01 +00:00
;; ~/src/hamacs/ha-programming-scheme.org
2022-03-03 23:13:48 +00:00
;; And tangle the file to recreate this one.
;;
;;; Code:
2022-06-18 00:25:47 +00:00
#+end_src
2022-03-03 23:13:48 +00:00
* Introduction
2022-03-15 16:20:11 +00:00
First, install MIT-Scheme, the Lisp dialect used throughout the SICP book:
2022-03-03 23:13:48 +00:00
=brew install mit-scheme= or =sudo apt install mit-scheme= .
2022-06-18 00:25:47 +00:00
#+begin_src sh
2022-03-15 16:20:11 +00:00
brew install mit-scheme
2022-06-18 00:25:47 +00:00
#+end_src
2022-03-15 16:20:11 +00:00
Or better yet, let’ s use Guile:
2022-06-18 00:25:47 +00:00
#+begin_src sh
2022-03-15 16:20:11 +00:00
brew install guile
2022-06-18 00:25:47 +00:00
#+end_src
2022-03-15 16:20:11 +00:00
* Geiser (Scheme Interface)
2022-06-18 00:25:47 +00:00
The [[https://www.nongnu.org/geiser/ ][geiser project ]] attempts to be the interface between Emacs and all the Schemes in the world. Since I can’ t decide which to use, I’ ll install/configure them all.
#+begin_src emacs-lisp
2022-03-03 23:13:48 +00:00
(use-package geiser
:init
(setq geiser-mit-binary "/usr/local/bin/scheme"
2022-03-15 16:20:11 +00:00
geiser-racket-binary "/usr/local/bin/racket"
geiser-guile-binary "/usr/local/bin/guile"
2022-04-05 03:20:59 +00:00
geiser-active-implementations '(guile mit)
2022-03-15 16:20:11 +00:00
geiser-default-implementations '(guile))
2022-03-03 23:13:48 +00:00
:config
2022-03-15 16:20:11 +00:00
(use-package geiser-mit)
(use-package geiser-guile)
2022-04-05 03:20:59 +00:00
(use-package geiser-racket))
2022-06-18 00:25:47 +00:00
#+end_src
2022-04-05 03:20:59 +00:00
** Org Mode
2022-03-15 16:20:11 +00:00
:PROPERTIES:
2022-04-05 03:20:59 +00:00
:header-args:scheme: :session *scheming* :results value replace
2022-03-15 16:20:11 +00:00
:END:
2022-04-05 03:20:59 +00:00
Do we need a Scheme work for Org Babel? According to [[https://orgmode.org/worg/org-contrib/babel/languages/ob-doc-scheme.html ][this document ]], we just need to make sure we add the =:session= variable to start the REPL.
2022-06-18 00:25:47 +00:00
#+begin_src emacs-lisp
2022-04-05 03:20:59 +00:00
(use-package ob-scheme
:straight (:type built-in)
:config
(add-to-list 'org-babel-load-languages '(scheme . t)))
2022-03-15 16:20:11 +00:00
2022-06-18 00:25:47 +00:00
#+end_src
2022-04-05 03:20:59 +00:00
Since the version of Scheme hasn't been updated with the deprecation, and subsequent removal of =org-babel-get-header= , we include it here:
2022-06-18 00:25:47 +00:00
#+begin_src emacs-lisp
2022-04-05 03:20:59 +00:00
(defun org-babel-get-header (params key &optional others)
(delq nil
(mapcar
(lambda (p) (when (funcall (if others #'not #'identity) (eq (car p) key)) p))
params)))
2022-06-18 00:25:47 +00:00
#+end_src
2022-03-15 16:20:11 +00:00
2022-04-05 03:20:59 +00:00
Let’ s test it out by defining a variable:
2022-06-18 00:25:47 +00:00
#+begin_src scheme
2022-04-05 03:20:59 +00:00
(define a 42)
2022-06-18 00:25:47 +00:00
#+end_src
2022-04-05 03:20:59 +00:00
And simply using it:
2022-06-18 00:25:47 +00:00
#+begin_src scheme :var b=8
2022-04-05 03:20:59 +00:00
(+ a b)
2022-06-18 00:25:47 +00:00
#+end_src
2022-04-05 03:20:59 +00:00
2024-03-07 04:02:25 +00:00
#+results :
2022-04-05 03:20:59 +00:00
: ;Value: 50
And what about Scheme-specific stuff needed for SICP?
2022-06-18 00:25:47 +00:00
#+begin_src scheme
2022-04-05 03:20:59 +00:00
(inc 42)
2022-06-18 00:25:47 +00:00
#+end_src
2022-03-15 16:20:11 +00:00
** Install SICP
:PROPERTIES:
:header-args:scheme: :session sicp :results value replace
:END:
2022-03-03 23:13:48 +00:00
Let’ s get the book available as an Info page:
2022-06-18 00:25:47 +00:00
#+begin_src emacs-lisp
2022-03-03 23:13:48 +00:00
(use-package sicp)
2022-06-18 00:25:47 +00:00
#+end_src
2022-03-03 23:13:48 +00:00
2022-03-15 16:20:11 +00:00
Still having difficulty getting the Scheme REPL to output the results back into this document. Let’ s try Racket...
2022-03-03 23:13:48 +00:00
2022-05-13 21:35:26 +00:00
Normally, I would just [[info:SICP ][read the book ]], however, if we want to read the [[file:~/.emacs.d/straight/build/sicp/sicp.info ][sicp.info ]] file, we need this, at least, temporarily:
2022-06-18 00:25:47 +00:00
#+begin_src emacs-lisp
2022-03-03 23:13:48 +00:00
(add-to-list 'auto-mode-alist '("\\.info\\'" . Info-mode))
2022-06-18 00:25:47 +00:00
#+end_src
2022-03-15 16:20:11 +00:00
* Racket
Actually, let’ s do this with [[https://racket-lang.org/ ][Racket ]]:
2022-06-18 00:25:47 +00:00
#+begin_src sh
2022-03-15 16:20:11 +00:00
brew install racket
2022-06-18 00:25:47 +00:00
#+end_src
2022-03-15 16:20:11 +00:00
While Racket, as a Scheme, should work with Geiser (below), let’ s also get [[https://racket-mode.com/ ][racket-mode ]] working:
2022-06-18 00:25:47 +00:00
#+begin_src emacs-lisp
2022-03-15 16:20:11 +00:00
(use-package racket-mode
:config (setq racket-program "/usr/local/bin/racket"))
2022-06-18 00:25:47 +00:00
#+end_src
2022-03-15 16:20:11 +00:00
Can we get Racket working with Org?
2022-06-18 00:25:47 +00:00
#+begin_src emacs-lisp
2022-03-15 16:20:11 +00:00
(use-package ob-racket
2022-08-09 16:57:20 +00:00
:straight (:host github :repo "DEADB17/ob-racket")
2022-03-15 16:20:11 +00:00
:after org
:config
(add-to-list 'org-babel-load-languages '(racket . t)))
2022-06-18 00:25:47 +00:00
#+end_src
2022-03-15 16:20:11 +00:00
** Try It Out
:PROPERTIES:
2022-03-18 21:21:18 +00:00
:HEADER-ARGS:racket: :session racketeering :results value replace :lang racket
2022-03-15 16:20:11 +00:00
:END:
Working for values?
2022-06-18 00:25:47 +00:00
#+begin_src racket
2022-03-15 16:20:11 +00:00
(* 6 7)
2022-06-18 00:25:47 +00:00
#+end_src
2022-03-15 16:20:11 +00:00
2024-03-07 04:02:25 +00:00
#+results :
2022-03-15 16:20:11 +00:00
: 42
Working for output?
2022-06-18 00:25:47 +00:00
#+begin_src racket :results output replace
2022-03-15 16:20:11 +00:00
(define str-1 "hello")
(define str-2 "world")
(define all (string-join (list str-1 str-2) ", "))
(display (string-titlecase all))
2022-06-18 00:25:47 +00:00
#+end_src
2022-03-15 16:20:11 +00:00
2024-03-07 04:02:25 +00:00
#+results :
2022-03-15 16:20:11 +00:00
: Hello, World
The interface is horrendously slow, as the =:session= doesn’ t seem to work, and starting up a Racket REPL takes a long time.
** SICP and Racket
:PROPERTIES:
:header-args:racket: :session *rsicp* :results value replace :lang sicp
:END:
If using [[https://docs.racket-lang.org/sicp-manual/SICP_Language.html ][Racket for SICP ]], install the SICP language:
2022-06-18 00:25:47 +00:00
#+begin_src sh
2022-03-15 16:20:11 +00:00
raco pkg install --auto --update-deps sicp
2022-06-18 00:25:47 +00:00
#+end_src
2022-03-15 16:20:11 +00:00
We now can give it a =#lang sicp= (or better yet, use the =:lang= header) to define certain SICP-specify features:
Let’ s try this now:
2022-06-18 00:25:47 +00:00
#+begin_src racket
2022-03-15 16:20:11 +00:00
(inc 42)
2022-06-18 00:25:47 +00:00
#+end_src
2022-03-15 16:20:11 +00:00
2024-03-07 04:02:25 +00:00
#+results :
2022-03-15 16:20:11 +00:00
: 43
* Technical Artifacts :noexport:
2022-03-03 23:13:48 +00:00
Let's =provide= a name so we can =require= this file:
2022-06-18 00:25:47 +00:00
#+begin_src emacs-lisp :exports none
2022-03-03 23:13:48 +00:00
(provide 'ha-programming-scheme)
;;; ha-programming-scheme.el ends here
2022-06-18 00:25:47 +00:00
#+end_src
2022-03-03 23:13:48 +00:00
2024-03-07 04:02:25 +00:00
#+description : A literate programming file configuring Emacs.
2022-03-03 23:13:48 +00:00
2024-03-07 04:02:25 +00:00
#+property : header-args:sh :tangle no
#+property : header-args:emacs-lisp :tangle yes
#+property : header-args :results none :eval no-export :comments no mkdirp yes
2022-03-03 23:13:48 +00:00
2024-03-07 04:02:25 +00:00
#+options : num:nil toc:t todo:nil tasks:nil tags:nil date:nil
#+options : skip:nil author:nil email:nil creator:nil timestamp:nil
#+infojs_opt : view:nil toc:t ltoc:t mouse:underline buttons:0 path:http://orgmode.org/org-info.js