From: Philippe Lorin
Subject: how to generate function names
Date: 
Message-ID: <42c65ac4$0$3721$626a14ce@news.free.fr>
I want to automate the writing of a few functions. My problem is 
generating their names. For instance, I want to be able to write:

(defun-my-functions 'type-a)
(defun-my-functions 'type-b)

and get something like:

(defun function1-type-a (...) ...)
(defun function2-type-a (...) ...)
(defun function1-type-b (...) ...)
(defun function2-type-b (...) ...)

but I have no idea how to generate the symbols "function1-type-a" etc. I 
tried "make-symbol", but it doesn't work as I'd expect; e.g. after 
evaluating this:

(set (make-symbol "x") 12)

I would expect the expression:

x

to be evaluated as 12, but all I get is an unbound variable error. 
Still, (symbol-name (make-symbol "x")) returns "x" as expected.

What is wrong with my expectations, and how can I get the result I want?

From: Rainer Joswig
Subject: Re: how to generate function names
Date: 
Message-ID: <BEEC2B91.EFAA%joswig@lisp.de>
Am 02.07.2005 11:14 Uhr schrieb "Philippe Lorin" unter
<············@gmail.com> in ························@news.free.fr:

> I want to automate the writing of a few functions. My problem is
> generating their names. For instance, I want to be able to write:
> 
> (defun-my-functions 'type-a)
> (defun-my-functions 'type-b)
> 
> and get something like:
> 
> (defun function1-type-a (...) ...)
> (defun function2-type-a (...) ...)
> (defun function1-type-b (...) ...)
> (defun function2-type-b (...) ...)
> 
> but I have no idea how to generate the symbols "function1-type-a" etc. I
> tried "make-symbol", but it doesn't work as I'd expect; e.g. after
> evaluating this:
> 
> (set (make-symbol "x") 12)
> 
> I would expect the expression:
> 
> x
> 
> to be evaluated as 12, but all I get is an unbound variable error.
> Still, (symbol-name (make-symbol "x")) returns "x" as expected.
> 
> What is wrong with my expectations, and how can I get the result I want?

Symbol names are uppercased when read by default.

Try (symbol-name 'x)  -> "X"

MAKE-SYMBOL does not intern a symbol into a package. Use INTERN.

(intern "X")

So you want: (set (intern "X") 3) and then you can evaluate x to 3.

Note that there is also a function STRING-UPCASE . (STRING-UPCASE "x") ->
"X"
From: Kalle Olavi Niemitalo
Subject: Re: how to generate function names
Date: 
Message-ID: <87mzp5pedc.fsf@Astalo.kon.iki.fi>
Rainer Joswig <······@lisp.de> writes:

> So you want: (set (intern "X") 3) and then you can evaluate x to 3.

However, SET is deprecated, so it might be better to write this as:
(setf (symbol-value (intern "X")) 3)
From: Robert Uhl
Subject: Re: how to generate function names
Date: 
Message-ID: <m3oe9lxfmy.fsf@4dv.net>
Philippe Lorin <············@gmail.com> writes:
>
> but I have no idea how to generate the symbols "function1-type-a"
> etc. I tried "make-symbol", but it doesn't work as I'd expect;
> e.g. after evaluating this:
>
> (set (make-symbol "x") 12)

In my yet-unreleased Tasting Notes, at one point I used INTERN to create
symbols.  I now only use it to create keywords:

  (defun make-keyword (string)
    (declare (string string))
    (intern (string-upcase string) "KEYWORD"))

I had similar trouble as yours with MAKE-SYMBOL, which I attribute to
ignorance on my own part.

-- 
Robert Uhl <http://public.xdi.org/=ruhl>
The law, in its majestic equality, forbids the rich as well as the
poor to sleep under bridges, to beg in the streets, and to steal
bread.                                          --Anatole France
From: Alan Crowe
Subject: Re: how to generate function names
Date: 
Message-ID: <86fyuxbbm4.fsf@cawtech.freeserve.co.uk>
Philippe Lorin wants to know what is wrong with this 
expectation of his:

	I want to automate the writing of a few functions. My problem is 
	generating their names. For instance, I want to be able to write:

	(defun-my-functions 'type-a)
	(defun-my-functions 'type-b)

	and get something like:

	(defun function1-type-a (...) ...)
	(defun function2-type-a (...) ...)
	(defun function1-type-b (...) ...)
	(defun function2-type-b (...) ...)

	but I have no idea how to generate the symbols "function1-type-a" etc. I 
	tried "make-symbol", but it doesn't work as I'd expect; e.g. after 
	evaluating this:

	(set (make-symbol "x") 12)

	I would expect the expression:

	x

	to be evaluated as 12, but all I get is an unbound variable error. 
 	Still, (symbol-name (make-symbol "x")) returns "x" as expected.

	What is wrong with my expectations, and how can I get the result I want?

The key issue is that variables and functions are named by
symbols, and not by strings. That is, a variable name is a
data structure in memory of a different kind from the
vector of characters that you are expecting.

The symbols, which name variables and functions, do
themselves have names, and the names of symbols are strings
= vectors of characters.

So your ordinary interactions at the REPL involve a two step
process.

First you press keys to type in characters. They name a
symbol via the package system. The symbol names a
variable. The variable has a value and the REPL prints it.

Before you decide that I'm smoking crack, try this:

* (defvar my-variable-name (make-symbol "x")) => MY-VARIABLE-NAME

* (set my-variable-name 23) => 23
      ^
      |
      `-- spot the absence of f or q 

* (eval my-variable-name) => 23

* my-variable-name => #:|x|

and also this


* (defvar my-function-name (make-symbol "f")) => MY-FUNCTION-NAME

* (setf (symbol-function my-function-name)
	(lambda (x) (* x x)))
=> #<Interpreted Function (LAMBDA (X) (* X X)) {4802C101}>

* (eval (list my-function-name 7)) => 49

So what is the point of this two step process?

Notice that in machine-written code it is a one step
process. It is fun to anthropomorphise macros and to talk
about them typing in code for us. In mundane languages that
is too close to the truth. A code generator for C writes
characters to a file. The lexical analyser has to read the
file character by character to turn variable names back into
tokens.

Common Lisp skips this round trip. When you define a code
generator with defmacro it sticks strictly at the symbol
level. It never descends to manipulating characters.

A terrible danger with code generators is the possibility of
a name clash between names you type in and internal names
within the machine-written code. The design of CL eliminates
this danger. One uses make-symbol or gensym to create the
the symbols used as variable names. They are not registered
with any package (we say they are uninterned). They cannot
clash with any name you type in because no string->symbol
translation has been set up that could be used to refer to
them.

From the point of view of printing the symbols, for example
for human inspection of machine written code, the uninterned
symbols symbols have the names given to them by make-symbol
or gensym. Choose those names wisely, you may have to debug
machine written code.

When it comes to typing symbols in at the keyboard, this
works via the package system. There must at least one
package with a mapping from the target symbols name to the
target symbol. The effect of being uninterned on keyboard
entry is as if the symbol doesn't have a name and cannot be
typed in.

This is Heavenly. What could be better than having one of
the worst kinds of bugs eliminated by the architecture of
the language?

One the other hand one has

* (set (make-symbol "X") 12) => 12
* X
Error in KERNEL::UNBOUND-SYMBOL-ERROR-HANDLER:  the variable X is unbound

You are completely stuck. Typing in X merely causes the
system to create a distinct symbol, also called X and
interned in the current package. The second symbol is easily
refered to. Just type in X and the system will successfully
look up the string "X" in the current package and find the
second symbol. The first X is lost and gone for ever.
X is a popular name for a symbol. In the REPL I'm sitting in
front of just now (find-all-symbols "X") returns a list of
14 symbols, and that is just the interned symbols.

Your basic decision is which of the names

function1-type-a 
function2-type-a
function1-type-b 
function2-type-b

are to be private names, the inner secrets of the machine
written code, and which names are the interface to the manually
entered code?

Names that you plan on typing in have to be registered with
a package. Usually this is very easy. Just use intern
instead of make-symbol. INTERN looks in the variable
*package* to see which package to use. If you would prefer
to refer to the symbol via a different package, use the
optional second argument to specify the package.

Watch out for INTERN's second return value. If it is not nil
that means that there is already a symbol of that name
registered with that particular package. INTERN assumes that
you are cool with using the old symbol, which sets the stage
for a bug when you stomp on the stuff the old symbol was
naming.

Alan Crowe
Edinbrugh
Scotland
From: Peter Lewerin
Subject: Re: how to generate function names
Date: 
Message-ID: <b72f3640.0507021413.986ad89@posting.google.com>
Philippe Lorin <············@gmail.com> wrote

> I want to automate the writing of a few functions. My problem is 
> generating their names.

    (defmacro defun-my-functions (x)
       (let ((n1 (intern (make-symbol (format nil "FUNCTION1-~A" x))))
             (n2 (intern (make-symbol (format nil "FUNCTION2-~A" x)))))
         `(progn
            (defun ,n1 () (print "I'm a type 1 function"))
            (defun ,n2 () (print "I'm a type 2 function")))))
From: Thomas F. Burdick
Subject: Re: how to generate function names
Date: 
Message-ID: <xcvirzsqj75.fsf@conquest.OCF.Berkeley.EDU>
·············@swipnet.se (Peter Lewerin) writes:

> Philippe Lorin <············@gmail.com> wrote
> 
> > I want to automate the writing of a few functions. My problem is 
> > generating their names.
> 
>     (defmacro defun-my-functions (x)
>        (let ((n1 (intern (make-symbol (format nil "FUNCTION1-~A" x))))
>              (n2 (intern (make-symbol (format nil "FUNCTION2-~A" x)))))
>          `(progn
>             (defun ,n1 () (print "I'm a type 1 function"))
>             (defun ,n2 () (print "I'm a type 2 function")))))

Intern takes a string for its first argument, not a symbol (for
hopefully obvious reasons).  And you probably don't want to go
interning symbols in whatever *package* happens to be bound to.  In
the cases where it makes a difference, this would probably provide
more intuitive behavior:

   (defmacro defun-my-functions (x)
      (let* ((package (symbol-package x))
             (n1 (intern (format nil "FUNCTION1-~A" x) package))
             (n2 (intern (format nil "FUNCTION2-~A" x) package)))
        `(progn
           (defun ,n1 () (print "I'm a type 1 function"))
           (defun ,n2 () (print "I'm a type 2 function")))))


-- 
           /|_     .-----------------------.                        
         ,'  .\  / | Free Mumia Abu-Jamal! |
     ,--'    _,'   | Abolish the racist    |
    /       /      | death penalty!        |
   (   -.  |       `-----------------------'
   |     ) |                               
  (`-.  '--.)                              
   `. )----'                               
From: Peter Lewerin
Subject: Re: how to generate function names
Date: 
Message-ID: <b72f3640.0507030848.2254422f@posting.google.com>
···@conquest.OCF.Berkeley.EDU (Thomas F. Burdick) wrote

> Intern takes a string for its first argument, not a symbol (for
> hopefully obvious reasons).

Right.  I was obviously more tired than I thought.

> And you probably don't want to go
> interning symbols in whatever *package* happens to be bound to.

Maybe I misunderstood the OP; I thought he *did* want
DEFUN-MY-FUNCTIONS to behave as if DEFUN had been called in that
place.  Anyway, I'm all for robustness.
From: Thomas F. Burdick
Subject: Re: how to generate function names
Date: 
Message-ID: <xcvfyuvr2rw.fsf@conquest.OCF.Berkeley.EDU>
·············@swipnet.se (Peter Lewerin) writes:

> ···@conquest.OCF.Berkeley.EDU (Thomas F. Burdick) wrote
> 
> > Intern takes a string for its first argument, not a symbol (for
> > hopefully obvious reasons).
> 
> Right.  I was obviously more tired than I thought.
> 
> > And you probably don't want to go
> > interning symbols in whatever *package* happens to be bound to.
> 
> Maybe I misunderstood the OP; I thought he *did* want
> DEFUN-MY-FUNCTIONS to behave as if DEFUN had been called in that
> place.

DEFUN does not intern anything, so what you said here is not a
contrast to what you quoted from me.  Consider:

  (in-package :cl-user)

  (defparameter *src* '(progn
                         (defun foo (x) (1+ x))
                         (eval `(defun ,(intern "FOO") (x) (- x)))
                         (defun-my-functions foo)))

  (let ((*package* (find-package :keyword)))
    (eval *src*))

This will define a function CL-USER::FOO, a function :FOO, and two
functions :FUNCTION1-FOO and :FUNCTION2-FOO ...

> Anyway, I'm all for robustness.

... so I'm sure you'll agree that the last two stand out a bit :-)

-- 
           /|_     .-----------------------.                        
         ,'  .\  / | Free Mumia Abu-Jamal! |
     ,--'    _,'   | Abolish the racist    |
    /       /      | death penalty!        |
   (   -.  |       `-----------------------'
   |     ) |                               
  (`-.  '--.)                              
   `. )----'                               
From: Pascal Bourguignon
Subject: Re: how to generate function names
Date: 
Message-ID: <87wto9xdow.fsf@thalassa.informatimago.com>
Philippe Lorin <············@gmail.com> writes:

> I want to automate the writing of a few functions. My problem is
> generating their names. For instance, I want to be able to write:
>
> (defun-my-functions 'type-a)
> (defun-my-functions 'type-b)
>
> and get something like:
>
> (defun function1-type-a (...) ...)
> (defun function2-type-a (...) ...)
> (defun function1-type-b (...) ...)
> (defun function2-type-b (...) ...)
>
> but I have no idea how to generate the symbols "function1-type-a"
> etc. I tried "make-symbol", but it doesn't work as I'd expect;
> e.g. after evaluating this:
>
> (set (make-symbol "x") 12)
>
> I would expect the expression:
>
> x
>
> to be evaluated as 12, but all I get is an unbound variable
> error. Still, (symbol-name (make-symbol "x")) returns "x" as expected.
>
> What is wrong with my expectations, and how can I get the result I want?

GENSYM and MAKE-SYMBOL create new symbols, and set their name.  But
they don't internalize the created symbols.  So the reader has no way
to retrieve these symbols. FIND-SYMBOL can't find them in any package.

INTERN find the symbol if it already was interned, or creates a new
symbol AND interns it in the specified package (or the current
*PACKAGE*).  Thereafter, FIND-SYMBOL can find it.



If you use FORMAT to build the symbol name, you might want to use with
WITH-STANDARD-IO-SYNTAX, taking care of the package too.

(defmacro wsiosbp (&body body)
  (let ((vpack (gensym)))
    `(let ((,vpack *package*))
       (with-standard-io-syntax ; this resets *package*
           (let ((*package* ,vpack))
             ,@body)))))

(defun defun-my-functions (root)
   `(progn 
        (defun ,(intern (wsiosbp (format nil "FUNCTION1-~A" root))) ...)
        (defun ,(intern (wsiosbp (format nil "FUNCTION2-~A" root))) ...)))


On the other hand, you might want to specify the package where to
intern the new symbols.  For example, taking the package of the root
symbol:

(defun defun-my-functions (root)
   `(progn 
        (defun ,(intern (wsiosbp (format nil "FUNCTION1-~A" root))
                        (or (and (symbolp root) (symbol-package root))
                             *package*)) ...)
        (defun ,(intern (wsiosbp (format nil "FUNCTION2-~A" root))
                        (or (and (symbolp root) (symbol-package root))
                             *package*)) ...)))

but it'd be better to take it explicitely:

(defun defun-my-functions (root &optional (*package* *package*))
   `(progn 
        (defun ,(intern (wsiosbp (format nil "FUNCTION1-~A" root))) ...)
        (defun ,(intern (wsiosbp (format nil "FUNCTION2-~A" root))) ...)))


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/
Wanna go outside.
Oh, no! Help! I got outside!
Let me back inside!