[Omake] Semantics for curried functions, partial applications and keyword argument.

Aleksey Nogin anogin at hrl.com
Tue Aug 7 10:14:53 PDT 2007


Jason,

Here is sketch for a consistent semantics and implementation scheme for 
curried functions, partial applications and keyword arguments in OMake.

Please let me know what you think.

- Keyword arguments are taken as a way to shadow an "extra" binding in 
the environment in which the function body will be evaluated.
   **OPTIONALLY**: The default is to shadow a "private" binding, but 
other bindings may be specified. E.g.
    CProgram(..., public.LDFLAGS = ...)
would be roughly equivalent to
   section
     public.LDFLAGS = ...
     CProgram(...)
(and if we go with this, we'd probably want to support a "+=" form as well).

- Similarly the keyword argument _specification_ is simply a way to 
introduce an extra binding into the closure.
    f(..., keyword = ...) =
       ...
is equivalent to
    section
       private.keyword = ...
       f(...) =
          ...

- **Optional**: We may want to allow referring to even regular arguments 
by name:
   f(x, y) =
     ...
   g = $(f y = bar)
   g(foo)

   becomes roughly equivalent to
   f(x, y) =
      ...
   f(foo, bar)

- **Optional**: Special syntax for partial applications:
   I am a bit concerned that without static checking and now with 
relaxed dynamic checking of the argument counts, mistakes in argument 
numbers would become too hard to track. One option is to require a 
special syntax (e.g. use {} in place of () ):
   - Definitions:
       f{...} =
         ...
     allow f to be curried (applied to "too many" arguments).
   - Applications:
       ${f ...}
     are allowed to be partial (note that there is no f{...} form, only 
explicit "value ${f ...}" ).
   - If we go with this, it would be natural to say that referring to 
arguments by name (previous "option") is allowed only inside ${...} 
applications.

- Implementation:
   A. Functional values are a tuple of (similar to how they are now):
      1. A private env
      2. A list of argument names
      3. [Optional] a list of non-private var-value bindings.
      4. A body
   B. When evaluating a function application, then:
      1. Apply it to each argument in order:
        a. [Optional] If it a non-private keyword argument, extend the 
list of non-private var-value bindings (A.3. in closure tuple)
        b. If it is a regular (private) keyword argument:
           i. If the keyword name is already bound in the private env 
(A.1. in closure tuple), augment the private env.
           ii. [Optional] Otherwise, if the keyword coincides with one 
of the argument names (A.2 in the closure tuple), then:
              - Remove that element from the argument list
              - Add the corresponding binding to the private env
	  iii. Report an "unknown keyword argument" error.
        c. If it is a non-keyword argument:
           i. If the argument list is empty, evaluate the function body 
(in the appropriate environment) and restart the argument application 
process.
           ii. Otherwise, remove the head element from the list of 
argument names and add the corresponding binding to the private env.
      2. Once all the arguments are applied, check the resulting list of 
argument names:
        a. If no argument names left (the function is fully applied), 
evaluate the body (in the appropriate environment)
        b. Otherwise, return the new closure.
   C. Environment for evaluating the function body:
      1. As usual, the static environment of the caller is replaced with 
the environment from the closure
      2. [Optional] the collected list of non-private var-value bindings 
(A.3. in the function closure) is applied to the environment.
   D. Report "argument length mismatch/partially applied function" errors:
      1. When a closure function is called as a F(...) expression (as 
opposed to $(F ...) one) and the result is a closure.
      2. If a closure is encountered in a string context 
(string[s]_of_value, file_of_value, etc).
      - As usual, we'd want a variable warn/error/ignore for this error, 
but "error" should be its default value.
   E. Primitive built-in functions:
      1. Prohibit keyword arguments.
      2. Prohibit partial applications.

-- 
Aleksey Nogin, Research Scientist
Advanced Technologies Department, Information & System Sciences Lab
HRL Laboratories, LLC, Malibu, CA


More information about the OMake-Devel mailing list