Compose out spaces
Agenda
- write a simple lambda to remove multiple embedded blanks from a string
- rewrite the lambda as a composition.
Firing blanks
We start with a good example of how vector solutions differ from looping solutions.
A classic looping solution would iterate through the characters, keeping a blank only if the previous character was not blank.
A vector solution starts by flagging the blanks.
q)str:"The quick    brown fox  jumps."
q)1 null\str
T h e   q u i c k         b r o w n   f o x     j u m p s .
0 0 0 1 0 0 0 0 0 1 1 1 1 0 0 0 0 0 1 0 0 0 1 1 0 0 0 0 0 0
null returns a vector the same length as its argument.
It is often helpful to compare corresponding argument and result items.
(str;null str) would do that. 
The ‘Zen monks’ pattern1 1 f\ is slightly easier to type.
(But make friends with the monks: they will help us later.)
We want to flag every position which is not a blank preceded by a blank,
q)(str;null str;not prior[and] null str)
T h e   q u i c k         b r o w n   f o x     j u m p s .
0 0 0 1 0 0 0 0 0 1 1 1 1 0 0 0 0 0 1 0 0 0 1 1 0 0 0 0 0 0
1 1 1 1 1 1 1 1 1 1 0 0 0 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1
q){x where not prior[and] null x}str
"The quick brown fox jumps."
The condition of unaries
All art constantly aspires towards the condition of music.
— Walter Pater, “The School of Georgione” (1888)Walter Horatio Pater was an English essayist, art and literary critic, and fiction writer, regarded as one of the great stylists. — Wikipedia
Ken Iverson (the mathematician who devised the notation from which q’s ancestor languages APL and J derived) saw even binary operations as sequences of unaries.
Thus
2+3-4*5%6
could be read as
2+ 3- 4* 5% 6
- Taylor’s Aphorism:
- 
All q expressions constantly aspire to be sequences of unaries. 
Get composed
There is nothing wrong with the eminently legible lambda, but we can improve our grasp of q syntax by rewriting it as a composition.
First of all we note that where not prior[and] null is a sequence of unaries, so 
where not prior[and] null ::
where not prior[and] " "=
f.
f:where not prior[and] " "=
str f str. 
Consider some other ways to write that.
str f str
str@f str
@[str;f str]
.[@;(str;f str)]
.[@] (str;f str)
.[@] 1 f\str
To be precise, can 1 \f be written as a unary and so composed? 
It’s slightly tricky.
Recall that all derived functions are variadic, so in x f\ the x could be its left argument or the next unary along; i.e. x@f\.
Composing 1 f\ requires us to disambiguate. 
We do that by writing f\[1;] making it clear that variadic f\ is being projected as a binary onto left argument 1.
q)g:.[@] f\[1;] ::
q)g str
"The quick brown fox jumps."
f
q)rmeb:.[@] (where not prior[and]" "=)\[1;] ::
q)rmeb str
"The quick brown fox jumps."
Exercises
- 
Good q style prefers keywords priorto the Each Prior iterator':andandto&.Never mind: rewrite the composition using &and':. Enlightenment awaits!AnswerRecall that iterators use postfix syntax, so the following are equivalent. The parentheses make a function atom of the variadic derived function And Each Prior (prior[and] (and) prior (&':)&':).A function atom has noun syntax: it can be applied with prefix syntax – i.e. as a unary – so (&':)can be composed as a unary.q)rmeb:.[@] (where not (&':) " "=)\[1;] :: / remove multiple embedded blanks q)rmeb str "The quick brown fox jumps."
- 
The posed problem is to remove duplicate embedded spaces. The solution given also removes duplicate trailing spaces, and all leading spaces. Notice the difference below between b&prev band&':[b].In the lambda, useq)(b;prev b;b&prev b;&':[b]) 1100010000011110000010001100000011b 0110001000001111000001000110000001b 0100000000001110000000000100000001b 1100000000001110000000000100000001bandandprevinstead ofprior[and]to make a lambda that collapses all duplicate spaces.Answerq)str:" The quick brown fox jumps. " q){x where not n and prev n:null x}str " The quick brown fox jumps. "
- 
Write the previous lambda as a composition. Answerq)cws:.[@] (where not .[&] prev\[1;] " "=)\[1;] :: / collapse white space q)cws str " The quick brown fox jumps. "