by Marc Nieper-Wißkirchen
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-212@nospamsrfi.schemers.org
. To subscribe to the list, follow these instructions. You can access previous messages via the mailing list archive.
This SRFI introduces alias definitions, a syntactic extension. An alias definition transfers the binding of one identifier to another, effectively aliasing the identifier.
In standard Scheme, an identifier can either name a type of syntax or a location where a value can be stored. In the former case, the identifier is said to be bound to a transformer for that syntax, and in the latter case, the identifier is said to be bound to the location.
The (lexical) binding of an identifier is an expand-time property of the identifier, in contrast to the (dynamic) value stored in a location, which is a run-time property of the location.
New bindings are established through variable or syntax definitions. For example, a variable definition
(define variable expression)
creates a new location, binds the identifier
variable
to it and stores the value
of expression
in the location.
In particular,
(define variable1 variable2)
creates a new location
for variable1
and copies
the value of variable2
into it. Subsequently modifying the value
of variable2
won't modify the
value of variable1
.
In contrast, the alias
definition introduced in
this SRFI transfers an existing binding to an identifier and
doesn't create a new one. For example,
(alias variable1 variable2)
doesn't create a new location
for variable1
, but
binds variable1
to the
location of variable2
. In
particular, subsequently modifying the value
of variable2
will modify the
value of variable1
accordingly.
Aliases allow one to locally alias identifiers under short names without changing the expanded version of the program:
(define *important-global-variable* '()) (define (setup!) (alias ls *important-global-variable*) (set! ls (cons 1 ls)) (set! ls (cons 2 ls))) (setup!) *important-global-variable* ⟹ (2 1)
Aliasing an unbound identifier is an error.
(alias x y) ⟹ error
Rebinding the aliased identifier doesn't change the binding of the aliasing identifier:
(let ((y +)) (alias x y) (let ((y *)) (free-identifier=? #'x #'y))) ⟹ #f
In particular, aliasing doesn't make the aliasing identifier equivalent to the aliased one in the sense that binding one would bind the other:
(let ((y +)) (alias x y) (bound-identifier=? #'x #'y)) ⟹ #f
The following expression, however, is invalid as it is an error for a definition to define an identifier whose binding has to be known in order to determine the meaning of any preceding definition that belongs to the same group of (internal) definitions:
(let ((y +)) (alias x y) (define y *) (free-identifier=? #'x #'y)) ⟹ error
Aliases can also be used to alias auxiliary syntax:
(alias inject unquote) `(list (inject (+ 1 2)) 4) ⟹ (list 3 4)
In macros, they can be used to inject bindings from the macro environment into the use environment:
(let ((y 1)) (let-syntax ((inject-y (syntax-rules () ((inject-y x) (alias x y))))) (let ((y 2)) (inject-y x) (set! x (* 3 x))) y)) ⟹ 3
Finally, the use of aliases is not limited to variables and keywords, but can also be used with other bindings like pattern variables:
(syntax-case #'pear () (pvar (let* () (alias fruit pvar) (syntax->datum #'(a fruit))))) ⟹ (a pear)
The alias definition is used to transfer the binding of one identifier to another. Like other definitions, it can appear either at the outermost level or in a body where other definitions can appear.
(alias identifier1
identifier2)
The binding
of identifier2
is
transferred
to identifier1
. This
means that
if identifier2
is bound
to the location of a variable, the location of a pattern
variable, a type of syntax, a type of syntax parameter, or any
other
quantity, identifier1
will be bound to the same quantity.
If identifier2
is
unbound, it is an error.
A portable Scheme implementation is not possible. An implementation of SRFI 212 is available in Unsyntax.
Chez Scheme
implements alias
in its (chezscheme)
library.
The Kawa Scheme
language also contains an implementation of alias
,
albeit under the name define-alias
.
Test suite for an implementation.
The author got the idea from reading the manual of Chez Scheme by R. Kent Dybvig.
© 2020 Marc Nieper-Wißkirchen.
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.