Search code examples
functional-programminglisplazy-evaluationkdbscoping

What is the name of this q/kdb+ feature? Does any flavor of LISP implement it? How?


The q programming language has a feature (which this tutorial calls "function projection") where a function of two or more parameters can be called with fewer parameters than it requires, but the result is an intermediate object, and the function will not be executed until all remaining parameters are passed; one way to see it is that functions behave like multi-dimensional arrays, so that (f[x])[y] is equivalent to f[x;y]. For example ...

q)add:{x+y}
q)add[42;]
{x+y}[42;]
q)add[42;][3]
45
q)g:add[42;]
q)g[3]
45

Since q does not have lexical scoping, this features become very useful in obtaining lexical scoping behavior by passing the necessary variables to an inner function as a partial list of parameters; e.g. a print parameter decorator can be constructed using this feature:

q)printParameterDecorator:{[f] {[f;x] -1 "Input: ",string x; f x}f};
q)f: printParameterDecorator (2+);
q)f 3
Input: 3
5

My questions:

  1. Is the term "function projection" a standard term? Or does this feature carry a different name in the functional programming literature?
  2. Does any variety of LISP implement this feature? Which ones?
  3. Could you provide some example LISP code please?

Solution

  • Is the term "function projection" a standard term? Or does this feature carry a different name in the functional programming literature?

    No, you usually call it partial application.

    Does any variety of LISP implement this feature? Which ones?

    Practically all Lisp allow you to partially apply a function, but usually you need to write a closure explicitly. For example in Common Lisp:

    (defun add (x y)
      (+ x y))
    

    The utility function curry from alexandria can be used to create a closure:

    USER> (alexandria:curry #'add 42)
    #<CLOSURE (LAMBDA (&REST ALEXANDRIA.1.0.0::MORE) :IN CURRY) {1019FE178B}>
    
    USER> (funcall * 3)  ;; asterisk (*) is the previous value, the closure
    45
    

    The resulting closure is equivalent to the following one:

    (lambda (y) (add 42 y))
    

    Some functional languages like OCaml only allow functions to have a single parameter, but syntactically you can define functions of multiple parameters:

    (fun x y -> x + y)
    

    The above is equivalent to:

    (function x -> (function y -> x + y))
    

    See also What is the difference between currying and partial application?


    Nb. in fact the q documentation refers to it as partial application:

    Notationally, projection is a partial application in which some arguments are supplied and the others are omitted