Title

Procedure Arity Inspection

Author

David Van Horn

Status

This SRFI is in ``withdrawn'' status. To see an explanation of each status that a SRFI can hold, see here. To provide input on this SRFI, please mail to <srfi minus 102 at srfi dot schemers dot org>. See instructions here to subscribe to the list. You can access previous messages via the archive of the mailing list. You can access post-withdrawal messages via the archive of the mailing list.

Table of contents

Abstract

Many Scheme systems provide mechanisms for inspecting the arity of a procedural value, making it a common feature, however there is no standard interface. As a result there is no portable way to observe the arity of a procedure without actually applying it. This SRFI proposes a simple interface that is consistent with existing Scheme systems' facilities and prior proposals.

Issues

Rationale

This proposal identifies a common, core set of operations that make it possible to inspect the arity of procedures and determine if a given procedure accepts a given number of arguments. These operations are already supported in several Scheme systems and it should be easy to add support in many more systems.

In preparing this proposal, the facilities available in Chez [1], Gauche [2], IronScheme [3], Larceny [4], MIT/GNU Scheme [5], PLT Scheme [6], and s7 [7] were reviewed. Also relevant is William D Clinger's 1996 straw proposal sent to the RnRS Authors mailing list [8]. Although there is some overlap among these systems, there are also many differences, precluding portability of code that relies on arity inspection. The most overlap occurs between Gauche, PLT Scheme, Larceny, and Clinger's proposal, and this forms the basis of this proposal. In particular, PLT Scheme and Gauche already implement this SRFI. Larceny implements a subset of this SRFI that makes it easy to portably define the remaining components and any Scheme that implements Clinger's proposal can likewise be easily and portably extended to implement this SRFI (such an extension is provided in the reference implementation section). The remaining systems provide interfaces in which this proposal is easily implemented.

A procedure to determine the arity of an arbitrary procedure's value was discussed briefly, without result, at the June 1992 RnRS Authors meeting [9]. In October 1995, version 0.29 of MzScheme added the arity procedure for inspecting the arity of a procedure [10]. That interface, which is the first this SRFI author was able to locate that includes support for Dybvig and Hieb's case-lambda form [11], is still supported in the current version of PLT Scheme (renamed procedure-arity) and has also been adopted by Gauche. In May 1996, William D Clinger submitted a straw proposal to the RnRS Authors mailing list [8]. Shortly afterward [12], Shriram Krishnamurthi suggested the proposal take into account the possibility of extending Scheme with case-lambda (which came to pass with the finalization of SRFI 16 [13] and again with the ratification of R6RS Standard Libraries [14]), in which a procedure has multiple traditional arities. Clinger's 1996 proposal for inspecting arities largely overlaps with this SRFI. The major differences are that Clinger's proposal:

  1. includes other procedure inspection facilities beyond the scope of this proposal;
  2. does not include support for procedures with disjoint arities, i.e., procedures constructed with the case-lambda syntax of Dybvig and Hieb, SRFI 16, and R6RS; and
  3. specifies that the arity of procedures accepting n or more arguments is represented by the inexact number n, while this proposal allows for such a representation, but does not require it.

Following Clinger's proposal, Scheme systems need not provide complete information for the arity of all procedures. There will be implementations for which this kind of information can always be provided, but there will also be systems or modes of operation in which this kind of information is not appropriate. Thus this SRFI specifies an interface only, and makes very few guarantees about what an implementation must produce when used. Scheme implementations are encouraged to document the guarantees supported in their particular implementation beyond those described here, if any. Portable programs should not depend on the behaviour of this feature beyond what is specified in this document.

Many Scheme systems provide procedure inspection facilities beyond arity inspection. For example, many Schemes provide mechanisms for recovering source code, source location, and documentation. This SRFI focuses solely on the ability to retrieve arity information from procedural values; features for retrieving other kinds of information from procedures are considered beyond the scope of this proposal and left for future SRFIs to take up.

Many Scheme systems provide a library of operations for procedural values. For example, many Schemes provide library procedures for composing, currying, and iterating procedures. A general library for procedures is considered beyond the scope of this proposal and left for future SRFIs.

At least one Scheme system, PLT Scheme, provides operations for restricting the set of acceptable arities for a procedure. These operations do not seem to be in wide use (outside of PLT) and are therefore not considered in this proposal.

Caveat Emptor

Inspecting procedure arity is not without its caveats and there are good reasons for not supporting such a feature. This section outlines some of those reason. The following analysis was developed during a conversation with R. Kent Dybvig and has been lightly edited.

An arity-reporting procedure may be misleading because it appears to but does not actually guarantee that an arity error will not occur when a procedure is called with an arity it is reported to accept (in fact, all that is guaranteed is that if a procedure is applied to arguments it is reported not to accept, an arity error is guaranteed to occur). It is common for a procedure to be a wrapper for one or more other procedures (for tracing, dispatch, or other reasons), to take an arbitrary number of arguments, and to apply one of the wrapped procedures to those arguments. This occurs, for example, when using the reference implementation of case-lambda given in SRFI 16 or the implementation given in R6RS. The effective number of arguments is that of the wrapped procedure that is actually called, but an arity-reporting procedure would report the number of arguments of the wrapping procedure.

Before using a procedure, it is necessary to know how many arguments it takes, their types, the ranges of acceptable values, and of course what it will and will not do. An arity-reporting procedure seems like a drop in the bucket and may not even be as useful as it seems at first blush.

A more subtle issue is that the mere existence of an arity-reporting procedure and the like might discourage people from using wrappers such as described, insidiously reducing a language's expressiveness even as they seem to increase it.

Specification

An arity object represents the arity of a procedure. An arity object is either #f, an exact non-negative integer, an arity-at-least object, or a list of exact non-negative integers and arity-at-least objects.

An arity-at-least object represents the arity (or one of the arities) of a procedure that accepts some number or more arguments. This proposal does not specify the representation of arity-at-least objects, other than to say that it must be disjoint from exact, non-negative integers; lists; and #f; and it must satisfy the requirements below.

procedure: (procedure-arity proc) → arity

Produces an arity object representing the arity of proc. If this procedure produces #f, no information is available for proc.

If this procedure produces an exact non-negative integer, k, then proc accepts exactly k arguments; applying proc to some number of arguments other than k will result in an arity error.

If this procedure produces an arity-at-least object, a, then proc accepts (arity-at-least-value a) or more arguments; applying proc to some number of arguments less than (arity-at-least-value a) will result in an arity error.

If this procedure produces a list, then proc accepts any of the arities described by the elements of the list; applying proc to some number of arguments not described by an element of the list will result in an arity error.

procedure: (arity-at-least? obj) → bool

Returns #t if obj is an arity-at-least object and false otherwise.

procedure: (arity-at-least-value arity-at-least) → k

Returns the exact non-negative integer denoting the minimum number of arguments required by the given arity-at-least object.

procedure: (procedure-arity-includes? proc k) → bool

Returns #t if the proc can accept k arguments and #f otherwise. If this procedure returns #f, applying proc to k arguments will result in an arity error.

Reference Implementation

A portable reference implementation of this SRFI that provides useful information is not possible. In its place we offer a portable implementation that does not provide useful information and implementation-specific implementations that do for PLT Scheme (a trivial wrapper for its native implementation of this interface) and Larceny (a trivial extension for its native implementation, which is sufficient for any Scheme that implements Clinger's 1996 proposal). Like PLT Scheme, Gauche natively supports this SRFI.

Portable "Null" implementation

#!r6rs
;; A portable, non-informative implementation of SRFI 102.
(library (srfi :102 procedure-arity)
  (export procedure-arity
          arity-at-least?
          arity-at-least-value
          procedure-arity-includes?)
  (import (rnrs base))
  (define (procedure-arity proc)
    (assert (procedure? proc))
    #f)
  (define (arity-at-least? obj)
    #f)
  (define (arity-at-least-value arity-at-least)
    (assert (arity-at-least? arity-at-least))
    #f)
  (define (procedure-arity-includes? proc k)
    (assert (procedure? proc))
    (assert (and (integer? k)
	         (exact? k)	 
                 (not (negative? k))))
    #f))

PLT Scheme implementation

#!r6rs
;; PLT Scheme specific implementation of SRFI 102.
(library (srfi :102 procedure-arity)
  (export procedure-arity
          arity-at-least?
          arity-at-least-value
          procedure-arity-includes?)
  (import (only (scheme base) require only-in))
  (require (only-in scheme/base 
                    procedure-arity
                    arity-at-least?
                    arity-at-least-value
                    procedure-arity-includes?)))

Larceny/Clinger 1996 proposal implementation

#!r6rs
;; Larceny specific implementation of SRFI 102.
;; This implementation should be sufficient to extend any
;; implementation of Clinger's 1996 arity proposal to implement SRFI 102.
(library (srfi :102 procedure-arity)
  (export procedure-arity
          arity-at-least?
          arity-at-least-value
          procedure-arity-includes?)
  (import (rnrs base)
          (primitives procedure-arity))

  (define (arity-at-least? obj)
    (and (integer? obj)
         (inexact? obj)	 
         (not (negative? obj))))

  (define (arity-at-least-value arity-at-least)
    (assert (arity-at-least? arity-at-least))
    (inexact->exact arity-at-least))

  (define (procedure-arity-includes proc k)
    (assert (procedure? proc))
    (assert (and (integer? k)
                 (exact? k)
                 (not (negative? k))))
    (let ((a (procedure-arity proc)))
      (and a
           (if (exact? a)
               (= k a)
               (< k a))))))

References

[1] Chez Scheme, Section 3.4. The Object Inspector
http://www.scheme.com/csug8/debug.html#./debug:h4
[2] Gauche Users' Reference: 6.16 Control features
http://practical-scheme.net/gauche/man/gauche-refe_54.html#SEC96
[3] IronScheme, Procedures exported from the (ironscheme) library
http://ironscheme.codeplex.com/Wiki/View.aspx?title=Procedures
[4] Larceny User Manual, Section 10.4. Procedures
http://larceny.ccs.neu.edu/doc/user-manual.html#id2536543
[5] MIT/GNU Scheme 7.7.90+, Section 12.2 Arity
http://www.gnu.org/software/mit-scheme/documentation/mit-scheme-ref/Arity.html
[6] PLT Scheme, Reference, Section 3.16 Procedures
http://docs.plt-scheme.org/reference/procedures.html
[7] s7
http://ccrma.stanford.edu/software/snd/snd/s7.html
[8] Extracting heuristic information from procedures.
William D Clinger, RnRS Authors mailing list
http://groups.csail.mit.edu/mac/ftpdir/scheme-mail/HTML/rrrs-1996/msg00148.html
[9] Draft Minutes of the RnRS Authors meeting.
Recorded and edited by William D Clinger, RnRS Authors mailing list
http://groups.csail.mit.edu/mac/ftpdir/scheme-mail/HTML/rrrs-1992/msg00199.html
[10] Release notes for MzScheme, Version 0.29, October 18, 1995
PLT Scheme Inc.
http://docs.plt-scheme.org/release-notes/mzscheme/HISTORY.txt
[11] A New Approach to Procedures with Variable Arity
R. Kent Dybvig and Robert Hieb
Lisp and Symbolic Computation, 3(3):229-244, September 1990.
http://www.cs.indiana.edu/~dyb/pubs/LaSC-3-3-pp229-244.pdf
[12] RE: Extracting heuristic information from procedures.
Shriram Krishnamurthi, RnRS Authors mailing list
http://groups.csail.mit.edu/mac/ftpdir/scheme-mail/HTML/rrrs-1996/msg00151.html
[13] SRFI 16: Syntax for procedures of variable arity
Lars T Hansen
http://srfi.schemers.org/srfi-16/
[14] Revised6 Report on the Algorithmic Language Scheme, Standard Libraries
Chapter 5, Control Structures
Michael Sperber, et al. (Editors)
http://www.r6rs.org/final/html/r6rs-lib/r6rs-lib-Z-H-6.html#node_idx_262

Acknowledgments

I would like to thank Eli Barzilay, R. Kent Dybvig, Matthias Felleisen, Daniel P. Friedman, and Shriram Krishnamurthi for answering questions on the history of arity inspection in Scheme. In particular, I would like to further thank R. Kent Dybvig for providing the analysis of why not to support arity inspection. I would like to thank Aaron W. Hsu for providing information on Chez Scheme's procedure inspection facilities. I am grateful to Michael Sperber for serving as SRFI editor. Support was provided by the National Science Foundation under Grant #0937060 to the Computing Research Association for the CIFellow Project.

Copyright

Copyright (C) David Van Horn 2009. All Rights Reserved.

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. REMEMBER, THERE IS NO SCHEME UNDERGROUND. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


Editor: Michael Sperber

Valid XHTML 1.0!