[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11. The Standard Library

This chapter gives an overview of the data types and operations provided by the standard library modules supplied with the Q programming system. Most of these scripts are already "preloaded" when you run the interpreter, because they are included in the "prelude" script prelude.q. The exact collection of library scripts may depend on your local setup, but a basic installation of the Q core package should at least provide the modules listed below. In this list, (*) indicates "external" modules which are (mostly) implemented in C, whereas (+) denotes modules which have to be imported explicitly, as they are not included in the prelude.

assert.q

print diagnostics

clib.q

basic C interface (*)

complex.q

complex numbers

cond.q

conditional expressions and tuple/list/stream comprehensions

error.q

print error messages

getopt.q

GNU getopt compatible option parser (+)

graphics.q

PostScript graphics interface (+)

math.q

mathematical functions

prelude.q

standard prelude

rational.q

rational numbers

reftypes.q

tuples, lists and streams of references (+)

sort.q

algorithms to sort a list

stddecl.q

shared declarations of the container data structures, cf. stdtypes.q (+)

stdlib.q

a collection of common standard functions

stdtypes.q

a collection of efficient container data structures (+)

stream.q

a lazy list data structure

string.q

additional string functions

system.q

POSIX system interface (*) (+)

tuple.q

additional tuple functions

typec.q

type-checking predicates

Here is a quick rundown of the most important modules: The prelude.q script implements the standard prelude, which loads the entire collection (except the modules marked with (+) in the list above, which must be imported explicitly). It adds some convenient operations for comparing lists, streams and tuples, the syntactic inequality operator `!=', as well as successor and predecessor functions on integers (succ and pred) and default implementations of various functions for subtypes derived from the Real type. It also contains definitions for some cases of list, tuple and stream enumerations which are not provided as builtins.

Specifically, the standard prelude overloads the =, <>, <, >, <= and >= operators with rules for deciding equality and inequality of lists, streams and tuples, and rules for ordering lists and streams lexicographically. That is, tuples, lists and streams can be compared with = and <>, which is done by checking that the operands are of the same size and recursively comparing all members of the operands. Lists and streams can also be compared lexicographically by recursively comparing the list or stream members; the first unequal members decide the comparison. This works just like the lexicographic comparison of strings. Thus, e.g., [1,2] is considered to be less than both [1,3] and [1,2,1], but more than [1,1,3] or [0,5].

Moreover, the prelude defines the syntactic inequality operator `!=' as the logical negation of the built-in `==' operator, cf. Non-Linear Equations. Like `==', `!=' is implemented as a special form.

Last but not least, the standard prelude also provides default definitions for arithmetic, relational, numeric and conversion functions on Real, so that a minimal implementation of a user-defined type derived from Real (or any of its subtypes) just needs to define the float function (which is needed to coerce values of the type to Float) and then add definitions for those operations which need special treatment. The default definitions in prelude.q are at the lowest priority level so that they can always be overridden if needed.

The stdlib.q script has those operations which will probably be used most frequently by the average programmer; it contains a lot of additional list processing functions and other useful stuff mostly adopted from [Bird/Wadler 1988]. This module is also included by many other library scripts. Historically, it was the first script written for the standard library.

The stream.q script extends most list operations defined in stdlib.q to streams, i.e., lazy lists. It also provides a number of other useful stream operations.

Similarly, the string.q and tuple.q scripts provide additional operations on strings and tuples, and also extend some list operations to these data types.

The stdtypes.q script simply includes all modules which implement common container data structures; currently these are array.q, bag.q, dict.q, hdict.q, heap.q and set.q, see Standard Types. Some declarations shared by these modules are in the stddecls.q script.

The complex.q and rational.q scripts implement complex and rational number types along with the usual operations on these types. These have been designed to integrate seamlessly into Q's system of built-in number types so that expressions involving arithmetic operations with any combination of integer, floating point, complex and rational arguments work as expected.

The clib.q and system.q modules give access to various useful system functions from the C library, including C-style formatted I/O, binary file I/O, process and thread management, internationalization support and regular expression routines. The clib.q module also provides mutable expression cells ("references"), as well as a "byte string" data type which lets you represent arbitrary C data, and it overrides various important standard library functions with much faster C versions. The operations of these modules are mostly written in C, using the C language interface discussed in C Language Interface. These modules are described in their own chapter, see Clib.

As of Q 7.8, the reftypes.q module provides additional convenience operations to work with mutable expression sequences implemented as tuples, lists or streams of references. These are also described in the "Clib" chapter, see Expression References.

The Q programming system comes bundled with some additional modules for interfacing to various third-party libraries and software packages. At the time of this writing, these are:

Preliminary documentation for these modules can be found in the etc subdirectory of your Q installation directory (usually in /usr/share/q or /usr/local/share/q). Other useful add-on modules are available as separate source packages. At the time of this writing this comprises additional GUI libraries (including a complete interface to Trolltech's very nice "Qt" toolkit), a bunch of graphics and multimedia modules (including interfaces to OpenGL, OpenAL, the Xine video library, and Grame's MidiShare and Faust) and more. Ready-made plugins for using the Q interpreter from the "Chicken" Scheme compiler, the Apache webserver and Miller Puckette's graphical computer music and multimedia environment "PureData" are also available. Please check out the Q website at http://q-lang.sourceforge.net for more information about these. (The Q module for Chicken, which was written by John Cowan, is available separately from the Chicken website, see http://www.call-with-current-continuation.org.)


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.1 Standard Functions

The stdlib.q script provides frequently used list operations and other stuff mostly adopted from [Bird/Wadler 1988].

abs X

absolute value of X

all P Xs

verify that each element of the list Xs satisfies the predicate P

any P Xs

verify that the list Xs contains an element satisfying predicate P

append Xs X

append a value X to the list Xs

cat Xs

concatenate a list of lists

cons X Xs

prepend an element to a list

cst X

constant-valued function: cst X Y ⇒ X

curry F

curry a function: turn a function operating on pairs into a function with two arguments

curry3 F

curry with three arguments

do F Xs

apply a function F to each member of a list Xs, return ()

dowith F Xs Ys

take two lists and apply a binary function to corresponding elements, return ()

dowith3 F Xs Ys Zs

dowith with three lists

drop N Xs

remove the first N elements from the list Xs

dropwhile P Xs

remove elements from the beginning of Xs while the predicate P is satisfied

eq X Y

syntactic equality (cf. Non-Linear Equations)

filter P Xs

filter a list with a predicate

foldl F A Xs

fold-left

foldl1 F Xs

fold-left over nonempty lists

foldr F A Xs

fold-right

foldr1 F Xs

fold-right over nonempty lists

hd Xs

return the head element of a list

hds Xs

return the list of all head elements in a list of lists

id

the identity function: id X ⇒ X

init Xs

return list Xs without its last element

iter N F A

generate the list of the first N values A, F A, F (F A), …

last Xs

return the last element of a list

map F Xs

apply function F to each member of a list

max X Y

maximum of two values

min X Y

minimum of two values

mklist X N

create a list of N X's

neg P

negate a predicate

neq X Y

syntactic inequality

null Xs

check whether a list is empty ([])

nums N M

generate a list of numbers in a given range

numsby K N M

generate a list of numbers with a given step size

pop Xs

remove the head element from a list

prd Xs

product of a list of numbers

push Xs X

prepend an element to a list (cons with arguments reversed)

reverse Xs

reverse a list

scanl F A Xs

apply foldl to every initial part of a list

scanl1 F Xs

apply foldl1 to every nonempty initial part of a list

scanr F A Xs

apply foldr to every final part of a list

scanr1 F Xs

apply foldr1 to every nonempty final part of a list

sgn X

sign of a number

sum Xs

sum of a list of numbers

take N Xs

select the first N elements from the list Xs

takewhile P Xs

select elements from the beginning of Xs while the predicate P is satisfied

tl Xs

remove the head element from a list

tls Xs

return a list of lists with all head elements removed

top Xs

return the head element from a list

transpose Xs

transpose a list of lists

uncurry F

uncurry a function: turn a function with two arguments into a function operating on pairs

uncurry3 F

uncurry with triples

until P F X

repeat applying F to X until P is satisfied

unzip Xs

transform a list of pairs into a pair of lists

unzip3 Xs

unzip with triples

while P F A

list repeated applications of F to A while P is satisfied

zip Xs Ys

take two lists and return a list of corresponding pairs

zip3 Xs Ys Zs

zip with three lists

zipwith F Xs Ys

take two lists and map a binary function to corresponding elements

zipwith3 F Xs Ys Zs

zipwith with three lists

Note that some of these functions are actually overridden with much faster C versions in the clib.q module; see C Replacements for Common Standard Library Functions.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.2 Tuple Functions

The tuple.q script provides some additional functions operating on tuples:

fst Xs

return first element of a tuple

mktuple X N

create a tuple of N X's

pair X Y

construct a pair

snd Xs

return second element of a tuple

trd Xs

return third element of a tuple

triple X Y Z

construct a triple

tuplecat Xs

concatenate a list of tuples

Moreover, the following list functions from stdlib.q are overloaded to also work on tuples: append, cat, cons, do, dowith, dowith3, map, null, pop, push, reverse, top. Most of these return tuples when applied to such arguments, except null (which returns a truth value), the do/dowith functions (which return ()) and cat (which always returns a list; use tuplecat if you want to concatenate a collection of tuples instead).

Also note that the reverse and tuplecat operations are actually overridden with much faster C versions in the clib.q module; see C Replacements for Common Standard Library Functions.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.3 String Functions

The string.q script provides a collection of additional string functions. Currently the following operations are implemented (most of these operations are actually overridden with much more efficient C implementations in the clib.q module; see C Replacements for Common Standard Library Functions):

chars S

return the list of individual characters in S

join DELIM Xs

concatenate a list of strings, interpolating the given DELIM string between each pair of consecutive strings in the list

mkstr S N

create a string consisting of N copies of the given string S

split DELIM S

split a string into a list of substrings delimited by characters in the given DELIM string

strcat Xs

concatenate a list of strings

Moreover, as of Q 7.8 this module overloads all list operations in stdlib.q so that they work on strings as expected. This lets you use strings mostly as if they were just another kind of list value. For instance:

 
==> take 3 "abcdef"
"abc"

==> dropwhile (<="c") "abcdef"
"def"

==> tl "abcdef"
"bcdef"

==> zip "abcdef" "ABCDEF"
[("a","A"),("b","B"),("c","C"),("d","D"),("e","E"),("f","F")]

==> map (+1) "HAL"
"IBM"

==> map ord "HAL"
[72,65,76]

==> [C-1 : C in "IBM"]
["H","A","L"]

(As the last example shows, strings can also serve as sources in the binding clauses of list comprehensions; cf. Conditionals and Comprehensions.)

Here's a somewhat more practical example which illustrates the use of various list operations on strings to build a ROT13 translation table:

 
import dict;

def CHARS = strcat ["a".."z"], RCHARS = drop 13 CHARS ++ take 13 CHARS,
  ROT13 = dict $ zip (CHARS++toupper CHARS) (RCHARS++toupper RCHARS);

rot13 C:Char    = C where C:Char = ROT13!C;
                = C otherwise;
rot13 S:String  = map rot13 S;

(This employs the dict function to create a dictionary mapping lower- and uppercase letters to their equivalents in the ROT13 encoding; see Dictionaries.) Example:

 
==> CHARS; RCHARS
"abcdefghijklmnopqrstuvwxyz"
"nopqrstuvwxyzabcdefghijklm"

==> rot13 "This is an encoded string."
"Guvf vf na rapbqrq fgevat."

==> rot13 _
"This is an encoded string."

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.4 Option Parsing

This module provides one function, getopt, which takes two arguments: OPTS, a list of option descriptions in the format described below, and ARGS, a list of strings containing the command line parameters to be parsed for options. The result is a pair (OPTS,ARGS) where OPTS is a list of pairs of options and their arguments (if any; missing arguments are returned as ()), and ARGS is the list of remaining (non-option) arguments. Options are parsed using the rules of GNU getopt(1). If an invalid option is encountered (unrecognized option, missing or extra argument, etc.), getopt throws the offending option string as an exception.

The OPTS argument of getopt is a list of triples (LONG,SHORT,FLAG), where LONG denotes the long option, SHORT the equivalent short option, and FLAG is one of the symbolic integer values NOARG, OPTARG and REQARG which specifies whether the option has no argument, an optional argument or a required argument, respectively. In the returned option-value list, all options will be represented using their long option equivalents.

Also note that both the long and short option values in the OPTS argument may actually be of any type, so unneeded options may be replaced with corresponding dummy values. You only have to make sure that the values given for the long options allow you to identify which option was actually specified.

Finally, please note that, as already pointed out, this script does not belong to the prelude, and hence has to be imported explicitly if you want to use the getopt operation in your program.

Example (see C-Style Formatted I/O, for a description of printf and fprintf):

 
import getopt;

def OPTS        = [("--help", "-h", NOARG),
                   ("--foo",  "-f", REQARG),
                   ("--bar",  "-b", OPTARG)];

invalid_option PROG OPT
                = fprintf ERROR "%s: invalid option %s\n" (PROG,OPT) ||
                  halt;

test [PROG|ARGS]
                = printf "OPTS = %s\nARGS = %s\n" (str OPTS, str ARGS)
                    where (OPTS,ARGS) = catch (invalid_option PROG) $
                      getopt OPTS ARGS;

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.5 Type-Checking Predicates

The typec.q script contains a collection of predicates which check whether an expression is of a given type. The following functions perform a purely syntactic check; they are all equivalent to the corresponding type guards:

isbool X

check for truth values

ischar X

check for single character strings

iscomplex X

check for complex numbers (cf. Complex Numbers)

isexcept X

check for Exception values (cf. Exception Handling)

isfile X

check for file objects

isfloat X

check for floating point numbers

isfunction X

check for lambda functions

isint X

check for integers

islist X

check for lists

isnum X

check for numbers

isrational X

check for rational numbers (cf. Rational Numbers)

isreal X

check for real numbers

isstr X

check for strings

issym X

check for function and variable symbols (special form)

istuple X

check for tuples

Note that the syntactic number predicates isint, isfloat etc. only check for a given representation. The typec.q module also provides various predicates which classify numbers according to the kind of abstract mathematical object they represent, regardless of the concrete representation:

iscompval X

check for complex values

isintval X

check for integer values

isratval X

check for rational values

isrealval X

check for real values

These predicates work mostly like their Scheme counterparts. E.g., 3 will be classified not only as an integer value, but also as a rational, real and a complex value. A complex number with zero imaginary part may also be classified as an integer, rational or real, depending on its real part. A floating point number with zero fractional part and a rational number with a denominator of 1 are both also classified as an integer value.

Moreover, the following predicates allow you to check whether a number is exact or inexact (inexact numbers generally involve floating point values), and whether a number represents an IEEE infinity or NaN ("not a number") value:

isexact X

check for exact numbers

isinexact X

check for inexact numbers

isinf X

check for infinite floating point values

isnan X

check for NaN floating point values

Finally, two other special-purpose predicates provided in typec.q are:

isenum X

check for enumeration type members

issym X

check for function and variable symbols (special form)


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.6 Sorting Algorithms

The sort.q script provides mergesort and quicksort algorithms for sorting a list using a given order predicate:

msort P Xs

mergesort algorithm

qsort P Xs

quicksort algorithm

The mergesort algorithm is more involved than quicksort, but may run much faster if input lists are large enough and are already partially sorted. Both algorithms take an order predicate as their first argument, which makes it possible to sort lists using different criteria. The order predicate must be a function accepting two arguments, and must return true iff the first argument is strictly less than the second. For instance, to sort a list in ascending order, you could say:

 
==> qsort (<) [1,5,3,2,4]
[1,2,3,4,5]

By reversing the order predicate, the list is sorted in descending order:

 
==> qsort (>) [1,5,3,2,4]
[5,4,3,2,1]

Custom order predicates also allow you to sort a list according to different sort keys. For instance, the following example shows how to sort a list of pairs using the first component of each pair as the sort key:

 
==> def L = [(1,2),(5,1),(3,3),(1,1),(4,5)]

==> var le1 = \X Y.fst X < fst Y

==> qsort le1 L
[(1,2),(1,1),(3,3),(4,5),(5,1)]

Both algorithms provided by this module are "stable", i.e., they preserve the relative order of list elements with "equal" sort keys. This is important when successive sorts are used to order elements according to different criteria. For instance:

 
==> var le2 = \X Y.snd X < snd Y

==> qsort le2 L
[(5,1),(1,1),(1,2),(3,3),(4,5)]

==> qsort le1 _
[(1,1),(1,2),(3,3),(4,5),(5,1)]

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.7 Standard Types

Please note that, as of Q 7.8 this module is no longer included in the prelude, so you have to import it explicitly if your script needs one of the data types described here. It is also possible to just import the individual data type modules (array.q, bag.q, etc.) if you do not need the entire collection.

The stdtypes.q script implements a collection of efficient container data structures, which currently comprises arrays, heaps (priority queues), ordered sets and bags, and (ordered as well as hashed) dictionaries. The different data types are actually implemented in the scripts array.q, bag.q, dict.q, hdict.q, heap.q and set.q. Many operations of these modules are overloaded; the declarations of these operations can be found in the stddecl.q script which is included by the different modules.

All data structures support equality checking with = and <>, as well as the operation # to determine the size of an object (number of elements it contains). Furthermore, the set and bag data structures overload the <, >, <= and >= operators to implement subset/subbag comparisons, and the +, - and * operators to compute the union, difference and intersection of two sets or bags, respectively.

For convenience, default views are provided for all container data structures, so that they will be printed in the form of a construction function (which is implemented as a virtual constructor of the type, cf. Views) applied to a member list (such as, e.g., set [1,2,3] in the case of Set, or dict [("a",1),("b",2),("c",3)] in the case of Dict). These are at a low priority, so you can easily override them when needed.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.7.1 Arrays

The array.q script provides a zero-based array data structure Array with logarithmic access times, implemented as size-balanced binary trees. The following operations are provided:

array Xs

create an array from list Xs

array2 Xs

create a two-dimensional array from a list of lists

emptyarray

return the empty array

mkarray X N

create an array consisting of N X's

mkarray2 X (N,M)

create a two-dimensional array with N rows and M columns

isarray X

check whether X is an array

null A

check whether A is the empty array

A1 = A2, A1 <> A2

array equality/inequality

#A

size of an array

A!I

return Ith member of an array

A!(I,J)

two-dimensional subscript

members A, list A

list the members of A

members2 A, list2 A

list a two-dimensional array

first A, last A

return the first and last element of an array

rmfirst A, rmlast A

remove the first and last element from an array

insert A X

insert X at the beginning of A

append A X

append X at the end of A

update A I X

replace the Ith member of A by X

update2 A (I,J) X

update two-dimensional array


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.7.2 Heaps

The heap.q script provides an efficient heap (priority queue) data structure Heap implemented as size-balanced binary trees. Heaps allow quick (i.e., constant-time) access to the smallest element, and to insert new elements in logarithmic time. The present implementation does not allow fast random updates of heap members; if such functionality is required, bags should be used instead (see Bags).

Heap members must be ordered by the <= predicate. Multiple instances of the same element may be stored in a heap; however, the order in which equal elements are retrieved is not specified.

The following operations are provided:

emptyheap

return the empty heap

heap Xs

construct a heap from a list of its members

isheap X

determine whether X is a heap

null H

check whether H is the empty heap

H1 = H2, H1 <> H2

heap equality/inequality

#H

size of a heap

members H, list H

list the members of H in ascending order

first H

return the first element of H

rmfirst H

remove the first element from H

insert H X

insert X into H


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.7.3 Sets

The set.q script provides an ordered set data structure Set implemented as AVL trees, and thus guaranteeing logarithmic access times. The following operations are defined in set.q:

emptyset

return the empty set

set Xs

create a set from a list of its members

isset X

check whether X is a set

null M

check whether M is the empty set

member M X

check whether M contains element X

M1 = M2, M1 <> M2

set equality/inequality

M1 < M2, M1 > M2, M1 <= M2, M1 >= M2

set comparison

M1 + M2, M1 - M2, M1 * M2

set union, difference and intersection

#M

size of a set

members M, list M

list the members of M in ascending order

first M, last M

return the first and last member of M

rmfirst M, rmlast M

remove the first and last member from M

insert M X

insert X into M

delete M X

delete X from M


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.7.4 Bags

The bag.q script defines the type Bag as a variant of the set data structure which may contain multiple instances of the same element. The operations are analogous to those of the set data structure; see Sets. The emptybag function returns the empty bag, and bag Xs constructs a bag from a list Xs of its members. The isbag predicate checks whether its argument is a bag.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.7.5 Dictionaries

The dict.q script supplies an (ordered) dictionary data structure Dict which maps keys from an ordered set to corresponding values. Like sets and bags, dictionaries are implemented as AVL trees, thus guaranteeing logarithmic access times to individual members of the dictionary. The following operations are defined in dict.q:

emptydict

return the empty dictionary

dict XYs

create a dictionary from a list of key/value pairs

mkdict Y Xs

create a dictionary from a list of keys and an initial value

isdict X

check whether X is a dictionary

null D

check whether D is the empty dictionary

member D X

check whether D contains X as a key

D1 = D2, D1 <> D2

dictionary equality/inequality

#D

size of a dictionary

D!X

return the value Y associated with X in D

members D, list D

list the members (key/value pairs) of D in ascending order by key

keys D

list the keys of D in ascending order

vals D

list the corresponding values

first D, last D

return the first and last member of D

rmfirst D, rmlast D

remove the first and last member from D

insert D (X,Y)

insert a key/value pair (X,Y) into D; update an existing entry for X if present

delete D X

remove key X from D

update D X Y

same as insert D (X,Y)


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.7.6 Hashed Dictionaries

The hdict.q script implements hashed dictionaries (HDict type), a variation of the Dict type which uses hashed key values obtained with the built-in hash function. The actual key-value pairs are stored in "buckets" for each hash value. This kind of data structure is also known as "hashes" or "associative arrays" in other programming languages.

The main advantage of the HDict type is that key values can be of any type and do not have to belong to an ordered set. For instance, hdict [(0,1),(foo,2),("bar",3)] is a legal HDict value which maps the integer 0 to 1, the symbol foo to 2, and the string "bar" to 3.

There are some other notable differences between the Dict and the HDict type. First of all, a HDict stores it members in an apparently random order which may depend on the order in which new entries are added to the dictionary. Hence equality testing for HDicts is more involved than for Dicts, as the member lists of two "equal" HDicts may be arbitrary permutations of each other. This also means that the first, rmfirst, last and rmlast operations do not make much sense with hashed dictionaries and are not supported by the HDict type. Moreover, key values are always compared syntactically when looking up and updating entries. Hence, e.g., 0 and 0.0 are different key values in a HDict object, whereas they are considered to be the same for the Dict type.

Apart from these differences, the operations of the HDict and Dict types work analogously. The HDict constructors are named emptyhdict, hdict and mkhdict which take the same arguments as the corresponding Dict constructors, and the ishdict predicate checks for HDict values.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.8 Streams

The stream.q script provides operations on streams, Q's lazy list data structure. Note that, as of Q 7.1, streams are now provided as a built-in data type, which is declared as follows:

 
public type Stream = special const nil_stream, cons_stream X Xs;

As explained in Lists, Streams and Tuples, the Q language now also provides syntactic sugar for these structures, so that streams can be denoted just like lists, using curly braces instead of brackets.

The stream.q module overloads most list operations so that they work on streams in a completely analogous fashion, and provides the following additional operations:

isstream X

check whether an object is a stream

stream Xs

convert a tuple or a list to a stream

list Xs

convert a stream to a list

strict Xs

force the heads and tails of a stream (see comments below)

lazy Xs

memoize the heads and tails of a stream (see comments below)

numstream N

generate the stream of all numbers >=N

numstreamby K N

generate a number stream with given step size

mkstream X

generate an infinite stream of X's

repeat X

generate an infinite stream of X's (works like mkstream, but is implemented as a special form and hence doesn't evaluate X)

repeatn ~N X

generate a stream of N X's (special form, equivalent to take N (repeat X))

cycle Xs

generate an infinite stream which repeatedly cycles through the members of the list or stream Xs

iterate F A

generate the stream of all values A, F A, F (F A), …

streamcat Xs

concatenate a stream or list of streams and/or lists (see comments below)

Operations like #, all, foldl will of course cause troubles with infinite streams since it can take them an infinite time to compute the result. The same holds for the foldr function unless the second argument of the folded operation is special.

The stream.q module also extends the list concatenation function cat defined in stdlib.q to work with any mixture of streams and lists. This operation will always return a list, thus it is not suitable to work with infinite streams either.

As a remedy, the streamcat function is provided which concatenates a stream of streams in a fully lazy manner, i.e., you can concatenate a (possibly infinite) stream of (possibly infinite) streams. The argument of streamcat can actually be a list or stream, which consists of any mixture of streams and lists. The result is always a stream.

The strict function expands a stream by forcing all its heads and tails to be evaluated (using `~', see Special Forms). This has essentially the same effect as list, but the result is still a stream rather than a list.

Conversely, the lazy function makes a stream even "lazier" than it normally is, by causing the heads and tails of the result stream to be memoized (using `&', see Special Forms). This reduces computation times when a stream is to be traversed repeatedly.

The stream.q module also provides some additional operations to force or memoize only the heads (hdstrict, hdlazy) or the tails (tlstrict, tllazy) of a stream, as well as the "mixed mode" operations strict_lazy and lazy_strict. See the streams.q script for a description of those.

An example for the use of lazy can be found in Memoization and Lazy Evaluation.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.9 Conditionals and Comprehensions

The cond.q script provides the special forms needed to implement both various conditionals and tuple/list/stream comprehensions.

ifelse ~P X Y, when ~P X, unless ~P X

simple conditional expressions

cond CASES, case ~X CASES

multiway and pattern matching conditional expressions

condfun CASES, casefun CASES

multiway and pattern matching conditional abstractions

dowhile P X

simple looping construct

for CLAUSES X

iterate over lists and streams

tupleof X CLAUSES, listof X CLAUSES, streamof X CLAUSES

tuple, list and stream comprehensions

All these functions are implemented as special forms.

The ifelse function has already been mentioned in Conditional Expressions and Lambdas. It returns the value of either X or Y, depending on whether the first argument is true or false. For instance, here is how the factorial function can be implemented using ifelse:

 
fac N                   = ifelse (N>0) (N*fac (N-1)) 1;

Or, if you prefer to write this using the if X then Y else Z syntax described in Conditional Expressions and Lambdas:

 
fac N                   = if N>0 then N*fac (N-1) else 1;

For cases in which you are only interested in executing one of the branches, you can also use the when and unless functions which return a () default value if the branch condition is not met:

 
==> def X = 1

==> when (X>0) (writes "positive\n")
positive
()

==> unless (X>=0) (writes "negative\n")
()

As indicated, these constructs are most useful when used with functions involving side-effects; unless works exactly like when, but reverses the branch condition P. The if X then Y construct is syntactic sugar for when:

 
==> if X>0 then writes "positive\n"
positive
()

A more general conditional expression is also provided, which allows you to discriminate between an arbitrary number of cases. It has the form:

 
cond ((P1,X1),(P2,X2),…)

Using the "grouping syntax" described in Lists, Streams and Tuples, this can also be written more succintly as:

 
cond (P1,X1;P2,X2;…)

This special form looks and behaves like Lisp's cond. That is, it returns the first value X for which the corresponding condition P evaluates to true. A branch condition of true can be used to indicate the default case. If no case matches then cond raises a syserr 8 exception (note that the same error code is also thrown in case of an invalid conditional in a rule, cf. Exception Handling).

There is also a more Haskell-like case conditional in which the first expression of each case is a pattern P to be matched against the given expression X:

 
case X (P1,Y1;P2,Y2;…)

The expression X, which is passed by value, is matched against each of the patterns P in turn, and as soon as a matching pattern is found, the corresponding value Y is returned, with the variables in the pattern bound to the corresponding values using lambda. A pattern of `_' can be used to denote the default case. If no case matches then case raises a syserr 8 exception.

Some examples:

 
fac N                   = cond (N>0, N*fac (N-1); true, 1);
sign X                  = cond (X>0, 1; X<0, -1; true, 0);
prod Xs                 = case Xs ([], 1; [Y|Ys], Y*prod Ys);
reply X                 = case X
                          ("y" , true;
                           "n" , false;
                           _   , throw "bad reply");

As of Q 7.7, there are also variations of cond and case, named condfun and casefun, which take the data to be analyzed as the second argument. These constructs can be used to create anonymous conditional and pattern-matching functions, respectively:

 
condfun (P1,F1;P2,F2;…) X
casefun (P1,Y1;P2,Y2;…) X

Note that casefun works exactly like case, but the arguments are reversed, so the above reply function could also be defined with an implicit parameter, as follows:

 
reply                   = casefun
                          ("y" , true;
                           "n" , false;
                           _   , throw "bad reply");

In contrast, condfun interprets each branch (P,F) as a pair of a predicate P and a function F which are to be applied to condfun's second "data" parameter X. Going through the tuple of branches, condfun returns the first value F X for which P X evaluates to true. Thus condfun works like cond except that the constituents of each branch are not constant values, but functions to be applied to the data parameter. For instance, here's an alternative way to define the sign function from above:

 
sign                    = condfun ((>0), cst 1; (<0), cst (-1);
                                   cst true, cst 0);

The dowhile function implements a simple looping construct which keeps re-evaluating the expression in the second argument as long as the condition in the first argument evaluates to true. Both arguments are special. The result is always (). This construct obviously makes sense only with expressions involving side-effects. For instance:

 
==> def F = fopen "/etc/passwd" "r"

==> dowhile (not feof F) (writes (freads F++"\n"))

The for function provides a means to iterate an operation with side-effects over tuples, lists and streams. It takes a tuple of clauses in the first argument, which has the same format as the second argument of a comprehension (see below). The second argument is then evaluated for each binding, performing parameter binding using lambda. The result is always (). Example:

 
==> for (I in [1..3],J in [1..I]) (write (I,J) || writes " ")
(1,1) (2,1) (2,2) (3,1) (3,2) (3,3) ()

The listof function allows to specify a list of values in a manner similar to the way sets are described in mathematics:

 
listof X (Y1, Y2, …)

This construct is also commonly called a list comprehension. For convenience, the Q language provides syntactic sugar for list comprehensions so that they can also be written as follows:

 
[X : Y1, Y2, …]

(Note that in scripts this alternative notation is only permitted on the right-hand side of equations and variable definitions, as the colon `:' is already used to denote type guards in left-hand side expressions. So in the unlikely case that you have to extend the definition of listof you will have to use the first syntax from above.)

The expressions Y1, Y2, … may either be so-called binding clauses or conditional clauses. A binding clause is an expression of the form Z in Zs, using the relational operator in, which is declared as follows:

 
public const (in) X Y @ 2; // relational in operator

A binding clause specifies that the pattern Z should be matched in turn to each member of the list Zs; only values matching the pattern will be extracted, and free variables in the pattern are bound to their corresponding values using lambda. Binding clauses are considered from left to right, which means that a clause may refer to any variable introduced in an earlier binding clause.

Any other expression specifies a conditional clause which must evaluate to a truth value; only those elements will be listed for which the conditional clause is satisfied.

Note that, as of Q 7.8, binding clauses may actually draw values from any combination of tuples, lists and streams. The result of the list comprehension is always a list no matter which kind of sequences the values come from. This also works analogously with the other type of comprehensions discussed below.

As an example, here is a function which computes the prime numbers up to a given integer N using Erathosthenes' sieve. Note the list comprehension [Y:Y in Xs,Y mod X<>0] in the second equation which is used to extract all numbers which are not divisible by the first list member (which is always a prime by virtue of the construction).

 
primes N                = sieve [2..N];
sieve [X|Xs]            = [X|sieve [Y:Y in Xs,Y mod X<>0]];
sieve []                = [];

The tupleof function works completely analogous, except that it generates tuples instead of lists. It also uses the same kind of syntactic sugar, but the expression is surrounded by ordinary parentheses instead of brackets. These constructs are also known as tuple comprehensions.

Similarly, the streamof function implements stream comprehensions. It works like listof, but in a lazy fashion and returns a stream instead of a list as the result. The Q language provides syntactic sugar for stream comprehensions, so that they look like list comprehensions, using curly braces instead of brackets.

Here is the same prime sieve algorithm as above, formulated with streams instead of lists. Instead of a list of all primes up to a given limit it simply generates the infinite stream of all prime numbers:

 
primes                  = sieve {2..};
sieve {X|Xs}            = {X|sieve {Y:Y in Xs,Y mod X<>0}};

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.10 Mathematical Functions

The math.q script defines the const variables inf and nan, which denote the special IEEE floating point values for (positive) infinity and NaN ("not a number"), and the following additional operations on floating point numbers:

floor X, ceil X

round to the nearest integer below and above the given number

asin X, acos X, tan X

additional trigonometric functions

lg X, log X

base 2 and 10 logarithms

sinh X, cosh X, tanh X

hyperbolic functions

asinh X, acosh X, atanh X

inverse hyperbolic functions


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.11 Complex Numbers

The complex.q script implements complex numbers. As of Q 7.7, Complex is now implemented as an abstract data type, very much like Rational (cf. Rational Numbers). A complex value with real part X and imaginary part Y is represented as X+:Y, employing the virtual constructor `+:', which is implemented as a binary infix operator with the same precedence as `+'. (The alias (:+) for (+:) is provided for Haskell compatibility.) Of course, to construct a complex value you can also use the more customary notation X+i*Y, where the constant i, which is implemented as a const variable, denotes the imaginary unit 0+:1.

The script overloads the usual arithmetic operations (including exponentiation), sqrt, exp, logarithms, trigonometric and hyperbolic functions so that they also work with complex numbers. The following basic operations are also provided:

abs Z, arg Z

absolute value and argument

re Z, im Z

real and imaginary part

re_im Z

returns a pair with both the real and the imaginary part

conj Z

complex conjugate

cis X

the complex exponential cis X = exp (i*X) = cos X + i*sin X

polar R X

convert polar coordinates to complex number, polar R X = R*cis X

Note that cis and polar are only defined on Real arguments. The other operations (including the virtual constructor `+:') work consistently on both real and complex numbers. The arg function returns the polar angle (in radians), thus (abs Z,arg Z) denotes the polar coordinates of a complex number Z. Conversely, polar R X converts the polar coordinates (R,X) back to the corresponding complex number.

Some examples:

 
==> 2^(1/i)
0.769238901363972 +: -0.638961276313635

==> lg _
0.0 +: -1.0

==> (abs _,arg _)
(1.0,-1.5707963267949)

Please note that the virtual constructor `+:', just like Haskell's `:+' constructor, is really an operator symbol with the same precedence as `+'. Thus an expression like 0+:1 is not "atomic", but has the same precedence and associativity as all addition operators. This yields results which might be somewhat surprising for the uninitiated. For instance, consider:

 
==> 1+:2*3+:4
1+:10

This result is indeed correct, as the input expression is parsed as 1+:(2*3)+:4 = (1+:6)+:4 and not as (1+:2)*(3+:4) = -5+:10. (Note that, unlike Haskell's `:+', Q's `+:' operator can be applied to both real and complex operands, so that `Z1+:Z2' will yield the same as Z1+i*Z2 in any case.)


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.12 Rational Numbers

Thanks to the work of Rob Hubbard, Q versions 7.2 and later also include the rational.q script which implements the rational number type Rational which is a subtype of Real. Please note that at present this module only provides the data type and the basic arithmetic. More advanced approximation and formatting operations for rational numbers can be found in a separate add-on package available from the Q website which also includes additional documentation [Hubbard 2006].

The module overloads the usual arithmetic operations as well as the functions abs, sgn, round, trunc, int, frac and pow (the latter comes from the clib module), and provides the following additional operations:

rational X

create a rational number from an integer, or a pair of integers (numerator, denominator)

num Q, den Q

normalized numerator and denominator (numerator and denominator are coprime and the sign is always in the numerator)

num_den Q

returns a pair of integers with the normalized numerator and denominator

Last but not least, the module also implements the exact division operator `%' (with the same precedence as `/') which returns a rational or complex rational number for each combination of integer, rational and complex integer/rational arguments; for any other arguments of type Num `%' behaves like the `/' operator. The `%' operator is actually implemented as a virtual constructor of the Rational type (cf. Views), and rational.q provides a corresponding default view for rational numbers in the format N%D, where N and D are the normalized numerator and denominator, respectively.

Examples:

 
==> 5%7 + 2%3
29%21

==> 3%8 - 1%3
1%24

==> pow (11%10) 3
1331%1000

==> pow 3 (-3)
1%27

==> num_den _
(1,27)

==> rational _
1%27

Since Rational is a subtype of Real, operations on complex numbers with rational components also work as expected:

 
==> (1+:2)%(3+:4)
11%25+:2%25

==> var sqr = \X.X*X; sqr (5+:-5%18)
8075%324 +: -25%9

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.13 Graphics

The graphics.q script implements an interface to Adobe's PostScript language [Adobe 1990]. PostScript is a page description language which has become one of the main standards in the desktop publishing world. The nice thing about PostScript is that page descriptions are device-independent - the same page description can be used for different output devices such as a screen previewer or a laser printer. The graphics.q script allows you to produce graphics output on any PostScript device. Note that, as already pointed out, this script does not belong to the set of "standard" scripts included by the prelude, and hence has to be imported explicitly if you want to use the operations described in the following.

The graphics device is implemented by the GRAPHICS variable, which by default is assigned to standard output. This is useful for taking a look at the generated PostScript code, e.g., for debugging purposes, but in a real application you will of course redirect the output to some PostScript file or device, which can be done by assigning a suitable value to the GRAPHICS variable. Any file object open for writing will do, however the script also provides the following convenience functions which each return an output file or pipe which can be used as the value of the GRAPHICS variable:

gsdev

pipe to the ghostscript program (see below)

gvdev

pipe to ghostview (see below)

lpdev

printer device (usually a pipe to lpr(1))

filedev NAME

output file with name NAME

nulldev

the null device (a synonym for filedev "/dev/null", or filedev "nul" under DOS/Windows)

For instance, you define the graphics device as a pipe to ghostscript as follows:

 
def GRAPHICS = gsdev;

You can either add this definition to your main script, or enter it directly at the command prompt of the interpreter (see Command Language).

Ghostscript is a popular PostScript previewer available for a wide range of different platforms. Ghostview is an improved X interface for ghostscript. A similar program, GSView, is also available for the Windows operating system. Note, however, that GSView cannot read its input from a pipe, hence gvdev is not directly supported on Windows. To preview your PostScript output under Windows, you can either use gsdev, or employ filedev to set up an output file and then invoke GSView manually. For instance (assuming that the gsview32 program is on your path):

 
==> def GRAPHICS = filedev "graphics.ps"

==> // output your PostScript graphics here ...

==> !gsview32 graphics.ps

Also note that on most systems output to a pipe created with popen is buffered, thus you might have to flush buffered data when using gsdev or gvdev as the graphics device. In addition, it might be necessary to invoke flushpage to force an immediate display update, see Overview of Graphics Operations. This can be done as follows:

 
==> flushpage || fflush GRAPHICS

If output goes to a printer or a file, you will probably need a minimal header which identifies the file as a PostScript document. To include such a header in the output file, use the psheader function before invoking any other graphics operation:

 
==> psheader

You can also set up a custom header and include other DSC and EPSF comments by means of the ps function; see DSC and EPSF Comments, for details.

In the following we give an overview of the graphics operations in the PostScript language, as they are provided by this module, and describe the implemented functions. For more details about PostScript please refer to [Adobe 1990].


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.13.1 Coordinate System

The PostScript coordinate system has its origin (0,0) in the lower left corner of the output page or display window, with the positive X and Y axes extending horizontally to the right and vertically upward, respectively. The default unit length is 1 point which is 1/72 of an inch.

The origin of the coordinate system, as well as the unit lengths and orientation of the X and Y axes can be changed by means of the translate, scale and rotate operations, cf. Graphics State.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.13.2 Overview of Graphics Operations

The process of painting a graphics object usually consists of the following three steps:

A path is an ordered sequence of straight and curved line segments. The individual segments may be connected to each other or they may be disconnected. Thus a path may consist of several connected pieces which are referred to as the subpaths of the path. In a subpath, each line segment starts at the point where the previous segment ends. The newpath function is used to begin a new path. A new subpath is obtained by invoking moveto which specifies the first point in the subpath. Various operations are provided to add straight and curved line segments to the current subpath. For instance, a path consisting of three straight line segments may be denoted as follows:

 
newpath || moveto 0 0 || lineto 1 0 || lineto 1 1 || lineto 0 1

The last point on the current subpath can be connected back to its starting point (usually the last point specified with moveto) by closing the subpath with the closepath operation. For instance, a rectangle is specified as follows:

 
newpath || moveto 0 0 || lineto 1 0 || lineto 1 1 || lineto 0 1 ||
closepath

Having constructed a path, the stroke function draws the line segments contained in the path. Alternatively, fill may be used to fill the interior of the path (for this purpose the entire path should consist of closed subpaths).

The precise appearance of stroked and filled objects on the output page is controlled by a collection of parameters referred to as the graphics state. Various operations are provided for changing these parameters. For instance, you can set the linewidth and dash pattern used by stroke, the color used by the stroke and fill operations, and the scale and translation of the coordinate axes. The current settings can be saved on a stack using gsave and restored (popped from the stack) with grestore.

Another important parameter is the current clipping path which specifies the regions on the page which can be affected by the painting operations. By default, the paintable area is the whole page. In order to restrict painting to a user-defined region, a path is constructed as usual, and then the clip function is used to set this path as the clipping path. Subsequent paint operations will only paint the interior of the clipping path, i.e., the region which would have been filled had we applied the fill operation instead of clip to the constructed path. Multiple applications of clip are accumulative. That is, clip intersects the current clipping area (as defined by previous invocations of clip) with the interior of the current path.

The treatment of textual output is somewhat special. It is possible to define a path consisting of the outlines of the characters in a given text string by means of the charpath function. More commonly, however, text strings are simply displayed at a given position which is accomplished by means of the show function. For instance, to display a text string S at a position (X,Y) on the current page the following expression is used:

 
moveto X Y || show S

The graphics.q script also provides several operations which deal with a graphics page as a whole. First of all, showpage emits the current page, and prepares for the next page by erasing the current page. The copypage operation is like showpage, but keeps the contents of the current page. This allows you to accumulate the contents of several pages. Both showpage and copypage are mainly used when output goes to a printer.

Two additional operations are provided for interactive use, when output goes to a display window. The erasepage function causes the contents of the current page to be erased. The flushpage operation updates the display, like showpage or copypage, but does not start a new page. (To improve performance, graphics output under the X window system is usually performed in larger chunks. The flushpage operation is required to synchronize the display by flushing any unwritten data.) Note that this operation is not part of the PostScript standard, but only works with Ghostscript and possibly some similar Postscript viewers.

If you want to achieve special effects which cannot be implemented in terms of the operations provided by graphics.q, you can directly invoke PostScript commands by means of the ps function. Also, you can copy a PostScript file to the graphics device with the psfile operation. As an example for the ps function, operations to display a string right-justified or centered at the current position can be implemented as follows:

 
showright S:String      = ps (psstr S++
                        " dup stringwidth pop neg 0 rmoveto show\n");
showcenter S:String     = ps (psstr S++
                        " dup stringwidth pop 2 div neg 0 rmoveto show\n");

(The psstr function converts a string to PostScript syntax; see Miscellaneous Operations.) The ps function is also useful to include DSC and EPSF comments in your graphics output if this is necessary. See DSC and EPSF Comments, for details.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.13.3 Path Construction

The graphics.q script defines the following collection of operations to define the current path used by the painting and clipping operations:

newpath

start a new path

closepath

close the current subpath

clippath

set the current path to the current clipping path

moveto X Y

absolute move to position (X,Y)

rmoveto DX DY

move relatively by DX units in horizontal and DY units in vertical direction

lineto X Y

straight line segment between the current point and absolute location (X,Y)

rlineto DX DY

straight line segment specified by displacement (DX,DY) with respect to the current point

curveto X1 Y1 X2 Y2 X3 Y3

Bezier cubic section between the current point and (X3,Y3), using (X1,Y1) and (X2,Y2) as control points

rcurveto DX1 DY1 DX2 DY2 DX3 DY3

Bezier cubic section, with the points specified as displacements with respect to the current point

arc X Y R A1 A2

arc of a circle with radius R centered at location (X,Y) starting and ending at angles A1 and A2 (0<=A1,A2<=360), respectively; if there is a current point, it is connected by a straight line segment to the first point on the arc

narc X Y R A1 A2

negative arc; the arc is drawn in clockwise rather than in counter-clockwise direction

arct X1 Y1 X2 Y2 R

arc specified by tangent lines; the center of the arc is located within the inner angle of the tangents, with the first tangent connecting the current point and (X1,Y1), and the second tangent connecting (X1,Y1) and (X2,Y2)

charpath S T

path consisting of the character outlines that would result if the string S where shown at the current point using show; T is a truth value denoting whether the path should be used for stroking to draw the character outlines (T = false) or whether the path should be adjusted for use with fill or clip (T = true)


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.13.4 Painting

The following operations are provided for stroking and filling, and for displaying text:

stroke

draw the line segments in the current path

fill, eofill

fill the interior of the current path (any unclosed subpaths of the current path are closed automatically)

show S

paint string S at the current point

The fill function uses the "nonzero winding number" rule for determining which points lie "inside" the current path, while eofill uses the "even-odd" rule. Please refer to [Adobe 1990] for the details.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.13.5 Clipping

The following operations are used to determine the current clipping path, as described in Overview of Graphics Operations:

clip, eoclip

intersect the current clipping area with the interior of the current path

The clip and eoclip operations use the same rules for insideness testing as fill and eofill, respectively, see Painting.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.13.6 Graphics State

As already indicated in Overview of Graphics Operations, the PostScript graphics state is a collection of parameters which control the behavior of the graphics operations. The graphics.q script provides the following operations to manipulate these parameters:

gsave

save the current graphics state

grestore

restore the previously saved graphics state

savematrix

push the current transformation matrix (CTM) on the PostScript stack; the CTM is manipulated by the translate, scale and rotate operations, see below

restorematrix

restore the CTM from the stack

translate TX TY

move the origin of the coordinate system TX units in horizontal and TY units in vertical direction

scale SX SY

scale the unit lengths of the coordinate axes by SX in horizontal and SY in vertical direction

rotate A

rotate the coordinate system by an angle of 0<=A<=360 degrees

setlinewidth X

set the line width to X units

setlinecap N

set the line cap style (0 = butt caps, 1 = round caps, 2 = projecting square caps)

setlinejoin N

set the line join style (0 = miter joins, 1 = round joins, 2 = bevel joins)

setdash Xs DX

set the dash pattern (see below)

setgray X

set the gray shade (0 = black, 1 = white)

setrgbcolor R G B

set the color in the RGB model (R = red, G = green, B = blue)

sethsbcolor H S B

set the color in the HSB model (H = hue, S = saturation, B = brightness)

setcmykcolor C M Y K

set the color in the CMYK model (C = cyan, M = magenta, Y = yellow, K = black)

setcolor C

set the color specified by symbolic color value C (see below)

setfont S X

select font S scaled by X units (see below)

The setrgbcolor, sethsbcolor and setcmykcolor functions enable you to select arbitrary colors in the RGB, HSB and CMYK model, respectively. A more user-friendly, but less flexible, routine setcolor is provided which allows colors to be selected from a fixed set of symbolic constants implemented by the Color type. Please refer to graphics.q for a list of the possible color values.

The setdash function sets the dash pattern for straight and curved line segments. The first argument of setdash is a list of length values which alternately specify the lengths of the "on" and "off" segments of the line (i.e., dashes and gaps between the dashes). This list is cycled through by the stroke function. For instance, setdash [2,1] 0 specifies the dash pattern "2 on, 1 off, 2 on, 1 off, …". If the list is empty (setdash [] 0) stroke produces solid lines. The second argument of setdash denotes the "phase" of the dash pattern, which is given by an offset into the pattern. E.g., setdash [2,3] 11 denotes the pattern "1 on, 3 off, 2 on, 3 off, 2 on, …".

The setfont function takes as its first argument a string denoting a PostScript font name such as "Times-Roman" or "Helvetica-Oblique". The second argument denotes the size in units to which the font should be scaled. For instance: setfont "Helvetica" 10. (This function is implemented by a combination of the PostScript operators findfont, scalefont and setfont.)


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.13.7 Miscellaneous Operations

showpage

emit the current page

copypage

like showpage, but do not erase the contents of the current page

flushpage

update the display (flush any buffered graphics)

erasepage

erase the contents of the current page

copies N

number of copies to be emitted with showpage

psfile NAME

copy a PostScript file to the graphics device

psstr S

convert a string to PostScript syntax

psheader

output a minimal PostScript header

ps CMD

output a PostScript command

The showpage, copypage, flushpage and erasepage functions have already been discussed in Overview of Graphics Operations. The copies operation determines the number of copies which should be printed when showpage is invoked:

 
==> copies 4 || showpage

To submit a PostScript file to the graphics device the psfile operation may be used. It takes one string argument, the name of the file. For instance:

 
==> psfile "foo.ps"

The ps function is used to directly invoke a PostScript command. Examples can be found in Overview of Graphics Operations. The psstr function converts a string to PostScript format. It takes care of embedded backslashes and parentheses. For instance:

 
==> writes (psstr "(silly\\) example") || writec "\n"
(\(silly\\\) example)
()

The psheader function is used to begin the output file with a minimal header identifying the file as PostScript; see DSC and EPSF Comments.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.13.8 DSC and EPSF Comments

Appendix G and H of [Adobe 1990] define a standard set of comments which should be included in PostScript documents to make explicit the document structure, and to allow inclusion of PostScript files in other documents. These standards are known as the document structuring conventions (DSC) and the encapsulated PostScript file (EPSF) format. See [Adobe 1990] for a detailed discussion of the purpose of these formats.

The graphics.q script currently does not provide any specialized operations for sending DSC and EPSF comments to the graphics device, with the exception of the psheader function which outputs a minimum header to make your printer recognize a graphics file as PostScript. Invoke this function as follows, before calling any other graphics operation:

 
==> psheader

You can also call the psheader function at initialization time from within a script, using a line like the following:

 
def INIT = psheader;

To include other types of DSC and EPSF comments in the graphics output, you have to specify these comments explicitly using the ps function. For instance, a function writing out the necessary DSC header comments of an EPS file may be implemented as follows:

 
/* (X1,Y1) and (X2,Y2) denote the lower left and the upper right corner
   of the bounding box, respectively */
epsf_header X1:Real Y1:Real X2:Real Y2:Real
                        = ps "%!PS-Adobe-3.0 EPSF-3.0\n" ||
                          ps ("%%BoundingBox: "++join " "
                              [str X1, str Y1, str X2, str Y2]++"\n");

As indicated, each comment must be terminated by a newline character. Use the epsf_header function in place of the psheader function if you are composing an EPS file which is to be used in other documents. E.g., when invoked as epsf_header 5 5 105 105, the following header information will be written to the graphics device:

 
%!PS-Adobe-3.0 EPSF-3.0
%%BoundingBox: 5 5 105 105

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

11.14 Diagnostics and Error Messages

The assert.q script supplies the special form assert for printing diagnostic messages:

 
foo X                   = assert (X>0) || bar (1/X);

The assert function verifies that the given expression evaluates to true, in which case it returns (). Otherwise it uses the error function to abort evaluation after printing an error message of the following form:

 
! Error: assertion (X) failed, value (value of X)

Error messages are printed using the error operation of the error.q script which prints an error message and then simply stops evaluation using halt. For instance:

 
hd []                   = error "hd: empty list";

This will print an error message

 
! Error: hd: empty list

when executed, and halt evaluation.


[ << ] [ >> ]           [Top] [Contents] [Index] [ ? ]

This document was generated by Albert Gräf on February, 23 2008 using texi2html 1.76.