There are other types of queues and functions in Q-BAL than queues of
numbers and functions on numbers. There are queues of queues, or functions on
queues, or queues of functions. These are declared with a variable number of
Q
s and F
s for the type section of a declaration.
For example, FQ sort
would declare a function on queues. In
general, a "queue" or "function" refers to a queue of numbers or a function
on numbers. An example of a use of a queue of queues follows:
QQ x Q y y = 'in *$y -> x ; - 3\(#y != 0) -> ; $x -> 'out ; - 2\(#x != 0) -> ; ; ->
This complete program will read strings until a null string is entered (return with no other characters), and then print them all out in the same order they were entered, followed by a blank line. (Don't worry about understanding it now; we'll refer back to it as we go on.)
When an assignment or attachment includes different data types, the
"Greatest Common Denominator Rule" is used to determine how the data is
manipulated. The GCD of two types is the largest string of Q
s
and F
s that is common to both, on the right side. In the case of
attachment, the GCD must be shorter in length than the shorter of the two
types, while in assignment it can be equal to the shorter. The GCD is the
longest data type that is manipulated. For any data type, if the GCD is more
than one letter shorter than the type in question (if the operation is
attachment) or if it is at all shorter (if the operation is assignment), then
the excess is put onto the top of the queue (or the output queue for
functions.) An example will serve to make this clearer:
FQQ x QQ y FQ z ... y -> x y = x z = y y -> z x -> z
Admittedly, you aren't likely to run across anything nearly this complex.
But it serves a good illustration. Let's take this in order. The first three
statements declare x
a function on queues of queues,
y
a queue of queues, and z
a function on queues.
The fourth line is an ellipsis, indicating that there is probably code in
between, but what it is doesn't matter. Now we're at the confusing part.
The first attachment has a GCD of Q
(it would be
QQ
, but an attachment GCD must be shorter than the shortest,
which in this case is QQ
). Therefore it works on queues. It pops
the first queue off y
(y
is a queue of queues) and
appends it to -- what? Well, excess is put onto the output queue, so it
appends it to the top queue of queues on the output queue of x
,
which is a function on queues of queues.
The second statement is an assignment with a GCD of QQ
. It
sets y
(a queue of queues) equal to the top queue of queues in
the output queue of x
(a function on queues of queues) without
popping it off x
.
The third statement is an assignment with a GCD of Q
. It sets
the top of the output queue of z
(a function on queues) equal to
the top of y
(a queue of queues) without popping it off
y
.
The fourth statement is an attachment with a GCD of Q
working
the same way between the same variables as the third statement. This one pops
the top queue off y
(a queue of queues) and appends it to the
bottom of the input queue of z
(a function on queues).
The fifth statement is an attachment with a GCD of Q
. It pops
the top queue off the top queue of queues of the output queue of
x
(a function on queues of queues) and appends it to the bottom
of the input queue of z
(a function on queues).
Got it? Good!
Remember the I/O override operators &
and @
from
advanced functions? They can apply to multiple data types as well. Normally,
excess is put on the top, or the top of the output queue, but these can force
it to be put on the bottom, or on the input queue. To this end, they can be
applied to queues as well as functions. When used in this way to functions,
sometimes they must be applied twice. The default is @
or
@@
, the top of the output queue. &
or
&&
will force it to the bottom of the input queue.
&@
will force the bottom of the output queue, and
@&
the top of the input queue. Needless to say, these are
generally considered bad form. But hey; who cares?
An object may be declared as a type ending in X
;, such as
QX
or FQX
. The X
stands for
"anything". QX
means a queue of anything, and
FQX
means a function on queues of anything. When used in an
expression, consider the X
by default to be whatever will make
the GCD the longest. If two X
-types are used in the same
expression, make both the X
s equal to whatever is at the top of
the source.
The String prefix operator $
forces the GCD to a higher
level. One use of the string on the source will raise an attachment to the
level of the smaller, if possible. For example:
QQ x Q y ... $y -> x
This code will leave y
a null queue and append to
x
(a queue of queues) what it used to be. The string operator
often leaves its operand a null queue. When used other than this, it causes
things to be strung together. For example:
Q x Q y ... $x -> y
This code will string together all of x
and append it to
y
. If x = {1,2,3}
and y = {1,4,9}
,
then after this code executes y = {1,4,9,1,2,3}
and
x
is a null queue. In general, be logical: it's usually pretty
obvious what the string operator should do in any given situation.
%
)The Diminish Prefix Operator %
is the opposite of the string
operator. It lowers the GCD by one letter. It is even more intuitive than the
string operator and needs no example.