From: David Trudgett
Subject: Abuse of defvar??
Date: 
Message-ID: <m3zmwf8hm1.fsf@rr.trudgett>
As a Lisp newbie, I thought I would ask some opinions from persons
more knowledgeable than I about the following bit of code which I
recently happened across:

(defvar hex-char
  (let ((chars #(#\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9 #\A #\B 
               #\C #\D #\E #\F)))
    (lambda (i) (aref chars (mod i 16)))))

I think it's quite cute in a way, but can't help wondering if there
could be an actual reason for (ab)using(?) DEFVAR in this way, rather
than simply using a DEFUN as follows:

(defun hex-char (i)
  (let ((chars #(#\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9 #\A #\B 
               #\C #\D #\E #\F)))
    (aref chars (mod i 16))))


To call the first requires (for example): (funcall hex-char 12)
To call the other requires only: (hex-char 12)

Please unconfuse a new Lisper! :-)

David


-- 

David Trudgett
http://www.zeta.org.au/~wpower/

Reality is 20% real and 80% made up stuff in your head.
But I'm not sure about the 20%.

From: Artie Gold
Subject: Re: Abuse of defvar??
Date: 
Message-ID: <3bbotnF6gg82mU1@individual.net>
David Trudgett wrote:
> As a Lisp newbie, I thought I would ask some opinions from persons
> more knowledgeable than I about the following bit of code which I
> recently happened across:
> 
> (defvar hex-char
>   (let ((chars #(#\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9 #\A #\B 
>                #\C #\D #\E #\F)))
>     (lambda (i) (aref chars (mod i 16)))))
> 
> I think it's quite cute in a way, but can't help wondering if there
> could be an actual reason for (ab)using(?) DEFVAR in this way, rather
> than simply using a DEFUN as follows:
> 
> (defun hex-char (i)
>   (let ((chars #(#\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9 #\A #\B 
>                #\C #\D #\E #\F)))
>     (aref chars (mod i 16))))
> 
> 
> To call the first requires (for example): (funcall hex-char 12)
> To call the other requires only: (hex-char 12)
> 
> Please unconfuse a new Lisper! :-)
> 
> David
> 
> 
Alas, I think writing it as a closure would be better:

(let ((chars #(#\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9 #\A #\B
                #\C #\D #\E #\F)))
    (defun hex-char (i)
       (aref chars (mod i 16))))

--ag
-- 
Artie Gold -- Austin, Texas
http://it-matters.blogspot.com (new post 12/5)
http://www.cafepress.com/goldsays
From: Alain Picard
Subject: Re: Abuse of defvar??
Date: 
Message-ID: <87ekdr6uwk.fsf@memetrics.com>
Artie Gold <·········@austin.rr.com> writes:

> Alas, I think writing it as a closure would be better:
>
> (let ((chars #(#\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9 #\A #\B
>                 #\C #\D #\E #\F)))
>     (defun hex-char (i)
>        (aref chars (mod i 16))))
>
What about the pedestrian

 (defun hex-char (i)
        (svref #(#\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 
               #\8 #\9 #\A #\B #\C #\D #\E #\F)
               (mod i 16)))
?

-- 
It would be difficult to construe        Larry Wall, in  article
this as a feature.			 <·····················@netlabs.com>
From: Kent M Pitman
Subject: Re: Abuse of defvar??
Date: 
Message-ID: <uekdrnn5y.fsf@nhplace.com>
Alain Picard <············@memetrics.com> writes:

> Artie Gold <·········@austin.rr.com> writes:
> 
> > Alas, I think writing it as a closure would be better:
> >
> > (let ((chars #(#\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9 #\A #\B
> >                 #\C #\D #\E #\F)))
> >     (defun hex-char (i)
> >        (aref chars (mod i 16))))
> >
> What about the pedestrian
> 
>  (defun hex-char (i)
>         (svref #(#\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 
>                #\8 #\9 #\A #\B #\C #\D #\E #\F)
>                (mod i 16)))

or

(defun hex-char (i) (digit-char i 16))

But seriously, I prefer the usage that uses DEFVAR (or DEFCONSTANT) because
constants that get named tend to find other uses.  Lisp is designed to
encourage reuse, and this is such a case.  e.g.,

 (defconstant +hex-chars+ #(#\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7
                            #\8 #\9 #\A #\B #\C #\D #\E #\F))
 (defun hex-char (i)
   ;; please don't use MOD since i=16 is SURELY an error
   (check-type i (integer 0 15) "the integer value of a hex digit")
   (svref +hex-chars+ i))

Later, you might (depending on various factors) decide to write the
inverse function as:

 (defun hex-weight (ch)
   (check-type ch character "a hex character")
   (position (char-upcase ch) +hex-chars+))

Of course, nothing keeps you from originally writing it as Alain suggests
and then just factoring out the named part when you find the second use.

I don't think it's a major issue either way.

I tend to make these things DEFCONSTANT when I think they will not change,
btw.  There are unlikely to be new hex digits any time soon, for example.
Using DEFCONSTANT instead of DEFVAR permits the compiler to sometimes save
a cycle or two in the access since it can compile a move of a constant not
an indirect move through a variable's value cell (in case of change).
Not that this necessarily is a major issue--it may depend on your application.

As I mentioned, there are other factors; if speed is REALLY an issue,
POSITION is not how you will want to do HEX-WEIGHT since it's algorithmically
too slow.  But for "light" use, there's nothing wrong with this definition...

(... other than the fact that digit-char-p and digit-char already exist.)
From: Kalle Olavi Niemitalo
Subject: Re: Abuse of defvar??
Date: 
Message-ID: <874qengl89.fsf@Astalo.kon.iki.fi>
Kent M Pitman <······@nhplace.com> writes:

>    ;; please don't use MOD since i=16 is SURELY an error
>    (check-type i (integer 0 15) "the integer value of a hex digit")
>    (svref +hex-chars+ i))

Do you mean the MOD function?  I think the MOD type specifier
would be quite appropriate here.
From: Rob Warnock
Subject: Re: Abuse of defvar??
Date: 
Message-ID: <B4qdnQucPqBOZ83fRVn-uQ@speakeasy.net>
Kalle Olavi Niemitalo  <···@iki.fi> wrote:
+---------------
| Kent M Pitman <······@nhplace.com> writes:
| >    ;; please don't use MOD since i=16 is SURELY an error
| >    (check-type i (integer 0 15) "the integer value of a hex digit")
| >    (svref +hex-chars+ i))
| 
| Do you mean the MOD function?  I think the MOD type specifier
| would be quite appropriate here.
+---------------

While type (MOD 16) is by definition [CLHS "Type Specifier MOD"]
exactly equivalent to (INTEGER 0 15), in this case I think it gives
the wrong connotation to the reader of the code. The latter form
more clearly identifies this as a range check.  IMHO...


-Rob

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Kalle Olavi Niemitalo
Subject: Re: Abuse of defvar??
Date: 
Message-ID: <871x9phhd1.fsf@Astalo.kon.iki.fi>
····@rpw3.org (Rob Warnock) writes:

> While type (MOD 16) is by definition [CLHS "Type Specifier MOD"]
> exactly equivalent to (INTEGER 0 15), in this case I think it gives
> the wrong connotation to the reader of the code. The latter form
> more clearly identifies this as a range check.  IMHO...

I prefer having the base 16 plainly visible in the check.
How about (integer #x0 #xF)?
From: Kent M Pitman
Subject: Re: Abuse of defvar??
Date: 
Message-ID: <u4qelk6am.fsf@nhplace.com>
Kalle Olavi Niemitalo <···@iki.fi> writes:

> ····@rpw3.org (Rob Warnock) writes:
> 
> > While type (MOD 16) is by definition [CLHS "Type Specifier MOD"]
> > exactly equivalent to (INTEGER 0 15), in this case I think it gives
> > the wrong connotation to the reader of the code. The latter form
> > more clearly identifies this as a range check.  IMHO...
> 
> I prefer having the base 16 plainly visible in the check.
> How about (integer #x0 #xF)?

Why?  Is the digit for 9 different when it's hex and not octal or decimal?

CL did the right thing in making the radix be an argument.  In which case,
it's a little hard to also make it part of the declarational notation. ;)

The weird thing about this discussion is that we're talking about hex
like the computation is different for octal or decimal.  Only the range
of the argument is; the rest works pretty much the same.

Another obvious way to get code re-use is to use the same table for 
implementing octal-xxx, decimal-xxx, etc.
From: Adam Warner
Subject: Re: Abuse of defvar??
Date: 
Message-ID: <pan.2005.04.04.11.46.09.508401@consulting.net.nz>
On Mon, 04 Apr 2005 05:08:12 +0000, Kent M Pitman wrote:
>  (defconstant +hex-chars+ #(#\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7
>                             #\8 #\9 #\A #\B #\C #\D #\E #\F))

Anyone who wants their code to run on SBCL cannot use the above form.
Subsequent evaluations of the form will throw an error:

debugger invoked on a DEFCONSTANT-UNEQL in thread 5205:
  The constant +HEX-CHARS+ is being redefined (from
  #(#\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9 #\A #\B ...) to
  #(#\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9 #\A #\B ...))
See also:
  The ANSI Standard, Macro DEFCONSTANT
  The SBCL Manual, Node "Idiosyncrasies"

I suggest this macro is used in place of DEFCONSTANT:

(defmacro defconst (name initial-value &optional doc)
  "Only evaluates initial-value when name is unbound to a value."
  `(eval-when (:compile-toplevel :load-toplevel :execute)
    (if (boundp ',name)
        ',name
        (defconstant ,name ,initial-value ,@(when doc (list doc))))))

i.e. (defconst +hex-chars+ #(#\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7
                             #\8 #\9 #\A #\B #\C #\D #\E #\F)

I dislike the +...+ convention, especially within forms containing
arithmetic. It's a pity "HEX-CHARS" and "hex-chars" intern to the same
symbol in the default readtable mode.[0]

Regards,
Adam

[0] (eq 'HEX-CHARS 'hex-chars) => T
From: Edi Weitz
Subject: Re: Abuse of defvar??
Date: 
Message-ID: <uvf72u47p.fsf@agharta.de>
On Mon, 04 Apr 2005 23:46:11 +1200, Adam Warner <······@consulting.net.nz> wrote:

> I suggest this macro is used in place of DEFCONSTANT:
>
> (defmacro defconst (name initial-value &optional doc)
>   "Only evaluates initial-value when name is unbound to a value."
>   `(eval-when (:compile-toplevel :load-toplevel :execute)
>     (if (boundp ',name)
>         ',name
>         (defconstant ,name ,initial-value ,@(when doc (list doc))))))

If you do it like this then DEFCONSTANT isn't a top level form
anymore.  See the CLHS dictionary entry for DEFCONSTANT.

Cheers,
Edi.

-- 

Lisp is not dead, it just smells funny.

Real email: (replace (subseq ·········@agharta.de" 5) "edi")
From: Christophe Rhodes
Subject: Re: Abuse of defvar??
Date: 
Message-ID: <squ0mmbryo.fsf@cam.ac.uk>
Edi Weitz <········@agharta.de> writes:

> On Mon, 04 Apr 2005 23:46:11 +1200, Adam Warner <······@consulting.net.nz> wrote:
>
>> I suggest this macro is used in place of DEFCONSTANT:
>>
>> (defmacro defconst (name initial-value &optional doc)
>>   "Only evaluates initial-value when name is unbound to a value."
>>   `(eval-when (:compile-toplevel :load-toplevel :execute)
>>     (if (boundp ',name)
>>         ',name
>>         (defconstant ,name ,initial-value ,@(when doc (list doc))))))
>
> If you do it like this then DEFCONSTANT isn't a top level form
> anymore.  See the CLHS dictionary entry for DEFCONSTANT.

Right.

(defmacro defconst (name initial-value doc)
  `(defconstant ,name (if (boundp ',name)
                          (progn 
                            ,initial-value
                            (symbol-value ',name))
                          ,initial-value)
     ,@(when doc (list doc))))

covers most of the bases, but doesn't deal with the possibility that
name might be bound in some environment that isn't the global
environment.

Christophe
From: Pascal Bourguignon
Subject: Re: Abuse of defvar??
Date: 
Message-ID: <87psxan01e.fsf@thalassa.informatimago.com>
Christophe Rhodes <·····@cam.ac.uk> writes:

> Edi Weitz <········@agharta.de> writes:
> 
> > On Mon, 04 Apr 2005 23:46:11 +1200, Adam Warner <······@consulting.net.nz> wrote:
> >
> >> I suggest this macro is used in place of DEFCONSTANT:
> >>
> >> (defmacro defconst (name initial-value &optional doc)
> >>   "Only evaluates initial-value when name is unbound to a value."
> >>   `(eval-when (:compile-toplevel :load-toplevel :execute)
> >>     (if (boundp ',name)
> >>         ',name
> >>         (defconstant ,name ,initial-value ,@(when doc (list doc))))))
> >
> > If you do it like this then DEFCONSTANT isn't a top level form
> > anymore.  See the CLHS dictionary entry for DEFCONSTANT.
> 
> Right.
> 
> (defmacro defconst (name initial-value doc)
>   `(defconstant ,name (if (boundp ',name)
>                           (progn 
>                             ,initial-value
>                             (symbol-value ',name))
>                           ,initial-value)
>      ,@(when doc (list doc))))
> 
> covers most of the bases, but doesn't deal with the possibility that
> name might be bound in some environment that isn't the global
> environment.

What about:

    (DEFPARAMETER +hex-char+ "0123456789ABCDEF")

?

For any type other than number, character and symbol, I'd forgot DEFCONSTANT...


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

The world will now reboot.  don't bother saving your artefacts.
From: Kent M Pitman
Subject: Re: Abuse of defvar??
Date: 
Message-ID: <u8y3yksjv.fsf@nhplace.com>
Adam Warner <······@consulting.net.nz> writes:

> I dislike the +...+ convention, especially within forms containing
> arithmetic.

Well, you missed the exodus of the entire herd of horses surrounding
this barn door when '*' was picked for special variables.

I recommend getting used to Lisp as its own language, not as a bastard
form of infix.  If you do that,  you'll feel better about it.  There
really is no syntactic confusion.

> It's a pity "HEX-CHARS" and "hex-chars" intern to the same
> symbol in the default readtable mode.[0]

They don't.

> Regards,
> Adam
> 
> [0] (eq 'HEX-CHARS 'hex-chars) => T

This is true, but it doesn't imply the other thing you said above.

Search in the c.l.l. for archives for an explanation of the difference
between "case sensitivity" (CL symbol interning is done in a
case-sensitive way) and "case translation" (CL has a case-translating 
reader).
From: David Trudgett
Subject: Re: Abuse of defvar??
Date: 
Message-ID: <m3k6niunbm.fsf@rr.trudgett>
Kent M Pitman <······@nhplace.com> writes:

> or
>
> (defun hex-char (i) (digit-char i 16))

Nice idea. Of course, it doesn't wrap around like the MOD example:

CL-USER>(hex-char 16)
NIL

But, then again, I'm not sure why you'd want the wrapping behaviour
anyway, because as you mention, (hex-char 16) would surely be an
error condition (and that would seem to be the case in the code from
which the example was taken).

>
> But seriously, I prefer the usage that uses DEFVAR (or DEFCONSTANT) because
> constants that get named tend to find other uses.  Lisp is designed to
> encourage reuse, and this is such a case.  e.g.,
>
>  (defconstant +hex-chars+ #(#\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7
>                             #\8 #\9 #\A #\B #\C #\D #\E #\F))
>  (defun hex-char (i)
>    ;; please don't use MOD since i=16 is SURELY an error
>    (check-type i (integer 0 15) "the integer value of a hex digit")
>    (svref +hex-chars+ i))

I like the CHECK-TYPE idea. It's the first time I've seen it (or paid
any attention to it). Has overtones of Ada there! ;-)


>
> Later, you might (depending on various factors) decide to write the
> inverse function as:
>
>  (defun hex-weight (ch)
>    (check-type ch character "a hex character")
>    (position (char-upcase ch) +hex-chars+))


The actual code to do the inverse was as follows:

(defun char-hex (c)
  (cond
    ((<= (char-code #\0) c (char-code #\9)) (- c (char-code #\0)))
    ((<= (char-code #\A) c (char-code #\F)) (+ 10 (- c (char-code #\A))))
    (t (throw 'BadChar nil))))

That seems like it is probably more efficient than the POSITION
method, plus it catches the bad char exception. I don't like
explicitly depending on collating sequences, though. It just seems
yucky.


> As I mentioned, there are other factors; if speed is REALLY an issue,
> POSITION is not how you will want to do HEX-WEIGHT since it's algorithmically
> too slow.  But for "light" use, there's nothing wrong with this definition...

The application (actually, it's in a support library for an
application) is translating streams of quoted-printable data to and
from HEX, so speed would matter.

>
> (... other than the fact that digit-char-p and digit-char already exist.)
>

That's the nice thing with CL, isn't it? There's so much already
there. It's just a matter of knowing about it! :-)

David


-- 

David Trudgett
http://www.zeta.org.au/~wpower/

Reality is 20% real and 80% made up stuff in your head.
But I'm not sure about the 20%.
From: Kent M Pitman
Subject: Re: Abuse of defvar??
Date: 
Message-ID: <u4qemkrkr.fsf@nhplace.com>
David Trudgett <······@zeta.org.au.nospamplease>  writes:

> The actual code to do the inverse was as follows:
> 
> (defun char-hex (c)
>   (cond
>     ((<= (char-code #\0) c (char-code #\9)) (- c (char-code #\0)))
>     ((<= (char-code #\A) c (char-code #\F)) (+ 10 (- c (char-code #\A))))
>     (t (throw 'BadChar nil))))

THROW is NOT an error handling technology.  It is a transfer of control
technology.  Please see my papers
  http://www.nhplace.com/kent/Papers/Exceptional-Situations-1990.html
and
  http://www.nhplace.com/kent/Papers/Condition-Handling-2001.html
though I think the former paper really covers the remedial info you need.

> That seems like it is probably more efficient than the POSITION
> method, plus it catches the bad char exception.

As I said, the issue is one of whether you need storage efficiency
[which the POSITION method offers, by being relatively compact code]
or speed efficiency.  While the above is still O(1), it certainly
makes more compares and more assumptions about implementation
encodings than it should if you don't have to.

> I don't like explicitly depending on collating sequences, though. 
> It just seems yucky.

Indeed.  Which is why I personally usually do something like this
[untested, caveat emptor] if I'm more interested in speed than space;
also, sometimes I use an array of size 128 instead of 256 ...

 (defconstant +hex-weights+ 
   (macrolet ((setup-table ()
                (let ((table (make-array 256 :element-type nil)))
                  (dotimes (hex-weight 16)
                    (let ((hex-digit-char (hex-digit hex-weight)))
                      (let ((hex-digit-code (char-code hex-digit-char)))
                        (when (>= hex-digit-code 256)
                          (error "+hex-weights+ requires reimplementation.")))
                      (setf  hex-weight)))
                  table)))
     (setup-table)))

 (defun char-hex (c)
   (let ((code (char-code c)))
     (if (< code 256) (svref +hex-weights+ code) nil)))

That's relatively efficient, makes little knowledge of the individual 
implementation's encoding [and self-tests the assumptions it does make,
that is, that the codes for 0-F all fall below 256 somewhere, even without
assuming any are contiguous, permitting things like EBCDIC that split up
the alpha range randomly], and does its "smarts" at compile time.

But you have to time it per implementation. For example, in clisp, which is
byte-coded, the results will be very different than in implementations that
compile to native instructions.

> > As I mentioned, there are other factors; if speed is REALLY an
> > issue, POSITION is not how you will want to do HEX-WEIGHT since
> > it's algorithmically too slow.  But for "light" use, there's
> > nothing wrong with this definition...
> 
> The application (actually, it's in a support library for an
> application) is translating streams of quoted-printable data to and
> from HEX, so speed would matter.

Right.

> > (... other than the fact that digit-char-p and digit-char already exist.)
> >
> 
> That's the nice thing with CL, isn't it? There's so much already
> there. It's just a matter of knowing about it! :-)

Yep.
From: David Trudgett
Subject: Re: Abuse of defvar??
Date: 
Message-ID: <m3oecs8fj0.fsf@rr.trudgett>
Kent M Pitman <······@nhplace.com> writes:

> THROW is NOT an error handling technology.  It is a transfer of
> control technology.  Please see my papers
> http://www.nhplace.com/kent/Papers/Exceptional-Situations-1990.html
> and http://www.nhplace.com/kent/Papers/Condition-Handling-2001.html

Thanks for the pointer to these papers. I read them both once through
quickly and found them interesting. Since the author allows me to
bookmark them <evil grin>, I think I will do so and read them again
when I have more time on my hands!

I appreciate your useful comments. Thanks to everyone else who
replied, too. I really didn't think a little DEFVAR abuse would get
the juices flowing! ;-)

David


-- 

David Trudgett
http://www.zeta.org.au/~wpower/

Reality is 20% real and 80% made up stuff in your head.
But I'm not sure about the 20%.
From: Peter Seibel
Subject: Re: Abuse of defvar??
Date: 
Message-ID: <m3hdijkc48.fsf@gigamonkeys.com>
David Trudgett <······@zeta.org.au.nospamplease> writes:

> Kent M Pitman <······@nhplace.com> writes:
>
>> THROW is NOT an error handling technology.  It is a transfer of
>> control technology.  Please see my papers
>> http://www.nhplace.com/kent/Papers/Exceptional-Situations-1990.html
>> and http://www.nhplace.com/kent/Papers/Condition-Handling-2001.html
>
> Thanks for the pointer to these papers. I read them both once
> through quickly and found them interesting. Since the author allows
> me to bookmark them <evil grin>, I think I will do so and read them
> again when I have more time on my hands!

You may also want to check out chapter 19 of _Practical Common
Lisp_[1], "Beyond Exception Handling: Conditions and Restarts" which
some folks have told me they found to be a useful explanation of how
to use the condition system.

-Peter

[1] <http://www.gigamonkeys.com/book/>

-- 
Peter Seibel                                     ·····@gigamonkeys.com

         Lisp is the red pill. -- John Fraser, comp.lang.lisp
From: David Trudgett
Subject: Re: Abuse of defvar??
Date: 
Message-ID: <m37jjf8om9.fsf@rr.trudgett>
Peter Seibel <·····@gigamonkeys.com> writes:

> You may also want to check out chapter 19 of _Practical Common
> Lisp_[1], "Beyond Exception Handling: Conditions and Restarts" which
> some folks have told me they found to be a useful explanation of how
> to use the condition system.
> [1] <http://www.gigamonkeys.com/book/>

Thanks for that, Peter. I actually read an earlier draft of it a while
ago, but I should revisit the latest incarnation. Maybe some more will
sink in! :-) I also plan to purchase the hardcopy, but circumstances
probably won't allow it for a while.

David


-- 

David Trudgett
http://www.zeta.org.au/~wpower/

Reality is 20% real and 80% made up stuff in your head.
But I'm not sure about the 20%.
From: David Trudgett
Subject: Re: Abuse of defvar??
Date: 
Message-ID: <m3psxaunbo.fsf@rr.trudgett>
Artie Gold <·········@austin.rr.com> writes:

> Alas, I think writing it as a closure would be better:
>
> (let ((chars #(#\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9 #\A #\B
>                 #\C #\D #\E #\F)))
>     (defun hex-char (i)
>        (aref chars (mod i 16))))

Yes, that's interesting for its encapsulation properties. Defining a
separate DEFVAR, DEFPARAMETER or DEFCONSTANT, for instance, can
occasionally lead to the type of bug where the value of the VAR could
be altered to something that is not compatible with a usage somewhere
else in the code.

I assume you could then continue with, for example:

(let ((chars #(#\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9 #\A #\B
                #\C #\D #\E #\F)))
    (defun hex-char (i)
       (aref chars (mod i 16)))
    (defun char-hex (i)
       (blah blah)))

Of course, if there were a lot of these, they could just all be put in
their own source file, and possibly even turned into a class if you're
into OO and speed penalties ;-).

David


-- 

David Trudgett
http://www.zeta.org.au/~wpower/

Reality is 20% real and 80% made up stuff in your head.
But I'm not sure about the 20%.
From: Peter Lewerin
Subject: Re: Abuse of defvar??
Date: 
Message-ID: <b72f3640.0504040206.a839768@posting.google.com>
David Trudgett <······@zeta.org.au.nospamplease>  wrote

> (defvar hex-char

My guess is that it's an Emacs Lisp thing.  In Emacs programming, the
programmer creates function objects like this and registers them. 
Emacs then does all the FUNCALLing in the appropriate places; the user
never uses HEX-CHAR directly.
From: David Trudgett
Subject: Re: Abuse of defvar??
Date: 
Message-ID: <m3ekdqunbl.fsf@rr.trudgett>
·············@swipnet.se (Peter Lewerin) writes:

> My guess is that it's an Emacs Lisp thing.  In Emacs programming, the
> programmer creates function objects like this and registers them. 
> Emacs then does all the FUNCALLing in the appropriate places; the user
> never uses HEX-CHAR directly.

Maybe the author has Emacs Lisp programming experience and it's a
carry over...?? The app itself is in Common Lisp.

Actually, I just did a search and HEX-CHAR is used in exactly one
place in the code. Viz:

(defun integer-hexlist (value &optional (len 2) tail)
  (dotimes (i len tail)
    (push (funcall hex-char value) tail)
    (setf value (truncate (/ value 16)))))


David


-- 

David Trudgett
http://www.zeta.org.au/~wpower/

Reality is 20% real and 80% made up stuff in your head.
But I'm not sure about the 20%.
From: Rob Warnock
Subject: Re: Abuse of defvar??
Date: 
Message-ID: <SZqdnduNcPUfgc_fRVn-gA@speakeasy.net>
David Trudgett  <······@zeta.org.au.nospamplease> wrote:
+---------------
| Actually, I just did a search and HEX-CHAR is used in exactly one
| place in the code. Viz:
| 
| (defun integer-hexlist (value &optional (len 2) tail)
|   (dotimes (i len tail)
|     (push (funcall hex-char value) tail)
|     (setf value (truncate (/ value 16)))))
+---------------

And how many places is INTEGER-HEXLIST used, also just once?
Could the whole call chain be replaced by this, perhaps?

  (format nil "~2,'0x" value)


-Rob

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Pascal Bourguignon
Subject: Re: Abuse of defvar??
Date: 
Message-ID: <873bu6ooaz.fsf@thalassa.informatimago.com>
David Trudgett <······@zeta.org.au.nospamplease> writes:

> As a Lisp newbie, I thought I would ask some opinions from persons
> more knowledgeable than I about the following bit of code which I
> recently happened across:
> 
> (defvar hex-char
>   (let ((chars #(#\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9 #\A #\B 
>                #\C #\D #\E #\F)))
>     (lambda (i) (aref chars (mod i 16)))))
> 
> I think it's quite cute in a way, but can't help wondering if there
> could be an actual reason for (ab)using(?) DEFVAR in this way, rather
> than simply using a DEFUN as follows:
> 
> (defun hex-char (i)
>   (let ((chars #(#\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9 #\A #\B 
>                #\C #\D #\E #\F)))
>     (aref chars (mod i 16))))
> 
> 
> To call the first requires (for example): (funcall hex-char 12)
> To call the other requires only: (hex-char 12)
> 
> Please unconfuse a new Lisper! :-)

A closure is not needed here.
You could use the literal array in aref:
    (aref #(#\0 ... #\F) (mod i 16))
but a vector of character is very close to a string, so:


(defun hex-char (i) (char "0123456789ABCDEF" (mod i 16)))



-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

Nobody can fix the economy.  Nobody can be trusted with their finger
on the button.  Nobody's perfect.  VOTE FOR NOBODY.
From: David Trudgett
Subject: Re: Abuse of defvar??
Date: 
Message-ID: <m38y3yunbk.fsf@rr.trudgett>
Pascal Bourguignon <····@mouse-potato.com> writes:

>
> (defun hex-char (i) (char "0123456789ABCDEF" (mod i 16)))

Cool! So, what you guys are telling me is: TMTOWTDI. Is that right??
:-)

Hey, Perl and Ada in one language. Neat! Guido wouldn't be happy,
though. You know there should only be one obvious way to do it, don't
you? :-)

David


-- 

David Trudgett
http://www.zeta.org.au/~wpower/

Reality is 20% real and 80% made up stuff in your head.
But I'm not sure about the 20%.
From: André Thieme
Subject: Re: Abuse of defvar??
Date: 
Message-ID: <d2ri2m$s1i$1@ulric.tng.de>
David Trudgett schrieb:

> To call the first requires (for example): (funcall hex-char 12)
> To call the other requires only: (hex-char 12)

You have probably seen the other answers (if not take a close look to 
Kents post).
I would like to add one possible idea: the person who has done it over 
defvar might need very often the function object for his program. So 
instead of writing 50 times (function hex-char) or #'hex-char the author 
can simply say HEX-CHAR. For some reason the author might not be 
interested in really calling this function very often. *shrug*


Andr�
--
From: David Trudgett
Subject: Re: Abuse of defvar??
Date: 
Message-ID: <m33bu6unbk.fsf@rr.trudgett>
Andr� Thieme <······························@justmail.de> writes:

> David Trudgett schrieb:
>
>> To call the first requires (for example): (funcall hex-char 12)
>> To call the other requires only: (hex-char 12)
>
> You have probably seen the other answers (if not take a close look to
> Kents post).
> I would like to add one possible idea: the person who has done it over
> defvar might need very often the function object for his program. So
> instead of writing 50 times (function hex-char) or #'hex-char the
> author can simply say HEX-CHAR. For some reason the author might not
> be interested in really calling this function very often. *shrug*

Interesting idea, but no. HEX-CHAR only gets used in one spot. The
author may have picked up the style from Emacs programming perhaps, as
someone else has suggested. I don't think there's really any important
reason for it in this case.

David



-- 

David Trudgett
http://www.zeta.org.au/~wpower/

Reality is 20% real and 80% made up stuff in your head.
But I'm not sure about the 20%.