Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
94 lines (81 sloc) 4.01 KB
Write a monadic function that puts a frame around a text matrix.
The solution given in the book works well for matrices of scalars, i.e., those
generated from expressions like 3 3⍴'ab a abc'. For them, the result will be
rendered as intended:
+---+
|ab |
|a |
|abc|
+---+
3-by-1 matrices of text vectors, e.g., generated by 3 1⍴'ab' 'a' 'abc', will
however be rendered like this:
+ - +
| ab |
| a |
| abc |
+ - +
There are two problems with this:
1. There isn't a correct amount of minus signs because a single minus sign is
prepended and appended, instead of a number of minus signs that corresponds
to the number of characters in the (longest line of the) text matrix.
2. The left and right boundaries are added as extra columns rather than being
prepended and appended to the individual text lines.
This can be addressed by providing logic that ravels the 3-by-1 matrix and
then turns it into a 3-by-3 one.
More generally speaking, we want a function that accepts a N-by-1 matrix of
text vectors and converts that into a N-by-M matrix of character scalars,
where M is the length of the longest vector in the matrix.
Happily, there is the format function (↑) that allows for doing just that in
combination with ravel; this combination turns the N-by-1 matrix into the kind
of matrix that is intended.
The below function is the solution from the book, with the extra bit added
that allows formatting of matrices of text vectors. However, that function
does not work for matrices of character scalars (unlike the book's solution).
FramedText Frame Text;nr;nc
FramedText ,Text
FramedText '-',[1]FramedText,[1]'-'
FramedText '|',[2]FramedText,[2]'|'
nr nc FramedText
FramedText[1,nr;1,nc] '+'
That's a bit unfortunate.
When we look at the second element of the shape of Text, we can see if we have
a 1-column matrix of text vectors (then that value is 1), or a larger number
in case we have a matrix of character scalars. The minimum of that number and
2 can be used as an index into a nested array containing both the
ravelled-and-formatted and the original version of Text, to make sure we end
up processing the right one. We also have to use the disclose function (⊃) to
extract the value from the nested array (which we haven't officially seen
yet).
Here goes:
FramedText FrameSecure Text;nr;nc
FramedText (2 (,Text) Text)[2 (Text)[2]]
FramedText '-',[1]FramedText,[1]'-'
FramedText '|',[2]FramedText,[2]'|'
nr nc FramedText
FramedText[1,nr;1,nc] '+'
Now this one works for our both examples above, but fails for a 3-by-1 matrix
of character scalars. This is because the conditional logic in the first line
of the function turns such matrices into vectors. These have to be converted
back to matrices by doing a similar stunt again. Checking the rank of the
result yields an index for a similar lookup.
FramedText FrameReallySecure Text;nr;nc
FramedText (2 (,Text) Text)[2 (Text)[2]]
FramedText (2 (((FramedText),1)FramedText) FramedText)[⍴⍴FramedText]
FramedText '-',[1]FramedText,[1]'-'
FramedText '|',[2]FramedText,[2]'|'
nr nc FramedText
FramedText[1,nr;1,nc] '+'
Phew.
In the second part of the exercise, the job is to output the frame with nicer
characters.
FramedText Frame2 Text;nr;nc
FramedText (2 (,Text) Text)[2 (Text)[2]]
FramedText (2 (((FramedText),1)FramedText) FramedText)[⍴⍴FramedText]
FramedText (⎕UCS 9472),[1]FramedText,[1](⎕UCS 9472)
FramedText (⎕UCS 9474),[2]FramedText,[2](⎕UCS 9474)
nr nc FramedText
FramedText[(1 1) (1 nc) (nr 1) (nr nc)] ⎕UCS 9484 9488 9492 9496
You can’t perform that action at this time.