I installed clisp+slime using this guide: http://www.osix.net/modules/article/?id=912
I'm using this tutorial: http://www.gigamonkeys.com/book/
I can think of two gotchas I've run into so far: a function body doesn't get wrapped in parentheses, and the first parenthesis goes before the called function's name, not after. Oh, and lists aren't supposed to be comma-delimited.
Naturally, macros are kind of hard to grasp. But I finally decided the most concise description is lazily-evaluated functions, based on the tutorial's explanation.
Right now I'm wondering how to do classes (prototypes?!), although I saw define-class and define-method mentioned in library code. But I'll wait until the tutorial gets to those.
But I really need to learn how to debug in emacs+slime+clisp. For that matter I need to learn to use the REPL for programming.
Because Common Lisp is a Lisp-2, that is a Lisp with two namespaces for variables and functions:
(fdefinition `foo)is the best place to SETF a global/dynamic function, if the global function FOO is already defined. I hack this up by saying
(defun foo () )before I need to SETF it.
- If a function is instead assigned as a variable it must be called with
(funcall foo arg0 arg1 ...)or
(apply foo args).
- To bind a function in the local/lexical scope and not need to call it with FUNCALL/APPLY you must alias it:
(let ((foo (lambda ()
#| ... |#)))
(flet ((foo (&rest args)
(apply foo args)))
;Now we can call it without FUNCALL:
- Note that the above code demonstrates what "Lisp-2" means: The function FOO is in a different namespace than the variable FOO, and their values are not inherently related. The function FOO can be get'ed with #'foo.
The Common Lisp community explains that the power of CL macros justifies the Lisp-2 nature. I am not yet qualified to give an opinion on the matter.
The LOOP macro had me stuck for a long while (no pun intended) on a syntax error. I finally got that cleared up, but now I have an infinite loop - bah. Anyway, here are the two things I learned, using http://www.ai.sri.com/pkarp/loop.html as my primary reference... (The chapter in Practical Common Lisp helped too, but only by mentioning the word "do" - I got too excited to keep reading.)
- Sentry variables for a 'while' loop must be assigned outside the loop itself, in a LET for example. ("for x from y" might work too; I didn't check. But "for x = y" makes that assignment every iteration.)
- The 'do' after the condition-form of your 'while' is there for a reason. This is what kept me stumped for a few days, because the error just said "syntax error" instead of "'do' expected." I decided to put the 'do' on the same line as the 'while' since I don't see any reason they might ever be separated.
thisis a pseudo-variable that changes for each function but cannot be assigned to. I wanted to make my JS functions syntactically similar to native Lisp functions, so I declared the function's lambda list and body as parameters to the function that manufactures JS functions (the Function constructor).
I managed to add this to the list of arguments passed from outside, and declared it in the lambda list. But then I needed to declare a new function using a (list "variable" "like" "this" "one") as the lambda list and the passed-in body. That didn't work; apparently the lazy compiler insists on knowing what each function looks like at compile-time. </self-deprecating-sarcasm>
Alright, enough about JS mechanics; here's the solution I got on a forum:
(defun makefun (name lambda)
(labels ((havefun (&rest args)
(let ((*this* "more details"))
(apply lambda args))))
(funcall (makefun "will travel" (lambda ()
I didn't compile that, but it should print "more details." What's sad is that I had read about special variables shortly before asking that question (a day at most, I think). I understood them, but for some reason the long way around the tree occurred to me first, as always.