swap [[>] dip] filter
won’t work because it assumes n
is accessible for each call to the quotation by which you’re filtering; that implies filter
can’t leave any intermediate values on the stack while it’s operating, and >
doesn’t consume n
. You need to capture the value of n
in that quotation.
First “eta”-reduce the list parameter:
l n f = l [ n > ] filter
n f = [ n > ] filter
Then capture n
by explicitly quoting it and composing it with >
:
n f = n quote [ > ] compose filter
(Assuming quote : a -> (-> a)
a.k.a. unit
, takes a value and wraps it in a quotation and compose : (A -> B) (B -> C) -> (A -> C)
a.k.a. cat
, concatenates two quotations.)
Then just “eta”-reduce n
:
f = quote [ > ] compose filter
I put “eta” in scare quotes because it’s a little more general than in lambda calculus, working for any number of values on the stack, not just one.
You can of course factor out partial application into its own definition, e.g. the papply
combinator in Cat, which is already defined as swons
(swap cons
) in Joy, but can also be defined like so:
DEFINE
papply (* x [F] -- [x F] *)
== [unit] dip concat ;
f (* xs n -- xs[>=n] *)
== [>] papply filter .
In Kitten this could be written in a few different ways, according to preference:
// Point-free
function \> compose filter
// Local variable and postfix
-> n; { n (>) } filter
// Local variable and operator section
-> n; \(n <) filter
Any evaluation strategy compatible with functional programming is also compatible with concatenative programming—popr is a lazy concatenative language.