Ryan's Manuals

Lisp

Magic that your boss will never let you use with a client.


Contents



Hello Lisp

  (defparameter *langs* '( clisp racket scheme ))

  (princ "Hello, ")
  (princ *langs*)

Bwah, LISP? From the 50s? Yes- Lisp is more common than you might think; often the "secret sauce" of successful companies like Grammarly and Amazon is a finely crafted lispy back-end. Lisps are beautifully simple and functional tools; the following article contains my impressions as I begin to learn the CLISP dialect. While many speak poorly of its age, there have been a few occasions in the first 30 pages where I've been caught off guard by the effortlessness of construction and computation that lisp provides. I almost cried the first time I saw LISP handle rational numbers.

It is important to note that there are many implementations of lisp, each with distinct advantages and disadvantages. For my learning, I'm going to be initially focusing on MIT lisps (adhering to the IEEE 1990 Scheme standard,) and SBCL, as these are what are used in my learning materials. Whether I settle with MIT-Scheme, Racket, Chicken or Guile depends on my mileage with each as I complete practice problems.

This manual contains snippets of all kinds of lisps. If I gravitate towards one in particular, say, Racket or Clojure, I'll breakout the lang-specific jargon into a separate manual. Currently, I am doing most of my learning in Scheme.

Emacs, SLIME, and ORG

Emacs is a text editor in the same way that a cell phone makes phone calls. This entire file is an .org file that is converted to a webpage by Hugo, allowing me to have inline executable code cells and other handy features.

Installing Emacs on Windows and OSX

…I know, I know, heresey. I'm typing this in VS Code too. Still trying to get some quicklisp packages working via SLIME.

First install Chocolatey, the package manager, then run this command:

choco install sbcl pyenv-win nvm.install elixir git -y
choco install emacs imagemagick msys2 -y

Open the msys2 shell and run:

pacman -S mingw-w64-x86_64-openssl

Add that .dll to the PATH:

C:\tools\msys64\mingw64\bin

Add something like this to your Emacs config. You can always use M-x describe-variable or describe-command.

  ;; Ryan's Windows EMACS Config
  ;; C-M-x to interpret a function, have fun.

  ;; Add package repository for installing slime, etc.
  (add-to-list 'package-archives
	       '("melpa-stable" . "https://stable.melpa.org/packages/") t)
  (package-initialize)

  (require 'package)
  (require 'srefactor)
  (require 'srefactor-lisp)

  (custom-set-variables
   ;; custom-set-variables was added by Custom.
   ;; If you edit it by hand, you could mess it up, so be careful.
   ;; Your init file should contain only one such instance.
   ;; If there is more than one, they won't work right.
   '(custom-enabled-themes nil) '(package-selected-packages '(srefactor
   slime)))

  (custom-set-faces
   ;; custom-set-faces was added by Custom.
   ;; If you edit it by hand, you could mess it up, so be careful.
   ;; Your init file should contain only one such instance.
   ;; If there is more than one, they won't work right.
   '(default ((t (:family "Noto Mono" :foundry "outline" :slant normal :weight normal :height 120 :width normal)))))

  ;; (setq inferior-lisp-program "/opt/sbcl/bin/sbcl")
  (setq inferior-lisp-program (executable-find "sbcl"))

  (add-to-list 'load-path "~/AppData/Roaming/slime")
  (require 'slime-autoloads)

  (load (expand-file-name "~/quicklisp/slime-helper.el"))
  ;; Replace "sbcl" with the path to your implementation

  ;; Semantic Refactor keybindings
  (global-set-key (kbd "M-RET o") 'srefactor-lisp-one-line)
  (global-set-key (kbd "M-RET m") 'srefactor-lisp-format-sexp)
  (global-set-key (kbd "M-RET d") 'srefactor-lisp-format-defun)
  (global-set-key (kbd "M-RET b") 'srefactor-lisp-format-buffer)

  ;; (global-set-key (kbd "M-RET b") 'srefactor-lisp-format-buffer)

Emacs Packages to Install:

  • slime
  • srefactor
  • srefactor-lisp
  • magit
  • org
  • markdown-mode
  • modus-themes (modus-vivendi-tinted)

Take note of this page on super and hyper keys – it is good to use your keyboard, whether it is on a MacBook or a full mechanical keyboard, to its fullest.

;; On Windows:
(setq w32-pass-rwindow-to-system nil)
(setq w32-rwindow-modifier 'super) ; Right Windows key

(setq w32-pass-apps-to-system nil)
(setq w32-apps-modifier 'hyper) ; Menu/App key

;; On OSX:
(setq mac-left-option-modifier 'super)
(setq mac-right-option-modifier 'control)
(setq mac-command-modifier 'meta)
(setq ns-function-modifier 'hyper)

Hide your menu, tool, and scroll bars:

(menu-bar-mode -1)
(tool-bar-mode -1)
(scroll-bar-mode -1)

Notes on Learn Common Lisp

Notes on the lisp-lang.org Common Lisp tutorial.

  (format t "Hello, world!")
Hello, world!

You can define functions using defun:

  (defun fib (n)
    "Return the nth Fibonacci number"
    (if (< n 2)
	n
	(+ (fib (- n 1))
	   (fib (- n 2))))))

  (fib 30)
FIB
  (fib 30)
832040
  (setq stuff '(bear bucket ball chain rope))
  (caddr stuff)
BALL

Section Archive

Sections below this point are old and are kept for reference.

Resource: Land of Lisp

Lisp has been hailed as the world's most powerful programming language, but its cryptic syntax and academic reputation can be enough to scare off even experienced programmers. Those dark days are finally over — Land of Lisp brings the power of functional programming to the people!

/images/SymbolicsKB.jpg

Symbolics KB

Resource: SICP

MIT's Structure and Interpretation of Computer Programs is a classic in the truest sense; the material in the tome has been used in MIT's programs since 1980, and many of the core concepts have diffused out into reality, becoming the core of our global infrastructure. The book is available for free online in many forms.

Resource: HTDP

How to Design Programs is another MIT classic, with a focus on the program design process over teaching a language.

Common LISP Basics

  1. Define a global variable with defparameter: (defparameter *xyz* 18)
  • AKA top-level definition, dynamic variable, special variable.
  • Don't forget the earmuffs!
  • (defvar *xyz* 18) will set but not overwrite.
  1. Define a global function with defun: (defun func_name (args))
  • Functions appear after (args):
  • (defun example_function () (commands))
  1. Define and use local varibles with let.
  • (let ((x 1)(y 2)) (commands))
  • These variables are only active in the function body.
  1. Define and use local functions with flet.
  • (flet ((func_name (args) (commands))) (commands with function))
  • Again, the function only works in the flet list.
  • Multple functions can be defined in the () after flet.
  1. Like flet, labels defines local functions, but also allows recursive calls.

A simple number-guessing game, using arithmetic shifts (binary search,) can be written like so with a few global functions:

  (defparameter *big* 100)
  (defparameter *small* 1)

  (defun guess-my-number ()
    (ash (+ *small* *big*) -1)
  )
  (defun smaller ()
    (setf *big* (1- (guess-my-number)))
    (guess-my-number)
  )
  (defun bigger ()
    (setf *small* (1+ (guess-my-number)))
    (guess-my-number)
  )
  (defun start-over ()
    (defparameter *small* 1)
    (defparameter *big* 100)
    (guess-my-number)
  )

  (start-over)
50

In higher-order functions, #'x stands in for (function x).

Here is another example program showing parameters being defined, functions being defined, string insertions, comments, and more:

  ;;;; Prog5: "Wizard Adventure Game" RCF 2018 - Land of Lisp p.70

  (defparameter *nodes*
    '(
      (living-room
      (you are in the living-room. a wizard is snoring loudly on the couch.))
      (garden
      (you are in a beautiful garden. a well is in front of you.))
      (attic
      (you are in the attic. there is a giant welding torch in the corner.))))

  (defparameter *edges*
   '(
      (living-room (garden west door) (attic upstairs ladder))
      (garden (living-room east door))
      (attic (lving-room downstairs ladder))))

  (defparameter *objects*'(whiskey bucket frog chain))

  (defparameter *object-locations*
    '(
	(whiskey living-room)
	(bucket living-room)
	(chain garden)
	(frog garden)))


  (defun describe-location (location nodes)
    (cadr (assoc location nodes)))

  (defun describe-path (edge)
    `(there is a ,(caddr edge) going ,(cadr edge) from here.))


  (defun describe-paths (location edges)
    (apply #'append
      (mapcar #'describe-path
	(cdr (assoc location edges)))))

  (defun objects-at (loc objs obj-locs)
    (labels
      ((at-loc-p (obj)
	(eq (cadr (assoc obj obj-locs)) loc)))
	(remove-if-not #'at-loc-p objs)))

  ;; Let's run and see:
  (describe-paths 'garden *edges*)
THEREISADOORGOINGEASTFROMHERE.

Catalogue of LISPs

MIT Scheme

The first time you install mit-scheme and run the REPL with scheme, you'll be greeted with all sorts of hackerisms:

MIT/GNU Scheme running under GNU/Linux
Type `^C' (control-C) followed by `H' to obtain information about interrupts.

Copyright (C) 2011 Massachusetts Institute of Technology
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Image saved on Saturday December 3, 2016 at 9:44:07 AM
Release 9.1.1 || Microcode 15.3 || Runtime 15.7 || LIAR/x86-64 4.118
Edwin 3.116

1 ]=> (exit)

Kill Scheme (y or n)? Yes
Moriturus te saluto.

MIT Scheme is recommended for learning and applying the contents of SICP.

  ; To run, execute: scheme < prog6.scm
  ; SICP Newton's Method for calculating square roots

  (define (square x) (* x x))

  (define (sqrt x)

      (define (good-enough? guess)
	  (< (abs (- (square guess) x)) 0.001))

      (define (improve guess)
	  (/ (+ (/ x guess) guess) 2))

      (define (iterate guess)
	  (if (good-enough? guess)
	  guess
	  (iterate (improve guess))))

      (iterate 1.0))

  (sqrt 104)
  ;Value: 10.198039027421274

  (square (sqrt 104))
  ;Value: 104.00000000480743

  ; Note that all definitions required to run sqrt are included inside the
  ; definition, meaning they are block scoped and can access lexically scoped
  ; variable x.

GUILE

GNU Guile 2.0.13
Copyright (C) 1995-2016 Free Software Foundation, Inc.

Guile comes with ABSOLUTELY NO WARRANTY; for details type `,show w'.
This program is free software, and you are welcome to redistribute it
under certain conditions; type `,show c' for details.

Enter `,help' for help.
scheme@(guile-user)> (exit)

Racket

Welcome to Racket v6.7.
> (exit)

Why use Functional Languages?

To expand my programming horizons, I chose to read a book on CLisp, which was fantastic. After this I began applying functional techniques everywhere else; these languages change the way you approach problems. I'm now reading through SICP and Land of Lisp, and enjoying both immensely.

Whichever LISP you use, I recommend using the rlwrap program to enhance your working experience. Running, for instance, rlwrap guile adds history, readline and bracket matching to the REPL, which can be a huge quality-of-life improvement.



Site Directory



Page Information

Title: Lisp
Word Count: 1570 words
Reading Time: 8 minutes
Permalink:
https://manuals.ryanfleck.ca/lisp/