From: dimitris
Subject: forms as parameter
Date: 
Message-ID: <41bcc08a-dc34-4ee8-9ed7-24c67f8d685a@u69g2000hse.googlegroups.com>
Hi all,

I'm trying to find a way to use the content of a class slot (probably
of type list or string) as a form that can be evaluated. I mean for
example I have the class A with the slot expression. What I want to do
is in a method of this function to be able to use this expression as a
form to be evaluated. So the user of the class can set the value of
this expression

(setf (expression A) '(+ i 1))   or as a string (setf (expression A)
"+ i 1")

and in this method I can have code executed like:

(loop for i from 0 below 10 do
  (setf x expression))

and this should evaluate as

(loop for i from 0 below 10 do
  (setf x (+ i 1)))

or whatever. the point is that I need to be able to define the
expression in the class slot as a list and then use it as a form an a
method of the same class.

I'm trying to do something with macros (i'm generally new to lisp, I
use SBCL) but no success.

(defmacro set-using-list (x e)
  `(setf ,x ,e))

so when I do

(let ((x 0)
(i 1))
(set-using-list x (+ i 1)))

I get the correct result that is 2. But when passing list as argument
(which is what i want) it does not work.

(let ((x 0)
(i 1)
(expression '(+ i 1)))
(set-using-list x expression))

results (+ i 1). probably this is how it should work, but is there any
way to solve this problem in common lisp?

thanks in advance,

dimitris

From: danb
Subject: Re: forms as parameter
Date: 
Message-ID: <a61d56fd-0e16-40c3-bd03-1616974f634a@m34g2000hsc.googlegroups.com>
On Mar 17, 10:24 pm, dimitris <·········@yahoo.com> wrote:
> Hi all,

Hi Dimitris.

> use the content of a class slot (probably of type
> list or string) as a form that can be evaluated.

Unless you're going to insert the form directly into a
macro somewhere, I would use a lambda instead.

> (setf (expression A) '(+ i 1))

(setf (function A) (lambda (x) (+ x 1)))

> (loop for i from 0 below 10 do
>   (setf x (expression))

(loop for i from 0 below (length array) do
  (setf (aref array i) (funcall (function A) i)))

> I'm trying to do something with macros
> (i'm generally new to lisp, I use SBCL)

One of the general rules of thumb is, only use macros
when you have to.  They're good for defining control
flow, assigning values to specific places in containers,
and definitions.  For returning a value, a function
works fine.

> (defmacro set-using-list (x e)
>   `(setf ,x ,e))

> (expression '(+ i 1)))
> (set-using-list x expression))

EXPRESSION isn't evaluated here, so this effectively
expands to (setf x 'expression).  X should be equal
to EXPRESSION after doing this.

--Dan

------------------------------------------------
Dan Bensen
http://www.prairienet.org/~dsb/
From: Kent M Pitman
Subject: Re: forms as parameter
Date: 
Message-ID: <uve3kmrag.fsf@nhplace.com>
danb <·········@gmail.com> writes:

> > (setf (expression A) '(+ i 1))
> 
> (setf (function A) (lambda (x) (+ x 1)))

The FUNCTION special form is not setf-able.

The SYMBOL-FUNCTION function is setf-able, but doesn't do the same thing
in lexical environments.

(setf (symbol-function 'A) (lambda (x) (+ x 1)))

There is no mechanism for imperative assignment to lexical function bindings,
only for toplevel global functions.  I'm not sure if that's good or bad.
But it's how it is.

> (loop for i from 0 below (length array) do
>   (setf (aref array i) (funcall (function A) i)))

This will work even though you need to have set the symbol-function, not
the function, because there is no lexical binding for function A.
It will also work to do:

(loop for i from 0 below (length array) do
  (setf (aref array i) (funcall 'A i)))

or

(loop for i from 0 below (length array) do
  (setf (aref array i) (A i))) 

There is no really material difference between (funcall #'A i) and
(A i) ... other than that the former requires that A is not a macro,
while the latter doesn't... but we assume in this example that that's
so, so they're effectively equivalent.
From: danb
Subject: Re: forms as parameter
Date: 
Message-ID: <b2a901cf-dcb2-4e5b-92c2-929616763057@u72g2000hsf.googlegroups.com>
> danb <·········@gmail.com> writes:
> > (setf (function A) (lambda (x) (+ x 1)))

On Mar 18, 2:20 am, Kent M Pitman <······@nhplace.com> wrote:
> The FUNCTION special form is not setf-able.

Maybe I should have thought of a better name.  From the
OP, it sounds like A is supposed to be a CLOS object and
EXPRESSION is an accessor.  I renamed the accessor to
FUNCTION because I changed the expression to a lambda,
and because I haven't used the FUNCTION special form
enough to remember it exists.  I'll give the accessor
a different name in future posts if the OP asks for more
info.

> > (loop for i from 0 below (length array) do
> >   (setf (aref array i) (funcall (function A) i)))

> (loop for i from 0 below (length array) do
>   (setf (aref array i) (A i)))
>
> There is no really material difference between
> (funcall #'A i) and (A i)

Except in my interpretation, where the OP may want to save
a lambda in a CLOS object and retrieve it at runtime.

> the former requires that A is not a macro, ...
> but we assume in this example that that's so

I thought the OP indicated that (expression A) is
"the content of a class slot", where I'm guessing
that, as a beginner, what he means by "class slot"
is "slot in a CLOS object".

--Dan

------------------------------------------------
Dan Bensen
http://www.prairienet.org/~dsb/
From: dimitris
Subject: Re: forms as parameter
Date: 
Message-ID: <f7191a61-1504-4070-963c-cc7acf6b30ec@u10g2000prn.googlegroups.com>
On Mar 18, 3:58 pm, danb <·········@gmail.com> wrote:
> Maybe I should have thought of a better name.  From the
> OP, it sounds like A is supposed to be a CLOS object and
> EXPRESSION is an accessor.

you got me right.


> I thought the OP indicated that (expression A) is
> "the content of a class slot", where I'm guessing
> that, as a beginner, what he means by "class slot"
> is "slot in a CLOS object".

true, that's what I mean.


well I managed to do what I wanted using your indications. I do the
following

(defclass A ()
  ((example-slot :type       symbol-function
                 :accessor   example-slot
                 :allocation :instance)))

(defmethod example-method (object-A)
  (let ((x 0))
    (loop for i from 0 below 10 do
      (setf x (funcall (example-slot object-A) i))
      (print x))))

and then

(let ((object-a (make-instance 'A)))
  (setf (example-slot object-a) (lambda (i) (+ i 1)))
  (example-method object-a))

and it seems to work fine.

thanks for your help!!
From: Thomas A. Russ
Subject: Re: forms as parameter
Date: 
Message-ID: <ymizlsvea4z.fsf@blackcat.isi.edu>
dimitris <·········@yahoo.com> writes:

> well I managed to do what I wanted using your indications. I do the
> following
> 
> (defclass A ()
>   ((example-slot :type       symbol-function
>                  :accessor   example-slot
>                  :allocation :instance)))
> 
> (defmethod example-method (object-A)
>   (let ((x 0))
>     (loop for i from 0 below 10 do
>       (setf x (funcall (example-slot object-A) i))
>       (print x))))

n.B. A more lisp-like way of writing this would dispense with X, and
especially with setting it to zero.

(defmethod example-method (object-A)
   (loop for i from 0 below 10
         do (print (funcall (example-slot object-A) i))))

> and then
> 
> (let ((object-a (make-instance 'A)))
>   (setf (example-slot object-a) (lambda (i) (+ i 1)))
>   (example-method object-a))
> 
> and it seems to work fine.

Yes.  That works and is a Lisp-y solution.  Note that you will need to
have a convention on the number of arguments the functions in these
slots will take.  In the example above, you have a protocol that says
these functions will take a single argument.

It is also possible to use closures to capture lexical variable values,
so the following would also work.

 (let ((object-a (make-instance 'A))
       (i 33))
   (setf (example-slot object-a) (lambda (i) (+ i 1)))
   (example-method-0 object-a)
   (setf i 100)
   (example-method-0 object-a)
   (setf i 300)
   (example-method-0 object-a))

 (defun example-method-0 (object-A)
   (funcall (example-slot object-A)))

which captures the value of "i" from the LET binding.  But from your
example above, I don't think that is exactly what you wanted.  I think
you like the lambda expression with a single argument better.

For even more fun, consider the following nooby puzzle:

 (let ((object-a (make-instance 'A))
       (i 33))
    (let ((i 44))
      (setf (example-slot object-a) (lambda (i) (+ i 1)))
      (example-method-0 object-a)
      (setf i 100)
      (example-method-0 object-a)
      (setf i 300)
      (example-method-0 object-a))
    (example-method-0 object-a)
    (setf i -200)
    (example-method-0 object-a))

-- 
Thomas A. Russ,  USC/Information Sciences Institute
From: dimitris
Subject: Re: forms as parameter
Date: 
Message-ID: <60f7ea6d-54e0-472c-ad5b-9d3593ba18f8@x30g2000hsd.googlegroups.com>
On Mar 19, 2:10 am, ····@sevak.isi.edu (Thomas A. Russ) wrote:

> It is also possible to use closures to capture lexical variable values,
> so the following would also work.
>
>  (let ((object-a (make-instance 'A))
>        (i 33))
>    (setf (example-slot object-a) (lambda (i) (+ i 1)))
>    (example-method-0 object-a)
>    (setf i 100)
>    (example-method-0 object-a)
>    (setf i 300)
>    (example-method-0 object-a))
>
>  (defun example-method-0 (object-A)
>    (funcall (example-slot object-A)))
>
> which captures the value of "i" from the LET binding.  But from your
> example above, I don't think that is exactly what you wanted.  I think
> you like the lambda expression with a single argument better.

True, it's not what I want, but I like these tricks and hacks, you
learn the details of how the language works better. example-method-0
does not work for me, I get an error like "invalid number of
arguments: 0", which I find reasonable since calling (example-slot
object-A) needs an argument since it was defined as (lambda (i) (+ i
1)) and if I call example-method instead of example-method-0 it counts
up to 10. So I couldn't really capture the value of "i" from the outer
let binding. Anyway.

My next step is to find if I can provide different functions (maybe
lambda expressions) so that I can then set the value of the slot to
one of these values and use it. I mean, in the same file with the
above definitions of class A and example-method (object-A) I try to
have definitions of these functions like

(setf (symbol-function uniform-distribution) (lambda (i) (random i)))

and maybe some more, like

(setf (symbol-function gaussian-distribution) (lambda (i j) (...)))

and then in the repl environment or in the same file or in another
file in a method or let binding, after compiling and loading the first
file, I should be able to do something like

(let ((object-a (make-instance 'A)))
  (setf (example-slot object-a) uniform-distribution)
  (example-method object-a))

or

(defmethod example-method-2 (object-a)
  (let ((i some-value-for-i)
        (j some-value-for-j))
    (print (funcall (example-slot object-a) i j))))

and then

(let ((object-a (make-instance 'A)))
  (setf (example-slot object-a) gaussian-distribution)
  (example-method-2 object-a))

But the thing is that I do not know how to define these lambda
expressions in the beginning of the file. I tried with

(defparameter (symbol-function *uniform*) (lambda (i) (range i)))

so that they are in the scope of repl or another file, but I have an
error -> can't declare a non-symbol as SPECIAL: (SYMBOL-FUNCTION
*UNIFORM*)
which I don't really know what it means (I try a lot but I'm still a
beginner...)

In the best case I should be to be able to define the method like:

(defmethod example-method (object-a)
  (print (case (example-slot object-a)
           (*uniform*  (let ((i some-value-for-i)) (funcall (example-
slot object-a) i)))
           (*gaussian* (let ((i some-value-for-i)
                             (j some-value-for-j)) (funcall (example-
slot-object-a) i j))))))

Does this make any sense? Too much thinking for today, I'll continue
with this tomorrow...
From: danb
Subject: Re: forms as parameter
Date: 
Message-ID: <f51c9f80-c276-460b-8ff7-2dccf1e2922f@c65g2000hsa.googlegroups.com>
On Mar 19, 10:17 pm, dimitris <·········@yahoo.com> wrote:
> (setf (symbol-function uniform-distribution)
>       (lambda (i) (random i)))
> (setf (example-slot object-a) uniform-distribution)
> But the thing is that I do not know how to define these lambda
> expressions in the beginning of the file.

You're trying to re-invent DEFUN.

(defun uniform-distribution (i) (random i))
(setf (example-slot object-a) #'uniform-distribution)

Or more simply,
(setf (example-slot object-a) #'random)

--Dan

------------------------------------------------
Dan Bensen
http://www.prairienet.org/~dsb/
From: dimitris
Subject: Re: forms as parameter
Date: 
Message-ID: <d8048227-81fd-41dd-b173-19a73c5ea30d@i12g2000prf.googlegroups.com>
On Mar 20, 3:59 am, danb <·········@gmail.com> wrote:

> You're trying to re-invent DEFUN.
>
> (defun uniform-distribution (i) (random i))
> (setf (example-slot object-a) #'uniform-distribution)
>
> Or more simply,
> (setf (example-slot object-a) #'random)

Yes, that's simple, I just didn't know that I can pass a function as a
parameter that easily.. I think I'm complete for now, thanks for your
help guys!!
From: Thomas A. Russ
Subject: Re: forms as parameter
Date: 
Message-ID: <ymi8x0ddprn.fsf@blackcat.isi.edu>
dimitris <·········@yahoo.com> writes:

> On Mar 19, 2:10 am, ····@sevak.isi.edu (Thomas A. Russ) wrote:

> My next step is to find if I can provide different functions (maybe
> lambda expressions) so that I can then set the value of the slot to
> one of these values and use it. I mean, in the same file with the
> above definitions of class A and example-method (object-A) I try to
> have definitions of these functions like
> 
> (setf (symbol-function uniform-distribution) (lambda (i) (random i)))
> 
> and maybe some more, like
> 
> (setf (symbol-function gaussian-distribution) (lambda (i j) (...)))

You should use DEFUN for these definitions.  It is a lot clearer, and
the language tools do a better job of supporting definitions that are
run through the DEFUN macro.

(defun uniform-distribution (i) (random i))
(defun gaussian-distribution (i j) ...)

> and then in the repl environment or in the same file or in another
> file in a method or let binding, after compiling and loading the first
> file, I should be able to do something like
> 
> (let ((object-a (make-instance 'A)))
>   (setf (example-slot object-a) uniform-distribution)
                                  ^

This needs quoting, either #' or a simple '

>   (example-method object-a))
> or
> 
> (defmethod example-method-2 (object-a)
>   (let ((i some-value-for-i)
>         (j some-value-for-j))
>     (print (funcall (example-slot object-a) i j))))

You could do this.  The problem is that you need to have some way of
knowing how many arguments need to be supplied to the contents of
EXAMPLE-SLOT, and also what their meaning is supposed to be.

If you can set up an appropriate protocol, so that you can define what
the interface of these functions is, then you can use this technique.
It is fairly common to use for call-backs from other routines.

The key, as I said, is making sure that the protocol is well-defined.
Just looking at the two examples above, it isn't clear how you would
know -- for an arbitrary value stored in EXAMPLE-SLOT, whether you need
to call it with a single or with two arguments.


> and then
> 
> (let ((object-a (make-instance 'A)))
>   (setf (example-slot object-a) gaussian-distribution)
>   (example-method-2 object-a))
> 
> But the thing is that I do not know how to define these lambda
> expressions in the beginning of the file. I tried with

Why do you think they need to be defined at the beginning of the file?

> (defparameter (symbol-function *uniform*) (lambda (i) (range i)))

You need to go back and look at the earliest parts of your lisp
tutorial.   You are making the definition forms too complicated.  Before
going further, make sure you understand about DEFUN, DEFVAR and
DEFPARAMETER.

DEFPARAMETER introduces a special variable and assigns a value to it.
It takes a symbol as its first argument, not an arbitrary form.

> so that they are in the scope of repl or another file, but I have an
> error -> can't declare a non-symbol as SPECIAL: (SYMBOL-FUNCTION
> *UNIFORM*)
> which I don't really know what it means (I try a lot but I'm still a
> beginner...)
> 
> In the best case I should be to be able to define the method like:
> 
> (defmethod example-method (object-a)
>   (print (case (example-slot object-a)
>            (*uniform*  (let ((i some-value-for-i)) (funcall (example-
> slot object-a) i)))
>            (*gaussian* (let ((i some-value-for-i)
>                              (j some-value-for-j)) (funcall (example-
> slot-object-a) i j))))))
> 
> Does this make any sense? Too much thinking for today, I'll continue
> with this tomorrow...

Not really.  What this means is that you have created a method (which is
supposed to handle type dispatch for you) and then carefully put a test
inside which does your own dispatch.  This is fundamentally related to
the issue I raised above, which is that you can't tell what sort of
function you have stored in the slot.

Also, I notice that you don't specialize your method on the type of its
argument.  It applies to things of all types.   


You would do much better, and have clearer code if you dispensed with
the storage of the procedure and just put a keyword in place:

(defmethod example-method ((arg object-a))
  (print (ecase (distribution-type arg)
	   (:uniform (uniform-distribution some-value-for-i))
	   (:gaussian (gaussian-distribution some-value-for-i
					     some-value-for-j)))))

And then use a DISTRIBUTION-TYPE slot instead of storing the computation
method.  Storing a lambda expression only makes sense if you always
store functions with the same signature there, so that you will know how
to invoke them.  If you have to do things differently depending on what
is in there, you don't gain any benefit by storing the function there.
(Although it is a cool lisp feature to be able to do it....)


-- 
Thomas A. Russ,  USC/Information Sciences Institute
From: dimitris
Subject: Re: forms as parameter
Date: 
Message-ID: <e479ec9e-36dc-4a1e-9a8b-5328c484edc7@s50g2000hsb.googlegroups.com>
On Mar 20, 9:55 pm, ····@sevak.isi.edu (Thomas A. Russ) wrote:

> Not really.  What this means is that you have created a method (which is
> supposed to handle type dispatch for you) and then carefully put a test
> inside which does your own dispatch.  This is fundamentally related to
> the issue I raised above, which is that you can't tell what sort of
> function you have stored in the slot.
>
> Also, I notice that you don't specialize your method on the type of its
> argument.  It applies to things of all types.
>
> You would do much better, and have clearer code if you dispensed with
> the storage of the procedure and just put a keyword in place:
>
> (defmethod example-method ((arg object-a))
>   (print (ecase (distribution-type arg)
>            (:uniform (uniform-distribution some-value-for-i))
>            (:gaussian (gaussian-distribution some-value-for-i
>                                              some-value-for-j)))))
>
> And then use a DISTRIBUTION-TYPE slot instead of storing the computation
> method.  Storing a lambda expression only makes sense if you always
> store functions with the same signature there, so that you will know how
> to invoke them.  If you have to do things differently depending on what
> is in there, you don't gain any benefit by storing the function there.
> (Although it is a cool lisp feature to be able to do it....)

I see. The whole thing started when I needed to be able to store in a
slot or pass to a function an arbitrary expression with one parameter,
but then I also needed these distributions. So I thought it would be
good to use the same means to do it. But you're right, I don't really
need it this way and it is more comprehensible if I use DISTRIBUTION-
TYPE as you said.