Tips for golfing in Lisp

9

2

What general tips are these for golfing in Lisp (any dialect)? Please post one tip per answer, and only answers that are specific to a dialect of Lisp (e.g. "remove comments" is not an answer).

Please post the dialect of Lisp your tip applies to with your tip.

NoOneIsHere

Posted 2016-05-10T22:50:31.750

Reputation: 1 916

3https://xkcd.com/297/ – James – 2016-05-10T23:50:39.017

1

Do you imagine these will be distinct from the tips for golfing in Scheme and Racket?

– Alex A. – 2016-05-11T00:09:53.077

1I would advise using tinylisp, a smaller, stripped-down version of Lisp for your golfing pleasure. – ckjbgames – 2017-02-01T23:12:55.037

Answers

4

Order function parameters to minimize whitespace

Instead of

(defun f(a b)(...))
...
(f x(1+ y))

try something like

(defun f(b a)(...))
...
(f(1+ y)x)

ceilingcat

Posted 2016-05-10T22:50:31.750

Reputation: 5 503

1

Print strings consisting of capital letters via printing atoms

The princ function in Common Lisp is short, and will print objects without escape characers. If you print Common Lisp symbols, which have the synax 'symbol-name, this saves you from needing quotes around what you want to print, and can also save on whitespace. Note that when printing symbols, they will be capitalized. Also, it does not add a newline or a space, so you don't need concatenation.

For example,

(princ'hai)

will print HAI.

And

(princ'hai)(princ(read))

will print HAI, ask for input, and print it back out, e.g. if you type hello, the result is

HAIhellohello

Matceporial

Posted 2016-05-10T22:50:31.750

Reputation: 41

1

Use 1+ and 1- for increment and decrement

Instead of (+ a 1) or (- b 1) try (1+ a) or (1- b).

ceilingcat

Posted 2016-05-10T22:50:31.750

Reputation: 5 503

I don't understand this. Isn't 1+ parsed as two tokens, 1 and +? I thought it was +1. – Esolanging Fruit – 2017-04-24T07:19:23.350

@Challenger5 1+ and 1- are parsed as a single token Common Lisp HyperSpec Function 1+, 1-

– ceilingcat – 2017-05-18T03:59:29.333

I thought that names couldn't start with digits? – Esolanging Fruit – 2017-05-18T06:58:41.197

@EsolangingFruit this is Lisp... – ASCII-only – 2018-05-18T07:51:14.870

1

Use loop and format, which is like printf on steroids. format includes iteration and conditions, as well as roman numerals, English numbers and English plurals. It is very, very ugly, and very compact.

Michael Vehrs

Posted 2016-05-10T22:50:31.750

Reputation: 771

1

Conditional Output

GNU Common Lisp

~v^

The up-and-out directive ~^ is most commonly used in a list formatting operation to terminate after the last list item. However, it can also be used with a v modifier to consume an argument, in which case it terminates if that argument is zero. This is particularly useful for dealing with the zero produced by dotimes.

(loop as n from 1 to 10 do(format t"~d~%"n))

(dotimes(n 11)(if(> n 0)(format t"~d~%"n)))

(dotimes(n 11)(format t"~v^~d~%"n n))

format(condition)

The first argument to format can be one of t, nil a.k.a. (), or a stream. If passed t, it will output to stdout, if nil it will return the formatted output as a string. This can be used conditionally output. The above example could be written equally as short as:

(dotimes(n 11)(format(> n 0)"~d~%"n))

If a value was output, the return value will be nil. Because of this, it can also be used as the terminating condition for a do loop:

(do((n 11))((<(decf n)1))(format t"~d~%"n))

(do((n 11))((format(>(decf n)0)"~d~%"n)))

~[...~]

The conditional formatter consumes an argument, and selects a formatting string from a list by index. A common use case is with the default formatter ~:; to select between zero and not zero.

(dotimes(n 11)(format t"~v^~[~r~:;~d~]~%"n(mod n 3)n))

Conditional formatters can also be nested, in which case each will consume an argument in turn.


~&

In each of the examples above, ~% is used to emit a newline. In most cases, this could be replaced by a literal newline. Another option is to use ~&, which will emit a newline if and only if the output cursor is not at the start of a line, a.k.a. a fresh-line.

Both ~% and ~& can also take an argument, with a v modifier or as a constant, and will produce as many newlines. They will also both happily accept a negative argument, in which case they emit nothing.


External References

Practical Common Lisp
18. A Few FORMAT Recipes

Common Lisp the Language, 2nd Edition
22.3.3. Formatted Output to Character Streams

primo

Posted 2016-05-10T22:50:31.750

Reputation: 30 891