Whoa! I never noticed this line about PREDSELECT before:
> It terminates as soon as its primary input stream is severed.
I was looking for files with APARNUM and not PTFNUM in them. I figured
I could COUNT the PTFNUMs and use the zeroes to select the APARNUMs.
Took me some digging to find why this never gave me any output:
(end /) ... | a: find APARNUM | b: predselect | ...
/ a: | find PTFNUM | count lines | strfind '0' | b:
As soon as COUNT finishes counting, PREDSELECT has seen EOF and ended
with no chance to write the last record.
Since I didn't need the alternate output, I could use CHOP 0|JUXTAPOSE
in place of PREDSELECT. For the general case, the most straightforward
workaround I see is to use TAKE|FANIN on both alternate inputs to keep
the primary open. My first thought was to use TAKE LAST 0:
(end /) ... | wait: fanin | sel: predselect | ...
/ ... | wait1: take last 0 | wait: / wait1: | sel: | ...
/ ... | wait2: take last 0 | wait: / wait2: | sel:
But that didn't reliably give me output either! When I ADDPIPE that
segment, and another stage downstream reads with CALLPIPE, it gets no
output. Using TAKE * instead does the trick:
(end /) ... | wait: fanin | sel: predselect | ...
/ ... | wait1: take * | sel: | ... / wait1: | wait:
/ ... | wait2: take * | sel: / wait2: | wait:
It turns out that TAKE LAST gets the order of the outputs backwards if
either one is empty. If there are records on both outputs, the
alternate output is severed before the primary is written, as expected:
pipe (end /) literal a b c | split | a: take last 1 | cons
| count lines | cons / a: | cons | count lines | cons
a
b
2
c
1
But TAKE LAST 0 severs the primary output immediately, before writing to
the alternate:
pipe (end /) literal a b c | split | a: take last 0 | cons
| count lines | cons / a: | cons | count lines | cons
0
a
b
c
3
And if the alternate output is empty, it doesn't appear to be severed
until the stage ends:
pipe (end /) literal a b c | split | a: take last 3 | cons
| count lines | cons / a: | cons | count lines | cons
a
b
c
3
0
DROP has a similar problem with both FIRST and LAST. DROP LAST 0 works
as expected, but DROP 0 doesn't appear to sever the alternate, and DROP
LAST doesn't appear to sever the primary if it's empty.
It's probably decades too late to consider fixing this, since there must
be scads of programs that unwittingly depend on that wrong order.
¬R