Old Lisp programs

I found an old chess program that Mark Watson (somehow I can’t find the original link anymore, my Gist mirroring it is here). I was wondering what it would take to get it to run again, and I was shocked to find out that when I copy-pasted it in, loaded the file, it … it just worked !!

This is not supposed to happen, really. Code from 28 years ago isn’t supposed to just run. I don’t need to talk about how even Python code from 10 years ago would require some work to run.

Also notable is the lack of required scaffolding in terms of makefiles, build tools or anything of the sort. Yes, you could imagine breaking the code up, but it’s just 585 lines. Drop it in and load the code, and you’re good to go. No extensions, shims, nothing.

As proof, here is a short transcript of me playing terribly with it.

 

Common Lisp nits/tips/libraries: Iteration

Background

Every once in a while, I see a mention of how Common Lisp really does support “non-functional” styles, and then cl:loop is trotted in, with attendant examples that make your eyes glaze over.

As you might expect, this isn’t the only way to do it; there’s a “Lispier” way, if you will (none of this is new, the original manual/memo dates from 1989!).

Installing

CL-USER> (ql:quickload "iterate")
To load "iterate":
Load 1 ASDF system:
asdf
Install 1 Quicklisp release:
iterate
; Loading "iterate"
[package iterate]...........................
("iterate")

(while I’m here, a plug for sly instead of slime; you know you’re successfully connected when you see the [sly] Connected. Take this REPL, brother, and may it serve you well. message 😀)

Simple uses

For a really simple example, iter is not too different from loop, but still:

Basic for loop

CL-USER> (loop for i from 1 to 10 collect i)
(1 2 3 4 5 6 7 8 9 10)
CL-USER> (iter:iter
(for i from 1 to 10)
(collect i))
(1 2 3 4 5 6 7 8 9 10)

Collecting tuples

CL-USER> (loop
for x in '(a b c d)
for y in '(d e f g)
collect (list x y))
((A D) (B E) (C F) (D G))
CL-USER> (iter:iter
(for x in '(a b c d))
(for y in '(d e f g))
(collect (list x y)))
((A D) (B E) (C F) (D G))

Intermediate example

Here is an example (from the CL cookbook) of looping, with an auxiliary variable on which we have a terminating condition, with a combination of “doing something” and collecting something else, at the same time:

CL-USER> (loop for x from 1
for y = (* x 10)
while (< y 100) do (print (* x 5)) collect y) 5 10 15 20 25 30 35 40 45 (10 20 30 40 50 60 70 80 90)
CL-USER> (iter:iter
(for x upfrom 1)
(for y = (* x 10))
(while (< y 100)) (print (* x 5)) (collect y)) 5 10 15 20 25 30 35 40 45 (10 20 30 40 50 60 70 80 90)

Another example, though a bit contrived (there’s a one-liner to do this without using either of these two, but …)

CL-USER> (let ((s "alpha45"))
(loop for i from 0 below (length s)
for ch = (char s i)
when (find ch "0123456789" :test #'eql)
return ch) )
#\4
CL-USER> (let ((s "alpha45"))
(iter:iter
(for ch in-string s)
(finding ch such-that
(find ch "0123456789" :test #'eql))))
#\4

Misc cool stuff

Making modifications

I find it easier to “splice in” new changes to iter. This is another contrived example, but sort of shows what I mean:

CL-USER> (iter:iter
(for i from 1 to 10)
(collect i into nums)
(finally (return nums)))
(1 2 3 4 5 6 7 8 9 10)
CL-USER> (iter:iter
(for i from 1 to 10)
(collect i into nums)
(collect (* i i) into nums)
(finally (return nums)))
(1 1 2 4 3 9 4 16 5 25 6 36 7 49 8 64 9 81 10 100)

Natural iteration for different types

The (for ... in ...) gathering clause applies quite naturally to a great many types of structures.

CL-USER> (iter:iter
(for x in '(1 5 6))
(when (oddp x)
(collect x)))
(1 5)
CL-USER> (iter:iter
(for x in-vector #(1 5 6))
(when (oddp x)
(collect x)))
(1 5)
CL-USER> (iter:iter
(for (k v) in-hashtable (alexandria:alist-hash-table '((foo bar) (baz quux))))
(collect v))
((BAR) (QUUX))

Accessing previous values

CL-USER> (iter:iter
(for x from 1 to 10)
(for p-x previous x initially 0)
(collect (+ x p-x)))
(1 3 5 7 9 11 13 15 17 19)

Collecting all vs. unique values

CL-USER> (iter:iter
(for x in '(7 1 4 3 2 1 7 1 0))
(collect x))
(7 1 4 3 2 1 7 1 0)
CL-USER> (iter:iter
(for x in '(7 1 4 3 2 1 7 1 0))
(adjoining x))
(7 1 4 3 2 0)

Reductions

You can splice in a reduction step (counting, summing, maximizing, minimizing, etc.) in ad-hoc way.

This extremely contrived example is essentially equivalent to (reduce #'* '(1 2 3 4 5 6 7 8 9 10)), but hopefully you get the point:

CL-USER> (iter:iter
(for x from 1 to 10)
(reducing x by #'* ))
3628800 (22 bits, #x375F00)

Conclusion

YMMV, but iter seems to have (for me) a more uniform syntax, a few extra features, better comparability of clauses, and I personally prefer it to loop. If you’ve never used either, I’d recommend just sticking with the former.

A giant CS/Lisp rant

Read the whole piece here, here’s a flavor:

Why are we not out there to offer a real database system with Common Lisp datatypes instead of the tragic mess that SQL imposes on us in the C-based APIs out there (not to mention that XML calamity)? Why are we not out there building the next planning system for interstate highway updates?

Why are we not building publication solutions that would allow a reversal of the most hostile of all hostile intellectual activities undertaken by mankind in the past 40,000 years – the flooding of innocent people with senseless loads of marketing crap – and building the foundation for pull advertising?

Where the hell did the intelligent agents go, anyway? Where is the grammar- and synonym-sensitive search engine that finds matches for articles with words you did not think of? Where is the dumbing-down service that can take a precisely formulated and primarily correct technical or scientific article and turn it into a meaningful piece of information for the 1000-word-vocabularians? Where is the research on machine representation of contextgoing? Never mind the expert system that learns, I simply want an interface to an encyclopedia or specialized information database that expects me to remember what I read in some other article not all that long ago, so I do not need the full-blown version aimed at the relatively ignorant.

Where is the artificial intelligence that can actually take care of some of the things the human brain sucks at, like precision in its otherwise amazing memory? Where is the active suggestor, as opposed to the passive computer of what-if-scenarios? I want to let the network of company computers run what-if-I-had-thought-of-that-experiments and other Searches for Terrestial Intelligence instead of wasting computrons on SETI. What if people were not so goddamn scared of machine intelligence higher than their own that they would keep computers as stupid as can be? Where are the people working on the future?

Where are the futurists that do the interesting stuff that will hit us all around the next bend? I mean, to hell with some practical extraction and reporting language, I want real progress, and I want it before I go mad with rage over the wastes of human ingenuity, such as it is, that goes into writing yet another spyware “app” for Windows so yet another retard can send his obnoxious, insulting advertising to people who explicitly do not want that kind of information? For that matter, where is the spam filter that does the job of the intelligent, conscientious receptionist I can no longer afford because of the supposed labor-saving office automation that makes an ordinary business letter cost 20 times what it did in 1965 (adjusted for all important economic indicators)?

While I am at it – where is the real savings of the computer revolution? Who took all my money and gave me advertising for life insurance and Viagra?

On syntax, in Haskell and Lisp

Yes, but not so much simplicity of syntax. I’m misled here by a superficial resemblance between the cultures of Haskell and Lisp. Both cultures are obsessed with mechanically processing code, and therefore want the language core to be as simple as possible. Since a minimal core is impractical to program in, both expect a larger, more useful language to be defined by translation to the core, so its complexity can be mechanically eliminated. And both consider the representation of code as text to be separate, at least in principle, from the core. So at first glance, it seems as if they should have the same attitude to syntactic complexity.

But they treat it quite differently. Lisp’s culture considers syntax unimportant, and therefore tries to make it as simple and transparent as possible, so it won’t prevent humans from seeing through it — because code is much more interesting than its textual representation. But Haskell’s culture considers syntax safely separate from the language core, and is therefore willing to tolerate complexity in it. Since it goes away without inflicting any complexity on the core, why shouldn’t it include whatever features are convenient?

Nit-picking languages

It’s that (too frequent) time again … when I anxiously (and full of fickleness) wonder what language to increase familiarity with.

The last year, I learnt quite a bit of common lisp, or atleast enough to write a lot of exploratory code in, working with libraries, timing, profiling, improving, and so on.

I had a rude shock when I learnt from one of my Scheme heroes that he really just prefers…

View On WordPress

Nit-picking languages

It’s that (too frequent) time again … when I anxiously (and full of fickleness) wonder what language to increase familiarity with.

The last year, I learnt quite a bit of common lisp, or atleast enough to write a lot of exploratory code in, working with libraries, timing, profiling, improving, and so on.

I had a rude shock when I learnt from one of my Scheme heroes that he really just prefers Haskell now. WTF? But seriously, he makes good points, chief among which is the lack of confidence in refactoring existing lisp code.

But both have the same “lack of libraries” barrier (sure, you’d say, why don’t you build your own — but that’s not the point).

So I’ve been moving around among these, toying with some web-development style languages (and always recoiling from JS), when I suddenly realized that I have absolutely zero experience with any of the .Net languages.

So, (just thinking out loud here) why not learn me some F#, and kill two birds with one stone?

Calculating, Scheming, and Paul Graham

Calculating, Scheming, and Paul Graham

I came across [this paper] recently, and it challenged some of the thoughts/assumptions that had been building in my mind for a while (it discusses Scheme vs Miranda, but you can imagine Lisp vs Haskell instead).

It also mirrors a short email exchange I had with someone who I expected to be a Scheme/Lisp “champion”, but who gently led me down from my gas balloon of hype.

Yes, S-expressions are…

View On WordPress