about summary refs log tree commit diff stats
path: root/js/games/nluqo.github.io/~bh/v2ch5
diff options
context:
space:
mode:
authorelioat <elioat@tilde.institute>2023-08-23 07:52:19 -0400
committerelioat <elioat@tilde.institute>2023-08-23 07:52:19 -0400
commit562a9a52d599d9a05f871404050968a5fd282640 (patch)
tree7d3305c1252c043bfe246ccc7deff0056aa6b5ab /js/games/nluqo.github.io/~bh/v2ch5
parent5d012c6c011a9dedf7d0a098e456206244eb5a0f (diff)
downloadtour-562a9a52d599d9a05f871404050968a5fd282640.tar.gz
*
Diffstat (limited to 'js/games/nluqo.github.io/~bh/v2ch5')
-rw-r--r--js/games/nluqo.github.io/~bh/v2ch5/prgdat.html499
-rw-r--r--js/games/nluqo.github.io/~bh/v2ch5/v2ch5.html499
2 files changed, 998 insertions, 0 deletions
diff --git a/js/games/nluqo.github.io/~bh/v2ch5/prgdat.html b/js/games/nluqo.github.io/~bh/v2ch5/prgdat.html
new file mode 100644
index 0000000..4023574
--- /dev/null
+++ b/js/games/nluqo.github.io/~bh/v2ch5/prgdat.html
@@ -0,0 +1,499 @@
+<HTML>
+<HEAD>
+<TITLE>Computer Science Logo Style vol 2 ch 5: Program as Data</TITLE>
+</HEAD>
+<BODY>
+<CITE>Computer Science Logo Style</CITE> volume 2:
+<CITE>Advanced Techniques</CITE> 2/e Copyright (C) 1997 MIT
+<H1>Program as Data</H1>
+
+<TABLE width="100%"><TR><TD>
+<IMG SRC="../csls2.jpg" ALT="cover photo">
+<TD><TABLE>
+<TR><TD align="right"><CITE><A HREF="http://www.cs.berkeley.edu/~bh/">Brian
+Harvey</A><BR>University of California, Berkeley</CITE>
+<TR><TD align="right"><BR>
+<TR><TD align="right"><A HREF="../pdf/v2ch05.pdf">Download PDF version</A>
+<TR><TD align="right"><A HREF="../v2-toc2.html">Back to Table of Contents</A>
+<TR><TD align="right"><A HREF="../v2ch4/v2ch4.html"><STRONG>BACK</STRONG></A>
+chapter thread <A HREF="../v2ch6/v2ch6.html"><STRONG>NEXT</STRONG></A>
+<TR><TD align="right"><A HREF="https://mitpress.mit.edu/books/computer-science-logo-style-second-edition-volume-2">MIT
+Press web page for <CITE>Computer Science Logo Style</CITE></A>
+</TABLE></TABLE>
+
+<HR>
+
+<P>
+In most programming languages there is a sharp distinction between
+<EM>program</EM> and <EM>data.</EM>  Data are the things you can
+manipulate in your program, things like numbers and letters.  These
+things live in variables, which can be given new values by your
+program.  But the program itself is not subject to manipulation; it's
+something you write ahead of time, and then it remains fixed.
+
+<P>
+In Logo the distinction is not so sharp.  We've made extensive use of one
+mechanism by which a program can manipulate itself: the instruction lists
+that are used as inputs to <CODE>run</CODE>, <CODE>if</CODE>, and so on are
+data that can be computed by a program.  For example, the solitaire program
+in Chapter 4 constructs a list of Logo instruction lists, each of
+which would move a card to some other legal position, and then says
+
+<PRE>
+run first :onto
+</PRE>
+
+<P>
+to move the card to the first such position.
+
+<H2><CODE>Text</CODE> and <CODE>Define</CODE></H2>
+
+<P>
+In this chapter we'll use a pair of more advanced tools that allow a
+program to create more program.  <CODE>Run</CODE> deals with a single
+<EM>instruction;</EM> now we'll be able to examine and create
+<EM>procedures.</EM>
+
+<P>
+<CODE>Text</CODE> is an operation that takes one input, a word.  That word
+must be the name of a user-defined procedure.  The output from
+<CODE>text</CODE> is a list.  The first member of that list is a list
+containing the names of the inputs to the chosen procedure.  (If the
+procedure has no inputs, the list will be empty.)*  The remaining
+members of the output list are instruction lists, one for each line in the
+definition of the procedure.
+
+<P>
+<SMALL><BLOCKQUOTE><SMALL><SUP>*</SUP>Berkeley Logo allows user-defined
+procedures with <EM>optional</EM> inputs.  For such a procedure, this first
+sublist may contain lists, representing optional inputs, as well as words,
+representing required inputs.</SMALL></BLOCKQUOTE></SMALL>
+
+<P>
+Here is an example.  Suppose we've defined the procedure
+
+<PRE>
+to opinion :yes :no
+print sentence [I like] :yes
+print sentence [I hate] :no
+end
+</PRE>
+
+<P>
+Here's what the text of that procedure looks like:
+
+<PRE>
+? <U>show text "opinion</U>
+[[yes no] [print sentence [I like] :yes] [print sentence [I hate] :no]]
+</PRE>
+
+<P>
+In this example the output from <CODE>text</CODE> is a list with three
+members.  The first member is a list containing the words <CODE>yes</CODE>
+and <CODE>no</CODE>, the names of <CODE>opinion</CODE>'s inputs.  (Note that
+the colons that are used to indicate inputs in a title line are <EM>not</EM>
+used here.) The second and third members of the output list are instruction
+lists, one for each line in the definition.  (Note that there is no
+<CODE>end</CODE> line in the definition; as I've remarked before, that line
+isn't an instruction in the procedure because <CODE>end</CODE> isn't a
+command.)
+
+<P>
+The opposite of <CODE>text</CODE> is the command <CODE>define</CODE>.  This
+command takes two inputs.  The first must be a word and the second a list.
+The effect of <CODE>define</CODE> is to define a procedure whose name is the
+first input and whose text is the second input.  You can use
+<CODE>define</CODE> to define a new procedure or to change the definition of
+an old one.  For example, I might redefine <CODE>opinion</CODE>:
+
+<PRE>
+? <U>define "opinion [[yes no] [print sentence :yes [is yummy.]]</U>
+                            <U>[print sentence :no [is yucky.]]]</U>
+? <U>opinion [Ice cream] "Cheese</U>
+Ice cream is yummy.
+Cheese is yucky.
+? <U>po "opinion</U>
+to opinion :yes :no
+print sentence :yes [is yummy.]
+print sentence :no [is yucky.]
+end
+</PRE>
+
+<P>
+Instead of replacing an old definition with an entirely new one, we
+can use <CODE>define</CODE> and <CODE>text</CODE> together to change a procedure's
+definition:
+
+<PRE>
+? <U>define "opinion lput [print sentence :no "stinks!] ~</U>
+                       <U>butlast text "opinion</U>
+? <U>opinion "Logo "Basic</U>
+Logo is yummy.
+Basic stinks!
+</PRE>
+
+<P>
+(Of course, I didn't have to redefine the same procedure
+name.  I could have said
+
+<PRE>
+? <U>define "strong.opinion ~</U>
+         <U>lput [print sentence :no "stinks!] butlast text "opinion</U>
+</PRE>
+
+<P>
+and then I would have had two procedures, the unchanged
+<CODE>opinion</CODE> and the new version named <CODE>strong.opinion</CODE>.)
+
+<P>
+It may be instructive to consider the analogy between <EM>variables,</EM>
+which hold data, and <EM>procedures,</EM> which hold instructions.
+Variables are given values with the <CODE>make</CODE> command and examined
+with the operation <CODE>thing</CODE>.  Procedures are given definitions with
+the <CODE>define</CODE> command and examined with the operation
+<CODE>text</CODE>.  (There is no abbreviation for <CODE>text</CODE>-quote,
+however, like the dots abbreviation for <CODE>thing</CODE>-quote.)
+
+<P>
+To illustrate <CODE>define</CODE> and <CODE>text</CODE>, I've used them in
+instructions typed in at top level.  In practice, you wouldn't use
+them that way; it's easier to examine a procedure with <CODE>po</CODE> and to
+change its definition with <CODE>edit</CODE>.  <CODE>Text</CODE> and <CODE>define</CODE>
+are meant to be used not at top level but inside a program.
+
+<H2>Automated Definition</H2>
+
+<P>
+Early in the first volume I defined the operation <CODE>second</CODE> this way:
+
+<PRE>
+to second :thing
+output first butfirst :thing
+end
+</PRE>
+
+<P>
+Suppose I want more operations following this model, to be
+called <CODE>third</CODE>, <CODE>fourth</CODE>, and so on.  I could define them all
+by hand or I could write a program to do it for me:
+
+<PRE>
+to ordinals
+ord1 [second third fourth fifth sixth seventh] [output first butfirst]
+end
+
+to ord1 :names :instr
+if emptyp :names [stop]
+define first :names list [thing] (lput ":thing :instr)
+ord1 (butfirst :names) (lput "butfirst :instr)
+end
+
+? <U>ordinals</U>
+? <U>po "fifth</U>
+to fifth :thing
+output first butfirst butfirst butfirst butfirst :thing
+end
+</PRE>
+
+<P>
+(The name <CODE>ordinals</CODE> comes from the phrase <EM>ordinal
+numbers,</EM> which is what things like &quot;third&quot; are called.  Regular
+numbers like &quot;three&quot; are called <EM>cardinal numbers.</EM>) This procedure
+automatically defined new procedures named <CODE>second</CODE> through
+<CODE>seventh</CODE>, each with one more <CODE>butfirst</CODE> in its
+instruction line.
+
+<H2>A Single-Keystroke Program Generator</H2>
+
+<P>
+A fairly common thing to do in Logo is to write a little program that
+lets you type a single character on the keyboard to carry out some
+instruction.  For example, teachers of very young children sometimes
+use a program that accepts <CODE>F</CODE> to move the turtle forward some
+distance, <CODE>B</CODE> for back, and <CODE>L</CODE> and <CODE>R</CODE> for left and
+right.  What I want to write is a <EM>program-writing program</EM> that
+will accept a name and a list of keystrokes and instructions as
+inputs and define a procedure with that name that understands those
+instructions.
+
+<PRE>
+to onekey :name :list
+local "text
+make "text [[] [local "char] [print [Type ? for help]]
+            [make "char readchar]]
+foreach :list [make "text lput (sentence [if equalp :char]
+                                         (word "" first ?)
+                                         butfirst ?)
+                               :text]
+make "text lput (lput (list "foreach :list ""print)
+                      [if equalp :char "?]) ~
+                :text
+make "text lput (list :name) :text
+define :name :text
+end
+</PRE>
+
+<P>
+If we use this program with the instruction
+
+<PRE>
+onekey "instant [[F [forward 20]] [B [back 20]]
+                 [L [left 15]] [R [right 15]]]
+</PRE>
+
+<P>
+then it creates the following procedure:
+
+<PRE>
+to instant
+local "char
+print [type ? for help]
+make "char readchar
+if equalp :char "F [forward 20]
+if equalp :char "B [back 20]
+if equalp :char "L [left 15]
+if equalp :char "R [right 15]
+if equalp :char "? [foreach [[F [forward 20]] [B [back 20]]
+                             [L [left 15]] [R [right 15]]]
+                            "print]
+instant
+end
+</PRE>
+
+<P>
+In addition to illustrating the use of <CODE>define</CODE>, this program
+demonstrates how <CODE>sentence</CODE>, <CODE>list</CODE>, and <CODE>lput</CODE> can
+all be useful in constructing lists, when you have to combine some
+constant members with some variable members.
+
+<P>
+Of course, if we only want to make one <CODE>instant</CODE> program, it's
+easier just to type it in.  An automatic procedure like <CODE>onekey</CODE>
+is useful when you want to create several different procedures like
+<CODE>instant</CODE>, each with a different &quot;menu&quot; of characters.  For
+example, consider these instructions:
+
+<PRE>
+onekey "instant [[F [forward 20]] [B [back 20]]
+                 [L [left 15]] [R [right 15]] [P [pens]]]
+onekey "pens [[U [penup stop]] [D [pendown stop]] [E [penerase stop]]]
+</PRE>
+
+<P>
+With these definitions, typing <CODE>P</CODE> to <CODE>instant</CODE>
+prepares to accept a pen command from the second list.  In effect,
+<CODE>instant</CODE> recognizes two-letter commands <CODE>PU</CODE> for <CODE>penup</CODE>
+and so on, except that the sequence <CODE>P?</CODE> will display the help
+information for just the pen commands.  Here's another example:
+
+<PRE>
+onekey "tinyturns [[F [forward 20]] [B [back 20]]
+                   [L [left 5]] [R [right 5]] [H [hugeturns]]]
+onekey "hugeturns [[F [forward 20]] [B [back 20]]
+                   [L [left 45]] [R [right 45]] [T [tinyturns]]]
+</PRE>
+
+<H2>Procedure Cross-Reference Listings</H2>
+
+<P>
+When you're working on a very large project, it's easy to lose track
+of which procedure invokes which other one.  We can use the computer
+to help solve this problem by
+creating a <EM>cross-reference listing</EM> for all
+the procedures in a project.  For every procedure
+in the project, a cross-reference listing tells which other procedures
+invoke that one.  If you write long procedures, it can also be helpful
+to list which instruction line in procedure <CODE>A</CODE> invokes procedure
+<CODE>B</CODE>.
+
+<P>
+The general strategy will be to look through the <CODE>text</CODE> of every
+procedure, looking for the name of the procedure we're interested in.
+Suppose we're finding all the references to procedure <CODE>X</CODE> and
+we're looking through procedures <CODE>A</CODE>, <CODE>B</CODE>, and
+<CODE>C</CODE>.  For each line of each procedure, we want to know whether
+the word <CODE>X</CODE> appears in that line.  (Of course you would not
+really name a procedure <CODE>A</CODE> or <CODE>X</CODE>.  You'd use
+meaningful names.  This is just an example.)  We can't, however, just test
+
+<PRE>
+memberp "x :instr
+</PRE>
+
+<P>
+(I'm imagining that the variable <CODE>instr</CODE> contains an
+instruction line.) The reason is that a procedure invocation can be
+part of a <EM>sublist</EM> of the instruction list if <CODE>X</CODE> is
+invoked by way of something like <CODE>if</CODE>.  For example, the word
+<CODE>X</CODE> is not a member of the list
+
+<PRE>
+[if emptyp :list [x :foo stop]]
+</PRE>
+
+<P>
+But it's a member of a member.  (Earlier I made a big fuss about the fact
+that if that instruction were part of procedure <CODE>A</CODE>, it's
+actually <CODE>if</CODE> that invokes <CODE>X</CODE>, not <CODE>A</CODE>.
+That's the true story, for the Logo interpreter.  But for purposes of a
+cross-reference listing, it does us no good to know that <CODE>if</CODE>
+invokes <CODE>X</CODE>; what we want to know is which procedure definition to
+look at if we want to find the instruction that uses <CODE>X</CODE>.)
+
+<P>
+So the first thing we need is a procedure <CODE>submemberp</CODE> that takes
+inputs like those of <CODE>memberp</CODE> but outputs <CODE>true</CODE> if the
+first input is a member of the second, or a member of a member, and so
+on.
+
+<PRE>
+to submemberp :thing :list
+if emptyp :list [output "false]
+if equalp :thing first :list [output "true]
+if listp first :list ~
+   [if submemberp :thing first :list [output "true]]
+output submemberp :thing butfirst :list
+end
+</PRE>
+
+<P>
+Now we want a procedure that will take two words as input, both of
+which are the names of procedures, and will print a list of all the
+references to the first procedure in the text of the second.
+
+<PRE>
+to reference :target :examinee
+ref1 :target :examinee butfirst text :examinee 1
+end
+
+to ref1 :target :examinee :instrs :linenum
+if emptyp :instrs [stop]
+if submemberp :target first :instrs ~
+   [print sentence "|   | (word :examinee "\( :linenum "\) )]
+ref1 :target :examinee butfirst :instrs :linenum+1
+end
+</PRE>
+
+<P>
+<CODE>Reference</CODE> uses <CODE>butfirst text :examinee</CODE> as the third
+input to <CODE>ref1</CODE> to avoid the list of inputs to the procedure we're
+examining.  That's because one of those inputs might have the same name as
+the <CODE>target</CODE> procedure, and we'd get a false indication of
+success.  (In the body of the definition of <CODE>:examinee</CODE>, any
+reference to a variable named <CODE>X</CODE> will not use the word
+<CODE>X</CODE> but rather the word <CODE>"X</CODE> or the word
+<CODE>:X</CODE>.  You may find that statement confusing.  When you type an
+<EM>instruction</EM> like
+
+<PRE>
+print "foo
+</PRE>
+
+<P>
+the Logo evaluator interprets <CODE>"foo</CODE> as a request for the word
+<CODE>foo</CODE>, quoted (as opposed to evaluated).  So <CODE>print</CODE>
+won't print a quotation mark.  But if we look at the <EM>list</EM>
+
+<PRE>
+[print "foo]
+</PRE>
+
+<P>
+then we are not, right now, evaluating it as a Logo
+instruction.  The second member of that list is the word <CODE>"foo</CODE>,
+quote mark and all.)
+
+<P>
+We can still get &quot;false hits,&quot; finding the word <CODE>X</CODE>
+(or whatever procedure name we're looking for) in an instruction list,
+but not being used as a procedure name:
+
+<PRE>
+print [w x y z]
+</PRE>
+
+<P>
+But cases like that will be relatively rare compared to the
+cases of variables and procedures with the same name.
+
+<P>
+The reason I'm printing spaces before the information is that I'm
+working toward a listing that will look like this:
+
+<PRE>
+target1
+   proca(3)
+   procb(1)
+   procc(4)
+target2
+   procb(3)
+   procb(4)
+</PRE>
+
+<P>
+This means that the procedure named <CODE>target1</CODE> is invoked
+in each of the procedures <CODE>proca</CODE>, <CODE>procb</CODE>, and <CODE>procc</CODE>;
+procedure <CODE>target2</CODE> is invoked by <CODE>procb</CODE> on two different
+instruction lines.
+
+<P>
+Okay, now we can find references to one specific procedure within the
+text of another specific procedure.  Now we want to look for
+references to one procedure within <EM>all</EM> the procedures making up
+a project.
+
+<PRE>
+to xref :target :list
+print :target
+foreach :list [reference :target ?]
+end
+</PRE>
+
+<P>
+We're almost done.  Now we want to apply <CODE>xref</CODE> to every
+procedure in the project.  This involves another run through the list
+of projects:
+
+<PRE>
+to xrefall :list
+foreach :list [xref ? :list]
+end
+</PRE>
+
+<P>
+To use this program to make a cross-reference listing of
+itself, you'd say
+
+<PRE>
+xrefall [xrefall xref reference ref1 submemberp]
+</PRE>
+
+<P>
+To cross-reference all of the procedures in your workspace,
+you'd say
+
+<PRE>
+xrefall procedures
+</PRE>
+
+<P>
+If you try this program on a project with a large number of procedures,
+you should expect it to take a <EM>long</EM> time.  If there
+are five procedures, we have to examine each of them for
+references to each of them, so we invoke <CODE>reference</CODE> 25 times.  If
+there are 10 procedures, we invoke <CODE>reference</CODE> 100 times!  In
+general, the number of invocations is the square of the number of
+procedures.  The fancy way to say this is that the program &quot;takes
+quadratic time&quot; or that it &quot;behaves quadratically.&quot;
+
+<P><A HREF="../v2-toc2.html">(back to Table of Contents)</A>
+<P><A HREF="../v2ch4/v2ch4.html"><STRONG>BACK</STRONG></A>
+chapter thread <A HREF="../v2ch6/v2ch6.html"><STRONG>NEXT</STRONG></A>
+
+<P>
+<ADDRESS>
+<A HREF="../index.html">Brian Harvey</A>, 
+<CODE>bh@cs.berkeley.edu</CODE>
+</ADDRESS>
+</BODY>
+</HTML>
diff --git a/js/games/nluqo.github.io/~bh/v2ch5/v2ch5.html b/js/games/nluqo.github.io/~bh/v2ch5/v2ch5.html
new file mode 100644
index 0000000..4023574
--- /dev/null
+++ b/js/games/nluqo.github.io/~bh/v2ch5/v2ch5.html
@@ -0,0 +1,499 @@
+<HTML>
+<HEAD>
+<TITLE>Computer Science Logo Style vol 2 ch 5: Program as Data</TITLE>
+</HEAD>
+<BODY>
+<CITE>Computer Science Logo Style</CITE> volume 2:
+<CITE>Advanced Techniques</CITE> 2/e Copyright (C) 1997 MIT
+<H1>Program as Data</H1>
+
+<TABLE width="100%"><TR><TD>
+<IMG SRC="../csls2.jpg" ALT="cover photo">
+<TD><TABLE>
+<TR><TD align="right"><CITE><A HREF="http://www.cs.berkeley.edu/~bh/">Brian
+Harvey</A><BR>University of California, Berkeley</CITE>
+<TR><TD align="right"><BR>
+<TR><TD align="right"><A HREF="../pdf/v2ch05.pdf">Download PDF version</A>
+<TR><TD align="right"><A HREF="../v2-toc2.html">Back to Table of Contents</A>
+<TR><TD align="right"><A HREF="../v2ch4/v2ch4.html"><STRONG>BACK</STRONG></A>
+chapter thread <A HREF="../v2ch6/v2ch6.html"><STRONG>NEXT</STRONG></A>
+<TR><TD align="right"><A HREF="https://mitpress.mit.edu/books/computer-science-logo-style-second-edition-volume-2">MIT
+Press web page for <CITE>Computer Science Logo Style</CITE></A>
+</TABLE></TABLE>
+
+<HR>
+
+<P>
+In most programming languages there is a sharp distinction between
+<EM>program</EM> and <EM>data.</EM>  Data are the things you can
+manipulate in your program, things like numbers and letters.  These
+things live in variables, which can be given new values by your
+program.  But the program itself is not subject to manipulation; it's
+something you write ahead of time, and then it remains fixed.
+
+<P>
+In Logo the distinction is not so sharp.  We've made extensive use of one
+mechanism by which a program can manipulate itself: the instruction lists
+that are used as inputs to <CODE>run</CODE>, <CODE>if</CODE>, and so on are
+data that can be computed by a program.  For example, the solitaire program
+in Chapter 4 constructs a list of Logo instruction lists, each of
+which would move a card to some other legal position, and then says
+
+<PRE>
+run first :onto
+</PRE>
+
+<P>
+to move the card to the first such position.
+
+<H2><CODE>Text</CODE> and <CODE>Define</CODE></H2>
+
+<P>
+In this chapter we'll use a pair of more advanced tools that allow a
+program to create more program.  <CODE>Run</CODE> deals with a single
+<EM>instruction;</EM> now we'll be able to examine and create
+<EM>procedures.</EM>
+
+<P>
+<CODE>Text</CODE> is an operation that takes one input, a word.  That word
+must be the name of a user-defined procedure.  The output from
+<CODE>text</CODE> is a list.  The first member of that list is a list
+containing the names of the inputs to the chosen procedure.  (If the
+procedure has no inputs, the list will be empty.)*  The remaining
+members of the output list are instruction lists, one for each line in the
+definition of the procedure.
+
+<P>
+<SMALL><BLOCKQUOTE><SMALL><SUP>*</SUP>Berkeley Logo allows user-defined
+procedures with <EM>optional</EM> inputs.  For such a procedure, this first
+sublist may contain lists, representing optional inputs, as well as words,
+representing required inputs.</SMALL></BLOCKQUOTE></SMALL>
+
+<P>
+Here is an example.  Suppose we've defined the procedure
+
+<PRE>
+to opinion :yes :no
+print sentence [I like] :yes
+print sentence [I hate] :no
+end
+</PRE>
+
+<P>
+Here's what the text of that procedure looks like:
+
+<PRE>
+? <U>show text "opinion</U>
+[[yes no] [print sentence [I like] :yes] [print sentence [I hate] :no]]
+</PRE>
+
+<P>
+In this example the output from <CODE>text</CODE> is a list with three
+members.  The first member is a list containing the words <CODE>yes</CODE>
+and <CODE>no</CODE>, the names of <CODE>opinion</CODE>'s inputs.  (Note that
+the colons that are used to indicate inputs in a title line are <EM>not</EM>
+used here.) The second and third members of the output list are instruction
+lists, one for each line in the definition.  (Note that there is no
+<CODE>end</CODE> line in the definition; as I've remarked before, that line
+isn't an instruction in the procedure because <CODE>end</CODE> isn't a
+command.)
+
+<P>
+The opposite of <CODE>text</CODE> is the command <CODE>define</CODE>.  This
+command takes two inputs.  The first must be a word and the second a list.
+The effect of <CODE>define</CODE> is to define a procedure whose name is the
+first input and whose text is the second input.  You can use
+<CODE>define</CODE> to define a new procedure or to change the definition of
+an old one.  For example, I might redefine <CODE>opinion</CODE>:
+
+<PRE>
+? <U>define "opinion [[yes no] [print sentence :yes [is yummy.]]</U>
+                            <U>[print sentence :no [is yucky.]]]</U>
+? <U>opinion [Ice cream] "Cheese</U>
+Ice cream is yummy.
+Cheese is yucky.
+? <U>po "opinion</U>
+to opinion :yes :no
+print sentence :yes [is yummy.]
+print sentence :no [is yucky.]
+end
+</PRE>
+
+<P>
+Instead of replacing an old definition with an entirely new one, we
+can use <CODE>define</CODE> and <CODE>text</CODE> together to change a procedure's
+definition:
+
+<PRE>
+? <U>define "opinion lput [print sentence :no "stinks!] ~</U>
+                       <U>butlast text "opinion</U>
+? <U>opinion "Logo "Basic</U>
+Logo is yummy.
+Basic stinks!
+</PRE>
+
+<P>
+(Of course, I didn't have to redefine the same procedure
+name.  I could have said
+
+<PRE>
+? <U>define "strong.opinion ~</U>
+         <U>lput [print sentence :no "stinks!] butlast text "opinion</U>
+</PRE>
+
+<P>
+and then I would have had two procedures, the unchanged
+<CODE>opinion</CODE> and the new version named <CODE>strong.opinion</CODE>.)
+
+<P>
+It may be instructive to consider the analogy between <EM>variables,</EM>
+which hold data, and <EM>procedures,</EM> which hold instructions.
+Variables are given values with the <CODE>make</CODE> command and examined
+with the operation <CODE>thing</CODE>.  Procedures are given definitions with
+the <CODE>define</CODE> command and examined with the operation
+<CODE>text</CODE>.  (There is no abbreviation for <CODE>text</CODE>-quote,
+however, like the dots abbreviation for <CODE>thing</CODE>-quote.)
+
+<P>
+To illustrate <CODE>define</CODE> and <CODE>text</CODE>, I've used them in
+instructions typed in at top level.  In practice, you wouldn't use
+them that way; it's easier to examine a procedure with <CODE>po</CODE> and to
+change its definition with <CODE>edit</CODE>.  <CODE>Text</CODE> and <CODE>define</CODE>
+are meant to be used not at top level but inside a program.
+
+<H2>Automated Definition</H2>
+
+<P>
+Early in the first volume I defined the operation <CODE>second</CODE> this way:
+
+<PRE>
+to second :thing
+output first butfirst :thing
+end
+</PRE>
+
+<P>
+Suppose I want more operations following this model, to be
+called <CODE>third</CODE>, <CODE>fourth</CODE>, and so on.  I could define them all
+by hand or I could write a program to do it for me:
+
+<PRE>
+to ordinals
+ord1 [second third fourth fifth sixth seventh] [output first butfirst]
+end
+
+to ord1 :names :instr
+if emptyp :names [stop]
+define first :names list [thing] (lput ":thing :instr)
+ord1 (butfirst :names) (lput "butfirst :instr)
+end
+
+? <U>ordinals</U>
+? <U>po "fifth</U>
+to fifth :thing
+output first butfirst butfirst butfirst butfirst :thing
+end
+</PRE>
+
+<P>
+(The name <CODE>ordinals</CODE> comes from the phrase <EM>ordinal
+numbers,</EM> which is what things like &quot;third&quot; are called.  Regular
+numbers like &quot;three&quot; are called <EM>cardinal numbers.</EM>) This procedure
+automatically defined new procedures named <CODE>second</CODE> through
+<CODE>seventh</CODE>, each with one more <CODE>butfirst</CODE> in its
+instruction line.
+
+<H2>A Single-Keystroke Program Generator</H2>
+
+<P>
+A fairly common thing to do in Logo is to write a little program that
+lets you type a single character on the keyboard to carry out some
+instruction.  For example, teachers of very young children sometimes
+use a program that accepts <CODE>F</CODE> to move the turtle forward some
+distance, <CODE>B</CODE> for back, and <CODE>L</CODE> and <CODE>R</CODE> for left and
+right.  What I want to write is a <EM>program-writing program</EM> that
+will accept a name and a list of keystrokes and instructions as
+inputs and define a procedure with that name that understands those
+instructions.
+
+<PRE>
+to onekey :name :list
+local "text
+make "text [[] [local "char] [print [Type ? for help]]
+            [make "char readchar]]
+foreach :list [make "text lput (sentence [if equalp :char]
+                                         (word "" first ?)
+                                         butfirst ?)
+                               :text]
+make "text lput (lput (list "foreach :list ""print)
+                      [if equalp :char "?]) ~
+                :text
+make "text lput (list :name) :text
+define :name :text
+end
+</PRE>
+
+<P>
+If we use this program with the instruction
+
+<PRE>
+onekey "instant [[F [forward 20]] [B [back 20]]
+                 [L [left 15]] [R [right 15]]]
+</PRE>
+
+<P>
+then it creates the following procedure:
+
+<PRE>
+to instant
+local "char
+print [type ? for help]
+make "char readchar
+if equalp :char "F [forward 20]
+if equalp :char "B [back 20]
+if equalp :char "L [left 15]
+if equalp :char "R [right 15]
+if equalp :char "? [foreach [[F [forward 20]] [B [back 20]]
+                             [L [left 15]] [R [right 15]]]
+                            "print]
+instant
+end
+</PRE>
+
+<P>
+In addition to illustrating the use of <CODE>define</CODE>, this program
+demonstrates how <CODE>sentence</CODE>, <CODE>list</CODE>, and <CODE>lput</CODE> can
+all be useful in constructing lists, when you have to combine some
+constant members with some variable members.
+
+<P>
+Of course, if we only want to make one <CODE>instant</CODE> program, it's
+easier just to type it in.  An automatic procedure like <CODE>onekey</CODE>
+is useful when you want to create several different procedures like
+<CODE>instant</CODE>, each with a different &quot;menu&quot; of characters.  For
+example, consider these instructions:
+
+<PRE>
+onekey "instant [[F [forward 20]] [B [back 20]]
+                 [L [left 15]] [R [right 15]] [P [pens]]]
+onekey "pens [[U [penup stop]] [D [pendown stop]] [E [penerase stop]]]
+</PRE>
+
+<P>
+With these definitions, typing <CODE>P</CODE> to <CODE>instant</CODE>
+prepares to accept a pen command from the second list.  In effect,
+<CODE>instant</CODE> recognizes two-letter commands <CODE>PU</CODE> for <CODE>penup</CODE>
+and so on, except that the sequence <CODE>P?</CODE> will display the help
+information for just the pen commands.  Here's another example:
+
+<PRE>
+onekey "tinyturns [[F [forward 20]] [B [back 20]]
+                   [L [left 5]] [R [right 5]] [H [hugeturns]]]
+onekey "hugeturns [[F [forward 20]] [B [back 20]]
+                   [L [left 45]] [R [right 45]] [T [tinyturns]]]
+</PRE>
+
+<H2>Procedure Cross-Reference Listings</H2>
+
+<P>
+When you're working on a very large project, it's easy to lose track
+of which procedure invokes which other one.  We can use the computer
+to help solve this problem by
+creating a <EM>cross-reference listing</EM> for all
+the procedures in a project.  For every procedure
+in the project, a cross-reference listing tells which other procedures
+invoke that one.  If you write long procedures, it can also be helpful
+to list which instruction line in procedure <CODE>A</CODE> invokes procedure
+<CODE>B</CODE>.
+
+<P>
+The general strategy will be to look through the <CODE>text</CODE> of every
+procedure, looking for the name of the procedure we're interested in.
+Suppose we're finding all the references to procedure <CODE>X</CODE> and
+we're looking through procedures <CODE>A</CODE>, <CODE>B</CODE>, and
+<CODE>C</CODE>.  For each line of each procedure, we want to know whether
+the word <CODE>X</CODE> appears in that line.  (Of course you would not
+really name a procedure <CODE>A</CODE> or <CODE>X</CODE>.  You'd use
+meaningful names.  This is just an example.)  We can't, however, just test
+
+<PRE>
+memberp "x :instr
+</PRE>
+
+<P>
+(I'm imagining that the variable <CODE>instr</CODE> contains an
+instruction line.) The reason is that a procedure invocation can be
+part of a <EM>sublist</EM> of the instruction list if <CODE>X</CODE> is
+invoked by way of something like <CODE>if</CODE>.  For example, the word
+<CODE>X</CODE> is not a member of the list
+
+<PRE>
+[if emptyp :list [x :foo stop]]
+</PRE>
+
+<P>
+But it's a member of a member.  (Earlier I made a big fuss about the fact
+that if that instruction were part of procedure <CODE>A</CODE>, it's
+actually <CODE>if</CODE> that invokes <CODE>X</CODE>, not <CODE>A</CODE>.
+That's the true story, for the Logo interpreter.  But for purposes of a
+cross-reference listing, it does us no good to know that <CODE>if</CODE>
+invokes <CODE>X</CODE>; what we want to know is which procedure definition to
+look at if we want to find the instruction that uses <CODE>X</CODE>.)
+
+<P>
+So the first thing we need is a procedure <CODE>submemberp</CODE> that takes
+inputs like those of <CODE>memberp</CODE> but outputs <CODE>true</CODE> if the
+first input is a member of the second, or a member of a member, and so
+on.
+
+<PRE>
+to submemberp :thing :list
+if emptyp :list [output "false]
+if equalp :thing first :list [output "true]
+if listp first :list ~
+   [if submemberp :thing first :list [output "true]]
+output submemberp :thing butfirst :list
+end
+</PRE>
+
+<P>
+Now we want a procedure that will take two words as input, both of
+which are the names of procedures, and will print a list of all the
+references to the first procedure in the text of the second.
+
+<PRE>
+to reference :target :examinee
+ref1 :target :examinee butfirst text :examinee 1
+end
+
+to ref1 :target :examinee :instrs :linenum
+if emptyp :instrs [stop]
+if submemberp :target first :instrs ~
+   [print sentence "|   | (word :examinee "\( :linenum "\) )]
+ref1 :target :examinee butfirst :instrs :linenum+1
+end
+</PRE>
+
+<P>
+<CODE>Reference</CODE> uses <CODE>butfirst text :examinee</CODE> as the third
+input to <CODE>ref1</CODE> to avoid the list of inputs to the procedure we're
+examining.  That's because one of those inputs might have the same name as
+the <CODE>target</CODE> procedure, and we'd get a false indication of
+success.  (In the body of the definition of <CODE>:examinee</CODE>, any
+reference to a variable named <CODE>X</CODE> will not use the word
+<CODE>X</CODE> but rather the word <CODE>"X</CODE> or the word
+<CODE>:X</CODE>.  You may find that statement confusing.  When you type an
+<EM>instruction</EM> like
+
+<PRE>
+print "foo
+</PRE>
+
+<P>
+the Logo evaluator interprets <CODE>"foo</CODE> as a request for the word
+<CODE>foo</CODE>, quoted (as opposed to evaluated).  So <CODE>print</CODE>
+won't print a quotation mark.  But if we look at the <EM>list</EM>
+
+<PRE>
+[print "foo]
+</PRE>
+
+<P>
+then we are not, right now, evaluating it as a Logo
+instruction.  The second member of that list is the word <CODE>"foo</CODE>,
+quote mark and all.)
+
+<P>
+We can still get &quot;false hits,&quot; finding the word <CODE>X</CODE>
+(or whatever procedure name we're looking for) in an instruction list,
+but not being used as a procedure name:
+
+<PRE>
+print [w x y z]
+</PRE>
+
+<P>
+But cases like that will be relatively rare compared to the
+cases of variables and procedures with the same name.
+
+<P>
+The reason I'm printing spaces before the information is that I'm
+working toward a listing that will look like this:
+
+<PRE>
+target1
+   proca(3)
+   procb(1)
+   procc(4)
+target2
+   procb(3)
+   procb(4)
+</PRE>
+
+<P>
+This means that the procedure named <CODE>target1</CODE> is invoked
+in each of the procedures <CODE>proca</CODE>, <CODE>procb</CODE>, and <CODE>procc</CODE>;
+procedure <CODE>target2</CODE> is invoked by <CODE>procb</CODE> on two different
+instruction lines.
+
+<P>
+Okay, now we can find references to one specific procedure within the
+text of another specific procedure.  Now we want to look for
+references to one procedure within <EM>all</EM> the procedures making up
+a project.
+
+<PRE>
+to xref :target :list
+print :target
+foreach :list [reference :target ?]
+end
+</PRE>
+
+<P>
+We're almost done.  Now we want to apply <CODE>xref</CODE> to every
+procedure in the project.  This involves another run through the list
+of projects:
+
+<PRE>
+to xrefall :list
+foreach :list [xref ? :list]
+end
+</PRE>
+
+<P>
+To use this program to make a cross-reference listing of
+itself, you'd say
+
+<PRE>
+xrefall [xrefall xref reference ref1 submemberp]
+</PRE>
+
+<P>
+To cross-reference all of the procedures in your workspace,
+you'd say
+
+<PRE>
+xrefall procedures
+</PRE>
+
+<P>
+If you try this program on a project with a large number of procedures,
+you should expect it to take a <EM>long</EM> time.  If there
+are five procedures, we have to examine each of them for
+references to each of them, so we invoke <CODE>reference</CODE> 25 times.  If
+there are 10 procedures, we invoke <CODE>reference</CODE> 100 times!  In
+general, the number of invocations is the square of the number of
+procedures.  The fancy way to say this is that the program &quot;takes
+quadratic time&quot; or that it &quot;behaves quadratically.&quot;
+
+<P><A HREF="../v2-toc2.html">(back to Table of Contents)</A>
+<P><A HREF="../v2ch4/v2ch4.html"><STRONG>BACK</STRONG></A>
+chapter thread <A HREF="../v2ch6/v2ch6.html"><STRONG>NEXT</STRONG></A>
+
+<P>
+<ADDRESS>
+<A HREF="../index.html">Brian Harvey</A>, 
+<CODE>bh@cs.berkeley.edu</CODE>
+</ADDRESS>
+</BODY>
+</HTML>