SLIME

SLIME, the Superior Lisp Interaction Mode for Emacs, is an Emacs mode for developing Common Lisp applications. SLIME originates in an Emacs mode called SLIM written by Eric Marsden. It is developed as an open-source public domain software project by Luke Gorrie and Helmut Eller. Over 100 Lisp developers have contributed code to SLIME since the project was started in 2003. SLIME uses a backend called Swank that is loaded into Common Lisp.

— Wikipedia on SLIME

.

C-x o

Window-Move to other

C-x C-e

Evaluate last expression

C-c C-r

Evaluate region

.

.

2018.10.19 Friday (c) ACHK

Ask users

gallerdude 3 months ago

There’s a good moral here. Everytime they had a question, they asked their users. Users don’t lie.

atYevP 3 months ago

Yev from Backblaze here -> That’s right! For better or worse they usually tell it like they see it, and that helps us inform decisions!

— How Backblaze Got Started (2017)

— Hacker News

.

.

2018.05.14 Monday ACHK

The best software

somethingsimple 3 months ago

> Software is the currency that we pay to solve problems, which is our actual goal. We should endeavor to build as little software as possible to solve our problems.

.

ScottBurson 3 months ago

My point today is that, if we wish to count lines of code, we should not regard them as “lines produced” but as “lines spent”: the current conventional wisdom is so foolish as to book that count on the wrong side of the ledger. — E. W. Dijkstra

.

That’s why the best choice of software is often no software …

— Coding Horror

— by Jeff Atwood

.

— Write dumb code

— Hacker News

.

.

2018.05.01 Tuesday ACHK

Lisp in Lisp


; The Lisp defined in McCarthy's 1960 paper, translated into CL.
; Assumes only quote, atom, eq, cons, car, cdr, cond.
; Bug reports to lispcode@paulgraham.com.

(defun null. (x)
  (eq x '()))

(defun and. (x y)
  (cond (x (cond (y 't) ('t '())))
        ('t '())))

(defun not. (x)
  (cond (x '())
        ('t 't)))

(defun append. (x y)
  (cond ((null. x) y)
        ('t (cons (car x) (append. (cdr x) y)))))

(defun list. (x y)
  (cons x (cons y '())))

(defun pair. (x y)
  (cond ((and. (null. x) (null. y)) '())
        ((and. (not. (atom x)) (not. (atom y)))
         (cons (list. (car x) (car y))
               (pair. (cdr x) (cdr y))))))

(defun assoc. (x y)
  (cond ((eq (caar y) x) (cadar y))
        ('t (assoc. x (cdr y)))))

(defun eval. (e a)
  (cond
    ((atom e) (assoc. e a))
    ((atom (car e))
     (cond
       ((eq (car e) 'quote) (cadr e))
       ((eq (car e) 'atom)  (atom   (eval. (cadr e) a)))
       ((eq (car e) 'eq)    (eq     (eval. (cadr e) a)
                                    (eval. (caddr e) a)))
       ((eq (car e) 'car)   (car    (eval. (cadr e) a)))
       ((eq (car e) 'cdr)   (cdr    (eval. (cadr e) a)))
       ((eq (car e) 'cons)  (cons   (eval. (cadr e) a)
                                    (eval. (caddr e) a)))
       ((eq (car e) 'cond)  (evcon. (cdr e) a))
       ('t (eval. (cons (assoc. (car e) a)
                        (cdr e))
                  a))))
    ((eq (caar e) 'label)
     (eval. (cons (caddar e) (cdr e))
            (cons (list. (cadar e) (car e)) a)))
    ((eq (caar e) 'lambda)
     (eval. (caddar e)
            (append. (pair. (cadar e) (evlis. (cdr e) a))
                     a)))))

(defun evcon. (c a)
  (cond ((eval. (caar c) a)
         (eval. (cadar c) a))
        ('t (evcon. (cdr c) a))))

(defun evlis. (m a)
  (cond ((null. m) '())
        ('t (cons (eval.  (car m) a)
                  (evlis. (cdr m) a)))))

— Paul Graham

.

.

2018.03.15 Thursday ACHK

Shape of a program

(defun bad-reverse (lst)
  (let* ((len (length lst))
	 (ilimit (truncate (/ len 2))))
    (do ((i 0 (1+ i))
	 (j (1- len) (1- j)))
	((>= i ilimit))
      (rotatef (nth i lst) (nth j lst)))))

It used to be thought that you could judge someone’s character by looking at the shape of his head. Whether or not this is true of people, it is generally true of Lisp programs. Functional programs have a different shape from imperative ones. The structure in a functional program comes entirely from the composition of arguments within expressions, and since arguments are indented, functional code will show more variation in indentation. Functional code looks fluid on the page; imperative code looks solid and blockish, like Basic.

Even from a distance, the shapes of bad- and good-reverse suggest which is the better program. And despite being shorter, good-reverse is also more efficient: O(n) instead of O(n^2).

(defun good-reverse (lst)
  (labels ((rev (lst acc)
		(if (null lst)
		    acc
		  (rev (cdr lst) (cons (car lst) acc)))))
    (rev lst nil)))

— p.30

— On Lisp

— Paul Graham

.

.

2018.03.02 Friday ACHK

On Lisp

paulgraham_2202_3475946

Lisp is an especially good language for writing extensible programs because it is itself an extensible program.

Because Lisp gives you the freedom to define your own operators, you can mold it into just the language you need. If you’re writing a text-editor, you can turn Lisp into a language for writing text-editors. If you’re writing a CAD program, you can turn Lisp into a language for writing CAD programs. And if you’re not sure yet what kind of program you’re writing, it’s a safe bet to write it in Lisp. Whatever kind of program yours turns out to be, Lisp will, during the writing of it, have evolved into a language for writing that kind of program.

— On Lisp: Advanced Techniques for Common Lisp

— Paul Graham

.

.

2018.02.21 Wednesday ACHK

Exercise 6.2

You Could Have Invented Monads! (And Maybe You Already Have.)

f :: a -> b
f' :: a -> m a
unit :: a -> m a

f' * g' = (bind f') . (bind g')

bind f xs = concat (map f xs)

bind unit xs = concat (map unit xs)

unit x = [x]

bind unit xs
= concat (map unit xs)
= concat (map unit [x1, x2, ...])
= concat [unit x1, unit x2, ...]
= concat [[x1], [x2], ...]
= [x1, x2, ...]
= xs

f' = lift f

lift f = unit . f

unit (or return) can directly act on an ordinary value only, but not on a monadic value. To act on a monadic value, you need to bind it.

How come we do not need to lift return?

f :: a -> b

liftM :: Monad m => (a -> b) -> m a -> m b

return :: a -> m a

(liftM f) :: m a -> m b

(>>=) :: Monad m => m a -> (a -> m b) -> m b

lifeM cannot be applied to return at all.

unit (or return) is neither a pure function nor a monadic function. Instead, it is an half-monadic function, meaning that while its input is an ordinary value, its output is a monadic value.

(bind return xs) -> ys

(bind return) applies to xs.

return applies to x.

liftM is merely fmap implemented with (>>=) and return

— Wikibooks on Haskell/Understanding monads
 

— Me@2016-01-26 03:05:50 PM

2016.01.30 Saturday (c) All rights reserved by ACHK

Inception 11

如何拯救眾生 4

.

Inception contains most of the important topics I have thought of in these few months:

1. Multi-mind

2. Layers of consciousness

3. Dream time

4. Lucid dream

5. Idea/software as a way to save Earth people

.

The deeper the consciousness, the more powerful it is.

The deepest layer is the Light.

The Light of everyone is the same.

— Me@2010.08.06

.

人同此心,心同此理

— Me@2010.08.09

.

.

.

2011.01.15 Saturday (c) ACHK

Intellectual Headaches

Game design

They got the key, and then some other stuff happened, and then they reached the door, and were able to open it; but “acquiring the key” and “opening the door” were stored as two separate, disconnected events in the player’s mind.

If the player had encountered the locked door first, tried to open it, been unable to, and then found the key and used it to open the door, the causal link would be unmistakable. You use the key to open the locked door, because you can’t open the locked door without the key.

Math education

I’ve drawn parallels between game design and education before, but it still took me a while to realize that problem-solution ordering issues crop up just as often in the classroom as they do in games.

Remember how, in high school math class, a lot of the work you were doing felt really, really pointless?

Consider Dan Meyer’s question for math educators: if math is the aspirin, then how do you create the headache?

In other words: if you introduce the solution (in this case, a new kind of math) before introducing the kind of problems that it’s meant to solve, the solution is likely to come across as pointless and arbitrary. But if you first let students try to tackle these problems with the math they already understand, they’re likely to come away with a kind of intellectual “headache” – and, therefore, to better understand the purpose of the “aspirin” you’re trying to sell.

Functional programming

— Locked doors, headaches, and intellectual need

— 27 October 2015

— Affording Play

Here are some excerpts of an elegant essay. Please go to the author’s website to read the whole.

— Me@2015-11-03 03:46:41 PM

2015.11.03 Tuesday ACHK

Exercise 6a (Corrected version)

You Could Have Invented Monads! (And Maybe You Already Have.)

Show that f' * unit = unit * f' = bind f'

——————————

f :: a -> b
f' :: a -> m a
unit :: a -> m a

lift f = unit . f
f' = lift f

The lift function in this tutorial is not the same as the liftM in Haskell. So you should use lift (but not liftM) with bind.

— Me@2015-10-13 11:59:53 AM

(f' * g') xs
= ((bind f') . (bind g')) xs

bind f' xs = concat (map f' xs)
unit x = [x]

bind unit xs
= concat (map unit xs)
= concat (map unit [x1, x2, ...])
= concat [unit x1, unit x2, ...]
= concat [[x1], [x2], ...]
= [x1, x2, ...]
= xs

(f' * unit) (x:xs)
= bind f' (bind unit (x:xs))
= bind f' (concat (map unit (x:xs)))
= bind f' (concat (map unit [x1, x2, ...]))
= bind f' (concat [[x1], [x2], ...])
= bind f' [x1, x2, ...]
= concat (map f' [x1, x2, ...])
= concat [f' x1, f' x2, ...]
= concat [(unit . f) x1, (unit . f) x2, ...]
= concat [(unit (f x1)), (unit (f x2)), ...]
= concat [[f x1], [f x2], ...]
= [f x1, f x2, ...]

(unit * f') (x:xs)
= ((bind unit) . (bind f')) (x:xs)
= bind unit (bind f' (x:xs))
= bind unit (concat (map f' (x:xs)))
= bind unit (concat (map f' [x1, x2, ...]))
= bind unit (concat [f' x1, f' x2, ...])
= bind unit (concat [(unit . f)  x1, (unit . f) x2, ...])
= bind unit (concat [(unit (f x1)), (unit (f x2)), ...])
= bind unit (concat [[f x1], [f x2], ...])
= bind unit [f x1, f x2, ...]
= concat (map unit [f x1, f x2, ...])
= concat [[f x1], [f x2], ...]
= [f x1, f x2, ...]

— Me@2015-10-15 07:19:18 AM

If we use the identity bind unit xs = xs, the proof will be much shorter.

(f' * unit) (x:xs)
= ((bind f') . (bind unit)) (x:xs)
= bind f' (bind unit (x:xs))
= bind f' (x:xs)

(unit * f') (x:xs)
= ((bind unit) . (bind f')) (x:xs)
= bind unit (bind f' (x:xs))
= bind f' (x:xs)

— Me@2015-10-15 11:45:44 AM

2015.10.15 Thursday (c) All rights reserved by ACHK

Exercise 6a

You Could Have Invented Monads! (And Maybe You Already Have.)

Show that f * unit = unit * f

——————————

(f * g) (x, xs)
= ((bind f) . (bind g)) (x, xs)

bind f x = concat (map f x)

(f * unit) (x:xs)
= bind f (bind unit (x:xs))
= bind f (concat (map unit (x:xs)))
= bind f (concat (map unit [x1, x2, x3, ...]))
= bind f (concat ([[x1], [x2], [x3], ...]))
= bind f [x1, x2, x3, ...]
= concat (map f [x1, x2, x3, ...])
= concat [f x1, f x2, f x3, ...]
= [f x1, f x2, f x3, ...]

(unit * f) (x:xs)
= ((bind unit) . (bind f)) (x:xs)
= bind unit (bind f (x:xs))
= bind unit (concat (map f (x:xs)))
= bind unit (concat (map f [x1, x2, ...]))
= bind unit (concat [f x1, f x2, ...])
= bind unit [f x1, f x2, ...]
= concat (map unit [f x1, f x2, ...])
= concat [[f x1], [f x2], ...]
= [f x1, f x2, ...]

— Me@2015.07.20 09:00 PM

2015.10.06 Tuesday (c) All rights reserved by ACHK

Inception 4.1

潛行凶間 4.1 | 如何拯救眾生 5.1 | 無限複製 5.1

.

What’s the most resilient parasite? A bacteria? A virus? An intestinal worm?

An idea.

Resilient, highly contagious. Once an idea’s taken hold in the brain it’s almost impossible to eradicate. A person can cover it up, ignore it – but it stays there.

Information, yes. But an idea? Fully formed, understood? That sticks… (taps forehead) In there, somewhere.

— Inception (film)

— Me@2011.01.18

.

.

.

2011.01.18 Tuesday ACHK

Exercise 3.2

You Could Have Invented Monads! (And Maybe You Already Have.)

Show that lift f * lift g = lift (f.g)

——————————

The meaning of f' * g' should be (bind f') . (bind g') instead.

f' * g' = (bind f') . (bind g')
lift f = unit . f
f' = lift f

(lift f * lift g) (x, xs)
= (bind (lift f)) . (bind (lift g)) (x, xs)
= bind (lift f) (bind (lift g) (x, xs))
= bind (lift f) (gx, xs++gs)
  where
    (gx, gs) = (lift g) x

= bind (lift f) (gx, xs++gs)
  where
    (gx, gs) = (g x, "")

= bind (lift f) (g x, xs)

= (fx, xs++fs)
  where
    (fx, fs) = (lift f) gx
 
= (fx, xs++fs)
  where
    (fx, fs) = (f gx, "")

= (fx, xs)
  where
    (fx, fs) = (f (g x), "")

= (f (g x), xs)

bind f' (gx,gs) = (fx, gs++fs)
                  where
                    (fx,fs) = f' gx

bind (lift (f.g)) (x, xs)
= (hx, xs++hs)
  where
    (hx, hs) = (lift (f.g)) x

= (hx, xs++hs)
  where
    (hx, hs) = ((f.g) x, "")

= ((f (g x)), xs)

— Me@2015.07.19 11:04 PM

2015.10.02 Friday (c) All rights reserved by ACHK

Exercise Three

You Could Have Invented Monads! (And Maybe You Already Have.)

Show that lift f * lift g = lift (f.g)

——————————

f' * g' = bind f' . g'
lift f = unit . f
f' = lift f

(lift f * lift g) (x, xs)
= bind (lift f . lift g) (x, xs)
= (hx, xs++hs)
  where
    (hx, hs) = lh x
    lh x = (f' . g') x
    f' = lift f
    g' = lift g

This line does not work, since f' cannot be applied to (g' x), for the data types are not compatible:

f' :: Float -> (Float, String)

g' :: Float -> (Float, String)

(g' x) :: (Float, String)

The meaning of f' * g' should be bind f' . (bind g') instead.

— Me@2015-09-27 10:24:54 PM

2015.09.27 Sunday (c) All rights reserved by ACHK