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

📄 tut.html

📁 A very small LISP implementation with several packages and demo programs.
💻 HTML
📖 第 1 页 / 共 5 页
字号:
<li>inspect the current environment by typing variable names or calling functions<li>execute <code>(d)</code> to recursively debug the next expression<li>execute <code>(<a href="refE.html#e">e</a>)</code> to evaluate the nextexpression, to see what will happen without actually advancing on<li>type ENTER (: enter an empty line) to leave the read-eval loop and continuewith the next expression</ul><p>Thus, in the simplest case, single-stepping consists of just hitting ENTERrepeatedly to step through the function.<p>To try it out, let's look at the <code><ahref="refS.html#stamp">stamp</a></code> system function.<p><pre><code>: (pp 'stamp)(de stamp (Dat Tim)   (default  Dat (date)  Tim (time))   (pack (dat$ Dat "-") " " (tim$ Tim T)) )-> stamp</code></pre><p><pre><code>: (debug 'stamp)                       # Debug it-> T: (stamp)                              # Call it again(default Dat (date) Tim (time))        # stopped at first expression!                                      # ENTER(pack (dat$ Dat "-") " " (tim$ ...     # second expression! Tim                                  # inspect 'Tim' variable-> 41908! (time Tim)                           # convert it-> (11 38 28)!                                      # ENTER-> "2004-10-29 11:38:28"               # done, as there are only 2 expressions</code></pre><p>Now we execute it again, but this time we want to look at what's happeninginside the second expression.<p><pre><code>: (stamp)                              # Call it again(default Dat (date) Tim (time))!                                      # ENTER(pack (dat$ Dat "-") " " (tim$ ...     # here we want to look closer! (d)                                  # debug this expression-> T!                                      # ENTER(dat$ Dat "-")                         # stopped at first subexpression! (e)                                  # evaluate it-> "2004-10-29"!                                      # ENTER(tim$ Tim T)                           # stopped at second subexpression! (e)                                  # evaluate it-> "11:40:44"!                                      # ENTER-> "2004-10-29 11:40:44"               # done</code></pre><p>The breakpoints still remain in the function body. We can see them when wepretty-print it:<p><pre><code>: (pp 'stamp)(de stamp (Dat Tim)   (! default Dat (date) Tim (time))   (! pack      (! dat$ Dat "-")      " "      (! tim$ Tim T) ) )-> stamp</code></pre><p>To reset the function to its normal state, call<p><pre><code>: (unbug 'stamp)</code></pre><p>Often, you will not want to single-step a whole function. Just use<code>edit</code> (see above) to insert a single breakpoint (the exclamationmark followed by a space) as CAR of an expression, and run your program.Execution will then stop there as described above; you can inspect theenvironment and continue execution with ENTER when you are done.<p><hr><h2><a name="funio">Functional I/O</a></h2><p>Input and output in Pico Lisp is functional, in the sense that there are notvariables assigned to file descriptors, which need then to be passed to I/Ofunctions for reading, writing and closing. Instead, these functions operate onimplicit input and output channels, which are created and maintained as dynamicenvironments.<p>Standard input and standard output are the default channels. Try reading asingle expression:<p><pre><code>: (read)(a b c)        # Console input-> (a b c)</code></pre><p>To read from a file, we redirect the input with <code><ahref="refI.html#in">in</a></code>. Note that comments and white space areautomatically skipped by <code>read</code>:<p><pre><code>: (in "doc/fun.l" (read))-> (de fact (N) (if (=0 N) 1 (* N (fact (- N 1)))))</code></pre><p>The <code><a href="refS.html#skip">skip</a></code> function can also be useddirectly. To get the first non-white character in the file with <code><ahref="refC.html#char">char</a></code>:<p><pre><code>: (in "doc/fun.l" (skip "#") (char))-> "("</code></pre><p><code><a href="refF.html#from">from</a></code> searches through the inputstream for given patterns. Typically, this is not done with Lisp source files(there are better ways), but for a simple example let's extract all itemsimmediately following <code>fact</code> in the file,<p><pre><code>: (in "doc/fun.l" (make (while (from "fact ") (link (read)))))-> ((N) (- N 1))</code></pre><p>or the word following "(de " with <code><ahref="refT.html#till">till</a></code>:<p><pre><code>: (in "doc/fun.l" (from "(de ") (till " " T)))-> "fact"</code></pre><p>With <code><a href="refL.html#line">line</a></code>, a line of characters isread, either into a single transient symbol,<p><pre><code>: (in "doc/tut.html" (line T))-> "&lt;!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\" ..."</code></pre><p>or into a list of characters:<p><pre><code>: (in "doc/tut.html" (line))-> ("&lt;" "!" "D" "O" "C" "T" "Y" "P" "E" " " "H" "T" "M" "L" ...</code></pre><p><code>line</code> is typically used to read tabular data from a file.Additional arguments can split the line into fixed-width fields, as described inthe <code><a href="refL.html#line">reference manual</a></code>. If, however, thedata are of variable width, delimited by some special character, the <code><ahref="refS.html#split">split</a></code> function can be used to extract thefields. A typical way to import the contents of such a file is:<p><pre><code>(load "lib/import.l")(in '("bin/utf2" "importFile.txt")              # Pipe: Convert to UTF-8   (until (eof)                                 # Process whole file      (let L (split (line) "^I")                # TAB-delimited data         ... use 'getStr', 'getNum' etc ...     # process them</code></pre><p>Some more examples:<p><pre><code>(in "a"                                         # Copy the first 40 Bytes   (out "b"                                     # from file "a" to file "b"      (echo 40) ) )(in "doc/tut.html"                              # Show the HTTP-header   (line)   (echo "&lt;body>") )(out "file.mac"                                 # Convert to Macintosh   (in "file.txt"                               # from Unix or DOS format:      (while (char)         (prin            (case @               ("^M" NIL)                       # ignore CR               ("^J" "^M")                      # convert CR to LF               (T @) ) ) ) ) )                  # otherwise no change(out "c"                                        # Merge the contents of "a"   (in "b"                                      # and "b" into "c"      (in "a"         (while (read)                          # Read an item from "a",            (println @ (in -1 (read))) ) ) ) )  # print it with an item from "b"</code></pre><p><hr><h2><a name="script">Scripting</a></h2><p>There are two possibilities to get the Pico Lisp interpreter into doinguseful work: Via command line arguments, or as a stand-alone script.<p>The command line can specify either files for execution, or arbitrary Lispexpressions for direct evaluation (see <code><ahref="ref.html#invoc">Invocation</a></code>): If an argument starts with ahyphen, it is evaluated, otherwise <code><ahref="refL.html#load">load</a></code>ed as a file. A typical invocation mightlook like:<p><pre><code>$ ./p dbg.l app/file1.l -main app/file2.l</code></pre><p>It loads the debugging environment, an application source file, calls themain function, and then loads another application source. In a typicaldevelopment and debugging session, this line is often modified using the shell'shistory mechanisms, e.g. by inserting debugging statements:<p><pre><code>$ ./p dbg.l app/file1.l -"trace 'foo" -main -"debug 'bar" app/file2.l</code></pre><p>Another convenience during debugging and testing is to put things into thecommand line (shell history) which would otherwise have to be done each time inthe application's user interface:<p><pre><code>$ ./p dbg.l app/file1.l -main app/file2.l -go -'login "name" "password"'</code></pre><p>The final production release of an application usually includes a shellscript, which initializes the environment, does some bookkeeping and cleanup,and calls the application with a proper command line. It is no problem if thecommand line is long and complicated.<p>For small utility programs, however, this is overkill. It is better to writea single executable file using the mechanisms of "interpreter files": If thefirst two characters in an executable file are "<code>#!</code>", the operatingsystem kernel will pass this file to an interpreter program whose pathname isgiven in the first line (optionally followed by a single argument). This is fastand efficient, because the overhead of a subshell is avoided.<p>Let's assume you installed Pico Lisp in the directory "/home/foo/picolisp/",and put links to the executable and the installation directory as:<p><pre><code>$ ln -s /home/foo/picolisp /usr/lib/picolisp$ ln -s /usr/lib/picolisp/bin/picolisp /usr/bin/picolisp</code></pre>Then a simple hello-world script might look like:<p><pre><code>#!/usr/bin/picolisp /usr/lib/picolisp/lib.l(prinl "Hello world!")(bye)</code></pre><p>If you write this into a text file, and use <code>chmod</code> to set it to"executable", it can be executed like any other command. Note that - because<code>#</code> is the comment character in Pico Lisp - the first line will notbe interpreted, and you can still use that file as a normal command lineargument to Pico Lisp (useful during debugging).<p>The fact that a hyphen causes evaluation of command line arguments can beused to simulate something like command line options. The following scriptdefines two functions <code>a</code> and <code>f</code>, and then calls<code>(<a href="refL.html#load">load</a> T)</code> to process the rest of thecommand line (which otherwise would be ignored because of the <code>(<ahref="refB.html#bye">bye</a>)</code> statement):<p><pre><code>#!/usr/bin/picolisp /usr/lib/picolisp/lib.l(de a ()   (println '-a '-> (opt)) )(de f ()   (println '-f '-> (opt)) )(load T)(bye)</code></pre>(<code><a href="refO.html#opt">opt</a></code> retrieves the next command lineoption)<p>Calling this script (let's say we named it "testOpts") gives:<p><pre><code>$ ./testOpts -f abc-f -> "abc"$ ./testOpts -a xxx  -f yyy-a -> "xxx"-f -> "yyy"</code></pre><p>We have to be aware of the fact, however, that the aggregation of argumentslike<p><pre><code>$ ./testOpts -axxx  -fyyy</code></pre><p>or<p><pre><code>$ ./testOpts -af yyy</code></pre><p>cannot be achieved with this simple and general mechanism of command lineprocessing.<p>Utilities are typically used outside the context of the Pico Lispenvironment. All examples above assumed that the current working directory isthe Pico Lisp installation directory, which is usually all right forapplications developed in that environment. Command line file arguments like"dbg.l" or "app/file1.l" will be properly found.<p>To allow utilities to run in arbitrary places on the host file system, theconcept of <i>home directory substitution</i> was introduced. The interpreterremembers internally at start-up the pathname of its first argument (usually"lib.l"), and substitutes any leading "<code>@</code>" character in subsequentfile names with that pathname. Thus, to run the above example in some otherplace, simply write:<p><pre><code>$ /home/foo/picolisp/p @dbg.l @app/file1.l -main @app/file2.l</code></pre><p>that is, supply a full path name to the initial command (here 'p'), or put itinto your <code>PATH</code> variable, and prefix each file which has to beloaded from the Pico Lisp home directory with a <code>@</code> character."Normal" files (not prefixed by <code>@</code>) will be opened or createdrelative to the current working directory as usual.<p>Stand-alone scripts will often want to load additional modules from the PicoLisp environment, beyond the "lib.l" we provided in the first line of thehello-world script. Typically, at least a call to<p><pre><code>(load "@lib/misc.l")</code></pre><p>(note the home directory substitution) will be included near the beginning ofthe script.<p>As a more complete example, here is a script which extracts the date, nameand size of the latest official Pico Lisp release version from the download website, and prints it to standard output:<p><pre><code>#!/usr/bin/picolisp /usr/lib/picolisp/lib.l(load "@lib/misc.l" "@lib/http.l")(use (@Date @Name @Size)   (when      (match         '(@Date " " "-" " " @Name " " "(" @Size ")")         (client "software-lab.de" 80 "down.html"            (from "Archive")            (from ".tgz\">")            (till "<") ) )      (prinl @Name)      (prinl @Date " -- " @Size) ) )(bye)</code></pre><p><hr><h2><a name="oop">Objects and Classes</a></h2><p>The Pico Lisp object model is very simple, yet flexible and powerful. Objectsas well as classes are both implemented as symbols. In fact, there is no formaldifference between objects and classes; classes are more a conceptual designconsideration in the head of the programmer than a physical reality.<p>Having said this, we declare that normally:

⌨️ 快捷键说明

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