Thread: [pure-lang-svn] SF.net SVN: pure-lang:[634] pure/trunk/pure.1.in (Page 2)
Status: Beta
Brought to you by:
agraef
|
From: <ag...@us...> - 2008-08-27 18:26:57
|
Revision: 634
http://pure-lang.svn.sourceforge.net/pure-lang/?rev=634&view=rev
Author: agraef
Date: 2008-08-27 18:27:08 +0000 (Wed, 27 Aug 2008)
Log Message:
-----------
Update documentation.
Modified Paths:
--------------
pure/trunk/pure.1.in
Modified: pure/trunk/pure.1.in
===================================================================
--- pure/trunk/pure.1.in 2008-08-27 10:38:09 UTC (rev 633)
+++ pure/trunk/pure.1.in 2008-08-27 18:27:08 UTC (rev 634)
@@ -957,11 +957,13 @@
.fi
.PP
The `timex' macro also provides a useful example of how you can use macros to
-define your own special forms, since the (expanded) macro arguments are
-effectively called by name at runtime. (Note that the above definition of
-`timex' wouldn't work as an ordinary function definition, since the x
-parameter would have been evaluated already before it is passed to `timex',
-making `timex' always return a zero time value. Try it.)
+define your own special forms, since the macro arguments will only be
+evaluated at runtime and can thus be passed to built-in special forms and
+other constructs which defer their evaluation. (Note that the above definition
+of `timex' wouldn't work as an ordinary function definition, since by virtue
+of Pure's basic eager evaluation strategy the x parameter would have been
+evaluated already before it is passed to `timex', making `timex' always return
+a zero time value. Try it.)
.PP
Finally, note that Pure macros are lexically scoped, i.e., symbols on the
right-hand-side of a macro definition can never refer to anything outside the
@@ -984,20 +986,47 @@
macros are a good way to shoot yourself in the foot. So use them thoughtfully
and with care.
.SH DECLARATIONS
-You probably noticed by now that Pure is a very terse language. That's
-because, in contrast to hopelessly verbose languages like Java, you don't
-declare much stuff in Pure, you just define it and be done with it. Usually,
-all necessary information about the defined symbols is inferred
-automatically. However, there are a few toplevel constructs which let you
-declare special symbol attributes and manage programs consisting of several
-source modules. These are: operator and constant symbol declarations,
+Pure is a very terse language by design; you don't declare much stuff, you
+just define it and be done with it. Usually, all necessary information about
+the defined symbols is inferred automatically. However, there are a few
+toplevel constructs which let you declare special symbol attributes and manage
+programs consisting of several source modules. These are:
+.BR private ,
+fixity (operator) and
+.B nullary
+(constant symbol) declarations,
.B extern
declarations for external C functions (described in the C INTERFACE section),
and
.B using
-clauses which provide a simple include file mechanism.
+clauses which let you include other scripts in a Pure script.
.TP
-.B Operator and constant declarations: infix \fIlevel\fP \fIop\fP\fR ...;\fP nullary \fIsymbol\fP\fR ...;\fP
+.B Private symbol declarations: private \fIsymbol\fP\fR ...;\fP
+Declares the listed symbols as
+.IR private .
+Pure programs usually consist of several source scripts (see the description
+of the
+.B using
+clauses below). By default, all global symbols are
+.I public
+symbols which are visible throughout the entire Pure program. Symbols
+explicitly declared as private are only visible in the script which declares
+them. This must be done before using these symbols. Example:
+.sp
+.nf
+\fBprivate\fP foo bar;
+foo (bar x) = x+1; // foo and bar symbols are private here
+.fi
+.sp
+Note that to declare multiple symbols in a single declaration, you just list
+them all with whitespace in between. The same applies to the other types of
+symbol declarations discussed below.
+.TP
+.B Operator declarations: infix \fIlevel\fP \fIop\fP\fR ...;\fP
+These may also be prefixed with the keyword
+.B private
+to indicate a private operator symbol (see above).
+.sp
Ten different precedence levels are available for user-defined operators,
numbered 0 (lowest) thru 9 (highest). On each precedence level, you can
declare (in order of increasing precedence)
@@ -1013,34 +1042,92 @@
\fBinfixl\fP 7 * / div mod ;
.fi
.sp
-Note that to declare multiple symbols in a single declaration, you just list
-them all with whitespace in between.
-.sp
-Similarly, constant symbols are introduced using a
+One thing worth noting here is that unary minus plays a special role in the
+syntax. Like in Haskell, unary minus is the only prefix operator symbol which
+is also used as an infix operator, and it always has the same precedence as
+binary minus (whose precedence may be chosen freely in the prelude). Thus,
+with the standard prelude, -x+y will be parsed as (-x)+y, whereas -x*y is the
+same as -(x*y). Also note that the notation `(-)' always denotes the binary
+minus operator; the unary minus operation can be denoted using the built-in
+`neg' function.
+.TP
+.B Constant symbol declarations: nullary \fIsymbol\fP\fR ...;\fP
+Constant symbols are introduced using a
.B nullary
-declaration, e.g.:
+declaration (again, a
+.B private
+prefix may be used to denote private constant symbols), e.g.:
.sp
.nf
-\fBnullary\fP [] () nil;
+\fBnullary\fP [] ();
+\fBprivate\fP \fBnullary\fP nil;
.fi
.sp
-Examples for all of these can be found in the prelude which declares a bunch
-of standard (arithmetic, relational, logical) operator symbols as well as the
-list and pair constructors `:' and `,' and the constant symbols `[]' and `()'
-denoting the empty list and tuple, respectively.
+As explained in the PURE OVERVIEW section,
+.B nullary
+symbols are like ordinary identifiers, but are treated as constants rather
+than variables when they occur on the left-hand side of an equation.
+.sp
+Examples for all types of symbol declarations can be found in the prelude
+which declares a bunch of standard (arithmetic, relational, logical) operator
+symbols as well as the list and pair constructors `:' and `,' and the empty
+list and tuple constants `[]' and `()'.
.TP
.B Using clause: using \fIname\fR, ...;
-Causes each given script to be included, at the position of the
+Causes each given script to be included in the Pure program. Each included
+script is loaded only
+.IR once ,
+when the first
.B using
-clause, but only if the script was not included already. Note that the
-constants, variables, functions and macros defined by the included script are
-then available anywhere in the program, not just the module that contains the
+clause for the script is encountered. This kind of clause is discussed in
+further detail below.
+.sp
+Note that the
.B using
-clause.
+clause also has an alternative form which allows dynamic libraries to be
+loaded, this will be discussed in the C INTERFACE section.
+.PP
+The
+.B using
+declaration provides a simple but effective way to assemble a Pure program
+from several source modules. The Pure program is just the concatenation of all
+the source modules listed as command line arguments and included through
+.B using
+clauses. Public constants, variables, functions and macros defined anywhere in
+the program share one big happy namespace and are available throughout the
+entire program (not just the module that contains a
+.B using
+clause for the script containing a given symbol). This approach has its
+drawbacks, but it makes it easy to define polymorphic functions and macros
+across separate modules.
+.PP
+To facilitate modular development, each script also has a separate namespace
+for private symbols which are only visible in the script which declares them
+(see the explanation of the
+.B private
+declaration above). This makes it possible to hide away internal operations,
+prevent name clashes between symbols of different modules, and keep the public
+namespace tidy and clean. A
+.B private
+declaration shadows a public symbol with the same print name, but this takes
+effect only
+.I after
+the
+.B private
+declaration of the symbol, so you can easily define yourself an alias for the
+public symbol before that, e.g.:
.sp
-The script name can be specified either as a string denoting the proper
-filename (possibly including path and/or filename extension), or as an
-identifier. In the latter case, the
+.nf
+public_foo = foo;
+\fBprivate\fP foo;
+foo x = public_foo (bar x);
+.fi
+.PP
+The script name in a
+.B using
+clause can be specified either as a string denoting the proper filename
+(possibly including path and/or filename extension), or as an identifier. In
+the latter case, the
.B .pure
filename extension is added automatically. In both cases, the interpreter
performs a search to locate the script, unless an absolute pathname was
@@ -1064,9 +1151,9 @@
to the command line, or by including `.' in the
.B PURE_INCLUDE
variable.
-.sp
-For the purpose of comparing and loading scripts, the interpreter always uses
-the canonicalized full pathname of the script, following symbolic links to the
+.PP
+For the purpose of comparing script names, the interpreter always uses the
+canonicalized full pathname of the script, following symbolic links to the
destination file (albeit only one level). Thus different scripts with the same
basename, such as
.B foo/utils.pure
@@ -1083,11 +1170,6 @@
be located in the script directory. This is the recommended practice for
installing standalone Pure applications in source form which are to be run
directly from the shell.
-.PP
-Note that the
-.B using
-clause also has an alternative form which allows dynamic libraries to be
-loaded, this will be discussed in the C INTERFACE section below.
.SH EXCEPTION HANDLING
Pure also offers a useful exception handling facility. To raise an exception,
you just invoke the built-in function
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ag...@us...> - 2008-08-27 19:31:10
|
Revision: 637
http://pure-lang.svn.sourceforge.net/pure-lang/?rev=637&view=rev
Author: agraef
Date: 2008-08-27 19:31:19 +0000 (Wed, 27 Aug 2008)
Log Message:
-----------
Update documentation.
Modified Paths:
--------------
pure/trunk/pure.1.in
Modified: pure/trunk/pure.1.in
===================================================================
--- pure/trunk/pure.1.in 2008-08-27 19:02:39 UTC (rev 636)
+++ pure/trunk/pure.1.in 2008-08-27 19:31:19 UTC (rev 637)
@@ -343,22 +343,29 @@
The case of identifiers is significant, but it doesn't carry any meaning
(that's in contrast to languages like Prolog and Q, where variables must be
capitalized). Instead, Pure distinguishes function and variable symbols by
-their position on the left-hand side of an equation, using the ``head =
-function'' rule: Any symbol (except the anonymous variable) which occurs as
-the head symbol of a function application is a function symbol, all other
-symbols are variables (except symbols explicitly declared as ``constant''
-a.k.a.
+their position on the left-hand side of an equation, using the following
+.I head = function
+rule: Any symbol (except the anonymous variable) which occurs as the head
+symbol of a function application is a function symbol, all other symbols are
+variables (except symbols explicitly declared as ``constant'' a.k.a.
.B nullary
symbols, see below).
.TP
.B Operator and constant symbols: \fRx+y, x==y, \fBnot\fP\ x, []
-As indicated, these take the form of an identifier or a sequence of ASCII
-punctuation symbols, as defined in the source using corresponding
-\fBprefix\fP, \fBpostfix\fP, \fBinfix\fP and \fBnullary\fP declarations, which
-are discussed in section DECLARATIONS. Enclosing an operator in parentheses,
-such as (+) or (\fBnot\fP), turns it into an ordinary function symbol. Symbols
-declared as \fBnullary\fP denote special constant symbols which simply stand
-for themselves. Technically, these are just ordinary identifiers; however, the
+As indicated, these take the form of an identifier or a sequence of
+punctuation symbols. As of Pure 0.6, operator and constant symbols may also
+contain arbitrary extended (non-ASCII) Unicode characters, which makes it
+possible, e.g., to use symbols from the math and APL symbol sets offered by
+Unicode.
+.sp
+Operator and constant symbols must always be declared before they can be used,
+using corresponding \fBprefix\fP, \fBpostfix\fP, \fBinfix\fP and \fBnullary\fP
+declarations, which are discussed in section DECLARATIONS.
+.sp
+Note that enclosing an operator in parentheses, such as (+) or (\fBnot\fP),
+turns it into an ordinary function symbol. Symbols declared as \fBnullary\fP
+denote special constant symbols which simply stand for themselves.
+Technically, these are just ordinary identifiers; however, the
.B nullary
attribute tells the compiler that when such an identifier occurs on the
left-hand side of an equation, it is to be interpreted as a constant rather
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ag...@us...> - 2008-08-27 21:31:29
|
Revision: 642
http://pure-lang.svn.sourceforge.net/pure-lang/?rev=642&view=rev
Author: agraef
Date: 2008-08-27 21:31:38 +0000 (Wed, 27 Aug 2008)
Log Message:
-----------
Update documentation.
Modified Paths:
--------------
pure/trunk/pure.1.in
Modified: pure/trunk/pure.1.in
===================================================================
--- pure/trunk/pure.1.in 2008-08-27 21:25:37 UTC (rev 641)
+++ pure/trunk/pure.1.in 2008-08-27 21:31:38 UTC (rev 642)
@@ -1535,8 +1535,9 @@
doesn't check whether the script is being used already and it puts the
definitions on the current temporary level (so that
.B clear
-can be used to remove them again). In particular, this makes it possible to
-quickly reload a script without exiting the interpreter, by issuing the
+can be used to remove them again). This also gives you access to all private
+symbols of the script, and it makes it possible to quickly reload a script
+without exiting the interpreter, by issuing the
.B clear
command followed by
.BR run .
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ag...@us...> - 2008-08-28 00:03:10
|
Revision: 645
http://pure-lang.svn.sourceforge.net/pure-lang/?rev=645&view=rev
Author: agraef
Date: 2008-08-28 00:03:19 +0000 (Thu, 28 Aug 2008)
Log Message:
-----------
Update documentation.
Modified Paths:
--------------
pure/trunk/pure.1.in
Modified: pure/trunk/pure.1.in
===================================================================
--- pure/trunk/pure.1.in 2008-08-27 23:04:26 UTC (rev 644)
+++ pure/trunk/pure.1.in 2008-08-28 00:03:19 UTC (rev 645)
@@ -1465,12 +1465,27 @@
I/O. More stuff will likely be provided in future releases.
.SH INTERACTIVE USAGE
In interactive mode, the interpreter reads definitions and expressions and
-processes them as usual. The input language is just the same as for source
-scripts, and hence individual definitions and expressions \fImust\fP be
-terminated with a semicolon before they are processed. For instance, here is a
-simple interaction which defines the factorial and then uses that definition
-in some evaluations. Input lines begin with ``>'', which is the interpreter's
-default command prompt:
+processes them as usual. If the
+.B -i
+option was used to force interactive mode when invoking the interpreter, the
+last script specified on the command line determines the visible namespace
+(i.e., all public symbols are visible, along with the private symbols of the
+loaded script). Otherwise only the public symbols defined in the prelude are
+available. Additional scripts can be loaded interactively using either a
+.B using
+declaration or the interactive
+.B run
+command (see the description of the
+.B run
+command below for the differences between these). Or you can just start typing
+away, entering your own definitions and expressions to be evaluated.
+.PP
+The input language is just the same as for source scripts, and hence
+individual definitions and expressions \fImust\fP be terminated with a
+semicolon before they are processed. For instance, here is a simple
+interaction which defines the factorial and then uses that definition in some
+evaluations. Input lines begin with ``>'', which is the interpreter's default
+command prompt:
.sp
.nf
> fact 1 = 1;
@@ -1496,8 +1511,9 @@
global variables). If no symbols are given, purge \fIall\fP definitions (after
confirmation) made after the most recent
.B save
-command (or the beginning of the interactive session). See the DEFINITION
-LEVELS AND OVERRIDE MODE section below for details.
+command, or the beginning of the interactive session. (It might be a good
+idea to first check your current definitions with \fBlist -t\fP before you do
+this, though.) See the DEFINITION LEVELS section below for details.
.TP
.B "help \fR[\fIargs\fP]\fP"
Display the
@@ -1516,7 +1532,7 @@
.B override
Enter ``override'' mode. This allows you to add equations ``above'' existing
definitions in the source script, possibly overriding existing equations. See
-the DEFINITION LEVELS AND OVERRIDE MODE section below for details.
+the DEFINITION LEVELS section below for details.
.TP
.B pwd
Print the current working dir (shell \fBpwd\fP(1) command).
@@ -1532,23 +1548,25 @@
the script ``anonymously'', as if the contents of the script had been typed at
the command prompt. That is,
.B run
-doesn't check whether the script is being used already and it puts the
-definitions on the current temporary level (so that
+will just put the definitions into the current namespace, giving you access to
+all private symbols of the script. Also, the definitions are placed at the
+current temporary level, so that
.B clear
-can be used to remove them again). This also gives you access to all private
-symbols of the script, and it makes it possible to quickly reload a script
-without exiting the interpreter, by issuing the
+can be used to remove them again. In particular, this makes it possible to
+quickly reload a script without exiting the interpreter, by issuing the
.B clear
command followed by
.BR run .
+(This works best if you start out from a clean environment, with no scripts
+loaded on the command line.)
.TP
.B save
Begin a new level of temporary definitions. A subsequent
.B clear
command (see above) will purge all definitions made after the most recent
.B save
-(or the beginning of the interactive session). See the DEFINITION LEVELS AND
-OVERRIDE MODE section below for details.
+(or the beginning of the interactive session). See the DEFINITION LEVELS
+section below for details.
.TP
.B "stats \fR[on|off]\fP"
Enables (default) or disables ``stats'' mode, in which various statistics are
@@ -1559,7 +1577,7 @@
.B underride
Exits ``override'' mode. This returns you to the normal mode of operation,
where new equations are added `below'' previous rules of an existing function.
-See the DEFINITION LEVELS AND OVERRIDE MODE section below for details.
+See the DEFINITION LEVELS section below for details.
.PP
Note that these special commands are only recognized at the beginning of the
interactive command line. (Thus you can escape a symbol looking like a command
@@ -1611,6 +1629,12 @@
.B -m
Print information about defined macros.
.TP
+.B -p[\fIflag\fP]
+List only private symbols in the current module if \fIflag\fP is nonzero (the
+default), otherwise (\fIflag\fP is zero) list only public symbols of all
+modules. List both private and public symbols if -p is omitted. The
+\fIflag\fP parameter, if given, must immediately follow the option character.
+.TP
.B -s
Summary format, print just summary information about listed symbols.
.TP
@@ -1619,9 +1643,8 @@
current level by default) or above. The \fIlevel\fP parameter, if given, must
immediately follow the option character. A \fIlevel\fP of 1 denotes all
temporary definitions, whereas 0 indicates \fIall\fP definitions (which is the
-default if \fB-t\fP is not specified). See the DEFINITION LEVELS AND OVERRIDE
-MODE section below for information about the notion of temporary definition
-levels.
+default if \fB-t\fP is not specified). See the DEFINITION LEVELS section below
+for information about the notion of temporary definition levels.
.TP
.B -v
Print information about defined variables.
@@ -1673,20 +1696,23 @@
the sources, the
.B list
command can easily do it for you. For instance, here's how you can list the
-definitions of all list ``zipping'' operations from the prelude in one go:
+definitions of all list ``fold'' operations from the prelude in one go:
.sp
.nf
-> \fBlist\fP -g zip*
-zip (x:xs) (y:ys) = (x,y):zip xs ys;
-zip _ _ = [];
-zip3 (x:xs) (y:ys) (z:zs) = (x,y,z):zip3 xs ys zs;
-zip3 _ _ _ = [];
-zipwith f (x:xs) (y:ys) = f x y:zipwith f xs ys;
-zipwith f _ _ = [];
-zipwith3 f (x:xs) (y:ys) (z:zs) = f x y z:zipwith3 f xs ys zs;
-zipwith3 f _ _ _ = [];
+> \fBlist\fP -g fold*
+foldl f a s::string = foldl f a (chars s);
+foldl f a [] = a;
+foldl f a (x:xs) = foldl f (f a x) xs;
+foldl1 f s::string = foldl1 f (chars s);
+foldl1 f (x:xs) = foldl f x xs;
+foldr f a s::string = foldr f a (chars s);
+foldr f a [] = a;
+foldr f a (x:xs) = f x (foldl (flip f) a (reverse xs));
+foldr1 f s::string = foldr1 f (chars s);
+foldr1 f [x] = x;
+foldr1 f (x:xs) = f x (foldl1 (flip f) (reverse xs));
.fi
-.SH DEFINITION LEVELS AND OVERRIDE MODE
+.SH DEFINITION LEVELS
To help with incremental development, the interpreter also offers some
facilities to manipulate the current set of definitions interactively. To
these ends, definitions are organized into different subsets called
@@ -1700,7 +1726,8 @@
.B run
command) and returns you to the previous one (if any). This gives you a
``stack'' of up to 255 temporary environments which enables you to ``plug and
-play'' in a safe fashion, without affecting the rest of your program. Example:
+play'' in a (more or less) safe fashion, without affecting the rest of your
+program. Example:
.sp
.nf
> foo (x:xs) = x+foo xs;
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ag...@us...> - 2008-08-29 14:55:43
|
Revision: 657
http://pure-lang.svn.sourceforge.net/pure-lang/?rev=657&view=rev
Author: agraef
Date: 2008-08-29 14:55:53 +0000 (Fri, 29 Aug 2008)
Log Message:
-----------
Update documentation.
Modified Paths:
--------------
pure/trunk/pure.1.in
Modified: pure/trunk/pure.1.in
===================================================================
--- pure/trunk/pure.1.in 2008-08-29 09:31:43 UTC (rev 656)
+++ pure/trunk/pure.1.in 2008-08-29 14:55:53 UTC (rev 657)
@@ -458,12 +458,14 @@
and
.BR case ,
followed by conditional expressions (\fBif\fP-\fBthen\fP-\fBelse\fP), followed
-by the ``simple'' expressions (i.e., all other kinds of expressions involving
-operators, function applications, constants, symbols and other primary
-expressions). Precedence and associativity of operator symbols are given by
-their declarations (in the prelude or the user's program), and function
-application binds stronger than all operators. Parentheses can be used to
-override default precedences and associativities as usual.
+by the
+.IR "simple expressions" ,
+i.e., all other kinds of expressions involving operators, function
+applications, constants, symbols and other primary expressions. Precedence and
+associativity of operator symbols are given by their declarations (in the
+prelude or the user's program), and function application binds stronger than
+all operators. Parentheses can be used to override default precedences and
+associativities as usual.
.PP
The common operator symbols like +, -, *, / etc. are all declared at the
beginning of the prelude, see the
@@ -513,10 +515,13 @@
and expressions to be evaluated:
.TP
.B Rules: \fIlhs\fR = \fIrhs\fR;
-The basic form can also be augmented with a condition \fBif\fP\ \fIguard\fP
-tacked on to the end of the rule (which restricts the applicability of the
-rule to the case that the guard evaluates to a nonzero integer), or the
-keyword
+These rules always combine a left-hand side
+.I pattern
+(which must be a simple expression) and a right-hand side (which can be any
+kind of Pure expression described above). In some cases, this basic form can
+also be augmented with a condition \fBif\fP\ \fIguard\fP tacked on to the end
+of the rule (which restricts the applicability of the rule to the case that
+the guard evaluates to a nonzero integer), or the keyword
.B otherwise
denoting an empty guard which is always true (this is nothing but syntactic
sugar to point out the ``default'' case of a definition; the interpreter just
@@ -532,7 +537,7 @@
function. No guards or multiple left-hand and right-hand sides are permitted
here. Macro rules are used to preprocess expressions on the right-hand side of
other definitions at compile time, and are typically employed to implement
-user-defined special forms and simple kinds of optimizations rules. See the
+user-defined special forms and simple kinds of optimization rules. See the
MACROS section below for details and examples.
.TP
.B Global variable bindings: let\fR \fIlhs\fR = \fIrhs\fR;
@@ -759,9 +764,10 @@
is picked. (Again, the \fBwhen\fP construct is treated differently, because
each rule is actually a separate definition.)
.PP
-In any case, the left-hand side pattern must not contain repeated variables
-(i.e., rules must be ``left-linear''), except for the anonymous variable `_'
-which matches an arbitrary value without binding a variable symbol.
+In any case, the left-hand side pattern (which, as already mentioned, is
+always a simple expression) must not contain repeated variables (i.e., rules
+must be ``left-linear''), except for the anonymous variable `_' which matches
+an arbitrary value without binding a variable symbol.
.PP
A left-hand side variable (including the anonymous variable) may be followed
by one of the special type tags \fB::int\fP, \fB::bigint\fP, \fB::double\fP,
@@ -855,7 +861,13 @@
.SH MACROS
Macros are a special type of functions to be executed as a kind of
``preprocessing stage'' at compile time. In Pure these are typically used to
-define custom special forms and to perform inlining of simple function calls.
+define custom special forms, and to perform inlining of function calls and
+other simple kinds of source-level optimizations. In the following, these are
+also referred to as
+.I convenience
+and
+.IR "optimization macros" ,
+respectively.
.PP
Whereas the macro facilities of most programming languages simply provide a
kind of textual substitution mechanism, Pure macros operate on symbolic
@@ -881,6 +893,7 @@
calls in macro arguments are expanded before the macro gets applied to its
parameters).
.PP
+.B Optimization rules.
Here is a simple example, showing a rule which expands saturated calls of the
.B succ
function (defined in the prelude) at compile time:
@@ -892,50 +905,96 @@
foo x::int = x+1+1;
.fi
.PP
-Rules like these can be useful to help the compiler generate better
-code. E.g., try the following interactive command to have a look at the
-assembler code for the above `foo' function (\fIwarning:\fP this is not for
-the faint at heart):
+Rules like these can be useful to help the compiler generate better code. Note
+that a macro may have the same name as an ordinary Pure function, which is
+essential if you want to optimize calls to an existing function, as in the
+previous example.
+.PP
+A somewhat more practical example is the following rule from the prelude,
+which eliminates saturated instances of the right-associative function
+application operator:
.sp
.nf
-> \fBlist\fP -d foo
+\fBdef\fP f $ x = f x;
.fi
.PP
-You'll see that (ignoring the function header and the boilerplate code for
-boxing and unboxing Pure expressions generated by the compiler) it essentially
-boils down to just a single integer increment instruction:
+Like in Haskell, this low-priority operator is handy to write cascading
+function calls. With the above macro rule, these will be ``inlined'' as
+ordinary function applications automagically. Example:
.sp
.nf
- ...
- %intval = load i32* %1 ; <i32> [#uses=1]
- add i32 %intval, 2 ; <i32>:2 [#uses=1]
- ...
+> foo x = bar $ bar $ 2*x;
+> \fBlist\fP foo
+foo x = bar (bar (2*x));
.fi
.PP
-Note that a macro may have the same name as an ordinary Pure function, which
-is useful for optimizing calls to an existing function, as shown in the
-example above. As a somewhat more practical example, since Pure 0.6 the
-following rule has been added to the prelude to eliminate saturated instances
-of the right-associative function application operator:
+Here is slightly more tricky rule from the prelude, which optimizes the case
+of ``throwaway'' list comprehensions. This is useful if a list comprehension
+is evaluated solely for its side effects.
.sp
.nf
-\fBdef\fP f $ x = f x;
+\fBdef\fP void (catmap f x) = do f x;
.fi
+.PP
+Note that the `void' function simply throws away its argument and returns ()
+instead. The `do' function applies a function to every member of a list (like
+`map'), but throws away all intermediate results and just returns (), which is
+much more efficient if you don't need those results anyway. These are both
+defined in the prelude.
+.PP
+Let's see how this rule transforms a list comprehension if we ``voidify'' it:
.sp
-Like in Haskell, this low-priority operator is handy to write cascading
-function calls. With the above macro rule, these will be ``inlined'' as
-ordinary function applications automagically. Example:
+.nf
+> \fBusing\fP system;
+> f = [printf "%g\n" (2^x+1); x=1..5; x mod 2];
+> g = void [printf "%g\n" (2^x+1); x=1..5; x mod 2];
+> \fBlist\fP f g
+f = catmap (\ex -> if x mod 2 then [printf "%g\n" (2^x+1)] else []) (1..5);
+g = do (\ex -> if x mod 2 then [printf "%g\n" (2^x+1)] else []) (1..5);
+.fi
+.PP
+Ok, so the `catmap' got replaced with a `do' which is just what we need to
+make this code go essentially as fast as a `for' loop in conventional
+programming languages (up to constant factors, of course). Here's how it looks
+like when we run the `g' function:
.sp
.nf
-> foo x = bar $ bar $ 2*x;
-> \fBlist\fP foo
-foo x = bar (bar (2*x));
+> g;
+3
+9
+33
+()
.fi
.PP
-Macros can also be recursive, consist of multiple rules and make use of
-pattern-matching like ordinary function definitions. Example:
+It's not all roses, however, since the above macro rule will only get rid of
+the outermost `catmap' if the list comprehension binds multiple variables:
.sp
.nf
+> u = void [puts $ str (x,y); x=1..2; y=1..3];
+> \fBlist\fP u
+u = do (\ex -> catmap (\ey -> [puts (str (x,y))]) (1..3)) (1..2);
+.fi
+.PP
+If you're bothered by this, you'll have to apply `void' recursively, creating
+a nested list comprehension which expands to a nested `do':
+.sp
+.nf
+> v = void [void [puts $ str (x,y); y=1..3]; x=1..2];
+> \fBlist\fP v
+v = do (\ex -> [do (\ey -> [puts (str (x,y))]) (1..3)]) (1..2);
+.fi
+.PP
+(It would be nice to have this handled automatically, but the left-hand side
+of a macro definition must be a simple expression, and thus it's not possible
+to write a macro which descends recursively into the lambda argument of
+`catmap'.)
+.PP
+.B Recursive macros.
+Macros can also be recursive, in which case they usually consist of multiple
+rules and make use of pattern-matching like ordinary function
+definitions. Example:
+.sp
+.nf
> \fBdef\fP foo (bar x) = foo x+1;
> \fBdef\fP foo x = x;
> baz = foo (bar (bar (bar x)));
@@ -943,17 +1002,29 @@
baz = x+1+1+1;
.fi
.PP
-Note that, whereas the right-hand side of a constant definition really gets
-evaluated to a normal form at the time the definition is processed, the only
-things that get evaluated during macro substitution are other macros. The
-right-hand side may be an arbitrary Pure expression involving conditional
-expressions, lambdas, binding clauses, etc., but these are
+Note that, technically, Pure macros are just as powerful as (unconditional)
+term rewriting systems and thus they are Turing-complete. This implies that a
+badly written macro may well send the Pure compiler into an infinite
+recursion, which results in a stack overflow at compile time. See the CAVEATS
+AND NOTES section at the end of this manual for information on how to deal
+with these by setting the
+.B PURE_STACK
+environment variable.
+.PP
+.B Convenience macros.
+The following `timex' macro provides an example of how you can use macros to
+define your own special forms. This is made possible by the fact that the
+macro arguments will only be evaluated at runtime and can thus be passed to
+built-in special forms and other constructs which defer their evaluation. In
+fact, the right-hand side of a macro rule may be an arbitrary Pure expression
+involving conditional expressions, lambdas, binding clauses, etc. These are
.I not
evaluated during macro substitution, they just become part of the macro
-expansion (after substituting the macro parameters). For instance, here is a
-useful little macro `timex', which employs the system function `clock' to
-report the cpu time in seconds needed to evaluate a given expression, along
-with the computed result:
+expansion (after substituting the macro parameters).
+.PP
+Our definition of `timex' employs the system function `clock' to report the
+cpu time in seconds needed to evaluate a given expression, along with the
+computed result:
.sp
.nf
> \fBusing\fP system;
@@ -963,19 +1034,16 @@
0.43,5000050000L
.fi
.PP
-The `timex' macro also provides a useful example of how you can use macros to
-define your own special forms, since the macro arguments will only be
-evaluated at runtime and can thus be passed to built-in special forms and
-other constructs which defer their evaluation. (Note that the above definition
-of `timex' wouldn't work as an ordinary function definition, since by virtue
-of Pure's basic eager evaluation strategy the x parameter would have been
-evaluated already before it is passed to `timex', making `timex' always return
-a zero time value. Try it.)
+(Note that the above definition of `timex' wouldn't work as an ordinary
+function definition, since by virtue of Pure's basic eager evaluation strategy
+the x parameter would have been evaluated already before it is passed to
+`timex', making `timex' always return a zero time value. Try it.)
.PP
-Finally, note that Pure macros are lexically scoped, i.e., symbols on the
-right-hand-side of a macro definition can never refer to anything outside the
-macro definition, and macro parameter substitution also takes into account
-binding constructs, such as
+.B Macro hygiene.
+Pure macros are lexically scoped, i.e., symbols on the right-hand-side of a
+macro definition can never refer to anything outside the macro definition, and
+macro parameter substitution also takes into account binding constructs, such
+as
.B with
and
.B when
@@ -985,13 +1053,11 @@
macros. They are not susceptible to so-called ``name capture,'' which makes
macros in less sophisticated languages bug-ridden and hard to use.
.PP
-Despite their simplicity and ease of use, Pure's macros are an incredibly
-powerful feature. But with power comes responsibility. If over-used, or used
-in inappropriate ways, macros can make your code incromprehensible and
-bloated, and a buggy macro may well kick the Pure compiler into an endless
-loop (usually resulting in a stack overflow at compile time). In other words,
-macros are a good way to shoot yourself in the foot. So use them thoughtfully
-and with care.
+Pure macros also have their limitations. Specifically, the left-hand side of a
+macro rule must be a simple expression, just like in ordinary function
+definitions. This restricts the kinds of expressions which can be rewritten by
+a macro. But Pure macros are certainly powerful enough for most common
+preprocessing purposes, while still being robust and easy to use.
.SH DECLARATIONS
Pure is a very terse language by design; you don't declare much stuff, you
just define it and be done with it. Usually, all necessary information about
@@ -1899,6 +1965,47 @@
the anonymous ``as'' pattern trick is a small price to pay for that
convenience.
.PP
+Sometimes you may also run into the complementary problem, i.e., to match a
+function argument against a given function. Consider this code fragment:
+.sp
+.nf
+foo x = x+1;
+foop f = \fBcase\fP f \fBof\fP foo = 1; _ = 0 \fBend\fP;
+.fi
+.PP
+You might expect `foop' to return true for `foo', and false on all other
+values. Better think again, because in reality `foop' will
+.I always
+return true! In fact, the Pure compiler will warn you about the second rule
+of the
+.B case
+expression not being used at all:
+.sp
+.nf
+> foop 99;
+warning: rule never reduced: _ = 0;
+1
+.fi
+.PP
+This happens because a non-nullary symbol on the left-hand side of a rule,
+which is not the head symbol of a function application, is always considered
+to be a variable, even if that symbol is defined as a global function
+elsewhere. So `foo' isn't a literal name in the above
+.B case
+expression, it's a variable! (As a matter of fact, this is rather useful,
+since otherwise a rule like `f g = g+1' would suddenly change meaning if you
+happen to add a definition like `g x = x-1' somewhere else in your program,
+which certainly isn't desirable.)
+.PP
+Fortunately, the syntactic equality operator `===' defined in the prelude
+comes to the rescue here. Just define `foop' as follows:
+.sp
+.nf
+> foop f = f===foo;
+> foop foo, foop 99;
+1,0
+.fi
+.PP
.B With or when?
A common source of confusion for Haskellers is that Pure provides two
different constructs to bind local function and variable symbols,
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ag...@us...> - 2008-08-29 22:22:02
|
Revision: 659
http://pure-lang.svn.sourceforge.net/pure-lang/?rev=659&view=rev
Author: agraef
Date: 2008-08-29 22:22:12 +0000 (Fri, 29 Aug 2008)
Log Message:
-----------
Update documentation.
Modified Paths:
--------------
pure/trunk/pure.1.in
Modified: pure/trunk/pure.1.in
===================================================================
--- pure/trunk/pure.1.in 2008-08-29 21:08:59 UTC (rev 658)
+++ pure/trunk/pure.1.in 2008-08-29 22:22:12 UTC (rev 659)
@@ -51,6 +51,15 @@
convenient, fully interactive environment for running Pure scripts and
evaluating expressions.
.PP
+Pure programs (a.k.a.
+.IR scripts )
+are just ordinary text files containing Pure code. A bunch of syntax
+highlighting files and programming modes for various popular text editors are
+included in the Pure sources. There's no difference between the Pure
+programming language and the input language accepted by the interpreter,
+except that the interpreter also understands some special commands when
+running in interactive mode; see the INTERACTIVE USAGE section for details.
+.PP
If any source scripts are specified on the command line, they are loaded and
executed, after which the interpreter exits. Otherwise the interpreter enters
the interactive read-eval-print loop. You can also use the
@@ -64,9 +73,9 @@
When the interpreter is in interactive mode and reads from a tty, commands are
read using
.BR readline (3)
-(providing completion for all commands listed in section INTERACTIVE USAGE
-below, as well as for symbols defined in the running program) and, when
-exiting the interpreter, the command history is stored in
+(providing completion for all commands listed under INTERACTIVE USAGE, as well
+as for symbols defined in the running program) and, when exiting the
+interpreter, the command history is stored in
.BR ~/.pure_history ,
from where it is restored the next time you run the interpreter.
.PP
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ag...@us...> - 2008-08-30 02:13:51
|
Revision: 662
http://pure-lang.svn.sourceforge.net/pure-lang/?rev=662&view=rev
Author: agraef
Date: 2008-08-30 02:14:01 +0000 (Sat, 30 Aug 2008)
Log Message:
-----------
Fix formatting glitch.
Modified Paths:
--------------
pure/trunk/pure.1.in
Modified: pure/trunk/pure.1.in
===================================================================
--- pure/trunk/pure.1.in 2008-08-30 01:33:10 UTC (rev 661)
+++ pure/trunk/pure.1.in 2008-08-30 02:14:01 UTC (rev 662)
@@ -955,8 +955,8 @@
.sp
.nf
> \fBusing\fP system;
-> f = [printf "%g\n" (2^x+1); x=1..5; x mod 2];
-> g = void [printf "%g\n" (2^x+1); x=1..5; x mod 2];
+> f = [printf "%g\en" (2^x+1); x=1..5; x mod 2];
+> g = void [printf "%g\en" (2^x+1); x=1..5; x mod 2];
> \fBlist\fP f g
f = catmap (\ex -> if x mod 2 then [printf "%g\n" (2^x+1)] else []) (1..5);
g = do (\ex -> if x mod 2 then [printf "%g\n" (2^x+1)] else []) (1..5);
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ag...@us...> - 2008-09-01 16:09:35
|
Revision: 682
http://pure-lang.svn.sourceforge.net/pure-lang/?rev=682&view=rev
Author: agraef
Date: 2008-09-01 16:09:44 +0000 (Mon, 01 Sep 2008)
Log Message:
-----------
Update documentation.
Modified Paths:
--------------
pure/trunk/pure.1.in
Modified: pure/trunk/pure.1.in
===================================================================
--- pure/trunk/pure.1.in 2008-09-01 15:12:23 UTC (rev 681)
+++ pure/trunk/pure.1.in 2008-09-01 16:09:44 UTC (rev 682)
@@ -291,9 +291,9 @@
first, i.e., using
.I "call by value"
semantics. Pure also has a few built-in special forms (most notably,
-conditional expressions, the short-circuit logical connectives && and || and
-the sequencing operator $$) which take some of their arguments unevaluated,
-using
+conditional expressions, the short-circuit logical connectives && and ||, the
+sequencing operator $$, and the lazy evaluation operator &) which take some or
+all of their arguments unevaluated, using
.IR "call by name" .
(User-defined special forms can be created with macros. More about that
later.)
@@ -491,8 +491,7 @@
.B and
and
.B or
-instead of `&' and `|', because the latter is reserved as a special symbol in
-rules, see RULE SYNTAX below.
+instead of `&' and `|', which are used for other purposes in Pure.
.PP
.B Special forms.
As already mentioned, some operators are actually implemented as special
@@ -504,11 +503,12 @@
mode just like in C. Thus, e.g., x&&y immediately becomes false if x evaluates
to false, without ever evaluating y.
.PP
-Another important special form is the sequencing operator $$, which evaluates
-its left operand, immediately throws the result away and then goes on to
-evaluate the right operand which gives the result of the entire
-expression. This operator is useful to write imperative-style code such as the
-following prompt/input interaction:
+The
+.I sequencing
+operator $$ evaluates its left operand, immediately throws the result away and
+then goes on to evaluate the right operand which gives the result of the
+entire expression. This operator is useful to write imperative-style code such
+as the following prompt/input interaction:
.sp
.nf
> \fBusing\fP system;
@@ -518,6 +518,40 @@
21.0
.fi
.PP
+The & operator does
+.IR "lazy evaluation" .
+More precisely, it turns its operand into a kind of parameterless anonymous
+closure, deferring its evaluation. These kinds of objects are commonly known
+as
+.I thunks
+or
+.IR futures .
+When the value of a future is actually needed (during pattern-matching, or
+when the value becomes an argument of a C call), it is evaluated automagically
+and gets
+.IR memoized ,
+i.e., the computed result replaces the thunk so that it only has to be
+computed once. Futures are useful to implement all kinds of lazy data
+structures in Pure, in particular: lazy lists a.k.a.
+.IR streams .
+A stream is simply a list with a thunked tail, which allows it to be
+infinite. E.g.:
+.sp
+.nf
+> ints n = n : ints (n+1) &; let nats = ints 1;
+> nats;
+1:<<thunk 0xb6033528>>
+> take 10 nats;
+[1,2,3,4,5,6,7,8,9,10]
+> nats;
+1:2:3:4:5:6:7:8:9:10:11:<<thunk 0xb5fb1a08>>
+> nats!9999;
+10000
+.fi
+.sp
+Note that the prelude defines & as a postfix operator which binds stronger
+than any other operation except function application.
+.PP
.B Toplevel.
At the toplevel, a Pure program basically consists of rewriting rules (which
are used to define functions and macros), constant and variable definitions,
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ag...@us...> - 2008-09-04 01:18:03
|
Revision: 695
http://pure-lang.svn.sourceforge.net/pure-lang/?rev=695&view=rev
Author: agraef
Date: 2008-09-04 01:18:14 +0000 (Thu, 04 Sep 2008)
Log Message:
-----------
Update documentation.
Modified Paths:
--------------
pure/trunk/pure.1.in
Modified: pure/trunk/pure.1.in
===================================================================
--- pure/trunk/pure.1.in 2008-09-04 00:45:30 UTC (rev 694)
+++ pure/trunk/pure.1.in 2008-09-04 01:18:14 UTC (rev 695)
@@ -411,7 +411,7 @@
lambdas, conditional expressions and ``catmaps'' (a list operation which
combines list concatenation and mapping a function over a list, defined in the
prelude), but they are often much easier to write. Some examples of list
-comprehensions can be found below at the end of this section.
+comprehensions can be found in the EXAMPLES section below.
.TP
.B Function applications: \fRfoo\ x\ y\ z
As in other modern FPLs, these are written simply as juxtaposition (i.e., in
@@ -520,9 +520,11 @@
.PP
The & operator does
.IR "lazy evaluation" .
-More precisely, it turns its operand into a kind of parameterless anonymous
-closure, deferring its evaluation. These kinds of objects are commonly known
-as
+This is the only postfix operator defined in the standard prelude, written as
+`x&', where x is an arbitrary Pure expression. The & operator binds stronger
+than any other operation except function application. It turns its operand
+into a kind of parameterless anonymous closure, deferring its
+evaluation. These kinds of objects are also commonly known as
.I thunks
or
.IR futures .
@@ -535,22 +537,9 @@
structures in Pure, in particular: lazy lists a.k.a.
.IR streams .
A stream is simply a list with a thunked tail, which allows it to be
-infinite. E.g.:
-.sp
-.nf
-> ints n = n : ints (n+1) &; let nats = ints 1;
-> nats;
-1:<<thunk 0xb6033528>>
-> take 10 nats;
-[1,2,3,4,5,6,7,8,9,10]
-> nats;
-1:2:3:4:5:6:7:8:9:10:11:<<thunk 0xb5fb1a08>>
-> nats!9999;
-10000
-.fi
-.sp
-Note that the prelude defines & as a postfix operator which binds stronger
-than any other operation except function application.
+infinite. The Pure prelude defines many functions for creating and
+manipulating these kinds of objects; further details and examples can be found
+in the EXAMPLES section below.
.PP
.B Toplevel.
At the toplevel, a Pure program basically consists of rewriting rules (which
@@ -699,8 +688,7 @@
symbols needed in an evaluation
.I before
entering the expression to be evaluated.
-.PP
-.B Examples.
+.SH EXAMPLES
Here are a few examples of simple Pure programs (see the following section for
a closer discussion of the rule syntax).
.PP
@@ -756,7 +744,8 @@
6.28318530717958
.fi
.PP
-A little list comprehension example (Erathosthenes' classical prime sieve):
+.B List comprehensions.
+Erathosthenes' classical prime sieve:
.sp
.nf
primes n = sieve (2..n) \fBwith\fP
@@ -796,6 +785,136 @@
= i1==i2 || j1==j2 || i1+j1==i2+j2 || i1-j1==i2-j2;
\fBend\fP;
.fi
+.PP
+.B Lazy evaluation and streams.
+As already mentioned, lists can also be evaluated in a ``lazy'' fashion, by
+just turning the tail of a list into a
+.IR future .
+This special kind of list is also called a
+.IR stream .
+Streams enable you to work with infinite lists (or finite lists which are so
+huge that we would never want to keep them in memory). E.g., here's one way to
+create the infinite list of all positive integers:
+.sp
+.nf
+> ones = 1:ones&;
+> integers = 1 : zipwith (+) ones integers&;
+> \fBlet\fP ints = integers; ints;
+1:<<thunk 0xb5fdd5b8>>
+.fi
+.PP
+(Note that we use machine integers in this example, so in fact the list will
+wrap around to the smallest negative integer at some point.)
+.PP
+Of course, care must be taken not to invoke ``eager'' operations such as `#'
+(which computes the size of a list) on infinite streams, since this never
+terminates. However, many list operations work with infinite streams just
+fine, and return the appropriate stream results. E.g., the `take' function
+(which retrieves a given number of elements from the front of a list) works
+with streams just as well as with ``eager'' lists:
+.sp
+.nf
+> take 10 ints;
+1:<<thunk 0xb5fdd5e8>>
+.fi
+.PP
+Hmm, not much progress there, but that's just how streams work (or rather
+don't, they're lazy bums indeed!). But the stream computed with `take' is in
+fact finite and we can readily convert it to an ordinary list, forcing its
+evaluation:
+.sp
+.nf
+> (list) (take 10 ints);
+[1,2,3,4,5,6,7,8,9,10]
+.fi
+.PP
+(Note that we typed `(list)' instead of just `list' here, so that the
+interpreter does not mistake this for the interactive
+.B list
+command. This is only necessary at the interactive command prompt, see
+INTERACTIVE USAGE.)
+.PP
+For interactive usage it's often convenient to define an eager variation of
+`take' which combines `take' and `list'. Let's do this now, so that we can use
+this operation in the following examples.
+.sp
+.nf
+> takel n xs = list (take n xs);
+> takel 10 ints;
+[1,2,3,4,5,6,7,8,9,10]
+.fi
+.PP
+Let's take another look at the `ints' stream now:
+.sp
+.nf
+> ints;
+1:2:3:4:5:6:7:8:9:10:<<thunk 0xb5fddcd8>>
+.fi
+.PP
+As you can see, the invokation of `list' on the result of `take' forced the
+corresponding prefix of the `ints' stream to be computed. The result of this
+is memoized, so that this portion of the stream is now readily available in
+case we need to have another look at it again later. By these means, possibly
+costly reevaluations are avoided, trading memory for execution speed.
+.PP
+A number of convenience operations are available for generating stream values.
+The prelude defines infinite arithmetic sequences, using
+.B inf
+or
+.B -inf
+to denote an upper (or lower) infinite bound for the sequence, e.g.:
+.sp
+.nf
+> let u = 1..inf; let v = -1.0,-1.2..-inf;
+> takel 10 u; takel 10 v;
+[1,2,3,4,5,6,7,8,9,10]
+[-1.0,-1.2,-1.4,-1.6,-1.8,-2.0,-2.2,-2.4,-2.6,-2.8]
+.fi
+.PP
+Other useful stream generator functions are `iterate', `repeat' and `cycle',
+which have been adopted from Haskell. Moreover, list comprehensions can draw
+values from streams and return the appropriate stream result:
+.sp
+.nf
+> \fBlet\fP pairs = [i,j; i=1..inf; j=1..i]; pairs;
+(1,1):<<thunk 0xb5f28818>>
+> takel 10 pairs;
+[(1,1),(2,1),(2,2),(3,1),(3,2),(3,3),(4,1),(4,2),(4,3),(4,4)]
+.fi
+.PP
+Finally, let's rewrite our prime sieve so that it generates the infinite
+stream of
+.I all
+prime numbers:
+.sp
+.nf
+all_primes = sieve (2..inf) \fBwith\fP
+ sieve [] = [];
+ sieve (p:qs) = p : sieve [q; q = qs; q mod p] &;
+\fBend\fP;
+.fi
+.sp
+Example:
+.sp
+.nf
+> \fBlet\fP P = all_primes;
+> takel 20 P;
+[2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71]
+> P!299;
+1987
+.fi
+.PP
+You can also just print the entire stream. This will run forever, so hit
+Ctrl-C when you get bored.
+.sp
+.nf
+> \fBusing\fP system;
+> do (printf "%d\en") all_primes;
+2
+3
+5
+ ...
+.fi
.SH RULE SYNTAX
Basically, the same rule syntax is used in all kinds of global and local
definitions. However, some constructs (specifically, \fBwhen\fP, \fBlet\fP,
@@ -1689,8 +1808,9 @@
See the DEFINITION LEVELS section below for details.
.PP
Note that these special commands are only recognized at the beginning of the
-interactive command line. (Thus you can escape a symbol looking like a command
-by prefixing it with a space.)
+interactive command line. (Thus you can escape an identifier at the beginning
+of the command line, which looks like a command, by prefixing it with a space
+or by wrapping it up in parentheses.)
.PP
Some commands which are especially important for effective operation of the
interpreter are discussed in more detail in the following sections.
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ag...@us...> - 2008-09-04 01:30:17
|
Revision: 697
http://pure-lang.svn.sourceforge.net/pure-lang/?rev=697&view=rev
Author: agraef
Date: 2008-09-04 01:30:26 +0000 (Thu, 04 Sep 2008)
Log Message:
-----------
Update documentation.
Modified Paths:
--------------
pure/trunk/pure.1.in
Modified: pure/trunk/pure.1.in
===================================================================
--- pure/trunk/pure.1.in 2008-09-04 01:26:04 UTC (rev 696)
+++ pure/trunk/pure.1.in 2008-09-04 01:30:26 UTC (rev 697)
@@ -614,7 +614,7 @@
.nf
> foo x = bar \fBwith\fP bar y = x+y \fBend\fP;
> \fBlet\fP f = foo 99; f;
-<<closure bar>>
+{{closure bar}}
> f 10, f 20;
109,119
.fi
@@ -800,7 +800,7 @@
> ones = 1:ones&;
> integers = 1 : zipwith (+) ones integers&;
> \fBlet\fP ints = integers; ints;
-1:<<thunk 0xb5fdd5b8>>
+1:{{thunk 0xb5fdd5b8}}
.fi
.PP
(Note that we use machine integers in this example, so in fact the list will
@@ -815,7 +815,7 @@
.sp
.nf
> take 10 ints;
-1:<<thunk 0xb5fdd5e8>>
+1:{{thunk 0xb5fdd5e8}}
.fi
.PP
Hmm, not much progress there, but that's just how streams work (or rather
@@ -848,7 +848,7 @@
.sp
.nf
> ints;
-1:2:3:4:5:6:7:8:9:10:<<thunk 0xb5fddcd8>>
+1:2:3:4:5:6:7:8:9:10:{{thunk 0xb5fddcd8}}
.fi
.PP
As you can see, the invokation of `list' on the result of `take' forced the
@@ -877,7 +877,7 @@
.sp
.nf
> \fBlet\fP pairs = [i,j; i=1..inf; j=1..i]; pairs;
-(1,1):<<thunk 0xb5f28818>>
+(1,1):{{thunk 0xb5f28818}}
> takel 10 pairs;
[(1,1),(2,1),(2,2),(3,1),(3,2),(3,3),(4,1),(4,2),(4,3),(4,4)]
.fi
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ag...@us...> - 2008-09-04 16:11:57
|
Revision: 701
http://pure-lang.svn.sourceforge.net/pure-lang/?rev=701&view=rev
Author: agraef
Date: 2008-09-04 16:12:04 +0000 (Thu, 04 Sep 2008)
Log Message:
-----------
Update documentation.
Modified Paths:
--------------
pure/trunk/pure.1.in
Modified: pure/trunk/pure.1.in
===================================================================
--- pure/trunk/pure.1.in 2008-09-04 16:11:47 UTC (rev 700)
+++ pure/trunk/pure.1.in 2008-09-04 16:12:04 UTC (rev 701)
@@ -793,39 +793,43 @@
This special kind of list is also called a
.IR stream .
Streams enable you to work with infinite lists (or finite lists which are so
-huge that we would never want to keep them in memory). E.g., here's one way to
-create the infinite list of all positive integers:
+huge that you would never want to keep them in memory in their
+entirety). E.g., here's one way to define the infinite stream of all Fibonacci
+numbers:
.sp
.nf
-> ones = 1:ones&;
-> integers = 1 : zipwith (+) ones integers&;
-> \fBlet\fP ints = integers; ints;
-1:{{thunk 0xb5fdd5b8}}
+> fibs = 0L : 1L : zipwith (+) fibs (tail fibs) &;
+> fibs;
+0L:1L:{{thunk 0xb5f875e8}}
.fi
.PP
-(Note that we use machine integers in this example, so in fact the list will
-wrap around to the smallest negative integer at some point.)
+Note the `&' on the tail of the list. This turns `fibs' into a stream, which
+is required to prevent `fibs' from recursing into samadhi. Also note that we
+work with bigints in this example because the Fibonacci numbers grow quite
+rapidly, so with machine integers the values would soon start wrapping around
+to negative integers.
.PP
-Of course, care must be taken not to invoke ``eager'' operations such as `#'
-(which computes the size of a list) on infinite streams, since this never
-terminates. However, many list operations work with infinite streams just
-fine, and return the appropriate stream results. E.g., the `take' function
-(which retrieves a given number of elements from the front of a list) works
-with streams just as well as with ``eager'' lists:
+Streams like these can be worked with in pretty much the same way as with
+lists. Of course, care must be taken not to invoke ``eager'' operations such
+as `#' (which computes the size of a list) on infinite streams, to prevent
+infinite recursion. However, many list operations work with infinite streams
+just fine, and return the appropriate stream results. E.g., the `take'
+function (which retrieves a given number of elements from the front of a list)
+works with streams just as well as with ``eager'' lists:
.sp
.nf
-> take 10 ints;
-1:{{thunk 0xb5fdd5e8}}
+> take 10 fibs;
+0L:1L:{{thunk 0xb5f87630}}
.fi
.PP
Hmm, not much progress there, but that's just how streams work (or rather
-don't, they're lazy bums indeed!). But the stream computed with `take' is in
-fact finite and we can readily convert it to an ordinary list, forcing its
-evaluation:
+don't, they're lazy bums indeed!). Nevertheless, the stream computed with
+`take' is in fact finite and we can readily convert it to an ordinary list,
+forcing its evaluation:
.sp
.nf
-> (list) (take 10 ints);
-[1,2,3,4,5,6,7,8,9,10]
+> (list) (take 10 fibs);
+[0L,1L,1L,2L,3L,5L,8L,13L,21L,34L]
.fi
.PP
(Note that we typed `(list)' instead of just `list' here, so that the
@@ -840,25 +844,98 @@
.sp
.nf
> takel n xs = list (take n xs);
-> takel 10 ints;
-[1,2,3,4,5,6,7,8,9,10]
+> takel 10 fibs;
+[0L,1L,1L,2L,3L,5L,8L,13L,21L,34L]
.fi
.PP
-Let's take another look at the `ints' stream now:
+Well, this naive definition of the Fibonacci stream works, but it's awfully
+inefficient. In fact, it takes exponential running time to determine the
+.IR n th
+member of the sequence, because of the two recursive calls to `fibs' on the
+right-hand side. This defect soon becomes rather annoying if we access larger
+members of the sequence. Just for fun, let's measure some evaluation times
+with the interactive
+.B stats
+command:
.sp
.nf
-> ints;
-1:2:3:4:5:6:7:8:9:10:{{thunk 0xb5fddcd8}}
+> \fBstats\fP
+> fibs!25; fibs!26; fibs!27;
+75025L
+2.29s
+121393L
+3.75s
+196418L
+6.12s
+> \fBstats off\fP
.fi
.PP
-As you can see, the invokation of `list' on the result of `take' forced the
-corresponding prefix of the `ints' stream to be computed. The result of this
-is memoized, so that this portion of the stream is now readily available in
-case we need to have another look at it again later. By these means, possibly
-costly reevaluations are avoided, trading memory for execution speed.
+It's quite apparent that the ratios between successive running times converge
+to the golden ratio from above (which is of course no accident!). So, assuming
+a fast computer which can produce the first stream element in a nanosecond, a
+conservative estimate of the time needed to compute just the 128th Fibonacci
+number would already exceed the current age of the universe by some 29.6%, if
+done this way. It goes without saying that this kind of algorithm won't even
+pass muster in a computer science freshman course.
.PP
-A number of convenience operations are available for generating stream values.
-The prelude defines infinite arithmetic sequences, using
+So let's get back to the drawing board. One nice trick of the trade is to have
+the
+.I value
+of the Fibonacci stream refer to itself in its definition, rather than just
+the function generating it. For that we need a kind of ``recursive variable
+definition'' which Pure doesn't have. (Haskellers should note here that the
+values of parameterless functions are never memoized in Pure, because that
+would wreak havoc on functions with side effects.) Fortunately, we can work
+around this quite easily by employing the so-called
+.IR "fixed point combinator" ,
+incidentally called
+.B fix
+in Pure and defined in the prelude as follows:
+.sp
+.nf
+> \fBlist\fP fix
+fix f = y y \fBwhen\fP y = \ex -> f (x x&) \fBend\fP;
+.fi
+.PP
+(Functional programming buffs surely notice that this is an implementation of
+the normal order fixed point combinator, decorated with `&' in the right place
+to make it work with eager evaluation. Aspiring novices may go read Wikipedia
+or a good book on the lambda calculus now.)
+.PP
+So here's how we can define a ``linear-time'' version of the Fibonacci
+stream. (Note that we also define the stream as a variable now, to take full
+advantage of memoization.)
+.sp
+.nf
+> \fBclear\fP fibs
+> \fBlet\fP fibs = fix (\ef -> 0L : 1L : zipwith (+) f (tail f) &);
+> fibs;
+0L:1L:{{thunk 0xb58d8ae0}}
+> takel 10 fibs;
+[0L,1L,1L,2L,3L,5L,8L,13L,21L,34L]
+> fibs;
+0L:1L:1L:2L:3L:5L:8L:13L:21L:34L:{{thunk 0xb4ce5d30}}
+.fi
+.PP
+As you can see, the invokation of our `takel' function forced the
+corresponding prefix of the `fibs' stream to be computed. The result of the
+evaluation is memoized, so that this portion of the stream is now readily
+available in case we need to have another look at it later. By these means,
+possibly costly reevaluations are avoided, trading memory for execution speed.
+.PP
+Also, the trick we played with the fixed point combinator pays off, and in
+fact computing large Fibonacci numbers is a piece of cake now:
+.sp
+.nf
+> \fBstats\fP
+> fibs!199;
+173402521172797813159685037284371942044301L
+0.1s
+> \fBstats off\fP
+.fi
+.PP
+Let's take a look at some of the other convenience operations for generating
+stream values. The prelude defines infinite arithmetic sequences, using
.B inf
or
.B -inf
@@ -872,16 +949,28 @@
.fi
.PP
Other useful stream generator functions are `iterate', `repeat' and `cycle',
-which have been adopted from Haskell. Moreover, list comprehensions can draw
-values from streams and return the appropriate stream result:
+which have been adopted from Haskell. In fact, infinite arithmetic
+progressions are implemented in terms of `iterate'. The `repeat' function just
+repeats its argument, and `cycle' cycles through the elements of the given
+list until hell freezes over:
.sp
.nf
-> \fBlet\fP pairs = [i,j; i=1..inf; j=1..i]; pairs;
-(1,1):{{thunk 0xb5f28818}}
-> takel 10 pairs;
-[(1,1),(2,1),(2,2),(3,1),(3,2),(3,3),(4,1),(4,2),(4,3),(4,4)]
+> takel 10 (repeat 1);
+[1,1,1,1,1,1,1,1,1,1]
+> takel 10 (cycle [0,1]);
+[0,1,0,1,0,1,0,1,0,1]
.fi
.PP
+Moreover, list comprehensions can draw values from streams and return the
+appropriate stream result:
+.sp
+.nf
+> \fBlet\fP rats = [m,n-m; n=2..inf; m=1..n-1; gcd m (n-m) == 1]; rats;
+(1,1):{{thunk 0xb5fd08b8}}
+> takel 10 rats;
+[(1,1),(1,2),(2,1),(1,3),(3,1),(1,4),(2,3),(3,2),(4,1),(1,5)]
+.fi
+.PP
Finally, let's rewrite our prime sieve so that it generates the infinite
stream of
.I all
@@ -915,6 +1004,12 @@
5
...
.fi
+.PP
+(Make sure that you really use the `all_primes' function instead of the P
+variable to print the stream. Otherwise the stream stored in P will grow with
+the number of elements printed until memory is exhausted. Calling `do' on a
+fresh instance of the stream of primes allows `do' to get rid of each `cons'
+cell after having printed the corresponding stream element.)
.SH RULE SYNTAX
Basically, the same rule syntax is used in all kinds of global and local
definitions. However, some constructs (specifically, \fBwhen\fP, \fBlet\fP,
@@ -2345,11 +2440,49 @@
.PP
.B Special forms.
Special forms are recognized at compile time only. Thus the catch function as
-well as the logical connectives && and || and the sequencing operator $$ are
-only treated as special forms in direct (saturated) calls. They can still be
-used if you pass them around as function values or partial applications, but
-in this case they lose all their special call-by-name argument processing.
+well as the logical connectives && and ||, the sequencing operator $$ and the
+lazy evaluation operator & are only treated as special forms in direct
+(saturated) calls. They can still be used if you pass them around as function
+values or partial applications, but in this case they lose all their special
+call-by-name argument processing.
.PP
+.B Laziness.
+Pure approaches lazy evaluation in basically the same as Alice ML, providing
+an explicit operation (&) to defer evaluation and create a ``future'' which is
+called by need. However, note that like any language with a basically eager
+evaluation strategy, Pure cannot really support lazy evaluation in a fully
+automatic way. That is, coding an operation so that it works with infinite
+data structures always requires additional effort to recognize futures in the
+input and handle them accordingly. This can be hard, but of course in the case
+of the prelude operations this work has already been done for you, so as long
+as you stick to these, you'll never have to think about these issues.
+.PP
+Specifically, the prelude goes to great lengths to implement all standard list
+operations in a way that properly deals with streams (a.k.a. list futures).
+What this all boils down to is that all list operations which can reasonably
+be expected to operate in a lazy way on streams, will do so. (Exceptions are
+inherently eager operations such as `#', reverse and foldl.) Only those
+portions of an input stream will be traversed which are strictly required to
+produce the result. For most purposes, this works just like in fully lazy FPLs
+such as Haskell. However, there are some notable differences:
+.IP *
+Since Pure uses dynamic typing, some of the list functions may have to peek
+ahead one element in input streams to check their arguments for validity,
+meaning that these functions will be slightly more eager than their Haskell
+counterparts.
+.IP *
+Pure's list functions never produce truly cyclic list structures such as the
+ones you get, e.g., with Haskell's `cycle' operation. (This is actually a good
+thing, because the current implementation of the interpreter cannot
+garbage-collect cyclic expression data.) Cyclic streams such as `cycle [1]' or
+`fix (\ex -> 1:x)' will of course work as expected, but, depending on the
+algorithm, memory usage may increase linearly as they are traversed.
+.IP *
+Pattern matching is always refutable (and therefore eager) in Pure. If you
+need something like Haskell's irrefutable matches, you'll have to code them
+explicitly using futures. See the definition of the `unzip' function in the
+prelude for an example showing how to do this.
+.PP
.B Stack size and tail recursion.
Pure programs may need a considerable amount of stack space to handle
recursive function calls, and the interpreter itself also takes its toll. So
@@ -2486,6 +2619,10 @@
Another functional programming language based on term rewriting,
\fIhttp://wouter.fov120.com/aardappel\fP.
.TP
+.B Alice ML
+A version of ML (see below) with ``futures'',
+\fIhttp://www.ps.uni-sb.de/alice\fP.
+.TP
.B Haskell
A popular non-strict FPL, \fIhttp://www.haskell.org\fP.
.TP
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ag...@us...> - 2008-09-04 23:01:31
|
Revision: 704
http://pure-lang.svn.sourceforge.net/pure-lang/?rev=704&view=rev
Author: agraef
Date: 2008-09-04 23:01:42 +0000 (Thu, 04 Sep 2008)
Log Message:
-----------
Update documentation.
Modified Paths:
--------------
pure/trunk/pure.1.in
Modified: pure/trunk/pure.1.in
===================================================================
--- pure/trunk/pure.1.in 2008-09-04 16:14:26 UTC (rev 703)
+++ pure/trunk/pure.1.in 2008-09-04 23:01:42 UTC (rev 704)
@@ -2020,21 +2020,15 @@
the sources, the
.B list
command can easily do it for you. For instance, here's how you can list the
-definitions of all list ``fold'' operations from the prelude in one go:
+definitions of all ``fold-left'' operations from the prelude in one go:
.sp
.nf
-> \fBlist\fP -g fold*
+> \fBlist\fP -g foldl*
foldl f a s::string = foldl f a (chars s);
foldl f a [] = a;
foldl f a (x:xs) = foldl f (f a x) xs;
foldl1 f s::string = foldl1 f (chars s);
foldl1 f (x:xs) = foldl f x xs;
-foldr f a s::string = foldr f a (chars s);
-foldr f a [] = a;
-foldr f a (x:xs) = f x (foldl (flip f) a (reverse xs));
-foldr1 f s::string = foldr1 f (chars s);
-foldr1 f [x] = x;
-foldr1 f (x:xs) = f x (foldl1 (flip f) (reverse xs));
.fi
.SH DEFINITION LEVELS
To help with incremental development, the interpreter also offers some
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ag...@us...> - 2008-09-05 00:44:23
|
Revision: 706
http://pure-lang.svn.sourceforge.net/pure-lang/?rev=706&view=rev
Author: agraef
Date: 2008-09-05 00:44:33 +0000 (Fri, 05 Sep 2008)
Log Message:
-----------
Update documentation.
Modified Paths:
--------------
pure/trunk/pure.1.in
Modified: pure/trunk/pure.1.in
===================================================================
--- pure/trunk/pure.1.in 2008-09-04 23:13:50 UTC (rev 705)
+++ pure/trunk/pure.1.in 2008-09-05 00:44:33 UTC (rev 706)
@@ -192,7 +192,7 @@
modules imported through a
.B using
clause. As a remedy, you can use the interactive
-.B list
+.B show
command (see the INTERACTIVE USAGE section below) to list definitions along
with additional debugging information.
.SH PURE OVERVIEW
@@ -738,7 +738,7 @@
> pi;
3.14159265358979
> foo x = 2*pi*x;
-> \fBlist\fP foo
+> \fBshow\fP foo
foo x = 2*3.14159265358979*x;
> foo 1;
6.28318530717958
@@ -765,7 +765,7 @@
expression the comprehension expanded to:
.sp
.nf
-> \fBlist\fP primes
+> \fBshow\fP primes
primes n = sieve (2..n) \fBwith\fP sieve [] = []; sieve (p:qs) = p:sieve
(catmap (\eq -> if q mod p then [q] else []) qs) \fBend\fP;
.fi
@@ -828,16 +828,10 @@
forcing its evaluation:
.sp
.nf
-> (list) (take 10 fibs);
+> list (take 10 fibs);
[0L,1L,1L,2L,3L,5L,8L,13L,21L,34L]
.fi
.PP
-(Note that we typed `(list)' instead of just `list' here, so that the
-interpreter does not mistake this for the interactive
-.B list
-command. This is only necessary at the interactive command prompt, see
-INTERACTIVE USAGE.)
-.PP
For interactive usage it's often convenient to define an eager variation of
`take' which combines `take' and `list'. Let's do this now, so that we can use
this operation in the following examples.
@@ -876,7 +870,7 @@
conservative estimate of the time needed to compute just the 128th Fibonacci
number would already exceed the current age of the universe by some 29.6%, if
done this way. It goes without saying that this kind of algorithm won't even
-pass muster in a computer science freshman course.
+pass muster in a freshman course.
.PP
So let's get back to the drawing board. One nice trick of the trade is to have
the
@@ -893,7 +887,7 @@
in Pure and defined in the prelude as follows:
.sp
.nf
-> \fBlist\fP fix
+> \fBshow\fP fix
fix f = y y \fBwhen\fP y = \ex -> f (x x&) \fBend\fP;
.fi
.PP
@@ -952,7 +946,7 @@
which have been adopted from Haskell. In fact, infinite arithmetic
progressions are implemented in terms of `iterate'. The `repeat' function just
repeats its argument, and `cycle' cycles through the elements of the given
-list until hell freezes over:
+list:
.sp
.nf
> takel 10 (repeat 1);
@@ -1158,7 +1152,7 @@
.nf
> \fBdef\fP succ x = x+1;
> foo x::int = succ (succ x);
-> \fBlist\fP foo
+> \fBshow\fP foo
foo x::int = x+1+1;
.fi
.PP
@@ -1181,7 +1175,7 @@
.sp
.nf
> foo x = bar $ bar $ 2*x;
-> \fBlist\fP foo
+> \fBshow\fP foo
foo x = bar (bar (2*x));
.fi
.PP
@@ -1205,7 +1199,7 @@
> \fBusing\fP system;
> f = [printf "%g\en" (2^x+1); x=1..5; x mod 2];
> g = void [printf "%g\en" (2^x+1); x=1..5; x mod 2];
-> \fBlist\fP f g
+> \fBshow\fP f g
f = catmap (\ex -> if x mod 2 then [printf "%g\n" (2^x+1)] else []) (1..5);
g = do (\ex -> if x mod 2 then [printf "%g\n" (2^x+1)] else []) (1..5);
.fi
@@ -1228,7 +1222,7 @@
.sp
.nf
> u = void [puts $ str (x,y); x=1..2; y=1..3];
-> \fBlist\fP u
+> \fBshow\fP u
u = do (\ex -> catmap (\ey -> [puts (str (x,y))]) (1..3)) (1..2);
.fi
.PP
@@ -1237,7 +1231,7 @@
.sp
.nf
> v = void [void [puts $ str (x,y); y=1..3]; x=1..2];
-> \fBlist\fP v
+> \fBshow\fP v
v = do (\ex -> [do (\ey -> [puts (str (x,y))]) (1..3)]) (1..2);
.fi
.PP
@@ -1255,7 +1249,7 @@
> \fBdef\fP foo (bar x) = foo x+1;
> \fBdef\fP foo x = x;
> baz = foo (bar (bar (bar x)));
-> \fBlist\fP baz
+> \fBshow\fP baz
baz = x+1+1+1;
.fi
.PP
@@ -1845,10 +1839,6 @@
.BR man (1)
with the given arguments.
.TP
-.B "list \fR[\fIoption\fP ...]\fP \fR[\fIsymbol\fP ...]\fP"
-List defined symbols in various formats. See the LIST COMMAND section below
-for details.
-.TP
.B "ls \fR[\fIargs\fP]\fP"
List files (shell \fBls\fP(1) command).
.TP
@@ -1891,6 +1881,10 @@
(or the beginning of the interactive session). See the DEFINITION LEVELS
section below for details.
.TP
+.B "show \fR[\fIoption\fP ...]\fP \fR[\fIsymbol\fP ...]\fP"
+Show the definitions of symbols in various formats. See the SHOW COMMAND
+section below for details.
+.TP
.B "stats \fR[on|off]\fP"
Enables (default) or disables ``stats'' mode, in which various statistics are
printed after an expression has been evaluated. Currently, this just prints
@@ -1909,12 +1903,12 @@
.PP
Some commands which are especially important for effective operation of the
interpreter are discussed in more detail in the following sections.
-.SH LIST COMMAND
+.SH SHOW COMMAND
In interactive mode, the
-.B list
+.B show
command can be used to obtain information about defined symbols in various
formats. This command recognizes the following options. Options may be
-combined, thus, e.g., \fBlist\fP -tvl is the same as \fBlist\fP -t -v -l.
+combined, thus, e.g., \fBshow\fP -tvl is the same as \fBshow\fP -t -v -l.
.TP
.B -a
Disassembles pattern matching automata. Works like the
@@ -1999,7 +1993,7 @@
prelude), simply say:
.sp
.nf
-> \fBlist\fP
+> \fBshow\fP
.fi
.PP
This may produce quite a lot of output, depending on which scripts are
@@ -2007,7 +2001,7 @@
variable symbols along with their current values (using the ``long format''):
.sp
.nf
-> \fBlist\fP -lv
+> \fBshow\fP -lv
argc var argc = 0;
argv var argv = [];
sysinfo var sysinfo = "i686-pc-linux-gnu";
@@ -2018,12 +2012,12 @@
If you're like me then you'll frequently have to look up how some operations
are defined. No sweat, with the Pure interpreter there's no need to dive into
the sources, the
-.B list
+.B show
command can easily do it for you. For instance, here's how you can list the
definitions of all ``fold-left'' operations from the prelude in one go:
.sp
.nf
-> \fBlist\fP -g foldl*
+> \fBshow\fP -g foldl*
foldl f a s::string = foldl f a (chars s);
foldl f a [] = a;
foldl f a (x:xs) = foldl f (f a x) xs;
@@ -2050,14 +2044,14 @@
.nf
> foo (x:xs) = x+foo xs;
> foo [] = 0;
-> \fBlist\fP -t
+> \fBshow\fP -t
foo (x:xs) = x+foo xs;
foo [] = 0;
> foo (1..10);
55
> \fBclear\fP
This will clear all temporary definitions at level #1. Continue (y/n)? y
-> \fBlist\fP foo
+> \fBshow\fP foo
> foo (1..10);
foo [1,2,3,4,5,6,7,8,9,10]
.fi
@@ -2076,7 +2070,7 @@
.nf
> foo (x:xs) = x+foo xs;
> foo [] = 0;
-> \fBlist\fP foo
+> \fBshow\fP foo
foo (x:xs) = x+foo xs;
foo [] = 0;
> foo (1..10);
@@ -2085,7 +2079,7 @@
save: now at temporary definitions level #2
> \fBoverride\fP
> foo (x:xs) = x*foo xs;
-> \fBlist\fP foo
+> \fBshow\fP foo
foo (x:xs) = x*foo xs;
foo (x:xs) = x+foo xs;
foo [] = 0;
@@ -2102,7 +2096,7 @@
.sp
.nf
> foo [] = 1;
-> \fBlist\fP foo
+> \fBshow\fP foo
foo (x:xs) = x*foo xs;
foo [] = 1;
foo (x:xs) = x+foo xs;
@@ -2123,7 +2117,7 @@
This will clear all temporary definitions at level #2. Continue (y/n)? y
clear: now at temporary definitions level #1
clear: override mode is on
-> \fBlist\fP foo
+> \fBshow\fP foo
foo (x:xs) = x+foo xs;
foo [] = 0;
> foo (1..10);
@@ -2339,7 +2333,7 @@
> \fBextern\fP double atan(double);
> \fBconst\fP pi = 4*atan 1.0;
> foo x = 2*pi*x;
-> \fBlist\fP foo
+> \fBshow\fP foo
foo x = 2*3.14159265358979*x;
.fi
.PP
@@ -2355,7 +2349,7 @@
> \fBclear\fP pi foo
> \fBdef\fP pi = 4*atan 1.0;
> foo x = 2*pi*x;
-> \fBlist\fP foo
+> \fBshow\fP foo
foo x = 2*(4*atan 1.0)*x;
.fi
.PP
@@ -2388,7 +2382,7 @@
.nf
> \fBconst\fP c = 2;
> foo x = c*x;
-> \fBlist\fP foo
+> \fBshow\fP foo
foo x = 2*x;
> foo 99;
198
@@ -2405,7 +2399,7 @@
> \fBclear\fP c
> \fBconst\fP c = 3;
> bar x = c*x;
-> \fBlist\fP foo bar
+> \fBshow\fP foo bar
foo x = 2*x;
bar x = 3*x;
.fi
@@ -2441,15 +2435,15 @@
call-by-name argument processing.
.PP
.B Laziness.
-Pure approaches lazy evaluation in basically the same as Alice ML, providing
-an explicit operation (&) to defer evaluation and create a ``future'' which is
-called by need. However, note that like any language with a basically eager
-evaluation strategy, Pure cannot really support lazy evaluation in a fully
-automatic way. That is, coding an operation so that it works with infinite
-data structures always requires additional effort to recognize futures in the
-input and handle them accordingly. This can be hard, but of course in the case
-of the prelude operations this work has already been done for you, so as long
-as you stick to these, you'll never have to think about these issues.
+Pure does lazy evaluation in the same way as Alice ML, providing an explicit
+operation (&) to defer evaluation and create a ``future'' which is called by
+need. However, note that like any language with a basically eager evaluation
+strategy, Pure cannot really support lazy evaluation in a fully automatic
+way. That is, coding an operation so that it works with infinite data
+structures always requires additional effort to recognize futures in the input
+and handle them accordingly. This can be hard, but of course in the case of
+the prelude operations this work has already been done for you, so as long as
+you stick to these, you'll never have to think about these issues.
.PP
Specifically, the prelude goes to great lengths to implement all standard list
operations in a way that properly deals with streams (a.k.a. list futures).
@@ -2594,7 +2588,7 @@
.TP
.B PURE_MORE
Shell command to be used for paging through output of the
-.B list
+.B show
command, when the interpreter runs in interactive mode.
.TP
.B PURE_PS
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ag...@us...> - 2008-09-05 01:12:49
|
Revision: 708
http://pure-lang.svn.sourceforge.net/pure-lang/?rev=708&view=rev
Author: agraef
Date: 2008-09-05 01:12:59 +0000 (Fri, 05 Sep 2008)
Log Message:
-----------
Update documentation.
Modified Paths:
--------------
pure/trunk/pure.1.in
Modified: pure/trunk/pure.1.in
===================================================================
--- pure/trunk/pure.1.in 2008-09-05 00:59:21 UTC (rev 707)
+++ pure/trunk/pure.1.in 2008-09-05 01:12:59 UTC (rev 708)
@@ -614,7 +614,7 @@
.nf
> foo x = bar \fBwith\fP bar y = x+y \fBend\fP;
> \fBlet\fP f = foo 99; f;
-{{closure bar}}
+#<closure bar>
> f 10, f 20;
109,119
.fi
@@ -800,7 +800,7 @@
.nf
> fibs = 0L : 1L : zipwith (+) fibs (tail fibs) &;
> fibs;
-0L:1L:{{thunk 0xb5f875e8}}
+0L:1L:#<thunk 0xb5f875e8>
.fi
.PP
Note the `&' on the tail of the list. This turns `fibs' into a stream, which
@@ -819,7 +819,7 @@
.sp
.nf
> take 10 fibs;
-0L:1L:{{thunk 0xb5f87630}}
+0L:1L:#<thunk 0xb5f87630>
.fi
.PP
Hmm, not much progress there, but that's just how streams work (or rather
@@ -843,7 +843,7 @@
.fi
.PP
Well, this naive definition of the Fibonacci stream works, but it's awfully
-inefficient. In fact, it takes exponential running time to determine the
+slow. In fact, it takes exponential running time to determine the
.IR n th
member of the sequence, because of the two recursive calls to `fibs' on the
right-hand side. This defect soon becomes rather annoying if we access larger
@@ -864,10 +864,10 @@
> \fBstats off\fP
.fi
.PP
-It's quite apparent that the ratios between successive running times converge
-to the golden ratio from above (which is of course no accident!). So, assuming
-a fast computer which can produce the first stream element in a nanosecond, a
-conservative estimate of the time needed to compute just the 128th Fibonacci
+It's quite apparent that the ratios between successive running times are about
+the golden ratio (which is of course no accident!). So, assuming a fast
+computer which can produce the head element of a stream in just a nanosecond,
+a conservative estimate of the time needed to compute just the 128th Fibonacci
number would already exceed the current age of the universe by some 29.6%, if
done this way. It goes without saying that this kind of algorithm won't even
pass muster in a freshman course.
@@ -904,11 +904,11 @@
> \fBclear\fP fibs
> \fBlet\fP fibs = fix (\ef -> 0L : 1L : zipwith (+) f (tail f) &);
> fibs;
-0L:1L:{{thunk 0xb58d8ae0}}
+0L:1L:#<thunk 0xb58d8ae0>
> takel 10 fibs;
[0L,1L,1L,2L,3L,5L,8L,13L,21L,34L]
> fibs;
-0L:1L:1L:2L:3L:5L:8L:13L:21L:34L:{{thunk 0xb4ce5d30}}
+0L:1L:1L:2L:3L:5L:8L:13L:21L:34L:#<thunk 0xb4ce5d30>
.fi
.PP
As you can see, the invokation of our `takel' function forced the
@@ -960,7 +960,7 @@
.sp
.nf
> \fBlet\fP rats = [m,n-m; n=2..inf; m=1..n-1; gcd m (n-m) == 1]; rats;
-(1,1):{{thunk 0xb5fd08b8}}
+(1,1):#<thunk 0xb5fd08b8>
> takel 10 rats;
[(1,1),(1,2),(2,1),(1,3),(3,1),(1,4),(2,3),(3,2),(4,1),(1,5)]
.fi
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ag...@us...> - 2008-09-05 02:11:29
|
Revision: 710
http://pure-lang.svn.sourceforge.net/pure-lang/?rev=710&view=rev
Author: agraef
Date: 2008-09-05 02:11:39 +0000 (Fri, 05 Sep 2008)
Log Message:
-----------
Update documentation.
Modified Paths:
--------------
pure/trunk/pure.1.in
Modified: pure/trunk/pure.1.in
===================================================================
--- pure/trunk/pure.1.in 2008-09-05 02:01:42 UTC (rev 709)
+++ pure/trunk/pure.1.in 2008-09-05 02:11:39 UTC (rev 710)
@@ -1897,9 +1897,11 @@
See the DEFINITION LEVELS section below for details.
.PP
Note that these special commands are only recognized at the beginning of the
-interactive command line. (Thus you can escape an identifier at the beginning
-of the command line, which looks like a command, by prefixing it with a space
-or by wrapping it up in parentheses.)
+interactive command line (they are not reserved keywords of the Pure
+language). Thus it's possible to ``escape'' identifiers looking like commands
+by entering a space at the start of the line. However, the compiler also warns
+you about identifiers which might be mistaken as command names, so that you
+can avoid this kind of problem.
.PP
Some commands which are especially important for effective operation of the
interpreter are discussed in more detail in the following sections.
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ag...@us...> - 2008-09-05 22:57:40
|
Revision: 721
http://pure-lang.svn.sourceforge.net/pure-lang/?rev=721&view=rev
Author: agraef
Date: 2008-09-05 22:57:51 +0000 (Fri, 05 Sep 2008)
Log Message:
-----------
Update documentation.
Modified Paths:
--------------
pure/trunk/pure.1.in
Modified: pure/trunk/pure.1.in
===================================================================
--- pure/trunk/pure.1.in 2008-09-05 14:12:15 UTC (rev 720)
+++ pure/trunk/pure.1.in 2008-09-05 22:57:51 UTC (rev 721)
@@ -1813,6 +1813,86 @@
[1,2,6,24,120,720,5040,40320,362880,3628800]
.fi
.PP
+.B Print syntax.
+As indicated, in interactive mode the normal forms of toplevel expressions are
+printed after each expression is entered. We also call this the
+.I read-eval-print
+loop. Normal form expressions are usually printed in the same form as you'd
+enter them. However, there are a few special kinds of objects like closures
+(anonymous and local functions), thunks (``lazy'' values to be evaluated when
+needed) and pointers which don't have a textual representation in the Pure
+syntax and will be printed in the format
+.BR "#<\fIobject description\fP>" .
+.PP
+The interpreter provides a ``hook'' to override the print representations of
+expressions at runtime by means of the
+.B __show__
+function. This is just an ordinary Pure function expected to return a string
+with the desired custom representation of a normal form value given as the
+function's single argument. __show__ is not defined by default, so you are
+free to add any rules that you want. The interpreter prints the strings
+returned by __show__ just as they are. It will
+.I not
+check whether they conform to Pure syntax and/or semantics, or modify them in
+any way.
+.PP
+Custom print representations are most useful for interactive purposes, when
+you're not happy with the default print syntax of some kinds of objects, or if
+you just want to change the format of numeric values. Here are some examples:
+.sp
+.nf
+> \fBusing\fP system;
+> __show__ x::double = sprintf "%0.6f" x;
+> 1/7;
+0.142857
+> __show__ x::int = sprintf "0x%0x" x;
+> 1786;
+0x6fa
+> \fBusing\fP math;
+> __show__ (x::double+:y::double) = sprintf "%0.6f+%0.6fi" (x,y);
+> cis (-pi);
+-1.000000+0.000000i
+.fi
+.PP
+The prelude function
+.BR str ,
+which returns the print representation of any Pure expression, uses __show__
+as well:
+.sp
+.nf
+> str (1/7);
+"0.142857"
+.fi
+.PP
+However, the str function always returns just the default representation of an
+expression if it is invoked through __show__. This prevents __show__ from
+going recursive, and allows you to define your custom representation in terms
+of the default one. E.g., the following rule removes the `L' suffixes from
+bigint values:
+.sp
+.nf
+> __show__ x::bigint = init (str x);
+> fact n = foldl (*) 1L (1..n);
+> fact 30;
+265252859812191058636308480000000
+.fi
+.PP
+By just purging the definition of the __show__ function you can easily go back
+to the standard print syntax:
+.sp
+.nf
+> \fBclear\fP __show__
+> 1/7; 1786; cis (-pi);
+0.142857142857143
+1786
+-1.0+:1.22460635382238e-16
+> str (1/7);
+"0.142857142857143"
+> fact 30;
+265252859812191058636308480000000L
+.fi
+.PP
+.B Interactive commands.
When running interactively, the interpreter also accepts a number of special
commands useful for interactive purposes. Here is a quick rundown of the
currently supported operations:
@@ -1899,9 +1979,9 @@
Note that these special commands are only recognized at the beginning of the
interactive command line (they are not reserved keywords of the Pure
language). Thus it's possible to ``escape'' identifiers looking like commands
-by entering a space at the start of the line. However, the compiler also warns
-you about identifiers which might be mistaken as command names, so that you
-can avoid this kind of problem.
+by entering a space at the beginning of the line. However, the compiler also
+warns you about identifiers which might be mistaken as command names, so that
+you can avoid this kind of problem.
.PP
Some commands which are especially important for effective operation of the
interpreter are discussed in more detail in the following sections.
@@ -2273,11 +2353,11 @@
and
.B when
clauses are tacked on to the end of the expression they belong to, which
-mimics mathematical notation but may be unfamilar if you're more accustomed to
-languages from the Algol/Pascal/C family. If you want to figure out what is
-actually going on there, it's usually best to read nested scopes ``in
-reverse'' (proceeding from the rightmost/outermost to the leftmost/innermost
-clause).
+mimics mathematical language but may be unfamilar if you're more accustomed to
+programming languages from the Algol/Pascal/C family. If you want to figure
+out what is actually going on there, it's usually best to read nested scopes
+``in reverse'' (proceeding from the rightmost/outermost to the
+leftmost/innermost clause).
.PP
Also note that since
.B with
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ag...@us...> - 2008-09-06 07:15:16
|
Revision: 723
http://pure-lang.svn.sourceforge.net/pure-lang/?rev=723&view=rev
Author: agraef
Date: 2008-09-06 07:15:26 +0000 (Sat, 06 Sep 2008)
Log Message:
-----------
Reformatting.
Modified Paths:
--------------
pure/trunk/pure.1.in
Modified: pure/trunk/pure.1.in
===================================================================
--- pure/trunk/pure.1.in 2008-09-05 22:58:16 UTC (rev 722)
+++ pure/trunk/pure.1.in 2008-09-06 07:15:26 UTC (rev 723)
@@ -224,9 +224,12 @@
Unix-like systems this allows you to add a ``shebang'' to your main script in
order to turn it into an executable program.
.PP
-There are a few reserved keywords which cannot be used as identifiers. These
-are: case const def else end extern if infix infixl infixr let nullary of
-otherwise postfix prefix private then using when with.
+There are a few reserved keywords which cannot be used as identifiers:
+.if t .PP
+.if t .RS
+case const def else end extern if infix infixl infixr let nullary of
+otherwise postfix prefix private then using when with
+.if t .RE
.PP
Pure is a terse language. You won't see many declarations, and often your
programs will read more like a collection of algebraic specifications (which
@@ -307,11 +310,10 @@
.B false
and any non-zero value
.BR true ).
-.PP
-.B Expression syntax.
+.SS Expression Syntax
Expressions consist of the following elements:
.TP
-.B Constants: \fR4711, 4711L, 1.2e-3, \(dqHello,\ world!\en\(dq
+\fBConstants:\fP 4711, 4711L, 1.2e-3, \(dqHello,\ world!\en\(dq
The usual C'ish notations for integers (decimal, hexadecimal, octal), floating
point values and double-quoted strings are all provided, although the Pure
syntax differs in some minor ways, as discussed in the following. First, there
@@ -344,7 +346,7 @@
Thus, e.g., \(dq\e©\(dq denotes the copyright character (code point
0x000A9).
.TP
-.B Function and variable symbols: \fRfoo, foo_bar, BAR, bar2
+\fBFunction and variable symbols:\fP foo, foo_bar, BAR, bar2
These consist of the usual sequence of ASCII letters (including the
underscore) and digits, starting with a letter. The `_' symbol, when occurring
on the left-hand side of an equation, is special; it denotes the
@@ -360,7 +362,7 @@
.B nullary
symbols, see below).
.TP
-.B Operator and constant symbols: \fRx+y, x==y, \fBnot\fP\ x, []
+\fBOperator and constant symbols:\fP x+y, x==y, \fBnot\fP\ x, []
As indicated, these take the form of an identifier or a sequence of
punctuation symbols. As of Pure 0.6, operator and constant symbols may also
contain arbitrary extended (non-ASCII) Unicode characters, which makes it
@@ -380,7 +382,7 @@
left-hand side of an equation, it is to be interpreted as a constant rather
than a variable (see above).
.TP
-.B Lists and tuples: \fR[x,y,z], x..y, x:xs, x,y,z
+\fBLists and tuples:\fP [x,y,z], x..y, x:xs, x,y,z
The necessary constructors to build lists and tuples are actually defined in
the prelude: `[]' and `()' are the empty list and tuple, `:' produces list
``conses'', and `,' produces ``pairs''. As indicated, Pure provides the usual
@@ -402,7 +404,7 @@
tuple 1,2, the integer 3, and another tuple 4,5. Likewise, [(1,2,3)] is list
with a single element, the tuple 1,2,3.
.TP
-.B List comprehensions: \fR[x,y; x = 1..n; y = 1..m; x<y]
+\fBList comprehensions:\fP [x,y; x = 1..n; y = 1..m; x<y]
Pure also has list comprehensions which generate lists from an expression and
one or more ``generator'' and ``filter'' clauses (the former bind a pattern to
values drawn from a list, the latter are just predicates determining which
@@ -413,26 +415,26 @@
prelude), but they are often much easier to write. Some examples of list
comprehensions can be found in the EXAMPLES section below.
.TP
-.B Function applications: \fRfoo\ x\ y\ z
+\fBFunction applications:\fP foo x y z
As in other modern FPLs, these are written simply as juxtaposition (i.e., in
``curried'' form) and associate to the left. Operator applications are written
using prefix, postfix or infix notation, as the declaration of the operator
demands, but are just ordinary function applications in disguise. E.g., x+y is
exactly the same as (+) x y.
.TP
-.B Conditional expressions: if\fR\ x\ \fBthen\fR\ y\ \fBelse\fR\ z
+\fBConditional expressions:\fP \fBif\fP x \fBthen\fP y \fBelse\fP z
Evaluates to y or z depending on whether x is ``true'' (i.e., a nonzero
integer). An exception is generated if the condition is not an
integer.
.TP
-.B Lambdas: \fR\ex\ ->\ y
+\fBLambdas:\fP \ex\ ->\ y
These work pretty much like in Haskell. More than one variable may be bound
(e.g, \ex\ y\ ->\ x*y), which is equivalent to a nested lambda
(\ex\ ->\ \ey\ ->\ x*y). Pure also fully supports pattern-matching lambda
abstractions which match a pattern against the lambda argument and bind
multiple lambda variables in one go, such as \e(x,y)\ ->\ x*y.
.TP
-.B Case expressions: case\fR\ x\ \fBof\fR\ \fIrule\fR;\ ...\ \fBend
+\fBCase expressions:\fP \fBcase\fP x \fBof\fP \fIrule\fP; ... \fBend\fP
Matches an expression, discriminating over a number of different cases,
similar to the Haskell \fBcase\fP construct. The expression x is matched in
turn against each left-hand side pattern in the rule list, and the first
@@ -440,7 +442,7 @@
evaluating the corresponding right-hand side with the variables in the pattern
bound to their corresponding values.
.TP
-.B When expressions: \fRx\ \fBwhen\fR\ \fIrule\fR;\ ...\ \fBend
+\fBWhen expressions:\fP x \fBwhen\fP \fIrule\fR; ... \fBend\fP
An alternative way to bind local variables by matching a collection of subject
terms against corresponding patterns. Similar to Aardappel's \fBwhen\fP
construct. A single binding such as x \fBwhen\fP u = v \fBend\fP is equivalent
@@ -452,14 +454,13 @@
like several nested \fBwhen\fP expressions, with the first binding being the
``outermost'' one.
.TP
-.B With expressions: \fRx\ \fBwith\fR\ \fIrule\fR;\ ...\ \fBend\fR
+\fBWith expressions:\fP x \fBwith\fP \fIrule\fR; ... \fBend\fP
Defines local functions. Like Haskell's \fBwhere\fP construct, but it can be
used anywhere inside an expression (just like Aardappel's \fBwhere\fP, but
Pure uses the keyword \fBwith\fP which better lines up with \fBcase\fP and
\fBwhen\fP). Several functions can be defined in a single \fBwith\fP clause,
and the definitions may consist of as many equations as you want.
-.PP
-.B Operators and precedence.
+.SS Operators and Precedence
Expressions are parsed according to the following precedence rules: Lambda
binds most weakly, followed by
.BR when ,
@@ -492,8 +493,7 @@
and
.B or
instead of `&' and `|', which are used for other purposes in Pure.
-.PP
-.B Special forms.
+.SS Special Forms
As already mentioned, some operators are actually implemented as special
forms. In particular, the conditional expression \fBif\fP x \fBthen\fP y
\fBelse\fP z is a special form with call-by-name arguments y and z; only one
@@ -540,13 +540,12 @@
infinite. The Pure prelude defines many functions for creating and
manipulating these kinds of objects; further details and examples can be found
in the EXAMPLES section below.
-.PP
-.B Toplevel.
+.SS Toplevel
At the toplevel, a Pure program basically consists of rewriting rules (which
are used to define functions and macros), constant and variable definitions,
and expressions to be evaluated:
.TP
-.B Rules: \fIlhs\fR = \fIrhs\fR;
+\fBRules:\fP \fIlhs\fP = \fIrhs\fP;
These rules always combine a left-hand side
.I pattern
(which must be a simple expression) and a right-hand side (which can be any
@@ -561,7 +560,7 @@
out common left-hand or right-hand sides in collections of rules; see section
RULE SYNTAX below for details.
.TP
-.B Macro rules: def\fR \fIlhs\fR = \fIrhs\fR;
+\fBMacro rules:\fP \fBdef\fP \fIlhs\fP = \fIrhs\fP;
A rule starting with the keyword
.B def
defines a
@@ -572,13 +571,13 @@
user-defined special forms and simple kinds of optimization rules. See the
MACROS section below for details and examples.
.TP
-.B Global variable bindings: let\fR \fIlhs\fR = \fIrhs\fR;
+\fBGlobal variable bindings:\fP \fBlet\fP \fIlhs\fP = \fIrhs\fP;
Binds every variable in the left-hand side pattern to the corresponding
subterm of the right-hand side (after evaluating it). This works like a
\fBwhen\fP clause, but serves to bind \fIglobal\fP variables occurring free on
the right-hand side of other function and variable definitions.
.TP
-.B Constant bindings: const\fR \fIlhs\fR = \fIrhs\fR;
+\fBConstant bindings:\fP \fBconst\fP \fIlhs\fP = \fIrhs\fP;
An alternative form of \fBlet\fP which defines constants rather than
variables. (These are not to be confused with
.B nullary
@@ -590,12 +589,11 @@
directly into the right-hand sides of other definitions, rather than being
looked up at runtime.
.TP
-.B Toplevel expressions: \fIexpr\fR;
+\fBToplevel expressions:\fP \fIexpr\fP;
A singleton expression at the toplevel, terminated with a semicolon, simply
causes the given value to be evaluated (and the result to be printed, when
running in interactive mode).
-.PP
-.B Scoping rules.
+.SS Scoping Rules
A few remarks about the scope of identifiers and other symbols are in order
here. Like most modern functional languages, Pure uses
.I lexical
@@ -743,9 +741,10 @@
> foo 1;
6.28318530717958
.fi
-.PP
-.B List comprehensions.
-Erathosthenes' classical prime sieve:
+.SS List Comprehensions
+List comprehensions are Pure's main workhorse for generating and processing
+all kinds of list values. Here's a well-known example, Erathosthenes'
+classical prime sieve:
.sp
.nf
primes n = sieve (2..n) \fBwith\fP
@@ -785,8 +784,7 @@
= i1==i2 || j1==j2 || i1+j1==i2+j2 || i1-j1==i2-j2;
\fBend\fP;
.fi
-.PP
-.B Lazy evaluation and streams.
+.SS Lazy Evaluation and Streams
As already mentioned, lists can also be evaluated in a ``lazy'' fashion, by
just turning the tail of a list into a
.IR future .
@@ -832,6 +830,9 @@
[0L,1L,1L,2L,3L,5L,8L,13L,21L,34L]
.fi
.PP
+(Conversely, you can also turn a list into a stream value with the `stream'
+function.)
+.PP
For interactive usage it's often convenient to define an eager variation of
`take' which combines `take' and `list'. Let's do this now, so that we can use
this operation in the following examples.
@@ -1143,8 +1144,7 @@
will be expanded using the leftmost-innermost reduction strategy (i.e., macro
calls in macro arguments are expanded before the macro gets applied to its
parameters).
-.PP
-.B Optimization rules.
+.SS Optimization Rules
Here is a simple example, showing a rule which expands saturated calls of the
.B succ
function (defined in the prelude) at compile time:
@@ -1239,8 +1239,7 @@
of a macro definition must be a simple expression, and thus it's not possible
to write a macro which descends recursively into the lambda argument of
`catmap'.)
-.PP
-.B Recursive macros.
+.SS Recursive Macros
Macros can also be recursive, in which case they usually consist of multiple
rules and make use of pattern-matching like ordinary function
definitions. Example:
@@ -1261,8 +1260,7 @@
with these by setting the
.B PURE_STACK
environment variable.
-.PP
-.B Convenience macros.
+.SS Convenience Macros
The following `timex' macro provides an example of how you can use macros to
define your own special forms. This is made possible by the fact that the
macro arguments will only be evaluated at runtime and can thus be passed to
@@ -1289,8 +1287,7 @@
function definition, since by virtue of Pure's basic eager evaluation strategy
the x parameter would have been evaluated already before it is passed to
`timex', making `timex' always return a zero time value. Try it.)
-.PP
-.B Macro hygiene.
+.SS Macro Hygiene
Pure macros are lexically scoped, i.e., symbols on the right-hand-side of a
macro definition can never refer to anything outside the macro definition, and
macro parameter substitution also takes into account binding constructs, such
@@ -1325,7 +1322,7 @@
.B using
clauses which let you include other scripts in a Pure script.
.TP
-.B Private symbol declarations: private \fIsymbol\fP\fR ...;\fP
+\fBPrivate symbol declarations:\fP \fBprivate\fP \fIsymbol\fP ...;
Declares the listed symbols as
.IR private .
Pure programs usually consist of several source scripts (see the description
@@ -1346,7 +1343,7 @@
them all with whitespace in between. The same applies to the other types of
symbol declarations discussed below.
.TP
-.B Operator declarations: infix \fIlevel\fP \fIop\fP\fR ...;\fP
+\fBOperator declarations:\fP \fBinfix\fP \fIlevel op\fP ...;
These may also be prefixed with the keyword
.B private
to indicate a private operator symbol (see above).
@@ -1375,7 +1372,7 @@
minus operator; the unary minus operation can be denoted using the built-in
`neg' function.
.TP
-.B Constant symbol declarations: nullary \fIsymbol\fP\fR ...;\fP
+\fBConstant symbol declarations:\fP \fBnullary\fP \fIsymbol\fP ...;
Constant symbols are introduced using a
.B nullary
declaration (again, a
@@ -1397,7 +1394,7 @@
symbols as well as the list and pair constructors `:' and `,' and the empty
list and tuple constants `[]' and `()'.
.TP
-.B Using clause: using \fIname\fR, ...;
+\fBUsing clause:\fP \fBusing\fP \fIname\fP, ...;
Causes each given script to be included in the Pure program. Each included
script is loaded only
.IR once ,
@@ -1410,7 +1407,7 @@
.B using
clause also has an alternative form which allows dynamic libraries to be
loaded, this will be discussed in the C INTERFACE section.
-.PP
+.SS The `using' Declaration
The
.B using
declaration provides a simple but effective way to assemble a Pure program
@@ -1580,9 +1577,11 @@
returns the first solution. Note the use of
.B throw
in the recursive search routine to bail out with a solution as soon as we
-found one. The value thrown there is caught in the main routine. If no value
-gets thrown, the function regularly returns with () to indicate that there is
-no solution.
+found one. The value thrown there is caught in the main routine. Also note the
+use of `void' in the second equation of `search'. This effectively turns the
+list comprehension into a simple loop which suppresses the normal list result
+and just returns () instead. Thus, if no value gets thrown then the function
+regularly returns with () to indicate that there is no solution.
.sp
.nf
queens1 n = catch reverse (search n 1 []) \fBwith\fP
@@ -1812,8 +1811,7 @@
> map fact (1..10);
[1,2,6,24,120,720,5040,40320,362880,3628800]
.fi
-.PP
-.B Print syntax.
+.SS Print Syntax
As indicated, in interactive mode the normal forms of toplevel expressions are
printed after each expression is entered. We also call this the
.I read-eval-print
@@ -1891,19 +1889,18 @@
> fact 30;
265252859812191058636308480000000L
.fi
-.PP
-.B Interactive commands.
+.SS Interactive Commands
When running interactively, the interpreter also accepts a number of special
commands useful for interactive purposes. Here is a quick rundown of the
currently supported operations:
.TP
-.B "! \fIcommand\fP"
+\fB!\fP \fIcommand\fP
Shell escape.
.TP
-.B "cd \fIdir\fP"
+\fBcd\fP \fIdir\fP
Change the current working dir.
.TP
-.B "clear \fR[\fIsymbol\fP ...]\fP"
+\fBclear\fP [\fIsymbol\fP ...]
Purge the definitions of the given symbols (functions, macros, constants or
global variables). If no symbols are given, purge \fIall\fP definitions (after
confirmation) made after the most recent
@@ -1912,14 +1909,14 @@
idea to first check your current definitions with \fBlist -t\fP before you do
this, though.) See the DEFINITION LEVELS section below for details.
.TP
-.B "help \fR[\fIargs\fP]\fP"
+\fBhelp\fP [\fIargs\fP]
Display the
.BR pure (1)
manpage, or invoke
.BR man (1)
with the given arguments.
.TP
-.B "ls \fR[\fIargs\fP]\fP"
+\fBls\fP [\fIargs\fP]
List files (shell \fBls\fP(1) command).
.TP
.B override
@@ -1933,17 +1930,16 @@
.B quit
Exits the interpreter.
.TP
-.B "run \fIscript\fP"
+\fBrun\fP \fIscript\fP
Loads the given script file and adds its definitions to the current
environment. This works more or less like a
.B using
clause, but only searches for the script in the current directory and loads
-the script ``anonymously'', as if the contents of the script had been typed at
-the command prompt. That is,
+the script ``anonymously.'' That is,
.B run
-will just put the definitions into the current namespace, giving you access to
-all private symbols of the script. Also, the definitions are placed at the
-current temporary level, so that
+puts the definitions into the current namespace, giving you access to all
+private symbols of the script. Also, the definitions are placed at the current
+temporary level, so that
.B clear
can be used to remove them again. In particular, this makes it possible to
quickly reload a script without exiting the interpreter, by issuing the
@@ -1961,11 +1957,11 @@
(or the beginning of the interactive session). See the DEFINITION LEVELS
section below for details.
.TP
-.B "show \fR[\fIoption\fP ...]\fP \fR[\fIsymbol\fP ...]\fP"
+\fBshow\fP [\fIoption\fP ...] [\fIsymbol\fP ...]
Show the definitions of symbols in various formats. See the SHOW COMMAND
section below for details.
.TP
-.B "stats \fR[on|off]\fP"
+\fBstats\fP [on|off]
Enables (default) or disables ``stats'' mode, in which various statistics are
printed after an expression has been evaluated. Currently, this just prints
the cpu time in seconds for each evaluation, but in the future additional
@@ -2029,7 +2025,7 @@
.B -m
Print information about defined macros.
.TP
-.B -p[\fIflag\fP]
+\fB-p\fP[\fIflag\fP]
List only private symbols in the current module if \fIflag\fP is nonzero (the
default), otherwise (\fIflag\fP is zero) list only public symbols of all
modules. List both private and public symbols if -p is omitted. The
@@ -2038,7 +2034,7 @@
.B -s
Summary format, print just summary information about listed symbols.
.TP
-.B -t[\fIlevel\fP]
+\fB-t\fP[\fIlevel\fP]
List only ``temporary'' symbols and definitions at the given \fIlevel\fP (the
current level by default) or above. The \fIlevel\fP parameter, if given, must
immediately follow the option character. A \fIlevel\fP of 1 denotes all
@@ -2222,8 +2218,7 @@
This section is a grab bag of casual remarks, useful tips and tricks, and
information on common pitfalls, quirks and limitations of the current
implementation and how to deal with them.
-.PP
-.B Purity.
+.SS Purity
People keep asking me what's so ``pure'' about Pure. The long and apologetic
answer is that at its core, Pure is in fact purely algebraic and purely
functional. Pure doesn't get in your way if you want to call external
@@ -2236,15 +2231,13 @@
The short answer is that I simply liked the name, and there wasn't any
programming language named ``Pure'' yet (quite a feat nowadays), so there's
one now. :)
-.PP
-.B Debugging.
+.SS Debugging
There's no symbolic debugger yet. So
.BR printf (3)
(available in the
.B system
standard library module) should be your friend. ;-)
-.PP
-.B ``As'' patterns.
+.SS ``As'' Patterns
In the current implementation, ``as'' patterns cannot be placed on the
``spine'' of a function definition. Thus rules like the following, which have
the pattern somewhere in the head of the left-hand side, will all provoke an
@@ -2265,8 +2258,7 @@
> \fBcase\fP bar 99 \fBof\fP y@(bar x) = y,x+1; \fBend\fP;
bar 99,100
.fi
-.PP
-.B Head = function.
+.SS Head = Function
``As'' patterns are also a useful device if you need to manipulate function
applications in a generic way. Note that the ``head = function'' rule means
that the head symbol f of an application f x1 ... xn occurring on (or inside)
@@ -2333,8 +2325,7 @@
> foop foo, foop 99;
1,0
.fi
-.PP
-.B With or when?
+.SS With or when?
A common source of confusion for Haskellers is that Pure provides two
different constructs to bind local function and variable symbols,
respectively. This distinction is necessary because Pure does not segregate
@@ -2368,8 +2359,7 @@
around this with conditional and
.B case
expressions, though.
-.PP
-.B Numeric calculations.
+.SS Numeric Calculations
If possible, you should decorate numeric variables on the left-hand sides of
function definitions with the appropriate type tags, like
.B ::int
@@ -2402,8 +2392,7 @@
against constant values of these types; in particular, a small integer
constant like `0' only matches machine integers, not bigints; for the latter
you'll have to use the ``big L'' notation `0L'.
-.PP
-.B Constant definitions.
+.SS Constant Definitions
When definining a function in terms of constant values which have to be
computed beforehand, it's usually better to use a
.B const
@@ -2490,8 +2479,7 @@
to redefine it as a constant, or vice versa, since Pure won't let you redefine
an existing constant or variable as a different kind of symbol. The same also
holds if a symbol is currently defined as a function or a macro.)
-.PP
-.B External C functions.
+.SS External C Functions
The interpreter always takes your
.B extern
declarations of C routines at face value. It will not go and read any C header
@@ -2507,16 +2495,14 @@
Therefore it is highly recommended that you wrap your lowlevel code in Pure
routines and data structures which do all the checks necessary to ensure that
only the right kind of data is passed to C routines.
-.PP
-.B Special forms.
+.SS Special Forms
Special forms are recognized at compile time only. Thus the catch function as
well as the logical connectives && and ||, the sequencing operator $$ and the
lazy evaluation operator & are only treated as special forms in direct
(saturated) calls. They can still be used if you pass them around as function
values or partial applications, but in this case they lose all their special
call-by-name argument processing.
-.PP
-.B Laziness.
+.SS Laziness
Pure does lazy evaluation in the same way as Alice ML, providing an explicit
operation (&) to defer evaluation and create a ``future'' which is called by
need. However, note that like any language with a basically eager evaluation
@@ -2552,8 +2538,7 @@
need something like Haskell's irrefutable matches, you'll have to code them
explicitly using futures. See the definition of the `unzip' function in the
prelude for an example showing how to do this.
-.PP
-.B Stack size and tail recursion.
+.SS Stack Size and Tail Recursion
Pure programs may need a considerable amount of stack space to handle
recursive function calls, and the interpreter itself also takes its toll. So
you may have to configure your system accordingly (8 MB of stack space is
@@ -2604,8 +2589,7 @@
can be changed at any time during an interactive session, without having to
recompile the entire program.) However, mutual tail recursion does work with
\fIlocal\fP functions, so it's easy to work around this limitation.
-.PP
-.B Handling of asynchronous signals.
+.SS Handling of Asynchronous Signals
As described in section EXCEPTION HANDLING, signals delivered to the process
can be caught and handled with Pure's exception handling facilities. Like
stack checks, checks for pending signals are only performed at certain places,
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ag...@us...> - 2008-09-06 07:38:51
|
Revision: 724
http://pure-lang.svn.sourceforge.net/pure-lang/?rev=724&view=rev
Author: agraef
Date: 2008-09-06 07:39:02 +0000 (Sat, 06 Sep 2008)
Log Message:
-----------
Fix typos and formatting glitches.
Modified Paths:
--------------
pure/trunk/pure.1.in
Modified: pure/trunk/pure.1.in
===================================================================
--- pure/trunk/pure.1.in 2008-09-06 07:15:26 UTC (rev 723)
+++ pure/trunk/pure.1.in 2008-09-06 07:39:02 UTC (rev 724)
@@ -225,11 +225,8 @@
order to turn it into an executable program.
.PP
There are a few reserved keywords which cannot be used as identifiers:
-.if t .PP
-.if t .RS
case const def else end extern if infix infixl infixr let nullary of
-otherwise postfix prefix private then using when with
-.if t .RE
+otherwise postfix prefix private then using when with.
.PP
Pure is a terse language. You won't see many declarations, and often your
programs will read more like a collection of algebraic specifications (which
@@ -912,7 +909,7 @@
0L:1L:1L:2L:3L:5L:8L:13L:21L:34L:#<thunk 0xb4ce5d30>
.fi
.PP
-As you can see, the invokation of our `takel' function forced the
+As you can see, the invocation of our `takel' function forced the
corresponding prefix of the `fibs' stream to be computed. The result of the
evaluation is memoized, so that this portion of the stream is now readily
available in case we need to have another look at it later. By these means,
@@ -1820,7 +1817,7 @@
(anonymous and local functions), thunks (``lazy'' values to be evaluated when
needed) and pointers which don't have a textual representation in the Pure
syntax and will be printed in the format
-.BR "#<\fIobject description\fP>" .
+\fB#<\fP\fIobject description\fP\fB>\fP.
.PP
The interpreter provides a ``hook'' to override the print representations of
expressions at runtime by means of the
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ag...@us...> - 2008-09-06 09:20:29
|
Revision: 727
http://pure-lang.svn.sourceforge.net/pure-lang/?rev=727&view=rev
Author: agraef
Date: 2008-09-06 09:20:39 +0000 (Sat, 06 Sep 2008)
Log Message:
-----------
Update documentation.
Modified Paths:
--------------
pure/trunk/pure.1.in
Modified: pure/trunk/pure.1.in
===================================================================
--- pure/trunk/pure.1.in 2008-09-06 08:49:07 UTC (rev 726)
+++ pure/trunk/pure.1.in 2008-09-06 09:20:39 UTC (rev 727)
@@ -7,7 +7,7 @@
\fBpure\fP [\fIoptions\fP ...] -x \fIscript\fP [\fIargs\fP ...]
.SH OPTIONS
.TP
-.B -h
+\fB--help\fP, \fB-h\fP
Print help message and exit.
.TP
.B -i
@@ -19,15 +19,24 @@
.BI -L directory
Add a directory to be searched for dynamic libraries.
.TP
-.B -n
-Suppress automatic inclusion of the prelude.
+.B --noediting
+Do not use readline for command-line editing.
.TP
+\fB--noprelude\fP, \fB-n\fP
+Do not load the prelude.
+.TP
+.B --norc
+Do not run the interactive startup files.
+.TP
.B -q
Quiet startup (suppresses sign-on message in interactive mode).
.TP
.BR -v [\fIlevel\fP]
Set verbosity level. See below for details.
.TP
+.B --version
+Print version information and exit.
+.TP
.B -x
Execute script with given command line arguments.
.TP
@@ -70,12 +79,27 @@
command or the end-of-file character (^D on Unix) at the beginning of the
command line.
.PP
-When the interpreter is in interactive mode and reads from a tty, commands are
-read using
+Unless the
+.B --norc
+option is specified, in interactive mode the interpreter automatically loads
+some additional startup files if they are present; first
+.B .purerc
+in the user's home directory (provided that the
+.B HOME
+environment variable is set accordingly), then
+.B .purerc
+in the current working directory. These are ordinary Pure scripts which can be
+used to provide additional definitions for interactive usage. See the
+INTERACTIVE USAGE section for details.
+.PP
+Unless the
+.B --noediting
+option is specified, when the interpreter is in interactive mode and reads
+from a tty, commands are read using
.BR readline (3)
(providing completion for all commands listed under INTERACTIVE USAGE, as well
-as for symbols defined in the running program) and, when exiting the
-interpreter, the command history is stored in
+as for symbols defined in the running program). When exiting the interpreter,
+the command history is stored in
.BR ~/.pure_history ,
from where it is restored the next time you run the interpreter.
.PP
@@ -1784,7 +1808,8 @@
last script specified on the command line determines the visible namespace
(i.e., all public symbols are visible, along with the private symbols of the
loaded script). Otherwise only the public symbols defined in the prelude are
-available. Additional scripts can be loaded interactively using either a
+available, as well as the (public or private) definitions in the startup files
+(see below). Additional scripts can be loaded interactively using either a
.B using
declaration or the interactive
.B run
@@ -1872,6 +1897,10 @@
265252859812191058636308480000000
.fi
.PP
+If you have a set of definitions for the __show__ function which should always
+be loaded at startup, you can put them into the interpreter's interactive
+startup files, see below.
+.PP
By just purging the definition of the __show__ function you can easily go back
to the standard print syntax:
.sp
@@ -1886,6 +1915,27 @@
> fact 30;
265252859812191058636308480000000L
.fi
+.SS Startup Files
+When running the interpreter interactively, it loads some additional scripts
+at startup, after loading the prelude. The interpreter first looks for a
+.B .purerc
+file in the user's home directory (as given by the
+.B HOME
+environment variable) and then for a
+.B .purerc
+file in the current working directory. These are just ordinary Pure scripts
+which may contain any additional definitions that you need. The
+.B .purerc
+file in the home directory is for global definitions which should always be
+available when running interactively, while the
+.B .purerc
+file in the current directory can be used for project-specific definitions.
+.PP
+The interpreter loads these files in the same way as with the
+.B run
+command (see below). When invoking the interpreter, you can specify the
+.B --norc
+option on the command line if you do not wish to load these files.
.SS Interactive Commands
When running interactively, the interpreter also accepts a number of special
commands useful for interactive purposes. Here is a quick rundown of the
@@ -2628,6 +2678,9 @@
.B ~/.pure_history
Interactive command history.
.TP
+\fB~/.purerc\fP, \fB.purerc\fP
+Interactive startup files.
+.TP
.B prelude.pure
Standard prelude. If available, this script is loaded before any other
definitions, unless
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ag...@us...> - 2008-09-06 15:00:25
|
Revision: 728
http://pure-lang.svn.sourceforge.net/pure-lang/?rev=728&view=rev
Author: agraef
Date: 2008-09-06 15:00:35 +0000 (Sat, 06 Sep 2008)
Log Message:
-----------
Update documentation.
Modified Paths:
--------------
pure/trunk/pure.1.in
Modified: pure/trunk/pure.1.in
===================================================================
--- pure/trunk/pure.1.in 2008-09-06 09:20:39 UTC (rev 727)
+++ pure/trunk/pure.1.in 2008-09-06 15:00:35 UTC (rev 728)
@@ -1931,7 +1931,7 @@
.B .purerc
file in the current directory can be used for project-specific definitions.
.PP
-The interpreter loads these files in the same way as with the
+The interpreter processes these files in the same way as with the
.B run
command (see below). When invoking the interpreter, you can specify the
.B --norc
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ag...@us...> - 2008-09-06 19:28:42
|
Revision: 734
http://pure-lang.svn.sourceforge.net/pure-lang/?rev=734&view=rev
Author: agraef
Date: 2008-09-06 19:28:53 +0000 (Sat, 06 Sep 2008)
Log Message:
-----------
Update documentation.
Modified Paths:
--------------
pure/trunk/pure.1.in
Modified: pure/trunk/pure.1.in
===================================================================
--- pure/trunk/pure.1.in 2008-09-06 18:19:20 UTC (rev 733)
+++ pure/trunk/pure.1.in 2008-09-06 19:28:53 UTC (rev 734)
@@ -89,8 +89,11 @@
environment variable is set accordingly), then
.B .purerc
in the current working directory. These are ordinary Pure scripts which can be
-used to provide additional definitions for interactive usage. See the
-INTERACTIVE USAGE section for details.
+used to provide additional definitions for interactive usage. Finally, a
+.B .pure
+file in the current directory (containing a dump from a previous interactive
+session) is loaded if it is present. See the INTERACTIVE USAGE section for
+details.
.PP
Unless the
.B --noediting
@@ -1929,7 +1932,14 @@
file in the home directory is for global definitions which should always be
available when running interactively, while the
.B .purerc
-file in the current directory can be used for project-specific definitions.
+file in the current directory can be used for project-specific
+definitions. There can be yet another
+.B .pure
+initialization file in the current directory, which is created by the
+.B dump
+command (see below) and is loaded after the
+.B .purerc
+files if it is present.
.PP
The interpreter processes these files in the same way as with the
.B run
@@ -1956,6 +1966,40 @@
idea to first check your current definitions with \fBlist -t\fP before you do
this, though.) See the DEFINITION LEVELS section below for details.
.TP
+\fBdump\fP [\fIoption\fP ...] [\fIsymbol\fP ...]
+Dump function, macro, variable and constant definitions to a file. This works
+similar to the
+.B show
+command (see below and the SHOW COMMAND section), but writes the definitions
+to a file. This command only supports a subset of the
+.B show
+options, type
+.B dump -h
+for a description of these.
+.sp
+By default, all definitions made interactively are written to a file named
+.B .pure
+in the current directory, which is then reloaded automatically the next time
+the interpreter starts up in interactive mode in the same directory. This
+provides a quick-and-dirty means to save an interactive session and have it
+restored later. (Please note that this isn't perfect yet, because variable
+values containing special objects such as thunks and pointers can't be
+reconstructed, and
+.B using
+or
+.B extern
+declarations are not recorded at all. For those you'll have to manually create
+a
+.B .purerc
+file instead.)
+.sp
+A different filename can be specified with the
+.B -F
+option. You can then edit that file and use it as a starting point for an
+ordinary script or a
+.B purerc
+file.
+.TP
\fBhelp\fP [\fIargs\fP]
Display the
.BR pure (1)
@@ -2678,8 +2722,9 @@
.B ~/.pure_history
Interactive command history.
.TP
-\fB~/.purerc\fP, \fB.purerc\fP
-Interactive startup files.
+\fB~/.purerc\fP, \fB.purerc\fP, \fB.pure\fP
+Interactive startup files. The latter is usually a dump from a previous
+interactive session.
.TP
.B prelude.pure
Standard prelude. If available, this script is loaded before any other
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ag...@us...> - 2008-09-07 06:54:51
|
Revision: 737
http://pure-lang.svn.sourceforge.net/pure-lang/?rev=737&view=rev
Author: agraef
Date: 2008-09-07 06:55:01 +0000 (Sun, 07 Sep 2008)
Log Message:
-----------
Update documentation.
Modified Paths:
--------------
pure/trunk/pure.1.in
Modified: pure/trunk/pure.1.in
===================================================================
--- pure/trunk/pure.1.in 2008-09-06 19:47:35 UTC (rev 736)
+++ pure/trunk/pure.1.in 2008-09-07 06:55:01 UTC (rev 737)
@@ -79,33 +79,6 @@
command or the end-of-file character (^D on Unix) at the beginning of the
command line.
.PP
-Unless the
-.B --norc
-option is specified, in interactive mode the interpreter automatically loads
-some additional startup files if they are present; first
-.B .purerc
-in the user's home directory (provided that the
-.B HOME
-environment variable is set accordingly), then
-.B .purerc
-in the current working directory. These are ordinary Pure scripts which can be
-used to provide additional definitions for interactive usage. Finally, a
-.B .pure
-file in the current directory (containing a dump from a previous interactive
-session) is loaded if it is present. See the INTERACTIVE USAGE section for
-details.
-.PP
-Unless the
-.B --noediting
-option is specified, when the interpreter is in interactive mode and reads
-from a tty, commands are read using
-.BR readline (3)
-(providing completion for all commands listed under INTERACTIVE USAGE, as well
-as for symbols defined in the running program). When exiting the interpreter,
-the command history is stored in
-.BR ~/.pure_history ,
-from where it is restored the next time you run the interpreter.
-.PP
Options and source files are processed in the order in which they are given on
the command line. Processing of options and source files ends when either the
.B --
@@ -148,6 +121,8 @@
.B prelude.pure
is loaded by the interpreter prior to any other other definitions, unless the
.B -n
+or
+.B --noprelude
option is specified. The prelude is searched for in the directory specified
with the
.B PURELIB
@@ -165,6 +140,31 @@
.B -L
options; see the sections DECLARATIONS and C INTERFACE below for details.
.PP
+If the interpreter runs in interactive mode, it may source a few additional
+interactive startup files immediately before entering the interactive loop,
+unless the
+.B --norc
+option is specified. First
+.B .purerc
+in the user's home directory is read, then
+.B .purerc
+in the current working directory. These are ordinary Pure scripts which can be
+used to provide additional definitions for interactive usage. Finally, a
+.B .pure
+file in the current directory (containing a dump from a previous interactive
+session) is loaded if it is present. See the INTERACTIVE USAGE section for
+details.
+.PP
+When the interpreter is in interactive mode and reads from a tty, unless the
+.B --noediting
+option is specified, commands are read using
+.BR readline (3)
+(providing completion for all commands listed under INTERACTIVE USAGE, as well
+as for symbols defined in the running program). When exiting the interpreter,
+the command history is stored in
+.BR ~/.pure_history ,
+from where it is restored the next time you run the interpreter.
+.PP
The
.B -v
option is most useful for debugging the interpreter, or if you are interested
@@ -286,7 +286,7 @@
98
.fi
.PP
-However, due to its term rewriting semantics, Pure goes beyond most other
+In fact, due to its term rewriting semantics, Pure goes beyond most other
functional languages in that it can do symbolic evaluations just as well as
``normal'' computations:
.sp
@@ -298,9 +298,11 @@
(a+b)*(a+b)
.fi
.PP
-In fact, all the Pure interpreter does is evaluating expressions in a symbolic
-fashion, rewriting expressions using the equations supplied by the programmer,
-until no more equations are applicable. The result of this process is called a
+Leaving aside the built-in support for some common data structures such as
+numbers and strings, all the Pure interpreter really does is evaluating
+expressions in a symbolic fashion, rewriting expressions using the equations
+supplied by the programmer, until no more equations are applicable. The result
+of this process is called a
.I "normal form"
which represents the ``value'' of the original expression. Keeping with the
tradition of term rewriting, there's no distinction between ``defined'' and
@@ -844,7 +846,7 @@
0L:1L:#<thunk 0xb5f87630>
.fi
.PP
-Hmm, not much progress there, but that's just how streams work (or rather
+Hmm, not much progress there, but that's just how streams work (or rather they
don't, they're lazy bums indeed!). Nevertheless, the stream computed with
`take' is in fact finite and we can readily convert it to an ordinary list,
forcing its evaluation:
@@ -913,13 +915,13 @@
.sp
.nf
> \fBshow\fP fix
-fix f = y y \fBwhen\fP y = \ex -> f (x x&) \fBend\fP;
+fix f = y y \fBwith\fP y x = f (x x&) \fBend\fP;
.fi
.PP
-(Functional programming buffs surely notice that this is an implementation of
-the normal order fixed point combinator, decorated with `&' in the right place
-to make it work with eager evaluation. Aspiring novices may go read Wikipedia
-or a good book on the lambda calculus now.)
+(Functional programming buffs will quickly recognize this as an implementation
+of the normal order fixed point combinator, decorated with `&' in the right
+place to make it work with eager evaluation. Aspiring novices may go read
+Wikipedia or a good book on the lambda calculus now.)
.PP
So here's how we can define a ``linear-time'' version of the Fibonacci
stream. (Note that we also define the stream as a variable now, to take full
@@ -1808,11 +1810,10 @@
processes them as usual. If the
.B -i
option was used to force interactive mode when invoking the interpreter, the
-last script specified on the command line determines the visible namespace
-(i.e., all public symbols are visible, along with the private symbols of the
-loaded script). Otherwise only the public symbols defined in the prelude are
-available, as well as the (public or private) definitions in the startup files
-(see below). Additional scripts can be loaded interactively using either a
+last script specified on the command line determines the visible namespace,
+i.e., the private symbols of that script are available in addition to the
+public symbols defined in the prelude and the other scripts specified on the
+command line. Additional scripts can be loaded interactively using either a
.B using
declaration or the interactive
.B run
@@ -1836,7 +1837,7 @@
> map fact (1..10);
[1,2,6,24,120,720,5040,40320,362880,3628800]
.fi
-.SS Print Syntax
+.PP
As indicated, in interactive mode the normal forms of toplevel expressions are
printed after each expression is entered. We also call this the
.I read-eval-print
@@ -1845,108 +1846,11 @@
(anonymous and local functions), thunks (``lazy'' values to be evaluated when
needed) and pointers which don't have a textual representation in the Pure
syntax and will be printed in the format
-\fB#<\fP\fIobject description\fP\fB>\fP.
-.PP
-The interpreter provides a ``hook'' to override the print representations of
-expressions at runtime by means of the
+\fB#<\fP\fIobject description\fP\fB>\fP by default. It is also possible to
+override the print representation of any kind of expression by means of the
.B __show__
-function. This is just an ordinary Pure function expected to return a string
-with the desired custom representation of a normal form value given as the
-function's single argument. __show__ is not defined by default, so you are
-free to add any rules that you want. The interpreter prints the strings
-returned by __show__ just as they are. It will
-.I not
-check whether they conform to Pure syntax and/or semantics, or modify them in
-any way.
+function, see the CAVEATS AND NOTES section for details.
.PP
-Custom print representations are most useful for interactive purposes, when
-you're not happy with the default print syntax of some kinds of objects, or if
-you just want to change the format of numeric values. Here are some examples:
-.sp
-.nf
-> \fBusing\fP system;
-> __show__ x::double = sprintf "%0.6f" x;
-> 1/7;
-0.142857
-> __show__ x::int = sprintf "0x%0x" x;
-> 1786;
-0x6fa
-> \fBusing\fP math;
-> __show__ (x::double+:y::double) = sprintf "%0.6f+%0.6fi" (x,y);
-> cis (-pi);
--1.000000+0.000000i
-.fi
-.PP
-The prelude function
-.BR str ,
-which returns the print representation of any Pure expression, uses __show__
-as well:
-.sp
-.nf
-> str (1/7);
-"0.142857"
-.fi
-.PP
-However, the str function always returns just the default representation of an
-expression if it is invoked through __show__. This prevents __show__ from
-going recursive, and allows you to define your custom representation in terms
-of the default one. E.g., the following rule removes the `L' suffixes from
-bigint values:
-.sp
-.nf
-> __show__ x::bigint = init (str x);
-> fact n = foldl (*) 1L (1..n);
-> fact 30;
-265252859812191058636308480000000
-.fi
-.PP
-If you have a set of definitions for the __show__ function which should always
-be loaded at startup, you can put them into the interpreter's interactive
-startup files, see below.
-.PP
-By just purging the definition of the __show__ function you can easily go back
-to the standard print syntax:
-.sp
-.nf
-> \fBclear\fP __show__
-> 1/7; 1786; cis (-pi);
-0.142857142857143
-1786
--1.0+:1.22460635382238e-16
-> str (1/7);
-"0.142857142857143"
-> fact 30;
-265252859812191058636308480000000L
-.fi
-.SS Startup Files
-When running the interpreter interactively, it loads some additional scripts
-at startup, after loading the prelude. The interpreter first looks for a
-.B .purerc
-file in the user's home directory (as given by the
-.B HOME
-environment variable) and then for a
-.B .purerc
-file in the current working directory. These are just ordinary Pure scripts
-which may contain any additional definitions that you need. The
-.B .purerc
-file in the home directory is for global definitions which should always be
-available when running interactively, while the
-.B .purerc
-file in the current directory can be used for project-specific
-definitions. There can be yet another
-.B .pure
-initialization file in the current directory, which is created by the
-.B dump
-command (see below) and is loaded after the
-.B .purerc
-files if it is present.
-.PP
-The interpreter processes these files in the same way as with the
-.B run
-command (see below). When invoking the interpreter, you can specify the
-.B --norc
-option on the command line if you do not wish to load these files.
-.SS Interactive Commands
When running interactively, the interpreter also accepts a number of special
commands useful for interactive purposes. Here is a quick rundown of the
currently supported operations:
@@ -1962,43 +1866,77 @@
global variables). If no symbols are given, purge \fIall\fP definitions (after
confirmation) made after the most recent
.B save
-command, or the beginning of the interactive session. (It might be a good
-idea to first check your current definitions with \fBlist -t\fP before you do
-this, though.) See the DEFINITION LEVELS section below for details.
+command, or the beginning of the interactive session. (It might be a good idea
+to first check your current definitions with \fBshow -t\fP or save them with
+\fBdump\fP before you do this, though.) See the DEFINITION LEVELS section
+below for details.
.TP
\fBdump\fP [\fIoption\fP ...] [\fIsymbol\fP ...]
-Dump function, macro, variable and constant definitions to a file. This works
-similar to the
+Dump a snapshot of the current function, macro, constant and variable
+definitions in Pure syntax to a text file. This works similar to the
.B show
command (see below and the SHOW COMMAND section), but writes the definitions
-to a file. This command only supports a subset of the
+to a file.
+.sp
+This command only supports a subset of the
.B show
options, type
.B dump -h
-for a description of these.
+for a description of these. Also note that by default the
+.B dump
+command only writes interactive definitions to the output file, which is
+equivalent to the
+.B -t1
+option of the
+.B show
+command. Presumably this is the most common usage, but using the
+.B -t
+option, you can select any definitions level just as with
+.BR show .
+In particular,
+.B dump -t
+saves only the definitions made after the most recent
+.B save
+command, and
+.B dump -t0
+can be used to dump the
+.I entire
+program (including the definitions of the prelude), which can be useful for
+debugging purposes.
.sp
-By default, all definitions made interactively are written to a file named
+The default output file is
.B .pure
in the current directory, which is then reloaded automatically the next time
the interpreter starts up in interactive mode in the same directory. This
provides a quick-and-dirty means to save an interactive session and have it
-restored later. (Please note that this isn't perfect yet, because variable
-values containing special objects such as thunks and pointers can't be
-reconstructed, and
+restored later. Please note that this isn't perfect; in order to properly
+handle
+.B extern
+and
.B using
-or
-.B extern
-declarations are not recorded at all. For those you'll have to manually create
-a
+declarations and other special cases such as thunks and pointers stored in
+variables, you'll probably have to prepare a corresponding
.B .purerc
-file instead.)
+file yourself, see ``Startup Files'' below.
.sp
A different filename can be specified with the
.B -F
option. You can then edit that file and use it as a starting point for an
ordinary script or a
-.B purerc
-file.
+.B .purerc
+file, or you can just run the file with the
+.B run
+command (see below) to restore the definitions in a subsequent interpreter
+session.
+.sp
+You can also specify a subset of symbols to be saved. Shell glob patterns can
+be used if the
+.B -g
+option is given. Options may be combined; e.g.,
+.B "dump -Ffg foo.pure foo*"
+is just the same as
+.BR "dump -F foo.pure -f -g foo*" ,
+and dumps all functions whose names start with `foo' to the file `foo.pure'.
.TP
\fBhelp\fP [\fIargs\fP]
Display the
@@ -2072,6 +2010,39 @@
.PP
Some commands which are especially important for effective operation of the
interpreter are discussed in more detail in the following sections.
+.SS Startup Files
+In interactive mode, the interpreter also runs some additional scripts at
+startup, after loading the prelude and the scripts specified on the command
+line.
+.PP
+The interpreter first looks for a
+.B .purerc
+file in the user's home directory (as given by the
+.B HOME
+environment variable) and then for a
+.B .purerc
+file in the current working directory. These are just ordinary Pure scripts
+which may contain any additional definitions that you need. The
+.B .purerc
+file in the home directory is for global definitions which should always be
+available when running interactively, while the
+.B .purerc
+file in the current directory can be used for project-specific
+definitions.
+.PP
+Finally, you can also have a
+.B .pure
+initialization file in the current directory, which is created by the
+.B dump
+command (see above) and is loaded after the
+.B .purerc
+files if it is present.
+.PP
+The interpreter processes all these files in the same way as with the
+.B run
+command (see above). When invoking the interpreter, you can specify the
+.B --norc
+option on the command line if you wish to skip these initializations.
.SH SHOW COMMAND
In interactive mode, the
.B show
@@ -2328,6 +2299,97 @@
(available in the
.B system
standard library module) should be your friend. ;-)
+.SS The __show__ Function
+As of Pure 0.6, the interpreter provides a ``hook'' to override the print
+representations of expressions at runtime by means of the
+.B __show__
+function, which works in a fashion similar to Haskell's show function. This
+feature is still a bit experimental, but seems to work reasonably well for the
+purposes for which it is intended.
+.PP
+.B __show__
+is just an ordinary Pure function expected to return a string with the desired
+custom representation of a normal form value given as the function's single
+argument. This function is not defined by default, so you are free to add any
+rules that you want. The interpreter prints the strings returned by __show__
+just as they are. It will
+.I not
+check whether they conform to Pure syntax and/or semantics, or modify them in
+any way.
+.PP
+Custom print representations are most useful for interactive purposes, if
+you're not happy with the default print syntax of some kinds of objects. One
+particularly useful application of __show__ is to change the format of numeric
+values. Here are some examples:
+.sp
+.nf
+> \fBusing\fP system;
+> __show__ x::double = sprintf "%0.6f" x;
+> 1/7;
+0.142857
+> __show__ x::int = sprintf "0x%0x" x;
+> 1786;
+0x6fa
+> \fBusing\fP math;
+> __show__ (x::double+:y::double) = sprintf "%0.6f+%0.6fi" (x,y);
+> cis (-pi/2);
+0.000000+-1.000000i
+.fi
+.PP
+The prelude function
+.BR str ,
+which returns the print representation of any Pure expression, calls __show__
+as well:
+.sp
+.nf
+> str (1/7);
+"0.142857"
+.fi
+.PP
+Conversely, you can call the str function from __show__, but in this case it
+always returns the default representation of an expression. This prevents the
+expression printer from going recursive, and allows you to define your custom
+representation in terms of the default one. E.g., the following rule removes
+the `L' suffixes from bigint values:
+.sp
+.nf
+> __show__ x::bigint = init (str x);
+> fact n = foldl (*) 1L (1..n);
+> fact 30;
+265252859812191058636308480000000
+.fi
+.PP
+Of course, your definition of __show__ can also call __show__ itself
+recursively to determine the custom representation of an object.
+.PP
+One case which needs special consideration are thunks (futures). The printer
+will never use __show__ for those, to prevent them from being forced
+inadvertently. In fact, you
+.I can
+use __show__ to define custom representations for thunks, but only in the
+context of a rule for other kinds of objects, such as lists. For instance:
+.sp
+.nf
+> \fBnullary\fP ...;
+> __show__ (x:xs) = str (x:...) \fBif\fP thunkp xs;
+> 1:2:(3..inf);
+1:2:3:...
+.fi
+.PP
+Finally, by just purging the definition of the __show__ function you can
+easily go back to the standard print syntax:
+.sp
+.nf
+> \fBclear\fP __show__
+> 1/7; 1786; cis (-pi/2);
+0.142857142857143
+1786
+6.12303176911189e-17+:-1.0
+.fi
+.PP
+Note that if you have a set of definitions for the __show__ function which
+should always be loaded at startup, you can put them into the interpreter's
+interactive startup files, see INTERACTIVE USAGE.
.SS ``As'' Patterns
In the current implementation, ``as'' patterns cannot be placed on the
``spine'' of a function definition. Thus rules like the following, which have
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ag...@us...> - 2008-09-11 23:16:50
|
Revision: 755
http://pure-lang.svn.sourceforge.net/pure-lang/?rev=755&view=rev
Author: agraef
Date: 2008-09-11 23:17:01 +0000 (Thu, 11 Sep 2008)
Log Message:
-----------
Update documentation.
Modified Paths:
--------------
pure/trunk/pure.1.in
Modified: pure/trunk/pure.1.in
===================================================================
--- pure/trunk/pure.1.in 2008-09-11 22:06:53 UTC (rev 754)
+++ pure/trunk/pure.1.in 2008-09-11 23:17:01 UTC (rev 755)
@@ -857,7 +857,8 @@
.fi
.PP
(Conversely, you can also turn a list into a stream value with the `stream'
-function.)
+function. This is done less frequently, but becomes useful if you want to
+generate a stream from a finite list in a list comprehension.)
.PP
For interactive usage it's often convenient to define an eager variation of
`take' which combines `take' and `list'. Let's do this now, so that we can use
@@ -999,12 +1000,12 @@
.sp
.nf
all_primes = sieve (2..inf) \fBwith\fP
- sieve [] = [];
sieve (p:qs) = p : sieve [q; q = qs; q mod p] &;
\fBend\fP;
.fi
.sp
-Example:
+Note that we can omit the empty list case of `sieve' here, since the sieve now
+never becomes empty. Example:
.sp
.nf
> \fBlet\fP P = all_primes;
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ag...@us...> - 2008-09-11 23:31:13
|
Revision: 757
http://pure-lang.svn.sourceforge.net/pure-lang/?rev=757&view=rev
Author: agraef
Date: 2008-09-11 23:31:24 +0000 (Thu, 11 Sep 2008)
Log Message:
-----------
Final touches (0.6 release).
Modified Paths:
--------------
pure/trunk/pure.1.in
Modified: pure/trunk/pure.1.in
===================================================================
--- pure/trunk/pure.1.in 2008-09-11 23:17:47 UTC (rev 756)
+++ pure/trunk/pure.1.in 2008-09-11 23:31:24 UTC (rev 757)
@@ -1,4 +1,4 @@
-.TH Pure 1 "August 2008" "Pure Version @version@"
+.TH Pure 1 "September 2008" "Pure Version @version@"
.SH NAME
pure \- the Pure interpreter
.SH SYNOPSIS
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ag...@us...> - 2008-09-25 00:54:41
|
Revision: 850
http://pure-lang.svn.sourceforge.net/pure-lang/?rev=850&view=rev
Author: agraef
Date: 2008-09-25 00:54:30 +0000 (Thu, 25 Sep 2008)
Log Message:
-----------
Update documentation.
Modified Paths:
--------------
pure/trunk/pure.1.in
Modified: pure/trunk/pure.1.in
===================================================================
--- pure/trunk/pure.1.in 2008-09-24 13:08:16 UTC (rev 849)
+++ pure/trunk/pure.1.in 2008-09-25 00:54:30 UTC (rev 850)
@@ -336,6 +336,8 @@
.B false
and any non-zero value
.BR true ).
+Pure also provides some built-in support for lists and matrices, although most
+of the corresponding operations are actually defined in the prelude.
.SS Expression Syntax
Expressions consist of the following elements:
.TP
@@ -430,15 +432,48 @@
tuple 1,2, the integer 3, and another tuple 4,5. Likewise, [(1,2,3)] is list
with a single element, the tuple 1,2,3.
.TP
-\fBList comprehensions:\fP [x,y; x = 1..n; y = 1..m; x<y]
-Pure also has list comprehensions which generate lists from an expression and
-one or more ``generator'' and ``filter'' clauses (the former bind a pattern to
-values drawn from a list, the latter are just predicates determining which
-generated elements should actually be added to the output list). List
-comprehensions are in fact syntactic sugar for a combination of nested
-lambdas, conditional expressions and ``catmaps'' (a list operation which
-combines list concatenation and mapping a function over a list, defined in the
-prelude), but they are often much easier to write. Some examples of list
+\fBMatrices:\fP {1.0,2.0,3.0}, {1,2;3,4}, {1L,y+1;foo,bar}
+Pure also offers matrices, a kind of arrays, as a built-in data structure
+which provides efficient storage and element access. These work more or less
+like their Octave/MATLAB equivalents, but using curly braces instead of
+brackets. As indicated, commas are used to separate the columns of a matrix,
+semicolons for its rows. In fact, the {...} construct is rather general,
+allowing you to construct new matrices from individual elements and/or
+submatrices, provided that all dimensions match up. E.g., {{1;3},{2;4}} is
+another way to write a 2x2 matrix in ``column-major'' form (however,
+internally all matrices are stored in C's row-major format).
+.sp
+If the interpreter was built with support for the GNU Scientific Library (GSL)
+then both numeric and symbolic matrices are available. The former are thin
+wrappers around GSL's homogeneous arrays of double, complex double or
+(machine) int matrices, while the latter can contain any mixture of Pure
+expressions. Pure will pick the appropriate type for the data at hand. If a
+matrix contains values of different types, or Pure values which cannot be
+stored in a numeric matrix, then a symbolic matrix is created instead (this
+also includes the case of bigints, which are considered as symbolic values as
+far as matrix construction is concerned). If the interpreter was built without
+GSL support then symbolic matrices are the only kind of matrices supported by
+the interpreter.
+.sp
+More information about matrices and corresponding examples can be found in the
+EXAMPLES section below.
+.TP
+\fBComprehensions:\fP [x,y | x=1..n; y=1..m; x<y], {i!=j | i=1..n; j=1..m}
+Pure provides the usual comprehension syntax as a convenient means to
+construct both list and matrix values from a ``template'' expression and one
+or more ``generator'' and ``filter'' clauses (the former bind a pattern to
+values drawn from a list or matrix, the latter are just predicates determining
+which generated elements should actually be added to the result). Both list
+and matrix comprehensions are in fact syntactic sugar for a combination of
+nested lambdas, conditional expressions and ``catmaps'' (a collection of
+operations which combine list or matrix construction and mapping a function
+over a list or matrix, defined in the prelude), but they are often much easier
+to write.
+.sp
+Matrix comprehensions work pretty much like list comprehensions, but produce
+matrices instead of lists. Generator clauses in matrix comprehensions
+alternate between row and column generation so that most common mathematical
+abbreviations carry over quite easily. Examples of both kinds of
comprehensions can be found in the EXAMPLES section below.
.TP
\fBFunction applications:\fP foo x y z
@@ -712,9 +747,113 @@
symbols needed in an evaluation
.I before
entering the expression to be evaluated.
+.SH RULE SYNTAX
+Basically, the same rule syntax is used in all kinds of global and local
+definitions. However, some constructs (specifically, \fBwhen\fP, \fBlet\fP,
+\fBconst\fP and \fBdef\fP) use a restricted rule syntax where no guards or
+multiple left-hand and right-hand sides are permitted. When matching against a
+function or macro call, or the subject term in a \fBcase\fP expression, the
+rules are always considered in the order in which they are written, and the
+first matching rule (whose guard evaluates to a nonzero value, if applicable)
+is picked. (Again, the \fBwhen\fP construct is treated differently, because
+each rule is actually a separate definition.)
+.PP
+In any case, the left-hand side pattern (which, as already mentioned, is
+always a simple expression) must not contain repeated variables (i.e., rules
+must be ``left-linear''), except for the anonymous variable `_' which matches
+an arbitrary value without binding a variable symbol.
+.PP
+A left-hand side variable (including the anonymous variable) may be followed
+by one of the special type tags \fB::int\fP, \fB::bigint\fP, \fB::double\fP,
+\fB::string\fP, \fB::matrix\fP, \fB::pointer\fP, to indicate that it can only
+match a constant value of the corresponding built-in type. (This is useful if
+you want to write rules matching \fIany\fP object of one of these types; note
+that there is no way to write out all ``constructors'' for the built-in types,
+as there are infinitely many.)
+.PP
+Pure also supports Haskell-style ``as'' patterns of the form
+.IB variable @ pattern
+which binds the given variable to the expression matched by the subpattern
+.I pattern
+(in addition to the variables bound by
+.I pattern
+itself). This is convenient if the value matched by the subpattern is to be
+used on the right-hand side of an equation. Syntactically, ``as'' patterns are
+primary expressions; if the subpattern is not a primary expression, it must be
+parenthesized. For instance, the following function duplicates the head
+element of a list:
+.sp
+.nf
+foo xs@(x:_) = x:xs;
+.fi
+.PP
+The left-hand side of a rule can be omitted if it is the same as for the
+previous rule. This provides a convenient means to write out a collection of
+equations for the same left-hand side which discriminates over different
+conditions:
+.sp
+.nf
+\fIlhs\fR = \fIrhs\fP \fBif\fP \fIguard\fP;
+ = \fIrhs\fP \fBif\fP \fIguard\fP;
+ ...
+ = \fIrhs\fP \fBotherwise\fP;
+.fi
+.PP
+For instance:
+.sp
+.nf
+fact n = n*fact (n-1) \fBif\fP n>0;
+ = 1 \fBotherwise\fP;
+.fi
+.PP
+Pure also allows a collection of rules with different left-hand sides but the
+same right-hand side(s) to be abbreviated as follows:
+.sp
+.nf
+\fIlhs\fP |
+ ...
+\fIlhs\fP = \fIrhs\fP;
+.fi
+.PP
+This is useful if you need different specializations of the same rule which
+use different type tags on the left-hand side variables. For instance:
+.sp
+.nf
+fact n::int |
+fact n::double |
+fact n = n*fact(n-1) \fBif\fP n>0;
+ = 1 \fBotherwise\fP;
+.fi
+.PP
+In fact, the left-hand sides don't have to be related at all, so that you can
+also write something like:
+.sp
+.nf
+foo x | bar y = x*y;
+.fi
+.PP
+However, this is most useful when using an ``as'' pattern to bind a common
+variable to a parameter value
+.I after
+checking that it matches one of several possible argument patterns (which is
+slightly more efficient than using an equivalent type-checking guard). E.g.,
+the following definition binds the xs variable to the parameter of foo, if it
+is either the empty list or a list starting with an integer:
+.sp
+.nf
+foo xs@[] | foo xs@(_::int:_) = ... xs ...;
+.fi
+.PP
+The same construct also works in
+.B case
+expressions, which is convenient if different cases should be mapped to the
+same value, e.g.:
+.sp
+.nf
+\fBcase\fP ans \fBof\fP "y" | "Y" = 1; _ = 0; \fBend\fP;
+.fi
.SH EXAMPLES
-Here are a few examples of simple Pure programs (see the following section for
-a closer discussion of the rule syntax).
+Here are a few examples of simple Pure programs.
.PP
The factorial:
.sp
@@ -1032,110 +1171,159 @@
the number of elements printed until memory is exhausted. Calling `do' on a
fresh instance of the stream of primes allows `do' to get rid of each `cons'
cell after having printed the corresponding stream element.)
-.SH RULE SYNTAX
-Basically, the same rule syntax is used in all kinds of global and local
-definitions. However, some constructs (specifically, \fBwhen\fP, \fBlet\fP,
-\fBconst\fP and \fBdef\fP) use a restricted rule syntax where no guards or
-multiple left-hand and right-hand sides are permitted. When matching against a
-function or macro call, or the subject term in a \fBcase\fP expression, the
-rules are always considered in the order in which they are written, and the
-first matching rule (whose guard evaluates to a nonzero value, if applicable)
-is picked. (Again, the \fBwhen\fP construct is treated differently, because
-each rule is actually a separate definition.)
+.SS Matrix Computations
+Pure offers a number of basic matrix operations, such as matrix construction,
+indexing, slicing, as well as getting the size and dimensions of a matrix
+(these are briefly described in the STANDARD LIBRARY section below). However,
+it does
+.I not
+supply built-in support for matrix arithmetic and other linear algebra
+algorithms. The idea is that these can and should be provided through separate
+libraries, such as a GSL interface (which will hopefully be available in the
+near future).
.PP
-In any case, the left-hand side pattern (which, as already mentioned, is
-always a simple expression) must not contain repeated variables (i.e., rules
-must be ``left-linear''), except for the anonymous variable `_' which matches
-an arbitrary value without binding a variable symbol.
+But Pure's facilities for matrix and list processing also make it easy to roll
+your own, if desired. First, the prelude provides matrix versions of the
+common list operations like map, fold, zip etc., which provide a way to
+implement common matrix operations. E.g., multiplying a matrix x with a scalar
+a amounts to mapping the function \ex->a*x to x, which can be done as follows:
+.sp
+.nf
+> a::int * x::matrix = map (\ex->a*x) x;
+> 2*{1,2,3;4,5,6};
+{2,4,6;8,10,12}
+.fi
.PP
-A left-hand side variable (including the anonymous variable) may be followed
-by one of the special type tags \fB::int\fP, \fB::bigint\fP, \fB::double\fP,
-\fB::string\fP, to indicate that it can only match a constant value of the
-corresponding built-in type. (This is useful if you want to write rules
-matching \fIany\fP object of one of these types; note that there is no way to
-write out all ``constructors'' for the built-in types, as there are infinitely
-many.)
+Likewise, matrix addition and other element-wise operations can be realized
+using zipwith, which combines corresponding elements of two matrices using a
+given binary function:
+.sp
+.nf
+> x::matrix + y::matrix = zipwith (+) x y;
+> {1,2,3;4,5,6}+{1,2,1;3,2,3};
+{2,4,4;7,7,9}
+.fi
.PP
-Pure also supports Haskell-style ``as'' patterns of the form
-.IB variable @ pattern
-which binds the given variable to the expression matched by the subpattern
-.I pattern
-(in addition to the variables bound by
-.I pattern
-itself). This is convenient if the value matched by the subpattern is to be
-used on the right-hand side of an equation. Syntactically, ``as'' patterns are
-primary expressions; if the subpattern is not a primary expression, it must be
-parenthesized. For instance, the following function duplicates the head
-element of a list:
+Second, matrix comprehensions make it easy to express a variety of algorithms
+which would be implemented using `for' loops in conventional programming
+languages. To illustrate the use of matrix comprehensions, here is how we can
+define an operation to create a square identity matrix of a given dimension:
.sp
.nf
-foo xs@(x:_) = x:xs;
+> eye n = {i==j | i = 1..n; j = 1..n};
+> eye 3;
+{1,0,0;0,1,0;0,0,1}
.fi
.PP
-The left-hand side of a rule can be omitted if it is the same as for the
-previous rule. This provides a convenient means to write out a collection of
-equations for the same left-hand side which discriminates over different
-conditions:
+Note that the i==j term is just a Pure idiom for the Kronecker symbol. Another
+point worth mentioning here is that the generator clauses of matrix
+comprehensions alternate between row and column generation
+automatically. (More precisely, the last generator, which varies most quickly,
+always yields a row, the next-to-last one a column of these row vectors, and
+so on.) This makes matrix comprehensions resemble customary mathematical
+notation very closely.
+.PP
+As a slightly more comprehensive example (no pun intended!), here is a
+definition of matrix multiplication in Pure. Let's start out with the simple
+case of the ``dot'' product of two vectors:
.sp
.nf
-\fIlhs\fR = \fIrhs\fP \fBif\fP \fIguard\fP;
- = \fIrhs\fP \fBif\fP \fIguard\fP;
- ...
- = \fIrhs\fP \fBotherwise\fP;
+> x::matrix * y::matrix = sum [x!i*y!i | i=0..#x-1]
+> \fBif\fP vectorp x && vectorp y;
+> sum = foldl (+) 0;
+> {1,2,3}*{1,0,1};
+4
.fi
.PP
-For instance:
+(For the sake of simplicity, this doesn't do much error checking; if the two
+vectors aren't the same size then you'll get an `out_of_bounds' exception with
+the definition above.)
+.PP
+The matrix product now boils down to a simple matrix comprehension which just
+multiplies all rows of x with all columns of y (the rows and cols functions
+are prelude operations found in matrices.pure):
.sp
.nf
-fact n = n*fact (n-1) \fBif\fP n>0;
- = 1 \fBotherwise\fP;
+> x::matrix * y::matrix = {u*v | u = rows x; v = cols y};
+> {0,1;1,0;1,1}*{1,2,3;4,5,6};
+{4,5,6;1,2,3;5,7,9}
.fi
.PP
-Pure also allows a collection of rules with different left-hand sides but the
-same right-hand side(s) to be abbreviated as follows:
+Well, that was easy. So let's take a look at a more challenging example,
+Gaussian elimination, which can be used to solve systems of linear
+equations. The algorithm brings a matrix into ``row echelon'' form, a
+generalization of triangular matrices. The resulting system can then be solved
+quite easily using back substitution. Here is a Pure implementation of the
+algorithm (please refer to any good textbook on numeric mathematics for a
+closer description of the algorithm):
.sp
.nf
-\fIlhs\fP |
- ...
-\fIlhs\fP = \fIrhs\fP;
+gauss_elimination x::matrix = p,x
+\fBwhen\fP n,m = dim x; p,_,x = foldl step (0..n-1,0,x) (0..m-1) \fBend\fP;
.fi
.PP
-This is useful if you need different specializations of the same rule which
-use different type tags on the left-hand side variables. For instance:
+The actual pivoting and elimination step is a bit involved. x is our matrix, i
+the current row index, j the current column index, and p keeps track of the
+current permutation of the row indices performed during pivoting. The
+algorithm returns the updated matrix x, row index i and row permutation p.
.sp
.nf
-fact n::int |
-fact n::double |
-fact n = n*fact(n-1) \fBif\fP n>0;
- = 1 \fBotherwise\fP;
+step (p,i,x) j
+= \fBif\fP max_x>0 \fBthen\fP
+ // updated row permutation and index:
+ transp i max_i p, i+1,
+ {// the top rows of the matrix remain unchanged:
+ x!!(0..i-1,0..m-1);
+ // the pivot row, divided by the pivot:
+ {x!(i,l)/x!(i,j) | l=0..m-1};
+ // subtract suitable multiples of the pivot row:
+ {x!(k,l)-x!(k,j)*x!(i,l)/x!(i,j) | k=i+1..n-1; l=0..m-1}}
+ \fBelse\fP p,i,x
+\fBwhen\fP
+ n,m = dim x; max_i, max_x = pivot i (col x j);
+ x = \fBif\fP max_x>0 \fBthen\fP swap x i max_i \fBelse\fP x;
+\fBend\fP \fBwith\fP
+ pivot i x = foldl max (0,0) [j,abs (x!j)|j=i..#x-1];
+ max (i,x) (j,y) = \fBif\fP x<y \fBthen\fP j,y \fBelse\fP i,x;
+\fBend\fP;
.fi
.PP
-In fact, the left-hand sides don't have to be related at all, so that you can
-also write something like:
+We also need the following little helper functions to swap two rows of a
+matrix (this is used in the pivoting step above) and to apply a transposition
+to a permutation (represented as a list):
.sp
.nf
-foo x | bar y = x*y;
+swap x i j = x!!(transp i j (0..n-1),0..m-1) \fBwhen\fP n,m = dim x \fBend\fP;
+transp i j p = [p!tr k | k=0..#p-1]
+\fBwith\fP tr k = \fBif\fP k==i \fBthen\fP j \fBelse\fP \fBif\fP k==j \fBthen\fP i \fBelse\fP k \fBend\fP;
.fi
.PP
-However, this is most useful when using an ``as'' pattern to bind a common
-variable to a parameter value
-.I after
-checking that it matches one of several possible argument patterns (which is
-slightly more efficient than using an equivalent type-checking guard). E.g.,
-the following definition binds the xs variable to the parameter of foo, if it
-is either the empty list or a list starting with an integer:
+Finally, let us define a convenient print representation of double matrices a
+la Octave (the meaning of the __show__ function is explained in the CAVEATS
+and NOTES section):
.sp
.nf
-foo xs@[] | foo xs@(_::int:_) = ... xs ...;
+\fBusing\fP system;
+__show__ x::matrix
+= strcat [printd j (x!(i,j))|i=0..n-1; j=0..m-1] + "\en"
+\fBwith\fP printd 0 = sprintf "\en%10.5f"; printd _ = sprintf "%10.5f" \fBend\fP
+\fBwhen\fP n,m = dim x \fBend\fP \fBif\fP dmatrixp x;
.fi
.PP
-The same construct also works in
-.B case
-expressions, which is convenient if different cases should be mapped to the
-same value, e.g.:
+Example:
.sp
.nf
-\fBcase\fP ans \fBof\fP "y" | "Y" = 1; _ = 0; \fBend\fP;
+> \fBlet\fP x = dmatrix {2,1,-1,8; -3,-1,2,-11; -2,1,2,-3};
+> x; gauss_elimination x;
+
+ 2.00000 1.00000 -1.00000 8.00000
+ -3.00000 -1.00000 2.00000 -11.00000
+ -2.00000 1.00000 2.00000 -3.00000
+
+[1,2,0],
+ 1.00000 0.33333 -0.66667 3.66667
+ 0.00000 1.00000 0.40000 2.60000
+ 0.00000 0.00000 1.00000 -1.00000
.fi
.SH MACROS
Macros are a special type of functions to be executed as a kind of
@@ -1688,18 +1876,19 @@
unsigned integers as well (if necessary, you can use a bigint to pass positive
values which are too big to fit into a machine int). Also note that when an
unsigned integer is returned by a C routine which is too big to fit into the
-corresponding signed integer type, it will become negative. In this case,
-depending on the target type, you can use the ubyte, ushort, uint and ulong
-functions provided by the prelude to convert the result back to an unsigned
-quantity.
+corresponding signed integer type, it will ``wrap around'' and become
+negative. In this case, depending on the target type, you can use the ubyte,
+ushort, uint and ulong functions provided by the prelude to convert the result
+back to an unsigned quantity.
.PP
Concerning the pointer types, char* is for string arguments and return values
which need translation between Pure's internal utf-8 representation and the
system encoding, while void* is for any generic kind of pointer (including
strings, which are \fInot\fP translated when passed/returned as void*). Any
-other kind of pointer (except expr*, see below) is effectively treated as
-void* right now, although in a future version the interpreter may keep track
-of the type names for the purpose of checking parameter types.
+other kind of pointer (except expr* and the GSL matrix pointer types, which
+are discussed below) is effectively treated as void* right now, although in a
+future version the interpreter may keep track of the type names for the
+purpose of checking parameter types.
.PP
The expr* pointer type is special; it indicates a Pure expression parameter or
return value which is just passed through unchanged. All other types of values
@@ -1708,6 +1897,32 @@
Pure). All of this is handled by the runtime system in a transparent way, of
course.
.PP
+The matrix pointer types dmatrix*, cmatrix* and imatrix* can be used to pass
+double, complex double and int matrices to GSL functions taking pointers to
+the corresponding GSL types (gsl_matrix, gsl_matrix_complex and
+gsl_matrix_int) as arguments or returning them as results. Note that there is
+no marshalling of Pure's symbolic matrix type, as these aren't supported by
+GSL anyway. Also note that matrices are always passed by reference. If you
+need to pass a matrix as an output parameter of a GSL matrix routine, you can
+either create a zero matrix or a copy of an existing matrix. The prelude
+provides various operations for that purpose (in particular, see the dmatrix,
+cmatrix, imatrix and pack functions in matrices.pure). For instance, here is
+how you can quickly wrap up GSL's double matrix addition function in a way
+that preserves value semantics:
+.sp
+.nf
+> \fBextern\fP int gsl_matrix_add(dmatrix*, dmatrix*);
+> x::matrix + y::matrix = gsl_matrix_add x y $$ x \fBwhen\fP x = pack x \fBend\fP;
+> \fBlet\fP x = dmatrix {1,2,3}; \fBlet\fP y = dmatrix {2,3,2}; x; y; x+y;
+{1.0,2.0,3.0}
+{2.0,3.0,2.0}
+{3.0,5.0,5.0}
+.fi
+.PP
+Most GSL matrix routines can be wrapped in this fashion quite easily. A
+ready-made GSL interface providing access to all of GSL's numeric functions
+will be provided in the future.
+.PP
As already mentioned, it is possible to augment an external C function with
ordinary Pure equations, but in this case you have to make sure that the
.B extern
@@ -1795,17 +2010,81 @@
.B using
clause. The prelude offers the necessary functions to work with the built-in
types (including arithmetic and logical operations) and to do most kind of
-list processing you can find in ML- and Haskell-like languages. Please refer
-to the
+list processing you can find in ML- and Haskell-like languages. It also
+provides a collection of basic string and matrix operations. Please refer to
+the
.B prelude.pure
-file for details on the provided operations. Common container data structures
-like sets and dictionaries are also available, see
-.BR set.pure ,
+file (as well as the modules included there, specifically
+.BR primitives.pure ,
+.B matrices.pure
+and
+.BR strings.pure )
+for details on the provided operations. Here is a very brief summary of some
+of the prelude operations which, besides the usual arithmetic and logical
+operators, are probably used most frequently:
+.TP
+x+y
+This is also used to denote list concatenation.
+.TP
+x:y
+This is the list-consing operation. x becomes the head of the list, y its tail.
+.TP
+x..y
+Constructs arithmetic sequences. x:y..z can be used to denote sequences with
+arbitrary stepsize y-x. Infinite sequences can be constructed using an
+infinite bound (i.e., inf or -inf). E.g., 1:3..inf denotes the stream of all
+positive odd (machine) integers.
+.TP
+#x
+The size (number of elements) of the list, tuple or matrix x. In addition, dim
+x yields the dimensions (number of rows and columns) of a matrix.
+.TP
+x'
+The transpose of a matrix.
+.TP
+x!y
+This is the list, tuple and matrix indexing operation. Note that all indices
+in Pure are zero-based, thus x!0 and x!(#x-1) are the first and last element
+of a list, tuple or matrix, respectively. In the case of matrices, the
+subscript may also be a pair of row and column indices, such as x!(1,2).
+.TP
+x!!ys
+This is Pure's list, tuple and matrix ``slicing'' operation, which returns the
+list, tuple or matrix of all x!y while y runs through the (list or matrix) ys.
+Thus, e.g., x!!(i..j) returns all the elements between i and j (inclusive).
+Indices which fall outside the valid index range are quietly discarded. In
+fact, the index range ys may contain any number of indices (also duplicates),
+in any order. Thus x![0|i=1..n] returns the first element of x n times, and,
+if ys is a permutation of the range 0..#x-1, then x!!ys yields the
+corresponding permutation of the elements of x. In the case of matrices the
+index range may also contain two-dimensional subscripts, or the index range
+itself may be specified as a pair of row/column index lists such as
+x!!(i..j,k..l).
+.PP
+The prelude also offers support operations for the implementation of list and
+matrix comprehensions, as well as the customary list operations like head,
+tail, drop, take, filter, map, foldl, foldr, scanl, scanr, zip, unzip, etc.,
+which make list programming so much fun in modern FPLs. In Pure, these also
+work on strings as well as matrices, although, for reasons of efficiency,
+these data structures are internally represented as different kinds of array
+data structures.
+.PP
+Besides the prelude, Pure's standard library also comprises a growing number
+of additional library modules which we can only mention in passing here. In
+particular, the
+.B math.pure
+module provides additional mathematical functions as well as Pure's complex
+and rational number data types. Common container data structures like sets and
+dictionaries are implemented in the
+.B set.pure
+and
.B dict.pure
-etc. Moreover, the (beginnings of a) system interface can be found in the
+modules, among others. Moreover, the (beginnings of a) system interface can be
+found in the
.B system.pure
-module. In particular, this module also includes operations to do basic
-I/O. More stuff will likely be provided in future releases.
+module. In particular, this module also provides operations to do basic
+C-style I/O, including printf and scanf. More stuff will likely be provided in
+future releases.
.SH INTERACTIVE USAGE
In interactive mode, the interpreter reads definitions and expressions and
processes them as usual. If the
@@ -2288,12 +2567,24 @@
operations with side effects (it does allow you to call any C function after
all), but with a few exceptions the standard library operations are free of
those. Just stay away from operations marked ``IMPURE'' in the library sources
-(most notably, eval and catch/throw) and avoid the system module, then your
-program will behave according to the semantics of term rewriting.
+(most notably, eval, catch/throw, references, sentries and direct pointer
+manipulations) and avoid the system module, then your program will behave
+according to the semantics of term rewriting.
.PP
The short answer is that I simply liked the name, and there wasn't any
programming language named ``Pure'' yet (quite a feat nowadays), so there's
one now. :)
+.SS Backward Compatibility
+Pure 0.7 introduced built-in matrix structures, which called for some minor
+changes in the syntax of comprehensions and arithmetic
+sequences. Specifically, the template expression and generator/filter clauses
+of a comprehension are now separated with '|'. (For the time being, the old
+[x; ...] list comprehension syntax is still supported, but the compiler will
+warn you about such constructs and flag them as deprecated.) Moreover,
+arithmetic sequences with arbitrary stepsize are now written x:y..z instead of
+x,y..z, and the `..' operator now has a lower precedence than the `,'
+operator. This makes writing matrix slices like x!!(i..j,k..l) much more
+convenient.
.SS Debugging
There's no symbolic debugger yet. So
.BR printf (3)
@@ -2377,6 +2668,24 @@
1:2:3:...
.fi
.PP
+Another case which needs special consideration are numeric matrices. For
+efficiency, the expression printer will always use the default representation
+for these, unless you override the representation of the matrix as a
+whole. E.g., the following rule for double matrices mimics Octave's default
+output format (for the sake of simplicity, this isn't perfect, but you get the
+idea):
+.sp
+.nf
+> __show__ x::matrix =
+> strcat [printd j (x!(i,j))|i=0..n-1; j=0..m-1] + "\en"
+> \fBwith\fP printd 0 = sprintf "\en%10.5f"; printd _ = sprintf "%10.5f" \fBend\fP
+> \fBwhen\fP n,m = dim x \fBend\fP \fBif\fP dmatrixp x;
+> {1.0,1/2;1/3,4.0};
+
+ 1.00000 0.50000
+ 0.33333 4.00000
+.fi
+.PP
Finally, by just purging the definition of the __show__ function you can
easily go back to the standard print syntax:
.sp
@@ -2826,15 +3135,25 @@
Albert Graef <Dr....@t-...>, Dept. of Computer Music, Johannes
Gutenberg University of Mainz, Germany.
.SH SEE ALSO
+(All software listed here is freely available, usually under the GNU Public
+License.)
.TP
.B Aardappel
Another functional programming language based on term rewriting,
\fIhttp://wouter.fov120.com/aardappel\fP.
.TP
.B Alice ML
-A version of ML (see below) with ``futures'',
-\fIhttp://www.ps.uni-sb.de/alice\fP.
+A version of ML (see below) from which Pure borrows its model of lazy
+evaluation, \fIhttp://www.ps.uni-sb.de/alice\fP.
.TP
+.B GNU Octave
+A popular high-level language for numeric applications and free MATLAB
+replacement, \fIhttp://www.gnu.org/software/octave\fP.
+.TP
+.B GNU Scientific Library
+A free software library for numeric applications, required for Pure's
+numeric matrix support, \fIhttp://www.gnu.org/software/gsl\fP.
+.TP
.B Haskell
A popular non-strict FPL, \fIhttp://www.haskell.org\fP.
.TP
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|