⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tut.html

📁 A very small LISP implementation with several packages and demo programs.
💻 HTML
📖 第 1 页 / 共 5 页
字号:
</code></pre><p>The function <code>who</code> returns <i>"who contains that"</i>, i.e. a listof symbols that contain a given argument somewhere in their value or propertylist.<p><pre><code>: (who 'print)-> ((print> . +Relation) query show select pretty "edit" msg rules pp more (print> . +Date))</code></pre><p>A dotted pair indicates either a method definition or a property entry. So<code>(print> . +Relation)</code> denotes the <code>print&gt;</code> method ofthe <code>+Relation</code> class.<p><code>who</code> can be conveniently combined with <code>more</code> and<code>pp</code>:<p><pre><code>: (more (who 'print) pp)(dm (print> . +Relation) (Val)   # Pretty-print these functions one by one   (print Val) )(de query ("Q" "Dbg")   ...</code></pre><p>The argument to <code>who</code> may also be a pattern list (see <code><ahref="refM.html#match">match</a></code>):<p><pre><code>: (who '(print @ (val @)))-> (show): (more (who '(% @ 7)) pp)(de day (Dat Lst)   (get      (or Lst *DayFmt)      (inc (% (inc Dat) 7)) ) )(de _week (Dat)   (/ (- Dat (% (inc Dat) 7)) 7) )</code></pre><p>The function <code>can</code> returns a list which indicates which classes<i>can</i> accept a given message. Again, this list is suitable for iterationwith <code>pp</code>:<p><pre><code>: (can 'del>)                                   # Which classes accept 'del>' ?-> ((del> . +Relation) (del> . +Entity) (del> . +List)): (more (can 'del>) pp)                         # Inspect the methods with 'pp'(dm (del> . +Relation) (Obj Old Val)   (and (&lt;> Old Val) Val) )(dm (del> . +Entity) (Var Val)   (when      (and         Val         (has> (meta This Var) Val (get This Var)) )      (let Old (get This Var)         (rel>            (meta This Var)            This            Old            (put This Var (del> (meta This Var) This Old @)) )         (upd> This Var Old) ) ) )(dm (del> . +List) (Obj Old Val)   (and (&lt;> Old Val) (delete Val Old)) )</code></pre><p><code>dep</code> shows the dependencies in a class hierarchy. That is, for agiven class it displays the tree of its (super)class(es) above it, and the treeof its subclasses below it.<p>To view the complete hierarchy of input fields, we start with the root class<code>+Relation</code>:<p><pre><code>: (dep '+Relation)+Relation   +Number      +Time      +Date   +Symbol      +String   +Blob   +Link      +Joint   +Bool   +Any   +Bag-> +Relation</code></pre><p>If we are interested in <code>+Link</code>:<p><pre><code>: (dep '+Link)   +Relation+Link   +Joint-> +Link</code></pre><p>This says that <code>+Link</code> is a subclass of <code>+Relation</code>,and has a single subclass (<code>+Joint</code>).<p><hr><h2><a name="fun">Defining Functions</a></h2><p>Most of the time during programming is spent defining functions (or methods).In the following we will concentrate on functions, but most will be true formethods as well except for using <code>dm</code> instead of <code>de</code>.<p>The notorious "Hello world" function must be defined:<p><pre><code>: (de hello ()   (prinl "Hello world") )-> hello</code></pre><p>The <code>()</code> in the first line indicates a function without arguments.The body of the function is in the second line, consisting of a singlestatement. The last line is the return value of <code>de</code>. From now on wewill omit the return values of examples when they are unimportant.<p>You'll know that you can call this function as<p><pre><code>: (hello)Hello world</code></pre><p>A function with an argument might look this way:<p><pre><code>: (de hello (X)   (prinl "Hello " X) )hello redefined</code></pre><p>Pico Lisp informs you that you have just redefined the function. This mightbe a useful warning in case you forgot that a bound symbol with that namealready existed.<p><pre><code>: (hello "world")Hello world</code></pre><p><pre><code>: (hello "Alex")Hello Alex</code></pre><p>Normally, Pico Lisp evaluates the arguments before it passes them to afunction:<p><pre><code>: (hello (+ 1 2 3))Hello 6</code></pre><p><pre><code>: (setq A 1  B 2)       # Set 'A' to 1 and 'B' to 2-> 2: (de foo (X Y)         # 'foo' returns the list of its arguments   (list X Y) )-> foo: (foo A B)             # Now call 'foo' with 'A' and 'B'-> (1 2)                # -> We get a list of 1 and 2, the values of 'A' and 'B'</code></pre><p>In some cases you don't want that. For some functions (<code><ahref="refS.html#setq">setq</a></code> for example) it is better if the functiongets all arguments unevaluated, and can decide for itself what to do with them.<p>For such cases you do not define the function with a <i>list</i> ofparameters, but give it a <i>single atomic</i> parameter instead. Pico Lisp willthen bind all (unevaluated) arguments to that list.<p><pre><code>: (de foo X   (list (car X) (cadr X)) )        # 'foo' lists the first two arguments: (foo A B)                         # Now call it again-> (A B)                            # -> We don't get '(1 2)', but '(A B)': (de foo X   (list (car X) (eval (cadr X))) ) # Now evaluate only the second argument: (foo A B)-> (A 2)                            # -> We get '(A 2)'</code></pre><p>As a logical consequence, you can combine these principles. To define afunction with 2 evaluated and an arbitrary number of unevaluated arguments:<p><pre><code>: (de foo (X Y . Z)     # Evaluate only the first two args   (list X Y Z) ): (foo A B C D E)-> (1 2 (C D E))        # -> Get the value of 'A' and 'B' and the remaining list</code></pre><p>More common, in fact, is the case where you want to pass an arbitrary numberof <i>evaluated</i> arguments to a function. For that, Pico Lisp recognizes thesymbol <code>@</code> as a single atomic parameter and remembers all evaluatedarguments in an internal frame. This frame can then be accessed sequentiallywith the <code><a href="refA.html#args">args</a></code>, <code><ahref="refN.html#next">next</a></code>, <code><ahref="refA.html#arg">arg</a></code> and <code><ahref="refR.html#rest">rest</a></code> functions.<p><pre><code>: (de foo @   (list (next) (next)) )     # Get the first two arguments: (foo A B)-> (1 2)</code></pre><p>Again, this can be combined:<p><pre><code>: (de foo (X Y . @)   (list X Y (next) (next)) ) # 'X' and 'Y' are fixed arguments: (foo A B (+ 3 4) (* 3 4))-> (1 2 7 12)                 # All arguments are evaluated</code></pre><p>These examples are not very useful, because the advantage of a variablenumber of arguments is not used. A function that prints all its evaluatednumeric arguments, each on a line followed by its squared value:<p><pre><code>: (de foo @   (while (args)      (println (next) (* (arg) (arg))) ) ): (foo (+ 2 3) (- 7 1) 1234 (* 9 9))5 256 361234 152275681 6561-> 6561</code></pre><p>Finally, it is possible to pass all these evaluated argument to anotherfunction, using <code><a href="refP.html#pass">pass</a></code>:<p><pre><code>: (de foo @   (pass println 9 8 7)       # First print all arguments preceded by 9, 8, 7   (pass + 9 8 7) )           # Then add all these values: (foo (+ 2 3) (- 7 1) 1234 (* 9 9))9 8 7 5 6 1234 81             # Printing ...-> 1350                       # Return the result</code></pre><p><hr><h2><a name="dbg">Debugging</a></h2><p>There are two major ways to debug functions (and methods) at runtime:<i>Tracing</i> and <i>single-stepping</i>.<p><i>Tracing</i> means letting functions of interest print their name and argumentswhen they are entered, and their name again and the return value when they areexited.<p>For demonstration, let's define the unavoidable factorial function (or just<code><a href="refL.html#load">load</a></code> the file "<code><ahref="fun.l">doc/fun.l</a></code>"):<p><pre><code>(de fact (N)   (if (=0 N)      1      (* N (fact (- N 1))) ) )</code></pre><p>With <code><a href="refT.html#trace">trace</a></code> we can put it in tracemode:<p><pre><code>: (trace 'fact)-> fact</code></pre><p>Calling <code>fact</code> now will display its execution trace.<p><pre><code>: (fact 3) fact : 3  fact : 2   fact : 1    fact : 0    fact = 1   fact = 1  fact = 2 fact = 6-> 6</code></pre><p>As can be seen here, each level of function call will indent by an additionalspace. Upon function entry, the name is separated from the arguments with acolon (<code>:</code>), and upon function exit with an equals sign(<code>=</code>) from the return value.<p>Trace works by modifying the function body, so generally only for functionsdefined as lists (lambda expressions, see <a href="ref.html#ev">Evaluation</a>).Tracing a C-function is possible, however, when it is a function that evaluatesall its arguments.<p>So let's trace the functions <code><a href="ref_.html#=0">=0</a></code> and<code><a href="ref_.html#*">*</a></code>:<p><pre><code>: (trace '=0)-> =0: (trace '*)-> *</code></pre><p>If we call <code>fact</code> again, we see the additional output:<p><pre><code>: (fact 3) fact : 3  =0 : 3  =0 = NIL  fact : 2   =0 : 2   =0 = NIL   fact : 1    =0 : 1    =0 = NIL    fact : 0     =0 : 0     =0 = 0    fact = 1    * : 1 1    * = 1   fact = 1   * : 2 1   * = 2  fact = 2  * : 3 2  * = 6 fact = 6-> 6</code></pre><p>To reset a function to its untraced state, call <code>untrace</code><p><pre><code>: (untrace 'fact)-> fact: (untrace '=0)-> =0: (untrace '*)-> *</code></pre><p>or simply<p><pre><code>: (mapc untrace '(fact =0 *))-> *</code></pre><p><i>Single-stepping</i> means to execute a function step by step, giving theprogrammer an opportunity to look more closely at what is happening. Thefunction <code><a href="refD.html#debug">debug</a></code> inserts a breakpointinto each top-level expression of a function. When the function is called, itstops at each breakpoint, displays the expression it is about to execute next(this expression is also stored into the global variable <code><ahref="ref_.html#^">^</a></code>) and enters a read-eval-loop. The programmer canthen<ul>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -