X server in 5000 lines of Common Lisp
github.com
github.com
My hot tip for the future of programming.
Would be interesting to see how much is needed to get it running with some other gl context. Also -- maybe this'll run under OS X and windows without requiring a X server for the GL context?
For example the TI Explorer Lisp Machine came with an X11 server written in Lisp. On my Symbolics Lisp Machine I used the usual MIT X11 server written in C - this was possible because the Symbolics Lisp machine had a C compiler.
But so as I recall was the virtual machine that interpreted the bytecodes the compiler produced.
Here I'm referring to what I remember being told about the CADR's microcode (it had a LOT, with options for more if you were willing to buy more $$$ static RAM), but the others were all direct descendants and I gather did pretty much the same things.
E.g. https://github.com/pyb/zen/blob/master/data/request-specs.li... describes X spec request syntax, accounts alone for nearly 1000 lines, and it's not really possible to trim down.
http://cgit.freedesktop.org/xorg/xserver/tree/hw/kdrive/ephy...
If the code is well indented, IMHO it's quite understandable. For example, what do you think of this Lisp code snippet (it's not the best possible code, just some stuff I have at hand to show without you needing to know the context):
;;takes two list l1 and l2 of same length, and return (l1[0] l2[0]
;;l1[1] l2[1] ...)
(defun mix (l1 l2)
(if (null l1) nil
(append (mix (cdr l1) (cdr l2)) (list (car l1) (car l2)))))
EDIT: formatted the code as per gcr suggestion. ;;takes two list l1 and l2 of same length, and return (l1[0] l2[0]
;;l1[1] l2[1] ...)
(defun mix (l1 l2)
(if (null l1)
nil
(append (mix (cdr l1)
(cdr l2))
(list (car l1)
(car l2)))))
(Also, for the record, you should say (append (list ...) (mix ...)) or else you'll reverse the result list, which I don't think is your intent)CDR and CAR refer to machine instructions on the IBM-704 that had a (by today's standards) a somewhat quaint handling of "words" in memory, roughly allowing CAR to refer to a data element at the head of a linked list, and CDR to refer to the pointer to the rest of the list (or the empty list) (As well as a CONS instruction to build a word in memory from for parts, including the two 15 bit values that CAR/CDR refer to)[1].
Lisp then extended this by allowing programmers to combine c(a|d)+r, to get the equivalent of second, third, first-of-second-sublist etc. I'm not convinced the succinctness is worth it -- apparently experienced lisp-coders disagree. The TL;DR is that if you don't know lisp, this code is the same as the above, and is a bit more intuitive:
;;takes two list l1 and l2 of same length, and return (l1[0] l2[0]
;;l1[1] l2[1] ...)
(defun mix (list1 list2)
(if (null list1)
nil
(append (mix (rest list1)
(rest list2))
(list (first list1)
(first list2)))))
Other languages might use head and tail, rather than first and rest. I'll agree that list1 and list2 might not offer much more readability than l1 and l2 -- at least not with the comments given.[1] Most of this is paraphrased from wikipedia, and what I remember from various times I've tried to get started with lisp, without ever really getting entirely comfortable with the language. http://en.wikipedia.org/wiki/CAR_and_CDR
[edit: I didn't notice the comment about reversing the list, but I think it is rather obvious that (append rest list(first)) does indeed reverse the order...? I actually wondered if append had a strange order of parameters while I "rewrote" the code :-) ]
Actually on day two of Lisp, fifty years ago, these patterns have been abstracted. Recursion of lists has been replaced by higher-order functions in many cases.
(defun mix (list1 list2)
(mapcan #'list list1 list2))
Above maps the function LIST over the two lists and concatenates the results.http://jtra.cz/stuff/lisp/sclr/mapcan.html
Also linked from the resources-section of:
http://gettingstartedwithcommonlisp.com/
I don't think I've come across the simplified reference before -- appears to be a good resource for those of us starting out with lisp -- striking a balance between all of CLOS and the sometimes simplistic presentation of text books.
A a redirect service for Common Lisp documentation:
A search engine:
Now, you could of course write an interpreter for such a language in lisp, but am I correct in assuming that there's no reasonable way to get a (standard'ish) lisp to compile an expression like (1:2 ...) to the equivalent caadr(?)-like expression?
I saw there's a library for clojure that adds "slice notation" -- but does so by adding a (slice x y list)-macro which of course is fine -- but it would seem that (x:y list) would give similar benefits to the cadr/cddr etc -- allowing selected subsets to be highly optimized, for example? (As well as offering concise syntax)
I would not write `slice` as a `macro` or special syntax. I would use the `SUBSEQ` function, which already exists.
CL-USER 7 > (subseq '(a b c d e f) 2 4)
(C D)
The simplest way to introduce a special syntax for it is to use different parentheses: {1 '(1 2 3 4)} -> 2
But the default Lisp style is this (functionname arg0 ... argn)
where `functionname` is a real symbol. It may be longer on the character level, which may be a problem for some users - not for me.That'd be how you could redefine "{" and "}" to work something like this?
At least I came across the following that seems to indicate that:
http://letoverlambda.com/index.cl/guest/chap4.html
http://jlongster.com/2012/02/18/its-not-about-macros-its-abo...
Common Lisp itself tries to minimize its usage of characters. It is expected that users or libraries want to make use of characters like {, }, [, ], and many others.
http://www.theguardian.com/education/2013/oct/08/england-you...
Literacy for example seems to be quite good in some countries with languages which for me would look difficult. The UK OTOH is not happy with their results.
The syntax is always[0] (procedure argument-1 argument-2 ...) where the procedure is applied to the arguments.
about half-hour in to this lecture the syntax is explained: http://ocw.mit.edu/courses/electrical-engineering-and-comput...
[0] - almost always. Macros look the same and often get treated the same but they are very different.
Beside macros, with non string-buffer editors, you get very very fast and calm typing or I should say low level refactoring.
Finally it has this weird quality of really looking like static data (relation v1 v2 v3) most of the time and really not like a cryptic (by the number of delimiters {} () , ; ) state dependent imperative notation. Makes you really think about how to interpret data rather than send commands to a machine.