From: Roy Leonard
Subject: Newbie RFC: A utility macro
Date: 
Message-ID: <918eee97.0409110821.5c51b217@posting.google.com>
Hello! I recently thought up a macro that seems (to me) interesting.

(defmacro fsetf (symbol function)
  `(setf (symbol-function ,symbol) ,function))

As an example of its use, in the spirit of Paul Graham:

(defun make-adder (sym &optional (reset-sym (gensym)))
  (let ((counter 0))
    (fsetf sym (lambda (&optional (increment 1))
                (incf counter increment)))
    (fsetf reset-sym (lambda (&optional (reset-val 0))
                (setf counter reset-val)))))

CL-USER> (make-adder 'foo 'bar)
#<CLOSURE :LAMBDA (&OPTIONAL (RESET-VAL 0)) (SETF COUNTER RESET-VAL)>
CL-USER> (foo)
1
CL-USER> (foo 5)
6
CL-USER> (bar)
0
CL-USER> (foo)
1

Any comments/suggestions?

From: Vassil Nikolov
Subject: Re: Newbie RFC: A utility macro
Date: 
Message-ID: <lzsm9o68ph.fsf@janus.vassil.nikolov.names>
···········@gmail.com (Roy Leonard) writes:

> Hello! I recently thought up a macro that seems (to me) interesting.
>
> (defmacro fsetf (symbol function)
>   `(setf (symbol-function ,symbol) ,function))


  That's the essence of what DEFUN does...


> As an example of its use, in the spirit of Paul Graham:
>
> (defun make-adder (sym &optional (reset-sym (gensym)))
>   (let ((counter 0))
>     (fsetf sym (lambda (&optional (increment 1))
>                 (incf counter increment)))
>     (fsetf reset-sym (lambda (&optional (reset-val 0))
>                 (setf counter reset-val)))))


  You can nest DEFUN forms in a LET form, and the functions defined by
  the former will close over the lexical variables introduced by the
  latter.


  ---Vassil.


-- 
Vassil Nikolov <········@poboxes.com>

Hollerith's Law of Docstrings: Everything can be summarized in 72 bytes.
From: Roy Leonard
Subject: Re: Newbie RFC: A utility macro
Date: 
Message-ID: <918eee97.0409111702.3868b2f1@posting.google.com>
Vassil Nikolov <········@poboxes.com> wrote in message 
> > (defmacro fsetf (symbol function)
> >   `(setf (symbol-function ,symbol) ,function))
>
>   That's the essence of what DEFUN does...

Aye, but to express:

> (fsetf 'foo #'+)

with DEFUN, one would have to:

> (defun foo (&rest args)
    (apply #'+ args))

- Actually, I don't like how fsetf requires a quoted first symbol, and
a sharp-quoted second function. Butchanging fsetf to:

(defmacro fsetf (symbol function)
  `(setf (symbol-function ,symbol) (symbol-function ,function)))

would make (fsetf 'foo (lambda (x) (+ x x))) illegal.

True, that wouldn't be an issue if we are using it like DEFUN, but if
we're dealing with functions that return functions, and assigning them
to symbols, we might have trouble.

>   You can nest DEFUN forms in a LET form, and the functions defined by
>   the former will close over the lexical variables introduced by the
>   latter.

So you're saying that:

(defmacro make-adder (sym &optional (reset-sym (gensym)))
  `(let ((counter 0))
    (defun ,sym (&optional (increment 1))
      (incf counter increment))
    (defun ,reset-sym (&optional (reset-val 0))
      (setf counter reset-val))))

would work just as well? (and it would have to be called as:

>(make-adder foo bar)

-with no symbol quoting, naturally. :-)
From: Vassil Nikolov
Subject: Re: Newbie RFC: A utility macro
Date: 
Message-ID: <lzk6v05gnv.fsf@janus.vassil.nikolov.names>
···········@gmail.com (Roy Leonard) writes:

> Vassil Nikolov <········@poboxes.com> wrote in message 
>> > (defmacro fsetf (symbol function)
>> >   `(setf (symbol-function ,symbol) ,function))
>>
>>   That's the essence of what DEFUN does...
>
> Aye, but to express:
>
>> (fsetf 'foo #'+)
>
> with DEFUN, one would have to:
>
>> (defun foo (&rest args)
>     (apply #'+ args))


  But how is that _essentially_ different?

  After all, there are a number of other things DEFUN does (like
  wrapping the body in a block, or SETF of DOCUMENTATION), or can
  reasonably be expected to do (like warning if a function is
  redefined in a different file, and many others that are of much
  practical importance), but they are not the essence of what DEFUN
  does.

  I suppose this is my opinion about FSETF: as an abstraction, it is
  not sufficiently different from DEFUN, and as syntactic sugar for
  its expansion, well, I don't think it adds that much value.


> [...]
>>   You can nest DEFUN forms in a LET form, and the functions defined by
>>   the former will close over the lexical variables introduced by the
>>   latter.
>
> So you're saying that:
>
> (defmacro make-adder (sym &optional (reset-sym (gensym)))
>   `(let ((counter 0))
>     (defun ,sym (&optional (increment 1))
>       (incf counter increment))
>     (defun ,reset-sym (&optional (reset-val 0))
>       (setf counter reset-val))))
>
> would work just as well? (and it would have to be called as:
>
>>(make-adder foo bar)
>
> -with no symbol quoting, naturally. :-)


  Yes, that's what I am saying, modulo some technical differences such
  that the original definition returned the second function object,
  and this returns the second function name (which may actually be
  better since, as Peter Seibel noted, that second name would be
  lost).  Also, I would call that macro DEFINE-ADDER or something like
  that.

  Of course, this may be more suitable for interactive exploration
  than for library code, since the DEFUN forms would not be at top
  level [1].  I can't say for sure what the best API for a library
  version of MAKE-ADDER would be, but I suppose it might be a function
  that just returns two functions, without any attempts to associate
  the latter with symbols.


  [1] Yes, it is quite legal to have a non-top-level DEFUN from, but I
  don't think this case is a good enough reason to do it.


  ---Vassil.

-- 
Vassil Nikolov <········@poboxes.com>

Hollerith's Law of Docstrings: Everything can be summarized in 72 bytes.
From: Kenny Tilton
Subject: Re: Newbie RFC: A utility macro
Date: 
Message-ID: <XaH0d.115835$4h7.18522308@twister.nyc.rr.com>
Roy Leonard wrote:

> Hello! I recently thought up a macro that seems (to me) interesting.
> 
> (defmacro fsetf (symbol function)
>   `(setf (symbol-function ,symbol) ,function))
> 
> As an example of its use, in the spirit of Paul Graham:
> 
> (defun make-adder (sym &optional (reset-sym (gensym)))
>   (let ((counter 0))
>     (fsetf sym (lambda (&optional (increment 1))
>                 (incf counter increment)))
>     (fsetf reset-sym (lambda (&optional (reset-val 0))
>                 (setf counter reset-val)))))
> 
> CL-USER> (make-adder 'foo 'bar)
> #<CLOSURE :LAMBDA (&OPTIONAL (RESET-VAL 0)) (SETF COUNTER RESET-VAL)>
> CL-USER> (foo)
> 1
> CL-USER> (foo 5)
> 6
> CL-USER> (bar)
> 0
> CL-USER> (foo)
> 1
> 
> Any comments/suggestions?

Comment: this seems to resist the idea of functions as first-class 
objects which can be passed around as data, stored in other structures 
in slots of any name, or bound to local variables of any name. And it's 
use disguises the fact that functions with potentially dynamic semantics 
are being called.

kt


-- 
Cells? Cello? Celtik?: http://www.common-lisp.net/project/cells/
Why Lisp? http://alu.cliki.net/RtL%20Highlight%20Film
From: Roy Leonard
Subject: Re: Newbie RFC: A utility macro
Date: 
Message-ID: <918eee97.0409112305.274b5c20@posting.google.com>
Kenny Tilton <·······@nyc.rr.com> wrote in message 
> Comment: this seems to resist the idea of functions as first-class 
> objects which can be passed around as data, stored in other structures 
> in slots of any name, or bound to local variables of any name. And it's 
> use disguises the fact that functions with potentially dynamic semantics 
> are being called.

So would you prefer:

(defun make-adder ()
  (let ((counter 0))
    (list (lambda (&optional (increment 1))
             (incf counter increment))
          (lambda (&optional (reset-val 0))
             (setf counter reset-val)))))

(substitute the list with a cons, vector, or your favourite data-structure:
(eg:

(defun make-hash-adder (hash-table key &optional 
                        (reset-key nil reset-key-p))
  (let ((counter 0))
    (setf (gethash key hash-table)
          (lambda (&optional (increment 1))
           (incf counter increment)))
    (when reset-key-p
      (setf (gethash reset-key hash-table)
            (lambda (&optional (reset-val 0))
              (setf counter reset-val))))))

))
From: Vassil Nikolov
Subject: Re: Newbie RFC: A utility macro
Date: 
Message-ID: <lzbrgb635m.fsf@janus.vassil.nikolov.names>
···········@gmail.com (Roy Leonard) writes:

> [...]
> (defun make-adder ()
>   (let ((counter 0))
>     (list (lambda (&optional (increment 1))
>              (incf counter increment))
>           (lambda (&optional (reset-val 0))
>              (setf counter reset-val)))))
>
> (substitute the list with a cons, vector,


  ...or return multiple values (with (VALUES #'(LAMBDA ...) #'(LAMBDA
  ...))), in which case it would be very easy for the caller to ignore
  the second function if they wish to do so.


> or your favourite data-structure:
> (eg:
>
> (defun make-hash-adder (hash-table key &optional 
>                         (reset-key nil reset-key-p))
>   (let ((counter 0))
>     (setf (gethash key hash-table)
>           (lambda (&optional (increment 1))
>            (incf counter increment)))
>     (when reset-key-p
>       (setf (gethash reset-key hash-table)
>             (lambda (&optional (reset-val 0))
>               (setf counter reset-val))))))


  That's really MAKE-ADDER-INTO (or MAKE-ADDER-INTO-HASH-TABLE, or
  something like that).  To make this analogous to the previous
  definition, this needs to make its own hash table.


  ---Vassil.


-- 
Vassil Nikolov <········@poboxes.com>

Hollerith's Law of Docstrings: Everything can be summarized in 72 bytes.
From: Kenny Tilton
Subject: Re: Newbie RFC: A utility macro
Date: 
Message-ID: <kU01d.34833$Ot3.33792@twister.nyc.rr.com>
Roy Leonard wrote:

> Kenny Tilton <·······@nyc.rr.com> wrote in message 
> 
>>Comment: this seems to resist the idea of functions as first-class 
>>objects which can be passed around as data, stored in other structures 
>>in slots of any name, or bound to local variables of any name. And it's 
>>use disguises the fact that functions with potentially dynamic semantics 
>>are being called.
> 
> 
> So would you prefer:
> 
> (defun make-adder ()
>   (let ((counter 0))
>     (list (lambda (&optional (increment 1))
>              (incf counter increment))
>           (lambda (&optional (reset-val 0))
>              (setf counter reset-val)))))

No, but the real point is letting an object be an object, not the 
mechanism by which a resetter is bundled with the incrementer. As for 
the latter, if I thought this kind of thing was going to become more and 
more elaborate as development continued, I would indeed do something 
such as the above and create an api by which the main function got 
invoked and reset or other auxiliary functions got invoked. If it was 
just a throway I would return one function with an optional argument to 
get the setf behavior instead of the incf behavior.

kenny

-- 
Cells? Cello? Celtik?: http://www.common-lisp.net/project/cells/
Why Lisp? http://alu.cliki.net/RtL%20Highlight%20Film
From: Peter Seibel
Subject: Re: Newbie RFC: A utility macro
Date: 
Message-ID: <m3wtz0h87g.fsf@javamonkey.com>
···········@gmail.com (Roy Leonard) writes:

> Hello! I recently thought up a macro that seems (to me) interesting.
>
> (defmacro fsetf (symbol function)
>   `(setf (symbol-function ,symbol) ,function))
>
> As an example of its use, in the spirit of Paul Graham:
>
> (defun make-adder (sym &optional (reset-sym (gensym)))
>   (let ((counter 0))
>     (fsetf sym (lambda (&optional (increment 1))
>                 (incf counter increment)))
>     (fsetf reset-sym (lambda (&optional (reset-val 0))
>                 (setf counter reset-val)))))
>
> CL-USER> (make-adder 'foo 'bar)
> #<CLOSURE :LAMBDA (&OPTIONAL (RESET-VAL 0)) (SETF COUNTER RESET-VAL)>
> CL-USER> (foo)
> 1
> CL-USER> (foo 5)
> 6
> CL-USER> (bar)
> 0
> CL-USER> (foo)
> 1
>
> Any comments/suggestions?

Uh, are you sure you want the default name of your reset function to
be a symbol you have no way of getting at again?

-Peter

-- 
Peter Seibel                                      ·····@javamonkey.com

         Lisp is the red pill. -- John Fraser, comp.lang.lisp
From: Coby Beck
Subject: Re: Newbie RFC: A utility macro
Date: 
Message-ID: <fDK0d.135815$A8.85168@edtnps89>
"Peter Seibel" <·····@javamonkey.com> wrote in message
···················@javamonkey.com...
> ···········@gmail.com (Roy Leonard) writes:
>
> > Hello! I recently thought up a macro that seems (to me) interesting.
> >
> > (defmacro fsetf (symbol function)
> >   `(setf (symbol-function ,symbol) ,function))
> >
> > As an example of its use, in the spirit of Paul Graham:
> >
> > (defun make-adder (sym &optional (reset-sym (gensym)))
> >   (let ((counter 0))
> >     (fsetf sym (lambda (&optional (increment 1))
> >                 (incf counter increment)))
> >     (fsetf reset-sym (lambda (&optional (reset-val 0))
> >                 (setf counter reset-val)))))
> >
> > CL-USER> (make-adder 'foo 'bar)
> > #<CLOSURE :LAMBDA (&OPTIONAL (RESET-VAL 0)) (SETF COUNTER RESET-VAL)>
> > CL-USER> (foo)
> > 1
> > CL-USER> (foo 5)
> > 6
> > CL-USER> (bar)
> > 0
> > CL-USER> (foo)
> > 1
> >
> > Any comments/suggestions?
>
> Uh, are you sure you want the default name of your reset function to
> be a symbol you have no way of getting at again?

Good catch, I didn't notice that.

Maybe the OP would prefer:
(defun make-adder (sym &optional (reset-sym (intern (format nil "RESET-~A"
sym))))

the usual caveats about readtable case apply as well as advice to force the
user of the macro to supply their own symbol.

-- 
Coby Beck
(remove #\Space "coby 101 @ big pond . com")
From: Peter Seibel
Subject: Re: Newbie RFC: A utility macro
Date: 
Message-ID: <m3sm9o7816.fsf@javamonkey.com>
"Coby Beck" <·····@mercury.bc.ca> writes:

> "Peter Seibel" <·····@javamonkey.com> wrote in message
> ···················@javamonkey.com...
>> ···········@gmail.com (Roy Leonard) writes:
>>
>> > Hello! I recently thought up a macro that seems (to me) interesting.
>> >
>> > (defmacro fsetf (symbol function)
>> >   `(setf (symbol-function ,symbol) ,function))
>> >
>> > As an example of its use, in the spirit of Paul Graham:
>> >
>> > (defun make-adder (sym &optional (reset-sym (gensym)))
>> >   (let ((counter 0))
>> >     (fsetf sym (lambda (&optional (increment 1))
>> >                 (incf counter increment)))
>> >     (fsetf reset-sym (lambda (&optional (reset-val 0))
>> >                 (setf counter reset-val)))))
>> >
>> > CL-USER> (make-adder 'foo 'bar)
>> > #<CLOSURE :LAMBDA (&OPTIONAL (RESET-VAL 0)) (SETF COUNTER RESET-VAL)>
>> > CL-USER> (foo)
>> > 1
>> > CL-USER> (foo 5)
>> > 6
>> > CL-USER> (bar)
>> > 0
>> > CL-USER> (foo)
>> > 1
>> >
>> > Any comments/suggestions?
>>
>> Uh, are you sure you want the default name of your reset function to
>> be a symbol you have no way of getting at again?
>
> Good catch, I didn't notice that.
>
> Maybe the OP would prefer:
> (defun make-adder (sym &optional (reset-sym (intern (format nil "RESET-~A"
> sym))))
>
> the usual caveats about readtable case apply as well as advice to force the
> user of the macro to supply their own symbol.

And the discussion of whether that shouldn't be:

  (intern (format nil "RESET-~A" sym) (symbol-package sym))

Which leads, of course, right back to the advice to force the user of the
macro to supply their own symbol.

Hmmmm. How about this as a fairly safe way to make one symbol name
from another:

  (defun make-related-symbol (symbol &key prefix suffix (package (symbol-package symbol)))
    (multiple-value-bind (symbol status)
        (intern
         (format nil ··@[~a-~]···@[-~a~]" 
                 (read-from-string (princ-to-string prefix))
                 symbol
                 (read-from-string (princ-to-string suffix)))
         package)
      (when status
        (warn "Constructed symbol ~a already exists: ~a" symbol status))
      symbol))

-Peter

-- 
Peter Seibel                                      ·····@javamonkey.com

         Lisp is the red pill. -- John Fraser, comp.lang.lisp
From: Vassil Nikolov
Subject: Re: Newbie RFC: A utility macro
Date: 
Message-ID: <lzoekc5i3e.fsf@janus.vassil.nikolov.names>
Peter Seibel <·····@javamonkey.com> writes:

> [...]
> Hmmmm. How about this as a fairly safe way to make one symbol name
> from another:
>
>   (defun make-related-symbol (symbol &key prefix suffix (package (symbol-package symbol)))
>     (multiple-value-bind (symbol status)
>         (intern
>          (format nil ··@[~a-~]···@[-~a~]" 
>                  (read-from-string (princ-to-string prefix))
>                  symbol
>                  (read-from-string (princ-to-string suffix)))
>          package)
>       (when status
>         (warn "Constructed symbol ~a already exists: ~a" symbol status))
>       symbol))


  Why do you do (READ-FROM-STRING (PRINC-TO-STRING PREFIX)) (and the
  same for the suffix)?  The above definition doesn't really say what
  the meaning of the prefix and suffix parameters is, but do we want
  to treat (... :PREFIX "NIL") the same as (... :PREFIX NIL), for
  example?  Or what do we do with string affixes that are unreadable,
  like (... :PREFIX "(" :SUFFIX ")")?  And by the way, forcing a
  separator hyphen on the caller is probably not so nice (compare
  GENSYM).


  (Otherwise, IMHO, it's better to simply make the caller supply the
  symbols, rather than try to compute them.  Of course, this is a good
  exercise about INTERN etc.)


  ---Vassil.


-- 
Vassil Nikolov <········@poboxes.com>

Hollerith's Law of Docstrings: Everything can be summarized in 72 bytes.
From: Roy Leonard
Subject: Re: Newbie RFC: A utility macro
Date: 
Message-ID: <918eee97.0409112248.8ce107f@posting.google.com>
> > > Uh, are you sure you want the default name of your reset function to
> > > be a symbol you have no way of getting at again?
> > >
> > > -Peter
>
> > From: Coby Beck:
> >
> > Maybe the OP would prefer:
> > (defun make-adder (sym &optional (reset-sym (intern (format nil "RESET-~A"
> > sym))))
> >
> > the usual caveats about readtable case apply as well as advice to force the
> > user of the macro to supply their own symbol.
>
>  (Otherwise, IMHO, it's better to simply make the caller supply the
>  symbols, rather than try to compute them.  Of course, this is a good
>  exercise about INTERN etc.)
>
>
>  ---Vassil.

Actually, I _did_ intend to have that other function lapse into
oblivion. (Or at least irretrevability)

The function is MAKE-COUNTER, so I wanted to leave it open to the user
to simply make a counter, and not make a reseter. Technically, if they
didn't supply a second symbol, I don't really need to make the second
setf.

I didn't at the time, but I could have:

(defun make-adder (sym &optional (reset-sym nil reset-sym-p))
  (let ((counter 0))
    (fsetf sym (lambda (&optional (increment 1))
                (incf counter increment)))
    (when reset-sym-p
      (fsetf reset-sym (lambda (&optional (reset-val 0))
                  (setf counter reset-val))))))

which would probably be clearer.

I have heard that it's a "bad idea" to intern any symbols in a
function that were not requested - they can get "leaky" (Or that's
what I read in the Gigamonkeys book - though that section was about
macros, I figure it could still apply :-) )
From: Vassil Nikolov
Subject: Re: Newbie RFC: A utility macro
Date: 
Message-ID: <lzfz5n63li.fsf@janus.vassil.nikolov.names>
···········@gmail.com (Roy Leonard) writes:

> [...]
> Actually, I _did_ intend to have that other function lapse into
> oblivion. (Or at least irretrevability)
>
> The function is MAKE-COUNTER, so I wanted to leave it open to the user
> to simply make a counter, and not make a reseter. Technically, if they
> didn't supply a second symbol, I don't really need to make the second
> setf.
>
> I didn't at the time, but I could have:
>
> (defun make-adder (sym &optional (reset-sym nil reset-sym-p))
>   (let ((counter 0))
>     (fsetf sym (lambda (&optional (increment 1))
>                 (incf counter increment)))
>     (when reset-sym-p
>       (fsetf reset-sym (lambda (&optional (reset-val 0))
>                   (setf counter reset-val))))))
>
> which would probably be clearer.


  Yes, that is much clearer.

  By the way, to repeat my point about naming, this function should be
  called something like MAKE-NAMED-ADDER (MAKE-ADDER being a name for
  the function that just makes and returns the closures, without
  associating them with any symbols).  Also, it might be better to
  make it into a macro (DEFINE-ADDER), though it's hard to say for
  sure without a broader context of where and how it is going to be
  used.  (And in a simple exercise there is no such context, of
  course.)


> I have heard that it's a "bad idea" to intern any symbols in a
> function that were not requested - they can get "leaky" (Or that's
> what I read in the Gigamonkeys book - though that section was about
> macros, I figure it could still apply :-) )


  I believe that polluting the name space, and putting names in the
  wrong name space, are even bigger worries than a leak.  (At least if
  this is about a memory leak from excessive internment of symbols,
  which I'm guessing that it refers to.)


  ---Vassil.


-- 
Vassil Nikolov <········@poboxes.com>

Hollerith's Law of Docstrings: Everything can be summarized in 72 bytes.
From: Peter Seibel
Subject: Re: Newbie RFC: A utility macro
Date: 
Message-ID: <m33c1n70ol.fsf@javamonkey.com>
Vassil Nikolov <········@poboxes.com> writes:

> Peter Seibel <·····@javamonkey.com> writes:
>
>> [...]
>> Hmmmm. How about this as a fairly safe way to make one symbol name
>> from another:
>>
>>   (defun make-related-symbol (symbol &key prefix suffix (package (symbol-package symbol)))
>>     (multiple-value-bind (symbol status)
>>         (intern
>>          (format nil ··@[~a-~]···@[-~a~]" 
>>                  (read-from-string (princ-to-string prefix))
>>                  symbol
>>                  (read-from-string (princ-to-string suffix)))
>>          package)
>>       (when status
>>         (warn "Constructed symbol ~a already exists: ~a" symbol status))
>>       symbol))
>
>
>   Why do you do (READ-FROM-STRING (PRINC-TO-STRING PREFIX)) (and the
>   same for the suffix)?  The above definition doesn't really say what
>   the meaning of the prefix and suffix parameters is, but do we want
>   to treat (... :PREFIX "NIL") the same as (... :PREFIX NIL), for
>   example?  

Yeah, the NIL problem is a good point. As far as reading back, the
point was to try deal with the readtable case issue. If you passed
strings for the prefix and suffix when they were read back the case
would be converted according to the readtable case. Though it's not
clear this does the right thing if you pass a symbol. Maybe slightly
better would be something like this:

  (defun make-related-symbol (symbol &key 
                              prefix
                              suffix
                              (package (symbol-package symbol)))
    (flet ((thing-to-name (thing)
             (typecase thing
               (null thing)
               (symbol (symbol-name thing))
               (t (read-from-string (princ-to-string thing))))))
      (multiple-value-bind (symbol status)
        (intern
         (format nil ··@[~a-~]···@[-~a~]"
                 (thing-to-name prefix)
                 symbol
                 (thing-to-name suffix))
         package)
      (when status
        (warn "Constructed symbol ~a already exists: ~a" symbol status))
      symbol)))


> Or what do we do with string affixes that are unreadable, like (...
> :PREFIX "(" :SUFFIX ")")? And by the way, forcing a separator hyphen
> on the caller is probably not so nice (compare GENSYM).

Sure. But the point--which of course I didn't state--was to provide a
way to easily handle the common case where the prefixes and suffixes
could themselves be symbols.. Though with the new version you could
make a name with unredable prefix or suffixes:

  (make-related-symbol 'foo :prefix :|(| :suffix 11)  ==> |(-FOO-11|

And of course if you wanted to make the separator parameterizable you
could do that too.

-Peter


-- 
Peter Seibel                                      ·····@javamonkey.com

         Lisp is the red pill. -- John Fraser, comp.lang.lisp
From: Vassil Nikolov
Subject: Re: Newbie RFC: A utility macro
Date: 
Message-ID: <lzd60r6op5.fsf@janus.vassil.nikolov.names>
Peter Seibel <·····@javamonkey.com> writes:

> Vassil Nikolov <········@poboxes.com> writes:
> [...]
>>   Why do you do (READ-FROM-STRING (PRINC-TO-STRING PREFIX)) (and the
>>   same for the suffix)?  The above definition doesn't really say what
>>   the meaning of the prefix and suffix parameters is, but do we want
>>   to treat (... :PREFIX "NIL") the same as (... :PREFIX NIL), for
>>   example?  
>
> Yeah, the NIL problem is a good point. As far as reading back, the
> point was to try deal with the readtable case issue. If you passed
> strings for the prefix and suffix when they were read back the case
> would be converted according to the readtable case.


  Well, I believe this is better left to the caller to sort out
  (like GENSYM does).


> Though it's not
> clear this does the right thing if you pass a symbol. Maybe slightly
> better would be something like this:
>
>   (defun make-related-symbol (symbol &key 
>                               prefix
>                               suffix
>                               (package (symbol-package symbol)))
>     (flet ((thing-to-name (thing)
>              (typecase thing
>                (null thing)
>                (symbol (symbol-name thing))
>                (t (read-from-string (princ-to-string thing))))))
>       (multiple-value-bind (symbol status)
>         (intern
>          (format nil ··@[~a-~]···@[-~a~]"
>                  (thing-to-name prefix)
>                  symbol
>                  (thing-to-name suffix))
>          package)
>       (when status
>         (warn "Constructed symbol ~a already exists: ~a" symbol status))
>       symbol)))
>
>
>> Or what do we do with string affixes that are unreadable, like (...
>> :PREFIX "(" :SUFFIX ")")? And by the way, forcing a separator hyphen
>> on the caller is probably not so nice (compare GENSYM).
>
> Sure. But the point--which of course I didn't state--was to provide a
> way to easily handle the common case where the prefixes and suffixes
> could themselves be symbols.. Though with the new version you could
> make a name with unredable prefix or suffixes:
>
>   (make-related-symbol 'foo :prefix :|(| :suffix 11)  ==> |(-FOO-11|


  Yes, but a call with :PREFIX "(" would still be an error...

  Besides, I am not sure we really want to allow arbitrary values (not
  just symbols and strings) supplied as affixes.  I think I'd rather
  have an ETYPECASE, with cases for NULL, SYMBOL, and STRING.


> And of course if you wanted to make the separator parameterizable you
> could do that too.


  True, but that's yet another piece of complexity...  I suppose if
  this is to tackle all of these issues in the right way, it would
  have to be somewhat overengineered, and I don't think it is worth
  it (again, unless this is an exercise).  My pedantic 0.02...


  ---Vassil.


-- 
Vassil Nikolov <········@poboxes.com>

Hollerith's Law of Docstrings: Everything can be summarized in 72 bytes.
From: Duane Rettig
Subject: Re: Newbie RFC: A utility macro
Date: 
Message-ID: <4d60sysgb.fsf@franz.com>
···········@gmail.com (Roy Leonard) writes:

> Hello! I recently thought up a macro that seems (to me) interesting.
> 
> (defmacro fsetf (symbol function)
>   `(setf (symbol-function ,symbol) ,function))
> 
> As an example of its use, in the spirit of Paul Graham:
> 
> (defun make-adder (sym &optional (reset-sym (gensym)))
>   (let ((counter 0))
>     (fsetf sym (lambda (&optional (increment 1))
>                 (incf counter increment)))
>     (fsetf reset-sym (lambda (&optional (reset-val 0))
>                 (setf counter reset-val)))))
> 
> CL-USER> (make-adder 'foo 'bar)
> #<CLOSURE :LAMBDA (&OPTIONAL (RESET-VAL 0)) (SETF COUNTER RESET-VAL)>
> CL-USER> (foo)
> 1
> CL-USER> (foo 5)
> 6
> CL-USER> (bar)
> 0
> CL-USER> (foo)
> 1
> 
> Any comments/suggestions?

This macro has a subset of functionality already provided by
cl:fdefinition and its inverse.  Why not use it instead?

Extra credit for finding the superset functionality provided
by (setf fdefinition).  A hint is in the immediately preceding
sentence.

-- 
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   
From: Vassil Nikolov
Subject: Re: Newbie RFC: A utility macro
Date: 
Message-ID: <lz8ybf6oh3.fsf@janus.vassil.nikolov.names>
Duane Rettig <·····@franz.com> writes:

> [...]
> Extra credit for finding the superset functionality provided
> by (setf fdefinition).  A hint is in the immediately preceding
> sentence.


  As an aside, I notice that (SETF FDEFINITION) is explicitly
  specified not to work for special operators, but I couldn't find
  such a restriction for DEFUN.  If I haven't missed it, is that just
  a trivial omission, rather than a deeper difference?

  ---Vassil.


-- 
Vassil Nikolov <········@poboxes.com>

Hollerith's Law of Docstrings: Everything can be summarized in 72 bytes.
From: Duane Rettig
Subject: Re: Newbie RFC: A utility macro
Date: 
Message-ID: <4llfevjf6.fsf@franz.com>
Vassil Nikolov <········@poboxes.com> writes:

> Duane Rettig <·····@franz.com> writes:
> 
> > [...]
> > Extra credit for finding the superset functionality provided
> > by (setf fdefinition).  A hint is in the immediately preceding
> > sentence.
> 
> 
>   As an aside, I notice that (SETF FDEFINITION) is explicitly
>   specified not to work for special operators, but I couldn't find
>   such a restriction for DEFUN.

It's there.  Since there are three types of fdefinition: function,
macro, and special operator, it suffices to either name the exclusion,
as does fdefinition's description, or else to name the acceptable
circumstances, as the first paragraph in defun's Description section
covers.

>  If I haven't missed it, is that just
>   a trivial omission, rather than a deeper difference?

I'd call it a different similarity.

-- 
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   
From: Vassil Nikolov
Subject: Re: Newbie RFC: A utility macro
Date: 
Message-ID: <lzhdq14ogi.fsf@janus.vassil.nikolov.names>
Duane Rettig <·····@franz.com> writes:

> Vassil Nikolov <········@poboxes.com> writes:
> [...]
>>   As an aside, I notice that (SETF FDEFINITION) is explicitly
>>   specified not to work for special operators, but I couldn't find
>>   such a restriction for DEFUN.
>
> It's there.  Since there are three types of fdefinition: function,
> macro, and special operator, it suffices to either name the exclusion,
> as does fdefinition's description, or else to name the acceptable
> circumstances, as the first paragraph in defun's Description section
> covers.


  Thanks.  I should know better than to only notice exclusions...


  ---Vassil.


-- 
Vassil Nikolov <········@poboxes.com>

Hollerith's Law of Docstrings: Everything can be summarized in 72 bytes.
From: ·········@random-state.net
Subject: Re: Newbie RFC: A utility macro
Date: 
Message-ID: <ci3da3$8t0dq$1@midnight.cs.hut.fi>
Vassil Nikolov <········@poboxes.com> wrote:

>   As an aside, I notice that (SETF FDEFINITION) is explicitly
>   specified not to work for special operators, but I couldn't find
>   such a restriction for DEFUN.  If I haven't missed it, is that just
>   a trivial omission, rather than a deeper difference?

It's implied by 11.1.2.1.2.

Cheers,

 -- Nikodemus                   "Not as clumsy or random as a C++ or Java. 
                             An elegant weapon for a more civilized time."
From: Duane Rettig
Subject: Re: Newbie RFC: A utility macro
Date: 
Message-ID: <4y8jefy3t.fsf@franz.com>
·········@random-state.net writes:

> Vassil Nikolov <········@poboxes.com> wrote:
> 
> >   As an aside, I notice that (SETF FDEFINITION) is explicitly
> >   specified not to work for special operators, but I couldn't find
> >   such a restriction for DEFUN.  If I haven't missed it, is that just
> >   a trivial omission, rather than a deeper difference?
> 
> It's implied by 11.1.2.1.2.

This was the first place I went to look as well, but it is not as
strong as the more direct places.  Of course, it does cover all
standard special operators, which of course are defined in the
Common Lisp package.  And if an implementor also implements a
standard macro as a special operator (and includes the required
macroexpansion) then it covers that situation.

However, since this section only describes limitations on the
Common Lisp package, it doesn't cover any special operators that
an implementor chooses to implement in a non-standard package.
So I abandoned this section as being redundant (regarding special
operator redefinition) in my explanation to Vassil.  The restrictions
are adequate in the fdefinition and defun descriptions without
resorting to this section.

-- 
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