📄 tut.html
字号:
</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></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 (<> 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 (<> 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 + -