From: Jm
Subject: how to execute code stored as data?
Date: 
Message-ID: <374a5kF55l0q5U1@individual.net>
Hi there.
I just started with LISP and have a problem here... how do i execute code
stored in a list?

(defstruct person
            name)

(setq code '((make-person :name "John")
                   (make-person :name "Joe")
                   (make-person :name "Bill")))

(vector (*what-do-i-put-here?* (nth 2 code)))

This must be really easy but i'm lost...
Thanks to anyone who can help.

From: Matthew Danish
Subject: Re: how to execute code stored as data?
Date: 
Message-ID: <873bw3neux.fsf@mapcar.org>
"Jm" <··@noemail.com> writes:

> Hi there.
> I just started with LISP and have a problem here... how do i execute code
> stored in a list?
> 
> (defstruct person
>             name)
> 
> (setq code '((make-person :name "John")
>                    (make-person :name "Joe")
>                    (make-person :name "Bill")))
> 
> (vector (*what-do-i-put-here?* (nth 2 code)))
> 
> This must be really easy but i'm lost...
> Thanks to anyone who can help.

You could do something like (mapcar 'eval code) to get
(#S(PERSON :NAME "John") #S(PERSON :NAME "Joe") #S(PERSON :NAME "Bill"))

But I think you're doing the wrong thing.  Using EVAL like this is
generally not correct, because it is an extremely, ***EXTREMELY***
heavyweight tool.  It's like (and in some cases IS) spawning a whole
new compiler process for your little bit of code.  What you really
want is higher-order functions:

(defparameter *code*
  (list (lambda () (make-person :name "John"))
        (lambda () (make-person :name "Joe"))
        (lambda () (make-person :name "Bill"))))

(mapcar 'funcall *code*) => ... same result as above ...

In addition you can construct your higher order functions inside other
functions, like so for example:

(defun make-code (names)
  (mapcar (lambda (name)
            (lambda () (make-person :name name)))
          names))

(mapcar 'funcall (make-code '("John" "Joe" "Bill"))) => ... same result ...

This will all be highly optimized and compiled away when you do your
normal compilation step, and does NOT require invoking the compiler
again at run-time.

-- 
;; Matthew Danish -- user: mrd domain: cmu.edu
;; OpenPGP public key: C24B6010 on keyring.debian.org
From: Wade Humeniuk
Subject: Re: how to execute code stored as data?
Date: 
Message-ID: <Kq7Pd.25277$K54.13356@edtnps84>
Jm wrote:
> Hi there.
> I just started with LISP and have a problem here... how do i execute code
> stored in a list?
> 
> (defstruct person
>             name)
> 
> (setq code '((make-person :name "John")
>                    (make-person :name "Joe")
>                    (make-person :name "Bill")))
> 
> (vector (*what-do-i-put-here?* (nth 2 code)))
> 

(defun execute-stored-code (form)
   (apply (car form) (rest form)))

(vector (execute-stored-code (nth 2 code)))

Wade
From: Wade Humeniuk
Subject: Re: how to execute code stored as data?
Date: 
Message-ID: <iQ7Pd.25333$K54.24241@edtnps84>
Jm wrote:
> Hi there.
> I just started with LISP and have a problem here... how do i execute code
> stored in a list?
> 

Just curious,

Why are you storing code in a list?

Wade
From: Kent M Pitman
Subject: Re: how to execute code stored as data?
Date: 
Message-ID: <umzua3lpf.fsf@nhplace.com>
"Jm" <··@noemail.com> writes:

> Hi there.
> I just started with LISP and have a problem here... how do i execute code
> stored in a list?
> 
> (defstruct person
>             name)
> 
> (setq code '((make-person :name "John")
>                    (make-person :name "Joe")
>                    (make-person :name "Bill")))
> 
> (vector (*what-do-i-put-here?* (nth 2 code)))
> 
> This must be really easy but i'm lost...
> Thanks to anyone who can help.

While you can store source code (list structure), and use EVAL to
execute it, you are electing to help perpetuate the myth that Lisp
works by running an interpreter at runtime.  Most Lisp code is
compiled, and there's not a lot of reason in the scope of the above
example not to involve compiled code more than you're doing.
Consider:

If you know you're going to make a person named John, Joe, and Bill only
once, then don't quote the list in the first place. e.g.,

 (setq people (list (make-person :name "John")
                    (make-person :name "Joe")
                    (make-person :name "Bill")))

  people => (#S(PERSON :NAME "John")
             #S(PERSON :NAME "Joe")
             #S(PERSON :NAME "Bill"))

[Side note: when making lists of people, practice making female names
            in the list.]

If you know you're going to want to make just these three people at some
later time, make a function to do it later:

 (defun make-people ()
   (list (make-person :name "John")
         (make-person :name "Joe")
         (make-person :name "Bill")))

 (make-people)


If you know you're going to want to make people later, but don't know their
names, make a function that takes the names. e.g.,

 (defun make-people (names)
   (mapcar (lambda (name) (make-person :name name)) names))

 (make-people '("John" "Joe" "Bill"))

If you know you're going to have arbitrary code that you want to defer,
which may be what you're trying to do here (i.e., maybe it's not always
just a bunch of make-person calls in a row), then you can make "closures".
You could just use the calls to make-person but I'm going to use other code
here to better motivate why one of the other solutions above isn't warranted
if you're using this style:

 (setq creators (list (lambda () (make-person :name "John"))
                      (lambda () (make-cat :name "Spot"))
                      (lambda () *something-i-made-before*)))

Making a closure, rather than a bunch of list stuff, makes this fast to
execute.  The LAMBDA will be compiled at compile time since it is not 
in quoted structure but in the program syntax area, and at runtime you'll
be doing:

 (setq creators (list '#<function that makes John>
                      '#<function that makes Spot>
                      '#<function that returns *something-i-made-before*>))

This is very fast to execute.  You can later call these by doing:

 (mapcar #'funcall creators)

or, if you're doing arguments, as in:

 (setq creators (list (lambda (name) (make-person :name name"))
                      (lambda (name) (make-cat :name name"))))

 (mapcar #'(lambda (creator name)
             (funcall creator name))
         creators
         '("John" "Spot"))

Note in this case that if either the list of creators or the list of names
is shorter, you'll only get that many results.

Note, too, that this could be written:

 (mapcar #'funcall creators '("John" "Spot"))

but only because funcall happens to take arguments in exactly the right 
form and order for your situation.  If you wanted to do:

 (mapcar #'(lambda (creator name)
             (funcall creator (concatenate 'string name " Jones")))
         creators
         '("John" "Spot"))

you can't shorten it, or if you want to, you can only do it by something
like

 (mapcar #'funcall
         creators
         (mapcar #'(lambda (name) (concatenate 'string name " Jones"))
                 '("John" "Spot")))

Does that help any?  Or leave some lingering confusion?
From: Christopher C. Stacy
Subject: Re: how to execute code stored as data?
Date: 
Message-ID: <uy8duk59u.fsf@news.dtpq.com>
Kent M Pitman <······@nhplace.com> writes:
> 
>   people => (#S(PERSON :NAME "John")
>              #S(PERSON :NAME "Joe")
>              #S(PERSON :NAME "Bill"))
> 
> [Side note: when making lists of people, practice making female names
>             in the list.]

Maybe those are female names!
From: Pascal Bourguignon
Subject: Re: how to execute code stored as data?
Date: 
Message-ID: <87zmy88qrb.fsf@thalassa.informatimago.com>
Kent M Pitman <······@nhplace.com> writes:
> [Side note: when making lists of people, practice making female names
>             in the list.]

Like what?  
In my programming classes there were no females.  
Is it really an existing sex?



(Well there were's some, about less than 2%, probably not
statistically significant).


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/
From: Jens Axel Søgaard
Subject: Re: how to execute code stored as data?
Date: 
Message-ID: <420f6b8e$0$12748$edfadb0f@dread14.news.tele.dk>
Pascal Bourguignon wrote:

> Kent M Pitman <······@nhplace.com> writes:
> 
>>[Side note: when making lists of people, practice making female names
>>            in the list.]
> 
> 
> Like what?  
> In my programming classes there were no females.  
> Is it really an existing sex?
> 
> 
> (Well there were's some, about less than 2%, probably not
> statistically significant).

Apropos female names on lists.

This week there we had election for parliment in Denmark.
One yong female candidate running for a red/green party
got, to her great surprise, elected. She had partipated
in only one election meeting - she had spent for her
time campaigning for another (a man).

The local newspaper decided to solve the mystery, and
got her voters to write the newspaper. Today the solved
the mystery. Although some voters voted on her because they
knew her and found her honest, the majority were voting on the
first female on the ballot that happened to be listed under
that party. Most parties put the most important candidates
first, but this party had listed them alphabetically!

-- 
Jens Axel Søgaard
From: Kent M Pitman
Subject: Re: how to execute code stored as data?
Date: 
Message-ID: <u1xbkqozp.fsf@nhplace.com>
Pascal Bourguignon <····@mouse-potato.com> writes:

> Kent M Pitman <······@nhplace.com> writes:
> > [Side note: when making lists of people, practice making female names
> >             in the list.]
> 
> Like what?  
> In my programming classes there were no females.  

So?  The bootstrapping of participation by a wide variety of folks is a 
complex matter.  It doesn't happen in one day, and it's very "chicken/egg".

Eliminating the markers that say "we expect all programmers are male" or
"because there are so many male programmers, we forget there are females
elsewhere in the world" may not, in and of itself, cause females to arrive
in droves in the programming world.  But it's unlikely to drive them away.

Including them says "we remember them and expect them to be here", 
notwithstanding the incidental fact tha they aren't in some (perhaps many)
environs.

But, beyond that, it helps you remember that the world is composed of
more variation than you might think.  Sort of like when you make a
list of random integers and you make them all positive.  Make some
negative, just to make sure your program is open-minded.  If it says
numbers, make some integers and some floats.  When you make a list of
names with no restriction, make some with one word, some with two,
e.g., "Bill" or "Sally Jones" or "box of frogs" just so that you'll 
detect bugs based on assuming too narrow a set of things about your 
unconstrained input data.  Choosing names of varying ethnicities, 
further, might test Unicode support, too, if you have such in place.

In sum, building diversity into your programs might help both your 
programs and your workplace.

> Is it really an existing sex?

IMO, the world would be better without such quips.
From: Peter Lewerin
Subject: Re: how to execute code stored as data?
Date: 
Message-ID: <b72f3640.0502131443.1ba2a1d2@posting.google.com>
Kent M Pitman <······@nhplace.com> wrote

> In sum, building diversity into your programs might help both your 
> programs and your workplace.

Very true.  "Free your mind," as they say.

I used to try to sell this way of thinking to my students when I was
teaching programming.  I'd try to show that test data should be
diverse and awkward, and I tried to create example cases that would
challenge world-views rather than just take a few friendly integers
out for a walk.

One day maybe I overdid it.  I was explaining simple regular
expressions using families as examples: "mother, father", "mother,
father, child", "father, child", etc.

In the heat of the moment, I brought in same-sex marriage as the root
of another tree of possibilities; "father, father"...

At that point, one of my students left the lecture room.
From: drewc
Subject: Re: how to execute code stored as data?
Date: 
Message-ID: <%sRPd.380382$8l.337108@pd7tw1no>
Peter Lewerin wrote:
> Kent M Pitman <······@nhplace.com> wrote
> 
> 
>>In sum, building diversity into your programs might help both your 
>>programs and your workplace.
> 
> 
> Very true.  "Free your mind," as they say.
> 
> I used to try to sell this way of thinking to my students when I was
> teaching programming.  I'd try to show that test data should be
> diverse and awkward, and I tried to create example cases that would
> challenge world-views rather than just take a few friendly integers
> out for a walk.
> 
> One day maybe I overdid it.  I was explaining simple regular
> expressions using families as examples: "mother, father", "mother,
> father, child", "father, child", etc.
> 
> In the heat of the moment, I brought in same-sex marriage as the root
> of another tree of possibilities; "father, father"...
> 
> At that point, one of my students left the lecture room.

This just seemed like the perfect moment to try out my new .sig :

-- 
Drew Crampsie
drewc at tech dot coop
--- Lambda, the Love That Dare Not Speak Its Name? ---
From: Peter Lewerin
Subject: Re: how to execute code stored as data?
Date: 
Message-ID: <b72f3640.0502131114.50c5c876@posting.google.com>
"Jm" <··@noemail.com> wrote

> I just started with LISP and have a problem here... how do i execute code
> stored in a list?

One approach is to see if it's really necessary to store the actual
code in the list.  In this case, the parameters suffice.

> (defstruct person
>             name)

(defparameter *code* (list '(:name "Anne")
                           '(:name "Bob")
                           '(:name "Claire")
                           '(:name "Dave")))

(apply #'make-person (nth 2 *code*))