From: Scott McIntire
Subject: Lambda from tree
Date: 
Message-ID: <uxlM9.33719$qF3.1625@sccrnsc04>
I would like to have a function/macro that takes a tree/symbol that is a
tree (in effect representing a function) and produce the actual function.
Example:
(setf *foo* '(+ x y))

;;; Gets the variables from an expression:
;;; Example: (get-vars '(+ ?x ?y)) produces (?x ?y).
(defun get-vars (tree)
  (labels ((rec (tree vars)
             (cond ((null tree) vars)
                   ((and (symbolp tree)
                         (eql (char (symbol-name tree) 0) #\?))
                    (cons tree vars))
                   ((atom tree) vars)
                   (t
                    (rec (cdr tree) (nconc (rec (car tree) nil) vars))))))
    (delete-duplicates (rec tree nil))))

;;; Makes a function from a variable list and a body.
(defmacro make-func (vars body)
          `#'(lambda ,(get-vars vars) ,body))

;;If we type
(macroexpand-1 '(make-func  (cdr '(?x ?y))   (+ ?x ?y))))

;;we get
#'(LAMBDA (?Y ?X) (+ ?X ?Y))

;;Success

What I would like is to have a function /macro that takes the a variable,
say 'bar, which is equal to '(+ ?x ?y) and
produce this same function.

Any ideas?

From: Kaz Kylheku
Subject: Re: Lambda from tree
Date: 
Message-ID: <cf333042.0212191114.3833e3d8@posting.google.com>
"Scott McIntire" <····················@attbi.com> wrote in message news:<····················@sccrnsc04>... 
> ;;; Makes a function from a variable list and a body.
> (defmacro make-func (vars body)
>           `#'(lambda ,(get-vars vars) ,body))

If you want more than one expression in a function body, you want:

  (defmacro make-func (vars &body body)
    `#'(lambda ,(get-vars vars) ,@body))

> ;;If we type
> (macroexpand-1 '(make-func  (cdr '(?x ?y))   (+ ?x ?y))))

Instead of passing (CDR (QUOTE (?x ?y))) to the macro, you can just
pass (?x ?y). Newbie? ;)
  
> What I would like is to have a function /macro that takes the a variable,
> say 'bar, which is equal to '(+ ?x ?y) and
> produce this same function.

I don't think you can achieve this without the use of EVAL. Your macro
must expand to code which assembles the LAMBDA expression together
using the current value of the variable, and then passes the resulting
list to the FUNCTION operator. This passing to the FUNCTION operator
of a dynamically constructed list can only be achieved by EVAL.

That is to say, you want the expression

  (make-func-from-variable x)

to generate this code:

  (let ((dynamic-code (list 'function 
                            (list* 'lambda (get-vars x) x))))
    (eval dynamic-code))

It's not necessary for dynamic-code to be a gensym. It's assumed that
x is a list of expressions, like ((+ x y)) or ((prin1 42) (+ x y)),
which is why I used the LIST* function. An alternate way to write
this, using the backquote operator instead of explicit list
construction would be:

   (let ((dynamic code `(function (lambda ,(get-vars x) ,x))))
     (eval dynamic-code))

Now to spin it into the make-func-from-variable macro:

   (defmacro make-func-from-variable (symbol)
     `(let ((dynamic-code `(function 
                             (lambda ,(get-vars ,symbol) 
                                ,@,symbol))))
        (eval dynamic-code)))

Test it:

   (macroexpand '(make-func-from-variable x))

   ==> (LET ((DYNAMIC-CODE `#'(LAMBDA ,(GET-VARS X) ,@X))) 
         (EVAL DYNAMIC-CODE))

I think that's it. Remember, the variable is expected to be a list of
expressions, not one expression. Also keep in mind that the code
evaluated by EVAL does not see the lexical environment. Your function
created by make-func-from-variable will not be able to capture the
bindings of lexical bindings visible in its body's scope.
From: Scott McIntire
Subject: Re: Lambda from tree
Date: 
Message-ID: <QgqM9.230511$pN3.19160@sccrnsc03>
Thanks Kaz - much appreciated.

"Kaz Kylheku" <···@ashi.footprints.net> wrote in message
·································@posting.google.com...
> "Scott McIntire" <····················@attbi.com> wrote in message
news:<····················@sccrnsc04>...
> > ;;; Makes a function from a variable list and a body.
> > (defmacro make-func (vars body)
> >           `#'(lambda ,(get-vars vars) ,body))
>
> If you want more than one expression in a function body, you want:
>
>   (defmacro make-func (vars &body body)
>     `#'(lambda ,(get-vars vars) ,@body))
>
> > ;;If we type
> > (macroexpand-1 '(make-func  (cdr '(?x ?y))   (+ ?x ?y))))
>
> Instead of passing (CDR (QUOTE (?x ?y))) to the macro, you can just
> pass (?x ?y). Newbie? ;)
>
> > What I would like is to have a function /macro that takes the a
variable,
> > say 'bar, which is equal to '(+ ?x ?y) and
> > produce this same function.
>
> I don't think you can achieve this without the use of EVAL. Your macro
> must expand to code which assembles the LAMBDA expression together
> using the current value of the variable, and then passes the resulting
> list to the FUNCTION operator. This passing to the FUNCTION operator
> of a dynamically constructed list can only be achieved by EVAL.
>
> That is to say, you want the expression
>
>   (make-func-from-variable x)
>
> to generate this code:
>
>   (let ((dynamic-code (list 'function
>                             (list* 'lambda (get-vars x) x))))
>     (eval dynamic-code))
>
> It's not necessary for dynamic-code to be a gensym. It's assumed that
> x is a list of expressions, like ((+ x y)) or ((prin1 42) (+ x y)),
> which is why I used the LIST* function. An alternate way to write
> this, using the backquote operator instead of explicit list
> construction would be:
>
>    (let ((dynamic code `(function (lambda ,(get-vars x) ,x))))
>      (eval dynamic-code))
>
> Now to spin it into the make-func-from-variable macro:
>
>    (defmacro make-func-from-variable (symbol)
>      `(let ((dynamic-code `(function
>                              (lambda ,(get-vars ,symbol)
>                                 ,@,symbol))))
>         (eval dynamic-code)))
>
> Test it:
>
>    (macroexpand '(make-func-from-variable x))
>
>    ==> (LET ((DYNAMIC-CODE `#'(LAMBDA ,(GET-VARS X) ,@X)))
>          (EVAL DYNAMIC-CODE))
>
> I think that's it. Remember, the variable is expected to be a list of
> expressions, not one expression. Also keep in mind that the code
> evaluated by EVAL does not see the lexical environment. Your function
> created by make-func-from-variable will not be able to capture the
> bindings of lexical bindings visible in its body's scope.
From: Timothy Moore
Subject: Re: Lambda from tree
Date: 
Message-ID: <atssb2$74r$0@216.39.145.192>
"Scott McIntire" <····················@attbi.com> writes:

> I would like to have a function/macro that takes a tree/symbol that is a
> tree (in effect representing a function) and produce the actual function.
> Example:
> (setf *foo* '(+ x y))
> 
...
> 
> ;;; Makes a function from a variable list and a body.
> (defmacro make-func (vars body)
>           `#'(lambda ,(get-vars vars) ,body))
> 
> ;;If we type
> (macroexpand-1 '(make-func  (cdr '(?x ?y))   (+ ?x ?y))))
> 
> ;;we get
> #'(LAMBDA (?Y ?X) (+ ?X ?Y))
> 
> ;;Success
> 
> What I would like is to have a function /macro that takes the a variable,
> say 'bar, which is equal to '(+ ?x ?y) and
> produce this same function.
> 
> Any ideas?
(defun make-func (vars body)
  (coerce `(lambda ,vars ,@body) 'function))

Tim
From: Scott McIntire
Subject: Re: Lambda from tree
Date: 
Message-ID: <H9nM9.429879$QZ.66934@sccrnsc02>
"Timothy Moore" <·····@bricoworks.com> wrote in message
·················@216.39.145.192...
> "Scott McIntire" <····················@attbi.com> writes:
>
> > I would like to have a function/macro that takes a tree/symbol that is a
> > tree (in effect representing a function) and produce the actual
function.
> > Example:
> > (setf *foo* '(+ x y))
> >
> ...
> >
> > ;;; Makes a function from a variable list and a body.
> > (defmacro make-func (vars body)
> >           `#'(lambda ,(get-vars vars) ,body))
> >
> > ;;If we type
> > (macroexpand-1 '(make-func  (cdr '(?x ?y))   (+ ?x ?y))))
> >
> > ;;we get
> > #'(LAMBDA (?Y ?X) (+ ?X ?Y))
> >
> > ;;Success
> >
> > What I would like is to have a function /macro that takes the a
variable,
> > say 'bar, which is equal to '(+ ?x ?y) and
> > produce this same function.
> >
> > Any ideas?
> (defun make-func (vars body)
>   (coerce `(lambda ,vars ,@body) 'function))
>
> Tim

Thanks Tim, but if I do this and compile make-func, I do not get back a
compiled function from make-func.
Is there a way to construct make-func so that I can get back a compiled
function?

-Scott
From: Tim Bradshaw
Subject: Re: Lambda from tree
Date: 
Message-ID: <ey3adj1nb1f.fsf@cley.com>
* Scott McIntire wrote:

> Thanks Tim, but if I do this and compile make-func, I do not get back a
> compiled function from make-func.
> Is there a way to construct make-func so that I can get back a compiled
> function?

(defun make-func (vars body)
  (compile nil `(lambda ,vars ,@body)))

--tim
From: Scott McIntire
Subject: Re: Lambda from tree
Date: 
Message-ID: <l%nM9.429364$NH2.31327@sccrnsc01>
Thanks again Tim.

-Scott

"Tim Bradshaw" <···@cley.com> wrote in message
····················@cley.com...
> * Scott McIntire wrote:
>
> > Thanks Tim, but if I do this and compile make-func, I do not get back a
> > compiled function from make-func.
> > Is there a way to construct make-func so that I can get back a compiled
> > function?
>
> (defun make-func (vars body)
>   (compile nil `(lambda ,vars ,@body)))
>
> --tim
>
>
>