[Date Prev] [Date Next] [Thread Prev] [Thread Next] Date Index Thread Index Search archive:
Date:Mon Dec 11 08:39:32 1993 
Subject:Re: Languages for self-modifying code 
From:Richard Harter 
Volume-ID:931211.01 

In article <1993Dec4.071851.1@ulkyvx.louisville.edu> hjcove01@ulkyvx.louisville.edu writes:
>	There has been an on going discussion of what languages 
>are effective for creating self-modifying code in the comp.ai 
>newsgroup.  I will summarize some of the langauges I have 
>identified thus far.  I am distributing this note to several 
>different language groups because I am interested in hearing 
>of other languages that are also effective for creating self-
>modifying code.

I have added comp.lang.misc to the list.

>	When discussing languages for creating self-modifying 
>code we must first identify why we want such languages...

Unfortunately the rationale for wanting such languages is not
really established.

>	What is the most effective representation of a function 
>that can be modified?  If we represent a function as a string it 
>is not as easily modified and manipulated as when it is 
>represented as a structure of symbols.  Thus to have an 
>effective language for the creation of self-modifying code it is 
>best to have a language that manipulates symbols and 
>structures effectively...

The observation about the inadequacy of dealing with functions
as strings is not correct; this is a function of the language
design.  One can deal quite nicely with functions as strings
provided that symbol structure is readily accessible.  This in
turn requires that syntax be simple and regular.

>	We would also need tools that can then execute the 
>symbol-structure representations of functions that we have 
>created.  Preferrably we would want a tool that could execute 
>the structure on different sets of input values.  This tool would 
>resemble the apply tool that exists in some implementations of 
>Lisp.  Apply takes two arguments.  The first argument is a 
>structure that represents a function.  The second argument is 
>a list  or structure of arguments to be passed to the function.

IMHO this is fundamentally insufficient.  

>H. Justin Coven, Ph.D.

Justin asks about other languages which can readily do this sort of
thing.  The remainder of this post discusses self-modifying code in
Lakota.

----

In Lakota the task of writing self modifying code is simple.  The
salient features of Lakota for the purposes of this discussion are
that it is procedural, the syntax is very simple, there are text
manipulation commands, there is a function which returns the text
of a procedure, and there is an execute-string command.  Procedures
can be created, altered, and deleted dynamically.

The following example walks through a procedure to compose two
procedures in some detail:

#   compose two procedures g and h to yield procedure f

procedure compose f g h
    set-string 1 procedure f
    :set-string 2    h {all-arguments}
    :set-string 3    g {all-of h}
    :set-string 4    return {all-of g}
    execute-string {separate (newline) {all-of 1 2 3 4}}

How this works:  In Lakota functions are delimited by braces; the colon at
the beginning of the statement turns off symbol substitution [marked by
parentheses] and function expansion.  There is a single type, the indexed
list of strings.

The first statement in procedure compose sets the contents of the string
1 to be the text "procedure f".  The second sets the contents of string 2
to be the text "   h {all-arguments}" -- the colon tells the interpreter
to treat "{all-arguments}" as a literal rather than as a function to
evaluate.  The execute-string command takes its argument text as a string
to be executed (it may contain more than one statement).  In this case the
"all-of" function replaces each argument by its content list.  The "separate"
function interleaves its first argument between each of the remaining
arguments.  Newline is a language variable containing the newline character.
Now lets look at usage and results:

#   compose two procedures and print the composition

compose foobar foo bar
print {procedure foobar}

procedure foobar
   bar {all-arguments}
   foo {all-of bar}
   return {all-of foo}

As noted, the "procedure" function returns the contents of a procedure as
a text string.  How does procedure foobar work?  The "all-arguments" function
returns all of the arguments passed to a procedure.  Therefore bar gets passed
all of the arguments passed to foobar.  Lakota procedures return value lists
by setting the content list of the variable with the same name in the calling
procedure, i.e. variable bar will contain the return list from the invocation
of procedure bar.  The return list from bar is passed as arguments to foo.
Finally foobar returns the list of values returned by foo.  In conventional
mathematical notation:

	foobar(...) = foo(bar(...))

As a further illustration, without further tedious explanation, is a
procedure to do a curry.

procedure curry long short args
   :set-string aa {all-arguments}
   set-string 1 procedure (short)
   set-string 2   (long) {separate (space) {all-of args}} (LB)all-arguments(RB)
   set-string 3   return (LB)all-of (long)(RB)
   execute-string {separate (newline) {all-of 1 2 3}}

The call "curry + add1 1" generates the procedure

procedure add1
  + 1 {all-arguments}
  return {all-of +}

As a final example, here is a procedure that destroys itself when called:

procedure suicide
   print Goodbye cruel world!
   delete-procedure suicide

-----

I have some difficulty in determining whether it is meaningful to talk
about an "apply" procedure in Lakota in the sense that Justin is talking
about.  I think the problem is that Lakota lacks anonymous functions and
procedures, i.e. there is no lambda.  Capturing the text of a procedure
as a string is not equivalent because the procedure body contains the
name of the procedure in the definition.  [It is possible (and pointless)
to fake lambda.]  For that matter, I really don't see that "apply" goes
very far in the direction of self-modifying code.  What one really wants
is to not merely pass in arguments to be substituted, but also directions
on what is to be done, i.e. what sort of modifications are to be made.

-----

It seems to me that Justin has raised but failed to address the key
issue -- Why do we want to write self-modifying code?  Or to put it in
other terms -- What point is there in being able to dynamically generate
code?

In assembly language the traditional rationale is simple:  self-modifying
code saves space and time.  Essentially we save space by reusing "dead"
instruction space; we save time by removing conditional tests and
indirection.  However these genuflections to the bitch goddess of
efficiency really have little to do with the traditional motives for
self-modifying code in AI.  Unfortunately these traditional motives
seem to be a bit murky.

When we designed Lakota, one of the thoughts that we had in mind was that
we would put in the power to do all of that neat AI self-modifying code
stuff.  Some time ago I raised the question in comp.lang.misc as to what
these neat things were.  There was much discussion but little real meat.
The most substantial that I can recall is that you can write a debugger
for a language in itself -- a convenience to be sure, but scarcely the
rock on which you erect a philosophy of programming language design.

It does turn out that these fancy-dan constructs are useful in bread and
butter programming.  I just went browsing though a few thousand lines of
code and saw that "execute-string" was used fairly often.  The principal
usage is that an interface is dynamically computed; routines call the
routine which determines the interface; it in turn returns the code to
activate the interface.  Of course this sort of thing only works because
Lakota has a rich suite of text manipulation functionality.


-- 
In my lifetime we've had a Polish Pope.         | Richard Harter, SMDS Inc.
In my lifetime Communism has collapsed.         | Phone: 508-369-7398
In my lifetime Men have walked on the Moon.     | SMDS Inc. PO Box 555
But will the Red Sox ever win a world series?   | Concord MA 01742