you get a readme that is a txt.
Code:
GoferLists 1.0 (SysRPL version) for the HP-49G/49G+/50G
========== === ======= ======== === === ===============
Library Id: 1652
Copyright (c) 1994 by Jarno Peschier (http://www.jarno.demon.nl/hp48.htm)
Copyright (c) 2001 by Luis Morales Boisset (http://www.arrakis.es/~lboisset/)
Copyright (c) 2007 by Albert Graef (http://www.musikwissenschaft.uni-mainz.de/~ag/hp49)
GoferLists is a library of useful list processing functions mostly borrowed
from the Haskell programming language. The name comes from the popular Haskell
dialect and interpreter by Mark P. Jones, which was originally called Gofer
and is now known as Hugs ("Haskell User's Gofer System", see
http://www.haskell.org/hugs/).
RPL's built-in list processing facilities such as DOLIST and STREAM are quite
powerful, but can be awkward to work with because they do not treat the corner
cases such as empty input lists in a consistent fashion. GoferLists attempts
to fix that by providing user-friendly frontends to the built-in operations,
in the form of an elaborate collection of generic list processing functions
which are fairly standard in modern functional languages and have proven their
utility in countless applications. GoferLists is implemented in System RPL and
thus the provided operations are fairly efficient as well.
GoferLists was originally written by Jarno Peschier and later ported to SysRPL
for better performance by Luis Morales Boisset. The present version was put
together by Albert Graef who fixed a couple of minor bugs in the SysRPL
version and added a bunch of additional operations (see the revision history
in the following section for details).
See below for installation instructions and an overview of the functions
provided in this version of the library. Also see README.OLD for the original
documentation included with the 0.1b version. Please report bugs in the
present version to Albert Graef at Dr.Graef@t-online.de.
REVISION HISTORY
======== =======
1.0 Jan 24 2007
Bugfixes and new operations by Albert Graef.
- Head, Tail and Init now produce the appropriate dimension errors on an empty
list.
- Copy now works with zero repeat count.
- Concat is now implemented in terms of Foldl.
- Nub was reimplemented in terms of ^AppendList instead of a (non-existing)
lib 776 entry point.
- Foldl, Foldr now take args in reverse order ({} ob prog), to facilitate
"currying", and now work with empty input lists.
- Subs now works with empty input lists.
- New functions: All, Any, Foldl1, Foldr1, Scanl, Scanr, Scanl1, Scanr1,
Zip/Unzip and friends, Seq, ElemIndex, Find, FindIndex, Insert, Delete,
Union/Diff/Intersect, Iterate, While, Until, Chars, Strcat, Sum, Product.
This makes for a total of 56 operations now, hence the library menu was
reordered alphabetically, to make it easier to find a particular function.
0.1b (2001)
Ported to System RPL by Luis Morales Boisset.
0.1 (1994)
Original User RPL version by Jarno Peschier (JPSOFT).
INSTALLATION
============
Transfer glsys49.lib to your calculator and store it in port 0, 1 or 2 (e.g.,
2 STO). Do a quick reboot with On+C, or just 1652 ATTACH, in order to attach
the library. After that the GoferLists function should be available via the
LIB menu or using the command 1652 MENU. For quicker access you might wish to
assign \<< 1652 MENU \>> to a key or include it in your custom menu.
IMPORTANT: GoferLists 1.0 is for the HP-49 series only, for the HP-48 series
calculators you'll have to go with the 0.1 UserRPL version still available at
http://www.hpcalc.org. This is BETA SOFTWARE, so please back up your
calculator before trying it! No warranty etc. etc.
OVERVIEW
========
Here is a brief rundown of the available functions. Most functions are named
after their Haskell counterparts (see, e.g., http://haskell.org/hoogle), but
some may take different arguments or take arguments in a different order, see
the notes below. Some functions don't exist in Haskell, but are provided here
for convenience. Other functions might work a bit different from their Haskell
counterparts, but still serve the same purpose.
Symbol legend: 0/1: truth value, s: string; n: integer (zint or real); x, y,
z: any object (sometimes also an arbitrary real or zint); xs, ys, zs: list;
xss, yss, zss: list of list; f: arbitrary program; p: predicate (program which
returns 0/1 to denote a truth value)
Function Stack Diagram Example
-------------- ---------------------- ------------------------------------
All xs p -> 0/1 { 1 2 3 } \<< 0 > \>> All
-> 1.
Any xs p -> 0/1 { 1 2 3 } \<< 0 < \>> Any
-> 0.
Chars s -> xs "abc" Chars
-> { "a" "b" "c" }
Concat xss -> ys { { 1 } { 2 3 } } Concat
-> { 1 2 3 }
Copy xs n -> ys { 1 2 3 } 3 Copy
-> { 1 2 3 1 2 3 1 2 3 }
Delete xs x -> ys { 1 2 3 } 2 Delete
-> { 1 3 }
Diff xs ys -> zs { 1 2 3 } { 3 4 5 } Diff
-> { 1 2 }
Drop xs n -> ys { 1 2 3 } 2 Drop
-> { 3 }
DropWhile xs p -> ys { 1 2 3 } \<< 2 < \>> DropWhile
-> { 2 3 }
Elem xs x -> 0/1 { 1 2 3 } 2 Elem
-> 1.
ElemIndex xs x -> n { 1 2 3 } 2 ElemIndex
-> 2.
Filter xs p -> ys { 1 2 3 } \<< 1 > \>> Filter
-> { 2 3 }
Find xs p -> x { 1 2 3 } \<< 1 > \>> Find
-> 2
FindIndex xs p -> n { 1 2 3 } \<< 1 > \>> FindIndex
-> 2.
Foldl xs x f -> ys { 1 2 3 } 0 \<< + \>> Foldl
-> 6
Foldl1 xs f -> ys { 1 2 3 } \<< + \>> Foldl1
-> 6
Foldr xs x f -> ys { 1 2 3 } 0 \<< + \>> Foldr
-> 6
Foldr1 xs f -> ys { 1 2 3 } \<< + \>> Foldr1
-> 6
Head xs -> x { 1 2 3 } Head
-> 1
Init xs -> ys { 1 2 3 } Init
-> { 1 2 }
Inits xs -> yss { 1 2 3 } Inits
-> { { } { 1 } { 1 2 } { 1 2 3 } }
Insert xs x -> ys { 1 2 3 } 4 Insert
-> { 1 2 3 4 }
Intersect xs ys -> zs { 1 2 3 } { 3 4 5 } Intersect
-> { 3 }
Iterate x f n -> xs 1 \<< 2 * \>> 10 Iterate
-> { 1 2 4 8 16 32 64 128 256 512 }
Last xs -> x { 1 2 3 } Last
-> 3
Length xs -> n { 1 2 3 } Length
-> 3.
Map xs f -> ys { 1 2 3 } \<< 3 ^ \>> Map
-> { 1 8 27 }
Nub xs -> ys { 1 2 2 3 2 3 3 } Nub
-> { 1 2 3 }
Null xs -> 0/1 { 1 2 3 } Null
-> 0.
Product xs -> x { 1 2 3 } Product
-> 6
Repeat x n -> xs 1 5 Repeat
-> { 1 1 1 1 1 }
Reverse xs -> ys { 1 2 3 } Reverse
-> { 3 2 1 }
Scanl xs x f -> yss { 1 2 3 } 0 \<< + \>> Scanl
-> { 0 1 3 6 }
Scanl1 xs f -> yss { 1 2 3 } \<< + \>> Scanl1
-> { 1 3 6 }
Scanr xs x f -> yss { 1 2 3 } 0 \<< + \>> Scanr
-> { 6 5 3 0 }
Scanr1 xs f -> yss { 1 2 3 } \<< + \>> Scanr1
-> { 6 5 3 }
Segs xs -> yss { 1 2 3 } Segs
-> { { } { 3 } { 2 } { 2 3 } { 1 }
{ 1 2 } { 1 2 3 } }
Seq x y z -> xs 1 10 2 Seq
-> { 1 3 5 7 9 }
Sort xs p -> ys { 1 3 2 } \<< < \>> Sort
-> { 1 2 3 }
Split xs n -> ys zs { 1 2 3 } 2 Split
-> { 1 2 } { 3 }
Strcat xs -> s { "a" "b" "c" } Strcat
-> "abc"
Subs xs -> yss { 1 2 3 } Subs
-> { { 1 2 3 } { 1 2 } { 1 3 } { 1 }
{ 2 3 } { 2 } { 3 } { } }
Sum xs -> x { 1 2 3 } Sum
-> 6
Tail xs -> ys { 1 2 3 } Tail
-> { 2 3 }
Tails xs -> yss { 1 2 3 } Tails
-> { { 1 2 3 } { 2 3 } { 3 } { } }
Take xs n -> ys { 1 2 3 } 2 Take
-> { 1 2 }
TakeWhile xs p -> ys { 1 2 3 } \<< 2 < \>> TakeWhile
-> { 1 }
Union xs ys -> zs { 1 2 3 } { 3 4 5 } Union
-> { 1 2 3 4 5 }
Until x f p -> y 1 \<< 2 * \>> \<< 1000 > \>> Until
-> 1024
Unzip xss -> xs ys { {1 A} {2 B} {3 C} } Unzip
-> { 1 2 3 } { A B C }
Unzip3 xss -> xs ys zs { {1 A x} {2 B y} {3 C z} } Unzip3
-> { 1 2 3 } { A B C } { x y z }
While x f p -> xs 1 \<< 2 * \>> \<< 1000 < \>> While
-> { 1 2 4 8 16 32 64 128 256 512 }
Zip xs ys -> xss { 1 2 3 } { A B C } Zip
-> { { 1 A } { 2 B } { 3 C } }
Zip3 xs ys zs -> xss { 1 2 3 } { A B C } { x y z } Zip3
-> { { 1 A x } { 2 B y } { 3 C z } }
ZipWith xs ys f -> xs' { 1 2 3 } DUP \<< * \>> ZipWith
-> { 1 4 9 }
ZipWith3 xs ys zs f -> xs' { 1 2 3 } DUP DUP \<< * * \>> ZipWith3
-> { 1 8 27 }
Notes:
1. Chars and Strcat are provided to convert between strings and lists of
single character strings. These are not available in Haskell (nor are they
needed, since a string already is a list of characters in Haskell), but
are provided here for your convenience so that you can manipulate strings
using list processing. Note that Strcat can also be used to concatenate an
arbitrary list of strings.
2. Copy and Split should actually be named Cycle and SplitAt, respectively,
but we retained those names for backward compatibility with previous
GoferLists versions. Also note that the Diff function (meaning list
difference) is implemented by an operator (\\) in Haskell.
3. Copy (a.k.a. Haskell's cycle), Iterate and Repeat take an additional
integer argument which specifies the number of repetitions or
iterations. In Haskell these functions return infinite lists instead. This
is possible because of Haskell's lazy evaluation, but of course this
wouldn't work in an eager language like RPL.
4. Foldl/Foldr now take their arguments in reverse order. This breaks
backward compatibility with previous GoferLists versions, but is
consistent with other generic list functions like Filter and Map, and
makes it possible to "curry" these operations just like you would in
Haskell. E.g., concatenating a list of lists can be done using {} << + >>
Foldl, just as you'd define concat = foldl (++) [] in Haskell, where the
"list of lists" parameter is implicit (the {} a.k.a. [] is the initial
empty list from which the accumulation starts). Note that in order to make
this work in RPL, the parameters have to be in reverse order, because of
RPN. Other higher-order list functions like Filter, Find, Iterate, Map,
Scanl/Scanr, Sort etc. work in an analogous fashion.
5. Concat, Product, Sum and Strcat are all just special instances of Foldl.
They could easily be defined in User RPL, but are already included in the
library for your convenience.
6. The Seg and Subs function are not in the Haskell library, but work in the
same fashion as Inits and Tails. Seg returns the list of all consecutive
sublists of a list, while Subs yields the list of *all* (2^N) sublists.
7. The Seq function (which is just a simplified frontend for the builtin SEQ)
provides a quick means to generate an arithmetic sequence, which can be
used as a replacement for Haskell's [x,y..z] construct.
8. The Sort function takes an additional order predicate as parameter, so
that lists can be sorted according to different criteria. E.g., \<< < \>>
Sort and \<< > \>> Sort sorts lists in ascending and descending order,
respectively. (Haskell also provides a sortBy function for this purpose,
but that function takes a special ordering function instead of a binary
predicate as argument.)
9. GoferLists also provides a number of operations which implement the usual
set operations on lists. The Nub function removes duplicates from a list,
so that the resulting list contains each of its members exactly once. The
Elem, Insert/Delete, Union/Diff/Intersect functions provide the common set
operations: membership test, insert/delete a member, set union, difference
and intersection. The Find function works similar to Elem, but looks for
an element satisfying the given predicate and returns that element if
found, NOVAL otherwise. Both functions also have a variation, ElemIndex/
FindIndex, which returns the index of the element in the list (0. if not
found) instead.
10. Two additional functions are provided to iterate a function starting from
an initial value. Until is not actually a list function but is provided
for your convenience anyway. It iterates a function starting from the
given value and returns the first of the computed values which satisfies
the given predicate. E.g., 1 \<< 2 * \>> \<< 1000 > \>> Until returns the
first power of 2 which is greater than 1000, i.e., 1024. The "dual" of the
Until function is While which returns the list of all iterated values up
to the point where the given predicate becomes false. Thus, e.g., 1 \<< 2
* \>> \<< 1000 < \>> While returns the list of all powers of two below
1000, { 1 2 4 8 16 32 64 128 256 512 }. This function is not actually part
of the Haskell library, but is equivalent to a combination of Haskell's
iterate and takeWhile functions.
11. Zip and Zip3 produce a list of lists instead of a list of tuples as in
Haskell. The Unzip and Unzip3 functions return two or three result lists
on the stack, respectively; in Haskell, these functions return a tuple of
lists instead.
EXAMPLE
=======
Here is a quick and dirty implementation of Erathosthenes' sieve in RPL. This
makes use of GoferLists's Filter, Head, Tail and Seq functions. The central
routine here is SIEVE which just takes away the first list element P (which
already is a prime by virtue of the construction) and invokes itself
recursively on the rest of the list after multiples of P have been removed.
SIEVE: \<< IF DUP Null NOT THEN DUP Head \-> P
\<< Tail \<< P MOD 0 \=/ \>> Filter SIEVE P SWAP + \>>
END \>>
PRIMES: \<< 2 SWAP 1 Seq SIEVE \>>
N PRIMES returns the list of prime numbers up to the given number N. For
instance: 50 PRIMES -> { 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 }
Enjoy. :)
Jan 26 2007
Albert Graef <Dr.Graef@t-online.de>