All procedures listed in the Catalog under Category Library procedure are defined in this memo. You should have this memo loaded most of the time, unless you're running into memory troubles.
Some useful (non-standard) functions
Defines some procedures to modify the graphics state variables and some other useful procedures and variables.
Defines hb-getrecord which reads an entire record from a HanDBase database and converts all fields from HanDBase's internal string representation to a more appropriate one depending on the fields internal type. A record is represented as a list.
Additionally, all linked records are read recursively and embedded as a list of records in the owner record.
Note that the date and time parsing functions use the German format (dd.mm.yy and hh:mm)
The function hb-getrecord is curried, so that repeated calls to the same DB can avoid re-reading the catalog (field descriptions). Use it like this:
(let ((reader (hb-getrecord "MyDB"))) (do looping conditions ... (reader recnum) ... ))
The classic non-primitive recursive Ackermann function. Don't try to evaluate (a 4 4) before buying an universe full of AAA cells!
Another classic: List the moves necessary to move n disks from peg a to peg b using the auxiliary peg c in the game Towers of Hanoi.
(hanoi 3 'from 'to 'aux)
((from . to) (from . aux) (to . aux) (from . to) (aux . from) (aux . to) (from . to))
A stupid way to implement those, sure, but it demonstrates 3 things:
This memo was used in the following performance test. The call (cc 100 coins) (How many ways are there to change 100$ into 1, 2, 5, 10, 20, 50 dollar bills) was run on a variety of Scheme implementations:
LispMe was originally developed with Visual Age C++ by IBM on a Pentium 133 with 64 MB running OS/2 Warp. Recently I discovered that MIT Scheme 7.4 is available for OS/2 and was compiled with the same compiler, so I ran a simple performance test.
|Machine||OS version||Language||operation mode||runtime|
|Pentium 133||OS/2 Warp||MIT Scheme 7.4||interpreted||7.00 s|
|Pentium 133||OS/2 Warp||MIT Scheme 7.4||compiled to native 386 code||0.96 s|
|Pentium 133||OS/2 Warp||LispMe 1.2||compiled SECD code||4.59 s|
|Pilot 1000||PalmOS 1.06||LispMe 1.2||compiled SECD code||747.13 s|
|Pilot 1000||PalmOS 2.02||LispMe 1.4||compiled SECD code||626.87 s|
|Pilot 1000||PalmOS 2.02||LispMe 1.6||compiled SECD code||657.35 s|
|Pilot 1000||PalmOS 2.02||LispMe 1.7||compiled SECD code||666.31 s|
|Pilot 1000||PalmOS 2.02||LispMe 2.0||compiled SECD code||697.45 s|
|Palm III||PalmOS 3.0||LispMe 2.3||compiled SECD code||662.45 s|
|Palm III||PalmOS 3.0||LispMe 2.7||compiled SECD code||688.22 s|
|Palm IIIc||PalmOS 3.5||LispMe 2.7||compiled SECD code||454.28 s|
|Palm III||PalmOS 3.3||LispMe 2.8||compiled SECD code||583.93 s|
|Palm IIIc||PalmOS 3.5||LispMe 2.8||compiled SECD code||384.27 s|
|Palm IIIc||PalmOS 3.5||LispMe 3.0||compiled SECD code||417.13 s|
|Palm IIIc||PalmOS 3.5||LispMe 3.2||compiled SECD code||403.23 s|
|Palm Tungsten T3||PalmOS 5.2||LispMe 3.2||compiled SECD code||82.31 s|
|Pilot 1000||PalmOS 2.02||PocketC 0.98a||unknown||1927.85 s|
Considering the immense effort that went into MIT Scheme and the difference between a Pentium and a Dragonball, this result is not too bad, I think! Notice the performance increase in V1.4 (The decrease in later versions is due to run-time type checking the additional data types)
Note that some hacks which patch the system event handler may cause a significant slowdown!
This benchmark has been adapted for PocketC (Source code) to allow a comparison.
Load ; Graphic utilities and just evaluate (demo). Compare the source with the output and note how to draw circles. See also how to access resources and draw bitmaps. In this case, resource 11000 of type Tbmp (=bitmap) is loaded and drawn. This bitmap (residing in a system resource) is the taxi image of a well-known Pilot easter egg!
Please note that both images were created by the same code proving the backward compatibility of the graphic system.
These definitions illustrate how to used delay to build infinite streams, try these expressions:
This sample is from chapter 19 of The Seasoned Schemer, pages 165-175. It demonstrates, how continuations can be used to model coroutines. In this case, the function waddle traverses a tree, yielding control whenever it finds a leaf. The functions get-first and get-next provide a functional interface for waddle, which is used by two-in-a-row*?
The helper functions haven't been localized into the main function (like on page 176) to be able to play around with them.
Load ; Graphic utilities before. To plot a function, evaluate (plot function x-min x-may y-min ymax).
As the Pilot ROM routines have some glitches with clipping, you may notice spurious lines when the functions leaves the range [y-min..y-max]. Try to avoid this.
Feel free to enhance this plotter (it's only a demo!) and please send me a copy of your code in this case.
Evaluate (cube 80 30 30 12 35). OK, it's not Quake, but the animation runs at about 12 FPS. The short pauses indicate garbage collections. The parameters are
The function diff computes the symbolic derivation of a function entered in LispMe syntax. The result is somewhat simplified (e.g. (* (+ a 5) 1) => (+ a 5))
Try these steps:
(diff '(* (* x x) (* y x))) evaluates to (+ (* (* x x) y) (* (+ x x) (* y x)))
Now (diff it) evaluates to (+ (* (+ x x) y) (+ (* (+ x x) y) (* 2 (* y x))))
And again, (diff it) evaluates to (+ (* 2 y) (+ (* 2 y) (* 2 y)))
Finally, (diff it) evaluates to 0
Note: This sample has been changed in version 2.2 to show local defines, case and quasiquote.
You must load ; Standard library, ; Utility library, and ; Graphic utilities before. To play a game of Tic Tac Toe, just evaluate (ttt who algo).
who can be #t, meaning you have the first move, or #f to let Pilot begin the game.
algo selects the algorithm by which the Pilot selects its move:
do-move returns the modified position when executing a move. find finds the best element of a list according to a predicate (which is assumed to be transitive)
So, static uses find to extract the best (lowest static value according to eval) triple from the list returned by extend and returns its move component.
smart filters the list before for positions, which are an immediate loss for Pilot. These positions are identified by not-loose, which uses extend in turn, this time with the player's moves.
human just waits for the player to tap a square and returns the new position, while pilot executes the move determined by its algo parameter for the Pilot. Finally, ttt is the game driver, calling human and pilot alternatingly, after setting up the result continuation which is called to end a game.
You way want to improve the Pilot's move algorithms (smart is quite slow, it always builds a search tree two levels deep) or implement real alpha-beta search. If you reach the MemoPad limit of 4k for the source, just split it into two memos and load both of them.
Source code (theory)
This is a sample program sent by Winton Davies. He wrote:
OK, so here's a small LispMe Theorem Prover for the Palm Pilot OS2.0 . I ported it from a Lisp version that comes with Mac Common Lisp 4.1 ("mcl:user contributed code:AI/Expert Systems:AI:"(prove-all.lisp and unify.lisp). Feel free to correct any bits of scheme I didn't do correctly.Load the ; Standard library before and evaluate (test) to see, who'll be eaten :-)
I believe the originating author is Mike Pazzani, from an Introductory AI course taught at UCI. However, it could also have been Rich and Knight or Touretsky (both books being referred to in the lecture notes). Perhaps Mike might fill us in?
It's probably a sub optimal port :) But it works on the test case. But I also have doubts as to its completeness. I'm not even sure how best to characterize it. The unify component works -- but doesn't do skolemization on functions it appears. The input has to be horn clause. The search method I haven't analysed... and applying the substitutions appears order dependent. Still, as I said -- it fits in 4K limit of memo-pad, and does work on the test case :-).
I don't know how you want to deliver them, but assuming Mike has no problems with them being public, then I have no problems either. The first file is called unify.lisp (contains unify and prove-all), the second is the dinky example...
This memo provides a tracing facility for arbitrary LispMe procedures. To start tracing of any (top-level) procedure, invoke (trace procname) and to stop tracing invoke (untrace procname). These macros install and remove a tracing prologue/epilogue for the procedures which prints its parameters and return value together with the call nesting depth to a memo Trace in the Unfiled category.
The currently traced procedures are stored in the global list *tracing* as pairs consisting of the name and the original closure. Note the use of old-depth to store the nesting depth in the dynamic context before calling the traced procedure, so that multiple returns via continuations use the correct value. Just incrementing depth before the call and decrementing it afterwards wouldn't work in this case!
This memo provides two example functions to retrieve data from the Internet. The first (atomic-time) retrieves the current time and date from the atomic clock in Braunschweig, Germany.
The second example rate uses the FXP protocol for retrieving currency exchange rates. The page describing the protocol seems to have vanished, but this page shows some scripts using it.
Use international currency codes to request current exchange rates:
(rate 'eur 'usd) => 0.8779as of 24. Nov 2001.
PilRC source code
Totally useless, but shows almost all UI elements supported. Have a look at the event handling in the subdialog invoked by pressing the Scroll button. There is a generic event handler synchronizing an entry field and its scrollbar. The higher-order function scroll-handler creates an event handler from the field and the scrollbar id.
Another higher-order function chain executes an arbitrary number of event handlers until the first returns #t (which indicates that the event has been completely handled).
The continuous display of the current ticks value is done by specifying a timeout in the event loop and redrawing it on each timeout event.
PilRC source code
Shows navigation between forms using frm-goto, frm-popup and frm-return.
PilRC source code
The most basic drawing program in 10 lines of code.
PilRC source code
Simple 4 function calculator.
PilRC source code
This sample shows connecting two Palms via infrared. Both Palms must have LispMe and this memo installed. Start the demo on both Palms and press the Connect buttons on each. Now you can send and receive text messages.
This demo uses the Palm's virtual serial IRComm port which can be accessed as a standard serial device. Sending data is simply done with write. To receive data, timeout events are enabled (one per second) and the serial port is polled using a read timeout of 0, so that the read attempt returns immediately when no data has arrived yet.