| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
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.qprint diagnostics
clib.qbasic C interface (*)
complex.qcomplex numbers
cond.qconditional expressions and tuple/list/stream comprehensions
error.qprint error messages
getopt.qGNU getopt compatible option parser (+)
graphics.qPostScript graphics interface (+)
math.qmathematical functions
prelude.qstandard prelude
rational.qrational numbers
reftypes.qtuples, lists and streams of references (+)
sort.qalgorithms to sort a list
stddecl.qshared declarations of the container data structures, cf. stdtypes.q (+)
stdlib.qa collection of common standard functions
stdtypes.qa collection of efficient container data structures (+)
stream.qa lazy list data structure
string.qadditional string functions
system.qPOSIX system interface (*) (+)
tuple.qadditional tuple functions
typec.qtype-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] | [ ? ] |
The stdlib.q script provides frequently used list operations and
other stuff mostly adopted from [Bird/Wadler 1988].
abs Xabsolute value of X
all P Xsverify that each element of the list Xs satisfies the predicate
P
any P Xsverify that the list Xs contains an element satisfying predicate
P
append Xs Xappend a value X to the list Xs
cat Xsconcatenate a list of lists
cons X Xsprepend an element to a list
cst Xconstant-valued function: cst X Y ⇒ X
curry Fcurry a function: turn a function operating on pairs into a function with two arguments
curry3 Fcurry with three arguments
do F Xsapply a function F to each member of a list Xs, return
()
dowith F Xs Ystake two lists and apply a binary function to corresponding elements,
return ()
dowith3 F Xs Ys Zsdowith with three lists
drop N Xsremove the first N elements from the list Xs
dropwhile P Xsremove elements from the beginning of Xs while the predicate P
is satisfied
eq X Ysyntactic equality (cf. Non-Linear Equations)
filter P Xsfilter a list with a predicate
foldl F A Xsfold-left
foldl1 F Xsfold-left over nonempty lists
foldr F A Xsfold-right
foldr1 F Xsfold-right over nonempty lists
hd Xsreturn the head element of a list
hds Xsreturn the list of all head elements in a list of lists
idthe identity function: id X ⇒ X
init Xsreturn list Xs without its last element
iter N F Agenerate the list of the first N values A, F A,
F (F A), …
last Xsreturn the last element of a list
map F Xsapply function F to each member of a list
max X Ymaximum of two values
min X Yminimum of two values
mklist X Ncreate a list of N X's
neg Pnegate a predicate
neq X Ysyntactic inequality
null Xscheck whether a list is empty ([])
nums N Mgenerate a list of numbers in a given range
numsby K N Mgenerate a list of numbers with a given step size
pop Xsremove the head element from a list
prd Xsproduct of a list of numbers
push Xs Xprepend an element to a list (cons with arguments reversed)
reverse Xsreverse a list
scanl F A Xsapply foldl to every initial part of a list
scanl1 F Xsapply foldl1 to every nonempty initial part of a list
scanr F A Xsapply foldr to every final part of a list
scanr1 F Xsapply foldr1 to every nonempty final part of a list
sgn Xsign of a number
sum Xssum of a list of numbers
take N Xsselect the first N elements from the list Xs
takewhile P Xsselect elements from the beginning of Xs while the predicate P
is satisfied
tl Xsremove the head element from a list
tls Xsreturn a list of lists with all head elements removed
top Xsreturn the head element from a list
transpose Xstranspose a list of lists
uncurry Funcurry a function: turn a function with two arguments into a function operating on pairs
uncurry3 Funcurry with triples
until P F Xrepeat applying F to X until P is satisfied
unzip Xstransform a list of pairs into a pair of lists
unzip3 Xsunzip with triples
while P F Alist repeated applications of F to A while P is
satisfied
zip Xs Ystake two lists and return a list of corresponding pairs
zip3 Xs Ys Zszip with three lists
zipwith F Xs Ystake two lists and map a binary function to corresponding elements
zipwith3 F Xs Ys Zszipwith 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] | [ ? ] |
The tuple.q script provides some additional functions operating
on tuples:
fst Xsreturn first element of a tuple
mktuple X Ncreate a tuple of N X's
pair X Yconstruct a pair
snd Xsreturn second element of a tuple
trd Xsreturn third element of a tuple
triple X Y Zconstruct a triple
tuplecat Xsconcatenate 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] | [ ? ] |
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 Sreturn the list of individual characters in S
join DELIM Xsconcatenate a list of strings, interpolating the given DELIM string
between each pair of consecutive strings in the list
mkstr S Ncreate a string consisting of N copies of the given string S
split DELIM Ssplit a string into a list of substrings delimited by characters in the
given DELIM string
strcat Xsconcatenate 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] | [ ? ] |
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] | [ ? ] |
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 Xcheck for truth values
ischar Xcheck for single character strings
iscomplex Xcheck for complex numbers (cf. Complex Numbers)
isexcept Xcheck for Exception values (cf. Exception Handling)
isfile Xcheck for file objects
isfloat Xcheck for floating point numbers
isfunction Xcheck for lambda functions
isint Xcheck for integers
islist Xcheck for lists
isnum Xcheck for numbers
isrational Xcheck for rational numbers (cf. Rational Numbers)
isreal Xcheck for real numbers
isstr Xcheck for strings
issym Xcheck for function and variable symbols (special form)
istuple Xcheck 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 Xcheck for complex values
isintval Xcheck for integer values
isratval Xcheck for rational values
isrealval Xcheck 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 Xcheck for exact numbers
isinexact Xcheck for inexact numbers
isinf Xcheck for infinite floating point values
isnan Xcheck for NaN floating point values
Finally, two other special-purpose predicates provided in typec.q
are:
isenum Xcheck for enumeration type members
issym Xcheck for function and variable symbols (special form)
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
The sort.q script provides mergesort and quicksort algorithms for
sorting a list using a given order predicate:
msort P Xsmergesort algorithm
qsort P Xsquicksort 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] | [ ? ] |
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.
| 11.7.1 Arrays | ||
| 11.7.2 Heaps | ||
| 11.7.3 Sets | ||
| 11.7.4 Bags | ||
| 11.7.5 Dictionaries | ||
| 11.7.6 Hashed Dictionaries |
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
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 Xscreate an array from list Xs
array2 Xscreate a two-dimensional array from a list of lists
emptyarrayreturn the empty array
mkarray X Ncreate an array consisting of N X's
mkarray2 X (N,M)create a two-dimensional array with N rows and M columns
isarray Xcheck whether X is an array
null Acheck whether A is the empty array
A1 = A2, A1 <> A2array equality/inequality
#Asize of an array
A!Ireturn Ith member of an array
A!(I,J)two-dimensional subscript
members A, list Alist the members of A
members2 A, list2 Alist a two-dimensional array
first A, last Areturn the first and last element of an array
rmfirst A, rmlast Aremove the first and last element from an array
insert A Xinsert X at the beginning of A
append A Xappend X at the end of A
update A I Xreplace the Ith member of A by X
update2 A (I,J) Xupdate two-dimensional array
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
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:
emptyheapreturn the empty heap
heap Xsconstruct a heap from a list of its members
isheap Xdetermine whether X is a heap
null Hcheck whether H is the empty heap
H1 = H2, H1 <> H2heap equality/inequality
#Hsize of a heap
members H, list Hlist the members of H in ascending order
first Hreturn the first element of H
rmfirst Hremove the first element from H
insert H Xinsert X into H
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
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:
emptysetreturn the empty set
set Xscreate a set from a list of its members
isset Xcheck whether X is a set
null Mcheck whether M is the empty set
member M Xcheck whether M contains element X
M1 = M2, M1 <> M2set equality/inequality
M1 < M2, M1 > M2, M1 <= M2, M1 >= M2set comparison
M1 + M2, M1 - M2, M1 * M2set union, difference and intersection
#Msize of a set
members M, list Mlist the members of M in ascending order
first M, last Mreturn the first and last member of M
rmfirst M, rmlast Mremove the first and last member from M
insert M Xinsert X into M
delete M Xdelete X from M
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
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] | [ ? ] |
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:
emptydictreturn the empty dictionary
dict XYscreate a dictionary from a list of key/value pairs
mkdict Y Xscreate a dictionary from a list of keys and an initial value
isdict Xcheck whether X is a dictionary
null Dcheck whether D is the empty dictionary
member D Xcheck whether D contains X as a key
D1 = D2, D1 <> D2dictionary equality/inequality
#Dsize of a dictionary
D!Xreturn the value Y associated with X in D
members D, list Dlist the members (key/value pairs) of D in ascending order by key
keys Dlist the keys of D in ascending order
vals Dlist the corresponding values
first D, last Dreturn the first and last member of D
rmfirst D, rmlast Dremove 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 Xremove key X from D
update D X Ysame as insert D (X,Y)
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
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] | [ ? ] |
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 Xcheck whether an object is a stream
stream Xsconvert a tuple or a list to a stream
list Xsconvert a stream to a list
strict Xsforce the heads and tails of a stream (see comments below)
lazy Xsmemoize the heads and tails of a stream (see comments below)
numstream Ngenerate the stream of all numbers >=N
numstreamby K Ngenerate a number stream with given step size
mkstream Xgenerate an infinite stream of X's
repeat Xgenerate an infinite stream of X's (works like mkstream,
but is implemented as a special form and hence doesn't evaluate
X)
repeatn ~N Xgenerate a stream of N X's (special form, equivalent to
take N (repeat X))
cycle Xsgenerate an infinite stream which repeatedly cycles through the members
of the list or stream Xs
iterate F Agenerate the stream of all values A, F A, F (F A),
…
streamcat Xsconcatenate 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] | [ ? ] |
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 Xsimple conditional expressions
cond CASES, case ~X CASESmultiway and pattern matching conditional expressions
condfun CASES, casefun CASESmultiway and pattern matching conditional abstractions
dowhile P Xsimple looping construct
for CLAUSES Xiterate over lists and streams
tupleof X CLAUSES, listof X CLAUSES, streamof X CLAUSEStuple, 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] | [ ? ] |
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 Xround to the nearest integer below and above the given number
asin X, acos X, tan Xadditional trigonometric functions
lg X, log Xbase 2 and 10 logarithms
sinh X, cosh X, tanh Xhyperbolic functions
asinh X, acosh X, atanh Xinverse hyperbolic functions
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
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 Zabsolute value and argument
re Z, im Zreal and imaginary part
re_im Zreturns a pair with both the real and the imaginary part
conj Zcomplex conjugate
cis Xthe complex exponential cis X = exp (i*X) = cos X + i*sin X
polar R Xconvert 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] | [ ? ] |
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 Xcreate a rational number from an integer, or a pair of integers (numerator, denominator)
num Q, den Qnormalized numerator and denominator (numerator and denominator are coprime and the sign is always in the numerator)
num_den Qreturns 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] | [ ? ] |
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:
gsdevpipe to the ghostscript program (see below)
gvdevpipe to ghostview (see below)
lpdevprinter device (usually a pipe to lpr(1))
filedev NAMEoutput file with name NAME
nulldevthe 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] | [ ? ] |
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] | [ ? ] |
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] | [ ? ] |
The graphics.q script defines the following collection of operations
to define the current path used by the painting and clipping operations:
newpathstart a new path
closepathclose the current subpath
clippathset the current path to the current clipping path
moveto X Yabsolute move to position (X,Y)
rmoveto DX DYmove relatively by DX units in horizontal and DY units in
vertical direction
lineto X Ystraight line segment between the current point and absolute location
(X,Y)
rlineto DX DYstraight line segment specified by displacement (DX,DY) with
respect to the current point
curveto X1 Y1 X2 Y2 X3 Y3Bezier
cubic section between the current point and (X3,Y3), using
(X1,Y1) and (X2,Y2) as control points
rcurveto DX1 DY1 DX2 DY2 DX3 DY3Bezier cubic section, with the points specified as displacements with respect to the current point
arc X Y R A1 A2arc 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 A2negative arc; the arc is drawn in clockwise rather than in counter-clockwise direction
arct X1 Y1 X2 Y2 Rarc 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 Tpath 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] | [ ? ] |
The following operations are provided for stroking and filling, and for displaying text:
strokedraw the line segments in the current path
fill, eofillfill the interior of the current path (any unclosed subpaths of the current path are closed automatically)
show Spaint 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] | [ ? ] |
The following operations are used to determine the current clipping path, as described in Overview of Graphics Operations:
clip, eoclipintersect 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] | [ ? ] |
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:
gsavesave the current graphics state
grestorerestore the previously saved graphics state
savematrixpush the current transformation matrix (CTM) on the PostScript stack; the
CTM is manipulated by the translate, scale and rotate
operations, see below
restorematrixrestore the CTM from the stack
translate TX TYmove the origin of the coordinate system TX units in horizontal and
TY units in vertical direction
scale SX SYscale the unit lengths of the coordinate axes by SX in horizontal
and SY in vertical direction
rotate Arotate the coordinate system by an angle of 0<=A<=360 degrees
setlinewidth Xset the line width to X units
setlinecap Nset the line cap style (0 = butt caps, 1 = round caps,
2 = projecting square caps)
setlinejoin Nset the line join style (0 = miter joins, 1 = round joins,
2 = bevel joins)
setdash Xs DXset the dash pattern (see below)
setgray Xset the gray shade (0 = black, 1 = white)
setrgbcolor R G Bset the color in the RGB model (R = red, G = green, B =
blue)
sethsbcolor H S Bset the color in the HSB model (H = hue, S = saturation,
B = brightness)
setcmykcolor C M Y Kset the color in the CMYK model (C = cyan, M = magenta,
Y = yellow, K = black)
setcolor Cset the color specified by symbolic color value C (see below)
setfont S Xselect 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] | [ ? ] |
showpageemit the current page
copypagelike showpage, but do not erase the contents of the current page
flushpageupdate the display (flush any buffered graphics)
erasepageerase the contents of the current page
copies Nnumber of copies to be emitted with showpage
psfile NAMEcopy a PostScript file to the graphics device
psstr Sconvert a string to PostScript syntax
psheaderoutput a minimal PostScript header
ps CMDoutput 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] | [ ? ] |
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] | [ ? ] |
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.