commit 3afbecc7bb148fa21f375530018ac782b0cadb15
parent 90b5fbe9da21f78d793766efe5f60a8ed326ca13
Author: Taylan Ulrich Bayırlı/Kammer <taylanbayirli@gmail.com>
Date: Fri, 14 Aug 2015 23:13:42 +0200
Add HTML version of README.
The plain old Perl implementation of Markdown works fine since the
README doesn't use any GitHub-specific features.
Diffstat:
A | README.html | | | 181 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
1 file changed, 181 insertions(+), 0 deletions(-)
diff --git a/README.html b/README.html
@@ -0,0 +1,181 @@
+<h1>Generic accessor and modifier operators</h1>
+
+<h2>Author</h2>
+
+<p>Taylan Ulrich Bayırlı/Kammer, taylanbayirli at Google Mail</p>
+
+<h2>Abstract</h2>
+
+<p>Lisp dialects including Scheme have traditionally lacked short,
+simple, generic syntax for accessing and modifying the fields of
+arbitrary "collection" objects. We fill this gap for Scheme by
+defining generalized <code>ref</code> and <code>set!</code> operators.</p>
+
+<h2>Rationale</h2>
+
+<p>In some types of code-bases, accessing and modifying fields of certain
+collection objects (such as vectors, hashtables, or records) are
+ubiquitous operations. Standard Scheme APIs contain verbose procedure
+names specialized for each data type, which may become very tedious to
+type, and clutter the code.</p>
+
+<p>In contrast, most other languages offer very short and simple syntax
+for such operations, such as square bracket and dotted notation:
+<code>object[field]</code> and <code>object.field</code> for access; <code>object[field] = value</code>
+and <code>object.field = value</code> for modification.</p>
+
+<p>To accommodate, we define a pair of generic accessor and modifier
+operators that work through type-based dynamic dispatch: <code>(ref object
+field)</code> for access and <code>(set! object field value)</code> for modification.</p>
+
+<p>We believe the overhead involved in this is negligible in most
+code-bases, and furthermore a programmer can always fall back to the
+type-specific accessor and modifier procedures in performance-critical
+sections of code.</p>
+
+<p>The operators are specified to work on bytevectors, R6RS hashtables,
+lists, strings, vectors, and all record types. Some notes on specific
+types:</p>
+
+<ul>
+<li><p>For bytevectors, 8-bit unsigned integer operations are assumed.
+There is no obvious way to incorporate other bytevector operations
+into the generalized API, and a programmer is most likely to have
+single-byte operations in mind when using a generalized API on
+bytevectors.</p></li>
+<li><p>For hashtables, the <code>ref</code> operator takes an additional <code>default</code>
+argument akin to <code>hashtable-ref</code>.</p></li>
+<li><p>Lists are supported by testing the given object for a pair. Pairs
+themselves are senseless to support because <code>(set! pair car value)</code>
+contains the same number of words as <code>(set-car! pair value)</code>. In
+the <code>ref</code> equivalent, it contains one word more: <code>(ref pair car)</code>.</p></li>
+<li><p>For records, the accepted values for the <code>field</code> parameter are
+symbols corresponding to the record type's field names. The
+overhead involved in looking up the correct accessor of modifier
+falls under the same rationale as other kinds of overhead involved
+with this SRFI.</p></li>
+</ul>
+
+<p>Alists are unfortunately impossible to support due to the lack of a
+reliable <code>alist?</code> predicate. (It's ambiguous in that every alist is
+also a list, and any list may coincidentally have the structure of an
+alist.)</p>
+
+<p>A <code>ref*</code> procedure taking an arbitrary number of <code>field</code> arguments and
+walking through several collections was considered, but deemed
+sub-optimal because it doesn't play well with collections that may
+have "empty" fields, and usually one doesn't walk through deep
+structures at once, and instead binds intermediate results to a
+variable. Nevertheless, it is trivial to define if desired:</p>
+
+<pre><code>(define (ref* object field . fields)
+ (if (null? fields)
+ (ref object field)
+ (apply ref* (ref object field) fields)
+</code></pre>
+
+<p>This might be a better candidate for SRFI-105's <code>$bracket-apply$</code> than
+regular <code>ref</code>.</p>
+
+<h2>Integration with SRFI-17 and SRFI-105</h2>
+
+<p>The <code>set!</code> operator in this SRFI does not conflict with the one in
+SRFI-17. The reference implementation extends the SRFI-17 <code>set!</code> and
+thus supports the functionality of both SRFI-17 and the one described
+here.</p>
+
+<p>Additionally, if SRFI-17 is supported, the <code>ref</code> procedure's "setter"
+may be defined as: <code>(lambda (object field value) (set! object field
+value))</code>. This is uninteresting in its own right, but can yield an
+interesting combination with SRFI-105. In code that already uses
+SRFI-105 heavily, a programmer may define <code>$bracket-apply$</code> as a
+synonym to <code>ref</code>, define <code>:=</code> as a synonym to <code>set!</code>, and then use the
+following syntax: <code>{object[field] := value}</code>.</p>
+
+<h2>Specification</h2>
+
+<ul>
+<li><code>(ref object field)</code> (procedure)</li>
+<li><code>(ref object field default)</code></li>
+</ul>
+
+<p>Returns the value for <code>field</code> in <code>object</code>. If <code>object</code> is of a type
+whose fields can be "empty" or "unassigned" (e.g. a hashtable), then
+the value of <code>default</code> is returned if given, and otherwise an error
+raised.</p>
+
+<p>Valid types for <code>object</code> are: bytevectors, hashtables, pairs, strings,
+vectors, and all record types.</p>
+
+<p>Valid types for <code>field</code> depend on the type of <code>object</code>. For
+bytevectors, hashtables, strings, and vectors, refer to their
+respective <code>*-ref</code> procedures. For pairs, refer to <code>list-ref</code>. For
+records, symbols that correspond with the record type's field names
+are taken.</p>
+
+<p>If SRFI-17 is supported, then the <code>ref</code> procedure has the following
+setter: <code>(lambda (object field value) (set! object field value))</code></p>
+
+<ul>
+<li><code>(set! object field value)</code> (syntax)</li>
+</ul>
+
+<p>Sets the value for <code>field</code> in <code>object</code> to <code>value</code>.</p>
+
+<p>Valid types for <code>object</code> and <code>field</code> are the same as in the <code>ref</code>
+procedure.</p>
+
+<p>Note: This operator is only a syntax keyword because it overloads the
+normal <code>set!</code> syntax.</p>
+
+<h2>Considerations when using as a library</h2>
+
+<p>The intent of this SRFI is to encourage Scheme systems to extend the
+semantics of their default <code>set!</code> operator in line with this SRFI. On
+the meanwhile, it can be used as a library, but certain considerations
+apply.</p>
+
+<p>The <code>set!</code> and <code>define-record-type</code> exports of the library conflict
+with the ones in <code>(scheme base)</code>, so either have to be renamed, or
+more typically, the ones from <code>(scheme base)</code> excluded.</p>
+
+<p>Record types not defined with the <code>default-record-type</code> exported by
+this library won't work with <code>ref</code> and <code>set!</code>.</p>
+
+<h2>Implementation</h2>
+
+<p>A reference implementation as a library is found in the version
+control repository of this SRFI.</p>
+
+<p>It might be desirable for Scheme systems to offer a more efficient
+<code>type-of</code> procedure than the one used in this implementation, which in
+the worst case consumes linear time with regard to the number of types
+(including every record type) within the system, albeit with a very
+small constant factor: one call to each type predicate.</p>
+
+<h2>Acknowledgments</h2>
+
+<p>Original idea and some input during design by Jorgen Schäfer.</p>
+
+<h2>Copyright and license</h2>
+
+<p>Copyright (C) Taylan Ulrich Bayırlı/Kammer (2015). All Rights Reserved.</p>
+
+<p>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:</p>
+
+<p>The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.</p>
+
+<p>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.</p>