[ art / civ / cult / cyb / diy / drg / feels / layer / lit / λ / q / r / sci / sec / tech / w / zzz ] archive provided by lainchan.jp

lainchan archive - /λ/ - 21131

File: 1482784080142.png (1.24 MB, 300x116, Space-cadet.jpg)


This is the Lisp General, ask any and all Lisp questions here. Below is a link to the general's texts which contain many links to various books, documentation, websites, and other interesting information.

>Check the texts first:


>Read the FAQ:


>To foster discussion:

Which dialect do you prefer?
Do you use Emacs or a different lisp-based editor?
What was your first experience with lisp?
What have you made in lisp?
What is your favorite Lisp program?
What do you like about Lisp?
How do you think Lisp is (one of) the superior programming language(s)?
How long have you been programming in Lisp?
What are your favorite Lisp resources? Please share, preferably links!
Is Lisp your main programming language or not? Regardless, what do you primarily use it for?
What would you like to see in the Lisp general?
What was your favorite aspect of the Lisp machines?
Do you think we'll ever get something similar to the LispMs again?
What is your preferred method of documenting your code?
In the dialects that allow it, do you make many reader macros or not?
Do you use more than one dialect? What are they and which do you prefer?
What do you consider the criteria for what constitutes a Lisp to be?
What is your favorite function in your chosen dialect(s)?

As with the last thread, write some utility functions or other enhancements that would be useful in other programs.



Every time I read it I agree with it more and more.

>Style considerations aside, macros have tool problems. Macros are notoriously hard to debug, and honestly it needn't be that way. If your editor knows all about macros, then you should be able to click to see the expansion, and click again to see its sub-expansions, all the way down to the primitive functions. Some editors can do this, but none of them (that I'm aware of) handle macros as cleanly or seamlessly as they do normal functions.

Racket Lisp has actually gained the most ground here. Macro expansion is in the editor. This is partly because Racket Lisp totally rethought the fundamental model behind macros and simplified it to a series of expanding scopes. Considering how difficult macros are to debug and how fundamental they're considered to Lisp, this is a great accomplishment. Unfortunately, almost all of Yegge's other points are STILL valid, even in modern lisps like Clojure and Racket.

Even simple things like polymorphism are things that I miss when I come back to a Lisp language after working in something more conventional. Racket has generics like (sequence-length ....) that work for all sequences like lists, streams, dictionaries, vectors, strings but they were added too late to replace their regular equivalent like (length ...) that work only for a specified data structure (normally the list), and they're not actually polymorphic iirc. They're still a hackaround. Polymorphism hasn't been worked out yet. Clojure can depend on the JVM for a lot of these things, but runs into its own problems (can't optimize tail calls, error messages).

His first problem about the lack of a canonical lisp is still a really big deal, although I just point people to Racket or Clojure depending on whether or not they (want to) work with the JVM. I wish the Common Lisp and Scheme standardization committees would just heave their respective languages out and decide to settle on making a single Lisp, The Language standard but each group is firmly fixed on backwards compatibility or maintaining an arbitrary degree of conciseness that it won't ever happen, so this problem is pretty much never going to be fixed.


I will judge this essay based on the now, whether than the then. I'm also well aware that I seem to adhere to the stereotypical Lisper with several of my opinions and solutions, which I don't find an issue.

>Problem 1: Which Lisp?

>Pick Scheme, and you have to pick a Scheme. Pick Common Lisp, and you have to pick a Common Lisp. Heck, there are even two or three flavors of Emacs-Lisp out there.
While Scheme does suffer from massive implementation differences, Common Lisp has one standard and multiple implementations, making it a nonissue. Emacs Lisp is whatever GNU releases.

The preceding paragraph completely ignores the horrible version schisms that languages such as the mentioned Java and Python suffer under.

>Eventually, if they stick with Lisp at all, they learn they can override most of these defaults in nonportable ways, which makes things infinitesimally more bearable.

There's rather nothing nonportable about the vast majority of things one can do with a Common Lisp implementation with regards to the language's stranger corners.

>So Common Lispers grumble about Paul in the hallways. If I read newsgroups (every time I try, the overall ugliness of humanity drives me away within hours; I only re-attempt it every decade or so) I see them grumbling there too.

I don't think about Paul Graham at all.

>Problem 2: Worthless Spec

>But what's wrong with Common Lisp? Do I really need to say it? Every single non-standard extension, everything not in the spec, is "wrong" with Common Lisp. This includes any support for threads, filesystem access, processes and IPC, operating system interoperability, a GUI, Unicode, and the long list of other features missing from the latest hyperspec.
I'm rather glad that Common Lisp isn't dying because some people wanted it to grow on Windows and UNIX as if a tumor.
If I'm using a Lisp integrated with an operating system, I'd prefer it be a good one.

>Problem 3: CLOS

>One obvious one is that length isn't a polymorphic function. It's one of the first speed bumps you encounter.
Create a new LENGTH in a different package.

If one doesn't like CLOS, avoid using it when possible. The solution for many of its perceived issues is creating an extension to CLOS with macros and new packages.

>Problem 4: Macros

>Lisp has a little syntax, and it shows up occasionally as, for instance, '(foo) being expanded as (quote foo), usually when you least expect it.
I'm confused as to what this is even meaning. How could this surprise anyone with even a passing familiarity with the language?

>Problem 4: Type System

I don't much care for type systems beyond the basics, so I like Common Lisp's reasonably well.

>The Lisp communities (yeah, there are a bunch) are going to have to realize that if Lisp is ever going to be massively successful, it needs an overhaul.

This isn't an area of concern for me and I'm forced to wonder why this individual seems to care.

>Contrary to what some might tell you, it doesn't need a committee, and it doesn't need a bunch of money. Linux proved exactly the opposite.

Linux is a cloned part of an operating system from the 1970s grown more cancerous.

>Lisp needs a benevolent dictator. Lisp needs to ditch the name "Lisp", since it scares people. And Lisp needs to learn from the lessons of the 45 years of languages that have followed it.

There's much to be said for different approaches to language community and whatnot, all having their merits.
If one wants a Lisp with a dictator, use Emacs Lisp, which also happens to provide all of the facilities lacking from others that this article mentioned.

In short, this article is over a decade old, but I wouldn't write that it ever had much of a valid message.


It's an old article that's pretty outdated but I'll comment from my perspective with Common Lisp.

>Which Lisp?

I don't consider this a problem, but I suppose I've never participated in editor wars either. Just pick an implementation. If it doesn't have a feature one wants, pick another. If all choices are eliminated, pick another language. Granted that there were portability issues in the past but there's work done to bridge the gaps between implementations. I say in respective order of implementation priority: SBCL, CCL, and then finally CLISP. ECL for extreme C interop. Maybe ABCL for Java interop but Clojure would likely be better.

The same argument has been used to point out 'why Linux is like kicking dead whales down the beach' while pointing at all the different distributions available. Strong adoption requires community consensus, lots of people, and 'marketing' which is unlikely to improve in a language philosophy that's very much about choice. The userbase is small in the first place so there aren't many lisp memes out there like 'Ubuntu is for beginners'. Informative/helpful community and resources will likely be best that can be offered for helping new lisp programmers.

>Worthless Spec

Ancient is 'kind of' a problem. There are historical compromises in the spec that can be annoying but in practice it isn't much of an issue. There's a hyperspec that's helpful in clarifying/finding the right symbols with garbled names. I don't expect myself or anyone to have them all memorized either. A beginner doesn't have to know all the keybindings before using Vim/Emacs to start editing, only the bas -- oh wait, wrong subject. The editor should be used to show info about argument order/name for inconsistent functions anyways. Semantics is far more important for lisp code. For example if one is reading code written using NTH and ELT, it isn't necessary to know what order the arguments should be in because the difference is negligible when every context using the functions will return an item in some position from some list/sequence.

For things not in the spec, there's been plenty done on portability layers and libraries which smooths out many issues in the past decade. Of a few categories listed:

(Threads -> bordeaux-threads), (Filesystem -> UIOP / cl-fad), (Processes & IPC -> UIOP), (OS Interop -> UIOP), (GUI -> cl-cffi-gtk (GTK+3, although broken on windows), commonqt/Qtools (Qt4), cl-tk/ltk (Tk), and etc.)


This could be valid but there are points listed that are factually wrong. Methods are not macros and can be used as functions to MAP without a fuss. In practice LENGTH can be redefined as a method and it was pointed out as well:
(shadow 'length)
(defmethod length ((thing list))
(cl:length thing))
(defmethod length ((thing vector))
(cl:length thing))
Aside from that, if not CLOS then what? Rephrased, he says, 'I don't like it because it's different' and 'I want a single dispatch system'. The latter would be an interesting idea to see whether it can simplify OOP in some cases. It's cheap to roll a new object system with closures. If it gained features and turned into a library I'd check it out. The flexibility/extensiblity of the CLOS that differs from conventional object systems are suppose to be features. I'd recommend using another language otherwise.


What it means to be 'hygenic' is more of a programmer's preference. It definitely would be nice to have better tools debugging macros but that doesn't mean macros are bad, they're just another feature.


I don't know enough about type systems to comment but the lisp called Shen might be of interest.


This article came out in 2006, Clojure did not exist yet, only old fashioned dialects that were built on the cons cell. Everything about this article is now obsolete now that we have Lisp dialects like Clojure and LFE which have completely erased the cons cell and run on much higher data structure abstractions. And then you have hybrid languages like Elixir which completely erase all the syntactic barriers that once defined a Lisp. Anyone who even bothers to read that whole article has just wasted 15 minutes of their life listening to someone complain about how their horse and buggy is showing its age against motor powered vehicles.


Is Clojure really that huge? I thought people hated it because of its dependence on JAVA.


Clojure is not dependent on Java, there are implementations of Clojure that run on .NET and Javascript


a handy cheatsheet for Racket that I wasn't aware existed


JVM Clojure is actually the single most used Lisp implementation afaik. Many of the users aren't necessarily old lispers though, but people who were previously unfamiliar with Lisp.

Being a single-implementation JVM language has some significant disadvantages, but it has some big advantages as well. Clojure arguably has the best library ecosystem of all the Lisps and performance comparable to SBCL.


...But the motor powered vehicles you're talking about (Clojure) are worse off for doing away with the cons.

Also, LFE totally has conses: so does Erlang, for that matter.


start listening at about 1:37


File: 1483029389790.png (28.32 KB, 138x200, images.jpg)

I'm on Arch Linux. What editor do I use for SICP? Does EMACS have an SICP mode?


That's entirely your choice, but emacs with paredit installed (https://www.emacswiki.org/emacs/ParEdit) is a good start.

If you want to evaluate your code inside the editor, and you probably will, see https://www.emacswiki.org/emacs/Scheme . As for the scheme dialect to use, I like Chicken scheme, but Guile might play more nicely with emacs. I seem to remember that Chicken had some annoying problems I had to debug when I set it up with emacs a while back.


What you need is a Scheme interpreter. Racket has a sicp "sublanguage" (#lang sicp), Emacs has a mode for racket interaction called geiser, and a lisp edition mode called paredit. Paredit takes some time to get used to but it's very nice.
You could otherwise use any other Scheme, geiser supports gnu guile and chicken scheme, at this point I assume you probably don't really care about the differences, so I guess racket's #lang sicp would be best.


SICP is designed for use with the Scheme Programming Language. There are several implementations to choose from.

SICP was originally designed for use with MIT Scheme (https://www.gnu.org/software/mit-scheme/), which comes with its own, emacs-like editor written entirely in Scheme called Edwin: you can call (ed) at the prompt to bring it up, IIRC. This isn't really all that important, however: Any compliant implementation of Scheme should work.

A common suggestion is to use Racket (http://racket-lang.org/) in Scheme mode, and use the Dr. Racket IDE that comes with Racket as your editor. If you like IDEs, that's what you'll probably want to do.

If you're an undying Emacs fan, and MIT Scheme's Edwin can't sate you, don't worry, you can use Real (GNU) Emacs as well: Scheme-mode comes with emacs by default, IIRC, but you'll want to install Geiser (http://www.nongnu.org/geiser/), which provides SLIME-like integration with a variety of Scheme implementations: Just use MIT Scheme for SICP if you can't decide which one you want to use. If you go down this road, I would also recommend installing Paredit, which makes editing Lisp a lot more pleasant.

You can, of course, use VIM, or any other editor, but most of them do not provide the incredibly-useful tight REPL integration of the above editors, and are otherwise ill-suited to editing Lisp.


>Download Racket Lisp
>open DrRacket (the built-in editor)
>select "SICP" from the language menu
>get back to studying instead of spending anywhere from several days to a week fiddling with an editor
This is, IMO, the best solution from someone who's new to Lisp and emacs and just wants to get started with SICP. Many modern scheme lisp languages aren't fully compatible with SICP anymore, so it's easier for someone who isn't experienced to just get the lisp language that has a built-in SICP compatibility mode language designed for this book.


>Many modern scheme lisp languages aren't fully compatible with SICP anymore

That's not true. Gambit, Chicken, Bigloo, Chez, MIT, Racket (in SICP mode), Guile, and Chibi all support most of R5RS, and thus SICP, AFAICT.


I think only Racket's SICP language supports the picture language and the lazy constructs (as in the book) out of the box.


But, IIRC, you write them yourself, or the book doesn't ask you to evaluate those. One of the two.

Anyways, if you really need them to do SICP, then MIT Scheme has got it, because SICP was written to work with MIT Scheme.


In light of the new year, I was heavily rewriting some routines I use and decided to make them suitable for others:

I've not yet tested it much, but don't believe it contains any horrible flaws. There are some design considerations I declined to address, such as allowing richer lambda lists and easier customization of read variables. Feel free to critique this or make suggestions.

The purpose of this small library is to facilitate easy creation of questioning functions. Each generated function accepts a string and optionally a stream, by default. Functions to read input, parse input, and validate input may be provided.

Read errors are ignored, which can possibly lead to some issues. Providing customized read error handling is something I'd like to add later.

I suppose a resolution for this new year is to be more active and release more programs, something every month, at the least. I've not forgotten of those programs I wanted to release from the last thread, but those aren't ready for various reasons.

I also wrote this routine, for convenience, but didn't end up using it for this library:
(defmacro 0lambda (&body body &aux (args (gensym)))
"A lambda of variable arguments that ignores all of them."
`(lambda (&rest ,args)
(declare (ignore ,args))


Saw this on hckrnews a few days ago
Wish this was around a few years ago when I tried to get my friend who loves Scheme into writing CL with me, he was so annoyed setting up slime he gave up


>he was so annoyed setting up slime he gave up
$package_manager sbcl
M-x package-install slime
C-x C-f .emacs
(setq inferior-lisp-program "/path/to/sbcl")
(setq slime-contribs '(slime-repl)) ; optional

Some people should just not be allowed to use computers if they get frustrated by this


its not quite that easy on some distros. I remember when I t ried on debian a while ago the SBCL on debian was way older than the Slime on elpa/melpa and it kept yelling at me that things would break. Sure I disabled the message, but who knows what neat features I was missing out on because Debian moves like a glacier.


oh, yes, that's true, debian packages are still in the mainframe era.
You're right, I have these kinds of problems all the time with every OS for whatever reason.


This has been a good effort in a direction of something along the lines of lein: https://github.com/roswell/roswell


I think the most often recommended way today is through quicklisp. That's a bit more fiddly, especially if you're not all that familiar with Lisp or Emacs.


Besides your .emacs, what lisp projects are you currently working on?


how do I write a macro for this form

(concat (repeat 3 (some-func))) 

;; -> (concat (some-func) (some-func) (some-func))


Clojure uses ~@ to splice lists within a backquoted form.

(defmacro myconcat [times DOIT]
`(concat ~@(repeat times DOIT)))

(macroexpand '(myconcat 3 (JKDFJD)))
;; => (clojure.core/concat (JKDFJD) (JKDFJD) (JKDFJD))

(myconcat 3 (range 1 5))
;; => (1 2 3 4 1 2 3 4 1 2 3 4)


The quicklisp website is clear enough on how to install it. Anyway, slime is in the Ubuntu repository (and probably on Debian too), that's what I used before I started messing up with quicklisp. It was a matter of doing an "apt-get install slime" then "M+x slime" from inside emacs.



and in Common Lisp?


`(symbol ,@alist) ; where alist => (a b c)
;; macroexpands to (symbol a b c)


So fellow lispers know: There is #programming on the the lainchan IRC. Lisp programming is often discussed. Please join in.

Point your client to lainchan.org port 6697 (ssl only)


Can someone explain the whole concept of recursive evaluation for me? I have no understanding of mathematics beside some basics i've learned at school.


Better read The Little Schemer for that

"Comment was succint and to the point, make it longer"



Think of a function as this: it takes arguments and returns a value. If you change the arguments, you change the return value.

When using recursion, instead of looping or whatever, the function simply calls itself again with different arguments.

Here's one rather stupid example of non-tail recursion:


add_nums(int a, int b)
if (b > 1) {
return 1 + add_nums(a, b - 1);
} else {
return a;

Try running that on paper with small positive values.

Of course, every time the function gets called, it pushes another frame on the call stack. If you had a large value of b, you'd probably run out of stack space.

Tail recursion solves that problem. If you change the first return statement to this:


return add_nums(a + 1, b - 1);

Then there's nothing left to do in the function after the recursive call. A good compiler/interpreter/whatever will see this and optimize it so that it reuses the same stack frame.

Not all problems can be converted to tail recursion, and not all languages or compilers support tail recursion. I used C here because while C doesn't guarantee tail recursive optimization, most C compilers can do it. GCC and Clang both do, and I would be very surprised if MSVC++ doesn't.

The best explanation for regular (non-tail) recursion came from the SICP videos, but I don't remember which video talked about it. It'll be one of the earlier ones.



Bah, misread the FAQ on how to put in code formatting. Please ignore the "C++" in the code blocks.



Bah, and also change the (b > 1) to (b > 0).

Dunno why I thought I could write code when I'm half asleep.


File: 1484625682175.png (7.66 KB, 192x189, gnu+emacs.jpg)

What do you think of emacs packages that provide structural editing, such as Lispy[1], Paredit[2], and Paxedit[3]? Do you use them (abuse them!?) or ignore them? Please provide a rationale.

I'm quite a fan of the environment Lispy provides, which is semi-modal editing for languages with sexprs, notably Common Lisp, Clojure, and Emacs Lisp. What I mean by semi-modal editing is that before an sexpr, pressing the letter a allows me to jump to a symbol, but once I'm inside an sexpr the letter a self-inserts. You get a lot of commands this way and there isn't much, if any, context switching. See https://www.youtube.com/watch?v=BverGxP41cE

[1] https://github.com/abo-abo/lispy
[2] http://mumble.net/~campbell/emacs/paredit.el
[3] https://github.com/promethial/paxedit



I use paredit.

But because I use evil-mode, I don't use most of its features. I mostly just use slurp/barf and kill-sexp - those and automatic parentheses balancing are the killer features for me.

I really need to hack a bit on the keymap for evil-mode so that it integrates better with paredit.


Check out lispyville https://github.com/noctuid/lispyville I hear it's a wonderfully sinister combination of evil and lispy.



Paredit is my preference, but mostly because it was the first one I used and learned keybinds for.


Paredit is "proven" and works well. Never looked into the others; wouldn't know what makes them better/different.


i find it weird that emacs doesn't come with this kind of functionality by default

i use smartparens




The Little Schemer is hands down the best book for learning recursion.


File: 1484815649871.png (174.76 KB, 200x185, 1445461259183.png)

I hacked some Elisp together so I could use the puush[1] service to upload text highlighted by region or the entire buffer if not. Nothing substantial but it works. To use it you need to create a puush account and grab https://github.com/sunmockyang/puush-linux.

I invite others to share some Lisp code, whatever dialect. Happy hacking.

(defun puush ()
(let ((filename (concat "/tmp/" (buffer-name) "@" (format-time-string "%Y-%m-%d"))))
(if (use-region-p)
(region-beginning) (region-end) filename)
(write-region (point-min) (point-max) filename))
(call-process-shell-command (concat "puush " filename))))

I bound this to C-c p via (global-set-key (kbd "C-c p") 'puush)

Also, I've tried to get Lisp syntax highlighting (because of indention, not the colors) but I can't seem to figure it out. See my /test/ spam.

[1] https://www.puu.sh




It depends on two more libraries in that repo (one directly one indirectly) but...

More miscellaneous goodies in that repo BTW, both for elisp development (utility libs) and for emacs usage.

Other than that, my most proud invention:



Common Lisp's support for generic functions is quite strong.


I have a question about your library. How would you represent something like void * and function pointers?


Hello lains. I was hoping someone might be able to assist me with a problem I have run into with SBCL.

I'm trying to set up a blog using Coleslaw. It works fine until I try to enable incremental builds. I'm getting an error that looks something like this:

remote: (UIOP/RUN-PROGRAM::%CHECK-RESULT 1 :COMMAND "git diff --name-status 487f0e4e56752e763229ae09dc1331ed996e7aef HEAD" :PROCESS NIL :IGNORE-ERROR-STATUS NIL)
remote: 0]
remote: * debugger invoked on a UIOP/RUN-PROGRAM:SUBPROCESS-ERROR in thread
remote: #<THREAD "main thread" RUNNING {1001BC2743}>:
remote: Subprocess with command "git diff --name-status 487f0e4e56752e763229ae09dc1331ed996e7aef HEAD"
remote: exited with error code 1

Now obviously I don't expect anyone to know what the problem might be, but I was hoping that you might be able to explain how I can find out what the actual error message 'git diff' is exiting with is. I've never used SBCL (in fact, I'm not really much of a programmer) and I have no idea how to debug with it. If I just knew what the output of 'git diff' was, I could probably fix this.

Thanks in advance for any help.


File: 1485016336358.png (196.97 KB, 150x200, 1438200095923.jpg)

Slowly learning emacs lisp here, I have a problem.

So I was looking at the ispell source code, and I find this:
(defvar ispell-parser 'use-mode-name
"Indicates whether ispell should parse the current buffer as TeX Code.
Special value `use-mode-name' tries to guess using the name of `major-mode'.
Default parser is `nroff'.
Currently the only other valid parser is `tex'.

You can set this variable in hooks in your init file -- eg:

\(add-hook \\='tex-mode-hook (lambda () (setq ispell-parser \\='tex)))")

I tried to understand wtf is 'use-mode-name, but I found nothing in the documentation, and nothing on the interweb.
The only thing I know is
>Special value `use-mode-name' tries to guess using the name of `major-mode'.

How come 'use-mode-name becomes 'tex when in latex-mode? Where is the function that does that? Is this some kind of dark magic?



I'm new to elisp as well. However I believe that 'use-mode'name uses the name of the current emacs mode. So if you are in a major mode that is Latex, it would spit that out.


strip the comment, you end up with
(defvar ispell-parser 'use-mode-name)
Which means ispell-parser is a variable set to the symbol 'use-mode-name.
Which I infer is used by the parsing function, which reads the contents of `ispell-parser' to know how to parse it, either by mode name (eg tex-mode) or some specific value, the options being 'tex an 'nroff.


But where the hell does it ever get set to 'tex?
When I evaluate it in a latex-mode buffer (after having used flyspell-buffer), it is set to 'tex, but I don't where it is done.


well, look at the source file of ispell and C-s ispell-parser
Some function should check for the values of ispell-parser to know how to behave


Why do so many .el files begin with three semi colon comments, and end with "file.el ends here"? Is there a practical reason?


I don't know about the "file ends here", but the three semi-colons is here to declare local variables in emacs https://www.emacswiki.org/emacs/LocalVariables




I don't quite like some of the Lisp conventions. For example I enjoy beginning the very top comment of a file with a single Semicolon. Another thing I like doing is having all conditions being indented at the same level even with the ending condition. Example: https://w1r3.net/dSJXWG.txt



That's the convention for package documentation.

There are several sections divided by headers. Headers all start with three semicolons.

Following the convention makes it easier to parse the file by machine. If you do C-h P, you can see an example of this.



The commenting thing is just a convention when you're not using it for Emacs packages. You'd probably have to hack a bit to get Emacs to not fuarrrk with it, but it shouldn't be too hard.

I'm not sure why Elisp formatting is so weird on conditionals, though. Scheme mode doesn't do that.

Bear in mind that Elisp style comes from the same fine folks that bring you GNU style for C programs. If you're not familiar, look it up, and then go get a drink.



Huh. Didn't know Stallman was quite handsome when he's young.


Stupid sexy Stallman.


File: 1485216921192.png (516.67 KB, 200x195, 1367108251.png)

What's your Common Lisp documentation setup like? I've tried using gcl.info[1] but it doesn't have a symbol index like the CLHS[2]. What I've found best is to install a local copy of the CLHS and use that in combination with Eww. Best way to do that is to evaluate (ql:quickload "clhs") and (clhs:print-emacs-setup-form) in slime and follow the instructions. Even this is lame though. The presentation is lackluster (and ugly) compared to a nicely structured info file, sigh..

[1] http://irreal.org/blog/?p=3815
[2] http://www.lispworks.com/documentation/HyperSpec/Front/X_Symbol.htm1


The number of semicolons doesn't matter when declaring local variables. The number of semicolons (for common lisp and elisp) is just a stylistic convention (4 for the beginning of the file in cl; 3 for headers; 2 for regular comments; 1 for comments on the same line after code).

> Another thing I like doing is having all conditions being indented at the same level even with the ending condition.

The indentation of if for both cl and elisp both make sense. Your indentation doesn't.



I think he's mostly referring to the following:

(if conditional

In Scheme mode, it's indented as such:

(if conditional

I prefer the latter, personally, although I can see valid arguments for the former.


The former makes sense for elisp since you can have as many else forms as you want.

Maybe the example ^ gave was a mistake, but the weird wording ("all conditions... even with the ending condition") makes it sound like it wasn't. The person also called it a lisp convention, so it wasn't clear if they were only criticizing the first style (the example was in elisp though).


File: 1485395426269.png (423.96 KB, 200x193, 1462658532001.jpg)

Regarding elisp, is there any reason one should not insert multiple settings into a single setq expression?

I'm also curious if anyone can point me to the recommened style guide, as well as a list of best practices, and dos and don'ts for elisp.



I tend to group my setq expressions logically. For instance, I have all the application window stuff in one setq, and all the fill/wrap stuff in one, etc.

As far as style goes, I saw an interesting note on emacshorrors about "idiomatic" elisp. It has an example of rms' style and notes that it's quite different than most elisp veterans.

Anyway, there's a style guide at https://github.com/bbatsov/emacs-lisp-style-guide but I don't know how well accepted it is.


Does anyone know of a "Lisp-in-a-Box" for Windows based on SBCL? By which I mean, an auto-installer for Emacs, SLIME, SBCL and perhaps ASDF/Quicklisp

The closest thing I can find is https://common-lisp.net/project/lispbox/ but that's for CCL


There's lispstick, which installs all that, and can be found here: http://www.iqool.de/lispstick.html

Check the github repo for the latest release, it's the one linked from the first comment.


File: 1485660538159.png (3.07 MB, 185x200, 25.png)


Would this be fine for learning emacs and associated lisp tools?


It would, but it depends on your current platform. With it being beta software, it has it's quirks. For example, I get a segfault if I try running it on Debian testing (https://github.com/Shinmera/portacle/issues/19).

What I recommend until this becomes stable is to install vanilla Emacs, read the tutorial (Control+h t), and then read https://tuhdo.github.io/emacs-tutor.html


I just bought Common Lisp the Reference and Common Lisp the Language


I've made some improvements to INTERROGATION: https://lainchan.org/~lisp/interrogation.lisp
The previous version is still available here: https://lainchan.org/~lisp/interrogation.old.lisp

I added the ability to specify a REPEAT parameter, which controls if a question will be repeated or not. I also corrected a flaw I recognized; consider identifying this flaw to be an exercise.

Lastly, for anyone having used this, I changed the parameters from specifying literal function designators to any S-expression that evaluates to a function designator. The ramifications of this change can be observed with the changes made to the provided QUESTION- functions.

Also, being fond of variadic procedures, considering the ease of these being one of Lisp's main notational advantages, I use an internal macro I created named DEFNMACRO; this allows one to create a (more) variadic macro from a normal macro. As an example, NDEFNMACRO can be created with (defnmacro defnmacro), which then allows one to make multiple DEFNMACRO calls in one S-expression.


Is there something similar for Scheme?


For scheme people tend to use GNU Emacs with Geiser.



I meant something like an auto-installer for Emacs and everything needed to comfortably work with Scheme.


This seems to be what you want and it comes with geiser: https://github.com/bbatsov/prelude


I'm studying some stuff and it got me thinking:

>delimited continuations

>memory management as stack allocation

I'm wondering why stack allocation is not more widely used in programming languages.

Specifically, why do we favor heaps when we can have split stacks instead? Programs can allocate memory on the stack without fearing it will overflow. This is faster and requires no system calls. It will also help avoid the complexity of asynchronous programming: threads can have small stacks and grow as needed, so we can have a million threads without memory requirements exploding.

You guys know of languages/implementations that use this concept?


My thinking is that Forth would technically qualify for this.


While having "forkable" stacks as parent-pointer data structures is useful for implementing continuations in a rather elegant way, it will only help multithreading in 32-bit architectures. 64 bit virtual address spaces have an absurd amount of space into which one may allocate an awful lot of stacks.

Well that's what I think. Everyone hates threads nowadays and prefers async programming despite the above so maybe I'm wrong


Overcommitting memory may introduce unpredictable latency into programs due to virtual memory being remapped to slow hardware.

Go did this segmented stacks thing but apparently it killed performance of tight loops, causing them to abandon the design. I wonder why they didn't split the stack before entering the loop though. If all they needed is enough stack space to run the tight loop, wouldn't a
making a brand new stack before starting be enough?


check spacemacs. It comes with a layer (aka configuration with popular plugins for a given language or task) for scheme


I don't need Go or Clojure to play with similar concurrency/parallelism features and build very fast servers, right?


you need concurrency/parallelism. You don't need go or Clojure. Anything that gives you access to those concepts will be usable



Lots of languages support concurrency and parallelism. What exactly are you wanting to do?

For a certain class of parallelism, OpenMP is very easy to work with and simple to learn. It only works with C, C++, and Fortran though. I've used it with C and Fortran for number crunching - it's quite nice.


damn i wish the terminus font had a nice glyph for the lambda character

i just feel like it looks cleaner if you use the symbol


I have the possibility to begin a new project in lisp, most likely Clojure due to the JVM and current popularity and adoption, and personally since I can use clojurescript too.
Any recommendation? like frameworks or something?


Does anyone know of a neat monospace font with a nice lambda glyph?


fixedsys excelsior exists, but its lambda glyph just looks bad

good if you liked the old VGA font though


oh and there's also GNU Unifont, which covers a LOAD of glyphs, though i think it's not as good looking as terminus

wikipedia claims it's "semi-monospaced", whatever that means


It means that there are two glyph widths. If I recall correctly, most glyphs in GNU Unifont are 8x16. The rest are 16x16 - for example, the Chinese characters.


Reagent and re-frame.



This is an IDE similar to Squeak (the Smalltalk environment) for CL. I thought it was pretty cool.


I meant pLisp, their own dialect. It isn't fit CL.


File: 1486769143934-0.png (36.99 KB, 200x107, foo.png)

File: 1486769143934-1.png (36.62 KB, 200x107, foo1.png)

PragmataPro is a wonderful font: https://archive.fo/5Hb2O. Uploaded here: https://0x0.st/4sF.zip


File: 1486820554450.png (94.25 KB, 200x158, 1oJ6juxSedxj2nM5T_ex1bw.png)


Looks awful in xterm, but beautiful in Emacs. Putting this in my .init.el, thank you.


My settings are (setq default-frame-alist '((font . "PragmataPro:style=Regular:size=18:hintstyle=hintslight")))


For some reason, the digamma glyph looks accurate when the font is set in .Xdefaults with *faceName, but looks inaccurate if set within Emacs.


What do you mean and how are you setting this in xdefaults?


Of note, February twelfth marks the third anniversary of the Lisp General threads.

What have you learned related to Lisp from these threads?

Here's to more.


Your git command is returning an error. ("exit with error code 1" is a Unix thing telling you that the Git Diff process failed for some reason)


File: 1486938481803.png (30.78 KB, 160x200, fantasque.png)

Fantasque Sans Mono is alright

But DejaVu and Liberation are good as well, also the default in most places.


File: 1487275130968.png (72.54 KB, 200x200, Avoiding Confusion in Metacircularity: The Meta-Helix.pdf)

Old CLOS paper:
Avoiding Confusion in Metacircularity:
The Meta-Helix
Shigeru Chiba, Gregor Kiczales, John Lamping


File: 1487620636271.png (1.09 MB, 200x200, David_S._Touretzky_Common_Lisp._A_Gentle_Introduction_To_Symbolic_Computation__1989.pdf)

I also enjoyed the Martin and the Dragon story on chapter 8 of 'Common lisp: A Gentle Introduction to Symbolic Computation' book.


Whenever Lisp is run on a modern unix machine it's through implementation, correct? Would there be any practical advantage to building a modern Lisp machine? I had thought the idea seemed cool but almost certainly beyond my technical skill. Right now I'm just interested if there'd be any advantage to having such a machine.


Theres not much advantage these days. A Lisp machine was cool because it was able to offer a lot of the abstractions other machines lacked at the time (like GC). However these kind of things are commonplace now, and lisp is starting to be seen as "just another language" through the eyes of most programmers.
Instead of a lisp machine we could have lisp kernels/OS, such that you have a higher level interface (able to pass around abstracted data rather than just character streams) at the process level. This is something I'm working on but it will just be experimental, not extremely useful.


File: 1487689615954.png (22.36 KB, 200x100, latency.png)

Linked lists are horribly slow compared to arrays on modern CPU architectures because they have caches (L1, L2 and L3 in the picture) whose access time is much faster than the RAM, and the pre-fetching algorithms for these caches expect data to be contiguous in memory. The next cell in a linked list could be anywhere in memory, so most of the processor time is spent waiting for the data to come from the caches or the RAM instead of actually processing things.
(That said, most lisps use more optimized implementations and algorithms to speed up lists.)
So yes, a Lisp machine with hardware designed around lists could potentially run Lisp faster than other CPUs, but like >>22210 said, at software level a Lisp-based OS and kernel would be much more useful.


Why do you assume people who use lisps only use lists?


Well-optimized Lisp code might never use a list at runtime.


All I'm saying is that on such a machine a Lisp wouldn't have to perform those optimizations.


In CL is it possible to make a displaced array from a column in the 2-dimensional parent array?
Or is it that I am using the totally wrong data structure for working with matrices?


>Whenever Lisp is run on a modern unix machine it's through implementation, correct?
>Would there be any practical advantage to building a modern Lisp machine? I had thought the idea seemed cool but almost certainly beyond my technical skill. Right now I'm just interested if there'd be any advantage to having such a machine.
A Lisp machine wouldn't have an abstraction that goes below Lisp. There would be no x86 memory dump or whatnot below it if something went wrong.

>In CL is it possible to make a displaced array from a column in the 2-dimensional parent array?
Arrays in Common Lisp are stored in row-major order; displacement must be contiguous; so no. You can do this with rows, though.
>Or is it that I am using the totally wrong data structure for working with matrices?
You can always add this manner of displacement, yourself. Simply translate the coordinates manually.


How many of you are using stumpwm?


I'm working through sicp at the moment and today I finally solved 3.26: Implementing a multidimensional table using a binary tree.

The reason this exercise took me longer than the previous ones was that you kind of mix two data structures together this time and I had trouble thinking about them independently (e.g. even in my final solution the procedures somewhat overlap as insert-multi does the job of lookup if the returned tree is not empty).

My question is: How would you structure something like this? How would you wrap everything in black boxes and show which procedure takes and returns what kind of data? I did it with comments for now.
Next thing I'm planning is replacing all the leftover car's cdr's and so on by specific accessors. Hopefully that will give me some clarity.

;; Ex 3.26
; definitions for the tree structure
(define (entry tree) (car tree))
(define (set-entry! tree value) (set-car! tree value))
(define (left-branch tree) (cadr tree))
(define (set-left-branch! tree value) (set-car! (cdr tree) value))
(define (right-branch tree) (caddr tree))
(define (set-right-branch! tree value) (set-car! (cddr tree) value))
(define (make-tree entry left right)
(list entry left right))
(define (empty-tree)
(make-tree '() '() '()))
(define (empty-tree? tree)
(null? (entry tree)))
; just integers as keys for now
(define (compare-keys a b) (- a b))

(define (make-multi-binary-table)
; internal storage for the table
(let ((table (cons (cons 'table 'value-placeholder)
(define (set-value! value) (set-cdr! (car table) value))
; assoc takes a key and a list of records (e.g. the cdr of a table)
; and returns the record-tree whose entry contains the key
; or if it reaches an empty tree, it returns that
(define (assoc key record-tree)
(if (empty-tree? record-tree)
(let ((comp-key (compare-keys key (car (entry record-tree)))))
(cond ((= comp-key 0) record-tree)
((< comp-key 0) (assoc key (left-branch record-tree)))
(else (assoc key (right-branch record-tree)))))))
; lookup takes a key and returns the subtable that is stored under that key
; or false if the key doesn't exist
(define (lookup key)
(let ((record-tree (assoc key (cdr table))))
(if (empty-tree? record-tree)
(cdr (entry record-tree)))))
; lookup-multi takes a list of keys and if the list is nil returns the
; current table's value, and if it isn't calls lookup-multi on the
; subtable returned by lookup and on the next key
; if no subtable is found it returns false
(define (lookup-multi keys)
(if (null? keys)
(cdar table)
(let ((subtable (lookup (car keys))))
(and subtable ((subtable 'lookup) (cdr keys))))))
; insert-multi takes a list of keys and a value and inserts the value in the
; corresponding level/dimension of the table
(define (insert-multi keys value)
(if (null? keys)
(set-value! value)
(let ((record-tree (assoc (car keys) (cdr table))))
(if (empty-tree? record-tree)
; create new subtable at entry and empty-trees at the branches
(let ((new-table (make-multi-binary-table)))
(set-entry! record-tree (cons (car keys) new-table))
(set-left-branch! record-tree (empty-tree))
(set-right-branch! record-tree (empty-tree))
((new-table 'insert) (cdr keys) value))
(((cdr (entry record-tree)) 'insert) (cdr keys) value)))))
;; interface
(define (dispatch m)
(cond ((eq? m 'lookup) lookup-multi)
((eq? m 'insert) insert-multi)
((eq? m 'print) table) ; need proper print proedure
(else (display "error: Unknown operation on TABLE: ") (display m)) ) )


;; If the region is active, behave as ‘M-w’, otherwise non-destructively kill
;; the whole line.
(defun luser/nond-kill-line ()
(if (region-active-p)
(kill-ring-save (region-beginning)
(kill-ring-save (point-at-bol)

This behaves how I want but it's terribly ugly. How could one write this more elegantly and in the future how would I go about discovering more elegant solutions to programs and such by myself?


>A Lisp machine wouldn't have an abstraction that goes below Lisp. There would be no x86 memory dump or whatnot below it if something went wrong.
Lisp Machines compiled to bytecode too.


It's my WM of choice. I probably don't get as much out of it as some, but it's very comfortable after some customisation and the ability to hack around in slime is very handy.

But the bytecode was still representative of Lisp's fundamental units like cons cells, wasn't it?


You could also just use a library that implements matrices.


>But the bytecode was still representative of Lisp's fundamental units like cons cells, wasn't it?
Oh, you mean that it had operations for cons, car, cdr then yeah that's definitely possible. I wonder how that would work with GC though, cons car and cdr aren't necessarily that simple. I wouldn't be surprised if a lot of LMs implemented cons in software, given that hardware GC doesn't really seem like a possibility. I don't know much about this kind of thing though!


This is what I use for copying lines.

(defun copy-line (arg)
"Copy lines (as many as prefix argument) in the kill ring"
(interactive "p")
(kill-ring-save (line-beginning-position)
(line-beginning-position (+ 1 arg)))
(message "%d line%s copied" arg (if (= 1 arg) "" "s")))


File: 1488010234516.png (154.56 KB, 200x184, kid-programming-a-robot.png)

Hope this is not a dumb question but I found not very much current information on this.

I am looking for a language to extend C/C++ with. I have never done this before so I do not know what's important here. And I am thinking about using Guile. An alternative would be Lua. I just have some basic experience with Racket and Emacs Lisp so I am not that experienced with Lisp/Scheme languages.

Does anyone know about the advantages of Guile over Lua? The latter one has a larger community and more documentation available because of the Game Dev community. I read multithreading is easier in Guile… On the other hand it is larger but that should be not much of a problem.

Has anyone experience on this subject?




I haven't used guile in a C program, but I've read about it while adding scheme support for a C library. It looks pretty straightforward. The guys in #guile on freenode are pretty helpful. The documentation is decent.

I've only really used Lua for Minecraft scripting, but I don't much care for it; it's too Javascripty for my tastes. If you like the whole prototyped OO paradigm, then Lua might be be a good choice for you.

TL;DR both languages are made for what you want to do, so pick the one you like to program in the most.


I've read a few chapters of Clojure for the brave and true thus far. I like the book and the language alot. My only qualm so far is the dependence of the JVM/CLR I wish it had a lighter weight language engine for quick scripting, like the guile vm or something.

What is the general opinion held on clojure here?



My 2 cents:

- JVM dependency
- Java inter-opts

- JVM dependency
- Java inter-opts (seriously, writing code to interface Clojure with Java makes me want to kill myself)


I liked the look of it until I learnt that there's no TCO. I understand that it's not a possibility on the JVM but I'd like to take advantage of recursion without worrying. I know that it's not part of the CL standard, but in reality most implementations do support it.

>seriously, writing code to interface Clojure with Java makes me want to kill myself
How does it compare to the Cffi in CL? That always makes me cringe a bit and desire to hide away the code.


is there a repository of guile scripts floating around somewhere? i'd like to use it more for my automation needs but I haven't found a good corpus of code to study


File: 1488211499267.png (60.01 KB, 135x200, IMG_20170227_170440.jpg)

Someone ever use picolisp? Seems interesting to me, what do you think?



Try GUIX. It's kind of like a package manager for GNU software. It'll run alongside your existing package management software.

There's also GUIX-SD, which is a Linux distro that uses Guile for configuration (and uses GUIX for package management).

If you just want Scheme code to look at, try script-fu.



I should have been more specific in >>22313

GUIX uses Guile extensively, so it's probably close to what you're looking for as far as automation.


Here is a list of guile programs and libraries http://sph.mn/content/3e73


Awesome, thanks for the resources.


I managed to get TinyScheme running as a script for my own game engine, complete with an embedded REPL on a debugger overlay, but the code is kind of a mess so I'm thinking about switching to another library, such as Chibi.
Parallelism wasn't a goal, I just wanted to get game logic script working with my component-based entity code.

I can guarantee that Guile is such a fine implementation and you won't regret using it, but my reason to drop Guile was not finding an ideal port to Windows/MinGW (and lack of maturity perharps. Didn't want to mess with Guile's source).


Is it worth to learn CLIM today? Is McCLIM a good enough implementation of it?



Eww, Qt. Are CL people really stuck with jury-rigged C++ toolkits if they want GUI?


I don't think it makes sense to say that about qtools; it is a lot more lispy than you might think. That said I agree that QT is gross.

I wouldn't say that it's in a great place right now, but CLIM is being worked on again, so there is hope for CLIM.


Someone should make something like Electron, but for Scheme. Yank out the Javascript and replace it with Scheme, use software to convert S-Expressions into HTML...


I bind this to ‘C-c x’: https://0x0.st/tc_.el


GNU Guile 2.2 is out, a lot of improvements.



>** Complete Emacs-compatible Elisp implementation
>Thanks to the work of Robin Templeton, Guile's Elisp implementation is
>now fully Emacs-compatible, implementing all of Elisp's features and
>quirks in the same way as the editor we know and love.

I keep hearing about some people wanting to make emacs use Guile, but what's the actual advantage? Is it just that maintaining one lisp implementation is better than two?


You have to look at the original purpose of GNU Guile, basically an embedable project which allows any GNU project to be extended the same way as emacs. With emacs also using Guile, libraries can be shared between GNU projects. Guile can also support other languages, not just lisps.


All I wanted was Windows or MinGW support so I could run my game engine with Scheme scripting everywhere... I guess I'll have to add an optional Lua REPL on the console.


Unfortunately there doesn't seem to be many devs using windows and have the time and ability to invest in making sure Guile works on Windows.


why not tinyscheme or bigloo or something?


Tried TinyScheme but it wasn't that good. I was thinking about Chibi but I'm still pondering about it since I'd have to rewrite the whole backend.


Chibi seems quite nice.


I've started reading The Little Schemer and doing the exercies in it. It asks me to implement a + function which adds two integers, using their add1 and sub1 functions.

I've come up with this:
  (define PLUS
(lambda (a b)
((zero? b) a)
(PLUS (add1 a) (sub1 b))))))

while their answer looks like this:
  (define o+
(lambda (n m)
((zero? m) n)
(add1 (o+ n (sub1 m)))))))

Is there any reason to prefer one over the other? Or is just a different approach to things? Obviously this is a very simple example, but I can see the second one being 'cleaner' and easier to understand, as only 1 parameter changes when recursing, compared to my two.


looks like the first is tail recursive while the second one isn't.


Does The Little Schemer talk about TCO? I don't remember right now.
Anyway, yours is actually much preferrable over the second one. Consider the expansion:
  ; Little Schemer version
(o+ 2 5)
(add1 (o+ 2 4))
(add1 (add1 (o+ 2 3)))
(add1 (add1 (add1 (o+ 2 2))))
(add1 (add1 (add1 (add1 (o+ 2 1)))))
(add1 (add1 (add1 (add1 (add1 (o+ 2 0))))))
(add1 (add1 (add1 (add1 (add1 2)))))

; Anon version
(PLUS 2 5)
(PLUS 3 2)
(PLUS 4 3)
(PLUS 5 2)
(PLUS 6 1)
(PLUS 7 0)
Scheme requires proper tail calls, which is an optimization that kicks in when you're calling a function and the continuation is empty, i.e. you're calling another function as the last thing in that function.
In the TLS version, when the function calls itself it still has to run "add1" on the result, so the call stack increases and could potentially cause a stack overflow.
In your version, the last thing the function has to do is to call itself, so the compiler sees that it has no continuation and doesn't increase the call stack.
Anyway, TLS covers continuations later, so don't worry if you don't get it right now.



Thanks, that makes a lot of sense.


Just use Racket Lisp then. It supports Windows out of the box. I don't think there's any serious intention to get Guile running or compiling on Windows any time soon. Racket can be used as a scripting language in a larger project since it can be embedded into C or C++.


I'm currently working through The Little Schemer (note: I'm not >>22586) and I've been having a very rough time with Chapter 8: Lambda the Ultimate. I've read some stuff on Stack Overflow but it's not quite sinking in—seems like something has yet to "click." How long did it take you guys to wrap your heads around continuations? Am I just dense? And does anyone perhaps have any useful resources for this?


I understood continuations only when described at the machine level, as preserving the stack and other local state to be reinstated, while leaving the other memory, the heap, alone.


Thanks, I'll spend some time digging into this stuff and see if it helps. I know next to nothing about machine-level computing yet.


It can be very confusing first, I remember struggling with it and seen others do the same. What really helped me was this video, a really nice explanation imho:


It took me forever to get continuations. Granted, I dropped the book for a long while and did very little programming in the intervening period, but it really took me a long time. I think I posted a similar question on here and got this video >>22716 back. (It didn't help me at all.)
It's actually quite simple for the way they're used in TLS, if you've ever used Javascript you'll most likely have experience with callbacks, which are one form of continuation.


Lisp Machine Flavors for LFE implementing objects on Erlang OTP


Thank you very much for the link! It's so much easier to absorb this stuff lecture-style than via text.
Glad I'm not the only one struggling with this stuff. My only previous programming experience was with Supercollider, and I didn't get very far. Callbacks, continuation, recursion, it's all new to me.


What are the options for low level Lisps (mainly Scheme)?


This video totally perplexed me. I had to stop some areas and replay them 5-6 times. I left thinking I was even more confused than I started out. And then I went back to The Little Schemer and completed a continuation example with (relative) ease. I guess it has finally clicked! Thanks again for the resource, lainon.


The Scheme standard does not describe a language that can be low level in the way that C is. For example, the numeric tower would be very difficult to implement in such a way that is "close to the metal", as it were. However, most Scheme implementations have mechanisms for interacting with low level stuff that's sufficient for most uses. I suggest Chicken, but I know Racket has a very good FFI for C.


Common Lisp was designed as a "systems language" and lets you inspect the assembly and tweak the compiler settings in any place you want.


Is there any practical difference between this (the textbook answer)

  ((lambda (mk-length)
(mk-length eternity))
(lambda (length)
((null? l) 0)
(else (add1 (length (cdr l)))))))

and this (the one that seems more immediate to me)?

  ((lambda (mk-length))
((lambda (length)
((null? l) 0)
(else (add1 (length (cdr l))))))

The (lambda (mk-length) (mk-length eternity)) bit in the first chunk throws me off with its doubling-down on the anonymous function.


These were both incorrect, sorry. Corrected:

  ((lambda (mk-length)
(mk-length eternity))
(lambda (length)
(lambda (l)
((null? l) 0)
(else (add1 (length (cdr l))))))))

((lambda (mk-length)
((lambda (length)
(lambda (l)
((null? l) 0)
(else (add1 (length (cdr l)))))))


At sometime you need to self-apply (e.g. (lambda (x) (x x)) ) in order to generate recursion, there's no way to generate recursion without it.
In your last example you have unbalanced parenthesis so I'm really not sure what you mean.


The self-application thing does make sense, thank you! I'm still very slowly pulling all these concepts together--sorry if my questions seem silly.
>unbalanced parenthesis
My bad, I'll double-check for errors in the future.


If you ever wanted to see any simpler examples of programs for Lisp machines, this is a good collection: http://www.cs.cmu.edu/afs/cs/project/ai-repository/ai/lang/lisp/code/impdep/explorer/jwz.tgz