Functions · Projections · Practice Question
Project a User-Defined Function
Question
Given the following function:
between:{[lo; hi; v] (v >= lo) and v <= hi}- Create
inWorkingHours— checks whether a time is between09:30:00and16:30:00 - Create
inPriceRange— checks whether a price is between100.0and200.0 - Apply both to a list using
each
Solution
between:{[lo; hi; v] (v >= lo) and v <= hi}
inWorkingHours: between[09:30:00; 16:30:00;]
inPriceRange: between[100.0; 200.0; ]
times: 08:00:00 10:00:00 12:30:00 17:00:00
inWorkingHours each times
/ 0110b
prices: 50.0 125.5 199.9 250.0
inPriceRange each prices
/ 0110bExplanation
between[09:30:00; 16:30:00;] fixes the first two arguments of between and leaves the third slot (v) open. The result is a rank-1 function that checks whether a single value falls within that fixed range.
Using each then applies the rank-1 projection to every element of a list, which is cleaner than writing:
/ Without projection — more repetition
{between[09:30:00; 16:30:00; x]} each timesThe projection version reads more naturally: "apply inWorkingHours to each time".
Why write projections in full? Always include all semicolons, even when fixing trailing arguments:
between[09:30:00; 16:30:00;] / preferred — the trailing semicolon shows the slot is open
between[09:30:00; 16:30:00] / also a projection, but easy to misread as a mistakeApplying a function to fewer arguments than it takes always produces a projection, so both lines create the same function. The trailing semicolon simply makes your intent clear to the reader.
(Because >=, <= and and all work on whole lists, inWorkingHours times without each gives the same result, and q's built-in within does the same job: times within 09:30:00 16:30:00.)