Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

how does recursion work?

37 views
Skip to first unread message

Cadwallader

unread,
Oct 15, 2000, 3:00:00 AM10/15/00
to
i am currently learning lisp (from LISP 3rd ed. Patrick Henry Winston) and i
just got to the part on recursion. for example, to make a function that
calculates an exponent you can multiply m (m^n-1). they have an example code
using recursion for this:

(defun recur-expt (m n)
(if (zerop n)
1
( * m (recur-expt m (- n 1)))))

now how does interpreter program execute this? wouldnt it have to get caught
in an infinite loop to execute it? to define recur-expt you need the
definition for recure-expt, to define that recure-expt you need the
defintion for recure-expt etc. so could somebody explain how this works?
thank you.

Mario Lang

unread,
Oct 15, 2000, 3:00:00 AM10/15/00
to
"Cadwallader" <ccad...@tampabay.rr.com> writes:

> just got to the part on recursion. for example, to make a function that
> calculates an exponent you can multiply m (m^n-1). they have an example code
> using recursion for this:
>
> (defun recur-expt (m n)
> (if (zerop n)
> 1
> ( * m (recur-expt m (- n 1)))))
>
> now how does interpreter program execute this? wouldnt it have to get caught
> in an infinite loop to execute it?

No. The if clause prevents this.

> to define recur-expt you need the
> definition for recure-expt, to define that recure-expt you need the
> defintion for recure-expt etc. so could somebody explain how this works?

I am fairly new to lisp too, but I try to through in mz 2-cents. Of course, anybody
please correct me if am getting it wrong:
The interpreter doesn't need the definition of recur-expt when it finds a
function-call to it in a defun. defun defines a function, but
doesnt execute it. The definition of recur-expt is only needed when there is a real
function-call to it (while executing some code). So, when you call
your function, it is already defined, and the interpeter can use it.

Example. If you defun something, you can put in nearly every kind of code, the
errors while only arrise when you call it.

> thank you.
>
>

--
CYa,
Mario <ml...@delysid.org>
Homepage(s): http://delysid.org | http://piss.at/

How many chunks could checkchunk check if checkchunk could check chunks?
-- Alan Cox

Weiqi Gao

unread,
Oct 15, 2000, 3:00:00 AM10/15/00
to
Cadwallader wrote:
>
> i am currently learning lisp (from LISP 3rd ed. Patrick Henry Winston) and i
> just got to the part on recursion. for example, to make a function that
> calculates an exponent you can multiply m (m^n-1). they have an example code
> using recursion for this:
>
> (defun recur-expt (m n)
> (if (zerop n)
> 1
> ( * m (recur-expt m (- n 1)))))
>
> now how does interpreter program execute this? wouldnt it have to get caught
> in an infinite loop to execute it? to define recur-expt you need the

> definition for recure-expt, to define that recure-expt you need the
> defintion for recure-expt etc. so could somebody explain how this works?
> thank you.

The four lines of code above defined 'recur-expt' completely. So your
assertion that "to define recur-expt you need the definition for
recure-expt" is incorrect. It would be correct to say " to execute
recur-expt you need the definition of recur-expt," but that poses no
problem at all, since by the time you are executing 'recur-expt', it has
alreasy been defined.

Xenophon Fenderson the Carbon(d)ated

unread,
Oct 15, 2000, 3:00:00 AM10/15/00
to
>>>>> "Cad" == Cadwallader <ccad...@tampabay.rr.com> writes:

Cad> (defun recur-expt (m n)
Cad> (if (zerop n)
Cad> 1
Cad> (* m (recur-expt m (- n 1)))))

Cad> now how does interpreter program execute this? wouldnt it
Cad> have to get caught in an infinite loop to execute it?

This is a perfectly reasonable question to ask.

For more detail, you should consult a book on language implementation.
There are several good books. I personally own copies of _The
Essentials of Programming Languages_ by Daniel P. Friedman, Mitchel
Wand, and Christopher T. Haynes; _LISP in Small Pieces_ by Christian
Queinnec; and _Modern Compiler Implementation_ by Andrew W. Appel.
The canonical language implementation book is _Structure and
Interpretation of Computer Programs_ by Sussman et al, and the
canonical compilers text is the Dragon Book (dunno what the actual
title is) by Aho, Sethi, and Ulman. I haven't read the last two in
this list, but I've read through the first three and they are
excellent texts. Appel actually has three different versions of his
book, one each for Standard ML, C, and Java. I own the Java version,
and I'm considering buying the ML version as well.

Basically, as far as the translator is concerned (it's much the same
for compilers as for interpreters), it sees your function as follows:

(FUNCTION-OF-N-ARGUMENTS
:arg-names-list ("M" "N")
:body ((IF-FORM
:test (FUNCTION-CALL
:func-name "ZEROP"
:arg-list ((VARIABLE-REFERENCE :symbol-name "M")))
:then-clause (INTEGER-LITERAL :value 1)
:else-clause (FUNCTION-CALL
:func-name "*"
:arg-list ((VARIABLE-REFERENCE :symbol-name "M")
(FUNCTION-CALL
:func-name "RECUR-EXPT"
:arg-list ((VARIABLE-REFERENCE :symbol-name "M")
(FUNCTION-CALL
:func-name "-"
:arg-list ((VARIABLE-REFERENCE :symbol-name "N")
(INTEGER-LITERAL :value 1))))))))))

This is called an "abstract syntax tree" and in mentioned in greater
detail in the texts to which I refer you. You should read this as
each node in the tree being a structure of the named type, and each
bit with ":name" being a field in the structure with the following as
its value. My apologies if the representation I chose is confusing.

As you can see, the recursive call to RECUR-EXPT on line 4 of your
function is treated by the translator as just another function call,
not as some kind of macro expansion in which the text "(recur-expt m
(- n 1))" needs to be replaced with the body of the RECUR-EXPT
function.

HOWEVER, when one is writing a macro, then yes, one must make certain
that the macro expansion process does terminate (and Very Bad Things
happen when it doesn't). For example, let's re-write RECUR-EXPT as a
macro which expands (RECUR-EXPT M N) into the appropriate number of
calls to *:

(defmacro recur-expt-inline (m n)
(if (zerop n)
1
`(* ,m (recur-expt-inline ,m ,(- n 1)))))

Here, the macro is in control. Note that "(- n 1)" is evaluated at
macro-expansion time, when previously it was evaluated at run time.
Note also that the translator will expand all macros until there are
no more macros, so:

(recur-expt-inline 3 2)

will expand (at translation time) in to:

(* 3 (recur-expt-inline 3 1))

then:

(* 3 (* 3 (recur-expt-inline 3 0)))

and finally:

(* 3 (* 3 1))

This last form is what is transformed into an abstract synax tree, and
the macro itself is of no further importance.

Hopefully this makes sense. Abstract syntax trees are covered in much
greater detail in the books to which I referred you. Macros are
covered in much greater detail in _On Lisp_ by Paul Graham (another
excellent book that I own).

Kind regards,
#\X

--
UN-altered reproduction and DISSEMINATION of this IMPORTANT information is
ENCOURAGED

vsync

unread,
Oct 15, 2000, 3:00:00 AM10/15/00
to
Kenny Tilton <kti...@nyc.rr.com> writes:

> BTW, lots of compiled languages do not care if a function exists
> when a call to one gets compiled, but they yell if by the time of a
> second "link" step all such names have not been bound. I myself do
> not know of any which like Lisp allow the function to be bound to
> the symbol at runtime.

Java is another language with late binding.

--
vsync
http://quadium.net/ - last updated Sat Oct 7 18:53:10 PDT 2000
(cons (cons (car (cons 'c 'r)) (cdr (cons 'a 'o))) ; Orjner
(cons (cons (car (cons 'n 'c)) (cdr (cons nil 's))) nil))

Erik Naggum

unread,
Oct 15, 2000, 8:25:01 PM10/15/00
to
* Xenophon Fenderson the Carbon(d)ated

| Basically, as far as the translator is concerned (it's much the same
| for compilers as for interpreters), it sees your function as follows:
|
| (FUNCTION-OF-N-ARGUMENTS
| :arg-names-list ("M" "N")
| :body ((IF-FORM
| :test (FUNCTION-CALL
| :func-name "ZEROP"
| :arg-list ((VARIABLE-REFERENCE :symbol-name "M")))
| :then-clause (INTEGER-LITERAL :value 1)
| :else-clause (FUNCTION-CALL
| :func-name "*"
| :arg-list ((VARIABLE-REFERENCE :symbol-name "M")
| (FUNCTION-CALL
| :func-name "RECUR-EXPT"
| :arg-list ((VARIABLE-REFERENCE :symbol-name "M")
| (FUNCTION-CALL
| :func-name "-"
| :arg-list ((VARIABLE-REFERENCE :symbol-name "N")
| (INTEGER-LITERAL :value 1))))))))))
|
| This is called an "abstract syntax tree" and in mentioned in greater
| detail in the texts to which I refer you.

Which (Common) Lisp implementation did you dig this stuff out of?

If you made it up on the spot, and it looks like you did because you
missed the fundamental idea in (Common) Lisp that symbols are not
named in some silly "abstract syntax trees" by their _string_ names,
would you apologize to the poor sap you lied to and retract it all?

#:Erik
--
I agree with everything you say, but I would
attack to death your right to say it.
-- Tom Stoppard

Erik Naggum

unread,
Oct 15, 2000, 8:18:03 PM10/15/00
to
* "Cadwallader" <ccad...@tampabay.rr.com>

| now how does interpreter program execute this?

A recursive function call is just a function call.

| wouldnt it have to get caught in an infinite loop to execute it? to


| define recur-expt you need the definition for recure-expt, to define
| that recure-expt you need the defintion for recure-expt etc.

You're actually asking about the way Lisp code is represented in
memory more than how the interpreter (or even compiled code)
executes the code. The function call (recur-expt m (- n 1)) is
represented as a list with three elements: the symbol recur-expt,
the symbol m, and the list of three elements: the symbol -, the
symbol n, and the integer 1. But how did we get to the symbols?

When you type in expression to the Lisp, they function read is
called upon to turn your textual representation into an in-memory
structure that consists mostly of pointers to objects. One of
Lisp's great and lasting ideas is that of having an external format
for its internal memory structures and having reader and writer
functions that convert between the two.

I'm sure you know how lists are represented in memory, so let's
consider how symbols are read and represented. First, the reader
collects all the characters that make up the name of the symbol.
Then it looks up the symbol in the package (a named symbol table),
or creates it there if it didn't already exist, and returns a
pointer to the (new) symbol. This pointer is stuffed in the list.

The symbol itself has pointers to quite a number of things, among
them the variable value and the functional value. When you define a
function, you set the functional value slot of the symbol structure,
but the neat thing is that the pointer to the symbol remains the
same. The symbol also prints the same as before: with its name.

Through this indirection at two different times, we avoid the whole
issue of referring directly to the function. The Lisp reader makes
the list element refer to the symbol and when the interpreter needs
to call the function, it looks up the functional value slot of the
symbol and calls that value.

It's all exceptionally elegant and simple, and doesn't need any of
the abstract syntax tree nonsense needed in other languages that
haven't figured out that it's pretty damn smart to represent your
code as a data structure from the get-go (I hope you ignored that
elaborate explanation because it made no sense in a Lisp context).

Kenny Tilton

unread,
Oct 15, 2000, 9:32:29 PM10/15/00
to
I think your point of confusuion is here:

> to define recur-expt you need the
> definition for recure-expt,
>

In brief, no you don't. :) Try this;

(defun a () (b))

Your interpreter may give you a warning, or it may not. ACL does not, because
all that happens at this point is that a note is made to call something called
'b at runtime. So with (defun a () (a)) (do not try that) by the same token the
compiler just makes a note to call /something called 'a'/ when it gets to it at
runtime.

Now try:

(a)

Now it is run time and your intrepeter actually tries to find B, you should get
an error that function B does not exist. Had 'a been calling 'a, of course it
would have found 'a and gone into a very tight loop. :)

now:

(defun b () (print "hello world"))

and try again;

(a) and you should see that all is well.The function is found at runtime.

Almost as an aside, some Lisps compile the whole thing then execute that. When
the compiler gets to the recursive call to 'recur-expt, it does not panic
because it already sees 'recur-expt is getting a definition (the function
property of the symbol 'recur-expt is getting a value) and it inserts an
instruction to call that symbol's function. It does not matter that that
function is still being compiled, all it needs do then is to insert the
instruction to call the function bound to the symbol 'recur-expt. I use ACL and
that squawks if a called function does not exist when I compile, but not in the
interpreter...but MCL compiles things entered in the Listener, so I wager it
might squawk in the interpreter as well.

And if you are talking about an interpreter, hey, you can play the part of the
interpreter by hand executing the code. What do /you/ do when you encounter the
recursive call as you read the code? You go back to the beginning of the
function and start a second trip thru with the new arguments...and now your only
problem is making sure you have arranged things so that some trip thru does not
lead to the invocation of 'recur-expt.

BTW, lots of compiled languages do not care if a function exists when a call to
one gets compiled, but they yell if by the time of a second "link" step all such
names have not been bound. I myself do not know of any which like Lisp allow the
function to be bound to the symbol at runtime.

kenny

> i am currently learning lisp (from LISP 3rd ed. Patrick Henry Winston) and i
> just got to the part on recursion. for example, to make a function that
> calculates an exponent you can multiply m (m^n-1). they have an example code
> using recursion for this:
>

> (defun recur-expt (m n)
> (if (zerop n)
> 1
> ( * m (recur-expt m (- n 1)))))
>
> now how does interpreter program execute this? wouldnt it have to get caught


> in an infinite loop to execute it? to define recur-expt you need the
> definition for recure-expt, to define that recure-expt you need the

George Acton

unread,
Oct 15, 2000, 9:47:44 PM10/15/00
to
Cadwallader wrote:
>
> i am currently learning lisp (from LISP 3rd ed. Patrick Henry Winston) and i
> just got to the part on recursion. for example, to make a function that
> calculates an exponent you can multiply m (m^n-1). they have an example code
> using recursion for this:
>
> (defun recur-expt (m n)
> (if (zerop n)
> 1
> ( * m (recur-expt m (- n 1)))))
>
> now how does interpreter program execute this? wouldnt it have to get caught
> in an infinite loop to execute it? to define recur-expt you need the
> definition for recure-expt, to define that recure-expt you need the
> defintion for recure-expt etc. so could somebody explain how this works?
> thank you.

I'm totally an amateur at this, and have never had a computer course,
but I did once write my own interpreter for LISP in BASIC on a machine
with something like 16K of memory.
What happens is that there's an area of memory organized as
as "stack". The interpreter churns through the code and when it
has to execute something like (+ a b), it pushes the "+" on the stack,
evaluates a, pushes the result on the stack, evaluates b, pushes it.
Then it goes down the stack looking for an operation, finds the
"+", pops the top arguments and applies the "+" function to get
the result. You can think of the stack as a way of organizing
intermediate results of a calculation in a consistent way.
Another way is to think of it as a reminder list that the
interpreter writes for itself about what to do next.
It turns out that the same idea works for a recursive function
as for a non-recursive one one like "+". The interpreter
calls recur-exp just like it did for "+". Since the "defun" has
been executed previously, the code for "recur-exp" is sitting around
in memory somewhere. With each call, it remembers that after
returning it has to multiply the result by "m". After a finite number
of recursions, the argument n is zero, the function returns 1 and the
interpreter unwinds the stack. So for evaluationg it with m=10,
the interpreter executes 20 or 30 pushes and pops of the stack in
the background.
Of course the interpreter can't make good on the implied
promise of infinite recursion. If you change the "-" sign to
a "+" in the definition, it will create a function that
will create an infinite number of items on the stack. With
a simple-minded interpreter and no protection from the
operating system, something will blow up. On a free LISP
interpreter (XLISP) I get a polite "error: argument stack
overflow".
I hope this has been helpful to you. It has been fun
recalling the little Eliza Doolittle moments when I figured some
of these things out.

Christopher Browne

unread,
Oct 15, 2000, 10:36:25 PM10/15/00
to
In our last episode (Sun, 15 Oct 2000 18:59:30 GMT),

the artist formerly known as Cadwallader said:
>i am currently learning lisp (from LISP 3rd ed. Patrick Henry Winston) and i
>just got to the part on recursion. for example, to make a function that
>calculates an exponent you can multiply m (m^n-1). they have an example code
>using recursion for this:
>
>(defun recur-expt (m n)
> (if (zerop n)
> 1
> ( * m (recur-expt m (- n 1)))))
>
>now how does interpreter program execute this? wouldnt it have to get caught
>in an infinite loop to execute it? to define recur-expt you need the
>definition for recure-expt, to define that recure-expt you need the
>defintion for recure-expt etc. so could somebody explain how this works?
>thank you.

Certainly there's some _risk_ of an infinite loop, supposing the recursion
function does not somehow succeed at "simplifying/reducing" the state.

For instance:
(defun recur-oops (m n)
(* m (recur-oops m (- n 1)))
... will never terminate, as it doesn't have any clause that
_doesn't_ recurse.

On the other hand, the concern you seem to be having is of whether
the recursive function can refer to its own name. Which is, frankly,
not an issue at all.

Different compiler environments may evaluate function references a little
differently, perhaps proposing inlining, if that improve performance.

But unlike languages like Pascal, Forth, and C, where there is some need to
pre-declare variables/functions before referring to them, or some pretty
special protocols to work around this need, it is perfectly acceptable
for a function to refer to a function that has not yet been defined.

It matters not in what order I define:
(defun addnmul (a b)
(* (add2 a b) (add2 a 3)))
(defun add2 (a b)
(+ a b 3))
addnmul refers to add2, but I can define add2 later if I so desire.

And your "recur-expt" can have a reference to recur-expt inside it
before the function has been fully defined. You won't want to _evaluate_
"recur-expt" before it has been fully defined, but that should not be
much of an issue; you can hardly evaluate the function before you have
finished defining it...

In effect, the function "name space" is dynamic; you can create a reference
to a function name that does not yet exist. Of course, if you try to
evaluate that unresolvable reference, you'll raise an error...
--
aa...@freenet.carleton.ca - <http://www.hex.net/~cbbrowne/lsf.html>
Nobody can fix the economy. Nobody can be trusted with their finger
on the button. Nobody's perfect. VOTE FOR NOBODY.

Erik Naggum

unread,
Oct 15, 2000, 10:51:09 PM10/15/00
to
* Kenny Tilton <kti...@nyc.rr.com>

| ACL does not, because all that happens at this point is that a note
| is made to call something called 'b at runtime.

'b as read as (quote b)? Whatever does _quote_ do in this context?

I'll (reluctantly :) have to side with Barry Margolin on this one:
People who think that it makes sense to write #'do and the like in
text in order to half-pretend to be writing code in Lisp do more
harm than good, and just as #'do doesn't even work, nobody calls 'b
as a function. This is actually a case where the call is #'b, but
in the interest of sanity, just keep it simple: It calls b.

Dave Pearson

unread,
Oct 16, 2000, 3:00:00 AM10/16/00
to
On 16 Oct 2000 02:51:09 +0000, Erik Naggum <er...@naggum.net> wrote:

> I'll (reluctantly :) have to side with Barry Margolin on this one:
> People who think that it makes sense to write #'do and the like in text
> in order to half-pretend to be writing code in Lisp do more harm than
> good, and just as #'do doesn't even work, nobody calls 'b as a function.
> This is actually a case where the call is #'b, but in the interest of
> sanity, just keep it simple: It calls b.

Would you mind expanding on this (or perhaps providing a pointer to where
Barry wrote about this)? The reason I ask is that I am in the habit of
writing #'foo when I'm talking about a function (in an effort to point out
that I'm talking about a function) and I'd be interested to see how I'm
doing more harm than good.

--
Take a look in Hagbard's World: | lbdb.el - LBDB interface.
http://www.hagbard.demon.co.uk/ | sawfish.el - Sawfish mode.
http://www.acemake.com/hagbard/ | uptimes.el - Record emacs uptimes.
emacs software, including.......| quickurl.el - Recall lists of URLs.

Xenophon Fenderson the Carbon(d)ated

unread,
Oct 16, 2000, 3:00:00 AM10/16/00
to
[Please note Followup-To.]

>>>>> "Erik" == Erik Naggum <er...@naggum.net> writes:

Erik> Which (Common) Lisp implementation did you dig this stuff
Erik> out of?

A Lisp implementation adapted from _The Essentials of Programming
Languages_ by Friedman et al. While the language described in the
book looks more Algoly than Lispy, my instructor for the course had us
instead write a Scheme interpreter in Scheme to avoid a discussion of
parsing. We used an abstract syntax tree (with various record types
representing various primitive and non-primitive operations) to drive
the interpreter, which seems to be a sensible design decision
(vis. abstraction). In a later course on compiler construction, we
revisited the topic and used the abstract syntax tree to drive the
semantic analysis, optimization, and code generation phases of a
simple compiler.

Erik> If you made it up on the spot, and it looks like you did
Erik> because you missed the fundamental idea in (Common) Lisp
Erik> that symbols are not named in some silly "abstract syntax
Erik> trees" by their _string_ names, would you apologize to the
Erik> poor sap you lied to and retract it all?

The individual's question was "how does recursion work?" with Lisp as
the context, not "how could a Common Lisp implementation represent
programs internally?". Hopefully, the answer I gave (along with
showing him abstract syntax trees) was general enough to get this
individual interested in language implementation in general, which is
why I went through the trouble of tracking down the references I did.

So certainly, symbols in Common Lisp have not only a name (i.e. a
string, usually converted internally to upper-case), but a package
name and several other structure members that, along with the list
structure syntax, make writing translators for Common Lisp much easier
than in other languages. I apologize to the readership for willfully
misleading them and recommend they add me to their filters
immediately.

If you would, Mr. Naggum, please referencer me to the relevant
literature that discusses modern alternatives to abstract syntax trees
in interpreter and, especially, compiler construction.

Boris Schaefer

unread,
Oct 16, 2000, 3:00:00 AM10/16/00
to
davep...@davep.org (Dave Pearson) writes:

| Would you mind expanding on this (or perhaps providing a pointer to where
| Barry wrote about this)? The reason I ask is that I am in the habit of
| writing #'foo when I'm talking about a function (in an effort to point out
| that I'm talking about a function) and I'd be interested to see how I'm
| doing more harm than good.

Check out this post:

From: Barry Margolin <bar...@genuity.net>
Newsgroups: comp.lang.lisp
Subject: Referring to #'<function> in text (was Re: Distance between two pts)
Message-ID: <%f9w5.12$ge7.918@burlma1-snr2>

--
bo...@uncommon-sense.net - <http://www.uncommon-sense.net/>

Strategy:
A long-range plan whose merit cannot be evaluated until sometime
after those creating it have left the organization.

Kenny Tilton

unread,
Oct 16, 2000, 3:00:00 AM10/16/00
to
Jee, my NG does not show the original post, so I'll just respond to the ether in
general....

Actually, until recently I would have written #'b, but I have always hated the
shift key and have carpal tunnel syndrome, so now I just toss in a leading tick
to make sure the referent stands out, seems more readable to me. As for sanity,
boy, I gave up on that a while ago, feels terrific. (paraphrasing New Yorker
cartoon)

Not sure how #'b is half-pretending anything, it seems to me quite precise to
talk about calling a symbol's function--perhaps it is the assumption of
Lisp-fluency that is objectionable?

Anyway, I consider my new octothorpe-free convention to be sloppy and am
grateful that the text is being read by true natural language machines--they are
so forgiving.

kenny

Kenny Tilton

unread,
Oct 17, 2000, 3:00:00 AM10/17/00
to

Erik Naggum wrote:
>
> * Kenny Tilton <kti...@nyc.rr.com>
> | ACL does not, because all that happens at this point is that a note
> | is made to call something called 'b at runtime.
>
> 'b as read as (quote b)? Whatever does _quote_ do in this context?
>

No, not (quote b). This is in the British (perhaps Pythonesque) sense of
"with antlers" or "without antlers", and here purely out of laziness I
went with a one-antlered b to contrast it with b, which I am assuming is
a special.

BTW, to avoid confusion, the above reference is to Python, not "Python".

kenny

Kenny Tilton

unread,
Oct 17, 2000, 3:00:00 AM10/17/00
to
Erik Naggum wrote:
> would you apologize to the poor sap you lied to and retract it all?

where do you get off calling someone a liar because you disagree on the
expansion of a function? and you pretend to be keeping this NG free of
undesirables? not.

Erik Naggum

unread,
Oct 17, 2000, 3:00:00 AM10/17/00
to
* Kenny Tilton <kti...@nyc.rr.com>

| Not sure how #'b is half-pretending anything, it seems to me quite
| precise to talk about calling a symbol's function--perhaps it is the
| assumption of Lisp-fluency that is objectionable?

You failed to recognize #'do as the example for what it is.
That's pretty good for someone aspiring to sloppy. Keep it up!

| Anyway, I consider my new octothorpe-free convention to be sloppy
| and am grateful that the text is being read by true natural language
| machines--they are so forgiving.

Perhaps you should be a politician? You both lie like one and have
figured out how to write nice words while being hostile. I'm sure
almost nobody could see that you're seething, and they might even
vote for you if you promised them something you couldn't deliver.

The solution to the shift-key problem is to use a computer that has
a programmable keyboard so one can no longer blame it for the ills
of having to type. The X Windows System has xmodmap, I'm sure the
great _innovators_ in Redmond, WA, have managed to invent something
about 10% as smart after the decade we have had X. Then there's
Emacs (and some other programmable editors) that can do most of the
work for you, and you can even teach Emacs or X not to require the
normally intrusive modifier keys as simultaneous keypresses. The
key to carpal tunnel syndrome or repetitive strain disorder (which
is not actually caused by repetitive strain and is a problem whose
occurrence pattern in groups and areas has no medical explanation,
but is related to insurance companies' willingness to entertain the
victims and the media coverage of the "problems" of new technology,
just like we have had similar ailments and problems with every new
technology, but the victims are no doubt in real pain and do suffer)
is to get a more relaxed attitude to the movements required by the
body in doing the work you want to do, not to regard the movements
as a hindrance and annoyance. Most patients need medication and a
sympathetic group of friends or co-sufferers to acquire this relaxed
attitude.

Regardless of CTS or RSD, having to use the shift key to reach the
parens and colon in particular are annoying to Common Lisp users.
Just swap : and ;, and move () to were [] are, shift [], and move {}
to where () were. Since Common Lisp has almost no use for =,
swapping = and + helps, too. Additionaly, swapping ~ and ` might
help unless you're writing more macros than format control strings,
and so on. If your function keys are reasonably close to the top
row of the keyboard proper (like Sun Type 4 keyboards), make them
the shifted versions of the digit keys or something.

There's just no need to play victim in pain and explain that one
does stupid things to other people with reference to a medically
bogus syndrome or disorder. Just do the right thing, and let the
computer help you in that most worthwhile of endeavors, don't fight
it as if _it_ had caused the problems.

Just another helpful, constructive suggestion that is no dobut going
to be read as hostile because the intended reader doesn't know how
to read something for what it is and misplaces his irritation to
begin with by effectively blaming # for his pain. Just get over it.

#:Erik, not quite the forgiving kind of guy

Erik Naggum

unread,
Oct 17, 2000, 3:00:00 AM10/17/00
to
* Kenny Tilton <ti...@liii.com>

| where do you get off calling someone a liar because you disagree on the
| expansion of a function? and you pretend to be keeping this NG free of
| undesirables? not.

Since you know about this, where do _you_ get off deciding that it
was simple _disagreement_ that caused me (conditionally, which you
also ignored in your typical zest to blame me for something I don't
do) to "call him a liar"? And has it occurred to you that someone
is not a _liar_ simply because one has told a lie? I don't describe
people, Kenny, I describe actions. You describe people, not actions.
There's a word for your behavior: Undesirable. If you are intent
upon continuing regardless of feedback and suggestions and hints,
_you_ may become undesirable, too, but it will probably take a long
time before you figure out the crucial difference between the
adjective and the noun "undesirable" the way you're heading, and I
very much doubt that I can say anything that will cause you to think
about anything at all, anymore, because you prioritize people before
truth, and for people who do that, there's only one chance: they
have to rearrange their priorities before there is any hope at all.

By the way, what _is_ all this to you? Why is it so important to
make an asshole of yourself by constantly proving that you judge and
comment on people when you should judge and comment on their actions?
What's the point to all this, Kenny? Do you think it's _right_ to
judge people and not actions, perhaps? That's so under-evolved and
so disturbingly brutal an attitude to justice that I wonder if you
would survive if anyone treated you like that. Quit while you're
alive and don't promulgate the idea that people aren't in control of
their behavior, but must be branded and punished simply for being.
It took mankind billions of unfairly lost lives to pay for the
wisdom of the modern justice systems, yet we still have serious
problems actually getting the message through to the population,
especially with false group accusations like racism and the like,
but if there is any hope for those living today, it is at least in
the knowledge that the legal system isn't ruled by brutal mobs who
lynch and kill people they don't like, regardless of what they did.

The mark of your evolution into a human being will be that you can
listen to the experience of and the truth explained by someone you
don't happen to like personally. You are not fully a human being if
you disregard the truth if you believe that those who tell it are
somehow incapable of truth and the same experiences that apply to
you: That way lies the idea of sub-humans and group discrimination.
Just exercise the intelligence you have and work hard at it if it
doesn't come quickly to you, and you will grasp the idea that truth
is independent of people, but has to be discovered by, propagated
by, and held by people to work. Otherwise, untruth wins by default.

If I can keep your intellectually under-nourished attitudes at bay,
Kenny, I can indeed pretend to keep this NG free of the undesirable
that you (and some others) bring with them here. But it's not why
I'm here, just like I'm interested in this aspect of society because
I have to live in one with people who similarly destructive as you,
not because I want to spend any time on it. Ideally, people would
have parents and teachers who told them about justice and dispelled
the notions that people _are_ bad because they _do_ bad. Some
people _do_ bad because they _are_ bad, but some good people do bad,
too, and the unfairness of treating them as bad people is the best
way to turn good people into bad people. In fact, that's how the
vast majority of bad people were created. It is in all our personal
interests to see to it that we create as few bad people as possible
and that we identify the few really bad people that are out there.

Dave Pearson

unread,
Oct 17, 2000, 3:00:00 AM10/17/00
to
On 16 Oct 2000 21:24:42 +0200, Boris Schaefer <bo...@uncommon-sense.net> wrote:
> davep...@davep.org (Dave Pearson) writes:
>
> | Would you mind expanding on this (or perhaps providing a pointer to where
> | Barry wrote about this)? The reason I ask is that I am in the habit of
> | writing #'foo when I'm talking about a function (in an effort to point out
> | that I'm talking about a function) and I'd be interested to see how I'm
> | doing more harm than good.
>
> Check out this post:
>
> From: Barry Margolin <bar...@genuity.net>
> Newsgroups: comp.lang.lisp
> Subject: Referring to #'<function> in text (was Re: Distance between two pts)
> Message-ID: <%f9w5.12$ge7.918@burlma1-snr2>

Thanks for that, Deja still had itน. I can fully see Barry's point and one
thing I've always been careful of is function-quoting something that isn't a
function. IOW I've always been careful not to place #' before the name of a
macro.

I guess the point here is that #' is a desire to say "this is something you
call" but that you can't always use it to mark something that you call. So,
why bother, what not say "call <foo>" in the code?

-----
น <URL:http://www.deja.com/getdoc.xp?AN=669744100&fmt=text>

thi

unread,
Oct 17, 2000, 3:00:00 AM10/17/00
to
Erik Naggum <er...@naggum.net> writes:

> Regardless of CTS or RSD, having to use the shift key to reach the
> parens and colon in particular are annoying to Common Lisp users.
> Just swap : and ;, and move () to were [] are, shift [], and move {}
> to where () were. Since Common Lisp has almost no use for =,
> swapping = and + helps, too. Additionaly, swapping ~ and ` might
> help unless you're writing more macros than format control strings,
> and so on. If your function keys are reasonably close to the top
> row of the keyboard proper (like Sun Type 4 keyboards), make them
> the shifted versions of the digit keys or something.

please see below for some elisp that rebinds [] to ().
i use it a lot. i'm sure it could be extended or that there are
more general packages...

thi


__________________________________________________
RCS/square-braces-as-parens.el,v --> standard output
revision 1.5
;;; ID: square-braces-as-parens.el,v 1.5 2000/10/13 20:36:58 ttn Rel
;;;
;;; Copyright (C) 2000 Thien-Thi Nguyen
;;; This file is part of ttn's personal elisp library, released under GNU
;;; GPL with ABSOLUTELY NO WARRANTY. See the file COPYING for details.

;;; Description: Minor mode to bind parens to square-braces keys.

;;;###autoload
(defvar square-braces-as-parens-mode nil
"If non-nil, \"[\" and \"]\" insert \"(\" and \")\", respectively.")

(defun square-braces-as-parens-insert (n yes no)
(while (< 0 n)
(insert (if square-braces-as-parens-mode yes no))
(setq n (1- n))))

;;;###autoload
(defun square-braces-as-parens-mode (&optional arg)
(interactive "P")
(setq square-braces-as-parens-mode
(if (null arg)
(not square-braces-as-parens-mode)
(> (prefix-numeric-value arg) 0)))
(local-set-key "[" #'(lambda (n)
(interactive "p")
(square-braces-as-parens-insert n "(" "[")))
(local-set-key "]" #'(lambda (n)
(interactive "p")
(square-braces-as-parens-insert n ")" "]")))
(unless noninteractive
(message "Square braces as parens mode: %s"
(if square-braces-as-parens-mode "on" "off"))))

;; load time action
(make-variable-buffer-local 'square-braces-as-parens-mode)
(put 'square-braces-as-parens-mode 'permanent-local t)

;; that's it
(provide 'square-braces-as-parens)

;;; square-braces-as-parens.el,v1.5 ends here

Rainer Joswig

unread,
Oct 17, 2000, 9:45:55 PM10/17/00
to
In article <y16og0j...@glug.org>, thi <t...@glug.org> wrote:

> Erik Naggum <er...@naggum.net> writes:
>
> > Regardless of CTS or RSD, having to use the shift key to reach the
> > parens and colon in particular are annoying to Common Lisp users.
> > Just swap : and ;, and move () to were [] are, shift [], and move {}
> > to where () were. Since Common Lisp has almost no use for =,
> > swapping = and + helps, too. Additionaly, swapping ~ and ` might
> > help unless you're writing more macros than format control strings,
> > and so on. If your function keys are reasonably close to the top
> > row of the keyboard proper (like Sun Type 4 keyboards), make them
> > the shifted versions of the digit keys or something.
>
> please see below for some elisp that rebinds [] to ().
> i use it a lot. i'm sure it could be extended or that there are
> more general packages...

That's why Symbolics users **love** their keyboard.
It's definitely the best keyboard on the planet. It's heavy (put into
a guillotine you can kill people with it) and has the right
touch. It has those "(", ")", ":", "'", Hyper, Super, etc. keys.
And it has an ADB adapter for older Macs. :-)

See: http://corporate-world.lisp.de/lispm/lispm-keyboard.jpg

--
Rainer Joswig, Hamburg, Germany
Email: mailto:jos...@corporate-world.lisp.de
Web: http://corporate-world.lisp.de/

Patrick A. O'Donnell

unread,
Oct 19, 2000, 3:00:00 AM10/19/00
to
Rainer Joswig <jos...@corporate-world.lisp.de> writes:
> In article <y16og0j...@glug.org>, thi <t...@glug.org> wrote:
> > Erik Naggum <er...@naggum.net> writes:

[... regarding unshifted (. ). :, and others ... ]

>
> That's why Symbolics users **love** their keyboard.
> It's definitely the best keyboard on the planet. It's heavy (put into
> a guillotine you can kill people with it) and has the right
> touch. It has those "(", ")", ":", "'", Hyper, Super, etc. keys.

...

And the "function keys" get larger the further they are from the home
row. You can hit them reliably without looking. I miss those.

- Pat

0 new messages