I'm making another run at learning Lisp. I've implemented rot13 for
strings, but my solution seems more verbose than I expected. Here's my
implementation:
(defun rot13 (string)
(labels ((compute-char (code base-char-code)
(code-char (+ base-char-code
(mod (+ 13 (- code base-char-code)) 26)))))
(let ((lowercase-a (char-code #\a))
(lowercase-z (char-code #\z))
(uppercase-a (char-code #\A))
(uppercase-z (char-code #\Z)))
(with-output-to-string (output-string)
(loop for char across string do
(let ((code (char-code char)))
(cond ((<= lowercase-a code lowercase-z)
(write-char (compute-char code lowercase-a)
output-string))
((<= uppercase-a code uppercase-z)
(write-char (compute-char code uppercase-a)
output-string))
(t (write-char char output-string)))))))))
Is my style just bad (aside from the hardcoded constants that I intend
to remove)? Are there standard functions that I'm not taking advantage
of? Is there a commonly used package for string manipulation? Do most
people develop their own set of macros and functions to simplify string
handling?
Thanks,
Jack
From: Duane Rettig
Subject: Re: Should rot13 be this hard?
Date:
Message-ID: <4ek8jjsgy.fsf@franz.com>
"Jack" <········@gmail.com> writes:
> I'm making another run at learning Lisp. I've implemented rot13 for
> strings, but my solution seems more verbose than I expected. Here's my
> implementation:
>
>
> (defun rot13 (string)
> (labels ((compute-char (code base-char-code)
> (code-char (+ base-char-code
> (mod (+ 13 (- code base-char-code)) 26)))))
> (let ((lowercase-a (char-code #\a))
> (lowercase-z (char-code #\z))
> (uppercase-a (char-code #\A))
> (uppercase-z (char-code #\Z)))
> (with-output-to-string (output-string)
> (loop for char across string do
> (let ((code (char-code char)))
> (cond ((<= lowercase-a code lowercase-z)
> (write-char (compute-char code lowercase-a)
> output-string))
> ((<= uppercase-a code uppercase-z)
> (write-char (compute-char code uppercase-a)
> output-string))
> (t (write-char char output-string)))))))))
>
> Is my style just bad (aside from the hardcoded constants that I intend
> to remove)? Are there standard functions that I'm not taking advantage
> of? Is there a commonly used package for string manipulation? Do most
> people develop their own set of macros and functions to simplify string
> handling?
As you've probably seen by now, there are many ways to write rot13 for
strings, some more efficient than others, and some more elegant than
others.
However, I'd like to expand the sides of the box a little, and ask:
Why do you want to perform rot13 on strings? Where would you get such
a string? What would you do with the result?
If you really think about it, you've already broken your problem down
into sub-problems, and intend to read your string in from a stream
somewhere, and will be writing the result out to another stream (perhaps
even *standard-output* or *terminal-io*). In fact, most applications
for rot13 eventually involve a stream at one end or the other, and thus
it might make sense to treat it as a stream problem.
For a simple-streams answer to this slightly expanded problem description,
see
http://www.franz.com/support/documentation/7.0/doc/streams.htm#encap-example-rot13b-2
--
Duane Rettig ·····@franz.com Franz Inc. http://www.franz.com/
555 12th St., Suite 1450 http://www.555citycenter.com/
Oakland, Ca. 94607 Phone: (510) 452-2000; Fax: (510) 452-0182
Duane Rettig wrote:
> As you've probably seen by now, there are many ways to write rot13 for
> strings, some more efficient than others, and some more elegant than
> others.
Yes. I'd like to thank everyone who has participated. You've given me
some great ideas and identified some gaps in my knowledge.
> However, I'd like to expand the sides of the box a little, and ask:
> Why do you want to perform rot13 on strings? Where would you get such
> a string? What would you do with the result?
I'm hacking around with some ideas for a crypto toolkit.
> In fact, most applications for rot13 eventually involve a stream at
> one end or the other, and thus it might make sense to treat it as a
> stream problem.
It's entirely possible that most encryption and decryption will operate
on streams. Thanks for the reference.
Jack
From: Christophe Rhodes
Subject: Re: Should rot13 be this hard?
Date:
Message-ID: <sqbr3nsnvy.fsf@cam.ac.uk>
"Jack" <········@gmail.com> writes:
> I'm making another run at learning Lisp. I've implemented rot13 for
> strings, but my solution seems more verbose than I expected. Here's my
> implementation:
>
> (labels ((compute-char (code base-char-code)
> (code-char (+ base-char-code
> (mod (+ 13 (- code base-char-code)) 26)))))
Amusingly, haha, I don't think this is defined to work, though of
course for all practical implementations around today it will because
they all use ASCII.
> Is my style just bad (aside from the hardcoded constants that I intend
> to remove)? Are there standard functions that I'm not taking advantage
> of? Is there a commonly used package for string manipulation? Do most
> people develop their own set of macros and functions to simplify string
> handling?
Well, it's possible that you're unaware that strings are sequences
(and so that all the sequence functions work on strings). That said,
I don't think there's a big win in using them.
Here's how I would write it, which is also quite verbose, but I think
shows a little more scope for generality. (And works in silly
character sets, too, though that's not such an advantage...). Only
lightly tested, so beware.
(let ((from "abcdefghijklmnopqrstuvwxyz")
(to "nopqrstuvwxyzabcdefghijklm"))
(let ((table (make-array
;; if your implementation makes this table be bigger than
;; 256 elements, consider using a hash table instead.
(1+ (max (reduce #'max from :key #'char-code)
(reduce #'max (string-upcase from) :key #'char-code)))
:element-type 'base-char)))
(dotimes (i (length table))
(setf (char table i) (code-char i)))
(dotimes (i (length from))
(setf (char table (char-code (char from i))) (char to i))
(setf (char table (char-code (char-upcase (char from i))))
(char-upcase (char to i))))
(defun rot13/char (char)
(let ((code (char-code char)))
(if (>= code (length table))
char
(char table code))))))
(defun nrot13 (string &key (start 0) end)
(let ((end (or end (length string))))
(do ((i start (1+ i)))
((>= i end) string)
(setf (char string i) (rot13/char (char string i))))))
(defun rot13 (string &key (start 0) end)
(let ((string (copy-seq string)))
(nrot13 string :start start :end end)))
Christophe
Christophe Rhodes <·····@cam.ac.uk> writes:
> (defun rot13 (string &key (start 0) end)
> (let ((string (copy-seq string)))
> (nrot13 string :start start :end end)))
What about (map 'string #'rot13/char string) for this (ignoring
the start and end parameters for a moment)? Is map slower, does it
more conses?
--
Stefan.
From: Damien Diederen
Subject: Re: Should rot13 be this hard?
Date:
Message-ID: <87hddf7h3k.fsf@keem.bcc>
Hi,
Christophe Rhodes <·····@cam.ac.uk> writes:
> "Jack" <········@gmail.com> writes:
>
>> I'm making another run at learning Lisp. I've implemented rot13 for
>> strings, but my solution seems more verbose than I expected. Here's my
>> implementation:
>>
>> (labels ((compute-char (code base-char-code)
>> (code-char (+ base-char-code
>> (mod (+ 13 (- code base-char-code)) 26)))))
>
> Amusingly, haha, I don't think this is defined to work, though of
> course for all practical implementations around today it will because
> they all use ASCII.
>
>> Is my style just bad (aside from the hardcoded constants that I intend
>> to remove)? Are there standard functions that I'm not taking advantage
>> of? Is there a commonly used package for string manipulation? Do most
>> people develop their own set of macros and functions to simplify string
>> handling?
>
> Well, it's possible that you're unaware that strings are sequences
> (and so that all the sequence functions work on strings). That said,
> I don't think there's a big win in using them.
>
> Here's how I would write it, which is also quite verbose, but I think
> shows a little more scope for generality. (And works in silly
> character sets, too, though that's not such an advantage...). Only
> lightly tested, so beware.
>
> (let ((from "abcdefghijklmnopqrstuvwxyz")
> (to "nopqrstuvwxyzabcdefghijklm"))
> (let ((table (make-array
> ;; if your implementation makes this table be bigger than
> ;; 256 elements, consider using a hash table instead.
> (1+ (max (reduce #'max from :key #'char-code)
> (reduce #'max (string-upcase from) :key #'char-code)))
> :element-type 'base-char)))
> (dotimes (i (length table))
> (setf (char table i) (code-char i)))
> (dotimes (i (length from))
> (setf (char table (char-code (char from i))) (char to i))
> (setf (char table (char-code (char-upcase (char from i))))
> (char-upcase (char to i))))
> (defun rot13/char (char)
> (let ((code (char-code char)))
> (if (>= code (length table))
> char
> (char table code))))))
>
> (defun nrot13 (string &key (start 0) end)
> (let ((end (or end (length string))))
> (do ((i start (1+ i)))
> ((>= i end) string)
> (setf (char string i) (rot13/char (char string i))))))
>
> (defun rot13 (string &key (start 0) end)
> (let ((string (copy-seq string)))
> (nrot13 string :start start :end end)))
For completeness, here are two other ways to write ROT13/CHAR, trading
runtime efficiency for succinctness:
(let ((from "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
(to "nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM"))
(defun rot13/char (char)
(let ((pos (position char from)))
(if pos (char to pos) char))))
(let ((table (make-hash-table)))
(loop :for from :across "abcdefghijklmnopqrstuvwxyz"
:for to :across "nopqrstuvwxyzabcdefghijklm"
:do (setf (gethash from table) to
(gethash (char-upcase from) table) (char-upcase to)))
(defun rot13/char (char)
(gethash char table char)))
Should work on any implementation, AFAICS. Only lightly tested.
> Christophe
Cu,
Damien.
--
http://foobox.net/~dash/
I can resist everything except temptation.
--Oscar Wilde
Jack wrote:
> Is my style just bad (aside from the hardcoded constants that I intend
> to remove)? Are there standard functions that I'm not taking advantage
> of? Is there a commonly used package for string manipulation? Do most
> people develop their own set of macros and functions to simplify string
> handling?
if you are using "loop", you can use "collect":
(coerce (loop for c across "Test"
collect (code-char (1+ (char-code c))))
'string)
-> "Uftu"
but I think using constants and "map" makes it much easier:
(defconstant +from+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
(defconstant +to+ "nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM")
(defun rot13 (text)
(map 'string
#'(lambda (c) (let ((p (position c +from+)))
(if p (char +to+ p) c)))
text))
of course, nrot13 is rot13:
(defun nrot13 (text)
(rot13 text))
--
Frank Bu�, ··@frank-buss.de
http://www.frank-buss.de, http://www.it4-systems.de
Frank Buss wrote:
> of course, nrot13 is rot13:
>
> (defun nrot13 (text)
> (rot13 text))
sorry, this is not right, I thought it were the negate of rot13, but it is
the in-place conversion, which is not possible with map.
--
Frank Bu�, ··@frank-buss.de
http://www.frank-buss.de, http://www.it4-systems.de
"Jack" <········@gmail.com> writes:
> I'm making another run at learning Lisp. I've implemented rot13 for
> strings, but my solution seems more verbose than I expected. Here's my
> implementation:
Hmmm... I don't think, mine is much better, but I don't think you
can avoid handling all the different cases (so I have no idea how
to make my rot13-char any shorter). Anyway I'm using map instead
of loop, so at least my version is a little bit shorter:
(defun rot13-char (char)
(flet ((rotate (char base)
(let ((code (char-code char))
(base-code (char-code base)))
(code-char (+ base-code
(mod (+ 13 (- code base-code)) 26))))))
(cond ((char<= #\a char #\z)
(rotate char #\a))
((char<= #\A char #\Z)
(rotate char #\A))
(t char))))
(defun rot13 (string) (map 'string #'rot13-char string))
> Is my style just bad
I don't think so -- i also often use loop instead of do, map and
Co. But sometimes map (and variants like reduce) come in very
handy.
--
Stefan.
Here's a simple solution.
(defconstant alphabet "aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ")
(defun rot13/char (char)
(if (alpha-char-p char)
(char alphabet
(mod (+ (position char alphabet) 26)
52))
char))
(defun rot13 (string)
(map 'string #'rot13/char string))
We shouldn't need a separate nrot13 function, since it's a symmetrical
operation.
CL-USER> (rot13 "This is a test to SEE if we CAN preserve CASE")
"Guvf vf n grfg gb FRR vs jr PNA cerfreir PNFR"
CL-USER> (rot13 *)
"This is a test to SEE if we CAN preserve CASE"
--
Tiarn�n
Jack wrote:
> Are there standard functions that I'm not taking advantage
> of? Is there a commonly used package for string manipulation? Do most
> people develop their own set of macros and functions to simplify string
> handling?
Lisp is different. It's not an array of functions called within a
syntactic framework. Instead, functionality is created by building
structures of functions. I think this is a rather good example for a
demonstration.
What you want to do is simply to take a string S and obtain a string
T that contains the characters in S, each transformed by a
transformation function F:
(setf T (map 'string #'F S))
In this case, T is a newly created string. Alternatively, the
storage used by S can be reused for T:
(setf T (map-into S #'F S))
If F is a standard function, or a function from a package, you're done
now. If not, next step is to define it. In pseudocode (sort of):
F(c) => c, if c isn't in the source alphabet;
otherwise, F(c) => c', where c' is c transformed
In Lisp (inadequate version):
(defun F (c)
(let ((p (G c)))
(if (not p)
c
(H p))))
The function G is a semi-predicate that returns the position of c in
the source alphabet, or NIL if it can't be found. First, define the
source alphabet:
(defconstant +a+ "abcdefghijklmnopqrstuvwxyz")
G might look like this:
(defun G (c)
(position-if (lambda (x) (char-equal x c)) +a+))
The function H does the actual transforming. It can be written as
a mapping function:
(defun H (p)
(char +a+ (mod (+ 13 p) 26)))
Another possibility is to define a corresponding alphabet of
transformed characters:
(defconstant +b+ "nopqrstuvwxyzabcdefghijklm")
In which case the transforming function simply picks out the
corresponding character:
(defun H (p)
(char +b+ p))
The simple F defined above collapses transformed characters into
lowercase. To preserve case, F can be defined this way:
(defun F (c)
(let ((p (G c)))
(cond ((not p) c)
((lower-case-p c) (H p))
(t (char-upcase (H p))))))
Peter Lewerin wrote:
>> (setf T (map 'string #'F S))
>
> Well, obviously you can't setf T.
Wasn't there a famous error message for this in the good old
days? Something like "VERITAS ETERNA - DON'T SET T"?
Arthur Lemmens wrote:
> Peter Lewerin wrote:
> > Well, obviously you can't setf T.
>
> Wasn't there a famous error message for this in the good old
> days? Something like "VERITAS ETERNA - DON'T SET T"?
In one early version of AutoLisp, you *could* setq T. "Quid est
veritas"?
Arthur Lemmens wrote:
> Peter Lewerin wrote:
>
>>> (setf T (map 'string #'F S))
>>
>>
>> Well, obviously you can't setf T.
>
>
> Wasn't there a famous error message for this in the good old
> days? Something like "VERITAS ETERNA - DON'T SET T"?
>
SBCL offer the following :
>(set t nil)
=> Veritas aeterna. (can't change T)
and my personal favorite L
>(set nil t)
=> Nihil ex nihil. (can't change NIL)
--
Drew Crampsie
drewc at tech dot coop
"Never mind the bollocks -- here's the sexp's tools."
-- Karl A. Krueger on comp.lang.lisp
Drew Crampsie wrote:
> SBCL offer the following :
>
> >(set t nil)
> => Veritas aeterna. (can't change T)
>
> and my personal favorite L
>
> >(set nil t)
> => Nihil ex nihil. (can't change NIL)
Ah, it's good to know that these nice error messages are still
alive. I'm afraid that Lispworks and Allegro give more prosaic
messages like "T is a constant and cannot be set or bound."
--
Arthur
drewc <·····@rift.com> writes:
>
> Arthur Lemmens wrote:
> > Peter Lewerin wrote:
> >
> >>> (setf T (map 'string #'F S))
> >>
> >>
> >> Well, obviously you can't setf T.
> >
> >
> > Wasn't there a famous error message for this in the good old
> > days? Something like "VERITAS ETERNA - DON'T SET T"?
> >
> SBCL offer the following :
>
> >(set t nil)
> => Veritas aeterna. (can't change T)
>
> and my personal favorite L
>
> >(set nil t)
> => Nihil ex nihil. (can't change NIL)
This was certainly the error message from the old MAC Lisp systems. I'm
glad to see that it has been perpetuated. Something about latin error
messages that lends a classic feel to a language.
--
Thomas A. Russ, USC/Information Sciences Institute
···@sevak.isi.edu (Thomas A. Russ) writes:
> drewc <·····@rift.com> writes:
>
> >
> > Arthur Lemmens wrote:
> > > Peter Lewerin wrote:
> > >
> > >>> (setf T (map 'string #'F S))
> > >>
> > >>
> > >> Well, obviously you can't setf T.
> > >
> > >
> > > Wasn't there a famous error message for this in the good old
> > > days? Something like "VERITAS ETERNA - DON'T SET T"?
> > >
> > SBCL offer the following :
> >
> > >(set t nil)
> > => Veritas aeterna. (can't change T)
> >
> > and my personal favorite L
> >
> > >(set nil t)
> > => Nihil ex nihil. (can't change NIL)
>
> This was certainly the error message from the old MAC Lisp systems. I'm
> glad to see that it has been perpetuated. Something about latin error
> messages that lends a classic feel to a language.
----------------------------------------------------------------------
MacLISP.2149
*
(setq nil t)
;(SETQ (NIL)) NIHIL EX NIHIL - DON'T SETQ NIL
;BKPT FAIL-ACT
(setq t nil)
;(SETQ (T)) VERITAS AETERNA - DON'T SETQ T
----------------------------------------------------------------------
········@yahoo.com (Tiarn�n � Corr�in) writes:
> Kent M Pitman <······@nhplace.com> writes:
>
> > ······@news.dtpq.com (Christopher C. Stacy) writes:
> >
> >> ----------------------------------------------------------------------
> >> MacLISP.2149
> >>
> >> *
> >> (setq nil t)
> >> ;(SETQ (NIL)) NIHIL EX NIHIL - DON'T SETQ NIL
> >>
> >> ;BKPT FAIL-ACT
> >>
> >> (setq t nil)
> >> ;(SETQ (T)) VERITAS AETERNA - DON'T SETQ T
> >> ----------------------------------------------------------------------
> >
> > There is another.
>
> And this is?
In Maclisp, if you make your own symbol with a pure [i.e., read-only]
value cell (something I don't recall how to do but probably involved
using PURCOPY somehow), trying to set it will say [this is from memory,
so might be off slightly]:
PURITAS NECESSE EST - DON'T DO RANDOM BINDINGS
Ah, yes, it seems my memory isn't too bad. A search for this exact
phrase (put stringquotes around it if you're using Google) turns up
among the short page of results a Midas [PDP10 assembly language]
source page that has this and other error messages on it.
···@sevak.isi.edu (Thomas A. Russ) writes:
> drewc <·····@rift.com> writes:
>> >(set nil t)
>> => Nihil ex nihil. (can't change NIL)
>
> This was certainly the error message from the old MAC Lisp systems. I'm
> glad to see that it has been perpetuated. Something about latin error
> messages that lends a classic feel to a language.
And there's something about ungrammatical Latin error messages that
lends it a sloppy feeling. That should be "nihil ex nihilo".
Peter
······@heslin.eclipse.co.uk wrote:
> ···@sevak.isi.edu (Thomas A. Russ) writes:
>
>
>>drewc <·····@rift.com> writes:
>>
>>> >(set nil t)
>>>=> Nihil ex nihil. (can't change NIL)
>>
>>This was certainly the error message from the old MAC Lisp systems. I'm
>>glad to see that it has been perpetuated. Something about latin error
>>messages that lends a classic feel to a language.
>
>
> And there's something about ungrammatical Latin error messages that
> lends it a sloppy feeling. That should be "nihil ex nihilo".
The funniest Latin boo-boo I have seen in a long time is the name of a
guild in the game World of Warcraft. (World of Warcraft is a very
popular MMORPG with a few million players; a player typically encounters
many other people in the course of an online session, and players
organize themselves into dozens or hundreds of guilds).
The guild was named "Vae Victus". Now, of course, what they meant to
name it was "Vae Victis", "woe to the vanquished", or, as I like to
render it in the modern vernacular, "sucks to lose." Great name for a
player-versus-player guild: "Sucks to Lose".
But they named it "Vae Victus", with "victus" in the nominative. "Woe
vanquished." Perhaps it's a message of hope. Or perhaps they mean
"Vanquished. Woe." As in, "we're losers. we suck."
"mikel" wrote:
> The guild was named "Vae Victus". Now, of course, what they meant to
> name it was "Vae Victis", "woe to the vanquished", or, as I like to
> render it in the modern vernacular, "sucks to lose." Great name for a
> player-versus-player guild: "Sucks to Lose".
>
> But they named it "Vae Victus", with "victus" in the nominative. "Woe
> vanquished." Perhaps it's a message of hope. Or perhaps they mean
> "Vanquished. Woe." As in, "we're losers. we suck."
ROMANES EUNT DOMUS ... :-)
--
Gareth McCaughan
.sig under construc
Brian McCaughan wrote:
> "mikel" wrote:
>
>
>>The guild was named "Vae Victus". Now, of course, what they meant to
>>name it was "Vae Victis", "woe to the vanquished", or, as I like to
>>render it in the modern vernacular, "sucks to lose." Great name for a
>>player-versus-player guild: "Sucks to Lose".
>>
>>But they named it "Vae Victus", with "victus" in the nominative. "Woe
>>vanquished." Perhaps it's a message of hope. Or perhaps they mean
>>"Vanquished. Woe." As in, "we're losers. we suck."
>
>
> ROMANES EUNT DOMUS ... :-)
Are you sure? Do you have enough paint? :)
Cheers
--
Marco
Marco Antoniotti wrote:
>>> The guild was named "Vae Victus". Now, of course, what they meant to
>>> name it was "Vae Victis", "woe to the vanquished", or, as I like to
>>> render it in the modern vernacular, "sucks to lose." Great name for a
>>> player-versus-player guild: "Sucks to Lose".
>>>
>>> But they named it "Vae Victus", with "victus" in the nominative. "Woe
>>> vanquished." Perhaps it's a message of hope. Or perhaps they mean
>>> "Vanquished. Woe." As in, "we're losers. we suck."
>>
>> ROMANES EUNT DOMUS ... :-)
>
> Are you sure? Do you have enough paint? :)
No. I'm a loser, and I suck. :-)
(Name change noted, btw.)
--
Gareth McCaughan
.sig under construc
······@heslin.eclipse.co.uk writes:
> ···@sevak.isi.edu (Thomas A. Russ) writes:
>
> > drewc <·····@rift.com> writes:
> >> >(set nil t)
> >> => Nihil ex nihil. (can't change NIL)
> >
> > This was certainly the error message from the old MAC Lisp systems. I'm
> > glad to see that it has been perpetuated. Something about latin error
> > messages that lends a classic feel to a language.
>
> And there's something about ungrammatical Latin error messages that
> lends it a sloppy feeling. That should be "nihil ex nihilo".
I'm pretty sure that nihil was irregular, although it was sometimes
declined nonetheless. Anyway, it certainly isn't "nihil ex nihil" due
to *sloppiness*. Guy Steel went to the Boston Latin School and
explains why he changed the message in this message:
<··················@livia.East.Sun.COM>
(It's here in Google's archive:
http://groups.google.com/group/comp.lang.scheme/msg/61fe57feb5a0f9d4?dmode=source
)
--
/|_ .-----------------------.
,' .\ / | Free Mumia Abu-Jamal! |
,--' _,' | Abolish the racist |
/ / | death penalty! |
( -. | `-----------------------'
| ) |
(`-. '--.)
`. )----'
···@conquest.OCF.Berkeley.EDU (Thomas F. Burdick) writes:
> Anyway, it certainly isn't "nihil ex nihil" due
> to *sloppiness*. Guy Steel went to the Boston Latin School and
> explains why he changed the message in this message:
> <··················@livia.East.Sun.COM>
>
> (It's here in Google's archive:
> http://groups.google.com/group/comp.lang.scheme/msg/61fe57feb5a0f9d4?dmode=source
Thanks for the reference. So it wasn't sloppiness, it was willful
foolishness.
When I became MacLisp maintainer in 1972, the message "NIHIL EX
NIHILO - DON'T SETQ NIL" was already in the system. A few years
later I modified the spelling to "NIHIL EX NIHIL - DON'T SETQ
NIL"---for my Boston Latin School education had drummed into me the
notion that "NIHIL" is indeclinable, though later I found evidence
that the form NIHILO was sometimes used-
So Steele deliberately changed the correct idiom to the incorrect one on
the basis of a misapplied rule he half-remembered from school. When he
later encountered evidence for the correct form, he dismissed it as a
variant form.
It's not as though "ex nihilo" is an uncommon phrase in
philosophical/cosmological discourse. How depressing ...
Peter
Paul Foley <···@below.invalid> (http://public.xdi.org/=pf) writes:
> It's not ungrammatical; nihil is indeclinable.
Nihil is indeclinable, but the sentence is ungrammatical nonetheless.
With the proposition "ex" the ablative of the by-formation "nihilum" is
used exclusively.
Peter