by Lassi Kortela
This SRFI is currently in final status. Here is
an
explanation of each status that a SRFI can hold. To provide
input on this SRFI, please send email to srfi-219@nospamsrfi.schemers.org
.
To subscribe to the list, follow these
instructions. You can access previous messages via the
mailing list archive.
This SRFI codifies the following shorthand syntax, which some Scheme implementations have had for a long time.
(define ((outer-name outer-args ...) inner-args ...) inner-body ...)
Procedures that make other procedures are commonly used in
Scheme. A shorthand syntax makes them easier to define, obviating
the need to write a lambda
inside a
lambda
.
Recall that RnRS defines a standard shorthand whereby the code:
(define foo (lambda (a b c) body ...))
can be abbreviated as:
(define (foo a b c) body ...)
This SRFI defines an additional shorthand which is an extrapolation of the standard one. The code:
(define (foo a b c) (lambda (d e f) body ...))
can be abbreviated as:
(define ((foo a b c) d e f) body ...)
The syntax generalizes further: lambda
s can be
nested arbitrarily deep by adding more nested lists. The key is
that each nested list always be at the head position of
the containing list. Each inner list adds one outer
lambda
; this order is intuitive when reading the
S-expression left-to-right. The identifier at the head position
of the innermost list becomes the name of the definition.
Apart from helping define higher-order functions, the additional shorthand syntax partially applies to the task of making partially applied functions in Scheme.
The shorthand has been in MIT Scheme since at least 1990, and may have originated in that implementation.
The following Scheme implementations have the shorthand syntax built in:
(ice-9 curried-definitions)
libraryThe following implementations don't have it: Bigloo, BiwaScheme, Chez Scheme, Chibi-Scheme, Cyclone, Gambit, Gerbil, Ikarus, IronScheme, Kawa, Loko, Mosh, s7, Scheme 48, SigScheme, STklos, TinyScheme, Vicare, Ypsilon.
SRFI 201: Syntactic Extensions to the Core Scheme Bindings standardizes this shorthand among several others.
Since the shorthand is non-standard (i.e. not defined in RnRS), it can be controversial or confusing to the uninitiated programmer.
This SRFI handles the conflict by storing the shorthand
version of define
in a library that does not have to
be imported by default. Then programmers can choose whether to
import it or not. In portable code the import
serves
to document the dependency on this SRFI.
The shorthand version of define
behaves as
follows:
(define symbol expr)
defines symbol with the value
expr
(define (symbol . args) expr ...)
defines symbol with the value
(lambda args expr ...)
(define ((symbol . args1) . args) expr ...)
defines symbol with the value
(lambda args1 (lambda args expr ...))
(define (((symbol . args2) . args1) . args) expr ...)
defines symbol with the value
(lambda args2 (lambda args1 (lambda args expr ...)))
and so on.
If the Scheme implementation supports attaching declarations
such as documentation strings or optimization settings to
procedures, any such declarations appearing in expr
...
can apply to the outer and/or inner
lambda
s at the discretion of the implementation.
In R6RS Scheme implementations, the shorthand
version of define
is exported from the library
(srfi :219)
. In R7RS Scheme
implementations, it is exported from the library (srfi
219)
.
The shorthand is exported under the name define
,
which means that it shadows RnRS
define
.
The shorthand may also be imported from other libraries,
possibly under names other than define
.
This SRFI does not say whether or not the shorthand is imported into the default interaction environment.
Simplest example:
(define ((greet-with-prefix prefix) suffix) (string-append prefix " " suffix)) (define greet (greet-with-prefix "Hello")) (greet "there!") => "Hello there!"
With a dotted list to take a variable number of arguments:
(define ((append-to . a) . b) (apply append (append a b))) ((append-to)) => () ((append-to '(1 2) '(3 4)) '(5 6) '(7 8)) => (1 2 3 4 5 6 7 8)
To avoid the name conflict between RnRS
define
and this SRFI's define
, a
program using this SRFI should import the
RnRS base library as:
(import (except (rnrs)
define))
(import (except (scheme base)
define))
Alternatively, Scheme's import renaming can be used to import
the shorthand define
under a different name, in
which case the same program can alternate between using the
shorthand define
and RnRS
define
. For example:
(import (rename (srfi :219) (define
define/higher)))
(import (rename (srfi 219) (define
define/higher)))
R6RS and R7RS libraries using
syntax-rules
are attached.
Thanks to Arthur Gleckler and Taylor Campbell from MIT Scheme for explaining the syntax and its history.
Thanks to by Panicz Maciej Godek for writing SRFI 201. At the time of writing this SRFI, I was unaware that it contained the same shorthand.
Thanks to Marc Nieper-Wißkirchen and Panicz for hints on
syntax-rules
simplification.
Thanks to Göran Weinholt for collaborating on Docker containers that made it easy to do the survey.
© 2021 Lassi Kortela.
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 (including the next paragraph) 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. 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.