[pure-lang-svn] SF.net SVN: pure-lang:[850] pure/trunk/pure.1.in
Status: Beta
Brought to you by:
agraef
From: <ag...@us...> - 2008-09-25 00:54:41
|
Revision: 850 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=850&view=rev Author: agraef Date: 2008-09-25 00:54:30 +0000 (Thu, 25 Sep 2008) Log Message: ----------- Update documentation. Modified Paths: -------------- pure/trunk/pure.1.in Modified: pure/trunk/pure.1.in =================================================================== --- pure/trunk/pure.1.in 2008-09-24 13:08:16 UTC (rev 849) +++ pure/trunk/pure.1.in 2008-09-25 00:54:30 UTC (rev 850) @@ -336,6 +336,8 @@ .B false and any non-zero value .BR true ). +Pure also provides some built-in support for lists and matrices, although most +of the corresponding operations are actually defined in the prelude. .SS Expression Syntax Expressions consist of the following elements: .TP @@ -430,15 +432,48 @@ tuple 1,2, the integer 3, and another tuple 4,5. Likewise, [(1,2,3)] is list with a single element, the tuple 1,2,3. .TP -\fBList comprehensions:\fP [x,y; x = 1..n; y = 1..m; x<y] -Pure also has list comprehensions which generate lists from an expression and -one or more ``generator'' and ``filter'' clauses (the former bind a pattern to -values drawn from a list, the latter are just predicates determining which -generated elements should actually be added to the output list). List -comprehensions are in fact syntactic sugar for a combination of nested -lambdas, conditional expressions and ``catmaps'' (a list operation which -combines list concatenation and mapping a function over a list, defined in the -prelude), but they are often much easier to write. Some examples of list +\fBMatrices:\fP {1.0,2.0,3.0}, {1,2;3,4}, {1L,y+1;foo,bar} +Pure also offers matrices, a kind of arrays, as a built-in data structure +which provides efficient storage and element access. These work more or less +like their Octave/MATLAB equivalents, but using curly braces instead of +brackets. As indicated, commas are used to separate the columns of a matrix, +semicolons for its rows. In fact, the {...} construct is rather general, +allowing you to construct new matrices from individual elements and/or +submatrices, provided that all dimensions match up. E.g., {{1;3},{2;4}} is +another way to write a 2x2 matrix in ``column-major'' form (however, +internally all matrices are stored in C's row-major format). +.sp +If the interpreter was built with support for the GNU Scientific Library (GSL) +then both numeric and symbolic matrices are available. The former are thin +wrappers around GSL's homogeneous arrays of double, complex double or +(machine) int matrices, while the latter can contain any mixture of Pure +expressions. Pure will pick the appropriate type for the data at hand. If a +matrix contains values of different types, or Pure values which cannot be +stored in a numeric matrix, then a symbolic matrix is created instead (this +also includes the case of bigints, which are considered as symbolic values as +far as matrix construction is concerned). If the interpreter was built without +GSL support then symbolic matrices are the only kind of matrices supported by +the interpreter. +.sp +More information about matrices and corresponding examples can be found in the +EXAMPLES section below. +.TP +\fBComprehensions:\fP [x,y | x=1..n; y=1..m; x<y], {i!=j | i=1..n; j=1..m} +Pure provides the usual comprehension syntax as a convenient means to +construct both list and matrix values from a ``template'' expression and one +or more ``generator'' and ``filter'' clauses (the former bind a pattern to +values drawn from a list or matrix, the latter are just predicates determining +which generated elements should actually be added to the result). Both list +and matrix comprehensions are in fact syntactic sugar for a combination of +nested lambdas, conditional expressions and ``catmaps'' (a collection of +operations which combine list or matrix construction and mapping a function +over a list or matrix, defined in the prelude), but they are often much easier +to write. +.sp +Matrix comprehensions work pretty much like list comprehensions, but produce +matrices instead of lists. Generator clauses in matrix comprehensions +alternate between row and column generation so that most common mathematical +abbreviations carry over quite easily. Examples of both kinds of comprehensions can be found in the EXAMPLES section below. .TP \fBFunction applications:\fP foo x y z @@ -712,9 +747,113 @@ symbols needed in an evaluation .I before entering the expression to be evaluated. +.SH RULE SYNTAX +Basically, the same rule syntax is used in all kinds of global and local +definitions. However, some constructs (specifically, \fBwhen\fP, \fBlet\fP, +\fBconst\fP and \fBdef\fP) use a restricted rule syntax where no guards or +multiple left-hand and right-hand sides are permitted. When matching against a +function or macro call, or the subject term in a \fBcase\fP expression, the +rules are always considered in the order in which they are written, and the +first matching rule (whose guard evaluates to a nonzero value, if applicable) +is picked. (Again, the \fBwhen\fP construct is treated differently, because +each rule is actually a separate definition.) +.PP +In any case, the left-hand side pattern (which, as already mentioned, is +always a simple expression) must not contain repeated variables (i.e., rules +must be ``left-linear''), except for the anonymous variable `_' which matches +an arbitrary value without binding a variable symbol. +.PP +A left-hand side variable (including the anonymous variable) may be followed +by one of the special type tags \fB::int\fP, \fB::bigint\fP, \fB::double\fP, +\fB::string\fP, \fB::matrix\fP, \fB::pointer\fP, to indicate that it can only +match a constant value of the corresponding built-in type. (This is useful if +you want to write rules matching \fIany\fP object of one of these types; note +that there is no way to write out all ``constructors'' for the built-in types, +as there are infinitely many.) +.PP +Pure also supports Haskell-style ``as'' patterns of the form +.IB variable @ pattern +which binds the given variable to the expression matched by the subpattern +.I pattern +(in addition to the variables bound by +.I pattern +itself). This is convenient if the value matched by the subpattern is to be +used on the right-hand side of an equation. Syntactically, ``as'' patterns are +primary expressions; if the subpattern is not a primary expression, it must be +parenthesized. For instance, the following function duplicates the head +element of a list: +.sp +.nf +foo xs@(x:_) = x:xs; +.fi +.PP +The left-hand side of a rule can be omitted if it is the same as for the +previous rule. This provides a convenient means to write out a collection of +equations for the same left-hand side which discriminates over different +conditions: +.sp +.nf +\fIlhs\fR = \fIrhs\fP \fBif\fP \fIguard\fP; + = \fIrhs\fP \fBif\fP \fIguard\fP; + ... + = \fIrhs\fP \fBotherwise\fP; +.fi +.PP +For instance: +.sp +.nf +fact n = n*fact (n-1) \fBif\fP n>0; + = 1 \fBotherwise\fP; +.fi +.PP +Pure also allows a collection of rules with different left-hand sides but the +same right-hand side(s) to be abbreviated as follows: +.sp +.nf +\fIlhs\fP | + ... +\fIlhs\fP = \fIrhs\fP; +.fi +.PP +This is useful if you need different specializations of the same rule which +use different type tags on the left-hand side variables. For instance: +.sp +.nf +fact n::int | +fact n::double | +fact n = n*fact(n-1) \fBif\fP n>0; + = 1 \fBotherwise\fP; +.fi +.PP +In fact, the left-hand sides don't have to be related at all, so that you can +also write something like: +.sp +.nf +foo x | bar y = x*y; +.fi +.PP +However, this is most useful when using an ``as'' pattern to bind a common +variable to a parameter value +.I after +checking that it matches one of several possible argument patterns (which is +slightly more efficient than using an equivalent type-checking guard). E.g., +the following definition binds the xs variable to the parameter of foo, if it +is either the empty list or a list starting with an integer: +.sp +.nf +foo xs@[] | foo xs@(_::int:_) = ... xs ...; +.fi +.PP +The same construct also works in +.B case +expressions, which is convenient if different cases should be mapped to the +same value, e.g.: +.sp +.nf +\fBcase\fP ans \fBof\fP "y" | "Y" = 1; _ = 0; \fBend\fP; +.fi .SH EXAMPLES -Here are a few examples of simple Pure programs (see the following section for -a closer discussion of the rule syntax). +Here are a few examples of simple Pure programs. .PP The factorial: .sp @@ -1032,110 +1171,159 @@ the number of elements printed until memory is exhausted. Calling `do' on a fresh instance of the stream of primes allows `do' to get rid of each `cons' cell after having printed the corresponding stream element.) -.SH RULE SYNTAX -Basically, the same rule syntax is used in all kinds of global and local -definitions. However, some constructs (specifically, \fBwhen\fP, \fBlet\fP, -\fBconst\fP and \fBdef\fP) use a restricted rule syntax where no guards or -multiple left-hand and right-hand sides are permitted. When matching against a -function or macro call, or the subject term in a \fBcase\fP expression, the -rules are always considered in the order in which they are written, and the -first matching rule (whose guard evaluates to a nonzero value, if applicable) -is picked. (Again, the \fBwhen\fP construct is treated differently, because -each rule is actually a separate definition.) +.SS Matrix Computations +Pure offers a number of basic matrix operations, such as matrix construction, +indexing, slicing, as well as getting the size and dimensions of a matrix +(these are briefly described in the STANDARD LIBRARY section below). However, +it does +.I not +supply built-in support for matrix arithmetic and other linear algebra +algorithms. The idea is that these can and should be provided through separate +libraries, such as a GSL interface (which will hopefully be available in the +near future). .PP -In any case, the left-hand side pattern (which, as already mentioned, is -always a simple expression) must not contain repeated variables (i.e., rules -must be ``left-linear''), except for the anonymous variable `_' which matches -an arbitrary value without binding a variable symbol. +But Pure's facilities for matrix and list processing also make it easy to roll +your own, if desired. First, the prelude provides matrix versions of the +common list operations like map, fold, zip etc., which provide a way to +implement common matrix operations. E.g., multiplying a matrix x with a scalar +a amounts to mapping the function \ex->a*x to x, which can be done as follows: +.sp +.nf +> a::int * x::matrix = map (\ex->a*x) x; +> 2*{1,2,3;4,5,6}; +{2,4,6;8,10,12} +.fi .PP -A left-hand side variable (including the anonymous variable) may be followed -by one of the special type tags \fB::int\fP, \fB::bigint\fP, \fB::double\fP, -\fB::string\fP, to indicate that it can only match a constant value of the -corresponding built-in type. (This is useful if you want to write rules -matching \fIany\fP object of one of these types; note that there is no way to -write out all ``constructors'' for the built-in types, as there are infinitely -many.) +Likewise, matrix addition and other element-wise operations can be realized +using zipwith, which combines corresponding elements of two matrices using a +given binary function: +.sp +.nf +> x::matrix + y::matrix = zipwith (+) x y; +> {1,2,3;4,5,6}+{1,2,1;3,2,3}; +{2,4,4;7,7,9} +.fi .PP -Pure also supports Haskell-style ``as'' patterns of the form -.IB variable @ pattern -which binds the given variable to the expression matched by the subpattern -.I pattern -(in addition to the variables bound by -.I pattern -itself). This is convenient if the value matched by the subpattern is to be -used on the right-hand side of an equation. Syntactically, ``as'' patterns are -primary expressions; if the subpattern is not a primary expression, it must be -parenthesized. For instance, the following function duplicates the head -element of a list: +Second, matrix comprehensions make it easy to express a variety of algorithms +which would be implemented using `for' loops in conventional programming +languages. To illustrate the use of matrix comprehensions, here is how we can +define an operation to create a square identity matrix of a given dimension: .sp .nf -foo xs@(x:_) = x:xs; +> eye n = {i==j | i = 1..n; j = 1..n}; +> eye 3; +{1,0,0;0,1,0;0,0,1} .fi .PP -The left-hand side of a rule can be omitted if it is the same as for the -previous rule. This provides a convenient means to write out a collection of -equations for the same left-hand side which discriminates over different -conditions: +Note that the i==j term is just a Pure idiom for the Kronecker symbol. Another +point worth mentioning here is that the generator clauses of matrix +comprehensions alternate between row and column generation +automatically. (More precisely, the last generator, which varies most quickly, +always yields a row, the next-to-last one a column of these row vectors, and +so on.) This makes matrix comprehensions resemble customary mathematical +notation very closely. +.PP +As a slightly more comprehensive example (no pun intended!), here is a +definition of matrix multiplication in Pure. Let's start out with the simple +case of the ``dot'' product of two vectors: .sp .nf -\fIlhs\fR = \fIrhs\fP \fBif\fP \fIguard\fP; - = \fIrhs\fP \fBif\fP \fIguard\fP; - ... - = \fIrhs\fP \fBotherwise\fP; +> x::matrix * y::matrix = sum [x!i*y!i | i=0..#x-1] +> \fBif\fP vectorp x && vectorp y; +> sum = foldl (+) 0; +> {1,2,3}*{1,0,1}; +4 .fi .PP -For instance: +(For the sake of simplicity, this doesn't do much error checking; if the two +vectors aren't the same size then you'll get an `out_of_bounds' exception with +the definition above.) +.PP +The matrix product now boils down to a simple matrix comprehension which just +multiplies all rows of x with all columns of y (the rows and cols functions +are prelude operations found in matrices.pure): .sp .nf -fact n = n*fact (n-1) \fBif\fP n>0; - = 1 \fBotherwise\fP; +> x::matrix * y::matrix = {u*v | u = rows x; v = cols y}; +> {0,1;1,0;1,1}*{1,2,3;4,5,6}; +{4,5,6;1,2,3;5,7,9} .fi .PP -Pure also allows a collection of rules with different left-hand sides but the -same right-hand side(s) to be abbreviated as follows: +Well, that was easy. So let's take a look at a more challenging example, +Gaussian elimination, which can be used to solve systems of linear +equations. The algorithm brings a matrix into ``row echelon'' form, a +generalization of triangular matrices. The resulting system can then be solved +quite easily using back substitution. Here is a Pure implementation of the +algorithm (please refer to any good textbook on numeric mathematics for a +closer description of the algorithm): .sp .nf -\fIlhs\fP | - ... -\fIlhs\fP = \fIrhs\fP; +gauss_elimination x::matrix = p,x +\fBwhen\fP n,m = dim x; p,_,x = foldl step (0..n-1,0,x) (0..m-1) \fBend\fP; .fi .PP -This is useful if you need different specializations of the same rule which -use different type tags on the left-hand side variables. For instance: +The actual pivoting and elimination step is a bit involved. x is our matrix, i +the current row index, j the current column index, and p keeps track of the +current permutation of the row indices performed during pivoting. The +algorithm returns the updated matrix x, row index i and row permutation p. .sp .nf -fact n::int | -fact n::double | -fact n = n*fact(n-1) \fBif\fP n>0; - = 1 \fBotherwise\fP; +step (p,i,x) j += \fBif\fP max_x>0 \fBthen\fP + // updated row permutation and index: + transp i max_i p, i+1, + {// the top rows of the matrix remain unchanged: + x!!(0..i-1,0..m-1); + // the pivot row, divided by the pivot: + {x!(i,l)/x!(i,j) | l=0..m-1}; + // subtract suitable multiples of the pivot row: + {x!(k,l)-x!(k,j)*x!(i,l)/x!(i,j) | k=i+1..n-1; l=0..m-1}} + \fBelse\fP p,i,x +\fBwhen\fP + n,m = dim x; max_i, max_x = pivot i (col x j); + x = \fBif\fP max_x>0 \fBthen\fP swap x i max_i \fBelse\fP x; +\fBend\fP \fBwith\fP + pivot i x = foldl max (0,0) [j,abs (x!j)|j=i..#x-1]; + max (i,x) (j,y) = \fBif\fP x<y \fBthen\fP j,y \fBelse\fP i,x; +\fBend\fP; .fi .PP -In fact, the left-hand sides don't have to be related at all, so that you can -also write something like: +We also need the following little helper functions to swap two rows of a +matrix (this is used in the pivoting step above) and to apply a transposition +to a permutation (represented as a list): .sp .nf -foo x | bar y = x*y; +swap x i j = x!!(transp i j (0..n-1),0..m-1) \fBwhen\fP n,m = dim x \fBend\fP; +transp i j p = [p!tr k | k=0..#p-1] +\fBwith\fP tr k = \fBif\fP k==i \fBthen\fP j \fBelse\fP \fBif\fP k==j \fBthen\fP i \fBelse\fP k \fBend\fP; .fi .PP -However, this is most useful when using an ``as'' pattern to bind a common -variable to a parameter value -.I after -checking that it matches one of several possible argument patterns (which is -slightly more efficient than using an equivalent type-checking guard). E.g., -the following definition binds the xs variable to the parameter of foo, if it -is either the empty list or a list starting with an integer: +Finally, let us define a convenient print representation of double matrices a +la Octave (the meaning of the __show__ function is explained in the CAVEATS +and NOTES section): .sp .nf -foo xs@[] | foo xs@(_::int:_) = ... xs ...; +\fBusing\fP system; +__show__ x::matrix += strcat [printd j (x!(i,j))|i=0..n-1; j=0..m-1] + "\en" +\fBwith\fP printd 0 = sprintf "\en%10.5f"; printd _ = sprintf "%10.5f" \fBend\fP +\fBwhen\fP n,m = dim x \fBend\fP \fBif\fP dmatrixp x; .fi .PP -The same construct also works in -.B case -expressions, which is convenient if different cases should be mapped to the -same value, e.g.: +Example: .sp .nf -\fBcase\fP ans \fBof\fP "y" | "Y" = 1; _ = 0; \fBend\fP; +> \fBlet\fP x = dmatrix {2,1,-1,8; -3,-1,2,-11; -2,1,2,-3}; +> x; gauss_elimination x; + + 2.00000 1.00000 -1.00000 8.00000 + -3.00000 -1.00000 2.00000 -11.00000 + -2.00000 1.00000 2.00000 -3.00000 + +[1,2,0], + 1.00000 0.33333 -0.66667 3.66667 + 0.00000 1.00000 0.40000 2.60000 + 0.00000 0.00000 1.00000 -1.00000 .fi .SH MACROS Macros are a special type of functions to be executed as a kind of @@ -1688,18 +1876,19 @@ unsigned integers as well (if necessary, you can use a bigint to pass positive values which are too big to fit into a machine int). Also note that when an unsigned integer is returned by a C routine which is too big to fit into the -corresponding signed integer type, it will become negative. In this case, -depending on the target type, you can use the ubyte, ushort, uint and ulong -functions provided by the prelude to convert the result back to an unsigned -quantity. +corresponding signed integer type, it will ``wrap around'' and become +negative. In this case, depending on the target type, you can use the ubyte, +ushort, uint and ulong functions provided by the prelude to convert the result +back to an unsigned quantity. .PP Concerning the pointer types, char* is for string arguments and return values which need translation between Pure's internal utf-8 representation and the system encoding, while void* is for any generic kind of pointer (including strings, which are \fInot\fP translated when passed/returned as void*). Any -other kind of pointer (except expr*, see below) is effectively treated as -void* right now, although in a future version the interpreter may keep track -of the type names for the purpose of checking parameter types. +other kind of pointer (except expr* and the GSL matrix pointer types, which +are discussed below) is effectively treated as void* right now, although in a +future version the interpreter may keep track of the type names for the +purpose of checking parameter types. .PP The expr* pointer type is special; it indicates a Pure expression parameter or return value which is just passed through unchanged. All other types of values @@ -1708,6 +1897,32 @@ Pure). All of this is handled by the runtime system in a transparent way, of course. .PP +The matrix pointer types dmatrix*, cmatrix* and imatrix* can be used to pass +double, complex double and int matrices to GSL functions taking pointers to +the corresponding GSL types (gsl_matrix, gsl_matrix_complex and +gsl_matrix_int) as arguments or returning them as results. Note that there is +no marshalling of Pure's symbolic matrix type, as these aren't supported by +GSL anyway. Also note that matrices are always passed by reference. If you +need to pass a matrix as an output parameter of a GSL matrix routine, you can +either create a zero matrix or a copy of an existing matrix. The prelude +provides various operations for that purpose (in particular, see the dmatrix, +cmatrix, imatrix and pack functions in matrices.pure). For instance, here is +how you can quickly wrap up GSL's double matrix addition function in a way +that preserves value semantics: +.sp +.nf +> \fBextern\fP int gsl_matrix_add(dmatrix*, dmatrix*); +> x::matrix + y::matrix = gsl_matrix_add x y $$ x \fBwhen\fP x = pack x \fBend\fP; +> \fBlet\fP x = dmatrix {1,2,3}; \fBlet\fP y = dmatrix {2,3,2}; x; y; x+y; +{1.0,2.0,3.0} +{2.0,3.0,2.0} +{3.0,5.0,5.0} +.fi +.PP +Most GSL matrix routines can be wrapped in this fashion quite easily. A +ready-made GSL interface providing access to all of GSL's numeric functions +will be provided in the future. +.PP As already mentioned, it is possible to augment an external C function with ordinary Pure equations, but in this case you have to make sure that the .B extern @@ -1795,17 +2010,81 @@ .B using clause. The prelude offers the necessary functions to work with the built-in types (including arithmetic and logical operations) and to do most kind of -list processing you can find in ML- and Haskell-like languages. Please refer -to the +list processing you can find in ML- and Haskell-like languages. It also +provides a collection of basic string and matrix operations. Please refer to +the .B prelude.pure -file for details on the provided operations. Common container data structures -like sets and dictionaries are also available, see -.BR set.pure , +file (as well as the modules included there, specifically +.BR primitives.pure , +.B matrices.pure +and +.BR strings.pure ) +for details on the provided operations. Here is a very brief summary of some +of the prelude operations which, besides the usual arithmetic and logical +operators, are probably used most frequently: +.TP +x+y +This is also used to denote list concatenation. +.TP +x:y +This is the list-consing operation. x becomes the head of the list, y its tail. +.TP +x..y +Constructs arithmetic sequences. x:y..z can be used to denote sequences with +arbitrary stepsize y-x. Infinite sequences can be constructed using an +infinite bound (i.e., inf or -inf). E.g., 1:3..inf denotes the stream of all +positive odd (machine) integers. +.TP +#x +The size (number of elements) of the list, tuple or matrix x. In addition, dim +x yields the dimensions (number of rows and columns) of a matrix. +.TP +x' +The transpose of a matrix. +.TP +x!y +This is the list, tuple and matrix indexing operation. Note that all indices +in Pure are zero-based, thus x!0 and x!(#x-1) are the first and last element +of a list, tuple or matrix, respectively. In the case of matrices, the +subscript may also be a pair of row and column indices, such as x!(1,2). +.TP +x!!ys +This is Pure's list, tuple and matrix ``slicing'' operation, which returns the +list, tuple or matrix of all x!y while y runs through the (list or matrix) ys. +Thus, e.g., x!!(i..j) returns all the elements between i and j (inclusive). +Indices which fall outside the valid index range are quietly discarded. In +fact, the index range ys may contain any number of indices (also duplicates), +in any order. Thus x![0|i=1..n] returns the first element of x n times, and, +if ys is a permutation of the range 0..#x-1, then x!!ys yields the +corresponding permutation of the elements of x. In the case of matrices the +index range may also contain two-dimensional subscripts, or the index range +itself may be specified as a pair of row/column index lists such as +x!!(i..j,k..l). +.PP +The prelude also offers support operations for the implementation of list and +matrix comprehensions, as well as the customary list operations like head, +tail, drop, take, filter, map, foldl, foldr, scanl, scanr, zip, unzip, etc., +which make list programming so much fun in modern FPLs. In Pure, these also +work on strings as well as matrices, although, for reasons of efficiency, +these data structures are internally represented as different kinds of array +data structures. +.PP +Besides the prelude, Pure's standard library also comprises a growing number +of additional library modules which we can only mention in passing here. In +particular, the +.B math.pure +module provides additional mathematical functions as well as Pure's complex +and rational number data types. Common container data structures like sets and +dictionaries are implemented in the +.B set.pure +and .B dict.pure -etc. Moreover, the (beginnings of a) system interface can be found in the +modules, among others. Moreover, the (beginnings of a) system interface can be +found in the .B system.pure -module. In particular, this module also includes operations to do basic -I/O. More stuff will likely be provided in future releases. +module. In particular, this module also provides operations to do basic +C-style I/O, including printf and scanf. More stuff will likely be provided in +future releases. .SH INTERACTIVE USAGE In interactive mode, the interpreter reads definitions and expressions and processes them as usual. If the @@ -2288,12 +2567,24 @@ operations with side effects (it does allow you to call any C function after all), but with a few exceptions the standard library operations are free of those. Just stay away from operations marked ``IMPURE'' in the library sources -(most notably, eval and catch/throw) and avoid the system module, then your -program will behave according to the semantics of term rewriting. +(most notably, eval, catch/throw, references, sentries and direct pointer +manipulations) and avoid the system module, then your program will behave +according to the semantics of term rewriting. .PP The short answer is that I simply liked the name, and there wasn't any programming language named ``Pure'' yet (quite a feat nowadays), so there's one now. :) +.SS Backward Compatibility +Pure 0.7 introduced built-in matrix structures, which called for some minor +changes in the syntax of comprehensions and arithmetic +sequences. Specifically, the template expression and generator/filter clauses +of a comprehension are now separated with '|'. (For the time being, the old +[x; ...] list comprehension syntax is still supported, but the compiler will +warn you about such constructs and flag them as deprecated.) Moreover, +arithmetic sequences with arbitrary stepsize are now written x:y..z instead of +x,y..z, and the `..' operator now has a lower precedence than the `,' +operator. This makes writing matrix slices like x!!(i..j,k..l) much more +convenient. .SS Debugging There's no symbolic debugger yet. So .BR printf (3) @@ -2377,6 +2668,24 @@ 1:2:3:... .fi .PP +Another case which needs special consideration are numeric matrices. For +efficiency, the expression printer will always use the default representation +for these, unless you override the representation of the matrix as a +whole. E.g., the following rule for double matrices mimics Octave's default +output format (for the sake of simplicity, this isn't perfect, but you get the +idea): +.sp +.nf +> __show__ x::matrix = +> strcat [printd j (x!(i,j))|i=0..n-1; j=0..m-1] + "\en" +> \fBwith\fP printd 0 = sprintf "\en%10.5f"; printd _ = sprintf "%10.5f" \fBend\fP +> \fBwhen\fP n,m = dim x \fBend\fP \fBif\fP dmatrixp x; +> {1.0,1/2;1/3,4.0}; + + 1.00000 0.50000 + 0.33333 4.00000 +.fi +.PP Finally, by just purging the definition of the __show__ function you can easily go back to the standard print syntax: .sp @@ -2826,15 +3135,25 @@ Albert Graef <Dr....@t-...>, Dept. of Computer Music, Johannes Gutenberg University of Mainz, Germany. .SH SEE ALSO +(All software listed here is freely available, usually under the GNU Public +License.) .TP .B Aardappel Another functional programming language based on term rewriting, \fIhttp://wouter.fov120.com/aardappel\fP. .TP .B Alice ML -A version of ML (see below) with ``futures'', -\fIhttp://www.ps.uni-sb.de/alice\fP. +A version of ML (see below) from which Pure borrows its model of lazy +evaluation, \fIhttp://www.ps.uni-sb.de/alice\fP. .TP +.B GNU Octave +A popular high-level language for numeric applications and free MATLAB +replacement, \fIhttp://www.gnu.org/software/octave\fP. +.TP +.B GNU Scientific Library +A free software library for numeric applications, required for Pure's +numeric matrix support, \fIhttp://www.gnu.org/software/gsl\fP. +.TP .B Haskell A popular non-strict FPL, \fIhttp://www.haskell.org\fP. .TP This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |