From: ······@gmail.com
Subject: Overlord programs
Date: 
Message-ID: <1117563943.345846.38700@g44g2000cwa.googlegroups.com>
Suppose that i have an overlord program that has a function who
manipulates lists . After a while the program starts counting to -let's
say- 10,000). When it reaches 10,000 it decides that it might be
interesting to do a little arithmetic and wants to create a function
that adds 3 numbers. How does the creation of this function is going to
be implemented by the program ? Possibly the program will write down a
body for the function and then is going to bind it with a funtion name.
How is this accomplisehd ? I wandered the HyperSpec for about 4 days
and i could't find a clear way to do it. i am getting kind of lost in
all these parameters and names. I heard that this is one of the most
fundmanental benefits of using Lisp so it shouldn't be hidden under all
these technicalities but instead it should be right at the fron of the
manual!Can you please help me? Thank you

From: ······@gmail.com
Subject: Re: Overlord programs
Date: 
Message-ID: <1117565118.095223.253360@o13g2000cwo.googlegroups.com>
Hmmmm maybe that wasn't a very good example because defun will still
work here. But what if i wanted to modify an existing function , or
compose a funtion form parts of old functions ? Or what if the Overlord
program saw the description of a function in an ASCII file and wanted
to have it as a function of its own ?
From: Pascal Bourguignon
Subject: Re: Overlord programs
Date: 
Message-ID: <87sm03b2lw.fsf@thalassa.informatimago.com>
······@gmail.com writes:

> Hmmmm maybe that wasn't a very good example because defun will still
> work here. But what if i wanted to modify an existing function , or
> compose a funtion form parts of old functions ? Or what if the Overlord
> program saw the description of a function in an ASCII file and wanted
> to have it as a function of its own ?

DEFUN is useful only if you want to be able to refer to the function by name.
You can build anonymous functions too and refer to them by value (closures).

To manipulate functions as you want, you could keep them in the form of lists.


    Some bookkeeping might be done by your implementation, but this is
    implementation specific, and most probably  you won't be able to count
    on it for all functions. For example in clisp you can write:

    [139]> (defun zero (x) (lambda (y) (function identity)))
    ZERO
    [140]> (car (get 'zero 'system::definition))
    (DEFUN ZERO (X) (LAMBDA (Y) #'IDENTITY))

    But this doesn't work for functions loaded from a .fasl file:

    [141]> (with-open-file (src "/tmp/test.lisp" :direction :output 
                           :if-does-not-exist :create :if-exists :supersede)
                (print '(defun one (x) (lambda (y) (zero y))) src))
    (DEFUN ONE (X) (LAMBDA (Y) (ZERO Y)))
    [142]> (load (compile-file "/tmp/test.lisp"))
    ;; Compiling file /tmp/test.lisp ...
    WARNING in ONE in line 2 :
    variable X is not used.
    Misspelled or missing IGNORE declaration?
    ;; Wrote file /tmp/test.fas
    0 errors, 1 warning
    ;; Loading file /tmp/test.fas ...
    ;; Loaded file /tmp/test.fas
    T
    [143]> (car (get 'one 'system::definition))
    NIL
    [144]>  



So you could use a SYMBOL structure or your own structure to hold
information about functions:

(defstruct funs source function)

(defmacro defuns (name args &body body)
    `(defparameter ,name (make-funs :source (quote (lambda ,args ,@body))
                                    :function      (lambda ,args ,@body))))

(defuns zero (x) (lambda (y) (function identity)))

[147]> zero
#S(FUNS :SOURCE (LAMBDA (X) (LAMBDA (Y) #'IDENTITY))
   :FUNCTION #<FUNCTION :LAMBDA (X) (LAMBDA (Y) #'IDENTITY)>)
[148]> 

However this way you have to handle your own function calling:

[148]> (defuns one  (x) (lambda (y) (zero y)))

ONE
[149]> one
#S(FUNS :SOURCE (LAMBDA (X) (LAMBDA (Y) (ZERO Y)))
   :FUNCTION #<FUNCTION :LAMBDA (X) (LAMBDA (Y) (ZERO Y))>)

Here, one refers to a function ZERO, but we only defined a structure
ZERO, and the function is (funs-function zero) and must be called
with: (funcall (funs-function zero) y)

You may want to do it like this  if you're implementing an interpreter
for another language on top of Common Lisp and you don't want to mix
layers.


Rather, if you just want some reflexive features in the Common Lisp
image, just add your own bookkeeping to normal CL stuff, using the
normal SYMBOL structures (the SYMBOL-PLIST accessed with GET):


(defpackage "KEEP-SOURCE-COMMON-LISP"
  (:nicknames "KSCL")
  (:use "COMMON-LISP")
  (:shadow "DEFUN"))
(in-package "KSCL")

(defmacro defun (name args &body body)
   `(progn 
      ;; our bookkeeping:
      (setf (get ',name :source) '(common-lisp:defun ,name ,args ,@body))
      ;; COMMON-LISP bookkeeping:
      (common-lisp:defun ,name ,args ,@body)))


(defun list-external-symbols (package &key (sorted t))
  (let ((pack (find-package package)))
    (if pack
      (let ((sl '())) (do-external-symbols (s pack) (push s sl))
           (if sorted (sort sl (function string<)) sl))
      (error "No package ~S" package))))

(export (mapcar (lambda (sym) (intern (string sym) *package*))
                (list-external-symbols "COMMON-LISP" :sorted nil)))

(defpackage "KEEP-SOURCE-COMMON-LISP-USER"
  (:nicknames "KSCL-USER")
  (:use "KEEP-SOURCE-COMMON-LISP"))
(in-package "KSCL-USER")

(defun zero (x) (lambda (y) (function identity)))
(defun one  (x) (lambda (y) (zero y)))

(values (get 'zero :source) (get 'one :source))

--> (COMMON-LISP:DEFUN ZERO (X) (LAMBDA (Y) #'IDENTITY)) ;
    (COMMON-LISP:DEFUN ONE (X) (LAMBDA (Y) (ZERO Y)))


With this, you can now write your function butchering functions.

(defun both (f1 f2)
  (let ((s1 (get f1 :source))
        (s2 (get f2 :source)))
    (unless (= (length (third s1)) (length (third s2)))
       ;; TODO: Actually compare the number of arguments, not the length
       ;;       of the argument lists...
       (error "Both functions must have the same number of argument."))
    (unless (equal (third s1) (third s2))
       (error "Substitution of argument names not implemented yet."))
    `(defun ,(intern (format nil "BOTH<~A,~A>" f1 f2))
            ,(third s1)
            (values (block ,f1 ,@(cdddr s1))
                    (block ,f2 ,@(cdddr s2))))))

and you can have some fun:

KSCL-USER[171]> (both 'one 'zero)
(DEFUN |BOTH<ONE,ZERO>| (X)
 (VALUES (BLOCK ONE (LAMBDA (Y) (ZERO Y)))
         (BLOCK ZERO (LAMBDA (Y) #'IDENTITY))))

KSCL-USER[172]> (eval (both 'one 'zero))
|BOTH<ONE,ZERO>|

KSCL-USER[173]> (|BOTH<ONE,ZERO>| (function one))
#<FUNCTION :LAMBDA (Y) (ZERO Y)> ;
#<FUNCTION :LAMBDA (Y) #'IDENTITY>

KSCL-USER[176]>  (get '|BOTH<ONE,ZERO>| :source)
(COMMON-LISP:DEFUN |BOTH<ONE,ZERO>| (X)
 (VALUES (BLOCK ONE (LAMBDA (Y) (ZERO Y)))
         (BLOCK ZERO (LAMBDA (Y) #'IDENTITY))))


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/
Kitty like plastic.
Confuses for litter box.
Don't leave tarp around.
From: rriggs
Subject: Re: Overlord programs
Date: 
Message-ID: <1117573199.100563.54120@o13g2000cwo.googlegroups.com>
I'm kind of new to the pure implemintation of LISP, but is'nt it also
possible to do this?

(setq my_list (list "(DEFUN (" ")"))
(setq my_num (list "1" "2" "3"))
(setq my_ops (list " (+ " ")")
(eval (read (strcat (nth 0 my_list) (nth 0 my_num) (nth 1 my_num) (nth
2 my_num) (nth 1 my_list) (nth 0 my_ops) (nth 1 my_ops) (nth 1
my_ops))))

and you could actually set the whole EVAL function to a variable and
either write the value to a file, or not, but it would be dynamically
created right?
From: Pascal Bourguignon
Subject: Re: Overlord programs
Date: 
Message-ID: <87fyw3awwc.fsf@thalassa.informatimago.com>
"rriggs" <··········@gmail.com> writes:

> I'm kind of new to the pure implemintation of LISP, but is'nt it also
> possible to do this?
>
> (setq my_list (list "(DEFUN (" ")"))
> (setq my_num (list "1" "2" "3"))
> (setq my_ops (list " (+ " ")")
> (eval (read (strcat (nth 0 my_list) (nth 0 my_num) (nth 1 my_num) (nth
> 2 my_num) (nth 1 my_list) (nth 0 my_ops) (nth 1 my_ops) (nth 1
> my_ops))))
>
> and you could actually set the whole EVAL function to a variable and
> either write the value to a file, or not, but it would be dynamically
> created right?

It's perfectly possible to do that, but then you're not programming in
LISP -- LIst and Symbol Processing, you're programming in C or any
other lowly language that only knows about strings.

(setq my-list (list 'defun 'foo '()))
(setq my-num  (list 1 2 3))
(setq my-ops  '+)
(print (append my-list (list (list* my-ops my-num))))
(eval  (append my-list (list (list* my-ops my-num))))
(foo)

But then, this is a silly ways to build a function.  
It would be better to use backquotes:

(let* ((name 'fact)
       (param 'x)
       (args  (list param))
       (expr `(if (<= ,param 1) 1 (* ,param  (,name (1- ,param))))))
  (print `(defun ,name ,args ,expr))
  (eval  `(defun ,name ,args ,expr)))

--> (DEFUN FACT (X) (IF (<= X 1) 1 (* X (FACT (1- X))))) 
    FACT


Another example of the superiority of the list and symbols over
strings, try to do this with strings:

(common-subexpressions  
   "(* (+ (* x x) (* y y)) (sqrt (+ (* x x) (* y y))))")
--> "(LET ((G4609 (* X X))
           (G4607 (* Y Y)))
       (+ G4610 G4608 (SQRT (+ G4610 G4608))))"


You would have more problems to solve than with lists and symbols:

(defun common-subexpressions (expression)
  (let ((subexprs (make-hash-table :test (function equal)))
        (lets '()))
    (labels ((cse (se)
                (when (consp se)
                  (incf (gethash se subexprs 0))
                  (mapcar (function cse) (cdr se))))
             (sse (se)
                  (cond
                   ((atom se) se)
                   ((gethash se subexprs))
                   (t (cons (car se) (mapcar (function sse) (cdr se)))))))
      (cse expression)
      (maphash (lambda (k v)
                 (if (< 1 v)
                   (progn (push (list (gensym) k) lets)
                          (setf (gethash k subexprs) (gensym)))
                   (remhash k subexprs))) subexprs)
      `(let ,lets ,(sse expression)))))

(common-subexpressions '(+ (* x x) (* y y) (sqrt (+ (* x x) (* y y)))))
--> (LET ((#:G4609 (* X X))
          (#:G4607 (* Y Y)))
       (+ #:G4610 #:G4608 (SQRT (+ #:G4610 #:G4608))))



-- 
__Pascal Bourguignon__                     http://www.informatimago.com/
Our enemies are innovative and resourceful, and so are we. They never
stop thinking about new ways to harm our country and our people, and
neither do we. -- Georges W. Bush
From: rriggs
Subject: Re: Overlord programs
Date: 
Message-ID: <1117578002.660546.221120@g44g2000cwa.googlegroups.com>
Like I said I'm pretty new to even understanding the available
functions within this pure LISP thing.
I'm not sure if this is part of the language, but in my previous uses I
used an "rtos" or "itoa" or applicable function to convert another data
type into a string, which would basically add another line to the code
for the conversion, but I'm not sure if those functions were only
avaliable to me in my secluded version of AutoLISP or not. But it seems
if you obtained those numbers or symbols in a list form then they could
easily be added in an (and) function.

(eval (and (read (strcat my_func1 my_func2)) (list #:G4608 #:G4609
etc...) (read close_func)))

I'm just assumming that this is possible.
Please correct me.
From: Pascal Bourguignon
Subject: Re: Overlord programs
Date: 
Message-ID: <87y89uafz2.fsf@thalassa.informatimago.com>
"rriggs" <··········@gmail.com> writes:

> Like I said I'm pretty new to even understanding the available
> functions within this pure LISP thing.
> I'm not sure if this is part of the language, but in my previous uses I
> used an "rtos" or "itoa" or applicable function to convert another data
> type into a string, which would basically add another line to the code
> for the conversion, but I'm not sure if those functions were only
> avaliable to me in my secluded version of AutoLISP or not. But it seems
> if you obtained those numbers or symbols in a list form then they could
> easily be added in an (and) function.
>
> (eval (and (read (strcat my_func1 my_func2)) (list #:G4608 #:G4609
> etc...) (read close_func)))
>
> I'm just assumming that this is possible.
> Please correct me.

Please read:
  http://www.unmutual.info/startingwithcl.html
  http://www.cliki.net/Online%20Tutorial
  http://www.lispworks.com/documentation/HyperSpec/Front/index.htm


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/
Until real software engineering is developed, the next best practice
is to develop with a dynamic system that has extreme late binding in
all aspects. The first system to really do this in an important way
is Lisp. -- Alan Kay
From: lin8080
Subject: Re: Overlord programs
Date: 
Message-ID: <429E517B.2F691D31@freenet.de>
Pascal Bourguignon schrieb:

> (let* ((name 'fact)
>        (param 'x)
>        (args  (list param))
>        (expr `(if (<= ,param 1) 1 (* ,param  (,name (1- ,param))))))
>   (print `(defun ,name ,args ,expr))
>   (eval  `(defun ,name ,args ,expr)))

Wow.
     -----<··@

stefan
From: ··············@hotmail.com
Subject: Re: Overlord programs
Date: 
Message-ID: <1117571076.403189.31460@g14g2000cwa.googlegroups.com>
You might like to look at the spectacular OnLisp by Paul Graham
http://paulgraham.com. It's free to download, and the first few
chapters cover the majority of interesting lispy things you can do with
functions. The book goes on to talk about the various things which you
can only do in lisp and is generally brain-expanding.
From: ······@gmail.com
Subject: Re: Overlord programs
Date: 
Message-ID: <1117572660.434526.190710@f14g2000cwb.googlegroups.com>
Many thanks for your help!
From: Edi Weitz
Subject: Re: Overlord programs
Date: 
Message-ID: <uacmbyqlj.fsf@agharta.de>
On 31 May 2005 11:25:43 -0700, ······@gmail.com wrote:

> I wandered the HyperSpec for about 4 days and i could't find a clear
> way to do it. i am getting kind of lost in all these parameters and
> names. I heard that this is one of the most fundmanental benefits of
> using Lisp so it shouldn't be hidden under all these technicalities
> but instead it should be right at the fron of the manual!

The HyperSpec is neither a manual nor an introductory text, it's the
definition of the language.  If you're learning Lisp try a good book
like this one:

  <http://www.gigamonkeys.com/book/>

Cheers,
Edi.

-- 

Lisp is not dead, it just smells funny.

Real email: (replace (subseq ·········@agharta.de" 5) "edi")
From: Thomas A. Russ
Subject: Re: Overlord programs
Date: 
Message-ID: <ymifyw0vepu.fsf@sevak.isi.edu>
Well, one place to start with this is looking at LAMBDA expressions.

To create a lambda (essentially an anonymous function), you just create
a list with the appropriate form:

(let ((args '(x y z))
      (body '(+ x y z)))
   (list 'lambda args body))

OK. that gets you the following list expression:

   (lambda (x y z) (+ x y z))

If you want to bind it to a symbol, this can be done locally by
the normal LET form, or globally by SETF on SYMBOL-FUNCTION for a
particular symbol.  Another possibility would be to use the COMPILE
function in order to get a compiled version:

  (setf (symbol-function 'add3) (function (lambda (x y z) (+ x y z))))

or

  (compile 'add3  (lambda (x y z) (+ x y z)))

Note that in general, you will not be able to recover the function body
once you have compiled the function.  With some implementations and
appropriate configurations, FUNCTION-LAMBDA-EXPRESSION will work, but it
doesn't have to return anything.

Once you have this function, you will probably need to invoke it.  For
that you will need to use FUNCALL or APPLY.

BTW, the HyperSpec is not a manual or a tutorial book.  It is a
reference manual.   It isn't the recommended way to learn Lisp.

-- 
Thomas A. Russ,  USC/Information Sciences Institute