[ < ] | [ > ] | [ << ] | [ 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.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] | [ ? ] |
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] | [ ? ] |
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] | [ ? ] |
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] | [ ? ] |
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 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] | [ ? ] |
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] | [ ? ] |
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 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 I
th 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 I
th member of A
by X
update2 A (I,J) X
update 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:
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] | [ ? ] |
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] | [ ? ] |
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
:
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] | [ ? ] |
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
HDict
s is more involved than for Dict
s, as the member
lists of two "equal" HDict
s 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 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] | [ ? ] |
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] | [ ? ] |
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] | [ ? ] |
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] | [ ? ] |
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] | [ ? ] |
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] | [ ? ] |
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:
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] | [ ? ] |
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] | [ ? ] |
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] | [ ? ] |
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] | [ ? ] |
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] | [ ? ] |
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.