General numeric vectors: In
this section, having learned Simple Numeric Scalars, you'll learn what a
Glee vector is. You'll also learn how they behave. Dealing with
objects as vectors gives Glee much of its power.
Representing Numbers: I
waited for vectors to introduce you to number representation. It lets me
illustrate it all in two steps. Illustrated here is representation of simple
(i.e not scientific) number representation. You will note that regardless of
the number of digits given, Glee only displays 6 significant
digits. This is currently hardwired but will likely be controllable by the user
in the near future. When I present the Glee formatting operator,
you will see that you have great flexibility in the way values are displayed.
Scientific Notation:
When numbers get very large or very small they are represented in scientific
notation. As shown, the exponential annotator (e) may be capitalized (E) as
well. Numbers are recognized if they begin with a digit, a sign, or a decimal
point. For readability it is recommend that you use a leading zero for numbers
less than magnitude 1 (e.g. 0.1234) even though Glee
doesn't require it. You might try entering some bogus numbers to see how
Glee behaves (e.g. 3.4.5)
Mixed length vectors: This
example illustrates vector extension. On the left of the "+"
we have the vector "1 2 3". We are to add that to
"4". When Glee sees two vectors that don't
match up, it forces them to match up. We need more numbers on the right
(there's only one and we have three on the left). Glee extends
vectors by doing what is called a "right take". In this case it's
doing a "right take 3". Glee starts at the right side
of the short vector (the "4") and begins taking numbers as
it works left (it only has one and it takes the "4"). When
it runs out (in this case that happens immediately), it remembers the last
number it took and replicates that. There's a better example later, but for
here, Glee takes "1 2 3" +
"4 4 4" and yields "5 6 7".
Vector Right (incorrect:)
At first look, you would expect this code to yield "3 4 5".
But you must remember the left to right rule. Glee picks up the
"1"; picks up the "+"; picks up the
"2"; performs the addition yielding "3";
picks up the "3" and forms a vector; picks up the
"4" and catenates yielding "3 3 4". This
is likely not what we wanted. It's one of those things we must watch for in
Glee. The solution is parenthetical grouping shown next.
Vector Right (done
correctly) We correct the problem in the previous example by using
parenthesis to group the order of execution. Here, Glee picks up
the "1" and "+" as before. But then it
sees the "(" and knows it must evaluate the parenthetical
expression before completing the addition. Glee picks up the
"2", "3", and "4" in
turn forming the three element vector. It then picks up the
")" which it matches with the "(" and
knows it can return the grouped contents "2 3 4". This
vector becomes the right argument to the "+".
Glee then (implicitly) performs vector extension of the left
argument yielding "1 1 1". It can now produce the final
result "(1 1 1)+(2 3 4)=(3 4 5)".
Take on left argument: We
noted earlier that Glee matches up argument lengths before
proceeding with an operation. In this example, we have two elements on the left
and three on the right. Glee does a Right Take 3 on the left
yielding "0 0 1". This matches the right length of 3. So
Glee then performs the operation "(0 0 1)+(2 3 4)=2 3
5. This illustrates what you can do if you want take to zero fill instead
of left element fill on a right take.
Need Parenthesis: Looking at
this expression you probably expected "5 7 9". But we get
"5 6 7 5 6". Remembering the left to right rule:
Glee picks up the "1", "2",
and "3" forming "(1 2 3)". It picks up
the "+" and the "4". It Right Takes the
"4" yielding "4 4 4". It performs the
addition "(1 2 3)+(4 4 4)=(5 6 7)". It picks up the
"5" and catenates yielding "5 6 7 5". It
picks up the 6 and catenates yielding the final result: "5 6
7 5 6". Parenthesizing as shown in the next example cures the
problem. This is something you need to be careful of in Glee.
You'll see when we start working with variables, the problem is mitigated.
Does what we expect: This is
the expression recommended to cure the problem in the previous example.
And being really safe: This is
the really safe cure and probably constitutes good Glee coding
style. When dealing with "literal" values (as in "you literally
supplied them yourself"), it's a good idea to parenthesize for readability
and safety.
Range of numbers: As a short
hand convenience, Glee allows you to enter literal ranges. This
is useful in indexing as we'll see later. Here Glee picks up the
"1"; picks up the ".." which is the range
operator; picks up the "4"; and performs the operation by
generating integers monotonically between the terminals of the range. It yields
the numeric integer vector "1 2 3 4".
Range with floats: This
example shows floats as the terminals of the range. Glee doesn't
support floats for the range operator. To do that would also require making
some kind of judgement about the increment. Maybe some day I'll figure that
out. But for now, and in the spirit of Glee's not scolding, the
floats are demoted to integers before the operation commences.
More than one range: This
appears to be an inconsistency in Glee (and Glee
hates inconsistency). It is not. I wanted to support multiple ranges so you can
more easily reach out and touch your data (more on that later). Here's how
Glee parses and executes. The parser picks up the
"1", the "..", and the
"4" and the executer invokes the (dyadic) range operator
"..". The range operator, having two scalar arguments,
creates the vector "1 2 3 4". This becomes the new left
argument. Moving on to the right, the parser picks up just the
"2" (the parser has short right scope). The executer
catenates the 2 to the left side vector giving "1 2 3 4
2" as the new left argument. The parser now picks up the next
"..". Dyadic operators take precedence over monadic, so the
parser looks futher to the right to check for dyadic. It finds the _2
which is data (i.e. not an operator; not an opener (e.g. (,[,{ );
not a statement separator ";"; and not the end of the
program.). So the Executer invokes the dyadic operator ".."
(range). Now ".." has a vector left argument ("1 2
3 4 2") and a scalar right argument ("_2"). In
this case the ".." operator takes the last element from the
left argument (now the "2"); peels it off (yelding 1 2 3
4); performs the scalar/scalar range operation (yielding 2 1 0 _1
_2); then catenates that result to the new left vector 1 2 3 4
and yields (1 2 3 4 2 1 0 _1 _2) for the result, which becomes the new
left argument. Glee operators take their arguments (none, left,
or left and right); perform their operation; and replace the left argument (or
become the left argument in the case of niladic operators) with their result.
In actuality, an operator can be written to produce any result in the world.
That result becomes the new left argument to the executer as the parser moves
on to the right.
Triangle wave: This range
operator is going to find most of its use in "reaching out and touching
your objects". It is part of the process of sculpting your solution. Here
we've compounded range operations to form a "triangle wave" of
indices ... not very useful probably, but cute.
Mixing ranges and literal
vectors: You can mix ranges with literal vectors of integers to achieve
lots of flexibility in building index vectors. Later you'll see the
"without" operator that further supports your needs.
Readability: When you
actually use these kinds of constructions in your code, it's probably a good
idea to use commas for readability. In Glee, the "," is
the catenation operator. In these examples, the catenation was happening
implicitly.
Implicit catenation: Another
way to gain readability is through parenthesizing. This does implicit
catenation as well.
Boolean Operations: Boolean
operations on numeric vectors deal with the complete vectors. For example, if
two vectors differ in any way, they are not equal. Relational tests like less
than ( < ) proceed from left to right, element by element. As soon as the
element test fails, a false is returned. If one vector is longer than the other
but in all other respects identical, the shorter vector is less than the
longer. GLEE does not adjust vector lengths before doing the comparison. GLEE
also has another complete set of operators for marking element by element
compares (e.g *<, *<=, *=, *~=, *>=, and *>).
Boolean Element Operations: GLEE
also has another complete set of operators for marking element by element
compares. For these operations, GLEE conforms lengths before making the element by element tests.