Thread: [pure-lang-svn] SF.net SVN: pure-lang:[439] pure/trunk/pure.1.in
Status: Beta
Brought to you by:
agraef
|
From: <ag...@us...> - 2008-07-29 12:13:06
|
Revision: 439
http://pure-lang.svn.sourceforge.net/pure-lang/?rev=439&view=rev
Author: agraef
Date: 2008-07-29 12:13:14 +0000 (Tue, 29 Jul 2008)
Log Message:
-----------
Add remark about command prompt.
Modified Paths:
--------------
pure/trunk/pure.1.in
Modified: pure/trunk/pure.1.in
===================================================================
--- pure/trunk/pure.1.in 2008-07-16 08:05:23 UTC (rev 438)
+++ pure/trunk/pure.1.in 2008-07-29 12:13:14 UTC (rev 439)
@@ -177,7 +177,9 @@
Pure is a fairly simple language. Programs are collections of equational rules
defining functions, \fBdef\fP and \fBlet\fP commands binding global constant
and variable symbols, and expressions to be evaluated. Here's a simple
-example, entered interactively in the interpreter:
+example, entered interactively in the interpreter (note that the \fB>\fP
+symbol at the beginning of each input line is the interpreter's default
+command prompt):
.sp
.nf
> // my first Pure example
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ag...@us...> - 2008-08-13 01:45:37
|
Revision: 480
http://pure-lang.svn.sourceforge.net/pure-lang/?rev=480&view=rev
Author: agraef
Date: 2008-08-13 01:45:47 +0000 (Wed, 13 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-13 01:07:48 UTC (rev 479)
+++ pure/trunk/pure.1.in 2008-08-13 01:45:47 UTC (rev 480)
@@ -586,7 +586,7 @@
expression the comprehension expanded to:
.sp
.nf
-> list primes
+> \fBlist\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
@@ -657,9 +657,27 @@
<stdin>:2.0-7: unhandled exception 'failed_cond' while evaluating 'fact foo'
.fi
.PP
-Exceptions can also be used to implement non-local value returns. For
-instance, here's a variation of our n queens algorithm which only returns the
-first solution. Note the use of
+Moreover, asynchronous signals can be reported using exceptions, too. Most
+standard termination signals (SIGINT, SIGTERM, etc.) are set up during startup
+of the interpreter to produce corresponding Pure exceptions of the form
+.B signal SIG
+where
+.B SIG
+is the signal number. Pure's system module provides symbolic constants for
+common POSIX signals and also defines the operation
+.B trap
+which lets you rebind any signal to a
+.B signal
+exception. For instance, the following lets you handle the SIGQUIT signal:
+.sp
+.nf
+> \fBusing\fP system;
+> trap SIG_TRAP SIGQUIT;
+.fi
+.PP
+Last but not least, exceptions can also be used to implement non-local value
+returns. For instance, here's a variation of our n queens algorithm which only
+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
@@ -874,11 +892,12 @@
and logical operations) and to do most kind of list processing you can find in
ML- and Haskell-like languages. Please refer to the
.B prelude.pure
-file for details on the provided operations. Also, the beginnings of a system
-interface can be found in the
+file for details on the provided operations. Common container data structures
+like sets and dictionaries are also available. Moreover, the beginnings of a
+system interface can be found in the
.B system.pure
module. In particular, this also includes operations to do basic I/O. More
-stuff will be provided in future releases.
+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
@@ -1288,9 +1307,9 @@
> foo x = c*x;
> foo 99;
c*99
-> let c = 2; foo 99;
+> \fBlet\fP c = 2; foo 99;
198
-> let c = 3; foo 99;
+> \fBlet\fP c = 3; foo 99;
297
.fi
.PP
@@ -1306,14 +1325,14 @@
definitions. E.g., continuing the previous example:
.sp
.nf
-> def d = 2;
+> \fBdef\fP d = 2;
> bar x = d*x;
-> list foo bar
+> \fBlist\fP foo bar
bar x = 2*x;
foo x = c*x;
> bar 99;
198
-> def d = 3;
+> \fBdef\fP d = 3;
<stdin>:9.0-8: symbol 'd' is already defined as a constant
.fi
.PP
@@ -1323,9 +1342,9 @@
definitions:
.sp
.nf
-> clear d
-> def d = 3;
-> list bar
+> \fBclear\fP d
+> \fBdef\fP d = 3;
+> \fBlist\fP bar
bar x = 2*x;
.fi
.PP
@@ -1370,10 +1389,10 @@
using constant folding and similar techniques. Example:
.sp
.nf
-> extern double atan(double);
-> def pi = 4*atan 1.0;
+> \fBextern\fP double atan(double);
+> \fBdef\fP pi = 4*atan 1.0;
> foo x = 2*pi*x;
-> list foo
+> \fBlist\fP foo
foo x = 2*3.14159265358979*x;
.fi
.PP
@@ -1385,7 +1404,7 @@
different environments, without any runtime penalties:
.sp
.nf
-> def running_on_windows = index sysinfo "mingw32" >= 0;
+> \fBdef\fP running_on_windows = index sysinfo "mingw32" >= 0;
> foo x = something x if running_on_windows;
> = something_else x otherwise;
.fi
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ag...@us...> - 2008-08-13 12:36:53
|
Revision: 482
http://pure-lang.svn.sourceforge.net/pure-lang/?rev=482&view=rev
Author: agraef
Date: 2008-08-13 12:37:02 +0000 (Wed, 13 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-13 09:06:17 UTC (rev 481)
+++ pure/trunk/pure.1.in 2008-08-13 12:37:02 UTC (rev 482)
@@ -177,7 +177,7 @@
Pure is a fairly simple language. Programs are collections of equational rules
defining functions, \fBdef\fP and \fBlet\fP commands binding global constant
and variable symbols, and expressions to be evaluated. Here's a simple
-example, entered interactively in the interpreter (note that the \fB>\fP
+example, entered interactively in the interpreter (note that the ``>''
symbol at the beginning of each input line is the interpreter's default
command prompt):
.sp
@@ -606,6 +606,68 @@
= i1==i2 || j1==j2 || i1+j1==i2+j2 || i1-j1==i2-j2;
\fBend\fP;
.fi
+.SH DECLARATIONS
+As you probably noticed, Pure is very terse. 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,
+.B extern
+declarations for external C functions (described in the \fBC INTERFACE\fP
+section), and
+.B using
+clauses which provide a simple include file mechanism.
+.TP
+.B Operator and constant declarations: infix \fIlevel\fP \fIop\fR ...;
+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)
+.BR infix " (binary non-associative),"
+.BR infixl " (binary left-associative),"
+.BR infixr " (binary right-associative),"
+.BR prefix " (unary prefix) and"
+.BR postfix " (unary postfix)"
+operators. For instance:
+.sp
+.nf
+\fBinfixl\fP 6 + - ;
+\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 declaration of the form:
+.sp
+.nf
+\fBnullary \fIsymbol\fR ...;
+.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.
+.TP
+.B Using clause: using \fIname\fR ...;
+Causes each given script to be included, at the position of the
+.B using
+clause, but only if the script was not included already. Note that the
+constants, variables and functions defined by the included script are then
+available anywhere in the program, not just the module that contains the
+.B using
+clause. 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
+.B .pure
+filename extension is added automatically. In both cases, the script is
+searched for in the current directory and the directory named by the
+.B PURELIB
+environment variable. (The
+.B using
+clause also has an alternative form which allows dynamic libraries to be
+loaded, this will be discussed in the \fBC INTERFACE\fP section.)
.SH EXCEPTION HANDLING
Pure also offers a useful exception handling facility. To raise an exception,
you just invoke the built-in function
@@ -657,9 +719,9 @@
<stdin>:2.0-7: unhandled exception 'failed_cond' while evaluating 'fact foo'
.fi
.PP
-Moreover, asynchronous signals can be reported using exceptions, too. Most
-standard termination signals (SIGINT, SIGTERM, etc.) are set up during startup
-of the interpreter to produce corresponding Pure exceptions of the form
+Exceptions also provide a way to handle asynchronous signals. Most standard
+termination signals (SIGINT, SIGTERM, etc.) are set up during startup of the
+interpreter to produce corresponding Pure exceptions of the form
.B signal SIG
where
.B SIG
@@ -675,6 +737,18 @@
> trap SIG_TRAP SIGQUIT;
.fi
.PP
+You can also use
+.B trap
+to just ignore a signal or revert to the system's default handler (which might
+take different actions depending on the type of signal, see
+.BR signal (7)
+for details):
+.sp
+.nf
+> trap SIG_IGN SIGQUIT; // signal is ignored
+> trap SIG_DFL SIGQUIT; // reinstalls the default signal handler
+.fi
+.PP
Last but not least, exceptions can also be used to implement non-local value
returns. For instance, here's a variation of our n queens algorithm which only
returns the first solution. Note the use of
@@ -700,64 +774,6 @@
> queens 8;
(1,1):(2,5):(3,8):(4,6):(5,3):(6,7):(7,2):(8,4):[]
.fi
-.SH DECLARATIONS
-As you probably noticed, Pure is very terse. 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,
-.B extern
-declarations for external C functions (described in the next section), and
-.B using
-clauses which provide a simple include file mechanism.
-.TP
-.B Operator and constant declarations: infix \fIlevel\fP \fIop\fR ...;
-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)
-.BR infix " (binary non-associative),"
-.BR infixl " (binary left-associative),"
-.BR infixr " (binary right-associative),"
-.BR prefix " (unary prefix) and"
-.BR postfix " (unary postfix)"
-operators. For instance:
-.sp
-.nf
-\fBinfixl\fP 6 + - ;
-\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 declaration of the form:
-.sp
-.nf
-\fBnullary \fIsymbol\fR ...;
-.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.
-.TP
-.B Using clause: using \fIname\fR ...;
-Causes each given script to be included, at the position of the
-.B using
-clause, but only if the script was not included already. 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
-.B .pure
-filename extension is added automatically. In both cases, the script is
-searched for in the current directory and the directory named by the
-.B PURELIB
-environment variable. (The
-.B using
-clause also has an alternative form which allows dynamic libraries to be
-loaded, this will be discussed in the following section.)
.SH C INTERFACE
Accessing C functions from Pure programs is dead simple. You just need an
.B extern
@@ -786,11 +802,12 @@
the human reader; they are effectively treated as comments by the compiler.
.PP
The interpreter makes sure that the parameters in a call match; if not, the
-call is treated as a normal form expression. The range of supported C types is
-a bit limited right now (void, bool, char, short, int, long, double, as well
-as arbitrary pointer types, i.e.: void*, char*, etc.), but in practice these
-should cover most kinds of calls that need to be done when interfacing to C
-libraries.
+call is treated as a normal form expression by default, which enables you to
+extend the external function with your own Pure equations. The range of
+supported C types is a bit limited right now (void, bool, char, short, int,
+long, float, double, as well as arbitrary pointer types, i.e.: void*, char*,
+etc.), but in practice these should cover most kinds of calls that need to be
+done when interfacing to C libraries.
.PP
Since Pure only has 32 bit machine integers and GMP bigints, a variety of C
integer types are provided which are converted from/to the Pure types in a
@@ -805,6 +822,9 @@
Pure bigint (which is truncated to 64 bit if necessary). 64 bit return values
are always converted to (signed) Pure bigints.
.PP
+Similarly, single precision float arguments and return values are converted
+from/to Pure's double precision floating point numbers automatically.
+.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
@@ -820,8 +840,8 @@
Pure). All of this is handled by the runtime system in a transparent way, of
course.
.PP
-It is even possible to augment an external C function with ordinary Pure
-equations, but in this case you have to make sure that the
+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
declaration of the function comes first. For instance, we might want to extend
our imported
@@ -829,6 +849,9 @@
function with a rule to handle integers:
.sp
.nf
+> \fBextern\fP double sin(double);
+> sin 0.3;
+0.29552020666134
> sin 0;
sin 0
> sin x::int = sin (double x);
@@ -887,17 +910,22 @@
error message is printed.
.SH STANDARD LIBRARY
Pure comes with a collection of Pure library modules, which includes the
-standard prelude. Right now the library is pretty rudimentary, but it 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
+standard prelude (loaded automatically at startup time) and some other modules
+which can be loaded explicitly with a
+.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
.B prelude.pure
file for details on the provided operations. Common container data structures
-like sets and dictionaries are also available. Moreover, the beginnings of a
-system interface can be found in the
+like sets and dictionaries are also available, see
+.BR set.pure ,
+.B dict.pure
+etc. Moreover, the (beginnings of a) system interface can be found in the
.B system.pure
-module. In particular, this also includes operations to do basic I/O. More
-stuff will likely be provided in future releases.
+module. In particular, this module also includes operations to do basic
+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
@@ -1473,8 +1501,38 @@
(\fBif\fP-\fBthen\fP-\fBelse\fP) are tail-recursive in both branches, just
like in Scheme, while the logical operators && and || are
.I not
-tail-recursive. This is because the logical operators always return a proper
-truth value (0 or 1) which wouldn't be possible with tail call semantics.
+tail-recursive. This is because in Pure the logical operators always return a
+proper truth value (0 or 1) which wouldn't be possible with tail call
+semantics.
+.PP
+.B Handling of asynchronous signals.
+As described in section \fBEXCEPTION HANDLING\fP, 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, such as entry into a global function. This doesn't include
+tail calls, however, so a busy loop like `loop = loop;' will \fInever\fP be
+interrupted. To work around this, just add a call to another global function
+to your loop to make it interruptible. For instance:
+.sp
+.nf
+loop = loop when _ = check end;
+check = ();
+.fi
+.PP
+(Of course, the `check' function can actually do any processing required by
+your application. In that case you'd probably want the `loop' function to
+carry around some ``state'' argument which is modified by the `check'
+routine.) To handle signals while the above loop is executing, add an
+exception handler like the following:
+.sp
+.nf
+loop = loop when _ = catch handle check end
+with handle (signal k) = catch handle (...) end;
+.fi
+.PP
+By these means the entire loop remains tail-recursive. (Note the `catch
+handle' around the signal processing code which is needed for safety because
+another signal may arrive while the signal handler is being executed.)
.SH FILES
.TP
.B ~/.pure_history
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ag...@us...> - 2008-08-13 13:24:53
|
Revision: 485
http://pure-lang.svn.sourceforge.net/pure-lang/?rev=485&view=rev
Author: agraef
Date: 2008-08-13 13:25:03 +0000 (Wed, 13 Aug 2008)
Log Message:
-----------
Cosmetic changes.
Modified Paths:
--------------
pure/trunk/pure.1.in
Modified: pure/trunk/pure.1.in
===================================================================
--- pure/trunk/pure.1.in 2008-08-13 13:13:21 UTC (rev 484)
+++ pure/trunk/pure.1.in 2008-08-13 13:25:03 UTC (rev 485)
@@ -33,7 +33,7 @@
Pure is a modern-style functional programming language based on term
rewriting. Pure programs are basically collections of equational rules used to
evaluate expressions in a symbolic fashion by reducing them to normal form. A
-brief overview of the language can be found in the \fBPURE OVERVIEW\fP section
+brief overview of the language can be found in the PURE OVERVIEW section
below. (In case you're wondering, the name ``Pure'' actually refers to the
adjective. But you can also write it as ``PURE'' and take this as a recursive
acronym for the ``Pure Universal Rewriting Engine''.)
@@ -58,8 +58,7 @@
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
-.B INTERACTIVE USAGE
+(providing completion for all commands listed in section INTERACTIVE USAGE
below, as well as for global function and variable symbols) and, when exiting
the interpreter, the command history is stored in
.BR ~/.pure_history ,
@@ -170,8 +169,8 @@
.B using
clause. As a remedy, you can use the interactive
.B list
-command (see the \fBINTERACTIVE USAGE\fP section below) to list definitions
-along with additional debugging information.
+command (see the INTERACTIVE USAGE section below) to list definitions along
+with additional debugging information.
.SH PURE OVERVIEW
.PP
Pure is a fairly simple language. Programs are collections of equational rules
@@ -615,8 +614,8 @@
programs consisting of several source modules. These are: operator and
constant symbol declarations,
.B extern
-declarations for external C functions (described in the \fBC INTERFACE\fP
-section), and
+declarations for external C functions (described in the C INTERFACE section),
+and
.B using
clauses which provide a simple include file mechanism.
.TP
@@ -667,7 +666,7 @@
environment variable. (The
.B using
clause also has an alternative form which allows dynamic libraries to be
-loaded, this will be discussed in the \fBC INTERFACE\fP section.)
+loaded, this will be discussed in the C INTERFACE section.)
.SH EXCEPTION HANDLING
Pure also offers a useful exception handling facility. To raise an exception,
you just invoke the built-in function
@@ -959,8 +958,8 @@
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 \fBDEFINITION LEVELS AND OVERRIDE MODE\fP section below for details.
+command (or the beginning of the interactive session). See the DEFINITION
+LEVELS AND OVERRIDE MODE section below for details.
.TP
.B "help \fR[\fIargs\fP]\fP"
Display the
@@ -970,16 +969,16 @@
with the given arguments.
.TP
.B "list \fR[\fIoption\fP ...]\fP \fR[\fIsymbol\fP ...]\fP"
-List defined symbols in various formats.
-See the \fBLIST COMMAND\fP section below for details.
+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
.B override
Enter ``override'' mode. This allows you to add equations ``above'' existing
-definitions in the source script, possibly overriding existing equations.
-See the \fBDEFINITION LEVELS AND OVERRIDE MODE\fP section below for details.
+definitions in the source script, possibly overriding existing equations. See
+the DEFINITION LEVELS AND OVERRIDE MODE section below for details.
.TP
.B pwd
Print the current working dir (shell \fBpwd\fP(1) command).
@@ -1004,8 +1003,8 @@
.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 \fBDEFINITION LEVELS AND OVERRIDE MODE\fP section below for details.
+(or the beginning of the interactive session). See the DEFINITION LEVELS AND
+OVERRIDE MODE section below for details.
.TP
.B "stats \fR[on|off]\fP"
Enables (default) or disables ``stats'' mode, in which various statistics are
@@ -1016,7 +1015,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 \fBDEFINITION LEVELS AND OVERRIDE MODE\fP section below for details.
+See the DEFINITION LEVELS AND OVERRIDE MODE 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
@@ -1073,9 +1072,9 @@
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 \fBDEFINITION LEVELS AND
-OVERRIDE MODE\fP section below for information about the notion of temporary
-definition levels.
+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.
.TP
.B -v
Print information about variable symbols.
@@ -1506,16 +1505,16 @@
semantics.
.PP
.B Handling of asynchronous signals.
-As described in section \fBEXCEPTION HANDLING\fP, 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, such as entry into a global function. This doesn't include
-tail calls, however, so a busy loop like `loop = loop;' will \fInever\fP be
+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,
+such as entry into a global function. This doesn't include tail calls,
+however, so a busy loop like `loop = loop;' will \fInever\fP be
interrupted. To work around this, just add a call to another global function
to your loop to make it interruptible. For instance:
.sp
.nf
-loop = loop when _ = check end;
+loop = loop \fBwhen\fP _ = check \fBend\fP;
check = ();
.fi
.PP
@@ -1526,8 +1525,8 @@
exception handler like the following:
.sp
.nf
-loop = loop when _ = catch handle check end
-with handle (signal k) = catch handle (...) end;
+loop = loop \fBwhen\fP _ = catch handle check \fBend\fP
+\fBwith\fP handle (signal k) = catch handle (...) \fBend\fP;
.fi
.PP
By these means the entire loop remains tail-recursive. (Note the `catch
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ag...@us...> - 2008-08-13 13:51:32
|
Revision: 486
http://pure-lang.svn.sourceforge.net/pure-lang/?rev=486&view=rev
Author: agraef
Date: 2008-08-13 13:51:40 +0000 (Wed, 13 Aug 2008)
Log Message:
-----------
Add remark concerning predefined operators.
Modified Paths:
--------------
pure/trunk/pure.1.in
Modified: pure/trunk/pure.1.in
===================================================================
--- pure/trunk/pure.1.in 2008-08-13 13:25:03 UTC (rev 485)
+++ pure/trunk/pure.1.in 2008-08-13 13:51:40 UTC (rev 486)
@@ -411,6 +411,24 @@
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 declared at the beginning
+of the prelude, see the
+.B prelude.pure
+script for a list of these. Arithmetic, relational and logical operators
+usually follow C conventions. However, out of necessity some of Pure's
+operator symbols deviate from C. Most notably, the `!' symbol is Pure's
+indexing operator, hence logical negation is denoted
+.B not
+instead (named for Haskell compatibility, but Pure's
+.B not
+is a real prefix operator instead of an ordinary function symbol). Moreover,
+the bitwise operators are named
+.B and
+and
+.B or
+instead of `&' and `|', because the latter is reserved as a special symbol in
+rules, see RULE SYNTAX below.
+.PP
At the toplevel, a Pure program basically consists of equations defining
functions, constant and variable definitions, and expressions to be evaluated.
.TP
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ag...@us...> - 2008-08-14 07:59:26
|
Revision: 491
http://pure-lang.svn.sourceforge.net/pure-lang/?rev=491&view=rev
Author: agraef
Date: 2008-08-14 07:59:36 +0000 (Thu, 14 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-14 07:58:03 UTC (rev 490)
+++ pure/trunk/pure.1.in 2008-08-14 07:59:36 UTC (rev 491)
@@ -1330,8 +1330,7 @@
symbols). On the other hand, generic rules operating on arbitrary function
applications are not all that common, so having to ``escape'' a variable using
the anonymous ``as'' pattern trick is a small price to pay for that
-convenience. Moreover, the prelude also provides operations to recognize and
-decompose function applications.
+convenience.
.PP
.B Constant and variable definitions.
Defined constants (symbols bound with \fBdef\fP) are somewhat limited in scope
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ag...@us...> - 2008-08-14 22:13:19
|
Revision: 499
http://pure-lang.svn.sourceforge.net/pure-lang/?rev=499&view=rev
Author: agraef
Date: 2008-08-14 22:13:28 +0000 (Thu, 14 Aug 2008)
Log Message:
-----------
Add missing description of C char type.
Modified Paths:
--------------
pure/trunk/pure.1.in
Modified: pure/trunk/pure.1.in
===================================================================
--- pure/trunk/pure.1.in 2008-08-14 21:31:33 UTC (rev 498)
+++ pure/trunk/pure.1.in 2008-08-14 22:13:28 UTC (rev 499)
@@ -830,7 +830,8 @@
integer types are provided which are converted from/to the Pure types in a
straightfoward way. The short type indicates 16 bit integers which are
converted from/to Pure machine ints using truncation and sign extension,
-respectively. The long type
+respectively. The char type, which denotes 8 bit integers, is treated
+analogously. The long type
.I always
denotes 64 bit integers, even if the corresponding C type is actually 32 bit
(as it usually is on most contemporary systems). This type is to be used if a
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ag...@us...> - 2008-08-16 00:54:12
|
Revision: 511
http://pure-lang.svn.sourceforge.net/pure-lang/?rev=511&view=rev
Author: agraef
Date: 2008-08-16 00:54:21 +0000 (Sat, 16 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-15 10:41:43 UTC (rev 510)
+++ pure/trunk/pure.1.in 2008-08-16 00:54:21 UTC (rev 511)
@@ -309,19 +309,18 @@
syntactic sugar for list values in brackets, such as [x,y,z], which is exactly
the same as x:y:z:[]. Moreover, the prelude also provides an infix `..'
operator to denote arithmetic sequences such as 1..10 or 1.0,1.2..3.0. Pure's
-tuples are a bit unusual, however: They are constructed by just ``paring''
-things using the `,' operator, for which the empty tuple acts as a neutral
-element (i.e., (),x is just x, as is x,()). The pairing operator is
-associative, which implies that tuples are completely flat (i.e., x,(y,z) is
-just x,y,z, as is (x,y),z). This means that there are no nested tuples (tuples
-of tuples), if you need such constructs then you should use lists
-instead. Also note that the parentheses are \fInot\fP part of the tuple syntax
-in Pure, although you \fIcan\fP use parentheses, just as with any other
-expression, for the usual purpose of grouping expressions and overriding
-default precedences and associativity. This means that a list of tuples will
-be printed (and must also be entered) using the ``canonical'' representation
-(x1,y1):(x2,y2):...:[] rather than [(x1,y1),(x2,y2),...] (which denotes just
-[x1,y1,x2,y2,...]).
+tuples are a bit unusual: They are constructed by just ``paring'' things using
+the `,' operator, for which the empty tuple acts as a neutral element (i.e.,
+(),x is just x, as is x,()). The pairing operator is associative, which
+implies that tuples are completely flat (i.e., x,(y,z) is just x,y,z, as is
+(x,y),z). This means that there are no nested tuples (tuples of tuples), if
+you need such constructs then you should use lists instead. Also note that the
+parentheses are \fInot\fP part of the tuple syntax in Pure, although you
+\fIcan\fP use parentheses, just as with any other expression, for the usual
+purpose of grouping expressions and overriding default precedences and
+associativity. This means that a list of tuples will be printed (and must also
+be entered) using the ``canonical'' representation (x1,y1):(x2,y2):...:[]
+rather than [(x1,y1),(x2,y2),...] (which denotes just [x1,y1,x2,y2,...]).
.TP
.B List comprehensions: \fR[x,y; x = 1..n; y = 1..m; x<y]
Pure also has list comprehensions which generate lists from an expression and
@@ -430,7 +429,8 @@
rules, see RULE SYNTAX below.
.PP
At the toplevel, a Pure program basically consists of equations defining
-functions, constant and variable definitions, and expressions to be evaluated.
+functions (also called ``rules''), constant and variable bindings, 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
@@ -462,6 +462,71 @@
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
+Here are a few examples showing how the above constructs are used (see the
+following section for a closer discussion of the rule syntax).
+.PP
+The factorial:
+.sp
+.nf
+fact n = n*fact (n-1) \fBif\fP n>0;
+ = 1 \fBotherwise\fP;
+.fi
+.PP
+The Fibonacci numbers:
+.sp
+.nf
+fib n = a \fBwhen\fP a, b = fibs n \fBend\fP
+ \fBwith\fP fibs n = 0, 1 \fBif\fP n<=0;
+ = \fBcase\fP fibs (n-1) \fBof\fP
+ a, b = b, a+b;
+ \fBend\fP;
+ \fBend\fP;
+
+\fBlet\fP fibs = map fib (1..30);
+fibs;
+.fi
+.PP
+A little list comprehension example (Erathosthenes' classical prime sieve):
+.sp
+.nf
+primes n = sieve (2..n) \fBwith\fP
+ sieve [] = [];
+ sieve (p:qs) = p : sieve [q; q = qs; q mod p];
+\fBend\fP;
+.fi
+.sp
+For instance:
+.sp
+.nf
+> primes 100;
+[2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97]
+.fi
+.PP
+If you dare, you can actually have a look at the catmap-lambda-if-then-else
+expression the comprehension expanded to:
+.sp
+.nf
+> \fBlist\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
+.PP
+List comprehensions are also a useful device to organize backtracking
+searches. For instance, here's an algorithm for the n queens problem, which
+returns the list of all placements of n queens on an n x n board (encoded as
+lists of n pairs (i,j) with i = 1..n), so that no two queens hold each other
+in check.
+.sp
+.nf
+queens n = search n 1 [] \fBwith\fP
+ search n i p = [reverse p] \fBif\fP i>n;
+ = cat [search n (i+1) ((i,j):p); j = 1..n; safe (i,j) p];
+ safe (i,j) p = not any (check (i,j)) p;
+ check (i1,j1) (i2,j2)
+ = i1==i2 || j1==j2 || i1+j1==i2+j2 || i1-j1==i2-j2;
+\fBend\fP;
+.fi
.SH RULE SYNTAX
Basically, the same rule syntax is used to define functions at the toplevel
and in \fBwith\fP expressions, as well as inside \fBcase\fP, \fBwhen\fP,
@@ -566,63 +631,6 @@
.nf
\fBcase\fP ans \fBof\fP "y" | "Y" = 1; _ = 0; \fBend\fP;
.fi
-.PP
-Here are a few more examples of rules illustrating some of the constructs
-introduced above and in the previous section. The first one is a definition of
-a function which generates the Fibonacci numbers:
-.sp
-.nf
-fib n = a \fBwhen\fP a, b = fibs n \fBend\fP
- \fBwith\fP fibs n = 0, 1 \fBif\fP n<=0;
- = \fBcase\fP fibs (n-1) \fBof\fP
- a, b = b, a+b;
- \fBend\fP;
- \fBend\fP;
-
-\fBlet\fP fibs = map fib (1..100);
-fibs;
-.fi
-.PP
-A little list comprehension example (Erathosthenes' classical prime sieve):
-.sp
-.nf
-primes n = sieve (2..n) \fBwith\fP
- sieve [] = [];
- sieve (p:qs) = p : sieve [q; q = qs; q mod p];
-\fBend\fP;
-.fi
-.sp
-For instance:
-.sp
-.nf
-> primes 100;
-[2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97]
-.fi
-.PP
-If you dare, you can actually have a look at the catmap-lambda-if-then-else
-expression the comprehension expanded to:
-.sp
-.nf
-> \fBlist\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
-.PP
-We mention in passing that list comprehensions are also a useful device to
-organize backtracking searches. For instance, here's an algorithm for the n
-queens problem, which returns the list of all placements of n queens on an n x
-n board (encoded as lists of n pairs (i,j) with i = 1..n), so that no two
-queens hold each other in check.
-.sp
-.nf
-queens n = search n 1 [] \fBwith\fP
- search n i p = [reverse p] \fBif\fP i>n;
- = cat [search n (i+1) ((i,j):p); j = 1..n; safe (i,j) p];
- safe (i,j) p = not any (check (i,j)) p;
- check (i1,j1) (i2,j2)
- = i1==i2 || j1==j2 || i1+j1==i2+j2 || i1-j1==i2-j2;
-\fBend\fP;
-.fi
.SH DECLARATIONS
As you probably noticed, Pure is very terse. That's because, in contrast to
hopelessly verbose languages like Java, you don't declare much stuff in Pure,
@@ -820,28 +828,35 @@
.PP
The interpreter makes sure that the parameters in a call match; if not, the
call is treated as a normal form expression by default, which enables you to
-extend the external function with your own Pure equations. The range of
-supported C types is a bit limited right now (void, bool, char, short, int,
-long, float, double, as well as arbitrary pointer types, i.e.: void*, char*,
-etc.), but in practice these should cover most kinds of calls that need to be
-done when interfacing to C libraries.
+extend the external function with your own Pure equations (see below). The
+range of supported C types is a bit limited right now (void, bool, char,
+short, int, long, float, double, as well as arbitrary pointer types, i.e.:
+void*, char*, etc.), but in practice these should cover most kinds of calls
+that need to be done when interfacing to C libraries.
.PP
-Since Pure only has 32 bit machine integers and GMP bigints, a variety of C
-integer types are provided which are converted from/to the Pure types in a
-straightfoward way. The short type indicates 16 bit integers which are
-converted from/to Pure machine ints using truncation and sign extension,
-respectively. The char type, which denotes 8 bit integers, is treated
-analogously. The long type
+Single precision float arguments and return values are converted from/to
+Pure's double precision floating point numbers automatically.
+.PP
+A variety of C integer types (char, short, int, long) are provided which are
+converted from/to the available Pure integer types in a straightforward
+way. One important thing to note here is that the the `long' type
.I always
denotes 64 bit integers, even if the corresponding C type is actually 32 bit
-(as it usually is on most contemporary systems). This type is to be used if a
-C function takes or returns 64 bit integer values. For a long parameter you
-can either pass a Pure machine int (which is sign-extended to 64 bit) or a
-Pure bigint (which is truncated to 64 bit if necessary). 64 bit return values
-are always converted to (signed) Pure bigints.
+(as it usually is on most contemporary systems). All integer parameter types
+take both Pure ints and bigints as arguments; truncation or sign extension is
+performed as needed, so that the C interface behaves as if the argument was
+``cast'' to the C target type. Returned integers use the smallest Pure type
+capable of holding the result (i.e., int for the C char, short and int types,
+bigint for long a.k.a. 64 bit integers).
.PP
-Similarly, single precision float arguments and return values are converted
-from/to Pure's double precision floating point numbers automatically.
+Pure considers all integers as signed quantities, but it is possible to pass
+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.
.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
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ag...@us...> - 2008-08-16 22:45:51
|
Revision: 514
http://pure-lang.svn.sourceforge.net/pure-lang/?rev=514&view=rev
Author: agraef
Date: 2008-08-16 22:46:01 +0000 (Sat, 16 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-16 21:44:56 UTC (rev 513)
+++ pure/trunk/pure.1.in 2008-08-16 22:46:01 UTC (rev 514)
@@ -645,7 +645,7 @@
.B using
clauses which provide a simple include file mechanism.
.TP
-.B Operator and constant declarations: infix \fIlevel\fP \fIop\fR ...;
+.B Operator and constant declarations: infix \fIlevel\fP \fIop\fP\fR ...;\fP nullary \fIsymbol\fP\fR ...;\fP
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)
@@ -664,10 +664,12 @@
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 declaration of the form:
+Similarly, constant symbols are introduced using a
+.B nullary
+declaration, e.g.:
.sp
.nf
-\fBnullary \fIsymbol\fR ...;
+\fBnullary\fP [] () nil;
.fi
.sp
Examples for all of these can be found in the prelude which declares a bunch
@@ -682,17 +684,53 @@
constants, variables and functions defined by the included script are then
available anywhere in the program, not just the module that contains the
.B using
-clause. The script name can be specified either as a string denoting the
-proper filename (possibly including path and/or filename extension), or as an
+clause.
+.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
.B .pure
filename extension is added automatically. In both cases, the script is
-searched for in the current directory and the directory named by the
+searched for first in the directory of the script containing the
+.B using
+clause, then the directory named by the
.B PURELIB
-environment variable. (The
+environment variable, and finally in the current working directory. This is
+different from the standard search order used for scripts specified on the
+command line, where the current directory is searched prior to the
+.B PURELIB
+directory. The search order employed here lets you install a script into any
+directory, along with any other required non-library scripts, and run the
+script from there. (Note that this will only work if 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.)
+clause is contained in a script file, but not if the clause is read from
+standard input or entered interactively. In the latter case the normal search
+order is used.)
+.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
+destination file (albeit only one level). Thus different scripts with the same
+basename, such as
+.B foo/utils.pure
+and
+.B bar/utils.pure
+can both be included in the same program (unless they link to the same
+file). The resolution of symbolic links also makes it possible to have an
+executable script with a shebang line in its own directory, to be executed via
+a symbolic link placed on the system
+.BR PATH .
+In this case the script search performed in
+.B using
+clauses will use the real script directory and thus other required scripts can
+be located in the script directory as usual. 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 works differently and 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
@@ -1024,13 +1062,18 @@
Loads the given script file and adds its definitions to the current
environment. This works more or less like a
.B using
-clause, but loads the script ``anonymously'', as if the contents of the script
-had been typed at the command prompt. That is,
+clause, but uses the standard search order and loads 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
.B clear
-can be used to remove them again).
+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 .
.TP
.B save
Begin a new level of temporary definitions. A subsequent
@@ -1586,7 +1629,7 @@
.B PURE_MORE
Shell command to be used for paging through output of the
.B list
-command, when the interpreter runs in interactive mode.
+command, when the interpreter runs in interactive mode (default: none).
.TP
.B PURE_PS
Command prompt used in the interactive command loop (">\ " by default).
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ag...@us...> - 2008-08-16 23:34:39
|
Revision: 516
http://pure-lang.svn.sourceforge.net/pure-lang/?rev=516&view=rev
Author: agraef
Date: 2008-08-16 23:34:50 +0000 (Sat, 16 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-16 23:13:37 UTC (rev 515)
+++ pure/trunk/pure.1.in 2008-08-16 23:34:50 UTC (rev 516)
@@ -677,7 +677,7 @@
list and pair constructors `:' and `,' and the constant symbols `[]' and `()'
denoting the empty list and tuple, respectively.
.TP
-.B Using clause: using \fIname\fR ...;
+.B Using clause: using \fIname\fR, ...;
Causes each given script to be included, at the position of the
.B using
clause, but only if the script was not included already. Note that the
@@ -728,9 +728,8 @@
.PP
Note that the
.B using
-clause also has an alternative form which works differently and allows dynamic
-libraries to be loaded, this will be discussed in the C INTERFACE section
-below.
+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
@@ -854,6 +853,14 @@
0.29552020666134
.fi
.sp
+Multiple prototypes can be given in one
+.B extern
+declaration, separating them with commas:
+.sp
+.nf
+\fBextern\fP double sin(double), double cos(double), double tan(double);
+.fi
+.sp
For clarity, the parameter types can also be annotated with parameter names,
e.g.:
.sp
@@ -877,12 +884,12 @@
.PP
A variety of C integer types (char, short, int, long) are provided which are
converted from/to the available Pure integer types in a straightforward
-way. One important thing to note here is that the the `long' type
+way. One important thing to note here is that the `long' type
.I always
denotes 64 bit integers, even if the corresponding C type is actually 32 bit
-(as it usually is on most contemporary systems). All integer parameter types
-take both Pure ints and bigints as arguments; truncation or sign extension is
-performed as needed, so that the C interface behaves as if the argument was
+(as it usually is on most contemporary systems). All integer parameters take
+both Pure ints and bigints as actual arguments; truncation or sign extension
+is performed as needed, so that the C interface behaves as if the argument was
``cast'' to the C target type. Returned integers use the smallest Pure type
capable of holding the result (i.e., int for the C char, short and int types,
bigint for long a.k.a. 64 bit integers).
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ag...@us...> - 2008-08-17 12:57:29
|
Revision: 521
http://pure-lang.svn.sourceforge.net/pure-lang/?rev=521&view=rev
Author: agraef
Date: 2008-08-17 12:57:39 +0000 (Sun, 17 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-17 11:46:10 UTC (rev 520)
+++ pure/trunk/pure.1.in 2008-08-17 12:57:39 UTC (rev 521)
@@ -308,19 +308,20 @@
``conses'', and `,' produces ``pairs''. As indicated, Pure provides the usual
syntactic sugar for list values in brackets, such as [x,y,z], which is exactly
the same as x:y:z:[]. Moreover, the prelude also provides an infix `..'
-operator to denote arithmetic sequences such as 1..10 or 1.0,1.2..3.0. Pure's
-tuples are a bit unusual: They are constructed by just ``paring'' things using
-the `,' operator, for which the empty tuple acts as a neutral element (i.e.,
-(),x is just x, as is x,()). The pairing operator is associative, which
-implies that tuples are completely flat (i.e., x,(y,z) is just x,y,z, as is
-(x,y),z). This means that there are no nested tuples (tuples of tuples), if
-you need such constructs then you should use lists instead. Also note that the
-parentheses are \fInot\fP part of the tuple syntax in Pure, although you
-\fIcan\fP use parentheses, just as with any other expression, for the usual
-purpose of grouping expressions and overriding default precedences and
-associativity. This means that a list of tuples will be printed (and must also
-be entered) using the ``canonical'' representation (x1,y1):(x2,y2):...:[]
-rather than [(x1,y1),(x2,y2),...] (which denotes just [x1,y1,x2,y2,...]).
+operator to denote arithmetic sequences such as 1..10 or 1.0,1.2..3.0.
+.sp
+Pure's tuples are a bit unusual: They are constructed by just ``paring''
+things using the `,' operator, for which the empty tuple acts as a neutral
+element (i.e., (),x is just x, as is x,()). The pairing operator is
+associative, which implies that tuples are completely flat (i.e., x,(y,z) is
+just x,y,z, as is (x,y),z). This means that there are no nested tuples (tuples
+of tuples), if you need such constructs then you should use lists
+instead. Also note that parentheses are generally only used to group
+expressions and are \fInot\fP part of the tuple syntax in Pure. There's one
+exception to this rule, however, namely that in order to include a tuple in a
+bracketed list you have to put it inside parentheses. E.g., [(1,2),3,(4,5)] is
+a three element list consisting of the 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]
Pure also has list comprehensions which generate lists from an expression and
@@ -330,7 +331,8 @@
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.
+prelude), but they are often much easier to write. Some examples of list
+comprehensions can be found below at the end of this section.
.TP
.B Function applications: \fRfoo\ x\ y\ z
As in other modern FPLs, these are written simply as juxtaposition (i.e., in
@@ -834,7 +836,7 @@
.sp
.nf
> queens 8;
-(1,1):(2,5):(3,8):(4,6):(5,3):(6,7):(7,2):(8,4):[]
+[(1,1),(2,5),(3,8),(4,6),(5,3),(6,7),(7,2),(8,4)]
.fi
.SH C INTERFACE
Accessing C functions from Pure programs is dead simple. You just need an
@@ -1332,6 +1334,9 @@
> \fBunderride\fP
.fi
.SH CAVEATS AND NOTES
+This section deals with common pitfalls and describes other quirks and
+limitations of the current implementation.
+.PP
.B Debugging.
There's no symbolic debugger yet. So
.BR printf (3)
@@ -1339,18 +1344,6 @@
.B system
standard library module) should be your friend. ;-)
.PP
-.B Tuples and parentheses.
-Please note that parentheses are really only used to group expressions and are
-\fInot\fP part of the tuple syntax; tuples are in fact not really part of the
-Pure language at all, but are implemented in the prelude. As you can see
-there, the pairing operator `,' used to construct tuples is
-(right-)associative. We call these the ``poor man's tuples'' since they are
-always flat and thus there are no nested tuples (if you need this then you
-should use lists instead). This also implies that an expression like
-[(1,2),(3,4)] is in fact exactly the same as [1,2,3,4]. If you want to denote
-a list of tuples, you must use the syntax (1,2):(3,4):[] instead; this is also
-the notation used when the interpreter prints such objects.
-.PP
.B Special forms.
Special forms are recognized at compile time only. Thus the catch function as
well as the short-circuit logical connectives && and || are only treated as
@@ -1464,8 +1457,8 @@
holds if a symbol is currently defined as a function.)
.PP
.B Numeric calculations.
-If possible, you should always decorate numeric variables on the left-hand
-sides of function definitions with the appropriate type tags, like
+If possible, you should decorate numeric variables on the left-hand sides of
+function definitions with the appropriate type tags, like
.B ::int
or
.BR ::double .
@@ -1482,6 +1475,10 @@
= 1 \fBotherwise\fP;
.fi
.PP
+(This obviously becomes unwieldy if you have to deal with several numeric
+arguments, however, so in this case it is usually better to just use a
+polymorphic rule.)
+.PP
Also note that
.B int
(the machine integers) and
@@ -1534,7 +1531,7 @@
routines, since currently there is no type checking for these; any pointer
type other than char* and expr* is effectively treated as void*. This
considerably simplifies lowlevel programming and interfacing to C libraries,
-but also makes it very easy to have your program segfault all over the place!
+but also makes it very easy to have your program segfault all over the place.
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.
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ag...@us...> - 2008-08-17 22:55:43
|
Revision: 525
http://pure-lang.svn.sourceforge.net/pure-lang/?rev=525&view=rev
Author: agraef
Date: 2008-08-17 22:55:53 +0000 (Sun, 17 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-17 21:10:10 UTC (rev 524)
+++ pure/trunk/pure.1.in 2008-08-17 22:55:53 UTC (rev 525)
@@ -2,9 +2,9 @@
.SH NAME
pure \- the Pure interpreter
.SH SYNOPSIS
-\fBpure\fP [-h] [-i] [-n] [-q] [-v[\fIlevel\fP]] [\fIscript\fP ...] [-- \fIargs\fP ...]
+\fBpure\fP [\fIoptions\fP ...] [\fIscript\fP ...] [-- \fIargs\fP ...]
.br
-\fBpure\fP [-h] [-i] [-n] [-q] [-v[\fIlevel\fP]] -x \fIscript\fP [\fIargs\fP ...]
+\fBpure\fP [\fIoptions\fP ...] -x \fIscript\fP [\fIargs\fP ...]
.SH OPTIONS
.TP
.B -h
@@ -13,13 +13,19 @@
.B -i
Force interactive mode (read commands from stdin).
.TP
+.BI -I directory
+Add a directory to be searched for included source scripts.
+.TP
+.BI -L directory
+Add a directory to be searched for dynamic libraries.
+.TP
.B -n
Suppress automatic inclusion of the prelude.
.TP
.B -q
Quiet startup (suppresses sign-on message in interactive mode).
.TP
-.B -v
+.BR -v [\fIlevel\fP]
Set verbosity level. See below for details.
.TP
.B -x
@@ -59,8 +65,8 @@
read using
.BR readline (3)
(providing completion for all commands listed in section INTERACTIVE USAGE
-below, as well as for global function and variable symbols) and, when exiting
-the interpreter, the command history is stored in
+below, 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
@@ -106,13 +112,22 @@
.B prelude.pure
is loaded by the interpreter prior to any other other definitions, unless the
.B -n
-option is specified. The prelude as well as other source scripts specified
-with a relative pathname are first searched for in the current directory and
-then in the directory specified with the
+option is specified. The prelude is searched for in the directory specified
+with the
.B PURELIB
environment variable. If the
.B PURELIB
-variable is not set, a system-specific default is used.
+variable is not set, a system-specific default is used. Other source scripts
+specified on the command line are searched for in the current directory if a
+relative pathname is given. In addition, the executed program may load other
+scripts and libraries via a
+.B using
+declaration in the source, which are searched for in a number of locations,
+including the directories named with the
+.B -I
+and
+.B -L
+options; see the sections DECLARATIONS and C INTERFACE below for details.
.PP
The
.B -v
@@ -313,15 +328,15 @@
Pure's tuples are a bit unusual: They are constructed by just ``paring''
things using the `,' operator, for which the empty tuple acts as a neutral
element (i.e., (),x is just x, as is x,()). The pairing operator is
-associative, which implies that tuples are completely flat (i.e., x,(y,z) is
-just x,y,z, as is (x,y),z). This means that there are no nested tuples (tuples
-of tuples), if you need such constructs then you should use lists
-instead. Also note that parentheses are generally only used to group
-expressions and are \fInot\fP part of the tuple syntax in Pure. There's one
-exception to this rule, however, namely that in order to include a tuple in a
-bracketed list you have to put it inside parentheses. E.g., [(1,2),3,(4,5)] is
-a three element list consisting of the 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.
+(right-)associative, meaning that x,(y,z) == x,y,z == (x,y),z, which implies
+that tuples are completely flat and thus there are no nested tuples (tuples of
+tuples). If you need such constructs then you should use lists instead. Also
+note that parentheses are generally only used to group expressions and are
+\fInot\fP part of the tuple syntax in Pure. There's one exception to this
+rule, however, namely that in order to include a tuple in a bracketed list you
+have to put it inside parentheses. E.g., [(1,2),3,(4,5)] is a three element
+list consisting of the 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]
Pure also has list comprehensions which generate lists from an expression and
@@ -692,22 +707,28 @@
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 script is
-searched for first in the directory of the script containing the
+filename extension is added automatically. In both cases, the interpreter
+performs a search to locate the script, unless an absolute pathname was
+given. It first searches the directory of the script containing the
.B using
-clause, then the directory named by the
+clause (or the current working directory if the clause was read from standard
+input, as is the case, e.g., in an interactive session), then the directories
+named in
+.B -I
+options on the command line (in the given order), then the colon-separated
+list of directories in the
+.B PURE_INCLUDE
+environment variable, and finally the directory named by the
.B PURELIB
-environment variable, and finally in the current working directory. This is
-different from the standard search order used for scripts specified on the
-command line, where the current directory is searched prior to the
-.B PURELIB
-directory. The search order employed here lets you install a script into any
-directory, along with any other required non-library scripts, and run the
-script from there. (Note that this will only work if the
+environment variable. Note that the current working directory is \fInot\fP
+searched by default (unless the
.B using
-clause is contained in a script file, but not if the clause is read from
-standard input or entered interactively. In the latter case the normal search
-order is used.)
+clause is read from standard input), but of course you can force this by
+adding the option
+.B -I.
+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
@@ -724,8 +745,8 @@
In this case the script search performed in
.B using
clauses will use the real script directory and thus other required scripts can
-be located in the script directory as usual. This is the recommended practice
-for installing standalone Pure applications in source form which are to be run
+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
@@ -980,11 +1001,23 @@
.B extern
declarations.
.PP
-Shared libraries opened with \fBusing\fP clauses are searched for on the usual
-system linker path (\fBLD_LIBRARY_PATH\fP on Linux). The necessary filename
-suffix (e.g., \fB.so\fP on Linux or \fB.dll\fP on Windows) will also be
-supplied automatically. You can also specify a full pathname for the library
-if you prefer that. If a library file cannot be found, or if an
+Shared libraries opened with \fBusing\fP clauses are searched for in the same
+way as source scripts (see section DECLARATIONS above), using the
+.B -L
+option and the
+.B PURE_LIBRARY
+environment variable in place of
+.B -I
+and
+.BR PURE_INCLUDE .
+If the library isn't found by these means, the interpreter will also consider
+other platform-specific locations searched by the dynamic linker, such as the
+system library directories and
+.B LD_LIBRARY_PATH
+on Linux. The necessary filename suffix (e.g., \fB.so\fP on Linux or
+\fB.dll\fP on Windows) will be supplied automatically when needed. Of course
+you can also specify a full pathname for the library if you prefer that. If a
+library file cannot be found, or if an
.B extern
declaration names a function symbol which cannot be resolved, an appropriate
error message is printed.
@@ -1071,9 +1104,9 @@
Loads the given script file and adds its definitions to the current
environment. This works more or less like a
.B using
-clause, but uses the standard search order and loads the script
-``anonymously'', as if the contents of the script had been typed at the
-command prompt. That is,
+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,
.B run
doesn't check whether the script is being used already and it puts the
definitions on the current temporary level (so that
@@ -1625,11 +1658,23 @@
.SH ENVIRONMENT
.TP
.B PURELIB
-Directory to search for source files, including the prelude. If
+Directory to search for library scripts, including the prelude. If
.B PURELIB
is not set, it defaults to some default location specified at installation
time.
.TP
+.B PURE_INCLUDE
+Additional directories to be searched for included scripts (default:
+none). Uses the same colon-separated format as the
+.B PATH
+variable.
+.TP
+.B PURE_LIBRARY
+Additional directories to be searched for dynamic libraries (default:
+none). Uses the same colon-separated format as the
+.B PATH
+variable.
+.TP
.B PURE_MORE
Shell command to be used for paging through output of the
.B list
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ag...@us...> - 2008-08-18 11:47:21
|
Revision: 531
http://pure-lang.svn.sourceforge.net/pure-lang/?rev=531&view=rev
Author: agraef
Date: 2008-08-18 11:47:30 +0000 (Mon, 18 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-18 10:32:13 UTC (rev 530)
+++ pure/trunk/pure.1.in 2008-08-18 11:47:30 UTC (rev 531)
@@ -247,8 +247,8 @@
first, i.e., using
.I "call by value"
semantics. Pure also has a few built-in special forms (most notably,
-conditional expressions and the short-circuit logical connectives && and ||)
-which take some of their arguments using
+conditional expressions, the short-circuit logical connectives && and || and
+the sequencing operator $$) which take some of their arguments using
.I "call by name"
semantics.
.PP
@@ -265,14 +265,16 @@
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
-is a special notation for denoting bigints. Note that an integer constant that
-is too large to fit into a machine integer will be interpreted as a bigint
-automatically. Moreover, as in Python an integer literal immediately followed
-by the uppercase letter ``L'' will always be interpreted as a bigint constant,
-even if it fits into a machine integer. This notation is also used when
-printing bigint constants. Second, character escapes in Pure strings have a
-more flexible syntax borrowed from the author's Q language, which provides
-notations to specify any Unicode character. In particular, the notation
+is a special notation for denoting bigints. Integer constants that are too
+large to fit into machine integers will be interpreted as bigints
+automatically. Moreover, integer literals immediately followed by the
+uppercase letter ``L'' will always be interpreted as bigint constants, even if
+they fit into machine integers. This notation is also used when printing
+bigint constants.
+.sp
+Second, character escapes in Pure strings have a more flexible syntax borrowed
+from the author's Q language, which provides notations to specify any Unicode
+character. In particular, the notation
.BR \e\fIn\fP ,
where \fIn\fP is an integer literal written in decimal (no prefix),
hexadecimal (`0x' prefix) or octal (`0' prefix) notation, denotes the Unicode
@@ -314,8 +316,8 @@
\fBprefix\fP, \fBpostfix\fP and \fBinfix\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 can also be
-defined as \fBnullary\fP to denote special constant symbols. See the prelude
-for examples.
+defined as \fBnullary\fP to denote special constant symbols. See below for
+further details.
.TP
.B Lists and tuples: \fR[x,y,z], x..y, x:xs, x,y,z
The necessary constructors to build lists and tuples are actually defined in
@@ -325,18 +327,19 @@
the same as x:y:z:[]. Moreover, the prelude also provides an infix `..'
operator to denote arithmetic sequences such as 1..10 or 1.0,1.2..3.0.
.sp
-Pure's tuples are a bit unusual: They are constructed by just ``paring''
+Pure's tuples are a bit unusual: They are constructed by just ``pairing''
things using the `,' operator, for which the empty tuple acts as a neutral
-element (i.e., (),x is just x, as is x,()). The pairing operator is
-(right-)associative, meaning that x,(y,z) == x,y,z == (x,y),z, which implies
-that tuples are completely flat and thus there are no nested tuples (tuples of
-tuples). If you need such constructs then you should use lists instead. Also
-note that parentheses are generally only used to group expressions and are
-\fInot\fP part of the tuple syntax in Pure. There's one exception to this
-rule, however, namely that in order to include a tuple in a bracketed list you
-have to put it inside parentheses. E.g., [(1,2),3,(4,5)] is a three element
-list consisting of the 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.
+element (i.e., (),x is just x, as is x,()). Pairs always associate to the
+right, meaning that x,y,z == x,(y,z) == (x,y),z, where x,(y,z) is the
+normalized representation. This implies that tuples are always flat, i.e.,
+there are no nested tuples (tuples of tuples); if you need such constructs
+then you should use lists instead. Also note that parentheses are generally
+only used to group expressions and are \fInot\fP part of the tuple syntax in
+Pure. There's one exception to this rule, however, namely that in order to
+include a tuple in a bracketed list you have to put it inside
+parentheses. E.g., [(1,2),3,(4,5)] is a three element list consisting of the
+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]
Pure also has list comprehensions which generate lists from an expression and
@@ -359,10 +362,7 @@
.B Conditional expressions: if\fR\ x\ \fBthen\fR\ y\ \fBelse\fR\ 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. Conditional expressions are special forms with call-by-name arguments
-y and z; only one of the branches is actually evaluated. (The logical
-operators && and || are treated in a similar fashion, in order to implement
-short-circuit semantics.)
+integer.
.TP
.B Lambdas: \fR\ex\ ->\ y
These work pretty much like in Haskell. More than one variable may be bound
@@ -398,6 +398,12 @@
\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
+Like in most modern functional languages, local functions and variables always
+use
+.IR "lexical binding" ,
+i.e., the value of a local name is completely determined by the surrounding
+program text.
+.PP
Syntactically, the equational rules in definitions always look the same (see
RULE SYNTAX below), therefore it is important to note the differences between
\fBwith\fP expressions which define local functions, and the local variable
@@ -413,6 +419,7 @@
a definition binding the local variable x by matching the constructor pattern
foo x against the value y.
.PP
+.B Expression syntax.
Expressions are parsed according to the following precedence rules: Lambda
binds most weakly, followed by
.BR when ,
@@ -427,8 +434,8 @@
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 declared at the beginning
-of the prelude, see the
+The common operator symbols like +, -, *, / etc. are all declared at the
+beginning of the prelude, see the
.B prelude.pure
script for a list of these. Arithmetic, relational and logical operators
usually follow C conventions. However, out of necessity some of Pure's
@@ -445,6 +452,31 @@
instead of `&' and `|', because the latter is reserved as a special symbol in
rules, see RULE SYNTAX below.
.PP
+.B 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
+of the branches is actually evaluated, depending on the value of x. Similarly,
+the logical connectives && and || evaluate their operands in
+.I short-circuit
+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:
+.sp
+.nf
+> using system;
+> puts "Enter a number:" $$ scanf "%g";
+Enter a number:
+21
+21.0
+.fi
+.PP
+.B Toplevel.
At the toplevel, a Pure program basically consists of equations defining
functions (also called ``rules''), constant and variable bindings, and
expressions to be evaluated:
@@ -480,6 +512,7 @@
causes the given value to be evaluated (and the result to be printed, when
running in interactive mode).
.PP
+.B Examples.
Here are a few examples showing how the above constructs are used (see the
following section for a closer discussion of the rule syntax).
.PP
@@ -488,6 +521,8 @@
.nf
fact n = n*fact (n-1) \fBif\fP n>0;
= 1 \fBotherwise\fP;
+
+\fBlet\fP facts = map fact (1..10); facts;
.fi
.PP
The Fibonacci numbers:
@@ -500,10 +535,21 @@
\fBend\fP;
\fBend\fP;
-\fBlet\fP fibs = map fib (1..30);
-fibs;
+\fBlet\fP fibs = map fib (1..30); fibs;
.fi
.PP
+It is worth noting here that in most cases Pure performs tail call
+optimization so that tail-recursive definitions like the following will be
+executed in constant stack space (see the CAVEATS AND NOTES section for more
+details on this).
+.sp
+.nf
+// tail-recursive factorial using an "accumulating parameter"
+fact n = loop 1 n \fBwith\fP
+ loop p n = \fBif\fP n>0 \fBthen\fP loop (p*n) (n-1) \fBelse\fP p;
+\fBend\fP;
+.fi
+.PP
A little list comprehension example (Erathosthenes' classical prime sieve):
.sp
.nf
@@ -1377,13 +1423,6 @@
.B system
standard library module) should be your friend. ;-)
.PP
-.B Special forms.
-Special forms are recognized at compile time only. Thus the catch function as
-well as the short-circuit logical connectives && and || 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 ``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
@@ -1424,7 +1463,70 @@
the anonymous ``as'' pattern trick is a small price to pay for that
convenience.
.PP
-.B Constant and variable definitions.
+.B 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
+or
+.BR ::double .
+This often helps the compiler to generate better code and makes your programs
+run faster. The `|' syntax makes it easy to add the necessary specializations
+of existing rules to your program. E.g., taking the polymorphic implementation
+of the factorial as an example, you only have to add a left-hand side with the
+appropriate type tag to make that definition go as fast as possible for the
+special case of machine integers:
+.sp
+.nf
+fact n::int |
+fact n = n*fact(n-1) \fBif\fP n>0;
+ = 1 \fBotherwise\fP;
+.fi
+.PP
+(This obviously becomes unwieldy if you have to deal with several numeric
+arguments, however, so in this case it is usually better to just use a
+polymorphic rule.)
+.PP
+Also note that
+.B int
+(the machine integers) and
+.B bigint
+(the GMP ``big'' integers) are really different kinds of objects, and thus if
+you want to define a function operating on both kinds of integers, you'll also
+have to provide equations for both. This also applies to equations matching
+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
+When definining a function in terms of numeric values bound to a symbol, it's
+usually better to use a constant symbol rather than a variable for that
+purpose, since this will often allow the compiler to generate better code
+using constant folding and similar techniques. Example:
+.sp
+.nf
+> \fBextern\fP double atan(double);
+> \fBdef\fP pi = 4*atan 1.0;
+> foo x = 2*pi*x;
+> \fBlist\fP foo
+foo x = 2*3.14159265358979*x;
+.fi
+.PP
+(If you take a look at the disassembled code for this function, you will find
+that the value 2*3.14159265358979 has actually been computed at compile time.)
+.PP
+Also, the LLVM backend will eliminate dead code automagically, which enables
+you to employ a constant computed at runtime to configure your code for
+different environments, without any runtime penalties:
+.sp
+.nf
+> \fBdef\fP running_on_windows = index sysinfo "mingw32" >= 0;
+> foo x = something x \fBif\fP running_on_windows;
+> = something_else x \fBotherwise\fP;
+.fi
+.PP
+In this case the code for one of the branches of foo will be completely
+eliminated, depending on whether your script runs on Windows or not.
+.PP
+.B Global definitions.
Defined constants (symbols bound with \fBdef\fP) are somewhat limited in scope
compared to (\fBlet\fP-bound) variable definitions, since the value bound to
the constant symbol must be usable at compile time, so that it can be
@@ -1489,69 +1591,44 @@
an existing constant or variable as a different kind of symbol. The same also
holds if a symbol is currently defined as a function.)
.PP
-.B 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
-or
-.BR ::double .
-This often helps the compiler to generate better code and makes your programs
-run faster. The `|' syntax makes it easy to add the necessary specializations
-of existing rules to your program. E.g., taking the polymorphic implementation
-of the factorial as an example, you only have to add a left-hand side with the
-appropriate type tag to make that definition go as fast as possible for the
-special case of machine integers:
-.sp
-.nf
-fact n::int |
-fact n = n*fact(n-1) \fBif\fP n>0;
- = 1 \fBotherwise\fP;
-.fi
+.B Local definitions.
+In the PURE OVERVIEW section, we briefly mentioned that local function and
+variable bindings always use
+.I static
+a.k.a.
+.I lexical scoping
+in Pure, which is in line with most other modern FPLs. What this means is that
+the bindings of local functions and variables are determined statically by the
+surrounding program text, rather than the environment an expression is
+executed in. (In contrast,
+.I global
+functions and variables are always bound
+.I dynamically
+in Pure, so that they can easily be changed at any time during an interactive
+session.) In particular, if a function returns another (anonymous or local)
+function, the returned function captures the environment it was created in,
+i.e., it becomes a lexical
+.IR closure .
.PP
-(This obviously becomes unwieldy if you have to deal with several numeric
-arguments, however, so in this case it is usually better to just use a
-polymorphic rule.)
-.PP
-Also note that
-.B int
-(the machine integers) and
-.B bigint
-(the GMP ``big'' integers) are really different kinds of objects, and thus if
-you want to define a function operating on both kinds of integers, you'll also
-have to provide equations for both. This also applies to equations matching
-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
-When definining a function in terms of numeric values bound to a symbol, it's
-usually better to use a constant symbol rather than a variable for that
-purpose, since this will often allow the compiler to generate better code
-using constant folding and similar techniques. Example:
+For instance, the following function, when invoked with a single argument x,
+creates another function which adds x to its argument:
.sp
.nf
-> \fBextern\fP double atan(double);
-> \fBdef\fP pi = 4*atan 1.0;
-> foo x = 2*pi*x;
-> \fBlist\fP foo
-foo x = 2*3.14159265358979*x;
+> foo x = bar \fBwith\fP bar y = x+y \fBend\fP;
+> \fBlet\fP f = foo 99; f;
+<<closure bar>>
+> f 10, f 20;
+109,119
.fi
.PP
-(If you take a look at the disassembled code for this function, you will find
-that the value 2*3.14159265358979 has actually been computed at compile time.)
-.PP
-Also, the LLVM backend will eliminate dead code automagically, which enables
-you to employ a constant computed at runtime to configure your code for
-different environments, without any runtime penalties:
+This works no matter what other bindings of `x' may be in effect when the
+closure is invoked:
.sp
.nf
-> \fBdef\fP running_on_windows = index sysinfo "mingw32" >= 0;
-> foo x = something x if running_on_windows;
-> = something_else x otherwise;
+> \fBlet\fP x = 77; f 10, f 20 \fBwhen\fP x = 88 \fBend\fP;
+109,119
.fi
.PP
-In this case the code for one of the branches of foo will be completely
-eliminated, depending on whether your script runs on Windows or not.
-.PP
.B External C functions.
The interpreter always takes your
.B extern
@@ -1569,6 +1646,13 @@
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.
+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.
+.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
@@ -1597,26 +1681,30 @@
loop = loop;
.fi
.PP
-In the current implementation, a tail call will be eliminated \fIonly\fP if
-the call is done \fIdirectly\fP, i.e., through an explicit call, not through a
-(global or local) function variable. Otherwise the call will be handled by the
-runtime system which is written in C and can't do proper tail calls because C
-can't (at least not in a portable way). This also affects mutually recursive
-global function calls, since there the calls are handled in an indirect way,
-too, through an anonymous global variable. (This is done so that a global
-function definition 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
-Scheme programmers should note that conditional expressions
-(\fBif\fP-\fBthen\fP-\fBelse\fP) are tail-recursive in both branches, just
-like in Scheme, while the logical operators && and || are
+This also works if your definition involves function parameters, guards and
+multiple equations, of course. Moreover, conditional expressions
+(\fBif\fP-\fBthen\fP-\fBelse\fP) are tail-recursive in both branches, and the
+sequence operator $$ is tail-recursive in its second operand. Note, however,
+that the logical operators && and || are
.I not
-tail-recursive. This is because in Pure the logical operators always return a
-proper truth value (0 or 1) which wouldn't be possible with tail call
-semantics.
+tail-recursive in Pure, because they are required to
+.I always
+yield a proper truth value (0 or 1), which wouldn't be possible with tail call
+semantics. (The rationale behind this design decision is that it allows the
+compiler to generate much better code for logical expressions.)
.PP
+There is one additional restriction in the current implementation, namely that
+a tail call will be eliminated \fIonly\fP if the call is done \fIdirectly\fP,
+i.e., through an explicit call, not through a (global or local) function
+variable. Otherwise the call will be handled by the runtime system which is
+written in C and can't do proper tail calls because C can't (at least not in a
+portable way). This also affects mutually recursive global function calls,
+since there the calls are handled in an indirect way, too, through an
+anonymous global variable. (This is done so that a global function definition
+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.
As described in section EXCEPTION HANDLING, signals delivered to the process
can be caught and handled with Pure's exception handling facilities. Like
@@ -1627,24 +1715,33 @@
to your loop to make it interruptible. For instance:
.sp
.nf
-loop = loop \fBwhen\fP _ = check \fBend\fP;
+loop = check $$ loop;
check = ();
.fi
.PP
-(Of course, the `check' function can actually do any processing required by
-your application. In that case you'd probably want the `loop' function to
-carry around some ``state'' argument which is modified by the `check'
-routine.) To handle signals while the above loop is executing, add an
-exception handler like the following:
+To handle signals while the above loop is executing, you can add an exception
+handler like the following:
.sp
.nf
-loop = loop \fBwhen\fP _ = catch handle check \fBend\fP
+loop = catch handle check $$ loop
\fBwith\fP handle (signal k) = catch handle (...) \fBend\fP;
.fi
.PP
-By these means the entire loop remains tail-recursive. (Note the `catch
-handle' around the signal processing code which is needed for safety because
-another signal may arrive while the signal handler is being executed.)
+(Note the `catch handle' around the signal processing code which is needed for
+safety because another signal may arrive while the signal handler is being
+executed.)
+.PP
+Of course, in a real application the `check' function would most likely have
+to do some actual processing, too. In that case you'd probably want the `loop'
+function to carry around some ``state'' argument to be processed by the
+`check' routine, which then returns an updated state value for the next
+iteration. This can be implemented as follows:
+.sp
+.nf
+loop x = loop (catch handle (check x))
+\fBwith\fP handle (signal k) = catch handle (...) \fBend\fP;
+check x = ...;
+.fi
.SH FILES
.TP
.B ~/.pure_history
@@ -1664,21 +1761,17 @@
time.
.TP
.B PURE_INCLUDE
-Additional directories to be searched for included scripts (default:
-none). Uses the same colon-separated format as the
-.B PATH
-variable.
+Additional directories (in colon-separated format) to be searched for included
+scripts.
.TP
.B PURE_LIBRARY
-Additional directories to be searched for dynamic libraries (default:
-none). Uses the same colon-separated format as the
-.B PATH
-variable.
+Additional directories (in colon-separated format) to be searched for dynamic
+libraries.
.TP
.B PURE_MORE
Shell command to be used for paging through output of the
.B list
-command, when the interpreter runs in interactive mode (default: none).
+command, when the interpreter runs in interactive mode.
.TP
.B PURE_PS
Command prompt used in the interactive command loop (">\ " by default).
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ag...@us...> - 2008-08-18 23:01:45
|
Revision: 534
http://pure-lang.svn.sourceforge.net/pure-lang/?rev=534&view=rev
Author: agraef
Date: 2008-08-18 23:01:53 +0000 (Mon, 18 Aug 2008)
Log Message:
-----------
Some reorganization and cosmetic changes. Also added some remarks concerning scoping rules.
Modified Paths:
--------------
pure/trunk/pure.1.in
Modified: pure/trunk/pure.1.in
===================================================================
--- pure/trunk/pure.1.in 2008-08-18 17:43:57 UTC (rev 533)
+++ pure/trunk/pure.1.in 2008-08-18 23:01:53 UTC (rev 534)
@@ -252,12 +252,16 @@
.I "call by name"
semantics.
.PP
+.B Expression syntax.
The Pure language provides built-in support for machine integers (32 bit),
bigints (implemented using GMP), floating point values (double precision
IEEE), character strings (UTF-8 encoded) and generic C pointers (these don't
have a syntactic representation in Pure, though, so they need to be created
with external C functions). Truth values are encoded as machine integers (as
-you might expect, zero denotes ``false'' and any non-zero value ``true'').
+you might expect, zero denotes
+.B false
+and any non-zero value
+.BR true ).
.PP
Expressions consist of the following elements:
.TP
@@ -398,28 +402,7 @@
\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
-Like in most modern functional languages, local functions and variables always
-use
-.IR "lexical binding" ,
-i.e., the value of a local name is completely determined by the surrounding
-program text.
-.PP
-Syntactically, the equational rules in definitions always look the same (see
-RULE SYNTAX below), therefore it is important to note the differences between
-\fBwith\fP expressions which define local functions, and the local variable
-bindings performed by \fBcase\fP and \fBwhen\fP expressions; the latter are
-also called \fIpattern bindings\fP.
-.PP
-While Haskell lets you do \fIboth\fP function definitions and pattern bindings
-in its \fBwhere\fP clauses, in Pure you have to use \fBwith\fP for the former
-and \fBwhen\fP for the latter. This is necessary because Pure does not
-distinguish between defined functions and constructors, and thus there is no
-magic to figure out whether an equation like `foo x = y' by itself is meant as
-a definition of a function foo with formal parameter x and return value y, or
-a definition binding the local variable x by matching the constructor pattern
-foo x against the value y.
-.PP
-.B Expression syntax.
+.B Operators and precedence.
Expressions are parsed according to the following precedence rules: Lambda
binds most weakly, followed by
.BR when ,
@@ -495,9 +478,9 @@
.TP
.B Global variable bindings: let\fR \fIlhs\fR = \fIrhs\fR;
Binds every variable in the left-hand side pattern to the corresponding
-subterm of the evaluated right-hand side. This works like a pattern binding in
-a \fBwhen\fP clause, but serves to bind \fIglobal\fP variables occurring free
-on the right-hand side of other function and variable definitions.
+subterm of the evaluated right-hand side. 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: def\fR \fIlhs\fR = \fIrhs\fR;
An alternative form of \fBlet\fP which binds constant symbols rather than
@@ -512,9 +495,110 @@
causes the given value to be evaluated (and the result to be printed, when
running in interactive mode).
.PP
+.B 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
+or
+.I static
+binding for local functions and variables. What this means is that the binding
+of a local name is completely determined at compile time by the surrounding
+program text, and does not change as the program is being executed. In
+particular, if a function returns another (anonymous or local) function, the
+returned function captures the environment it was created in, i.e., it becomes
+a (lexical)
+.IR closure .
+For instance, the following function, when invoked with a single argument x,
+returns another function which adds x to its argument:
+.sp
+.nf
+> foo x = bar \fBwith\fP bar y = x+y \fBend\fP;
+> \fBlet\fP f = foo 99; f;
+<<closure bar>>
+> f 10, f 20;
+109,119
+.fi
+.PP
+This works the same no matter what other bindings of `x' may be in effect when
+the closure is invoked:
+.sp
+.nf
+> \fBlet\fP x = 77; f 10, f 20 \fBwhen\fP x = 88 \fBend\fP;
+109,119
+.fi
+.PP
+Global bindings of constant, variable and function symbols work a bit
+differently, though. Like many languages which are to be used interactively,
+Pure binds global symbols
+.IR dynamically ,
+so that they can be changed easily at any time during an interactive
+session. This is mainly a convenience for interactive usage, but works the
+same no matter whether the source code is entered interactively or being read
+from a script, in order to ensure consistent behaviour between interactive
+and batch mode operation.
+.PP
+So, for instance, you can easily bind a global variable to a new value by just
+entering a corresponding
+.B let
+command:
+.sp
+.nf
+> foo x = c*x;
+> foo 99;
+c*99
+> \fBlet\fP c = 2; foo 99;
+198
+> \fBlet\fP c = 3; foo 99;
+297
+.fi
+.PP
+This works pretty much like global variables in imperative languages, but note
+that in Pure the value of a global variable can \fInot\fP be changed inside a
+function definition. Thus referential transparency is unimpaired; while the
+value of an expression depending on a global variable may change between
+different computations, the variable will always take the same value in a
+single evaluation.
+.PP
+Similarly, you can also add new equations to an existing function at any time:
+.sp
+.nf
+> fact 0 = 1;
+> fact n::int = n*fact (n-1) \fBif\fP n>0;
+> fact 10;
+3628800
+> fact 10.0;
+fact 10.0
+> fact 1.0 = 1.0;
+> fact n::double = n*fact (n-1) \fBif\fP n>1;
+> fact 10.0;
+3628800.0
+> fact 10;
+3628800
+.fi
+.PP
+(In interactive mode, it is even possible to completely erase constant,
+variable and function definitions. See section INTERACTIVE USAGE for details.)
+.PP
+So, while the meaning of a local symbol never changes once its definition has
+been processed, the definition of global functions and variables my well
+evolve while the program is being processed. When you evaluate an expression
+(to print its value, or to bind it to a variable or constant symbol), the
+interpreter will always use the
+.I latest
+definitions of all global constants, variables and functions used in the
+expression, up to the current point in the source where the expression is
+evaluated. Thus you have to make sure that, when you evaluate an expression,
+all the functions, constants and variables it uses have already been defined
+at this point in the source (no matter whether the source is being entered
+interactively, or read from a script). (Note that constant symbols work a bit
+differently from variables in that their values are not supposed to change
+once they have been defined, and the values will be substituted into other
+definitions rather than being looked up at runtime. But you still have to
+define them before they can be used.)
+.PP
.B Examples.
-Here are a few examples showing how the above constructs are used (see the
-following section for a closer discussion of the rule syntax).
+Here are a few examples of simple Pure programs (see the following section for
+a closer discussion of the rule syntax).
.PP
The factorial:
.sp
@@ -593,14 +677,14 @@
.SH RULE SYNTAX
Basically, the same rule syntax is used to define functions at the toplevel
and in \fBwith\fP expressions, as well as inside \fBcase\fP, \fBwhen\fP,
-\fBlet\fP and \fBdef\fP constructs for the purpose of performing pattern
-bindings (however, for obvious reasons guards are not permitted in \fBwhen\fP,
+\fBlet\fP and \fBdef\fP constructs for the purpose of binding variable values
+(however, for obvious reasons guards are not permitted in \fBwhen\fP,
\fBlet\fP and \fBdef\fP clauses). When matching against a function 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
-pattern binding.)
+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 `_'
@@ -1413,8 +1497,9 @@
> \fBunderride\fP
.fi
.SH CAVEATS AND NOTES
-This section deals with common pitfalls and describes other quirks and
-limitations of the current implementation.
+This section deals with some common pitfalls, as well as quirks and
+limitations of the current implementation, and lists some useful tips and
+tricks.
.PP
.B Debugging.
There's no symbolic debugger yet. So
@@ -1436,24 +1521,33 @@
.fi
.PP
This is because the spine of a function application is not available when the
-function is called at runtime. ``As'' patterns in pattern bindings are not
-affected by this restriction since the entire value to be matched is available
-at runtime. For instance:
+function is called at runtime. ``As'' patterns in pattern bindings
+(\fBcase\fP, \fBwhen\fP) are not affected by this restriction since the entire
+value to be matched is available at runtime. For instance:
.sp
.nf
> \fBcase\fP bar 99 \fBof\fP y@(bar x) = y,x+1; \fBend\fP;
bar 99,100
.fi
.PP
-.B Manipulating function applications.
-The ``head = function'' rule means that the head symbol f of an application f
-x1 ... xn occurring on (or inside) the left-hand side of an equation, pattern
-binding, or pattern-matching lambda expression, is always interpreted as a
-literal function symbol (not a variable). This implies that you cannot match
-the ``function'' component of an application against a variable, at least not
-directly. However, an anonymous ``as'' pattern like f@_ will do the trick,
-since the anonymous variable is always recognized, even if it occurs as the
-head symbol of a function application.
+.B 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)
+the left-hand side of an equation, variable binding, or pattern-matching
+lambda expression, is always interpreted as a literal function symbol (not a
+variable). This implies that you cannot match the ``function'' component of an
+application against a variable, at least not directly. An anonymous ``as''
+pattern like f@_ does the trick, however, since the anonymous variable is
+always recognized, even if it occurs as the head symbol of a function
+application. Here's a little example which demonstrates how you can convert a
+function application to a list containing the function and all arguments:
+.sp
+.nf
+> foo x = a [] x \fBwith\fP a xs (x@_ y) = a (y:xs) x; a xs x = x:xs \fBend\fP;
+> foo (a b c d);
+[a,b,c,d]
+.fi
.PP
This may seem a little awkward, but as a matter of fact the ``head =
function'' rule is quite useful since it covers the common cases without
@@ -1463,6 +1557,40 @@
the anonymous ``as'' pattern trick is a small price to pay for that
convenience.
.PP
+.B With or when?
+A common source of confusion for Haskell renegades is that Pure provides two
+different constructs to bind local function and variable symbols,
+respectively, namely
+.BR with ,
+which is used for local function definitions, and
+.BR when ,
+which binds local variables. This distinction is necessary because Pure does
+not segregate defined functions and constructors, and thus there is no magic
+to figure out whether an equation like `foo x = y' by itself is meant as a
+definition of a function foo with formal parameter x and return value y, or a
+definition binding the local variable x by matching the constructor pattern
+foo x against the value y. The
+.B with
+construct does the former,
+.B when
+the latter.
+.PP
+Another pitfall is that, since
+.B with
+and
+.B when
+clauses are tacked on to the end of the expression they belong to, they have
+to be read in reverse, if you want to figure out what is actually going on
+there. Also note that since
+.B with
+and
+.B when
+are part of the expression, not the rule syntax, these clauses cannot span
+both the right-hand side and the guard of a rule. Usually it's easy to work
+around this with conditional and
+.B case
+expressions, though.
+.PP
.B Numeric calculations.
If possible, you should decorate numeric variables on the left-hand sides of
function definitions with the appropriate type tags, like
@@ -1483,8 +1611,8 @@
.fi
.PP
(This obviously becomes unwieldy if you have to deal with several numeric
-arguments, however, so in this case it is usually better to just use a
-polymorphic rule.)
+arguments of different types, however, so in this case it is usually better to
+just use a polymorphic rule.)
.PP
Also note that
.B int
@@ -1497,10 +1625,12 @@
constant like `0' only matches machine integers, not bigints; for the latter
you'll have to use the ``big L'' notation `0L'.
.PP
-When definining a function in terms of numeric values bound to a symbol, it's
-usually better to use a constant symbol rather than a variable for that
-purpose, since this will often allow the compiler to generate better code
-using constant folding and similar techniques. Example:
+.B Working with constants.
+When definining a function in terms of constant values which have to be
+computed beforehand, it's usually better to use a constant symbol (rather than
+a variable or a parameterless function) for that purpose, since this will
+often allow the compiler to generate better code using constant folding and
+similar techniques. Example:
.sp
.nf
> \fBextern\fP double atan(double);
@@ -1526,109 +1656,50 @@
In this case the code for one of the branches of foo will be completely
eliminated, depending on whether your script runs on Windows or not.
.PP
-.B Global definitions.
-Defined constants (symbols bound with \fBdef\fP) are somewhat limited in scope
-compared to (\fBlet\fP-bound) variable definitions, since the value bound to
-the constant symbol must be usable at compile time, so that it can be
-substituted into other definitions. Thus, while there is no \fIa priori\fP
-restriction on the computations you can perform to obtain the value of the
-constant, the value must not be a pointer object (other than the null
-pointer), or an anonymous closure (which also rules out local functions,
-because these cannot be referred to by their names at the toplevel), or an
-aggregate value containing any such values.
+On the other hand, constant definitions are somewhat limited in scope compared
+to variable definitions, since the value bound to the constant symbol must be
+usable at compile time, so that it can be substituted into other
+definitions. Thus, while there is no \fIa priori\fP restriction on the
+computations you can perform to obtain the value of the constant, the value
+must not be a pointer object (other than the null pointer), or an anonymous
+closure (which also rules out local functions, because these cannot be
+referred to by their names at the toplevel), or an aggregate value containing
+any such values.
.PP
-Global variables are also more versatile in that they can be redefined at any
-time, which will immediately affect all uses of the variable in function
-definitions. For instance:
+Constant symbols also differ from variables in that they cannot be redefined
+(that's their purpose after all) and will only take effect on subsequent
+definitions. E.g.:
.sp
.nf
+> \fBdef\fP c = 2;
> foo x = c*x;
+> \fBlist\fP foo
+foo x = 2*x;
> foo 99;
-c*99
-> \fBlet\fP c = 2; foo 99;
198
-> \fBlet\fP c = 3; foo 99;
-297
+> \fBdef\fP c = 3;
+<stdin>:5.0-8: symbol 'c' is already defined as a constant
.fi
.PP
-This works pretty much like global variables in imperative languages, but in
-Pure the value of a global variable can \fInot\fP be changed inside a function
-definition. Thus referential transparency is unimpaired; while the value of an
-expression depending on a global variable may change between different
-computations, the variable will always take the same value in a single
-evaluation.
-.PP
-Constant symbols work differently in that they cannot be redefined (that's
-their purpose after all) and will only take effect on subsequent
-definitions. E.g., continuing the previous example:
+Well, in fact this not the full truth because in interactive mode it \fIis\fP
+possible to redefine constant symbols after all, if the old definition is
+first purged with the \fBclear\fP command. However, this won't affect any
+other existing definitions:
.sp
.nf
-> \fBdef\fP d = 2;
-> bar x = d*x;
+> \fBclear\fP c
+> \fBdef\fP c = 3;
+> bar x = c*x;
> \fBlist\fP foo bar
-bar x = 2*x;
-foo x = c*x;
-> bar 99;
-198
-> \fBdef\fP d = 3;
-<stdin>:9.0-8: symbol 'd' is already defined as a constant
+foo x = 2*x;
+bar x = 3*x;
.fi
.PP
-Well, in fact it \fIis\fP possible to redefine constant symbols when running
-the interpreter in interactive mode, but only after the old definition is
-purged with the \fBclear\fP command, and this won't affect any other existing
-definitions:
-.sp
-.nf
-> \fBclear\fP d
-> \fBdef\fP d = 3;
-> \fBlist\fP bar
-bar x = 2*x;
-.fi
-.PP
(You'll also have to purge any existing definition of a variable if you want
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.)
.PP
-.B Local definitions.
-In the PURE OVERVIEW section, we briefly mentioned that local function and
-variable bindings always use
-.I static
-a.k.a.
-.I lexical scoping
-in Pure, which is in line with most other modern FPLs. What this means is that
-the bindings of local functions and variables are determined statically by the
-surrounding program text, rather than the environment an expression is
-executed in. (In contrast,
-.I global
-functions and variables are always bound
-.I dynamically
-in Pure, so that they can easily be changed at any time during an interactive
-session.) In particular, if a function returns another (anonymous or local)
-function, the returned function captures the environment it was created in,
-i.e., it becomes a lexical
-.IR closure .
-.PP
-For instance, the following function, when invoked with a single argument x,
-creates another function which adds x to its argument:
-.sp
-.nf
-> foo x = bar \fBwith\fP bar y = x+y \fBend\fP;
-> \fBlet\fP f = foo 99; f;
-<<closure bar>>
-> f 10, f 20;
-109,119
-.fi
-.PP
-This works no matter what other bindings of `x' may be in effect when the
-closure is invoked:
-.sp
-.nf
-> \fBlet\fP x = 77; f 10, f 20 \fBwhen\fP x = 88 \fBend\fP;
-109,119
-.fi
-.PP
.B External C functions.
The interpreter always takes your
.B extern
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ag...@us...> - 2008-08-19 11:04:12
|
Revision: 540
http://pure-lang.svn.sourceforge.net/pure-lang/?rev=540&view=rev
Author: agraef
Date: 2008-08-19 11:04:21 +0000 (Tue, 19 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-19 08:01:20 UTC (rev 539)
+++ pure/trunk/pure.1.in 2008-08-19 11:04:21 UTC (rev 540)
@@ -189,11 +189,11 @@
.SH PURE OVERVIEW
.PP
Pure is a fairly simple language. Programs are collections of equational rules
-defining functions, \fBdef\fP and \fBlet\fP commands binding global constant
-and variable symbols, and expressions to be evaluated. Here's a simple
-example, entered interactively in the interpreter (note that the ``>''
-symbol at the beginning of each input line is the interpreter's default
-command prompt):
+defining functions, \fBconst\fP and \fBlet\fP commands binding global
+constants and variables, and expressions to be evaluated. Here's a simple
+example, entered interactively in the interpreter (note that the ``>'' symbol
+at the beginning of each input line is the interpreter's default command
+prompt):
.sp
.nf
> // my first Pure example
@@ -314,14 +314,18 @@
.B nullary
symbols, see below).
.TP
-.B Operator and constant symbols: \fRx+y, x==y, \fBnot\fP\ x
+.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 and \fBinfix\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 can also be
-defined as \fBnullary\fP to denote special constant symbols. See below for
-further details.
+\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
+.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
+than a variable (see above).
.TP
.B Lists and tuples: \fR[x,y,z], x..y, x:xs, x,y,z
The necessary constructors to build lists and tuples are actually defined in
@@ -482,13 +486,17 @@
but serves to bind \fIglobal\fP variables occurring free on the right-hand
side of other function and variable definitions.
.TP
-.B Constant bindings: def\fR \fIlhs\fR = \fIrhs\fR;
-An alternative form of \fBlet\fP which binds constant symbols rather than
-variables. Like \fBlet\fP, this binds the variables on the left-hand side to
-the corresponding values on the evaluated right-hand side. The difference is
-that constant symbols can only be defined once, after which their values are
-substituted directly into the right-hand sides of other definitions, rather
-than being evaluated at runtime.
+.B Constant bindings: const\fR \fIlhs\fR = \fIrhs\fR;
+An alternative form of \fBlet\fP which defines constants rather than
+variables. (These are not to be confused with
+.B nullary
+symbols which simply stand for themselves!) Like \fBlet\fP, this construct
+binds the variable symbols on the left-hand side to the corresponding values
+on the evaluated right-hand side. The difference is that
+.B const
+symbols can only be defined once, after which their values are substituted
+directly into the right-hand sides of other definitions, rather than being
+looked up at runtime.
.TP
.B Toplevel expressions: \fIexpr\fR;
A singleton expression at the toplevel, terminated with a semicolon, simply
@@ -527,9 +535,9 @@
109,119
.fi
.PP
-Global bindings of constant, variable and function symbols work a bit
-differently, though. Like many languages which are to be used interactively,
-Pure binds global symbols
+Global bindings of variable and function symbols work a bit differently,
+though. Like many languages which are to be used interactively, Pure binds
+global symbols
.IR dynamically ,
so that they can be changed easily at any time during an interactive
session. This is mainly a convenience for interactive usage, but works the
@@ -580,21 +588,17 @@
variable and function definitions. See section INTERACTIVE USAGE for details.)
.PP
So, while the meaning of a local symbol never changes once its definition has
-been processed, the definition of global functions and variables my well
+been processed, the definition of global functions and variables may well
evolve while the program is being processed. When you evaluate an expression
-(to print its value, or to bind it to a variable or constant symbol), the
-interpreter will always use the
+(to print its value, or to bind it to a variable symbol), the interpreter will
+always use the
.I latest
definitions of all global constants, variables and functions used in the
expression, up to the current point in the source where the expression is
evaluated. Thus you have to make sure that, when you evaluate an expression,
all the functions, constants and variables it uses have already been defined
at this point in the source (no matter whether the source is being entered
-interactively, or read from a script). (Note that constant symbols work a bit
-differently from variables in that their values are not supposed to change
-once they have been defined, and the values will be substituted into other
-definitions rather than being looked up at runtime. But you still have to
-define them before they can be used.)
+interactively, or read from a script).
.PP
.B Examples.
Here are a few examples of simple Pure programs (see the following section for
@@ -634,6 +638,24 @@
\fBend\fP;
.fi
.PP
+Here is an example showing how constants are defined and used. Constant
+definitions take pretty much the same form as variable definitions with
+.B let
+(see above), but work more like the definition of a parameterless function
+whose value is precomputed at compile time:
+.sp
+.nf
+> \fBextern\fP double atan(double);
+> \fBconst\fP pi = 4*atan 1.0;
+> pi;
+3.14159265358979
+> foo x = 2*pi*x;
+> \fBlist\fP foo
+foo x = 2*3.14159265358979*x;
+> foo 1;
+6.28318530717958
+.fi
+.PP
A little list comprehension example (Erathosthenes' classical prime sieve):
.sp
.nf
@@ -677,9 +699,9 @@
.SH RULE SYNTAX
Basically, the same rule syntax is used to define functions at the toplevel
and in \fBwith\fP expressions, as well as inside \fBcase\fP, \fBwhen\fP,
-\fBlet\fP and \fBdef\fP constructs for the purpose of binding variable values
+\fBlet\fP and \fBconst\fP constructs for the purpose of binding variable values
(however, for obvious reasons guards are not permitted in \fBwhen\fP,
-\fBlet\fP and \fBdef\fP clauses). When matching against a function call or the
+\fBlet\fP and \fBconst\fP clauses). When matching against a function 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
@@ -1285,7 +1307,7 @@
option of the interpreter.
.TP
.B -c
-Print information about constant symbols.
+Print information about defined constants.
.TP
.B -d
Disassembles LLVM IR, showing the generated LLVM assembler code of a
@@ -1300,7 +1322,7 @@
option of the interpreter.
.TP
.B -f
-Print information about function symbols.
+Print information about defined functions.
.TP
.B -g
Indicates that the following symbols are actually shell glob patterns and that
@@ -1326,7 +1348,7 @@
levels.
.TP
.B -v
-Print information about variable symbols.
+Print information about defined variables.
.PP
If none of the
.BR -c ,
@@ -1497,9 +1519,9 @@
> \fBunderride\fP
.fi
.SH CAVEATS AND NOTES
-This section deals with some common pitfalls, as well as quirks and
-limitations of the current implementation, and lists some useful tips and
-tricks.
+This section is a grab bag of useful tips and tricks, common pitfalls, quirks
+and limitations of the current implementation and information on how to deal
+with them.
.PP
.B Debugging.
There's no symbolic debugger yet. So
@@ -1558,30 +1580,31 @@
convenience.
.PP
.B With or when?
-A common source of confusion for Haskell renegades is that Pure provides two
+A common source of confusion for Haskellers is that Pure provides two
different constructs to bind local function and variable symbols,
-respectively, namely
-.BR with ,
-which is used for local function definitions, and
-.BR when ,
-which binds local variables. This distinction is necessary because Pure does
-not segregate defined functions and constructors, and thus there is no magic
-to figure out whether an equation like `foo x = y' by itself is meant as a
-definition of a function foo with formal parameter x and return value y, or a
-definition binding the local variable x by matching the constructor pattern
-foo x against the value y. The
+respectively. This distinction is necessary because Pure does not segregate
+defined functions and constructors, and thus there is no magic to figure out
+whether an equation like `foo x = y' by itself is meant as a definition of a
+function foo with formal parameter x and return value y, or a definition
+binding the local variable x by matching the constructor pattern foo x against
+the value y. The
.B with
construct does the former,
.B when
the latter.
.PP
-Another pitfall is that, since
+Another pitfall is that
.B with
and
.B when
-clauses are tacked on to the end of the expression they belong to, they have
-to be read in reverse, if you want to figure out what is actually going on
-there. Also note that since
+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).
+.PP
+Also note that since
.B with
and
.B when
@@ -1625,16 +1648,17 @@
constant like `0' only matches machine integers, not bigints; for the latter
you'll have to use the ``big L'' notation `0L'.
.PP
-.B Working with constants.
+.B Constant definitions.
When definining a function in terms of constant values which have to be
-computed beforehand, it's usually better to use a constant symbol (rather than
-a variable or a parameterless function) for that purpose, since this will
-often allow the compiler to generate better code using constant folding and
-similar techniques. Example:
+computed beforehand, it's usually better to use a
+.B const
+definition (rather than defining a variable or a parameterless function) for
+that purpose, since this will often allow the compiler to generate better code
+using constant folding and similar techniques. Example:
.sp
.nf
> \fBextern\fP double atan(double);
-> \fBdef\fP pi = 4*atan 1.0;
+> \fBconst\fP pi = 4*atan 1.0;
> foo x = 2*pi*x;
> \fBlist\fP foo
foo x = 2*3.14159265358979*x;
@@ -1648,47 +1672,46 @@
different environments, without any runtime penalties:
.sp
.nf
-> \fBdef\fP running_on_windows = index sysinfo "mingw32" >= 0;
-> foo x = something x \fBif\fP running_on_windows;
-> = something_else x \fBotherwise\fP;
+\fBconst\fP win = index sysinfo "mingw32" >= 0;
+check boy = bad boy \fBif\fP win;
+ = good boy \fBotherwise\fP;
.fi
.PP
-In this case the code for one of the branches of foo will be completely
-eliminated, depending on whether your script runs on Windows or not.
+In this case the code for one of the branches of `check' will be completely
+eliminated, depending on the outcome of the configuration check.
.PP
On the other hand, constant definitions are somewhat limited in scope compared
-to variable definitions, since the value bound to the constant symbol must be
-usable at compile time, so that it can be substituted into other
-definitions. Thus, while there is no \fIa priori\fP restriction on the
-computations you can perform to obtain the value of the constant, the value
-must not be a pointer object (other than the null pointer), or an anonymous
-closure (which also rules out local functions, because these cannot be
-referred to by their names at the toplevel), or an aggregate value containing
-any such values.
+to variable definitions, since the bound value must be usable at compile time,
+so that it can be substituted into other definitions. Thus, while there is no
+\fIa priori\fP restriction on the computations you can perform to obtain the
+value of the constant, the value must not be a pointer object (other than the
+null pointer), or an anonymous closure (which also rules out local functions,
+because these cannot be referred to by their names at the toplevel), or an
+aggregate value containing any such values.
.PP
-Constant symbols also differ from variables in that they cannot be redefined
-(that's their purpose after all) and will only take effect on subsequent
+Constants also differ from variables in that they cannot be redefined (that's
+their purpose after all) and will only take effect on subsequent
definitions. E.g.:
.sp
.nf
-> \fBdef\fP c = 2;
+> \fBconst\fP c = 2;
> foo x = c*x;
> \fBlist\fP foo
foo x = 2*x;
> foo 99;
198
-> \fBdef\fP c = 3;
+> \fBconst\fP c = 3;
<stdin>:5.0-8: symbol 'c' is already defined as a constant
.fi
.PP
Well, in fact this not the full truth because in interactive mode it \fIis\fP
-possible to redefine constant symbols after all, if the old definition is
-first purged with the \fBclear\fP command. However, this won't affect any
-other existing definitions:
+possible to redefine constants after all, if the old definition is first
+purged with the \fBclear\fP command. However, this won't affect any other
+existing definitions:
.sp
.nf
> \fBclear\fP c
-> \fBdef\fP c = 3;
+> \fBconst\fP c = 3;
> bar x = c*x;
> \fBlist\fP foo bar
foo x = 2*x;
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ag...@us...> - 2008-08-19 12:19:45
|
Revision: 543
http://pure-lang.svn.sourceforge.net/pure-lang/?rev=543&view=rev
Author: agraef
Date: 2008-08-19 12:19:54 +0000 (Tue, 19 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-19 11:46:50 UTC (rev 542)
+++ pure/trunk/pure.1.in 2008-08-19 12:19:54 UTC (rev 543)
@@ -589,16 +589,15 @@
.PP
So, while the meaning of a local symbol never changes once its definition has
been processed, the definition of global functions and variables may well
-evolve while the program is being processed. When you evaluate an expression
-(to print its value, or to bind it to a variable symbol), the interpreter will
-always use the
+evolve while the program is being processed. When you evaluate an expression,
+the interpreter will always use the
.I latest
definitions of all global constants, variables and functions used in the
expression, up to the current point in the source where the expression is
-evaluated. Thus you have to make sure that, when you evaluate an expression,
-all the functions, constants and variables it uses have already been defined
-at this point in the source (no matter whether the source is being entered
-interactively, or read from a script).
+evaluated. (This also applies to scripts read from a file, thus you have to
+make sure that all required functions, constants and variables have been
+defined at each point in a script where an expression is evaluated or assigned
+to a global variable or constant.)
.PP
.B Examples.
Here are a few examples of simple Pure programs (see the following section for
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ag...@us...> - 2008-08-20 01:14:13
|
Revision: 544
http://pure-lang.svn.sourceforge.net/pure-lang/?rev=544&view=rev
Author: agraef
Date: 2008-08-20 01:14:23 +0000 (Wed, 20 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-19 12:19:54 UTC (rev 543)
+++ pure/trunk/pure.1.in 2008-08-20 01:14:23 UTC (rev 544)
@@ -456,7 +456,7 @@
following prompt/input interaction:
.sp
.nf
-> using system;
+> \fBusing\fP system;
> puts "Enter a number:" $$ scanf "%g";
Enter a number:
21
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ag...@us...> - 2008-08-20 14:12:01
|
Revision: 550
http://pure-lang.svn.sourceforge.net/pure-lang/?rev=550&view=rev
Author: agraef
Date: 2008-08-20 14:12:10 +0000 (Wed, 20 Aug 2008)
Log Message:
-----------
Fix typo.
Modified Paths:
--------------
pure/trunk/pure.1.in
Modified: pure/trunk/pure.1.in
===================================================================
--- pure/trunk/pure.1.in 2008-08-20 09:07:48 UTC (rev 549)
+++ pure/trunk/pure.1.in 2008-08-20 14:12:10 UTC (rev 550)
@@ -725,7 +725,7 @@
(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
+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:
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ag...@us...> - 2008-08-20 18:58:30
|
Revision: 551
http://pure-lang.svn.sourceforge.net/pure-lang/?rev=551&view=rev
Author: agraef
Date: 2008-08-20 18:58:40 +0000 (Wed, 20 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-20 14:12:10 UTC (rev 550)
+++ pure/trunk/pure.1.in 2008-08-20 18:58:40 UTC (rev 551)
@@ -188,12 +188,15 @@
with additional debugging information.
.SH PURE OVERVIEW
.PP
-Pure is a fairly simple language. Programs are collections of equational rules
-defining functions, \fBconst\fP and \fBlet\fP commands binding global
-constants and variables, and expressions to be evaluated. Here's a simple
-example, entered interactively in the interpreter (note that the ``>'' symbol
-at the beginning of each input line is the interpreter's default command
-prompt):
+Pure is a fairly simple but very powerful language. Programs are collections
+of equational rules defining functions, and expressions to be
+evaluated. Moreover, the \fBconst\fP and \fBlet\fP commands can be used to
+assign the value of an expression to a global constant or a variable,
+respectively.
+.PP
+Here's a simple example, entered interactively in the interpreter (note that
+the ``>'' symbol at the beginning of each input line is the interpreter's
+default command prompt):
.sp
.nf
> // my first Pure example
@@ -212,10 +215,10 @@
order to turn it into an executable program.
.PP
On the surface, Pure is quite similar to other modern functional languages
-like Haskell and ML. But under the hood it is a much more dynamic and
-reflective language, more akin to Lisp. In particular, Pure is dynamically
-typed, so functions can be fully polymorphic and you can add to the definition
-of an existing function at any time:
+like Haskell and ML. But under the hood it is a much more dynamic language,
+more akin to Lisp. In particular, Pure is dynamically typed, so functions can
+be fully polymorphic and you can add to the definition of an existing function
+at any time:
.sp
.nf
> fact 1.0 = 1.0;
@@ -225,11 +228,26 @@
> fact 10;
3628800
.fi
+.PP
+Like in Haskell and ML, functions and variables are often defined by
+.IR pattern-matching ,
+i.e., the left-hand side of a definition is compared to the target expression,
+binding the variables in the pattern to their actual values accordingly:
.sp
-Also, due to its term rewriting semantics, Pure can do symbolic evaluations:
+.nf
+> foo (bar x) = x-1;
+> foo (bar 99);
+98
+.fi
+.PP
+However, 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
.nf
> square x = x*x;
+> square 4;
+16
> square (a+b);
(a+b)*(a+b)
.fi
@@ -241,7 +259,14 @@
which represents the ``value'' of the original expression. Keeping with the
tradition of term rewriting, there's no distinction between ``defined'' and
``constructor'' function symbols in Pure; any function symbol (or operator)
-also acts as a constructor if it happens to occur in a normal form term.
+also acts as a constructor if it happens to occur in a normal form term:
+.sp
+.nf
+> (x+y)*z = x*z+y*z; x*(y+z) = x*y+x*z;
+> x*(y*z) = (x*y)*z; x+(y+z) = (x+y)+z;
+> square (a+b);
+a*a+a*b+b*a+b*b
+.fi
.PP
Expressions are generally evaluated from left to right, innermost expressions
first, i.e., using
@@ -252,7 +277,6 @@
.I "call by name"
semantics.
.PP
-.B Expression syntax.
The Pure language provides built-in support for machine integers (32 bit),
bigints (implemented using GMP), floating point values (double precision
IEEE), character strings (UTF-8 encoded) and generic C pointers (these don't
@@ -263,6 +287,7 @@
and any non-zero value
.BR true ).
.PP
+.B Expression syntax.
Expressions consist of the following elements:
.TP
.B Constants: \fR4711, 4711L, 1.2e-3, \(dqHello,\ world!\en\(dq
@@ -539,11 +564,11 @@
though. Like many languages which are to be used interactively, Pure binds
global symbols
.IR dynamically ,
-so that they can be changed easily at any time during an interactive
+so that the bindings can be changed easily at any time during an interactive
session. This is mainly a convenience for interactive usage, but works the
same no matter whether the source code is entered interactively or being read
-from a script, in order to ensure consistent behaviour between interactive
-and batch mode operation.
+from a script, in order to ensure consistent behaviour between interactive and
+batch mode operation.
.PP
So, for instance, you can easily bind a global variable to a new value by just
entering a corresponding
@@ -1046,12 +1071,12 @@
the human reader; they are effectively treated as comments by the compiler.
.PP
The interpreter makes sure that the parameters in a call match; if not, the
-call is treated as a normal form expression by default, which enables you to
-extend the external function with your own Pure equations (see below). The
-range of supported C types is a bit limited right now (void, bool, char,
-short, int, long, float, double, as well as arbitrary pointer types, i.e.:
-void*, char*, etc.), but in practice these should cover most kinds of calls
-that need to be done when interfacing to C libraries.
+call is treated as a normal form expression by default, which gives you the
+opportunity to extend the external function with your own Pure equations (see
+below). The range of supported C types is a bit limited right now (void, bool,
+char, short, int, long, float, double, as well as arbitrary pointer types,
+i.e.: void*, char*, etc.), but in practice these should cover most kinds of
+calls that need to be done when interfacing to C libraries.
.PP
Single precision float arguments and return values are converted from/to
Pure's double precision floating point numbers automatically.
@@ -1131,8 +1156,8 @@
the symbol in the C library and Pure's runtime library (or the interpreter
executable, if the interpreter was linked statically). Thus all C library and
Pure runtime functions are readily available in Pure programs. Other functions
-can be provided by including them in the runtime, or by linking the
-interpreter against the corresponding modules. Or, better yet, you can just
+can be provided by adding them to the runtime, or by linking them statically
+into the runtime or the interpreter executable. Better yet, you can just
``dlopen'' shared libraries at runtime with a special form of the
.B using
clause:
@@ -1411,37 +1436,39 @@
.SH DEFINITION LEVELS AND OVERRIDE MODE
To help with incremental development, the interpreter also offers some
facilities to manipulate the current set of definitions interactively. To
-these ends, defined symbols and their definitions are organized into different
-subsets called \fIlevels\fP. The prelude, as well as other source programs
-specified when invoking the interpreter, are always at level 0, while the
-interactive environment starts at level 1.
+these ends, definitions are organized into different subsets called
+\fIlevels\fP. The prelude, as well as other source programs specified when
+invoking the interpreter, are always at level 0, while the interactive
+environment starts at level 1.
.PP
Each \fBsave\fP command introduces a new temporary level, and each subsequent
-\fBclear\fP command ``pops'' the symbols and definitions on the current level
-(including any definitions read using the
+\fBclear\fP command ``pops'' the definitions on the current level (including
+any definitions read using the
.B run
-command) and returns you to the previous one. 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:
+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:
.sp
.nf
-> \fBsave\fP
-save: now at temporary definitions level #2
> foo (x:xs) = x+foo xs;
> foo [] = 0;
-> \fBlist\fP foo
+> \fBlist\fP -t
foo (x:xs) = x+foo xs;
foo [] = 0;
> foo (1..10);
55
> \fBclear\fP
-This will clear all temporary definitions at level #2. Continue (y/n)? y
-clear: now at temporary definitions level #1
+This will clear all temporary definitions at level #1. Continue (y/n)? y
> \fBlist\fP foo
> foo (1..10);
foo [1,2,3,4,5,6,7,8,9,10]
.fi
.PP
+(Please note that the
+.B clear
+command only works in this way when invoked without arguments. Otherwise the
+symbols given as arguments will be purged unconditionally, at all levels.)
+.PP
We've seen already that normally, if you enter a sequence of equations, they
will be recorded in the order in which they were written. However, it is also
possible to override definitions in lower levels with the
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ag...@us...> - 2008-08-22 11:09:16
|
Revision: 568
http://pure-lang.svn.sourceforge.net/pure-lang/?rev=568&view=rev
Author: agraef
Date: 2008-08-22 11:09:24 +0000 (Fri, 22 Aug 2008)
Log Message:
-----------
Final touches (0.5 release).
Modified Paths:
--------------
pure/trunk/pure.1.in
Modified: pure/trunk/pure.1.in
===================================================================
--- pure/trunk/pure.1.in 2008-08-22 10:39:04 UTC (rev 567)
+++ pure/trunk/pure.1.in 2008-08-22 11:09:24 UTC (rev 568)
@@ -1,4 +1,4 @@
-.TH Pure 1 "June 2008" "Pure Version @version@"
+.TH Pure 1 "August 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-08-24 23:46:49
|
Revision: 604
http://pure-lang.svn.sourceforge.net/pure-lang/?rev=604&view=rev
Author: agraef
Date: 2008-08-24 23:46:59 +0000 (Sun, 24 Aug 2008)
Log Message:
-----------
Add some remarks about the purity of Pure.
Modified Paths:
--------------
pure/trunk/pure.1.in
Modified: pure/trunk/pure.1.in
===================================================================
--- pure/trunk/pure.1.in 2008-08-24 12:59:31 UTC (rev 603)
+++ pure/trunk/pure.1.in 2008-08-24 23:46:59 UTC (rev 604)
@@ -1545,10 +1545,24 @@
> \fBunderride\fP
.fi
.SH CAVEATS AND NOTES
-This section is a grab bag of useful tips and tricks, common pitfalls, quirks
-and limitations of the current implementation and information on how to deal
-with them.
+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.
+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
+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.
+.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. :)
+.PP
.B Debugging.
There's no symbolic debugger yet. So
.BR printf (3)
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ag...@us...> - 2008-08-25 20:26:41
|
Revision: 608
http://pure-lang.svn.sourceforge.net/pure-lang/?rev=608&view=rev
Author: agraef
Date: 2008-08-25 20:24:03 +0000 (Mon, 25 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-25 19:56:07 UTC (rev 607)
+++ pure/trunk/pure.1.in 2008-08-25 20:24:03 UTC (rev 608)
@@ -191,8 +191,9 @@
Pure is a fairly simple but very powerful language. Programs are collections
of equational rules defining functions, and expressions to be
evaluated. Moreover, the \fBconst\fP and \fBlet\fP commands can be used to
-assign the value of an expression to a global constant or a variable,
-respectively.
+assign the value of an expression to a global constant or a variable, and the
+\fBdef\fP command can be used to define macros (a kind of ``preprocessing''
+functions to be executed at compile time).
.PP
Here's a simple example, entered interactively in the interpreter (note that
the ``>'' symbol at the beginning of each input line is the interpreter's
@@ -504,6 +505,16 @@
treats this as a comment). Pure also provides some abbreviations for factoring
out common left-hand or right-hand sides in collections of rules; see section
RULE SYNTAX below for details.
+.sp
+A rule starting with the keyword
+.B def
+defines a
+.I macro
+function. Such functions are executed at compile time to rewrite expression on
+the right-hand side of other definitions, and are typically used to handle
+user-defined special forms and simple kinds of optimizations to be performed
+at ``preprocessing'' time. Macro rules are described in their own section, see
+MACROS below.
.TP
.B Global variable bindings: let\fR \fIlhs\fR = \fIrhs\fR;
Binds every variable in the left-hand side pattern to the corresponding
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ag...@us...> - 2008-08-25 20:27:27
|
Revision: 610
http://pure-lang.svn.sourceforge.net/pure-lang/?rev=610&view=rev
Author: agraef
Date: 2008-08-25 20:27:34 +0000 (Mon, 25 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-25 20:25:57 UTC (rev 609)
+++ pure/trunk/pure.1.in 2008-08-25 20:27:34 UTC (rev 610)
@@ -835,6 +835,8 @@
.nf
\fBcase\fP ans \fBof\fP "y" | "Y" = 1; _ = 0; \fBend\fP;
.fi
+.SH MACROS
+To be written.
.SH DECLARATIONS
As you probably noticed, Pure is very terse. That's because, in contrast to
hopelessly verbose languages like Java, you don't declare much stuff in Pure,
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ag...@us...> - 2008-08-25 23:55:57
|
Revision: 611
http://pure-lang.svn.sourceforge.net/pure-lang/?rev=611&view=rev
Author: agraef
Date: 2008-08-25 23:56:04 +0000 (Mon, 25 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-25 20:27:34 UTC (rev 610)
+++ pure/trunk/pure.1.in 2008-08-25 23:56:04 UTC (rev 611)
@@ -494,7 +494,7 @@
functions (also called ``rules''), constant and variable bindings, and
expressions to be evaluated:
.TP
-.B Rules: \fIlhs\fR = \fIrhs\fR;
+.B Rules: \fIlhs\fR = \fIrhs\fR; \fBdef\fR \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
@@ -734,14 +734,14 @@
.SH RULE SYNTAX
Basically, the same rule syntax is used to define functions at the toplevel
and in \fBwith\fP expressions, as well as inside \fBcase\fP, \fBwhen\fP,
-\fBlet\fP and \fBconst\fP constructs for the purpose of binding variable values
-(however, for obvious reasons guards are not permitted in \fBwhen\fP,
-\fBlet\fP and \fBconst\fP clauses). When matching against a function 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.)
+\fBlet\fP and \fBconst\fP constructs for the purpose of binding variable
+values (however, for obvious reasons guards are not permitted in \fBwhen\fP,
+\fBlet\fP and \fBconst\fP clauses). When matching against a function 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 must not contain repeated variables
(i.e., rules must be ``left-linear''), except for the anonymous variable `_'
@@ -836,7 +836,125 @@
\fBcase\fP ans \fBof\fP "y" | "Y" = 1; _ = 0; \fBend\fP;
.fi
.SH MACROS
-To be written.
+As already mentioned, macros are a special type of functions to be executed as
+a kind of ``preprocessing stage'' at compile time. They are useful for many
+things, such as the definition of user-defined special forms and optimization
+rules to be applied to the source program in its symbolic form.
+.PP
+Whereas the macro facilities of most programming languages simply provide a
+kind of textual substitution mechanism, Pure macros operate on symbolic
+expressions and are implemented by the same kind of rewriting rules that are
+also used to define ordinary functions in Pure. However, macro rules start out
+with the keyword
+.BR def ,
+and only simple kinds of rules without any guards or multiple left-hand and
+right-hand sides are permitted. Thus, syntactically, a macro definition looks
+just like a variable or constant definition, using
+.B def
+in lieu of
+.B let
+or
+.BR const ,
+but they are processed in an entirely different way.
+.PP
+Macros are substituted into the right-hand sides of function, constant and
+variable definitions, pretty much like constants are substituted into
+definitions. All macro substitution happens before constant substitutions and
+the actual compilation step.
+.PP
+Here is a simple example, showing a rule which expands saturated calls of the
+.B succ
+function (defined in the prelude) at compile time:
+.sp
+.nf
+> \fBdef\fP succ x = x+1;
+> foo x::int = succ (succ x);
+> \fBlist\fP foo
+foo x::int = x+1+1;
+.fi
+.PP
+This can be useful to help the compiler generate better code. (E.g., if you
+have a look at the assembler code for the above function, you'll see that it's
+basically just a single integer increment instruction, plus the usual
+(un)boxing of the integer argument and the result value.)
+.PP
+Note that a macro may have the same name as an ordinary Pure function, which
+is useful for optimizing calls to an existing Pure function, as shown in the
+example above. As a slightly more practical example, as of Pure 0.6 the
+following rule has been added to the prelude to eliminate saturated function
+compositions:
+.sp
+.nf
+\fBdef\fP (f.g) x = f (g x);
+.fi
+.sp
+Example:
+.sp
+.nf
+> foo x = (succ.succ) x;
+> \fBlist\fP foo
+foo x = x+1+1;
+.fi
+.PP
+Macros can also be recursive, 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)));
+> \fBlist\fP baz
+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 arbitrarily complex Pure expression involving
+conditional expressions, binding clauses, etc., but these are
+.I not
+be 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:
+.sp
+.nf
+> using system;
+> \fBdef\fP timex x = (clock-t0)/CLOCKS_PER_SEC,y \fBwhen\fP t0 = clock; y = x \fBend\fP;
+> sum = foldl (+) 0;
+> timex $ sum (1..100000);
+0.21,705082704
+.fi
+.PP
+The `timex' macro also provides a useful example of how you can use macros to
+define your own special forms, since macro arguments are always called by
+name. (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.)
+.PP
+A final remark about the scoping rules used in macros is in order. Pure macros
+are lexically scoped, i.e., symbols on the right-hand-side of a macro
+definition can never refer to anything outside of the macro definition, and
+macro parameter substitution also takes into account binding constructs, such
+as
+.B with
+and
+.B when
+clauses, in the right-hand side of the definition. Macro facilities with these
+properties are also known as
+.I hygienic
+macros. They are not susceptible to so-called ``name capture,'' which makes
+macros in less sophisticated languages bug-ridden, hard to use and mostly
+useless.
+.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. In other words, macros are a good way to shoot yourself in the foot. So
+use them with care, ``or else!''
.SH DECLARATIONS
As you probably noticed, Pure is very terse. That's because, in contrast to
hopelessly verbose languages like Java, you don't declare much stuff in Pure,
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ag...@us...> - 2008-08-26 09:43:22
|
Revision: 617
http://pure-lang.svn.sourceforge.net/pure-lang/?rev=617&view=rev
Author: agraef
Date: 2008-08-26 09:43:31 +0000 (Tue, 26 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-26 00:24:38 UTC (rev 616)
+++ pure/trunk/pure.1.in 2008-08-26 09:43:31 UTC (rev 617)
@@ -188,16 +188,16 @@
with additional debugging information.
.SH PURE OVERVIEW
.PP
-Pure is a fairly simple but very powerful language. Programs are collections
-of equational rules defining functions, and expressions to be
-evaluated. Moreover, the \fBconst\fP and \fBlet\fP commands can be used to
-assign the value of an expression to a global constant or a variable, and the
-\fBdef\fP command can be used to define macros (a kind of ``preprocessing''
-functions to be executed at compile time).
+Pure is a fairly simple yet powerful language. Programs are basically
+collections of rewriting rules and expressions to be evaluated. For
+convenience, it is also possible to define global variables and constants, and
+for advanced uses Pure offers macro functions as a kind of preprocessing
+facility. These are all described below and in the following sections.
.PP
-Here's a simple example, entered interactively in the interpreter (note that
-the ``>'' symbol at the beginning of each input line is the interpreter's
-default command prompt):
+Here's a first example which demonstrates how to define a simple recursive
+function in Pure, entered interactively in the interpreter (note that the
+``>'' symbol at the beginning of each input line is the interpreter's default
+command prompt):
.sp
.nf
> // my first Pure example
@@ -215,6 +215,15 @@
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 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
+in fact they are, only that the specifications are executable). This is
+intended and keeps the code tidy and clean.
+.PP
On the surface, Pure is quite similar to other modern functional languages
like Haskell and ML. But under the hood it is a much more dynamic language,
more akin to Lisp. In particular, Pure is dynamically typed, so functions can
@@ -274,9 +283,11 @@
.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 using
-.I "call by name"
-semantics.
+the sequencing operator $$) which take some of their arguments unevaluated,
+using
+.IR "call by name" .
+(User-defined special forms can be created with macros. More about that
+later.)
.PP
The Pure language provides built-in support for machine integers (32 bit),
bigints (implemented using GMP), floating point values (double precision
@@ -490,11 +501,11 @@
.fi
.PP
.B Toplevel.
-At the toplevel, a Pure program basically consists of equations defining
-functions (also called ``rules''), constant and variable bindings, and
-expressions to be evaluated:
+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; \fBdef\fR \fIlhs\fR = \fIrhs\fR;
+.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
@@ -505,22 +516,23 @@
treats this as a comment). Pure also provides some abbreviations for factoring
out common left-hand or right-hand sides in collections of rules; see section
RULE SYNTAX below for details.
-.sp
+.TP
+.B Macro rules: def\fR \fIlhs\fR = \fIrhs\fR;
A rule starting with the keyword
.B def
defines a
.I macro
-function. Such functions are executed at compile time to rewrite expression on
-the right-hand side of other definitions, and are typically used to handle
-user-defined special forms and simple kinds of optimizations to be performed
-at ``preprocessing'' time. Macro rules are described in their own section, see
-MACROS below.
+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
+MACROS section below for details and examples.
.TP
.B Global variable bindings: let\fR \fIlhs\fR = \fIrhs\fR;
Binds every variable in the left-hand side pattern to the corresponding
-subterm of the evaluated right-hand side. 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.
+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;
An alternative form of \fBlet\fP which defines constants rather than
@@ -528,7 +540,7 @@
.B nullary
symbols which simply stand for themselves!) Like \fBlet\fP, this construct
binds the variable symbols on the left-hand side to the corresponding values
-on the evaluated right-hand side. The difference is that
+on the right-hand side (after evaluation). The difference is that
.B const
symbols can only be defined once, after which their values are substituted
directly into the right-hand sides of other definitions, rather than being
@@ -597,11 +609,11 @@
.fi
.PP
This works pretty much like global variables in imperative languages, but note
-that in Pure the value of a global variable can \fInot\fP be changed inside a
-function definition. Thus referential transparency is unimpaired; while the
-value of an expression depending on a global variable may change between
-different computations, the variable will always take the same value in a
-single evaluation.
+that in Pure the value of a global variable can \fIonly\fP be changed with a
+.B let
+command at the toplevel. Thus referential transparency is unimpaired; while
+the value of a global variable may change between different toplevel
+expressions, it will always take the same value in a single evaluation.
.PP
Similarly, you can also add new equations to an existing function at any time:
.sp
@@ -620,20 +632,18 @@
3628800
.fi
.PP
-(In interactive mode, it is even possible to completely erase constant,
-variable and function definitions. See section INTERACTIVE USAGE for details.)
+(In interactive mode, it is even possible to completely erase a definition,
+see section INTERACTIVE USAGE for details.)
.PP
So, while the meaning of a local symbol never changes once its definition has
-been processed, the definition of global functions and variables may well
-evolve while the program is being processed. When you evaluate an expression,
-the interpreter will always use the
+been processed, toplevel definitions may well evolve while the program is
+being processed, and the interpreter will always use the
.I latest
-definitions of all global constants, variables and functions used in the
-expression, up to the current point in the source where the expression is
-evaluated. (This also applies to scripts read from a file, thus you have to
-make sure that all required functions, constants and variables have been
-defined at each point in a script where an expression is evaluated or assigned
-to a global variable or constant.)
+definitions at a given point in the source when an expression is
+evaluated. This means that, even in a script file, you have to define all
+symbols needed in an evaluation
+.I before
+entering the expression to be evaluated.
.PP
.B Examples.
Here are a few examples of simple Pure programs (see the following section for
@@ -732,27 +742,27 @@
\fBend\fP;
.fi
.SH RULE SYNTAX
-Basically, the same rule syntax is used to define functions at the toplevel
-and in \fBwith\fP expressions, as well as inside \fBcase\fP, \fBwhen\fP,
-\fBlet\fP and \fBconst\fP constructs for the purpose of binding variable
-values (however, for obvious reasons guards are not permitted in \fBwhen\fP,
-\fBlet\fP and \fBconst\fP clauses). When matching against a function 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.)
+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 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 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.)
+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.)
.PP
Pure also supports Haskell-style ``as'' patterns of the form
.IB variable @ pattern
@@ -836,32 +846,34 @@
\fBcase\fP ans \fBof\fP "y" | "Y" = 1; _ = 0; \fBend\fP;
.fi
.SH MACROS
-As already mentioned, macros are a special type of functions to be executed as
-a kind of ``preprocessing stage'' at compile time. They are useful for many
-things, such as the definition of user-defined special forms and optimization
-rules to be applied to the source program in its symbolic form.
+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.
.PP
Whereas the macro facilities of most programming languages simply provide a
kind of textual substitution mechanism, Pure macros operate on symbolic
expressions and are implemented by the same kind of rewriting rules that are
-also used to define ordinary functions in Pure. However, macro rules start out
-with the keyword
+also used to define ordinary functions in Pure. In difference to these, macro
+rules start out with the keyword
.BR def ,
and only simple kinds of rules without any guards or multiple left-hand and
-right-hand sides are permitted. Thus, syntactically, a macro definition looks
-just like a variable or constant definition, using
+right-hand sides are permitted.
+.PP
+Syntactically, a macro definition looks just like a variable or constant
+definition, using
.B def
in lieu of
.B let
or
.BR const ,
-but they are processed in an entirely different way.
+but they are processed in a different way. Macros are substituted into the
+right-hand sides of function, constant and variable definitions. All macro
+substitution happens before constant substitutions and the actual compilation
+step. Macros can be defined in terms of other macros (also recursively), and
+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
-Macros are substituted into the right-hand sides of function, constant and
-variable definitions, pretty much like constants are substituted into
-definitions. All macro substitution happens before constant substitutions and
-the actual compilation step.
-.PP
Here is a simple example, showing a rule which expands saturated calls of the
.B succ
function (defined in the prelude) at compile time:
@@ -873,27 +885,44 @@
foo x::int = x+1+1;
.fi
.PP
-This can be useful to help the compiler generate better code. (E.g., if you
-have a look at the assembler code for the above function, you'll see that it's
-basically just a single integer increment instruction, plus the usual
-(un)boxing of the integer argument and the result value.)
+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):
+.sp
+.nf
+> \fBlist\fP -d foo
+.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:
+.sp
+.nf
+ ...
+ %intval = load i32* %1 ; <i32> [#uses=1]
+ add i32 %intval, 2 ; <i32>:2 [#uses=1]
+ ...
+.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 Pure function, as shown in the
-example above. As a slightly more practical example, as of Pure 0.6 the
-following rule has been added to the prelude to eliminate saturated function
-compositions:
+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:
.sp
.nf
-\fBdef\fP (f.g) x = f (g x);
+\fBdef\fP f $ x = f x;
.fi
.sp
-Example:
+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
-> foo x = (succ.succ) x;
+> foo x = bar $ bar $ 2*x;
> \fBlist\fP foo
-foo x = x+1+1;
+foo x = bar (bar (2*x));
.fi
.PP
Macros can also be recursive, consist of multiple rules and make use of
@@ -910,59 +939,58 @@
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 arbitrarily complex Pure expression involving
-conditional expressions, binding clauses, etc., but these are
+right-hand side may be an arbitrary Pure expression involving conditional
+expressions, lambdas, binding clauses, etc., but these are
.I not
-be evaluated during macro substitution, they just become part of the macro
+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:
.sp
.nf
-> using system;
+> \fBusing\fP system;
> \fBdef\fP timex x = (clock-t0)/CLOCKS_PER_SEC,y \fBwhen\fP t0 = clock; y = x \fBend\fP;
-> sum = foldl (+) 0;
-> timex $ sum (1..100000);
-0.21,705082704
+> sum = foldl (+) 0L;
+> timex $ sum (1L..100000L);
+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 macro arguments are always called by
-name. (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 (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.)
.PP
-A final remark about the scoping rules used in macros is in order. Pure macros
-are lexically scoped, i.e., symbols on the right-hand-side of a macro
-definition can never refer to anything outside of the macro definition, and
-macro parameter substitution also takes into account binding constructs, such
-as
+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 with
and
.B when
clauses, in the right-hand side of the definition. Macro facilities with these
-properties are also known as
+pleasant properties are also known as
.I hygienic
macros. They are not susceptible to so-called ``name capture,'' which makes
-macros in less sophisticated languages bug-ridden, hard to use and mostly
-useless.
+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. In other words, macros are a good way to shoot yourself in the foot. So
-use them with care, ``or else!''
+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.
.SH DECLARATIONS
-As you probably noticed, Pure is very terse. 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,
+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,
.B extern
declarations for external C functions (described in the C INTERFACE section),
and
@@ -1005,8 +1033,8 @@
Causes each given script to be included, at the position of the
.B using
clause, but only if the script was not included already. Note that the
-constants, variables and functions defined by the included script are then
-available anywhere in the program, not just the module that contains 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
.B using
clause.
.sp
@@ -1375,8 +1403,8 @@
Change the current working dir.
.TP
.B "clear \fR[\fIsymbol\fP ...]\fP"
-Purge the definitions of the given symbols (functions, constants or global
-variables). If no symbols are given, purge \fIall\fP definitions (after
+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
.B save
command (or the beginning of the interactive session). See the DEFINITION
@@ -1490,6 +1518,9 @@
Long format, prints definitions along with the summary symbol information.
This implies \fB-s\fP.
.TP
+.B -m
+Print information about defined macros.
+.TP
.B -s
Summary format, print just summary information about listed symbols.
.TP
@@ -1507,11 +1538,12 @@
.PP
If none of the
.BR -c ,
-.B -f
+.BR -f ,
+.B -m
and
.B -v
-options are specified, then all kinds of symbols (constants, functions,
-variables) are printed, otherwise only the specified categories will be
+options are specified, then all kinds of symbols (constants, functions, macros
+and variables) are printed, otherwise only the specified categories will be
listed.
.PP
Note that some of the options (in particular,
@@ -1823,9 +1855,9 @@
When definining a function in terms of constant values which have to be
computed beforehand, it's usually better to use a
.B const
-definition (rather than defining a variable or a parameterless function) for
-that purpose, since this will often allow the compiler to generate better code
-using constant folding and similar techniques. Example:
+definition (rather than defining a variable or a parameterless function or
+macro) for that purpose, since this will often allow the compiler to generate
+better code using constant folding and similar techniques. Example:
.sp
.nf
> \fBextern\fP double atan(double);
@@ -1836,13 +1868,26 @@
.fi
.PP
(If you take a look at the disassembled code for this function, you will find
-that the value 2*3.14159265358979 has actually been computed at compile time.)
+that the value 2*3.14159265358979 = 6.28318530717959 has actually been
+computed at compile time.)
.PP
-Also, the LLVM backend will eliminate dead code automagically, which enables
-you to employ a constant computed at runtime to configure your code for
-different environments, without any runtime penalties:
+Note that constant definitions differ from parameterless macros in that the
+right-hand side of the definition is in fact evaluated at compile time. E.g.,
+compare the above with the following macro definition:
.sp
.nf
+> \fBclear\fP pi foo
+> \fBdef\fP pi = 4*atan 1.0;
+> foo x = 2*pi*x;
+> \fBlist\fP foo
+foo x = 2*(4*atan 1.0)*x;
+.fi
+.PP
+The LLVM backend also eliminates dead code automagically, which enables you to
+employ a constant computed at runtime to configure your code for different
+environments, without any runtime penalties:
+.sp
+.nf
\fBconst\fP win = index sysinfo "mingw32" >= 0;
check boy = bad boy \fBif\fP win;
= good boy \fBotherwise\fP;
@@ -1892,7 +1937,7 @@
(You'll also have to purge any existing definition of a variable if you want
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.)
+holds if a symbol is currently defined as a function or a macro.)
.PP
.B External C functions.
The interpreter always takes your
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|